Various UI fixes

This commit is contained in:
Ilya Laktyushin 2019-11-01 20:39:56 +04:00
parent c1030b193d
commit 845f8fa8ee
6 changed files with 69 additions and 223 deletions

View File

@ -6,7 +6,7 @@ public protocol KeyShortcutResponder {
public class KeyShortcutsController: UIResponder {
private var effectiveShortcuts: [KeyShortcut]?
private var viewControllerEnumerator: ((ContainableController) -> Bool) -> Void
private var viewControllerEnumerator: (@escaping (ContainableController) -> Bool) -> Void
public static var isAvailable: Bool {
if #available(iOSApplicationExtension 8.0, iOS 8.0, *), UIDevice.current.userInterfaceIdiom == .pad {
@ -16,7 +16,7 @@ public class KeyShortcutsController: UIResponder {
}
}
public init(enumerator: @escaping ((ContainableController) -> Bool) -> Void) {
public init(enumerator: @escaping (@escaping (ContainableController) -> Bool) -> Void) {
self.viewControllerEnumerator = enumerator
super.init()
}

View File

@ -1168,11 +1168,15 @@ public class Window1 {
}
public func forEachViewController(_ f: (ContainableController) -> Bool) {
if let navigationController = self._rootController as? NavigationController, let controller = navigationController.topOverlayController {
!f(controller)
}
for (controller, _) in self.presentationContext.controllers {
if !f(controller) {
break
}
}
for controller in self.topLevelOverlayControllers {
if !f(controller) {
break

View File

@ -110,14 +110,11 @@ private func allOpenInOptions(context: AccountContext, item: OpenInItem) -> [Ope
}
return .none
}))
options.append(OpenInOption(identifier: "yandex", application: .other(title: "Yandex", identifier: 483693909, scheme: "yandexbrowser-open-url", store: nil), action: {
if let escapedUrl = url.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) {
return .openUrl(url: "yandexbrowser-open-url://\(escapedUrl)")
}
return .none
}))
options.append(OpenInOption(identifier: "duckDuckGo", application: .other(title: "DuckDuckGo", identifier: 663592361, scheme: "ddgQuickLink", store: nil), action: {
return .openUrl(url: "ddgQuickLink://\(url)")
}))
options.append(OpenInOption(identifier: "edge", application: .other(title: "Microsoft Edge", identifier: 1288723196, scheme: "microsoft-edge-http", store: nil), action: {
if let url = URL(string: url), var components = URLComponents(url: url, resolvingAgainstBaseURL: true) {
components.scheme = components.scheme == "https" ? "microsoft-edge-https" : "microsoft-edge-http"
@ -127,9 +124,12 @@ private func allOpenInOptions(context: AccountContext, item: OpenInItem) -> [Ope
}
return .none
}))
options.append(OpenInOption(identifier: "duckDuckGo", application: .other(title: "DuckDuckGo", identifier: 663592361, scheme: "ddgQuickLink", store: nil), action: {
return .openUrl(url: "ddgQuickLink://\(url)")
options.append(OpenInOption(identifier: "yandex", application: .other(title: "Yandex Browser", identifier: 483693909, scheme: "yandexbrowser-open-url", store: nil), action: {
if let escapedUrl = url.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) {
return .openUrl(url: "yandexbrowser-open-url://\(escapedUrl)")
}
return .none
}))
options.append(OpenInOption(identifier: "brave", application: .other(title: "Brave", identifier: 1052879175, scheme: "brave", store: nil), action: {
@ -139,28 +139,27 @@ private func allOpenInOptions(context: AccountContext, item: OpenInItem) -> [Ope
return .none
}))
options.append(OpenInOption(identifier: "alook", application: .other(title: "Alook Browser", identifier: 1261944766, scheme: "alook", store: nil), action: {
return .openUrl(url: "alook://\(url)")
}))
options.append(OpenInOption(identifier: "dolphin", application: .other(title: "Dolphin", identifier: 452204407, scheme: "dolphin", store: nil), action: {
options.append(OpenInOption(identifier: "dolphin", application: .other(title: "Dolphin", identifier: 1440710469, scheme: "dolphin", store: "us"), action: {
return .openUrl(url: "dolphin://\(url)")
}))
options.append(OpenInOption(identifier: "onion", application: .other(title: "Onion Browser", identifier: 519296448, scheme: "onionhttp", store: nil), action: {
if let url = URL(string: url), var components = URLComponents(url: url, resolvingAgainstBaseURL: true) {
components.scheme = components.scheme == "https" ? "onionhttps" : "onionhttp"
if let url = components.string {
return .openUrl(url: url)
}
if let url = URL(string: url), var components = URLComponents(url: url, resolvingAgainstBaseURL: true) {
components.scheme = components.scheme == "https" ? "onionhttps" : "onionhttp"
if let url = components.string {
return .openUrl(url: url)
}
return .none
}))
}
return .none
}))
options.append(OpenInOption(identifier: "ucbrowser", application: .other(title: "UC Browser", identifier: 1048518592, scheme: "ucbrowser", store: nil), action: {
return .openUrl(url: "ucbrowser://\(url)")
}))
options.append(OpenInOption(identifier: "alook", application: .other(title: "Alook Browser", identifier: 1261944766, scheme: "alook", store: nil), action: {
return .openUrl(url: "alook://\(url)")
}))
case let .location(location, withDirections):
let lat = location.latitude
let lon = location.longitude

View File

@ -2991,9 +2991,8 @@ public func openInAppIcon(postbox: Postbox, appIcon: OpenInAppIcon) -> Signal<(T
}
if let sourceImage = sourceImage, let cgImage = sourceImage.cgImage {
let imageSize = sourceImage.size.aspectFilled(arguments.drawingRect.size)
context.withFlippedContext { c in
c.draw(cgImage, in: CGRect(origin: CGPoint(x: floor((arguments.drawingRect.size.width - imageSize.width) / 2.0), y: floor((arguments.drawingRect.size.height - imageSize.height) / 2.0)), size: imageSize))
c.draw(cgImage, in: CGRect(origin: CGPoint(), size: arguments.drawingRect.size))
drawOpenInAppIconBorder(into: c, arguments: arguments)
}
} else {

View File

@ -21,6 +21,7 @@ import PasscodeUI
import ImageBlur
import WatchBridge
import SettingsUI
import AppLock
final class UnauthorizedApplicationContext {
let sharedContext: SharedAccountContextImpl
@ -74,7 +75,6 @@ final class AuthorizedApplicationContext {
private var inAppNotificationSettings: InAppNotificationSettings?
private var isLocked: Bool = true
var passcodeController: PasscodeEntryController?
private var currentAppUpdateInfo: AppUpdateInfo?
@ -128,194 +128,31 @@ final class AuthorizedApplicationContext {
if KeyShortcutsController.isAvailable {
let keyShortcutsController = KeyShortcutsController { [weak self] f in
if let strongSelf = self {
if strongSelf.isLocked {
return
}
if let tabController = strongSelf.rootController.rootTabController {
let controller = tabController.controllers[tabController.selectedIndex]
if !f(controller) {
if let strongSelf = self, let appLockContext = strongSelf.context.sharedContext.appLockContext as? AppLockContextImpl {
let _ = (appLockContext.isCurrentlyLocked
|> take(1)
|> deliverOnMainQueue).start(next: { locked in
guard !locked else {
return
}
if let controller = strongSelf.rootController.topViewController as? ViewController {
if !f(controller) {
if let tabController = strongSelf.rootController.rootTabController {
let selectedController = tabController.controllers[tabController.selectedIndex]
if !f(selectedController) {
return
}
if let controller = strongSelf.rootController.topViewController as? ViewController, controller !== selectedController {
if !f(controller) {
return
}
}
}
}
strongSelf.mainWindow.forEachViewController(f)
strongSelf.mainWindow.forEachViewController(f)
})
}
}
context.keyShortcutsController = keyShortcutsController
}
/*let previousPasscodeState = Atomic<PasscodeState?>(value: nil)
let passcodeStatusData = combineLatest(queue: Queue.mainQueue(), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.presentationPasscodeSettings]), context.sharedContext.accountManager.accessChallengeData(), context.sharedContext.applicationBindings.applicationIsActive)
let passcodeState = passcodeStatusData
|> map { sharedData, accessChallengeDataView, isActive -> PasscodeState in
let accessChallengeData = accessChallengeDataView.data
let passcodeSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.presentationPasscodeSettings] as? PresentationPasscodeSettings
return PasscodeState(isActive: isActive, challengeData: accessChallengeData, autolockTimeout: passcodeSettings?.autolockTimeout, enableBiometrics: passcodeSettings?.enableBiometrics ?? false, biometricsDomainState: passcodeSettings?.biometricsDomainState)
}
self.passcodeStatusDisposable.set(passcodeState.start(next: { [weak self] updatedState in
guard let strongSelf = self else {
return
}
let previousState = previousPasscodeState.swap(updatedState)
var updatedAutolockDeadline: Int32?
if updatedState.isActive != previousState?.isActive, let autolockTimeout = updatedState.autolockTimeout {
updatedAutolockDeadline = Int32(CFAbsoluteTimeGetCurrent()) + max(10, autolockTimeout)
}
var effectiveAutolockDeadline = updatedState.challengeData.autolockDeadline
if updatedState.isActive {
} else if previousState != nil && previousState!.autolockTimeout != updatedState.autolockTimeout {
effectiveAutolockDeadline = updatedAutolockDeadline
}
if let previousState = previousState, previousState.isActive, !updatedState.isActive, effectiveAutolockDeadline != 0 {
effectiveAutolockDeadline = updatedAutolockDeadline
}
var isLocked = false
if isAccessLocked(data: updatedState.challengeData.withUpdatedAutolockDeadline(effectiveAutolockDeadline), at: Int32(CFAbsoluteTimeGetCurrent())) {
isLocked = true
updatedAutolockDeadline = 0
}
let isLockable: Bool
switch updatedState.challengeData {
case .none:
isLockable = false
default:
isLockable = true
}
if previousState?.isActive != updatedState.isActive || isLocked != strongSelf.isLocked {
if updatedAutolockDeadline != previousState?.challengeData.autolockDeadline {
let _ = (strongSelf.context.sharedContext.accountManager.transaction { transaction -> Void in
let data = transaction.getAccessChallengeData().withUpdatedAutolockDeadline(updatedAutolockDeadline)
transaction.setAccessChallengeData(data)
}).start()
}
strongSelf.isLocked = isLocked
if isLocked {
if updatedState.isActive {
if strongSelf.passcodeController == nil {
let presentAnimated = previousState != nil && previousState!.isActive
let biometrics: PasscodeEntryControllerBiometricsMode
if updatedState.enableBiometrics {
biometrics = .enabled(updatedState.biometricsDomainState)
} else {
biometrics = .none
}
let controller = PasscodeEntryController(context: strongSelf.context, challengeData: updatedState.challengeData, biometrics: biometrics, arguments: PasscodeEntryControllerPresentationArguments(animated: presentAnimated, lockIconInitialFrame: { [weak self] in
if let strongSelf = self, let lockViewFrame = strongSelf.rootController.chatListController?.lockViewFrame {
return lockViewFrame
} else {
return CGRect()
}
}))
strongSelf.passcodeController = controller
strongSelf.unlockedStatePromise.set(.single(false))
controller.presentationCompleted = {
strongSelf.rootController.view.isHidden = true
strongSelf.context.sharedContext.mediaManager.overlayMediaManager.controller?.view.isHidden = true
strongSelf.notificationController.view.isHidden = true
}
strongSelf.mainWindow.present(controller, on: .passcode)
if !presentAnimated {
controller.requestBiometrics()
}
} else if previousState?.isActive != updatedState.isActive, updatedState.isActive, let passcodeController = strongSelf.passcodeController {
passcodeController.requestBiometrics()
}
strongSelf.updateCoveringViewSnaphot(false)
strongSelf.mainWindow.coveringView = nil
} else {
strongSelf.unlockedStatePromise.set(.single(false))
strongSelf.updateCoveringViewSnaphot(true)
strongSelf.mainWindow.coveringView = strongSelf.passcodeController == nil ? strongSelf.lockedCoveringView : nil
strongSelf.rootController.view.isHidden = true
strongSelf.context.sharedContext.mediaManager.overlayMediaManager.controller?.view.isHidden = true
strongSelf.notificationController.view.isHidden = true
}
} else {
if !updatedState.isActive && isLockable {
strongSelf.updateCoveringViewSnaphot(true)
strongSelf.mainWindow.coveringView = strongSelf.passcodeController == nil ? strongSelf.lockedCoveringView : nil
strongSelf.rootController.view.isHidden = true
strongSelf.context.sharedContext.mediaManager.overlayMediaManager.controller?.view.isHidden = true
strongSelf.notificationController.view.isHidden = true
} else {
strongSelf.updateCoveringViewSnaphot(false)
strongSelf.mainWindow.coveringView = nil
strongSelf.rootController.view.isHidden = false
strongSelf.context.sharedContext.mediaManager.overlayMediaManager.controller?.view.isHidden = false
strongSelf.notificationController.view.isHidden = false
if strongSelf.rootController.rootTabController == nil {
strongSelf.rootController.addRootControllers(showCallsTab: strongSelf.showCallsTab)
if let (peerId, messageId, activateInput) = strongSelf.scheduledOperChatWithPeerId {
strongSelf.scheduledOperChatWithPeerId = nil
strongSelf.openChatWithPeerId(peerId: peerId, messageId: messageId, activateInput: activateInput)
}
if let url = strongSelf.scheduledOpenExternalUrl {
strongSelf.scheduledOpenExternalUrl = nil
strongSelf.openUrl(url)
}
if #available(iOS 10.0, *) {
} else {
DeviceAccess.authorizeAccess(to: .contacts, presentationData: strongSelf.context.sharedContext.currentPresentationData.with { $0 }, present: { c, a in
})
}
if let passcodeController = strongSelf.passcodeController {
if let chatListController = strongSelf.rootController.chatListController {
let _ = chatListController.ready.get().start(next: { [weak passcodeController] _ in
if let strongSelf = self, let passcodeController = passcodeController, strongSelf.passcodeController === passcodeController {
strongSelf.passcodeController = nil
strongSelf.rootController.chatListController?.displayNode.recursivelyEnsureDisplaySynchronously(true)
passcodeController.dismiss()
}
})
} else {
strongSelf.passcodeController = nil
strongSelf.rootController.chatListController?.displayNode.recursivelyEnsureDisplaySynchronously(true)
passcodeController.dismiss()
}
}
} else {
if let passcodeController = strongSelf.passcodeController {
strongSelf.passcodeController = nil
passcodeController.dismiss()
}
}
}
strongSelf.unlockedStatePromise.set(.single(true))
}
}
if let tabsController = strongSelf.rootController.viewControllers.first as? TabBarController, !tabsController.controllers.isEmpty, tabsController.selectedIndex >= 0 {
let controller = tabsController.controllers[tabsController.selectedIndex]
let combinedReady = combineLatest(tabsController.ready.get(), controller.ready.get())
|> map { $0 && $1 }
|> filter { $0 }
|> take(1)
strongSelf.isReady.set(combinedReady)
} else {
strongSelf.isReady.set(.single(true))
}
}))*/
if self.rootController.rootTabController == nil {
self.rootController.addRootControllers(showCallsTab: self.showCallsTab)
}
@ -392,25 +229,32 @@ final class AuthorizedApplicationContext {
inAppNotificationSettings = InAppNotificationSettings.defaultSettings
}
if !strongSelf.isLocked {
let isMuted = firstMessage.attributes.contains(where: { attribute in
if let attribute = attribute as? NotificationInfoMessageAttribute {
return attribute.flags.contains(.muted)
} else {
return false
if let appLockContext = strongSelf.context.sharedContext.appLockContext as? AppLockContextImpl {
let _ = (appLockContext.isCurrentlyLocked
|> take(1)
|> deliverOnMainQueue).start(next: { locked in
guard !locked else {
return
}
let isMuted = firstMessage.attributes.contains(where: { attribute in
if let attribute = attribute as? NotificationInfoMessageAttribute {
return attribute.flags.contains(.muted)
} else {
return false
}
})
if !isMuted {
if firstMessage.id.peerId == context.account.peerId, !firstMessage.flags.contains(.WasScheduled) {
} else {
if inAppNotificationSettings.playSounds {
serviceSoundManager.playIncomingMessageSound()
}
if inAppNotificationSettings.vibrate {
serviceSoundManager.playVibrationSound()
}
}
}
})
if !isMuted {
if firstMessage.id.peerId == context.account.peerId, !firstMessage.flags.contains(.WasScheduled) {
} else {
if inAppNotificationSettings.playSounds {
serviceSoundManager.playIncomingMessageSound()
}
if inAppNotificationSettings.vibrate {
serviceSoundManager.playVibrationSound()
}
}
}
}
if chatIsVisible {

View File

@ -8072,7 +8072,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
guard case let .peer(peerId) = self.chatLocation, peerId.namespace == Namespaces.Peer.CloudUser && peerId != self.context.account.peerId else {
return
}
if #available(iOSApplicationExtension 11.0, iOS 11.0, *) {
if #available(iOSApplicationExtension 13.2, iOS 13.2, *) {
let _ = (self.context.account.postbox.loadedPeerWithId(peerId)
|> mapToSignal { peer -> Signal<(Peer, UIImage?), NoError> in
let avatarImage = peerAvatarImage(account: self.context.account, peer: peer, authorOfMessage: nil, representation: peer.smallProfileImage, round: false) ?? .single(nil)