mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-30 03:44:18 +00:00
Bugfixes
This commit is contained in:
parent
5da7197c55
commit
bb9b706c94
24
Makefile
24
Makefile
@ -168,6 +168,28 @@ package_arm64:
|
||||
PACKAGE_BUNDLE_ID="${BUNDLE_ID}" \
|
||||
sh package_app.sh iphoneos-arm64 $(BUCK) $(BUCK_OPTIONS) ${BUCK_RELEASE_OPTIONS}
|
||||
|
||||
package_debug_arm64:
|
||||
PACKAGE_DEVELOPMENT_TEAM="${DEVELOPMENT_TEAM}" \
|
||||
PACKAGE_CODE_SIGN_IDENTITY="${DEVELOPMENT_CODE_SIGN_IDENTITY}" \
|
||||
PACKAGE_PROVISIONING_PROFILE_APP="${DEVELOPMENT_PROVISIONING_PROFILE_APP}" \
|
||||
PACKAGE_ENTITLEMENTS_APP="${ENTITLEMENTS_APP}" \
|
||||
PACKAGE_PROVISIONING_PROFILE_EXTENSION_Share="${DEVELOPMENT_PROVISIONING_PROFILE_EXTENSION_SHARE}" \
|
||||
PACKAGE_ENTITLEMENTS_EXTENSION_Share="${ENTITLEMENTS_EXTENSION_SHARE}" \
|
||||
PACKAGE_PROVISIONING_PROFILE_EXTENSION_Widget="${DEVELOPMENT_PROVISIONING_PROFILE_EXTENSION_WIDGET}" \
|
||||
PACKAGE_ENTITLEMENTS_EXTENSION_Widget="${ENTITLEMENTS_EXTENSION_WIDGET}" \
|
||||
PACKAGE_PROVISIONING_PROFILE_EXTENSION_NotificationService="${DEVELOPMENT_PROVISIONING_PROFILE_EXTENSION_NOTIFICATIONSERVICE}" \
|
||||
PACKAGE_ENTITLEMENTS_EXTENSION_NotificationService="${ENTITLEMENTS_EXTENSION_NOTIFICATIONSERVICE}" \
|
||||
PACKAGE_PROVISIONING_PROFILE_EXTENSION_NotificationContent="${DEVELOPMENT_PROVISIONING_PROFILE_EXTENSION_NOTIFICATIONCONTENT}" \
|
||||
PACKAGE_ENTITLEMENTS_EXTENSION_NotificationContent="${ENTITLEMENTS_EXTENSION_NOTIFICATIONCONTENT}" \
|
||||
PACKAGE_PROVISIONING_PROFILE_EXTENSION_Intents="${DEVELOPMENT_PROVISIONING_PROFILE_EXTENSION_INTENTS}" \
|
||||
PACKAGE_ENTITLEMENTS_EXTENSION_Intents="${ENTITLEMENTS_EXTENSION_INTENTS}" \
|
||||
PACKAGE_PROVISIONING_PROFILE_WATCH_APP="${DEVELOPMENT_PROVISIONING_PROFILE_WATCH_APP}" \
|
||||
PACKAGE_PROVISIONING_PROFILE_WATCH_EXTENSION="${DISTRIBUTION_PROVISIONING_PROFILE_WATCH_EXTENSION}" \
|
||||
PACKAGE_BUNDLE_ID="${BUNDLE_ID}" \
|
||||
ENABLE_GET_TASK_ALLOW=1 \
|
||||
CODESIGNING_PROFILES_VARIANT="development" \
|
||||
sh package_app.sh iphoneos-arm64 $(BUCK) $(BUCK_OPTIONS) ${BUCK_RELEASE_OPTIONS}
|
||||
|
||||
package:
|
||||
PACKAGE_DEVELOPMENT_TEAM="${DEVELOPMENT_TEAM}" \
|
||||
PACKAGE_CODE_SIGN_IDENTITY="${DISTRIBUTION_CODE_SIGN_IDENTITY}" \
|
||||
@ -192,7 +214,7 @@ app: build package
|
||||
|
||||
app_arm64: build_arm64 package_arm64
|
||||
|
||||
app_debug_arm64: build_debug_arm64 package_arm64
|
||||
app_debug_arm64: build_debug_arm64 package_debug_arm64
|
||||
|
||||
build_buckdebug: check_env
|
||||
BUCK_DEBUG_MODE=1 $(BUCK) build \
|
||||
|
||||
@ -301,6 +301,11 @@
|
||||
<string>remote-notification</string>
|
||||
<string>voip</string>
|
||||
</array>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<false/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
@ -356,10 +361,5 @@
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@ -44,6 +44,8 @@
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
@ -65,6 +67,8 @@
|
||||
ReferencedContainer = "container:Project.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
||||
@ -44,6 +44,8 @@
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
@ -65,6 +67,8 @@
|
||||
ReferencedContainer = "container:Project.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
||||
@ -44,6 +44,8 @@
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
@ -65,6 +67,8 @@
|
||||
ReferencedContainer = "container:Project.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
||||
@ -44,6 +44,8 @@
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
@ -65,6 +67,8 @@
|
||||
ReferencedContainer = "container:Project.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
||||
@ -44,6 +44,8 @@
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
@ -65,6 +67,8 @@
|
||||
ReferencedContainer = "container:Project.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
||||
@ -2563,6 +2563,8 @@
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
@ -2572,6 +2574,8 @@
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
stopOnEveryThreadSanitizerIssue = "YES"
|
||||
stopOnEveryMainThreadCheckerIssue = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
@ -2584,6 +2588,8 @@
|
||||
ReferencedContainer = "container:Project.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
||||
@ -184,6 +184,12 @@ for ITEM in $APP_ITEMS_WITH_PROVISIONING_PROFILE; do
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$ENABLE_GET_TASK_ALLOW" == "1" ]; then
|
||||
KEY="com.apple.security.get-task-allow"
|
||||
PLUTIL_KEY=$(echo "$KEY" | sed 's/\./\\\./g')
|
||||
plutil -insert "$PLUTIL_KEY" -xml "<false/>" "$PROFILE_ENTITLEMENTS_PATH"
|
||||
fi
|
||||
|
||||
ENTITLEMENTS_VAR=PACKAGE_ENTITLEMENTS_$ITEM
|
||||
if [ ! -z "${!ENTITLEMENTS_VAR}" ]; then
|
||||
if [ ! -f "${!ENTITLEMENTS_VAR}" ]; then
|
||||
|
||||
@ -24,6 +24,6 @@
|
||||
|
||||
+ (void)getHardwareEncryptionAvailableWithBaseAppBundleId:(NSString * _Nonnull)baseAppBundleId completion:(void (^)(NSData * _Nullable))completion;
|
||||
+ (void)encryptApplicationSecret:(NSData * _Nonnull)secret baseAppBundleId:(NSString * _Nonnull)baseAppBundleId completion:(void (^)(NSData * _Nullable, NSData * _Nullable))completion;
|
||||
+ (void)decryptApplicationSecret:(NSData * _Nonnull)secret publicKey:(NSData * _Nonnull)publicKey baseAppBundleId:(NSString * _Nonnull)baseAppBundleId completion:(void (^)(NSData * _Nullable))completion;
|
||||
+ (void)decryptApplicationSecret:(NSData * _Nonnull)secret publicKey:(NSData * _Nonnull)publicKey baseAppBundleId:(NSString * _Nonnull)baseAppBundleId completion:(void (^)(NSData * _Nullable, bool))completion;
|
||||
|
||||
@end
|
||||
|
||||
@ -694,28 +694,29 @@ API_AVAILABLE(ios(10))
|
||||
});
|
||||
}
|
||||
|
||||
+ (void)decryptApplicationSecret:(NSData * _Nonnull)secret publicKey:(NSData * _Nonnull)publicKey baseAppBundleId:(NSString * _Nonnull)baseAppBundleId completion:(void (^)(NSData * _Nullable))completion {
|
||||
+ (void)decryptApplicationSecret:(NSData * _Nonnull)secret publicKey:(NSData * _Nonnull)publicKey baseAppBundleId:(NSString * _Nonnull)baseAppBundleId completion:(void (^)(NSData * _Nullable, bool))completion {
|
||||
dispatch_async([self encryptionQueue], ^{
|
||||
LocalPrivateKey *privateKey = [self getApplicationSecretKey:baseAppBundleId isCheckKey:false];
|
||||
if (privateKey == nil) {
|
||||
completion(nil);
|
||||
completion(nil, false);
|
||||
return;
|
||||
}
|
||||
if (privateKey == nil) {
|
||||
completion(nil);
|
||||
completion(nil, false);
|
||||
return;
|
||||
}
|
||||
NSData *currentPublicKey = [privateKey getPublicKey];
|
||||
if (currentPublicKey == nil) {
|
||||
completion(nil);
|
||||
completion(nil, false);
|
||||
return;
|
||||
}
|
||||
if (![publicKey isEqualToData:currentPublicKey]) {
|
||||
completion(nil);
|
||||
completion(nil, false);
|
||||
return;
|
||||
}
|
||||
NSData *result = [privateKey decrypt:secret cancelled:nil];
|
||||
completion(result);
|
||||
bool cancelled = false;
|
||||
NSData *result = [privateKey decrypt:secret cancelled:&cancelled];
|
||||
completion(result, cancelled);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -57,6 +57,8 @@ public final class ContextGesture: UIGestureRecognizer, UIGestureRecognizerDeleg
|
||||
override public func reset() {
|
||||
super.reset()
|
||||
|
||||
self.endPressedAppearance()
|
||||
|
||||
self.currentProgress = 0.0
|
||||
self.delayTimer?.invalidate()
|
||||
self.delayTimer = nil
|
||||
@ -152,9 +154,8 @@ public final class ContextGesture: UIGestureRecognizer, UIGestureRecognizerDeleg
|
||||
|
||||
if let touch = touches.first {
|
||||
if !self.currentProgress.isZero, self.isValidated {
|
||||
if #available(iOS 9.0, *) {
|
||||
self.activationProgress?(0.0, .ended(self.currentProgress))
|
||||
}
|
||||
self.currentProgress = 0.0
|
||||
self.activationProgress?(0.0, .ended(self.currentProgress))
|
||||
}
|
||||
|
||||
self.externalEnded?((self.view, touch.location(in: self.view)))
|
||||
@ -170,9 +171,8 @@ public final class ContextGesture: UIGestureRecognizer, UIGestureRecognizerDeleg
|
||||
super.touchesCancelled(touches, with: event)
|
||||
|
||||
if let touch = touches.first, !self.currentProgress.isZero, self.isValidated {
|
||||
if #available(iOS 9.0, *) {
|
||||
self.activationProgress?(0.0, .ended(self.currentProgress))
|
||||
}
|
||||
self.currentProgress = 0.0
|
||||
self.activationProgress?(0.0, .ended(self.currentProgress))
|
||||
}
|
||||
|
||||
self.delayTimer?.invalidate()
|
||||
@ -183,6 +183,7 @@ public final class ContextGesture: UIGestureRecognizer, UIGestureRecognizerDeleg
|
||||
|
||||
public func cancel() {
|
||||
if !self.currentProgress.isZero, self.isValidated {
|
||||
self.currentProgress = 0.0
|
||||
self.activationProgress?(0.0, .ended(self.currentProgress))
|
||||
|
||||
self.delayTimer?.invalidate()
|
||||
|
||||
@ -95,10 +95,8 @@ final class GlobalOverlayPresentationContext {
|
||||
}
|
||||
return keyboardWindow
|
||||
} else {
|
||||
if underStatusBar, let view = self.parentView {
|
||||
if let view = self.parentView {
|
||||
return view
|
||||
} else {
|
||||
return statusBarHost.statusBarWindow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3313,6 +3313,10 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
indicatorFrame.origin.y = self.visibleSize.height - (self.scrollIndicatorInsets.bottom + indicatorBottomInset) - indicatorFrame.height
|
||||
}
|
||||
|
||||
if indicatorFrame.origin.y.isNaN {
|
||||
indicatorFrame.origin.y = indicatorTopInset
|
||||
}
|
||||
|
||||
if indicatorHeight >= visibleHeightWithoutIndicatorInsets {
|
||||
verticalScrollIndicator.isHidden = true
|
||||
verticalScrollIndicator.frame = indicatorFrame
|
||||
|
||||
@ -76,13 +76,22 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
private(set) var controllers: [ViewController] = []
|
||||
private var state: State = State(layout: nil, canBeClosed: nil, top: nil, transition: nil, pending: nil)
|
||||
|
||||
private var ignoreInputHeight: Bool = false
|
||||
|
||||
private(set) var isReady: Bool = false
|
||||
var isReadyUpdated: (() -> Void)?
|
||||
var controllerRemoved: (ViewController) -> Void
|
||||
var keyboardViewManager: KeyboardViewManager? {
|
||||
didSet {
|
||||
if self.keyboardViewManager !== oldValue {
|
||||
|
||||
}
|
||||
}
|
||||
var canHaveKeyboardFocus: Bool = false {
|
||||
didSet {
|
||||
if self.canHaveKeyboardFocus != oldValue {
|
||||
if !self.canHaveKeyboardFocus {
|
||||
self.view.endEditing(true)
|
||||
self.performUpdate(transition: .animated(duration: 0.5, curve: .spring))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -147,6 +156,7 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
guard self.state.transition == nil else {
|
||||
return
|
||||
}
|
||||
|
||||
let beginGesture = self.controllers.count > 1
|
||||
|
||||
if beginGesture {
|
||||
@ -163,7 +173,7 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
|
||||
topController.viewWillDisappear(true)
|
||||
let topNode = topController.displayNode
|
||||
bottomController.containerLayoutUpdated(layout, transition: .immediate)
|
||||
bottomController.containerLayoutUpdated(layout.withUpdatedInputHeight(nil), transition: .immediate)
|
||||
bottomController.viewWillAppear(true)
|
||||
let bottomNode = bottomController.displayNode
|
||||
|
||||
@ -195,11 +205,16 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
|
||||
let topController = top.value
|
||||
let bottomController = transition.previous.value
|
||||
|
||||
if viewTreeContainsFirstResponder(view: top.value.view) {
|
||||
strongSelf.ignoreInputHeight = true
|
||||
}
|
||||
strongSelf.keyboardViewManager?.dismissEditingWithoutAnimation(view: topController.view)
|
||||
|
||||
strongSelf.state.transition = nil
|
||||
|
||||
strongSelf.controllerRemoved(top.value)
|
||||
strongSelf.ignoreInputHeight = false
|
||||
})
|
||||
} else {
|
||||
navigationTransitionCoordinator.animateCancel({ [weak self] in
|
||||
@ -383,12 +398,16 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
}
|
||||
|
||||
private func makeChild(layout: ContainerViewLayout, value: ViewController) -> Child {
|
||||
value.containerLayoutUpdated(layout, transition: .immediate)
|
||||
return Child(value: value, layout: layout)
|
||||
let updatedLayout = layout.withUpdatedInputHeight(nil)
|
||||
value.containerLayoutUpdated(updatedLayout, transition: .immediate)
|
||||
return Child(value: value, layout: updatedLayout)
|
||||
}
|
||||
|
||||
private func applyLayout(layout: ContainerViewLayout, to child: Child, isMaster: Bool, transition: ContainedViewLayoutTransition) {
|
||||
var childFrame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
|
||||
var updatedLayout = layout
|
||||
|
||||
var shouldSyncKeyboard = false
|
||||
if let transition = self.state.transition {
|
||||
childFrame.origin.x = child.value.displayNode.frame.origin.x
|
||||
@ -400,10 +419,21 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
case .push:
|
||||
break
|
||||
}
|
||||
if updatedLayout.inputHeight != nil {
|
||||
if !self.canHaveKeyboardFocus {
|
||||
updatedLayout = updatedLayout.withUpdatedInputHeight(nil)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if isMaster {
|
||||
shouldSyncKeyboard = true
|
||||
}
|
||||
|
||||
if updatedLayout.inputHeight != nil {
|
||||
if !self.canHaveKeyboardFocus || self.ignoreInputHeight {
|
||||
updatedLayout = updatedLayout.withUpdatedInputHeight(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
if child.value.displayNode.frame != childFrame {
|
||||
transition.updateFrame(node: child.value.displayNode, frame: childFrame)
|
||||
@ -411,9 +441,9 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
if shouldSyncKeyboard && isMaster {
|
||||
self.syncKeyboard(leftEdge: childFrame.minX, transition: transition)
|
||||
}
|
||||
if child.layout != layout {
|
||||
child.layout = layout
|
||||
child.value.containerLayoutUpdated(layout, transition: transition)
|
||||
if child.layout != updatedLayout {
|
||||
child.layout = updatedLayout
|
||||
child.value.containerLayoutUpdated(updatedLayout, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
@ -430,13 +460,13 @@ final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
private func pendingChildIsReady(_ child: PendingChild) {
|
||||
if let pending = self.state.pending, pending === child {
|
||||
pending.isReady = true
|
||||
self.performUpdate()
|
||||
self.performUpdate(transition: .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
private func performUpdate() {
|
||||
private func performUpdate(transition: ContainedViewLayoutTransition) {
|
||||
if let layout = self.state.layout, let canBeClosed = self.state.canBeClosed {
|
||||
self.update(layout: layout, canBeClosed: canBeClosed, controllers: self.controllers, transition: .immediate)
|
||||
self.update(layout: layout, canBeClosed: canBeClosed, controllers: self.controllers, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -118,12 +118,18 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
return self.view as! NavigationControllerView
|
||||
}
|
||||
|
||||
var inCallNavigate: (() -> Void)?
|
||||
private var inCallStatusBar: StatusBar?
|
||||
private var globalScrollToTopNode: ScrollToTopNode?
|
||||
private var rootContainer: RootContainer?
|
||||
private var rootModalFrame: NavigationModalFrame?
|
||||
private var modalContainers: [NavigationModalContainer] = []
|
||||
private var overlayContainers: [NavigationOverlayContainer] = []
|
||||
private var validLayout: ContainerViewLayout?
|
||||
private var validStatusBarStyle: NavigationStatusBarStyle?
|
||||
private var validStatusBarHidden: Bool = false
|
||||
|
||||
private var currentStatusBarExternalHidden: Bool = false
|
||||
|
||||
private var scheduledLayoutTransitionRequestId: Int = 0
|
||||
private var scheduledLayoutTransitionRequest: (Int, ContainedViewLayoutTransition)?
|
||||
@ -151,7 +157,10 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
return self._displayNode!
|
||||
}
|
||||
|
||||
var statusBarHost: StatusBarHost?
|
||||
var statusBarHost: StatusBarHost? {
|
||||
didSet {
|
||||
}
|
||||
}
|
||||
var keyboardViewManager: KeyboardViewManager?
|
||||
|
||||
public func updateMasterDetailsBlackout(_ blackout: MasterDetailLayoutBlackout?, transition: ContainedViewLayoutTransition) {
|
||||
@ -199,6 +208,9 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
for modalContainer in self.modalContainers {
|
||||
supportedOrientations = supportedOrientations.intersection(modalContainer.container.combinedSupportedOrientations(currentOrientationToLock: currentOrientationToLock))
|
||||
}
|
||||
for overlayContrainer in self.overlayContainers {
|
||||
supportedOrientations = supportedOrientations.intersection(overlayContrainer.controller.combinedSupportedOrientations(currentOrientationToLock: currentOrientationToLock))
|
||||
}
|
||||
return supportedOrientations
|
||||
}
|
||||
|
||||
@ -214,18 +226,10 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
}
|
||||
}
|
||||
if self.isViewLoaded {
|
||||
if statusBarStyleUpdated {
|
||||
self.validStatusBarStyle = self.theme.statusBar
|
||||
let normalStatusBarStyle: UIStatusBarStyle
|
||||
switch self.theme.statusBar {
|
||||
case .black:
|
||||
normalStatusBarStyle = .default
|
||||
case .white:
|
||||
normalStatusBarStyle = .lightContent
|
||||
}
|
||||
//self.statusBarHost?.setStatusBarStyle(normalStatusBarStyle, animated: false)
|
||||
}
|
||||
self.controllerView.backgroundColor = theme.emptyAreaColor
|
||||
if let layout = self.validLayout {
|
||||
self.containerLayoutUpdated(layout, transition: .immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,16 +243,33 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
}
|
||||
self.validLayout = layout
|
||||
self.updateContainers(layout: layout, transition: transition)
|
||||
|
||||
self.inCallStatusBar?.frame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: max(40.0, layout.safeInsets.top)))
|
||||
self.inCallStatusBar?.updateState(statusBar: nil, withSafeInsets: false, inCallText: "In Call Text", animated: false)
|
||||
}
|
||||
|
||||
private func updateContainers(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
private weak var currentTopVisibleOverlayContainerStatusBar: NavigationOverlayContainer? = nil
|
||||
|
||||
private func updateContainers(layout rawLayout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
var layout = rawLayout
|
||||
|
||||
if let globalScrollToTopNode = self.globalScrollToTopNode {
|
||||
globalScrollToTopNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -1.0), size: CGSize(width: layout.size.width, height: 1.0))
|
||||
}
|
||||
|
||||
if let inCallStatusBar = self.inCallStatusBar {
|
||||
let inCallStatusBarFrame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: max(40.0, layout.safeInsets.top)))
|
||||
if inCallStatusBar.frame.isEmpty {
|
||||
inCallStatusBar.frame = inCallStatusBarFrame
|
||||
} else {
|
||||
transition.updateFrame(node: inCallStatusBar, frame: inCallStatusBarFrame)
|
||||
}
|
||||
layout.statusBarHeight = inCallStatusBarFrame.height
|
||||
self.inCallStatusBar?.frame = inCallStatusBarFrame
|
||||
}
|
||||
|
||||
let navigationLayout = makeNavigationLayout(mode: self.mode, layout: layout, controllers: self._viewControllers)
|
||||
|
||||
var transition = transition
|
||||
var statusBarStyle: StatusBarStyle = .Ignore
|
||||
var statusBarHidden = false
|
||||
var animateStatusBarStyleTransition = transition.isAnimated
|
||||
|
||||
var modalContainers: [NavigationModalContainer] = []
|
||||
@ -311,6 +332,56 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
}
|
||||
self.modalContainers = modalContainers
|
||||
|
||||
var previousOverlayContainer: NavigationOverlayContainer?
|
||||
var topVisibleOverlayContainerWithStatusBar: NavigationOverlayContainer?
|
||||
for i in (0 ..< self.overlayContainers.count).reversed() {
|
||||
let overlayContainer = self.overlayContainers[i]
|
||||
|
||||
let containerTransition: ContainedViewLayoutTransition
|
||||
if overlayContainer.supernode == nil {
|
||||
containerTransition = .immediate
|
||||
} else {
|
||||
containerTransition = transition
|
||||
}
|
||||
|
||||
containerTransition.updateFrame(node: overlayContainer, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
overlayContainer.update(layout: layout, transition: containerTransition)
|
||||
|
||||
if overlayContainer.supernode == nil && overlayContainer.isReady {
|
||||
if let previousOverlayContainer = previousOverlayContainer {
|
||||
self.displayNode.insertSubnode(overlayContainer, belowSubnode: previousOverlayContainer)
|
||||
} else if let globalScrollToTopNode = self.globalScrollToTopNode {
|
||||
self.displayNode.insertSubnode(overlayContainer, belowSubnode: globalScrollToTopNode)
|
||||
} else {
|
||||
self.displayNode.addSubnode(overlayContainer)
|
||||
}
|
||||
overlayContainer.transitionIn()
|
||||
}
|
||||
|
||||
if overlayContainer.supernode != nil {
|
||||
previousOverlayContainer = overlayContainer
|
||||
let controllerStatusBarStyle = overlayContainer.controller.statusBar.statusBarStyle
|
||||
switch controllerStatusBarStyle {
|
||||
case .Black, .White, .Hide:
|
||||
if topVisibleOverlayContainerWithStatusBar == nil {
|
||||
topVisibleOverlayContainerWithStatusBar = overlayContainer
|
||||
}
|
||||
if case .Hide = controllerStatusBarStyle {
|
||||
statusBarHidden = true
|
||||
} else {
|
||||
statusBarHidden = overlayContainer.controller.statusBar.alpha.isZero
|
||||
}
|
||||
case .Ignore:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.currentTopVisibleOverlayContainerStatusBar !== topVisibleOverlayContainerWithStatusBar {
|
||||
self.currentTopVisibleOverlayContainerStatusBar = topVisibleOverlayContainerWithStatusBar
|
||||
animateStatusBarStyleTransition = true
|
||||
}
|
||||
|
||||
var previousModalContainer: NavigationModalContainer?
|
||||
var visibleModalCount = 0
|
||||
var topModalDismissProgress: CGFloat = 0.0
|
||||
@ -342,6 +413,10 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
self.displayNode.insertSubnode(modalContainer, belowSubnode: previousModalContainer)
|
||||
} else if let inCallStatusBar = self.inCallStatusBar {
|
||||
self.displayNode.insertSubnode(modalContainer, belowSubnode: inCallStatusBar)
|
||||
} else if let previousOverlayContainer = previousOverlayContainer {
|
||||
self.displayNode.insertSubnode(modalContainer, belowSubnode: previousOverlayContainer)
|
||||
} else if let globalScrollToTopNode = self.globalScrollToTopNode {
|
||||
self.displayNode.insertSubnode(modalContainer, belowSubnode: globalScrollToTopNode)
|
||||
} else {
|
||||
self.displayNode.addSubnode(modalContainer)
|
||||
}
|
||||
@ -354,11 +429,14 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
topModalDismissProgress = modalContainer.dismissProgress
|
||||
if case .compact = layout.metrics.widthClass {
|
||||
modalContainer.keyboardViewManager = self.keyboardViewManager
|
||||
modalContainer.canHaveKeyboardFocus = true
|
||||
} else {
|
||||
modalContainer.keyboardViewManager = nil
|
||||
modalContainer.canHaveKeyboardFocus = true
|
||||
}
|
||||
} else {
|
||||
modalContainer.keyboardViewManager = nil
|
||||
modalContainer.canHaveKeyboardFocus = false
|
||||
}
|
||||
previousModalContainer = modalContainer
|
||||
}
|
||||
@ -371,8 +449,10 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
case let .flat(flatContainer):
|
||||
if previousModalContainer == nil {
|
||||
flatContainer.keyboardViewManager = self.keyboardViewManager
|
||||
flatContainer.canHaveKeyboardFocus = true
|
||||
} else {
|
||||
flatContainer.keyboardViewManager = nil
|
||||
flatContainer.canHaveKeyboardFocus = false
|
||||
}
|
||||
transition.updateFrame(node: flatContainer, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
flatContainer.update(layout: layout, canBeClosed: false, controllers: controllers, transition: transition)
|
||||
@ -386,6 +466,13 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
}
|
||||
strongSelf.updateContainers(layout: layout, transition: transition)
|
||||
}
|
||||
if previousModalContainer == nil {
|
||||
flatContainer.keyboardViewManager = self.keyboardViewManager
|
||||
flatContainer.canHaveKeyboardFocus = true
|
||||
} else {
|
||||
flatContainer.keyboardViewManager = nil
|
||||
flatContainer.canHaveKeyboardFocus = false
|
||||
}
|
||||
self.displayNode.insertSubnode(flatContainer, at: 0)
|
||||
self.rootContainer = .flat(flatContainer)
|
||||
flatContainer.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
@ -402,6 +489,13 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
}
|
||||
strongSelf.updateContainers(layout: layout, transition: transition)
|
||||
}
|
||||
if previousModalContainer == nil {
|
||||
flatContainer.keyboardViewManager = self.keyboardViewManager
|
||||
flatContainer.canHaveKeyboardFocus = true
|
||||
} else {
|
||||
flatContainer.keyboardViewManager = nil
|
||||
flatContainer.canHaveKeyboardFocus = false
|
||||
}
|
||||
self.displayNode.insertSubnode(flatContainer, at: 0)
|
||||
self.rootContainer = .flat(flatContainer)
|
||||
flatContainer.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
@ -413,23 +507,42 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
case let .flat(flatContainer):
|
||||
let splitContainer = NavigationSplitContainer(theme: self.theme, controllerRemoved: { [weak self] controller in
|
||||
self?.controllerRemoved(controller)
|
||||
}, scrollToTop: { [weak self] subject in
|
||||
self?.scrollToTop(subject)
|
||||
})
|
||||
self.displayNode.insertSubnode(splitContainer, at: 0)
|
||||
self.rootContainer = .split(splitContainer)
|
||||
if previousModalContainer == nil {
|
||||
splitContainer.canHaveKeyboardFocus = true
|
||||
} else {
|
||||
splitContainer.canHaveKeyboardFocus = false
|
||||
}
|
||||
splitContainer.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
splitContainer.update(layout: layout, masterControllers: masterControllers, detailControllers: detailControllers, transition: .immediate)
|
||||
flatContainer.statusBarStyleUpdated = nil
|
||||
flatContainer.removeFromSupernode()
|
||||
case let .split(splitContainer):
|
||||
if previousModalContainer == nil {
|
||||
splitContainer.canHaveKeyboardFocus = true
|
||||
} else {
|
||||
splitContainer.canHaveKeyboardFocus = false
|
||||
}
|
||||
transition.updateFrame(node: splitContainer, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
splitContainer.update(layout: layout, masterControllers: masterControllers, detailControllers: detailControllers, transition: transition)
|
||||
}
|
||||
} else {
|
||||
let splitContainer = NavigationSplitContainer(theme: self.theme, controllerRemoved: { [weak self] controller in
|
||||
self?.controllerRemoved(controller)
|
||||
}, scrollToTop: { [weak self] subject in
|
||||
self?.scrollToTop(subject)
|
||||
})
|
||||
self.displayNode.insertSubnode(splitContainer, at: 0)
|
||||
self.rootContainer = .split(splitContainer)
|
||||
if previousModalContainer == nil {
|
||||
splitContainer.canHaveKeyboardFocus = true
|
||||
} else {
|
||||
splitContainer.canHaveKeyboardFocus = false
|
||||
}
|
||||
splitContainer.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
splitContainer.update(layout: layout, masterControllers: masterControllers, detailControllers: detailControllers, transition: .immediate)
|
||||
}
|
||||
@ -439,8 +552,9 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
switch rootContainer {
|
||||
case let .flat(container):
|
||||
statusBarStyle = container.statusBarStyle
|
||||
self.globalScrollToTopNode?.isHidden = false
|
||||
case .split:
|
||||
break
|
||||
self.globalScrollToTopNode?.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -559,6 +673,18 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
}
|
||||
}
|
||||
|
||||
if self.inCallStatusBar != nil {
|
||||
statusBarStyle = .White
|
||||
}
|
||||
|
||||
if let topVisibleOverlayContainerWithStatusBar = topVisibleOverlayContainerWithStatusBar {
|
||||
statusBarStyle = topVisibleOverlayContainerWithStatusBar.controller.statusBar.statusBarStyle
|
||||
}
|
||||
|
||||
if self.currentStatusBarExternalHidden {
|
||||
statusBarHidden = true
|
||||
}
|
||||
|
||||
let resolvedStatusBarStyle: NavigationStatusBarStyle
|
||||
switch statusBarStyle {
|
||||
case .Ignore, .Hide:
|
||||
@ -580,6 +706,11 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
}
|
||||
self.statusBarHost?.setStatusBarStyle(normalStatusBarStyle, animated: animateStatusBarStyleTransition)
|
||||
}
|
||||
|
||||
if self.validStatusBarHidden != statusBarHidden {
|
||||
self.validStatusBarHidden = statusBarHidden
|
||||
self.statusBarHost?.setStatusBarHidden(statusBarHidden, animated: animateStatusBarStyleTransition)
|
||||
}
|
||||
}
|
||||
|
||||
private func controllerRemoved(_ controller: ViewController) {
|
||||
@ -589,6 +720,28 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
public func updateModalTransition(_ value: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
}
|
||||
|
||||
private func scrollToTop(_ subject: NavigationSplitContainerScrollToTop) {
|
||||
if let _ = self.inCallStatusBar {
|
||||
self.inCallNavigate?()
|
||||
} else if let rootContainer = self.rootContainer {
|
||||
if let modalContainer = self.modalContainers.last {
|
||||
modalContainer.container.controllers.last?.scrollToTop?()
|
||||
} else {
|
||||
switch rootContainer {
|
||||
case let .flat(container):
|
||||
container.controllers.last?.scrollToTop?()
|
||||
case let .split(container):
|
||||
switch subject {
|
||||
case .master:
|
||||
container.masterControllers.last?.scrollToTop?()
|
||||
case .detail:
|
||||
container.detailControllers.last?.scrollToTop?()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func updateToInterfaceOrientation(_ orientation: UIInterfaceOrientation) {
|
||||
/*for record in self._viewControllers {
|
||||
if let controller = record.controller as? ContainableController {
|
||||
@ -613,9 +766,11 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
}
|
||||
self.navigationBar.removeFromSuperview()
|
||||
|
||||
/*let inCallStatusBar = StatusBar()
|
||||
self.displayNode.addSubnode(inCallStatusBar)
|
||||
self.inCallStatusBar = inCallStatusBar*/
|
||||
let globalScrollToTopNode = ScrollToTopNode(action: { [weak self] in
|
||||
self?.scrollToTop(.master)
|
||||
})
|
||||
self.displayNode.addSubnode(globalScrollToTopNode)
|
||||
self.globalScrollToTopNode = globalScrollToTopNode
|
||||
}
|
||||
|
||||
public func pushViewController(_ controller: ViewController) {
|
||||
@ -750,6 +905,53 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
}
|
||||
}
|
||||
|
||||
public func presentOverlay(controller: ViewController, inGlobal: Bool = false) {
|
||||
let container = NavigationOverlayContainer(controller: controller, controllerRemoved: { [weak self] controller in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
for i in 0 ..< strongSelf.overlayContainers.count {
|
||||
let overlayContainer = strongSelf.overlayContainers[i]
|
||||
if overlayContainer.controller === controller {
|
||||
overlayContainer.removeFromSupernode()
|
||||
strongSelf.overlayContainers.remove(at: i)
|
||||
break
|
||||
}
|
||||
}
|
||||
if let layout = strongSelf.validLayout {
|
||||
strongSelf.updateContainers(layout: layout, transition: .immediate)
|
||||
}
|
||||
}, statusBarUpdated: { [weak self] transition in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if let layout = strongSelf.validLayout {
|
||||
strongSelf.updateContainers(layout: layout, transition: transition)
|
||||
}
|
||||
})
|
||||
self.overlayContainers.append(container)
|
||||
container.isReadyUpdated = { [weak self, weak container] in
|
||||
guard let strongSelf = self, let container = container else {
|
||||
return
|
||||
}
|
||||
if let layout = strongSelf.validLayout {
|
||||
strongSelf.updateContainers(layout: layout, transition: .immediate)
|
||||
}
|
||||
}
|
||||
if let layout = self.validLayout {
|
||||
self.updateContainers(layout: layout, transition: .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
func updateExternalStatusBarHidden(_ value: Bool, transition: ContainedViewLayoutTransition) {
|
||||
if self.currentStatusBarExternalHidden != value {
|
||||
self.currentStatusBarExternalHidden = value
|
||||
if let layout = self.validLayout {
|
||||
self.updateContainers(layout: layout, transition: transition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override open func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
|
||||
preconditionFailure()
|
||||
}
|
||||
@ -816,4 +1018,49 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
self.containerLayoutUpdated(validLayout, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
public func setForceInCallStatusBar(_ forceInCallStatusBarText: String?, transition: ContainedViewLayoutTransition = .animated(duration: 0.3, curve: .easeInOut)) {
|
||||
if let forceInCallStatusBarText = forceInCallStatusBarText {
|
||||
let inCallStatusBar: StatusBar
|
||||
if let current = self.inCallStatusBar {
|
||||
inCallStatusBar = current
|
||||
} else {
|
||||
inCallStatusBar = StatusBar()
|
||||
inCallStatusBar.inCallNavigate = { [weak self] in
|
||||
self?.scrollToTop(.master)
|
||||
}
|
||||
inCallStatusBar.alpha = 0.0
|
||||
self.inCallStatusBar = inCallStatusBar
|
||||
|
||||
var bottomOverlayContainer: NavigationOverlayContainer?
|
||||
for overlayContainer in self.overlayContainers {
|
||||
if overlayContainer.supernode != nil {
|
||||
bottomOverlayContainer = overlayContainer
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if let bottomOverlayContainer = bottomOverlayContainer {
|
||||
self.displayNode.insertSubnode(inCallStatusBar, belowSubnode: bottomOverlayContainer)
|
||||
} else if let globalScrollToTopNode = self.globalScrollToTopNode {
|
||||
self.displayNode.insertSubnode(inCallStatusBar, belowSubnode: globalScrollToTopNode)
|
||||
} else {
|
||||
self.displayNode.addSubnode(inCallStatusBar)
|
||||
}
|
||||
transition.updateAlpha(node: inCallStatusBar, alpha: 1.0)
|
||||
}
|
||||
if let layout = self.validLayout {
|
||||
self.containerLayoutUpdated(layout, transition: transition)
|
||||
inCallStatusBar.updateState(statusBar: nil, withSafeInsets: false, inCallText: forceInCallStatusBarText, animated: false)
|
||||
}
|
||||
} else if let inCallStatusBar = self.inCallStatusBar {
|
||||
self.inCallStatusBar = nil
|
||||
transition.updateAlpha(node: inCallStatusBar, alpha: 0.0, completion: { [weak inCallStatusBar] _ in
|
||||
inCallStatusBar?.removeFromSupernode()
|
||||
})
|
||||
if let layout = self.validLayout {
|
||||
self.containerLayoutUpdated(layout, transition: transition)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,6 +33,12 @@ final class NavigationModalContainer: ASDisplayNode, UIScrollViewDelegate, UIGes
|
||||
}
|
||||
}
|
||||
|
||||
var canHaveKeyboardFocus: Bool = false {
|
||||
didSet {
|
||||
self.container.canHaveKeyboardFocus = self.canHaveKeyboardFocus
|
||||
}
|
||||
}
|
||||
|
||||
init(theme: NavigationControllerTheme, controllerRemoved: @escaping (ViewController) -> Void) {
|
||||
self.theme = theme
|
||||
|
||||
@ -195,6 +201,8 @@ final class NavigationModalContainer: ASDisplayNode, UIScrollViewDelegate, UIGes
|
||||
self.dismissProgress = dismissProgress
|
||||
|
||||
self.applyDismissProgress(transition: transition, completion: {})
|
||||
|
||||
self.view.endEditing(true)
|
||||
}
|
||||
|
||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
|
||||
@ -0,0 +1,78 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import AsyncDisplayKit
|
||||
import SwiftSignalKit
|
||||
|
||||
final class NavigationOverlayContainer: ASDisplayNode {
|
||||
let controller: ViewController
|
||||
|
||||
private(set) var isReady: Bool = false
|
||||
var isReadyUpdated: (() -> Void)?
|
||||
private var isReadyDisposable: Disposable?
|
||||
|
||||
private var validLayout: ContainerViewLayout?
|
||||
|
||||
var keyboardViewManager: KeyboardViewManager? {
|
||||
didSet {
|
||||
if self.keyboardViewManager !== oldValue {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init(controller: ViewController, controllerRemoved: @escaping (ViewController) -> Void, statusBarUpdated: @escaping (ContainedViewLayoutTransition) -> Void) {
|
||||
self.controller = controller
|
||||
|
||||
super.init()
|
||||
|
||||
self.controller.navigation_setDismiss({ [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
controllerRemoved(strongSelf.controller)
|
||||
}, rootController: nil)
|
||||
|
||||
self.controller.statusBar.alphaUpdated = { transition in
|
||||
statusBarUpdated(transition)
|
||||
}
|
||||
|
||||
self.isReadyDisposable = (self.controller.ready.get()
|
||||
|> filter { $0 }
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if !strongSelf.isReady {
|
||||
strongSelf.isReady = true
|
||||
strongSelf.isReadyUpdated?()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.isReadyDisposable?.dispose()
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
}
|
||||
|
||||
func update(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
let updateLayout = self.validLayout != layout
|
||||
|
||||
self.validLayout = layout
|
||||
|
||||
if updateLayout {
|
||||
transition.updateFrame(node: self.controller.displayNode, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
self.controller.containerLayoutUpdated(layout, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
func transitionIn() {
|
||||
self.controller.viewWillAppear(false)
|
||||
self.controller.setIgnoreAppearanceMethodInvocations(true)
|
||||
self.addSubnode(self.controller.displayNode)
|
||||
self.controller.setIgnoreAppearanceMethodInvocations(false)
|
||||
self.controller.viewDidAppear(false)
|
||||
}
|
||||
}
|
||||
@ -3,19 +3,42 @@ import UIKit
|
||||
import AsyncDisplayKit
|
||||
import SwiftSignalKit
|
||||
|
||||
enum NavigationSplitContainerScrollToTop {
|
||||
case master
|
||||
case detail
|
||||
}
|
||||
|
||||
final class NavigationSplitContainer: ASDisplayNode {
|
||||
private var theme: NavigationControllerTheme
|
||||
|
||||
private let masterScrollToTopView: ScrollToTopView
|
||||
private let detailScrollToTopView: ScrollToTopView
|
||||
private let masterContainer: NavigationContainer
|
||||
private let detailContainer: NavigationContainer
|
||||
private let separator: ASDisplayNode
|
||||
|
||||
private var masterControllers: [ViewController] = []
|
||||
private var detailControllers: [ViewController] = []
|
||||
private(set) var masterControllers: [ViewController] = []
|
||||
private(set) var detailControllers: [ViewController] = []
|
||||
|
||||
init(theme: NavigationControllerTheme, controllerRemoved: @escaping (ViewController) -> Void) {
|
||||
var canHaveKeyboardFocus: Bool = false {
|
||||
didSet {
|
||||
self.masterContainer.canHaveKeyboardFocus = self.canHaveKeyboardFocus
|
||||
self.detailContainer.canHaveKeyboardFocus = self.canHaveKeyboardFocus
|
||||
}
|
||||
}
|
||||
|
||||
init(theme: NavigationControllerTheme, controllerRemoved: @escaping (ViewController) -> Void, scrollToTop: @escaping (NavigationSplitContainerScrollToTop) -> Void) {
|
||||
self.theme = theme
|
||||
|
||||
self.masterScrollToTopView = ScrollToTopView(frame: CGRect())
|
||||
self.masterScrollToTopView.action = {
|
||||
scrollToTop(.master)
|
||||
}
|
||||
self.detailScrollToTopView = ScrollToTopView(frame: CGRect())
|
||||
self.detailScrollToTopView.action = {
|
||||
scrollToTop(.detail)
|
||||
}
|
||||
|
||||
self.masterContainer = NavigationContainer(controllerRemoved: controllerRemoved)
|
||||
self.masterContainer.clipsToBounds = true
|
||||
|
||||
@ -30,6 +53,8 @@ final class NavigationSplitContainer: ASDisplayNode {
|
||||
self.addSubnode(self.masterContainer)
|
||||
self.addSubnode(self.detailContainer)
|
||||
self.addSubnode(self.separator)
|
||||
self.view.addSubview(self.masterScrollToTopView)
|
||||
self.view.addSubview(self.detailScrollToTopView)
|
||||
}
|
||||
|
||||
func updateTheme(theme: NavigationControllerTheme) {
|
||||
@ -40,6 +65,9 @@ final class NavigationSplitContainer: ASDisplayNode {
|
||||
let masterWidth = min(max(320.0, floor(layout.size.width / 3.0)), floor(layout.size.width / 2.0))
|
||||
let detailWidth = layout.size.width - masterWidth
|
||||
|
||||
self.masterScrollToTopView.frame = CGRect(origin: CGPoint(x: 0.0, y: -1.0), size: CGSize(width: masterWidth, height: 1.0))
|
||||
self.detailScrollToTopView.frame = CGRect(origin: CGPoint(x: masterWidth, y: -1.0), size: CGSize(width: detailWidth, height: 1.0))
|
||||
|
||||
transition.updateFrame(node: self.masterContainer, frame: CGRect(origin: CGPoint(), size: CGSize(width: masterWidth, height: layout.size.height)))
|
||||
transition.updateFrame(node: self.detailContainer, frame: CGRect(origin: CGPoint(x: masterWidth, y: 0.0), size: CGSize(width: detailWidth, height: layout.size.height)))
|
||||
transition.updateFrame(node: self.separator, frame: CGRect(origin: CGPoint(x: masterWidth, y: 0.0), size: CGSize(width: UIScreenPixel, height: layout.size.height)))
|
||||
|
||||
@ -35,3 +35,15 @@ class ScrollToTopView: UIScrollView, UIScrollViewDelegate {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
class ScrollToTopNode: ASDisplayNode {
|
||||
init(action: @escaping () -> Void) {
|
||||
super.init()
|
||||
|
||||
self.setViewBlock({
|
||||
let view = ScrollToTopView(frame: CGRect())
|
||||
view.action = action
|
||||
return view
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,6 +68,7 @@ public final class StatusBar: ASDisplayNode {
|
||||
didSet {
|
||||
if self.statusBarStyle != oldValue {
|
||||
self.layer.invalidateUpTheTree()
|
||||
self.alphaUpdated?(.immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -94,6 +95,13 @@ public final class StatusBar: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
var alphaUpdated: ((ContainedViewLayoutTransition) -> Void)?
|
||||
|
||||
public func updateAlpha(_ alpha: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
self.alpha = alpha
|
||||
self.alphaUpdated?(transition)
|
||||
}
|
||||
|
||||
public override init() {
|
||||
self.inCallLabel = StatusBarLabelNode()
|
||||
self.inCallLabel.isUserInteractionEnabled = false
|
||||
|
||||
@ -12,5 +12,8 @@ public protocol StatusBarHost {
|
||||
|
||||
var handleVolumeControl: Signal<Bool, NoError> { get }
|
||||
|
||||
var isApplicationInForeground: Bool { get }
|
||||
|
||||
func setStatusBarStyle(_ style: UIStatusBarStyle, animated: Bool)
|
||||
func setStatusBarHidden(_ value: Bool, animated: Bool)
|
||||
}
|
||||
|
||||
@ -127,6 +127,15 @@ open class TabBarController: ViewController {
|
||||
self.theme = theme
|
||||
|
||||
super.init(navigationBarPresentationData: navigationBarPresentationData)
|
||||
|
||||
self.scrollToTop = { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if let controller = strongSelf.currentController {
|
||||
controller.scrollToTop?()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
required public init(coder aDecoder: NSCoder) {
|
||||
|
||||
@ -246,7 +246,7 @@ public enum ViewControllerNavigationPresentation {
|
||||
}
|
||||
|
||||
private func updateScrollToTopView() {
|
||||
if self.scrollToTop != nil {
|
||||
/*if self.scrollToTop != nil {
|
||||
if let displayNode = self._displayNode , self.scrollToTopView == nil {
|
||||
let scrollToTopView = ScrollToTopView(frame: CGRect(x: 0.0, y: -1.0, width: displayNode.bounds.size.width, height: 1.0))
|
||||
scrollToTopView.action = { [weak self] in
|
||||
@ -257,7 +257,7 @@ public enum ViewControllerNavigationPresentation {
|
||||
self.scrollToTopView = scrollToTopView
|
||||
self.view.addSubview(scrollToTopView)
|
||||
}
|
||||
} else if let scrollToTopView = self.scrollToTopView {
|
||||
} else*/ if let scrollToTopView = self.scrollToTopView {
|
||||
scrollToTopView.removeFromSuperview()
|
||||
self.scrollToTopView = nil
|
||||
}
|
||||
|
||||
@ -280,7 +280,7 @@ public class Window1 {
|
||||
private var deviceMetrics: DeviceMetrics
|
||||
|
||||
private let statusBarHost: StatusBarHost?
|
||||
private let statusBarManager: StatusBarManager?
|
||||
//private let statusBarManager: StatusBarManager?
|
||||
private let keyboardManager: KeyboardManager?
|
||||
private let keyboardViewManager: KeyboardViewManager?
|
||||
private var statusBarChangeObserver: AnyObject?
|
||||
@ -312,7 +312,7 @@ public class Window1 {
|
||||
public private(set) var forceInCallStatusBarText: String? = nil
|
||||
public var inCallNavigate: (() -> Void)? {
|
||||
didSet {
|
||||
self.statusBarManager?.inCallNavigate = self.inCallNavigate
|
||||
//self.statusBarManager?.inCallNavigate = self.inCallNavigate
|
||||
}
|
||||
}
|
||||
|
||||
@ -323,21 +323,17 @@ public class Window1 {
|
||||
|
||||
private var keyboardTypeChangeTimer: SwiftSignalKit.Timer?
|
||||
|
||||
private let volumeControlStatusBar: VolumeControlStatusBar
|
||||
private let volumeControlStatusBarNode: VolumeControlStatusBarNode
|
||||
//private let volumeControlStatusBar: VolumeControlStatusBar
|
||||
//private let volumeControlStatusBarNode: VolumeControlStatusBarNode
|
||||
|
||||
private var isInteractionBlocked = false
|
||||
|
||||
/*private var accessibilityElements: [Any]? {
|
||||
return self.viewController?.view.accessibilityElements
|
||||
}*/
|
||||
|
||||
public init(hostView: WindowHostView, statusBarHost: StatusBarHost?) {
|
||||
self.hostView = hostView
|
||||
|
||||
self.volumeControlStatusBar = VolumeControlStatusBar(frame: CGRect(origin: CGPoint(x: 0.0, y: -20.0), size: CGSize(width: 100.0, height: 20.0)), shouldBeVisible: statusBarHost?.handleVolumeControl ?? .single(false))
|
||||
self.volumeControlStatusBarNode = VolumeControlStatusBarNode()
|
||||
self.volumeControlStatusBarNode.isHidden = true
|
||||
//self.volumeControlStatusBar = VolumeControlStatusBar(frame: CGRect(origin: CGPoint(x: 0.0, y: -20.0), size: CGSize(width: 100.0, height: 20.0)), shouldBeVisible: statusBarHost?.handleVolumeControl ?? .single(false))
|
||||
//self.volumeControlStatusBarNode = VolumeControlStatusBarNode()
|
||||
//self.volumeControlStatusBarNode.isHidden = true
|
||||
|
||||
let boundsSize = self.hostView.eventView.bounds.size
|
||||
self.deviceMetrics = DeviceMetrics(screenSize: UIScreen.main.bounds.size, statusBarHeight: statusBarHost?.statusBarFrame.height ?? defaultStatusBarHeight, onScreenNavigationHeight: self.hostView.onScreenNavigationHeight)
|
||||
@ -346,12 +342,12 @@ public class Window1 {
|
||||
let statusBarHeight: CGFloat
|
||||
if let statusBarHost = statusBarHost {
|
||||
statusBarHeight = statusBarHost.statusBarFrame.size.height
|
||||
self.statusBarManager = StatusBarManager(host: statusBarHost, volumeControlStatusBar: self.volumeControlStatusBar, volumeControlStatusBarNode: self.volumeControlStatusBarNode)
|
||||
//self.statusBarManager = StatusBarManager(host: statusBarHost, volumeControlStatusBar: self.volumeControlStatusBar, volumeControlStatusBarNode: self.volumeControlStatusBarNode)
|
||||
self.keyboardManager = KeyboardManager(host: statusBarHost)
|
||||
self.keyboardViewManager = KeyboardViewManager(host: statusBarHost)
|
||||
} else {
|
||||
statusBarHeight = self.deviceMetrics.statusBarHeight
|
||||
self.statusBarManager = nil
|
||||
//self.statusBarManager = nil
|
||||
self.keyboardManager = nil
|
||||
self.keyboardViewManager = nil
|
||||
}
|
||||
@ -394,7 +390,7 @@ public class Window1 {
|
||||
}
|
||||
|
||||
self.hostView.layoutSubviews = { [weak self] in
|
||||
self?.layoutSubviews()
|
||||
self?.layoutSubviews(force: false)
|
||||
}
|
||||
|
||||
self.hostView.updateToInterfaceOrientation = { [weak self] orientation in
|
||||
@ -433,7 +429,7 @@ public class Window1 {
|
||||
}*/
|
||||
|
||||
self.presentationContext.view = self.hostView.containerView
|
||||
self.presentationContext.volumeControlStatusBarNodeView = self.volumeControlStatusBarNode.view
|
||||
//self.presentationContext.volumeControlStatusBarNodeView = self.volumeControlStatusBarNode.view
|
||||
self.presentationContext.containerLayoutUpdated(containedLayoutForWindowLayout(self.windowLayout, deviceMetrics: self.deviceMetrics), transition: .immediate)
|
||||
self.overlayPresentationContext.containerLayoutUpdated(containedLayoutForWindowLayout(self.windowLayout, deviceMetrics: self.deviceMetrics), transition: .immediate)
|
||||
|
||||
@ -455,7 +451,7 @@ public class Window1 {
|
||||
keyboardHeight = max(0.0, keyboardHeight - 24.0)
|
||||
}
|
||||
|
||||
print("keyboardHeight: \(keyboardHeight)")
|
||||
//print("rotation keyboardHeight: \(keyboardHeight)")
|
||||
|
||||
var duration: Double = (notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0.0
|
||||
if duration > Double.ulpOfOne {
|
||||
@ -483,12 +479,31 @@ public class Window1 {
|
||||
}
|
||||
}
|
||||
|
||||
var popoverDelta: CGFloat = 0.0
|
||||
|
||||
let screenHeight: CGFloat
|
||||
var inPopover = false
|
||||
if keyboardFrame.width.isEqual(to: UIScreen.main.bounds.width) {
|
||||
var portraitScreenSize = UIScreen.main.bounds.size
|
||||
if portraitScreenSize.width > portraitScreenSize.height {
|
||||
portraitScreenSize = CGSize(width: portraitScreenSize.height, height: portraitScreenSize.width)
|
||||
}
|
||||
var portraitLayoutSize = strongSelf.windowLayout.size
|
||||
if portraitLayoutSize.width > portraitLayoutSize.height {
|
||||
portraitLayoutSize = CGSize(width: portraitLayoutSize.height, height: portraitLayoutSize.width)
|
||||
}
|
||||
if abs(strongSelf.windowLayout.size.height - UIScreen.main.bounds.height) > 41.0 {
|
||||
screenHeight = UIScreen.main.bounds.height
|
||||
inPopover = true
|
||||
if abs(portraitLayoutSize.height - portraitScreenSize.height) > 41.0 || abs(portraitLayoutSize.width - portraitScreenSize.width) > 41.0 {
|
||||
popoverDelta = 48.0
|
||||
inPopover = true
|
||||
}
|
||||
} else if abs(strongSelf.windowLayout.size.height - UIScreen.main.bounds.height) > 39.0 {
|
||||
screenHeight = UIScreen.main.bounds.height
|
||||
if abs(portraitLayoutSize.height - portraitScreenSize.height) > 39.0 || abs(portraitLayoutSize.width - portraitScreenSize.width) > 39.0 {
|
||||
popoverDelta = 40.0
|
||||
inPopover = true
|
||||
}
|
||||
} else {
|
||||
screenHeight = strongSelf.windowLayout.size.height
|
||||
}
|
||||
@ -503,14 +518,14 @@ public class Window1 {
|
||||
keyboardHeight = max(0.0, screenHeight - keyboardFrame.minY)
|
||||
if inPopover {
|
||||
if strongSelf.windowLayout.onScreenNavigationHeight != nil {
|
||||
keyboardHeight = max(0.0, keyboardHeight - 24.0)
|
||||
keyboardHeight = max(0.0, keyboardHeight - popoverDelta / 2.0)
|
||||
} else {
|
||||
keyboardHeight = max(0.0, keyboardHeight - 48.0)
|
||||
keyboardHeight = max(0.0, keyboardHeight - popoverDelta)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print("keyboardHeight: \(keyboardHeight)")
|
||||
print("keyboardHeight: \(keyboardHeight) (raw: \(keyboardFrame))")
|
||||
|
||||
var duration: Double = (notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0.0
|
||||
if duration > Double.ulpOfOne {
|
||||
@ -586,8 +601,8 @@ public class Window1 {
|
||||
self.windowPanRecognizer = recognizer
|
||||
self.hostView.containerView.addGestureRecognizer(recognizer)
|
||||
|
||||
self.hostView.containerView.addSubview(self.volumeControlStatusBar)
|
||||
self.hostView.containerView.addSubview(self.volumeControlStatusBarNode.view)
|
||||
//self.hostView.containerView.addSubview(self.volumeControlStatusBar)
|
||||
//self.hostView.containerView.addSubview(self.volumeControlStatusBarNode.view)
|
||||
}
|
||||
|
||||
public required init(coder aDecoder: NSCoder) {
|
||||
@ -613,7 +628,7 @@ public class Window1 {
|
||||
}
|
||||
|
||||
public func setupVolumeControlStatusBarGraphics(_ graphics: (UIImage, UIImage, UIImage)) {
|
||||
self.volumeControlStatusBarNode.graphics = graphics
|
||||
//self.volumeControlStatusBarNode.graphics = graphics
|
||||
}
|
||||
|
||||
public func setForceInCallStatusBar(_ forceInCallStatusBarText: String?, transition: ContainedViewLayoutTransition = .animated(duration: 0.3, curve: .easeInOut)) {
|
||||
@ -701,6 +716,9 @@ public class Window1 {
|
||||
transition = .immediate
|
||||
}
|
||||
self.updateLayout { $0.update(size: value, metrics: layoutMetricsForScreenSize(value), safeInsets: self.deviceMetrics.safeInsets(inLandscape: value.width > value.height), forceInCallStatusBarText: self.forceInCallStatusBarText, transition: transition, overrideTransition: true) }
|
||||
if let statusBarHost = self.statusBarHost, !statusBarHost.isApplicationInForeground {
|
||||
self.layoutSubviews(force: true)
|
||||
}
|
||||
}
|
||||
|
||||
private var _rootController: ContainableController?
|
||||
@ -718,6 +736,9 @@ public class Window1 {
|
||||
if let rootController = rootController as? NavigationController {
|
||||
rootController.statusBarHost = self.statusBarHost
|
||||
rootController.keyboardViewManager = self.keyboardViewManager
|
||||
rootController.inCallNavigate = { [weak self] in
|
||||
self?.inCallNavigate?()
|
||||
}
|
||||
}
|
||||
if !self.windowLayout.size.width.isZero && !self.windowLayout.size.height.isZero {
|
||||
rootController.displayNode.frame = CGRect(origin: CGPoint(), size: self.windowLayout.size)
|
||||
@ -738,6 +759,9 @@ public class Window1 {
|
||||
}
|
||||
set(value) {
|
||||
for controller in self._topLevelOverlayControllers {
|
||||
if let controller = controller as? ViewController {
|
||||
controller.statusBar.alphaUpdated = nil
|
||||
}
|
||||
controller.view.removeFromSuperview()
|
||||
}
|
||||
self._topLevelOverlayControllers = value
|
||||
@ -750,7 +774,25 @@ public class Window1 {
|
||||
if let coveringView = self.coveringView {
|
||||
self.hostView.containerView.insertSubview(controller.view, belowSubview: coveringView)
|
||||
} else {
|
||||
self.hostView.containerView.insertSubview(controller.view, belowSubview: self.volumeControlStatusBarNode.view)
|
||||
self.hostView.containerView.addSubview(controller.view)
|
||||
}
|
||||
|
||||
if let controller = controller as? ViewController {
|
||||
controller.statusBar.alphaUpdated = { [weak self] transition in
|
||||
guard let strongSelf = self, let navigationController = strongSelf._rootController as? NavigationController else {
|
||||
return
|
||||
}
|
||||
var isStatusBarHidden: Bool = false
|
||||
for controller in strongSelf._topLevelOverlayControllers {
|
||||
if let controller = controller as? ViewController {
|
||||
if case .Hide = controller.statusBar.statusBarStyle {
|
||||
isStatusBarHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
navigationController.updateExternalStatusBarHidden(isStatusBarHidden, transition: .animated(duration: 0.3, curve: .easeInOut))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -771,7 +813,7 @@ public class Window1 {
|
||||
coveringView.layer.removeAnimation(forKey: "opacity")
|
||||
coveringView.layer.allowsGroupOpacity = false
|
||||
coveringView.alpha = 1.0
|
||||
self.hostView.containerView.insertSubview(coveringView, belowSubview: self.volumeControlStatusBarNode.view)
|
||||
self.hostView.containerView.addSubview(coveringView)
|
||||
if !self.windowLayout.size.width.isZero {
|
||||
coveringView.frame = CGRect(origin: CGPoint(), size: self.windowLayout.size)
|
||||
coveringView.updateLayout(self.windowLayout.size)
|
||||
@ -781,7 +823,7 @@ public class Window1 {
|
||||
}
|
||||
}
|
||||
|
||||
private func layoutSubviews() {
|
||||
private func layoutSubviews(force: Bool) {
|
||||
var hasPreview = false
|
||||
var updatedHasPreview = false
|
||||
for subview in self.hostView.eventView.subviews {
|
||||
@ -796,7 +838,7 @@ public class Window1 {
|
||||
updatedHasPreview = true
|
||||
}
|
||||
|
||||
if self.tracingStatusBarsInvalidated || updatedHasPreview, let statusBarManager = statusBarManager, let keyboardManager = keyboardManager {
|
||||
if self.tracingStatusBarsInvalidated || updatedHasPreview, let keyboardManager = keyboardManager {
|
||||
self.tracingStatusBarsInvalidated = false
|
||||
|
||||
/*if self.statusBarHidden {
|
||||
@ -902,7 +944,9 @@ public class Window1 {
|
||||
}
|
||||
}
|
||||
|
||||
if !UIWindow.isDeviceRotating() {
|
||||
if force {
|
||||
self.commitUpdatingLayout()
|
||||
} else if !UIWindow.isDeviceRotating() {
|
||||
if !self.hostView.isUpdatingOrientationLayout {
|
||||
self.commitUpdatingLayout()
|
||||
} else {
|
||||
@ -967,6 +1011,9 @@ public class Window1 {
|
||||
let boundsSize = updatingLayout.layout.size
|
||||
let isLandscape = boundsSize.width > boundsSize.height
|
||||
var statusBarHeight: CGFloat? = self.deviceMetrics.statusBarHeight(for: boundsSize)
|
||||
if let statusBarHeightValue = statusBarHeight, let statusBarHost = self.statusBarHost {
|
||||
statusBarHeight = max(statusBarHeightValue, statusBarHost.statusBarFrame.size.height)
|
||||
}
|
||||
|
||||
if self.deviceMetrics.type == .tablet, let onScreenNavigationHeight = self.hostView.onScreenNavigationHeight, onScreenNavigationHeight != self.deviceMetrics.onScreenNavigationHeight(inLandscape: false) {
|
||||
self.deviceMetrics = DeviceMetrics(screenSize: UIScreen.main.bounds.size, statusBarHeight: statusBarHeight ?? defaultStatusBarHeight, onScreenNavigationHeight: onScreenNavigationHeight)
|
||||
@ -1023,8 +1070,8 @@ public class Window1 {
|
||||
})
|
||||
}
|
||||
|
||||
self.volumeControlStatusBarNode.frame = CGRect(origin: CGPoint(), size: self.windowLayout.size)
|
||||
self.volumeControlStatusBarNode.updateLayout(layout: childLayout, transition: updatingLayout.transition)
|
||||
//self.volumeControlStatusBarNode.frame = CGRect(origin: CGPoint(), size: self.windowLayout.size)
|
||||
//self.volumeControlStatusBarNode.updateLayout(layout: childLayout, transition: updatingLayout.transition)
|
||||
|
||||
if let coveringView = self.coveringView {
|
||||
coveringView.frame = CGRect(origin: CGPoint(), size: self.windowLayout.size)
|
||||
@ -1035,7 +1082,12 @@ public class Window1 {
|
||||
}
|
||||
|
||||
public func present(_ controller: ContainableController, on level: PresentationSurfaceLevel, blockInteraction: Bool = false, completion: @escaping () -> Void = {}) {
|
||||
self.presentationContext.present(controller, on: level, blockInteraction: blockInteraction, completion: completion)
|
||||
if let navigationController = self._rootController as? NavigationController, let controller = controller as? ViewController {
|
||||
navigationController.presentOverlay(controller: controller, inGlobal: false)
|
||||
} else {
|
||||
assertionFailure()
|
||||
}
|
||||
//self.presentationContext.present(controller, on: level, blockInteraction: blockInteraction, completion: completion)
|
||||
}
|
||||
|
||||
public func presentInGlobalOverlay(_ controller: ContainableController) {
|
||||
|
||||
@ -275,14 +275,14 @@ open class GalleryControllerNode: ASDisplayNode, UIScrollViewDelegate, UIGesture
|
||||
UIView.animate(withDuration: 0.3, animations: {
|
||||
let alpha: CGFloat = self.areControlsHidden ? 0.0 : 1.0
|
||||
self.navigationBar?.alpha = alpha
|
||||
self.statusBar?.alpha = alpha
|
||||
self.statusBar?.updateAlpha(alpha, transition: .animated(duration: 0.3, curve: .easeInOut))
|
||||
self.footerNode.alpha = alpha
|
||||
self.updateThumbnailContainerNodeAlpha(.immediate)
|
||||
})
|
||||
} else {
|
||||
let alpha: CGFloat = self.areControlsHidden ? 0.0 : 1.0
|
||||
self.navigationBar?.alpha = alpha
|
||||
self.statusBar?.alpha = alpha
|
||||
self.statusBar?.updateAlpha(alpha, transition: .immediate)
|
||||
self.footerNode.alpha = alpha
|
||||
self.updateThumbnailContainerNodeAlpha(.immediate)
|
||||
}
|
||||
@ -374,7 +374,11 @@ open class GalleryControllerNode: ASDisplayNode, UIScrollViewDelegate, UIGesture
|
||||
self.updateThumbnailContainerNodeAlpha(.immediate)
|
||||
|
||||
if !self.areControlsHidden {
|
||||
self.statusBar?.alpha = transition
|
||||
if transition < 0.5 {
|
||||
self.statusBar?.updateAlpha(0.0, transition: .animated(duration: 0.3, curve: .easeInOut))
|
||||
} else {
|
||||
self.statusBar?.updateAlpha(1.0, transition: .animated(duration: 0.3, curve: .easeInOut))
|
||||
}
|
||||
self.navigationBar?.alpha = transition
|
||||
self.footerNode.alpha = transition
|
||||
|
||||
|
||||
@ -364,10 +364,10 @@ open class ItemListControllerNode<Entry: ItemListNodeEntry>: ASDisplayNode, UISc
|
||||
addedInsets = UIEdgeInsets(top: 0.0, left: inset, bottom: 0.0, right: inset)
|
||||
|
||||
if self.leftOverlayNode.supernode == nil {
|
||||
self.addSubnode(self.leftOverlayNode)
|
||||
self.insertSubnode(self.leftOverlayNode, aboveSubnode: self.listNode)
|
||||
}
|
||||
if self.rightOverlayNode.supernode == nil {
|
||||
self.addSubnode(self.rightOverlayNode)
|
||||
self.insertSubnode(self.rightOverlayNode, aboveSubnode: self.listNode)
|
||||
}
|
||||
} else {
|
||||
insets.left += layout.safeInsets.left
|
||||
|
||||
@ -93,13 +93,15 @@
|
||||
|
||||
- (BOOL)prefersStatusBarHidden
|
||||
{
|
||||
if (!TGIsPad() && iosMajorVersion() >= 11 && UIInterfaceOrientationIsLandscape([[LegacyComponentsGlobals provider] applicationStatusBarOrientation]))
|
||||
return true;
|
||||
|
||||
/*if (!TGIsPad() && iosMajorVersion() >= 11 && UIInterfaceOrientationIsLandscape([[LegacyComponentsGlobals provider] applicationStatusBarOrientation]))
|
||||
return true;
|
||||
|
||||
if (self.childViewControllers.count > 0)
|
||||
return [self.childViewControllers.lastObject prefersStatusBarHidden];
|
||||
|
||||
return [super prefersStatusBarHidden];
|
||||
return [super prefersStatusBarHidden];*/
|
||||
}
|
||||
|
||||
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures
|
||||
@ -262,7 +264,7 @@
|
||||
{
|
||||
[UIView animateWithDuration:0.2 animations:^
|
||||
{
|
||||
[strongSelf->_context setApplicationStatusBarAlpha:1.0f];
|
||||
//[strongSelf->_context setApplicationStatusBarAlpha:1.0f];
|
||||
}];
|
||||
}
|
||||
|
||||
@ -1155,7 +1157,7 @@ static CGFloat transformRotation(CGAffineTransform transform)
|
||||
{
|
||||
[UIView animateWithDuration:0.2 animations:^
|
||||
{
|
||||
[_context setApplicationStatusBarAlpha:1.0f];
|
||||
//[_context setApplicationStatusBarAlpha:1.0f];
|
||||
}];
|
||||
}
|
||||
}
|
||||
@ -1228,7 +1230,7 @@ static CGFloat transformRotation(CGAffineTransform transform)
|
||||
|
||||
if (self.adjustsStatusBarVisibility)
|
||||
{
|
||||
[_context setApplicationStatusBarAlpha:1.0f];
|
||||
//[_context setApplicationStatusBarAlpha:1.0f];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -247,7 +247,7 @@ public final class LegacyControllerContext: NSObject, LegacyComponentsContext {
|
||||
|
||||
public func setApplicationStatusBarAlpha(_ alpha: CGFloat) {
|
||||
if let controller = self.controller {
|
||||
controller.statusBar.alpha = alpha
|
||||
controller.statusBar.updateAlpha(alpha, transition: .immediate)
|
||||
self.updateDeferScreenEdgeGestures()
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,6 +21,8 @@ public extension Peer {
|
||||
}
|
||||
} else if let lastName = user.lastName {
|
||||
return lastName
|
||||
} else if let phone = user.phone {
|
||||
return "+\(phone)"
|
||||
} else {
|
||||
return strings.User_DeletedAccount
|
||||
}
|
||||
|
||||
@ -29,6 +29,8 @@
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
@ -40,6 +42,17 @@
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "E66DC04E89A74F8D00000000"
|
||||
BuildableName = "libSwiftSignalKit.dylib"
|
||||
BlueprintName = "SwiftSignalKit#shared"
|
||||
ReferencedContainer = "container:SwiftSignalKit.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
||||
@ -1102,9 +1102,13 @@ public func settingsController(context: AccountContext, accountManager: AccountM
|
||||
|> mapToSignal { context in
|
||||
return context.account.postbox.preferencesView(keys: [PreferencesKeys.appConfiguration])
|
||||
|> map { view -> Bool in
|
||||
let appConfiguration = view.values[PreferencesKeys.appConfiguration] as? AppConfiguration ?? .defaultValue
|
||||
let configuration = WalletConfiguration.with(appConfiguration: appConfiguration)
|
||||
return configuration.config != nil
|
||||
if #available(iOSApplicationExtension 10.3, iOS 10.3, *) {
|
||||
let appConfiguration = view.values[PreferencesKeys.appConfiguration] as? AppConfiguration ?? .defaultValue
|
||||
let configuration = WalletConfiguration.with(appConfiguration: appConfiguration)
|
||||
return configuration.config != nil
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1375,7 +1379,7 @@ public func settingsController(context: AccountContext, accountManager: AccountM
|
||||
(controller?.navigationController as? NavigationController)?.replaceAllButRootController(value, animated: true, animationOptions: [.removeOnMasterDetails])
|
||||
}
|
||||
presentControllerImpl = { [weak controller] value, arguments in
|
||||
controller?.present(value, in: .window(.root), with: arguments ?? ViewControllerPresentationArguments(presentationAnimation: .modalSheet), blockInteraction: true)
|
||||
controller?.present(value, in: .window(.root), with: arguments, blockInteraction: true)
|
||||
}
|
||||
presentInGlobalOverlayImpl = { [weak controller] value, arguments in
|
||||
controller?.presentInGlobalOverlay(value, with: arguments)
|
||||
|
||||
@ -54,7 +54,7 @@ public extension TermsOfServiceControllerTheme {
|
||||
}
|
||||
}
|
||||
|
||||
public class TermsOfServiceController: ViewController {
|
||||
public class TermsOfServiceController: ViewController, StandalonePresentableController {
|
||||
private var controllerNode: TermsOfServiceControllerNode {
|
||||
return self.displayNode as! TermsOfServiceControllerNode
|
||||
}
|
||||
|
||||
@ -271,6 +271,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
self.scrollNode.view.disablesInteractiveTransitionGestureRecognizer = true
|
||||
self.scrollNode.view.showsHorizontalScrollIndicator = false
|
||||
self.scrollNode.view.isPagingEnabled = true
|
||||
self.scrollNode.view.delegate = self
|
||||
|
||||
@ -129,7 +129,7 @@ public extension Peer {
|
||||
var isDeleted: Bool {
|
||||
switch self {
|
||||
case let user as TelegramUser:
|
||||
return user.firstName == nil && user.lastName == nil
|
||||
return user.firstName == nil && user.lastName == nil && user.phone == nil
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ public enum TonKeychainEncryptDataError {
|
||||
public enum TonKeychainDecryptDataError {
|
||||
case generic
|
||||
case publicKeyMismatch
|
||||
case cancelled
|
||||
}
|
||||
|
||||
public struct TonKeychain {
|
||||
@ -332,8 +333,8 @@ public final class TonInstance {
|
||||
|
||||
fileprivate func walletRestoreWords(walletInfo: WalletInfo, keychain: TonKeychain, serverSalt: Data) -> Signal<[String], WalletRestoreWordsError> {
|
||||
return keychain.decrypt(walletInfo.encryptedSecret)
|
||||
|> mapError { _ -> WalletRestoreWordsError in
|
||||
return .secretDecryptionFailed
|
||||
|> mapError { error -> WalletRestoreWordsError in
|
||||
return .secretDecryptionFailed(error)
|
||||
}
|
||||
|> mapToSignal { decryptedSecret -> Signal<[String], WalletRestoreWordsError> in
|
||||
return Signal { subscriber in
|
||||
@ -365,8 +366,8 @@ public final class TonInstance {
|
||||
|
||||
fileprivate func deleteLocalWalletData(walletInfo: WalletInfo, keychain: TonKeychain, serverSalt: Data) -> Signal<Never, DeleteLocalWalletDataError> {
|
||||
return keychain.decrypt(walletInfo.encryptedSecret)
|
||||
|> mapError { _ -> DeleteLocalWalletDataError in
|
||||
return .secretDecryptionFailed
|
||||
|> mapError { error -> DeleteLocalWalletDataError in
|
||||
return .secretDecryptionFailed(error)
|
||||
}
|
||||
|> mapToSignal { decryptedSecret -> Signal<Never, DeleteLocalWalletDataError> in
|
||||
return Signal { subscriber in
|
||||
@ -581,7 +582,7 @@ public func importWallet(postbox: Postbox, network: Network, tonInstance: TonIns
|
||||
|
||||
public enum DeleteLocalWalletDataError {
|
||||
case generic
|
||||
case secretDecryptionFailed
|
||||
case secretDecryptionFailed(TonKeychainDecryptDataError)
|
||||
}
|
||||
|
||||
public func deleteLocalWalletData(postbox: Postbox, network: Network, tonInstance: TonInstance, keychain: TonKeychain, walletInfo: WalletInfo) -> Signal<Never, DeleteLocalWalletDataError> {
|
||||
@ -612,7 +613,7 @@ public func deleteLocalWalletData(postbox: Postbox, network: Network, tonInstanc
|
||||
|
||||
public enum WalletRestoreWordsError {
|
||||
case generic
|
||||
case secretDecryptionFailed
|
||||
case secretDecryptionFailed(TonKeychainDecryptDataError)
|
||||
}
|
||||
|
||||
public func walletRestoreWords(network: Network, walletInfo: WalletInfo, tonInstance: TonInstance, keychain: TonKeychain) -> Signal<[String], WalletRestoreWordsError> {
|
||||
|
||||
@ -56,6 +56,15 @@ private let keyboardWindowClass: AnyClass? = {
|
||||
private class ApplicationStatusBarHost: StatusBarHost {
|
||||
private let application = UIApplication.shared
|
||||
|
||||
var isApplicationInForeground: Bool {
|
||||
switch self.application.applicationState {
|
||||
case .background:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
var statusBarFrame: CGRect {
|
||||
return self.application.statusBarFrame
|
||||
}
|
||||
@ -71,6 +80,10 @@ private class ApplicationStatusBarHost: StatusBarHost {
|
||||
self.application.setStatusBarStyle(style, animated: animated)
|
||||
}
|
||||
|
||||
func setStatusBarHidden(_ value: Bool, animated: Bool) {
|
||||
self.application.setStatusBarHidden(value, with: animated ? .fade : .none)
|
||||
}
|
||||
|
||||
var statusBarWindow: UIView? {
|
||||
return self.application.value(forKey: "statusBarWindow") as? UIView
|
||||
}
|
||||
@ -664,6 +677,7 @@ final class SharedApplicationContext {
|
||||
#if targetEnvironment(simulator)
|
||||
tonKeychain = TonKeychain(encryptionPublicKey: {
|
||||
//return .single(nil)
|
||||
//return .single("1".data(using: .utf8)!)
|
||||
return .single(Data())
|
||||
}, encrypt: { data in
|
||||
return Signal { subscriber in
|
||||
@ -701,11 +715,17 @@ final class SharedApplicationContext {
|
||||
}
|
||||
}, decrypt: { encryptedData in
|
||||
return Signal { subscriber in
|
||||
BuildConfig.decryptApplicationSecret(encryptedData.data, publicKey: encryptedData.publicKey, baseAppBundleId: baseAppBundleId, completion: { result in
|
||||
BuildConfig.decryptApplicationSecret(encryptedData.data, publicKey: encryptedData.publicKey, baseAppBundleId: baseAppBundleId, completion: { result, cancelled in
|
||||
if let result = result {
|
||||
subscriber.putNext(result)
|
||||
} else {
|
||||
subscriber.putError(.generic)
|
||||
let error: TonKeychainDecryptDataError
|
||||
if cancelled {
|
||||
error = .cancelled
|
||||
} else {
|
||||
error = .generic
|
||||
}
|
||||
subscriber.putError(error)
|
||||
}
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
@ -1259,9 +1279,12 @@ final class SharedApplicationContext {
|
||||
#endif
|
||||
}
|
||||
|
||||
if UIApplication.shared.isStatusBarHidden {
|
||||
UIApplication.shared.setStatusBarHidden(false, with: .none)
|
||||
}
|
||||
NotificationCenter.default.addObserver(forName: UIWindow.didBecomeHiddenNotification, object: nil, queue: nil, using: { notification in
|
||||
if UIApplication.shared.isStatusBarHidden {
|
||||
UIApplication.shared.setStatusBarHidden(false, with: .none)
|
||||
//UIApplication.shared.setStatusBarHidden(false, with: .none)
|
||||
}
|
||||
})
|
||||
return true
|
||||
|
||||
@ -456,6 +456,7 @@ final class AuthorizedApplicationContext {
|
||||
}, expandAction: { expandData in
|
||||
if let strongSelf = self {
|
||||
let chatController = ChatControllerImpl(context: strongSelf.context, chatLocation: .peer(firstMessage.id.peerId), mode: .overlay)
|
||||
//chatController.navigation_setNavigationController(strongSelf.rootController)
|
||||
(strongSelf.rootController.viewControllers.last as? ViewController)?.present(chatController, in: .window(.root), with: ChatControllerOverlayPresentationData(expandData: expandData()))
|
||||
}
|
||||
}))
|
||||
|
||||
@ -2312,7 +2312,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
private func themeAndStringsUpdated() {
|
||||
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
|
||||
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
|
||||
switch self.presentationInterfaceState.mode {
|
||||
case .standard:
|
||||
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
|
||||
self.deferScreenEdgeGestures = []
|
||||
case .overlay:
|
||||
self.statusBar.statusBarStyle = .Hide
|
||||
self.deferScreenEdgeGestures = [.top]
|
||||
case .inline:
|
||||
self.statusBar.statusBarStyle = .Ignore
|
||||
}
|
||||
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
|
||||
self.chatTitleView?.updateThemeAndStrings(theme: self.presentationData.theme, strings: self.presentationData.strings)
|
||||
self.updateChatPresentationInterfaceState(animated: false, interactive: false, { state in
|
||||
@ -2589,22 +2598,19 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
self.chatDisplayNode.historyNode.contentPositionChanged = { [weak self] offset in
|
||||
if let strongSelf = self {
|
||||
let offsetAlpha: CGFloat
|
||||
if case let .standard(previewing) = strongSelf.presentationInterfaceState.mode, previewing {
|
||||
offsetAlpha = 0.0
|
||||
} else {
|
||||
switch offset {
|
||||
case let .known(offset):
|
||||
if offset < 40.0 {
|
||||
offsetAlpha = 0.0
|
||||
} else {
|
||||
offsetAlpha = 1.0
|
||||
}
|
||||
case .unknown:
|
||||
offsetAlpha = 1.0
|
||||
case .none:
|
||||
switch offset {
|
||||
case let .known(offset):
|
||||
if offset < 40.0 {
|
||||
offsetAlpha = 0.0
|
||||
}
|
||||
} else {
|
||||
offsetAlpha = 1.0
|
||||
}
|
||||
case .unknown:
|
||||
offsetAlpha = 1.0
|
||||
case .none:
|
||||
offsetAlpha = 0.0
|
||||
}
|
||||
|
||||
strongSelf.chatDisplayNode.navigateButtons.displayDownButton = !offsetAlpha.isZero
|
||||
}
|
||||
}
|
||||
|
||||
@ -1903,6 +1903,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
|
||||
switch self.chatPresentationInterfaceState.mode {
|
||||
case .standard(previewing: true):
|
||||
if let result = self.navigateButtons.hitTest(self.view.convert(point, to: self.navigateButtons.view), with: event) {
|
||||
return result
|
||||
}
|
||||
if self.bounds.contains(point) {
|
||||
return self.historyNode.view
|
||||
}
|
||||
|
||||
@ -15,6 +15,8 @@ public final class NotificationContainerController: ViewController {
|
||||
private var presentationData: PresentationData
|
||||
private var presentationDataDisposable: Disposable?
|
||||
|
||||
private var validLayout: ContainerViewLayout?
|
||||
|
||||
public init(context: AccountContext) {
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
@ -61,7 +63,15 @@ public final class NotificationContainerController: ViewController {
|
||||
|
||||
self.controllerNode.displayingItemsUpdated = { [weak self] value in
|
||||
if let strongSelf = self {
|
||||
strongSelf.statusBar.statusBarStyle = value ? .Hide : .Ignore
|
||||
var statusBarHidden = false
|
||||
if value, let layout = strongSelf.validLayout {
|
||||
if let statusBarHeight = layout.statusBarHeight, statusBarHeight > 20.0 {
|
||||
statusBarHidden = false
|
||||
} else {
|
||||
statusBarHidden = true
|
||||
}
|
||||
}
|
||||
strongSelf.statusBar.statusBarStyle = statusBarHidden ? .Hide : .Ignore
|
||||
if value {
|
||||
strongSelf.deferScreenEdgeGestures = [.top]
|
||||
} else {
|
||||
@ -72,6 +82,8 @@ public final class NotificationContainerController: ViewController {
|
||||
}
|
||||
|
||||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
self.validLayout = layout
|
||||
|
||||
super.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
self.controllerNode.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
@ -68,29 +68,19 @@ final class NotificationContainerControllerNode: ASDisplayNode {
|
||||
if let (item, topItemNode) = self.topItemAndNode {
|
||||
if item.groupingKey == key {
|
||||
self.topItemAndNode = nil
|
||||
self.displayingItemsUpdated?(false)
|
||||
topItemNode.animateOut(completion: { [weak self, weak topItemNode] in
|
||||
topItemNode?.removeFromSupernode()
|
||||
|
||||
if let strongSelf = self, strongSelf.topItemAndNode == nil {
|
||||
strongSelf.displayingItemsUpdated?(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func enqueue(_ item: NotificationItem) {
|
||||
var updatedDisplayingItems = false
|
||||
if let (_, topItemNode) = self.topItemAndNode {
|
||||
topItemNode.animateOut(completion: { [weak self, weak topItemNode] in
|
||||
topItemNode?.removeFromSupernode()
|
||||
|
||||
if let strongSelf = self, strongSelf.topItemAndNode == nil {
|
||||
strongSelf.displayingItemsUpdated?(false)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
updatedDisplayingItems = true
|
||||
}
|
||||
|
||||
var useCompactLayout = false
|
||||
@ -138,9 +128,7 @@ final class NotificationContainerControllerNode: ASDisplayNode {
|
||||
containerNode.animateIn()
|
||||
}
|
||||
|
||||
if updatedDisplayingItems {
|
||||
self.displayingItemsUpdated?(true)
|
||||
}
|
||||
self.displayingItemsUpdated?(true)
|
||||
|
||||
self.resetTimeoutTimer()
|
||||
}
|
||||
@ -172,12 +160,9 @@ final class NotificationContainerControllerNode: ASDisplayNode {
|
||||
if let strongSelf = self {
|
||||
if let (_, topItemNode) = strongSelf.topItemAndNode {
|
||||
strongSelf.topItemAndNode = nil
|
||||
strongSelf.displayingItemsUpdated?(false)
|
||||
topItemNode.animateOut(completion: { [weak topItemNode] in
|
||||
topItemNode?.removeFromSupernode()
|
||||
|
||||
if let strongSelf = self, strongSelf.topItemAndNode == nil {
|
||||
strongSelf.displayingItemsUpdated?(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -842,10 +842,13 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
} else {
|
||||
text = presentationData.strings.Call_StatusBar("").0
|
||||
}
|
||||
|
||||
self.mainWindow?.setForceInCallStatusBar(text)
|
||||
if let navigationController = self.mainWindow?.viewController as? NavigationController {
|
||||
navigationController.setForceInCallStatusBar(text)
|
||||
}
|
||||
} else {
|
||||
self.mainWindow?.setForceInCallStatusBar(nil)
|
||||
if let navigationController = self.mainWindow?.viewController as? NavigationController {
|
||||
navigationController.setForceInCallStatusBar(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -94,16 +94,20 @@ public final class WalletSplashScreen: ViewController {
|
||||
return
|
||||
}
|
||||
strongSelf.sendGrams(walletInfo: walletInfo, decryptedSecret: decryptedSecret, address: address, amount: amount, textMessage: textMessage, forceIfDestinationNotInitialized: false, randomId: randomId, serverSalt: serverSalt)
|
||||
}, error: { [weak self] _ in
|
||||
}, error: { [weak self] error in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let text = strongSelf.presentationData.strings.Wallet_Send_ErrorDecryptionFailed
|
||||
let controller = textAlertController(context: strongSelf.context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
|
||||
self?.dismiss()
|
||||
})])
|
||||
strongSelf.present(controller, in: .window(.root))
|
||||
strongSelf.dismiss()
|
||||
if case .cancelled = error {
|
||||
strongSelf.dismiss()
|
||||
} else {
|
||||
let text = strongSelf.presentationData.strings.Wallet_Send_ErrorDecryptionFailed
|
||||
let controller = textAlertController(context: strongSelf.context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
|
||||
self?.dismiss()
|
||||
})])
|
||||
strongSelf.present(controller, in: .window(.root))
|
||||
strongSelf.dismiss()
|
||||
}
|
||||
})
|
||||
case .sent:
|
||||
self.navigationItem.setLeftBarButton(UIBarButtonItem(customDisplayNode: ASDisplayNode())!, animated: false)
|
||||
@ -235,15 +239,18 @@ public final class WalletSplashScreen: ViewController {
|
||||
strongSelf.mode = .created(walletInfo, wordList)
|
||||
controller.dismiss()
|
||||
strongSelf.push(WalletWordDisplayScreen(context: strongSelf.context, tonContext: strongSelf.tonContext, walletInfo: walletInfo, wordList: wordList, mode: .check, walletCreatedPreloadState: strongSelf.walletCreatedPreloadState))
|
||||
}, error: { _ in
|
||||
}, error: { error in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
controller.dismiss()
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: strongSelf.presentationData.strings.Wallet_Created_ExportErrorTitle, text: strongSelf.presentationData.strings.Wallet_Created_ExportErrorText, actions: [
|
||||
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
|
||||
})
|
||||
], actionLayout: .vertical), in: .window(.root))
|
||||
if case let .secretDecryptionFailed(.cancelled) = error {
|
||||
} else {
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: strongSelf.presentationData.strings.Wallet_Created_ExportErrorTitle, text: strongSelf.presentationData.strings.Wallet_Created_ExportErrorText, actions: [
|
||||
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
|
||||
})
|
||||
], actionLayout: .vertical), in: .window(.root))
|
||||
}
|
||||
})
|
||||
}
|
||||
case let .success(walletInfo):
|
||||
@ -720,16 +727,7 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
|
||||
let secondaryActionSize = self.secondaryActionTitleNode.updateLayout(CGSize(width: layout.size.width - sideInset * 2.0, height: layout.size.height))
|
||||
|
||||
let contentHeight = iconSize.height + iconSpacing + titleSize.height + titleSpacing + textSize.height
|
||||
let contentVerticalOrigin = floor((layout.size.height - contentHeight - iconSize.height / 2.0) / 2.0)
|
||||
|
||||
let iconFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0), y: contentVerticalOrigin), size: iconSize).offsetBy(dx: iconOffset.x, dy: iconOffset.y)
|
||||
transition.updateFrameAdditive(node: self.iconNode, frame: iconFrame)
|
||||
self.animationNode.updateLayout(size: iconFrame.size)
|
||||
transition.updateFrameAdditive(node: self.animationNode, frame: iconFrame)
|
||||
let titleFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - titleSize.width) / 2.0), y: iconFrame.maxY + iconSpacing), size: titleSize)
|
||||
transition.updateFrameAdditive(node: self.titleNode, frame: titleFrame)
|
||||
let textFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - textSize.width) / 2.0), y: titleFrame.maxY + titleSpacing), size: textSize)
|
||||
transition.updateFrameAdditive(node: self.textNode, frame: textFrame)
|
||||
var contentVerticalOrigin = floor((layout.size.height - contentHeight - iconSize.height / 2.0) / 2.0)
|
||||
|
||||
let minimalBottomInset: CGFloat = 60.0
|
||||
let bottomInset = layout.intrinsicInsets.bottom + max(minimalBottomInset, termsSize.height + termsSpacing * 2.0)
|
||||
@ -740,12 +738,27 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
|
||||
transition.updateFrame(node: self.buttonNode, frame: buttonFrame)
|
||||
self.buttonNode.updateLayout(width: buttonFrame.width, transition: transition)
|
||||
|
||||
var maxContentVerticalOrigin = buttonFrame.minY - 12.0 - contentHeight
|
||||
|
||||
if !secondaryActionSize.width.isZero {
|
||||
let secondaryActionFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - secondaryActionSize.width) / 2.0), y: buttonFrame.minY - 20.0 - secondaryActionSize.height), size: secondaryActionSize)
|
||||
transition.updateFrameAdditive(node: self.secondaryActionTitleNode, frame: secondaryActionFrame)
|
||||
transition.updateFrame(node: self.secondaryActionButtonNode, frame: secondaryActionFrame.insetBy(dx: -10.0, dy: -10.0))
|
||||
|
||||
maxContentVerticalOrigin = secondaryActionFrame.minY - 12.0 - contentHeight
|
||||
}
|
||||
|
||||
contentVerticalOrigin = min(contentVerticalOrigin, maxContentVerticalOrigin)
|
||||
|
||||
let iconFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0), y: contentVerticalOrigin), size: iconSize).offsetBy(dx: iconOffset.x, dy: iconOffset.y)
|
||||
transition.updateFrameAdditive(node: self.iconNode, frame: iconFrame)
|
||||
self.animationNode.updateLayout(size: iconFrame.size)
|
||||
transition.updateFrameAdditive(node: self.animationNode, frame: iconFrame)
|
||||
let titleFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - titleSize.width) / 2.0), y: iconFrame.maxY + iconSpacing), size: titleSize)
|
||||
transition.updateFrameAdditive(node: self.titleNode, frame: titleFrame)
|
||||
let textFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - textSize.width) / 2.0), y: titleFrame.maxY + titleSpacing), size: textSize)
|
||||
transition.updateFrameAdditive(node: self.textNode, frame: textFrame)
|
||||
|
||||
let termsFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - termsSize.width) / 2.0), y: buttonFrame.maxY + floor((layout.size.height - layout.intrinsicInsets.bottom - buttonFrame.maxY - termsSize.height) / 2.0)), size: termsSize)
|
||||
transition.updateFrameAdditive(node: self.termsNode, frame: termsFrame)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user