mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Voice Chat UI improvements
This commit is contained in:
parent
9eddf57416
commit
e94885aa08
70 changed files with 4378 additions and 3941 deletions
|
|
@ -6001,6 +6001,13 @@ Sorry for the inconvenience.";
|
|||
|
||||
"Conversation.Dice.u1F3B3" = "Send a bowling emoji to try your luck.";
|
||||
|
||||
"VoiceOver.Common.TapToChange" = "Tap To Change";
|
||||
"VoiceOver.Common.SwitchHint" = "Double Tap To Toggle";
|
||||
"VoiceOver.Common.On" = "On";
|
||||
"VoiceOver.Common.Off" = "Off";
|
||||
|
||||
"VoiceOver.Chat.MessagesSelected_0" = "%@ messages selected";
|
||||
"VoiceOver.Chat.MessagesSelected_1" = "%@ message selected";
|
||||
"VoiceOver.Chat.MessagesSelected_2" = "%@ messages selected";
|
||||
"VoiceOver.Chat.MessagesSelected_3_10" = "%@ messages selected";
|
||||
"VoiceOver.Chat.MessagesSelected_many" = "%@ messages selected";
|
||||
"VoiceOver.Chat.MessagesSelected_any" = "%@ messages selected";
|
||||
|
|
|
|||
|
|
@ -565,7 +565,7 @@ public protocol SharedAccountContext: class {
|
|||
|
||||
func makeRecentSessionsController(context: AccountContext, activeSessionsContext: ActiveSessionsContext) -> ViewController & RecentSessionsController
|
||||
|
||||
func navigateToCurrentCall(sourcePanel: ASDisplayNode?)
|
||||
func navigateToCurrentCall()
|
||||
var hasOngoingCall: ValuePromise<Bool> { get }
|
||||
var immediateHasOngoingCall: Bool { get }
|
||||
|
||||
|
|
@ -674,6 +674,6 @@ public protocol AccountContext: class {
|
|||
func chatLocationOutgoingReadState(for location: ChatLocation, contextHolder: Atomic<ChatLocationContextHolder?>) -> Signal<MessageId?, NoError>
|
||||
func applyMaxReadIndex(for location: ChatLocation, contextHolder: Atomic<ChatLocationContextHolder?>, messageIndex: MessageIndex)
|
||||
|
||||
func joinGroupCall(peerId: PeerId, activeCall: CachedChannelData.ActiveCall, sourcePanel: ASDisplayNode?)
|
||||
func joinGroupCall(peerId: PeerId, activeCall: CachedChannelData.ActiveCall)
|
||||
func requestCall(peerId: PeerId, isVideo: Bool, completion: @escaping () -> Void)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -288,8 +288,6 @@ public protocol PresentationGroupCall: class {
|
|||
func invitePeer(_ peerId: PeerId)
|
||||
func removedPeer(_ peerId: PeerId)
|
||||
var invitedPeers: Signal<[PeerId], NoError> { get }
|
||||
|
||||
var sourcePanel: ASDisplayNode? { get set }
|
||||
}
|
||||
|
||||
public protocol PresentationCallManager: class {
|
||||
|
|
@ -297,5 +295,5 @@ public protocol PresentationCallManager: class {
|
|||
var currentGroupCallSignal: Signal<PresentationGroupCall?, NoError> { get }
|
||||
|
||||
func requestCall(context: AccountContext, peerId: PeerId, isVideo: Bool, endCurrentIfAny: Bool) -> RequestCallResult
|
||||
func joinGroupCall(context: AccountContext, peerId: PeerId, initialCall: CachedChannelData.ActiveCall, endCurrentIfAny: Bool, sourcePanel: ASDisplayNode?) -> JoinGroupCallManagerResult
|
||||
func joinGroupCall(context: AccountContext, peerId: PeerId, initialCall: CachedChannelData.ActiveCall, endCurrentIfAny: Bool) -> JoinGroupCallManagerResult
|
||||
}
|
||||
|
|
|
|||
|
|
@ -709,7 +709,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
|
|||
override func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition, additionalInsets: UIEdgeInsets) {
|
||||
var updatedInsets = layout.intrinsicInsets
|
||||
updatedInsets.bottom += BotCheckoutActionButton.diameter + 20.0
|
||||
super.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: updatedInsets, safeInsets: layout.safeInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), navigationBarHeight: navigationBarHeight, transition: transition, additionalInsets: additionalInsets)
|
||||
super.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: updatedInsets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), navigationBarHeight: navigationBarHeight, transition: transition, additionalInsets: additionalInsets)
|
||||
|
||||
let actionButtonFrame = CGRect(origin: CGPoint(x: 10.0, y: layout.size.height - 10.0 - BotCheckoutActionButton.diameter - layout.intrinsicInsets.bottom), size: CGSize(width: layout.size.width - 20.0, height: BotCheckoutActionButton.diameter))
|
||||
transition.updateFrame(node: self.actionButton, frame: actionButtonFrame)
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ final class BotReceiptControllerNode: ItemListControllerNode {
|
|||
override func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition, additionalInsets: UIEdgeInsets) {
|
||||
var updatedInsets = layout.intrinsicInsets
|
||||
updatedInsets.bottom += BotCheckoutActionButton.diameter + 20.0
|
||||
super.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: updatedInsets, safeInsets: layout.safeInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), navigationBarHeight: navigationBarHeight, transition: transition, additionalInsets: additionalInsets)
|
||||
super.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: updatedInsets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), navigationBarHeight: navigationBarHeight, transition: transition, additionalInsets: additionalInsets)
|
||||
|
||||
let actionButtonFrame = CGRect(origin: CGPoint(x: 10.0, y: layout.size.height - 10.0 - BotCheckoutActionButton.diameter - layout.intrinsicInsets.bottom), size: CGSize(width: layout.size.width - 20.0, height: BotCheckoutActionButton.diameter))
|
||||
transition.updateFrame(node: self.actionButton, frame: actionButtonFrame)
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ final class ContactsControllerNode: ASDisplayNode {
|
|||
searchDisplayController.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: transition)
|
||||
}
|
||||
|
||||
self.contactListNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: insets, safeInsets: layout.safeInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), headerInsets: headerInsets, transition: transition)
|
||||
self.contactListNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: insets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), headerInsets: headerInsets, transition: transition)
|
||||
|
||||
self.contactListNode.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1267,7 +1267,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||
}
|
||||
contentUnscaledSize = CGSize(width: constrainedWidth, height: max(100.0, proposedContentHeight))
|
||||
|
||||
if let preferredSize = contentParentNode.controller.preferredContentSizeForLayout(ContainerViewLayout(size: contentUnscaledSize, metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact), deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false)) {
|
||||
if let preferredSize = contentParentNode.controller.preferredContentSizeForLayout(ContainerViewLayout(size: contentUnscaledSize, metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact), deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false)) {
|
||||
contentUnscaledSize = preferredSize
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1277,7 +1277,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||
let proposedContentHeight = layout.size.height - topEdge - contentActionsSpacing - actionsSize.height - layout.intrinsicInsets.bottom - actionsBottomInset
|
||||
contentUnscaledSize = CGSize(width: min(layout.size.width, 340.0), height: min(568.0, proposedContentHeight))
|
||||
|
||||
if let preferredSize = contentParentNode.controller.preferredContentSizeForLayout(ContainerViewLayout(size: contentUnscaledSize, metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact), deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false)) {
|
||||
if let preferredSize = contentParentNode.controller.preferredContentSizeForLayout(ContainerViewLayout(size: contentUnscaledSize, metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact), deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false)) {
|
||||
contentUnscaledSize = preferredSize
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ public extension CALayer {
|
|||
self.add(animationGroup, forKey: key)
|
||||
}
|
||||
|
||||
func animateKeyframes(values: [AnyObject], duration: Double, keyPath: String, removeOnCompletion: Bool = true, additive: Bool = false, completion: ((Bool) -> Void)? = nil) {
|
||||
func animateKeyframes(values: [AnyObject], duration: Double, keyPath: String, timingFunction: String = CAMediaTimingFunctionName.linear.rawValue, removeOnCompletion: Bool = true, additive: Bool = false, completion: ((Bool) -> Void)? = nil) {
|
||||
let k = Float(UIView.animationDurationFactor())
|
||||
var speed: Float = 1.0
|
||||
if k != 0 && k != 1 {
|
||||
|
|
@ -150,6 +150,8 @@ public extension CALayer {
|
|||
animation.speed = speed
|
||||
animation.duration = duration
|
||||
animation.isAdditive = additive
|
||||
animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName(rawValue: timingFunction))
|
||||
animation.isRemovedOnCompletion = removeOnCompletion
|
||||
if let completion = completion {
|
||||
animation.delegate = CALayerAnimationDelegate(animation: animation, completion: completion)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,17 +46,19 @@ public struct ContainerViewLayout: Equatable {
|
|||
public var deviceMetrics: DeviceMetrics
|
||||
public var intrinsicInsets: UIEdgeInsets
|
||||
public var safeInsets: UIEdgeInsets
|
||||
public var additionalInsets: UIEdgeInsets
|
||||
public var statusBarHeight: CGFloat?
|
||||
public var inputHeight: CGFloat?
|
||||
public var inputHeightIsInteractivellyChanging: Bool
|
||||
public var inVoiceOver: Bool
|
||||
|
||||
public init(size: CGSize, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, intrinsicInsets: UIEdgeInsets, safeInsets: UIEdgeInsets, statusBarHeight: CGFloat?, inputHeight: CGFloat?, inputHeightIsInteractivellyChanging: Bool, inVoiceOver: Bool) {
|
||||
public init(size: CGSize, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, intrinsicInsets: UIEdgeInsets, safeInsets: UIEdgeInsets, additionalInsets: UIEdgeInsets, statusBarHeight: CGFloat?, inputHeight: CGFloat?, inputHeightIsInteractivellyChanging: Bool, inVoiceOver: Bool) {
|
||||
self.size = size
|
||||
self.metrics = metrics
|
||||
self.deviceMetrics = deviceMetrics
|
||||
self.intrinsicInsets = intrinsicInsets
|
||||
self.safeInsets = safeInsets
|
||||
self.additionalInsets = additionalInsets
|
||||
self.statusBarHeight = statusBarHeight
|
||||
self.inputHeight = inputHeight
|
||||
self.inputHeightIsInteractivellyChanging = inputHeightIsInteractivellyChanging
|
||||
|
|
@ -64,19 +66,19 @@ public struct ContainerViewLayout: Equatable {
|
|||
}
|
||||
|
||||
public func addedInsets(insets: UIEdgeInsets) -> ContainerViewLayout {
|
||||
return ContainerViewLayout(size: self.size, metrics: self.metrics, deviceMetrics: self.deviceMetrics, intrinsicInsets: UIEdgeInsets(top: self.intrinsicInsets.top + insets.top, left: self.intrinsicInsets.left + insets.left, bottom: self.intrinsicInsets.bottom + insets.bottom, right: self.intrinsicInsets.right + insets.right), safeInsets: self.safeInsets, statusBarHeight: self.statusBarHeight, inputHeight: self.inputHeight, inputHeightIsInteractivellyChanging: self.inputHeightIsInteractivellyChanging, inVoiceOver: self.inVoiceOver)
|
||||
return ContainerViewLayout(size: self.size, metrics: self.metrics, deviceMetrics: self.deviceMetrics, intrinsicInsets: UIEdgeInsets(top: self.intrinsicInsets.top + insets.top, left: self.intrinsicInsets.left + insets.left, bottom: self.intrinsicInsets.bottom + insets.bottom, right: self.intrinsicInsets.right + insets.right), safeInsets: self.safeInsets, additionalInsets: self.additionalInsets, statusBarHeight: self.statusBarHeight, inputHeight: self.inputHeight, inputHeightIsInteractivellyChanging: self.inputHeightIsInteractivellyChanging, inVoiceOver: self.inVoiceOver)
|
||||
}
|
||||
|
||||
public func withUpdatedSize(_ size: CGSize) -> ContainerViewLayout {
|
||||
return ContainerViewLayout(size: size, metrics: self.metrics, deviceMetrics: self.deviceMetrics, intrinsicInsets: self.intrinsicInsets, safeInsets: self.safeInsets, statusBarHeight: self.statusBarHeight, inputHeight: self.inputHeight, inputHeightIsInteractivellyChanging: self.inputHeightIsInteractivellyChanging, inVoiceOver: self.inVoiceOver)
|
||||
return ContainerViewLayout(size: size, metrics: self.metrics, deviceMetrics: self.deviceMetrics, intrinsicInsets: self.intrinsicInsets, safeInsets: self.safeInsets, additionalInsets: self.additionalInsets, statusBarHeight: self.statusBarHeight, inputHeight: self.inputHeight, inputHeightIsInteractivellyChanging: self.inputHeightIsInteractivellyChanging, inVoiceOver: self.inVoiceOver)
|
||||
}
|
||||
|
||||
public func withUpdatedInputHeight(_ inputHeight: CGFloat?) -> ContainerViewLayout {
|
||||
return ContainerViewLayout(size: self.size, metrics: self.metrics, deviceMetrics: self.deviceMetrics, intrinsicInsets: self.intrinsicInsets, safeInsets: self.safeInsets, statusBarHeight: self.statusBarHeight, inputHeight: inputHeight, inputHeightIsInteractivellyChanging: self.inputHeightIsInteractivellyChanging, inVoiceOver: self.inVoiceOver)
|
||||
return ContainerViewLayout(size: self.size, metrics: self.metrics, deviceMetrics: self.deviceMetrics, intrinsicInsets: self.intrinsicInsets, safeInsets: self.safeInsets, additionalInsets: self.additionalInsets, statusBarHeight: self.statusBarHeight, inputHeight: inputHeight, inputHeightIsInteractivellyChanging: self.inputHeightIsInteractivellyChanging, inVoiceOver: self.inVoiceOver)
|
||||
}
|
||||
|
||||
public func withUpdatedMetrics(_ metrics: LayoutMetrics) -> ContainerViewLayout {
|
||||
return ContainerViewLayout(size: self.size, metrics: metrics, deviceMetrics: self.deviceMetrics, intrinsicInsets: self.intrinsicInsets, safeInsets: self.safeInsets, statusBarHeight: self.statusBarHeight, inputHeight: self.inputHeight, inputHeightIsInteractivellyChanging: self.inputHeightIsInteractivellyChanging, inVoiceOver: self.inVoiceOver)
|
||||
return ContainerViewLayout(size: self.size, metrics: metrics, deviceMetrics: self.deviceMetrics, intrinsicInsets: self.intrinsicInsets, safeInsets: self.safeInsets, additionalInsets: self.additionalInsets, statusBarHeight: self.statusBarHeight, inputHeight: self.inputHeight, inputHeightIsInteractivellyChanging: self.inputHeightIsInteractivellyChanging, inVoiceOver: self.inVoiceOver)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public final class ContextContentContainerNode: ASDisplayNode {
|
|||
transition.updateBounds(node: controller, bounds: CGRect(origin: CGPoint(), size: size))
|
||||
transition.updateTransformScale(node: controller, scale: scaledSize.width / size.width)
|
||||
controller.updateLayout(size: size, transition: transition)
|
||||
controller.controller.containerLayoutUpdated(ContainerViewLayout(size: size, metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact), deviceMetrics: .iPhoneX, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: transition)
|
||||
controller.controller.containerLayoutUpdated(ContainerViewLayout(size: size, metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact), deviceMetrics: .iPhoneX, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: transition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,10 +34,6 @@ public class KeyShortcutsController: UIResponder {
|
|||
return true
|
||||
})
|
||||
|
||||
// iOS 8 fix
|
||||
convertedCommands.append(KeyShortcut(modifiers:[.command]).uiKeyCommand)
|
||||
convertedCommands.append(KeyShortcut(modifiers:[.alternate]).uiKeyCommand)
|
||||
|
||||
convertedCommands.append(contentsOf: shortcuts.map { $0.uiKeyCommand })
|
||||
|
||||
self.effectiveShortcuts = shortcuts
|
||||
|
|
|
|||
|
|
@ -34,9 +34,6 @@ public struct NavigationAnimationOptions : OptionSet {
|
|||
public static let removeOnMasterDetails = NavigationAnimationOptions(rawValue: 1 << 0)
|
||||
}
|
||||
|
||||
private final class NavigationControllerContainerView: UIView {
|
||||
}
|
||||
|
||||
public enum NavigationEmptyDetailsBackgoundMode {
|
||||
case image(UIImage)
|
||||
case wallpaper(UIImage)
|
||||
|
|
@ -100,6 +97,11 @@ private final class NavigationControllerNode: ASDisplayNode {
|
|||
return super.hitTest(point, with: event)
|
||||
}
|
||||
}
|
||||
|
||||
override func accessibilityPerformEscape() -> Bool {
|
||||
print("escape")
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public protocol NavigationControllerDropContentItem: class {
|
||||
|
|
@ -544,6 +546,7 @@ open class NavigationController: UINavigationController, ContainableController,
|
|||
}
|
||||
}
|
||||
|
||||
var additionalSideInsets = UIEdgeInsets()
|
||||
var previousOverlayContainer: NavigationOverlayContainer?
|
||||
for i in (0 ..< self.overlayContainers.count).reversed() {
|
||||
let overlayContainer = self.overlayContainers[i]
|
||||
|
|
@ -573,6 +576,9 @@ open class NavigationController: UINavigationController, ContainableController,
|
|||
overlayContainer.transitionIn()
|
||||
}
|
||||
|
||||
let controllerAdditionalSideInsets = overlayContainer.controller.additionalSideInsets
|
||||
additionalSideInsets = UIEdgeInsets(top: 0.0, left: max(additionalSideInsets.left, controllerAdditionalSideInsets.left), bottom: 0.0, right: max(additionalSideInsets.right, controllerAdditionalSideInsets.right))
|
||||
|
||||
if overlayContainer.supernode != nil {
|
||||
previousOverlayContainer = overlayContainer
|
||||
let controllerStatusBarStyle = overlayContainer.controller.statusBar.statusBarStyle
|
||||
|
|
@ -592,6 +598,9 @@ open class NavigationController: UINavigationController, ContainableController,
|
|||
}
|
||||
}
|
||||
|
||||
layout.additionalInsets.left = max(layout.intrinsicInsets.left, additionalSideInsets.left)
|
||||
layout.additionalInsets.right = max(layout.intrinsicInsets.right, additionalSideInsets.right)
|
||||
|
||||
if self.currentTopVisibleOverlayContainerStatusBar !== topVisibleOverlayContainerWithStatusBar {
|
||||
animateStatusBarStyleTransition = true
|
||||
self.currentTopVisibleOverlayContainerStatusBar = topVisibleOverlayContainerWithStatusBar
|
||||
|
|
|
|||
|
|
@ -378,7 +378,7 @@ final class NavigationModalContainer: ASDisplayNode, UIScrollViewDelegate, UIGes
|
|||
effectiveStatusBarHeight = nil
|
||||
}
|
||||
|
||||
containerLayout = ContainerViewLayout(size: CGSize(width: layout.size.width, height: layout.size.height - topInset), metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(top: 0.0, left: layout.intrinsicInsets.left, bottom: layout.intrinsicInsets.bottom, right: layout.intrinsicInsets.right), safeInsets: UIEdgeInsets(top: 0.0, left: layout.safeInsets.left, bottom: layout.safeInsets.bottom, right: layout.safeInsets.right), statusBarHeight: effectiveStatusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver)
|
||||
containerLayout = ContainerViewLayout(size: CGSize(width: layout.size.width, height: layout.size.height - topInset), metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(top: 0.0, left: layout.intrinsicInsets.left, bottom: layout.intrinsicInsets.bottom, right: layout.intrinsicInsets.right), safeInsets: UIEdgeInsets(top: 0.0, left: layout.safeInsets.left, bottom: layout.safeInsets.bottom, right: layout.safeInsets.right), additionalInsets: layout.additionalInsets, statusBarHeight: effectiveStatusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver)
|
||||
let unscaledFrame = CGRect(origin: CGPoint(x: 0.0, y: topInset - coveredByModalTransition * 10.0), size: containerLayout.size)
|
||||
let maxScale: CGFloat = (containerLayout.size.width - 16.0 * 2.0) / containerLayout.size.width
|
||||
containerScale = 1.0 * (1.0 - coveredByModalTransition) + maxScale * coveredByModalTransition
|
||||
|
|
@ -424,7 +424,7 @@ final class NavigationModalContainer: ASDisplayNode, UIScrollViewDelegate, UIGes
|
|||
effectiveStatusBarHeight = nil
|
||||
}
|
||||
|
||||
containerLayout = ContainerViewLayout(size: containerSize, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), statusBarHeight: effectiveStatusBarHeight, inputHeight: inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver)
|
||||
containerLayout = ContainerViewLayout(size: containerSize, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), additionalInsets: UIEdgeInsets(), statusBarHeight: effectiveStatusBarHeight, inputHeight: inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver)
|
||||
}
|
||||
transition.updateFrameAsPositionAndBounds(node: self.container, frame: containerFrame.offsetBy(dx: 0.0, dy: layout.size.height))
|
||||
transition.updateTransformScale(node: self.container, scale: containerScale)
|
||||
|
|
|
|||
|
|
@ -94,8 +94,8 @@ final class NavigationSplitContainer: ASDisplayNode {
|
|||
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)))
|
||||
|
||||
self.masterContainer.update(layout: ContainerViewLayout(size: CGSize(width: masterWidth, height: layout.size.height), metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: layout.intrinsicInsets, safeInsets: layout.safeInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), canBeClosed: false, controllers: masterControllers, transition: transition)
|
||||
self.detailContainer.update(layout: ContainerViewLayout(size: CGSize(width: detailWidth, height: layout.size.height), metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: layout.intrinsicInsets, safeInsets: layout.safeInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), canBeClosed: true, controllers: detailControllers, transition: transition)
|
||||
self.masterContainer.update(layout: ContainerViewLayout(size: CGSize(width: masterWidth, height: layout.size.height), metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: layout.intrinsicInsets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), canBeClosed: false, controllers: masterControllers, transition: transition)
|
||||
self.detailContainer.update(layout: ContainerViewLayout(size: CGSize(width: detailWidth, height: layout.size.height), metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: layout.intrinsicInsets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), canBeClosed: true, controllers: detailControllers, transition: transition)
|
||||
|
||||
var controllersUpdated = false
|
||||
if self.detailControllers.last !== detailControllers.last {
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ final class TabBarControllerNode: ASDisplayNode {
|
|||
let tabBarFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - (self.tabBarHidden ? 0.0 : tabBarHeight)), size: CGSize(width: layout.size.width, height: tabBarHeight))
|
||||
|
||||
transition.updateFrame(node: self.tabBarNode, frame: tabBarFrame)
|
||||
self.tabBarNode.updateLayout(size: layout.size, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: bottomInset, transition: transition)
|
||||
self.tabBarNode.updateLayout(size: layout.size, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, additionalSideInsets: layout.additionalInsets, bottomInset: bottomInset, transition: transition)
|
||||
|
||||
transition.updateFrame(node: self.disabledOverlayNode, frame: tabBarFrame)
|
||||
|
||||
|
|
|
|||
|
|
@ -326,7 +326,7 @@ class TabBarNode: ASDisplayNode {
|
|||
private let swipeAction: (Int, TabBarItemSwipeDirection) -> Void
|
||||
|
||||
private var theme: TabBarControllerTheme
|
||||
private var validLayout: (CGSize, CGFloat, CGFloat, CGFloat)?
|
||||
private var validLayout: (CGSize, CGFloat, CGFloat, UIEdgeInsets, CGFloat)?
|
||||
private var horizontal: Bool = false
|
||||
private var centered: Bool = false
|
||||
|
||||
|
|
@ -405,7 +405,7 @@ class TabBarNode: ASDisplayNode {
|
|||
}
|
||||
|
||||
if let validLayout = self.validLayout {
|
||||
self.updateLayout(size: validLayout.0, leftInset: validLayout.1, rightInset: validLayout.2, bottomInset: validLayout.3, transition: .immediate)
|
||||
self.updateLayout(size: validLayout.0, leftInset: validLayout.1, rightInset: validLayout.2, additionalSideInsets: validLayout.3, bottomInset: validLayout.4, transition: .immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -513,7 +513,7 @@ class TabBarNode: ASDisplayNode {
|
|||
|
||||
if previousImageSize != updatedImageSize || previousTextImageSize != updatedTextImageSize {
|
||||
if let validLayout = self.validLayout, layout {
|
||||
self.updateLayout(size: validLayout.0, leftInset: validLayout.1, rightInset: validLayout.2, bottomInset: validLayout.3, transition: .immediate)
|
||||
self.updateLayout(size: validLayout.0, leftInset: validLayout.1, rightInset: validLayout.2, additionalSideInsets: validLayout.3, bottomInset: validLayout.4, transition: .immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -523,7 +523,7 @@ class TabBarNode: ASDisplayNode {
|
|||
self.tabBarNodeContainers[index].badgeValue = value
|
||||
if self.tabBarNodeContainers[index].badgeValue != self.tabBarNodeContainers[index].appliedBadgeValue {
|
||||
if let validLayout = self.validLayout {
|
||||
self.updateLayout(size: validLayout.0, leftInset: validLayout.1, rightInset: validLayout.2, bottomInset: validLayout.3, transition: .immediate)
|
||||
self.updateLayout(size: validLayout.0, leftInset: validLayout.1, rightInset: validLayout.2, additionalSideInsets: validLayout.3, bottomInset: validLayout.4, transition: .immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -532,13 +532,13 @@ class TabBarNode: ASDisplayNode {
|
|||
self.tabBarNodeContainers[index].titleValue = value
|
||||
if self.tabBarNodeContainers[index].titleValue != self.tabBarNodeContainers[index].appliedTitleValue {
|
||||
if let validLayout = self.validLayout {
|
||||
self.updateLayout(size: validLayout.0, leftInset: validLayout.1, rightInset: validLayout.2, bottomInset: validLayout.3, transition: .immediate)
|
||||
self.updateLayout(size: validLayout.0, leftInset: validLayout.1, rightInset: validLayout.2, additionalSideInsets: validLayout.3, bottomInset: validLayout.4, transition: .immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
self.validLayout = (size, leftInset, rightInset, bottomInset)
|
||||
func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, additionalSideInsets: UIEdgeInsets, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
self.validLayout = (size, leftInset, rightInset, additionalSideInsets, bottomInset)
|
||||
|
||||
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -separatorHeight), size: CGSize(width: size.width, height: separatorHeight)))
|
||||
|
||||
|
|
@ -551,13 +551,34 @@ class TabBarNode: ASDisplayNode {
|
|||
}
|
||||
|
||||
if self.tabBarNodeContainers.count != 0 {
|
||||
let distanceBetweenNodes = size.width / CGFloat(self.tabBarNodeContainers.count)
|
||||
var tabBarNodeContainers = self.tabBarNodeContainers
|
||||
var width = size.width
|
||||
|
||||
let internalWidth = distanceBetweenNodes * CGFloat(self.tabBarNodeContainers.count - 1)
|
||||
let leftNodeOriginX = (size.width - internalWidth) / 2.0
|
||||
var callsTabBarNodeContainer: TabBarNodeContainer?
|
||||
if tabBarNodeContainers.count == 4 {
|
||||
callsTabBarNodeContainer = tabBarNodeContainers[1]
|
||||
}
|
||||
|
||||
for i in 0 ..< self.tabBarNodeContainers.count {
|
||||
let container = self.tabBarNodeContainers[i]
|
||||
if additionalSideInsets.right > 0.0 {
|
||||
width -= additionalSideInsets.right
|
||||
|
||||
if let callsTabBarNodeContainer = callsTabBarNodeContainer {
|
||||
tabBarNodeContainers.remove(at: 1)
|
||||
transition.updateAlpha(node: callsTabBarNodeContainer.imageNode, alpha: 0.0)
|
||||
}
|
||||
} else {
|
||||
if let callsTabBarNodeContainer = callsTabBarNodeContainer {
|
||||
transition.updateAlpha(node: callsTabBarNodeContainer.imageNode, alpha: 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
let distanceBetweenNodes = width / CGFloat(tabBarNodeContainers.count)
|
||||
|
||||
let internalWidth = distanceBetweenNodes * CGFloat(tabBarNodeContainers.count - 1)
|
||||
let leftNodeOriginX = (width - internalWidth) / 2.0
|
||||
|
||||
for i in 0 ..< tabBarNodeContainers.count {
|
||||
let container = tabBarNodeContainers[i]
|
||||
let node = container.imageNode
|
||||
let nodeSize = node.textImageNode.image?.size ?? CGSize()
|
||||
|
||||
|
|
@ -612,7 +633,7 @@ class TabBarNode: ASDisplayNode {
|
|||
}
|
||||
|
||||
private func tapped(at location: CGPoint, longTap: Bool) {
|
||||
if let bottomInset = self.validLayout?.3 {
|
||||
if let bottomInset = self.validLayout?.4 {
|
||||
if location.y > self.bounds.size.height - bottomInset {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -253,6 +253,8 @@ public enum TabBarItemContextActionType {
|
|||
|
||||
public var additionalNavigationBarHeight: CGFloat = 0.0
|
||||
|
||||
public var additionalSideInsets: UIEdgeInsets = UIEdgeInsets()
|
||||
|
||||
private let _ready = Promise<Bool>(true)
|
||||
open var ready: Promise<Bool> {
|
||||
return self._ready
|
||||
|
|
|
|||
|
|
@ -65,14 +65,14 @@ private final class ViewControllerPeekContentNode: ASDisplayNode, PeekController
|
|||
if !self.hasValidLayout {
|
||||
self.hasValidLayout = true
|
||||
self.controller.view.frame = CGRect(origin: CGPoint(), size: size)
|
||||
self.controller.containerLayoutUpdated(ContainerViewLayout(size: size, metrics: LayoutMetrics(), deviceMetrics: .unknown(screenSize: size, statusBarHeight: 20.0, onScreenNavigationHeight: nil), intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: .immediate)
|
||||
self.controller.containerLayoutUpdated(ContainerViewLayout(size: size, metrics: LayoutMetrics(), deviceMetrics: .unknown(screenSize: size, statusBarHeight: 20.0, onScreenNavigationHeight: nil), intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: .immediate)
|
||||
self.controller.setIgnoreAppearanceMethodInvocations(true)
|
||||
self.view.addSubview(self.controller.view)
|
||||
self.controller.setIgnoreAppearanceMethodInvocations(false)
|
||||
self.controller.viewWillAppear(false)
|
||||
self.controller.viewDidAppear(false)
|
||||
} else {
|
||||
self.controller.containerLayoutUpdated(ContainerViewLayout(size: size, metrics: LayoutMetrics(), deviceMetrics: .unknown(screenSize: size, statusBarHeight: 20.0, onScreenNavigationHeight: nil), intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: transition)
|
||||
self.controller.containerLayoutUpdated(ContainerViewLayout(size: size, metrics: LayoutMetrics(), deviceMetrics: .unknown(screenSize: size, statusBarHeight: 20.0, onScreenNavigationHeight: nil), intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: transition)
|
||||
}
|
||||
|
||||
return size
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ private func containedLayoutForWindowLayout(_ layout: WindowLayout, deviceMetric
|
|||
resolvedSafeInsets = deviceMetrics.safeInsets(inLandscape: isLandscape)
|
||||
}
|
||||
|
||||
return ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: deviceMetrics, intrinsicInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: layout.onScreenNavigationHeight ?? 0.0, right: 0.0), safeInsets: resolvedSafeInsets, statusBarHeight: resolvedStatusBarHeight, inputHeight: updatedInputHeight, inputHeightIsInteractivellyChanging: layout.upperKeyboardInputPositionBound != nil && layout.upperKeyboardInputPositionBound != layout.size.height && layout.inputHeight != nil, inVoiceOver: layout.inVoiceOver)
|
||||
return ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: deviceMetrics, intrinsicInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: layout.onScreenNavigationHeight ?? 0.0, right: 0.0), safeInsets: resolvedSafeInsets, additionalInsets: UIEdgeInsets(), statusBarHeight: resolvedStatusBarHeight, inputHeight: updatedInputHeight, inputHeightIsInteractivellyChanging: layout.upperKeyboardInputPositionBound != nil && layout.upperKeyboardInputPositionBound != layout.size.height && layout.inputHeight != nil, inVoiceOver: layout.inVoiceOver)
|
||||
}
|
||||
|
||||
private func encodeText(_ string: String, _ key: Int) -> String {
|
||||
|
|
|
|||
|
|
@ -1246,7 +1246,7 @@ public class GalleryController: ViewController, StandalonePresentableController
|
|||
if let centralItemNode = self.galleryNode.pager.centralItemNode(), let itemSize = centralItemNode.contentSize() {
|
||||
centralItemNode.adjustForPreviewing()
|
||||
self.preferredContentSize = itemSize.aspectFitted(layout.size)
|
||||
self.containerLayoutUpdated(ContainerViewLayout(size: self.preferredContentSize, metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: .immediate)
|
||||
self.containerLayoutUpdated(ContainerViewLayout(size: self.preferredContentSize, metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: .immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ final class HashtagSearchControllerNode: ASDisplayNode {
|
|||
insets.top += toolbarHeight - 4.0
|
||||
let chatSize = CGSize(width: layout.size.width, height: layout.size.height)
|
||||
transition.updateFrame(node: chatController.displayNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: chatSize))
|
||||
chatController.containerLayoutUpdated(ContainerViewLayout(size: chatSize, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(top: insets.top, left: 0.0, bottom: layout.intrinsicInsets.bottom, right: 0.0), safeInsets: layout.safeInsets, statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: .immediate)
|
||||
chatController.containerLayoutUpdated(ContainerViewLayout(size: chatSize, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(top: insets.top, left: 0.0, bottom: layout.intrinsicInsets.bottom, right: 0.0), safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: .immediate)
|
||||
|
||||
if chatController.displayNode.supernode == nil {
|
||||
chatController.viewWillAppear(false)
|
||||
|
|
|
|||
|
|
@ -411,7 +411,7 @@ final class InstantPageSlideshowNode: ASDisplayNode, InstantPageNode {
|
|||
super.layout()
|
||||
|
||||
self.pagerNode.frame = self.bounds
|
||||
self.pagerNode.containerLayoutUpdated(ContainerViewLayout(size: self.bounds.size, metrics: LayoutMetrics(), deviceMetrics: .unknown(screenSize: CGSize(), statusBarHeight: 0.0, onScreenNavigationHeight: nil), intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: .immediate)
|
||||
self.pagerNode.containerLayoutUpdated(ContainerViewLayout(size: self.bounds.size, metrics: LayoutMetrics(), deviceMetrics: .unknown(screenSize: CGSize(), statusBarHeight: 0.0, onScreenNavigationHeight: nil), intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: .immediate)
|
||||
|
||||
self.pageControlNode.layer.transform = CATransform3DIdentity
|
||||
self.pageControlNode.frame = CGRect(origin: CGPoint(x: 0.0, y: self.bounds.size.height - 20.0), size: CGSize(width: self.bounds.size.width, height: 20.0))
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ public class ItemListSwitchItemNode: ListViewItemNode, ItemListItemNode {
|
|||
|
||||
strongSelf.activateArea.accessibilityLabel = item.title
|
||||
strongSelf.activateArea.accessibilityValue = item.value ? item.presentationData.strings.VoiceOver_Common_On : item.presentationData.strings.VoiceOver_Common_Off
|
||||
strongSelf.activateArea.accessibilityHint = item.presentationData.strings.VoiceOver_Common_TapToChange
|
||||
strongSelf.activateArea.accessibilityHint = item.presentationData.strings.VoiceOver_Common_SwitchHint
|
||||
var accessibilityTraits = UIAccessibilityTraits()
|
||||
if item.enabled {
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ typedef enum
|
|||
TGMediaLibraryAuthorizationStatusNotDetermined,
|
||||
TGMediaLibraryAuthorizationStatusRestricted,
|
||||
TGMediaLibraryAuthorizationStatusDenied,
|
||||
TGMediaLibraryAuthorizationStatusLimited,
|
||||
TGMediaLibraryAuthorizationStatusAuthorized
|
||||
} TGMediaLibraryAuthorizationStatus;
|
||||
|
||||
|
|
|
|||
|
|
@ -400,13 +400,12 @@
|
|||
{
|
||||
case PHAuthorizationStatusRestricted:
|
||||
return TGMediaLibraryAuthorizationStatusRestricted;
|
||||
|
||||
case PHAuthorizationStatusDenied:
|
||||
return TGMediaLibraryAuthorizationStatusDenied;
|
||||
|
||||
case PHAuthorizationStatusLimited:
|
||||
return TGMediaLibraryAuthorizationStatusLimited;
|
||||
case PHAuthorizationStatusAuthorized:
|
||||
return TGMediaLibraryAuthorizationStatusAuthorized;
|
||||
|
||||
default:
|
||||
return TGMediaLibraryAuthorizationStatusNotDetermined;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -888,7 +888,7 @@ final class LocationPickerControllerNode: ViewControllerTracingNode, CLLocationM
|
|||
|
||||
if let searchContainerNode = self.searchContainerNode {
|
||||
searchContainerNode.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
searchContainerNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: layout.intrinsicInsets, safeInsets: layout.safeInsets, statusBarHeight: nil, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), navigationBarHeight: navigationHeight, transition: transition)
|
||||
searchContainerNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: layout.intrinsicInsets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: nil, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), navigationBarHeight: navigationHeight, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -641,7 +641,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
|||
self.galleryNode.setControlsHidden(true, animated: false)
|
||||
if let centralItemNode = self.galleryNode.pager.centralItemNode(), let itemSize = centralItemNode.contentSize() {
|
||||
self.preferredContentSize = itemSize.aspectFitted(self.view.bounds.size)
|
||||
self.containerLayoutUpdated(ContainerViewLayout(size: self.preferredContentSize, metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: .immediate)
|
||||
self.containerLayoutUpdated(ContainerViewLayout(size: self.preferredContentSize, metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: .immediate)
|
||||
centralItemNode.activateAsInitial()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ public final class ChannelMembersSearchController: ViewController {
|
|||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
super.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationInsetHeight, transition: transition)
|
||||
self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationInsetHeight, actualNavigationBarHeight: self.navigationHeight, transition: transition)
|
||||
}
|
||||
|
||||
private func activateSearch() {
|
||||
|
|
|
|||
|
|
@ -461,18 +461,21 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
|
|||
self.searchDisplayController?.updatePresentationData(self.presentationData)
|
||||
}
|
||||
|
||||
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, actualNavigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
let hadValidLayout = self.containerLayout != nil
|
||||
self.containerLayout = (layout, navigationBarHeight)
|
||||
|
||||
var insets = layout.insets(options: [.input])
|
||||
insets.top += navigationBarHeight
|
||||
|
||||
var headerInsets = layout.insets(options: [.input])
|
||||
headerInsets.top += actualNavigationBarHeight
|
||||
|
||||
self.listNode.bounds = CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: layout.size.height)
|
||||
self.listNode.position = CGPoint(x: layout.size.width / 2.0, y: layout.size.height / 2.0)
|
||||
|
||||
let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition)
|
||||
let updateSizeAndInsets = ListViewUpdateSizeAndInsets(size: layout.size, insets: insets, duration: duration, curve: curve)
|
||||
let updateSizeAndInsets = ListViewUpdateSizeAndInsets(size: layout.size, insets: insets, headerInsets: headerInsets, duration: duration, curve: curve)
|
||||
|
||||
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: nil, updateSizeAndInsets: updateSizeAndInsets, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
|
||||
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ public final class SearchDisplayController {
|
|||
safeInsets.left += 20.0
|
||||
safeInsets.right += 20.0
|
||||
|
||||
self.contentNode.containerLayoutUpdated(ContainerViewLayout(size: size, metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: layout.intrinsicInsets, safeInsets: safeInsets, statusBarHeight: nil, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), navigationBarHeight: navigationBarHeight, transition: transition)
|
||||
self.contentNode.containerLayoutUpdated(ContainerViewLayout(size: size, metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: layout.intrinsicInsets, safeInsets: safeInsets, additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), navigationBarHeight: navigationBarHeight, transition: transition)
|
||||
}
|
||||
|
||||
public func activate(insertSubnode: @escaping (ASDisplayNode, Bool) -> Void, placeholder: SearchBarPlaceholderNode?) {
|
||||
|
|
@ -160,7 +160,7 @@ public final class SearchDisplayController {
|
|||
var safeInsets = layout.safeInsets
|
||||
safeInsets.left += 20.0
|
||||
safeInsets.right += 20.0
|
||||
self.contentNode.containerLayoutUpdated(ContainerViewLayout(size: size, metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: safeInsets, statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), navigationBarHeight: navigationBarHeight, transition: .immediate)
|
||||
self.contentNode.containerLayoutUpdated(ContainerViewLayout(size: size, metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: safeInsets, additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), navigationBarHeight: navigationBarHeight, transition: .immediate)
|
||||
|
||||
var contentNavigationBarHeight = navigationBarHeight
|
||||
if layout.statusBarHeight == nil {
|
||||
|
|
|
|||
|
|
@ -685,7 +685,7 @@ public final class ShareController: ViewController {
|
|||
let shareToInstagram = ShareToInstagramActivity(action: { sharedItems in
|
||||
let renderer = MessageStoryRenderer(context: strongSelf.currentContext, messages: messages)
|
||||
|
||||
let layout = ContainerViewLayout(size: CGSize(width: 414.0, height: 896.0), metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact), deviceMetrics: .iPhoneX, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), statusBarHeight: 0.0, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false)
|
||||
let layout = ContainerViewLayout(size: CGSize(width: 414.0, height: 896.0), metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact), deviceMetrics: .iPhoneX, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), additionalInsets: UIEdgeInsets(), statusBarHeight: 0.0, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false)
|
||||
renderer.update(layout: layout) { image in
|
||||
if let data = image?.pngData() {
|
||||
let pasteboardItems: [[String: Any]] = [["com.instagram.sharedSticker.backgroundImage": data,
|
||||
|
|
|
|||
|
|
@ -465,8 +465,7 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
|
|||
}
|
||||
strongSelf.joinGroupCall(
|
||||
peerId: groupCallPanelData.peerId,
|
||||
info: groupCallPanelData.info,
|
||||
sourcePanel: strongSelf.groupCallAccessoryPanel
|
||||
info: groupCallPanelData.info
|
||||
)
|
||||
})
|
||||
if let navigationBar = self.navigationBar {
|
||||
|
|
@ -883,7 +882,7 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
|
|||
})]
|
||||
}
|
||||
|
||||
private func joinGroupCall(peerId: PeerId, info: GroupCallInfo, sourcePanel: GroupCallNavigationAccessoryPanel?) {
|
||||
self.context.joinGroupCall(peerId: peerId, activeCall: CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash), sourcePanel: sourcePanel)
|
||||
private func joinGroupCall(peerId: PeerId, info: GroupCallInfo) {
|
||||
self.context.joinGroupCall(peerId: peerId, activeCall: CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ private class CallStatusBarBackgroundNode: ASDisplayNode {
|
|||
override init() {
|
||||
self.foregroundView = UIView()
|
||||
self.foregroundGradientLayer = CAGradientLayer()
|
||||
self.maskCurveView = VoiceCurveView(frame: CGRect(), maxLevel: 2.5, smallCurveRange: (0.0, 0.0), mediumCurveRange: (0.1, 0.55), bigCurveRange: (0.1, 1.0))
|
||||
self.maskCurveView = VoiceCurveView(frame: CGRect(), maxLevel: 1.5, smallCurveRange: (0.0, 0.0), mediumCurveRange: (0.1, 0.55), bigCurveRange: (0.1, 1.0))
|
||||
self.maskCurveView.setColor(UIColor(rgb: 0xffffff))
|
||||
|
||||
var updateInHierarchy: ((Bool) -> Void)?
|
||||
|
|
@ -170,11 +170,11 @@ public class CallStatusBarNodeImpl: CallStatusBarNode {
|
|||
self.microphoneNode = VoiceChatMicrophoneNode()
|
||||
self.titleNode = ImmediateTextNode()
|
||||
self.subtitleNode = ImmediateAnimatedCountLabelNode()
|
||||
self.subtitleNode.reverseAnimationDirection = true
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.backgroundNode)
|
||||
self.addSubnode(self.microphoneNode)
|
||||
self.addSubnode(self.titleNode)
|
||||
self.addSubnode(self.subtitleNode)
|
||||
}
|
||||
|
|
@ -267,7 +267,6 @@ public class CallStatusBarNodeImpl: CallStatusBarNode {
|
|||
}
|
||||
|
||||
var title: String = ""
|
||||
var subtitle: String = ""
|
||||
|
||||
let textFont = Font.regular(13.0)
|
||||
let textColor = UIColor.white
|
||||
|
|
@ -336,7 +335,7 @@ public class CallStatusBarNodeImpl: CallStatusBarNode {
|
|||
let titleSize = self.titleNode.updateLayout(CGSize(width: 160.0, height: size.height))
|
||||
let subtitleSize = self.subtitleNode.updateLayout(size: CGSize(width: 160.0, height: size.height), animated: true)
|
||||
|
||||
let totalWidth = animationSize + iconSpacing + titleSize.width + spacing + subtitleSize.width
|
||||
let totalWidth = titleSize.width + spacing + subtitleSize.width
|
||||
let horizontalOrigin: CGFloat = floor((size.width - totalWidth) / 2.0)
|
||||
|
||||
let contentHeight: CGFloat = 24.0
|
||||
|
|
@ -344,11 +343,11 @@ public class CallStatusBarNodeImpl: CallStatusBarNode {
|
|||
|
||||
let transition: ContainedViewLayoutTransition = wasEmpty ? .immediate : .animated(duration: 0.2, curve: .easeInOut)
|
||||
|
||||
transition.updateFrame(node: self.microphoneNode, frame: CGRect(origin: CGPoint(x: horizontalOrigin, y: verticalOrigin + floor((contentHeight - animationSize) / 2.0)), size: CGSize(width: animationSize, height: animationSize)))
|
||||
self.microphoneNode.update(state: VoiceChatMicrophoneNode.State(muted: self.currentIsMuted, color: UIColor.white), animated: true)
|
||||
// transition.updateFrame(node: self.microphoneNode, frame: CGRect(origin: CGPoint(x: horizontalOrigin, y: verticalOrigin + floor((contentHeight - animationSize) / 2.0)), size: CGSize(width: animationSize, height: animationSize)))
|
||||
// self.microphoneNode.update(state: VoiceChatMicrophoneNode.State(muted: self.currentIsMuted, color: UIColor.white), animated: true)
|
||||
|
||||
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: horizontalOrigin + animationSize + iconSpacing, y: verticalOrigin + floor((contentHeight - titleSize.height) / 2.0)), size: titleSize))
|
||||
transition.updateFrame(node: self.subtitleNode, frame: CGRect(origin: CGPoint(x: horizontalOrigin + animationSize + iconSpacing + titleSize.width + spacing, y: verticalOrigin + floor((contentHeight - subtitleSize.height) / 2.0)), size: subtitleSize))
|
||||
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: horizontalOrigin, y: verticalOrigin + floor((contentHeight - titleSize.height) / 2.0)), size: titleSize))
|
||||
transition.updateFrame(node: self.subtitleNode, frame: CGRect(origin: CGPoint(x: horizontalOrigin + titleSize.width + spacing, y: verticalOrigin + floor((contentHeight - subtitleSize.height) / 2.0)), size: subtitleSize))
|
||||
|
||||
self.backgroundNode.speaking = self.currentIsConnected && !self.currentIsMuted
|
||||
self.backgroundNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.height + 18.0))
|
||||
|
|
@ -381,7 +380,7 @@ private final class VoiceCurveView: UIView {
|
|||
self.maxLevel = maxLevel
|
||||
|
||||
self.smallCurve = CurveView(
|
||||
pointsCount: 7,
|
||||
pointsCount: 8,
|
||||
minRandomness: 1,
|
||||
maxRandomness: 1.3,
|
||||
minSpeed: 0.9,
|
||||
|
|
@ -390,7 +389,7 @@ private final class VoiceCurveView: UIView {
|
|||
maxOffset: smallCurveRange.max
|
||||
)
|
||||
self.mediumCurve = CurveView(
|
||||
pointsCount: 7,
|
||||
pointsCount: 8,
|
||||
minRandomness: 1.2,
|
||||
maxRandomness: 1.5,
|
||||
minSpeed: 1.0,
|
||||
|
|
@ -399,7 +398,7 @@ private final class VoiceCurveView: UIView {
|
|||
maxOffset: mediumCurveRange.max
|
||||
)
|
||||
self.bigCurve = CurveView(
|
||||
pointsCount: 7,
|
||||
pointsCount: 8,
|
||||
minRandomness: 1.2,
|
||||
maxRandomness: 1.7,
|
||||
minSpeed: 1.0,
|
||||
|
|
@ -595,9 +594,9 @@ final class CurveView: UIView {
|
|||
func updateSpeedLevel(to newSpeedLevel: CGFloat) {
|
||||
speedLevel = max(speedLevel, newSpeedLevel)
|
||||
|
||||
if abs(lastSpeedLevel - newSpeedLevel) > 0.45 {
|
||||
animateToNewShape()
|
||||
}
|
||||
// if abs(lastSpeedLevel - newSpeedLevel) > 0.45 {
|
||||
// animateToNewShape()
|
||||
// }
|
||||
}
|
||||
|
||||
func startAnimating() {
|
||||
|
|
|
|||
|
|
@ -82,6 +82,10 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
|||
|> distinctUntilChanged
|
||||
}
|
||||
|
||||
public var hasActiveGroupCall: Bool {
|
||||
return self.currentGroupCall != nil
|
||||
}
|
||||
|
||||
private let currentCallPromise = Promise<PresentationCall?>(nil)
|
||||
public var currentCallSignal: Signal<PresentationCall?, NoError> {
|
||||
return self.currentCallPromise.get()
|
||||
|
|
@ -620,9 +624,9 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
|||
}
|
||||
}
|
||||
|
||||
public func joinGroupCall(context: AccountContext, peerId: PeerId, initialCall: CachedChannelData.ActiveCall, endCurrentIfAny: Bool, sourcePanel: ASDisplayNode?) -> JoinGroupCallManagerResult {
|
||||
public func joinGroupCall(context: AccountContext, peerId: PeerId, initialCall: CachedChannelData.ActiveCall, endCurrentIfAny: Bool) -> JoinGroupCallManagerResult {
|
||||
let begin: () -> Void = { [weak self] in
|
||||
let _ = self?.startGroupCall(accountContext: context, peerId: peerId, initialCall: initialCall, sourcePanel: sourcePanel).start()
|
||||
let _ = self?.startGroupCall(accountContext: context, peerId: peerId, initialCall: initialCall).start()
|
||||
}
|
||||
|
||||
if let currentGroupCall = self.currentGroupCallValue {
|
||||
|
|
@ -657,8 +661,7 @@ public final class PresentationCallManagerImpl: PresentationCallManager {
|
|||
accountContext: AccountContext,
|
||||
peerId: PeerId,
|
||||
initialCall: CachedChannelData.ActiveCall,
|
||||
internalId: CallSessionInternalId = CallSessionInternalId(),
|
||||
sourcePanel: ASDisplayNode?
|
||||
internalId: CallSessionInternalId = CallSessionInternalId()
|
||||
) -> Signal<Bool, NoError> {
|
||||
let (presentationData, present, openSettings) = self.getDeviceAccessData()
|
||||
|
||||
|
|
|
|||
|
|
@ -425,8 +425,6 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
|||
private var isCurrentlyConnecting: Bool?
|
||||
|
||||
private var myAudioLevelTimer: SwiftSignalKit.Timer?
|
||||
|
||||
public weak var sourcePanel: ASDisplayNode?
|
||||
|
||||
private var proximityManagerIndex: Int?
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
|
|||
private let titleLabel: ImmediateTextNode
|
||||
private let subtitleLabel: ImmediateTextNode
|
||||
|
||||
private var currentParams: (size: CGSize, buttonSize: CGSize, state: VoiceChatActionButton.State, dark: Bool, small: Bool, title: String, subtitle: String)?
|
||||
private var currentParams: (size: CGSize, buttonSize: CGSize, state: VoiceChatActionButton.State, dark: Bool, small: Bool, title: String, subtitle: String, snap: Bool)?
|
||||
|
||||
private var activePromise = ValuePromise<Bool>(false)
|
||||
private var outerColorPromise = ValuePromise<UIColor?>(nil)
|
||||
|
|
@ -47,12 +47,18 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
|
|||
|
||||
var pressing: Bool = false {
|
||||
didSet {
|
||||
if self.pressing {
|
||||
var pressing = self.pressing
|
||||
var snap = false
|
||||
if let (_, _, _, _, _, _, _, snapValue) = self.currentParams, snapValue {
|
||||
pressing = false
|
||||
snap = true
|
||||
}
|
||||
if pressing {
|
||||
let transition: ContainedViewLayoutTransition = .animated(duration: 0.25, curve: .spring)
|
||||
transition.updateTransformScale(node: self.iconNode, scale: 0.9)
|
||||
} else {
|
||||
let transition: ContainedViewLayoutTransition = .animated(duration: 0.25, curve: .spring)
|
||||
transition.updateTransformScale(node: self.iconNode, scale: 1.0)
|
||||
transition.updateTransformScale(node: self.iconNode, scale: snap ? 0.5 : 1.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -76,12 +82,19 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
|
|||
|
||||
self.highligthedChanged = { [weak self] highlighted in
|
||||
if let strongSelf = self {
|
||||
var highlighted = highlighted
|
||||
var snap = false
|
||||
if let (_, _, _, _, _, _, _, snapValue) = strongSelf.currentParams, snapValue {
|
||||
highlighted = false
|
||||
snap = true
|
||||
}
|
||||
|
||||
if highlighted {
|
||||
let transition: ContainedViewLayoutTransition = .animated(duration: 0.25, curve: .spring)
|
||||
transition.updateTransformScale(node: strongSelf.iconNode, scale: 0.9)
|
||||
} else if !strongSelf.pressing {
|
||||
let transition: ContainedViewLayoutTransition = .animated(duration: 0.25, curve: .spring)
|
||||
transition.updateTransformScale(node: strongSelf.iconNode, scale: 1.0)
|
||||
transition.updateTransformScale(node: strongSelf.iconNode, scale: snap ? 0.5 : 1.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -104,7 +117,7 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
|
|||
}
|
||||
|
||||
func applyParams(animated: Bool) {
|
||||
guard let (size, _, _, _, small, title, subtitle) = self.currentParams else {
|
||||
guard let (size, _, state, _, small, title, subtitle, snap) = self.currentParams else {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -144,19 +157,52 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
|
|||
|
||||
self.backgroundNode.bounds = CGRect(origin: CGPoint(), size: size)
|
||||
self.backgroundNode.position = CGPoint(x: size.width / 2.0, y: size.height / 2.0)
|
||||
if small {
|
||||
self.backgroundNode.transform = CATransform3DMakeScale(0.85, 0.85, 1.0)
|
||||
|
||||
var active = false
|
||||
switch state {
|
||||
case let .active(state):
|
||||
switch state {
|
||||
case .on:
|
||||
active = true
|
||||
default:
|
||||
break
|
||||
}
|
||||
case .connecting:
|
||||
break
|
||||
}
|
||||
|
||||
let transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.2, curve: .easeInOut) : .immediate
|
||||
if snap {
|
||||
transition.updateTransformScale(node: self.backgroundNode, scale: active ? 0.75 : 0.5)
|
||||
transition.updateTransformScale(node: self.iconNode, scale: 0.5)
|
||||
transition.updateAlpha(node: self.titleLabel, alpha: 0.0)
|
||||
transition.updateAlpha(node: self.subtitleLabel, alpha: 0.0)
|
||||
} else {
|
||||
self.backgroundNode.transform = CATransform3DIdentity
|
||||
transition.updateTransformScale(node: self.backgroundNode, scale: small ? 0.85 : 1.0)
|
||||
transition.updateTransformScale(node: self.iconNode, scale: self.pressing ? 0.9 : 1.0)
|
||||
transition.updateAlpha(node: self.titleLabel, alpha: 1.0)
|
||||
transition.updateAlpha(node: self.subtitleLabel, alpha: 1.0)
|
||||
}
|
||||
|
||||
let iconSize = CGSize(width: 90.0, height: 90.0)
|
||||
self.iconNode.frame = CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0)), size: iconSize)
|
||||
self.iconNode.bounds = CGRect(origin: CGPoint(), size: iconSize)
|
||||
self.iconNode.position = CGPoint(x: size.width / 2.0, y: size.height / 2.0)
|
||||
}
|
||||
|
||||
func update(snap: Bool) {
|
||||
if let previous = self.currentParams {
|
||||
self.currentParams = (previous.size, previous.buttonSize, previous.state, previous.dark, previous.small, previous.title, previous.subtitle, snap)
|
||||
|
||||
self.backgroundNode.glowHidden = snap
|
||||
|
||||
self.applyParams(animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
func update(size: CGSize, buttonSize: CGSize, state: VoiceChatActionButton.State, title: String, subtitle: String, dark: Bool, small: Bool, animated: Bool = false) {
|
||||
let previousState = self.currentParams?.state
|
||||
self.currentParams = (size, buttonSize, state, dark, small, title, subtitle)
|
||||
let previous = self.currentParams
|
||||
let previousState = previous?.state
|
||||
self.currentParams = (size, buttonSize, state, dark, small, title, subtitle, previous?.snap ?? false)
|
||||
|
||||
var iconMuted = true
|
||||
var iconColor: UIColor = .white
|
||||
|
|
@ -195,7 +241,7 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
|
|||
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
var hitRect = self.bounds
|
||||
if let (_, buttonSize, _, _, _, _, _) = self.currentParams {
|
||||
if let (_, buttonSize, _, _, _, _, _, _) = self.currentParams {
|
||||
hitRect = self.bounds.insetBy(dx: (self.bounds.width - buttonSize.width) / 2.0, dy: (self.bounds.height - buttonSize.height) / 2.0)
|
||||
}
|
||||
let result = super.hitTest(point, with: event)
|
||||
|
|
@ -336,7 +382,7 @@ private final class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
|
|||
override init() {
|
||||
self.state = .connecting
|
||||
|
||||
self.maskBlobView = VoiceBlobView(frame: CGRect(origin: CGPoint(x: (areaSize.width - blobSize.width) / 2.0, y: (areaSize.height - blobSize.height) / 2.0), size: blobSize), maxLevel: 2.0, mediumBlobRange: (0.69, 0.87), bigBlobRange: (0.71, 1.0))
|
||||
self.maskBlobView = VoiceBlobView(frame: CGRect(origin: CGPoint(x: (areaSize.width - blobSize.width) / 2.0, y: (areaSize.height - blobSize.height) / 2.0), size: blobSize), maxLevel: 1.5, mediumBlobRange: (0.69, 0.87), bigBlobRange: (0.71, 1.0))
|
||||
self.maskBlobView.setColor(white)
|
||||
self.maskBlobView.isHidden = true
|
||||
|
||||
|
|
@ -426,7 +472,7 @@ private final class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
|
|||
if self.maskBlobView.presentationAudioLevel > 0.15 {
|
||||
newValue = CGPoint(x: CGFloat.random(in: 0.8 ..< 1.0), y: CGFloat.random(in: 0.1 ..< 0.45))
|
||||
} else {
|
||||
newValue = CGPoint(x: CGFloat.random(in: 0.6 ..< 0.8), y: CGFloat.random(in: 0.1 ..< 0.45))
|
||||
newValue = CGPoint(x: CGFloat.random(in: 0.65 ..< 0.85), y: CGFloat.random(in: 0.1 ..< 0.45))
|
||||
}
|
||||
self.foregroundGradientLayer.startPoint = newValue
|
||||
|
||||
|
|
@ -490,15 +536,25 @@ private final class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
|
|||
}
|
||||
}
|
||||
|
||||
var glowHidden: Bool = false {
|
||||
didSet {
|
||||
if self.glowHidden != oldValue {
|
||||
let initialAlpha = CGFloat(self.maskProgressLayer.opacity)
|
||||
let targetAlpha: CGFloat = self.glowHidden ? 0.0 : 1.0
|
||||
self.maskGradientLayer.opacity = Float(targetAlpha)
|
||||
self.maskGradientLayer.animateAlpha(from: initialAlpha, to: targetAlpha, duration: 0.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateGlowScale(_ scale: CGFloat?) {
|
||||
return
|
||||
if let scale = scale {
|
||||
self.maskGradientLayer.transform = CATransform3DMakeScale(0.89 + 0.11 * scale, 0.89 + 0.11 * scale, 1.0)
|
||||
} else {
|
||||
// let initialScale: CGFloat = ((self.maskGradientLayer.value(forKeyPath: "presentationLayer.transform.scale.x") as? NSNumber)?.floatValue).flatMap({ CGFloat($0) }) ?? (((self.maskGradientLayer.value(forKeyPath: "transform.scale.x") as? NSNumber)?.floatValue).flatMap({ CGFloat($0) }) ?? (effectivePreviousActive ? 0.95 : 0.8))
|
||||
// let targetScale: CGFloat = self.isActive ? 0.89 : 0.85
|
||||
// self.maskGradientLayer.transform = CATransform3DMakeScale(targetScale, targetScale, 1.0)
|
||||
// self.maskGradientLayer.animateScale(from: initialScale, to: targetScale, duration: 0.3)
|
||||
let initialScale: CGFloat = ((self.maskGradientLayer.value(forKeyPath: "presentationLayer.transform.scale.x") as? NSNumber)?.floatValue).flatMap({ CGFloat($0) }) ?? (((self.maskGradientLayer.value(forKeyPath: "transform.scale.x") as? NSNumber)?.floatValue).flatMap({ CGFloat($0) }) ?? (0.89))
|
||||
let targetScale: CGFloat = self.isActive ? 0.89 : 0.85
|
||||
self.maskGradientLayer.transform = CATransform3DMakeScale(targetScale, targetScale, 1.0)
|
||||
self.maskGradientLayer.animateScale(from: initialScale, to: targetScale, duration: 0.3)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1041,9 +1097,9 @@ final class BlobView: UIView {
|
|||
func updateSpeedLevel(to newSpeedLevel: CGFloat) {
|
||||
speedLevel = max(speedLevel, newSpeedLevel)
|
||||
|
||||
if abs(lastSpeedLevel - newSpeedLevel) > 0.45 {
|
||||
animateToNewShape()
|
||||
}
|
||||
// if abs(lastSpeedLevel - newSpeedLevel) > 0.45 {
|
||||
// animateToNewShape()
|
||||
// }
|
||||
}
|
||||
|
||||
func startAnimating() {
|
||||
|
|
|
|||
|
|
@ -174,8 +174,8 @@ class VoiceChatActionItemNode: ListViewItemNode {
|
|||
strongSelf.activateArea.frame = CGRect(origin: CGPoint(x: params.leftInset, y: 0.0), size: CGSize(width: layout.contentSize.width - params.leftInset - params.rightInset, height: layout.contentSize.height))
|
||||
|
||||
if let _ = updatedTheme {
|
||||
strongSelf.topStripeNode.backgroundColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
strongSelf.topStripeNode.backgroundColor = UIColor(rgb: 0xffffff, alpha: 0.08)
|
||||
strongSelf.bottomStripeNode.backgroundColor = UIColor(rgb: 0xffffff, alpha: 0.08)
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
|
||||
strongSelf.iconNode.image = generateTintedImage(image: item.icon.image, color: UIColor(rgb: 0xffffff))
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ private func cornersImage(top: Bool, bottom: Bool, dark: Bool) -> UIImage? {
|
|||
}
|
||||
|
||||
|
||||
private final class VoiceChatControllerTitleView: UIView {
|
||||
private final class VoiceChatControllerTitleNode: ASDisplayNode {
|
||||
private var theme: PresentationTheme
|
||||
|
||||
private let titleNode: ASTextNode
|
||||
|
|
@ -76,7 +76,7 @@ private final class VoiceChatControllerTitleView: UIView {
|
|||
self.infoNode.truncationMode = .byTruncatingTail
|
||||
self.infoNode.isOpaque = false
|
||||
|
||||
super.init(frame: CGRect())
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.titleNode)
|
||||
self.addSubnode(self.infoNode)
|
||||
|
|
@ -86,35 +86,34 @@ private final class VoiceChatControllerTitleView: UIView {
|
|||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func set(title: String, subtitle: String) {
|
||||
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.medium(17.0), textColor: .white)
|
||||
self.infoNode.attributedText = NSAttributedString(string: subtitle, font: Font.regular(13.0), textColor: UIColor.white.withAlphaComponent(0.5))
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
let size = self.bounds.size
|
||||
|
||||
if size.height > 40.0 {
|
||||
let titleSize = self.titleNode.measure(size)
|
||||
let infoSize = self.infoNode.measure(size)
|
||||
let titleInfoSpacing: CGFloat = 0.0
|
||||
|
||||
let combinedHeight = titleSize.height + infoSize.height + titleInfoSpacing
|
||||
|
||||
self.titleNode.frame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: floor((size.height - combinedHeight) / 2.0)), size: titleSize)
|
||||
self.infoNode.frame = CGRect(origin: CGPoint(x: floor((size.width - infoSize.width) / 2.0), y: floor((size.height - combinedHeight) / 2.0) + titleSize.height + titleInfoSpacing), size: infoSize)
|
||||
} else {
|
||||
let titleSize = self.titleNode.measure(CGSize(width: floor(size.width / 2.0), height: size.height))
|
||||
let infoSize = self.infoNode.measure(CGSize(width: floor(size.width / 2.0), height: size.height))
|
||||
|
||||
let titleInfoSpacing: CGFloat = 8.0
|
||||
let combinedWidth = titleSize.width + infoSize.width + titleInfoSpacing
|
||||
|
||||
self.titleNode.frame = CGRect(origin: CGPoint(x: floor((size.width - combinedWidth) / 2.0), y: floor((size.height - titleSize.height) / 2.0)), size: titleSize)
|
||||
self.infoNode.frame = CGRect(origin: CGPoint(x: floor((size.width - combinedWidth) / 2.0 + titleSize.width + titleInfoSpacing), y: floor((size.height - infoSize.height) / 2.0)), size: infoSize)
|
||||
func update(size: CGSize, title: String, subtitle: String, transition: ContainedViewLayoutTransition) {
|
||||
var titleUpdated = false
|
||||
if let previousTitle = self.titleNode.attributedText?.string {
|
||||
titleUpdated = previousTitle != title
|
||||
}
|
||||
|
||||
if titleUpdated, let snapshotView = self.titleNode.view.snapshotContentTree() {
|
||||
snapshotView.frame = self.titleNode.frame
|
||||
self.view.addSubview(snapshotView)
|
||||
|
||||
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
||||
snapshotView?.removeFromSuperview()
|
||||
})
|
||||
|
||||
self.titleNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
}
|
||||
|
||||
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.medium(17.0), textColor: UIColor(rgb: 0xffffff))
|
||||
self.infoNode.attributedText = NSAttributedString(string: subtitle, font: Font.regular(13.0), textColor: UIColor(rgb: 0xffffff, alpha: 0.5))
|
||||
|
||||
let titleSize = self.titleNode.measure(size)
|
||||
let infoSize = self.infoNode.measure(size)
|
||||
let titleInfoSpacing: CGFloat = 0.0
|
||||
|
||||
let combinedHeight = titleSize.height + infoSize.height + titleInfoSpacing
|
||||
|
||||
self.titleNode.frame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: floor((size.height - combinedHeight) / 2.0)), size: titleSize)
|
||||
self.infoNode.frame = CGRect(origin: CGPoint(x: floor((size.width - infoSize.width) / 2.0), y: floor((size.height - combinedHeight) / 2.0) + titleSize.height + titleInfoSpacing), size: infoSize)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -172,17 +171,23 @@ public final class VoiceChatController: ViewController {
|
|||
}
|
||||
}
|
||||
|
||||
func updateAudioLevels(_ levels: [(PeerId, Float)]) {
|
||||
func updateAudioLevels(_ levels: [(PeerId, Float)], reset: Bool = false) {
|
||||
var updated = Set<PeerId>()
|
||||
for (peerId, level) in levels {
|
||||
if let pipe = self.audioLevels[peerId] {
|
||||
pipe.putNext(max(0.001, level))
|
||||
if reset {
|
||||
pipe.putNext(level)
|
||||
} else {
|
||||
pipe.putNext(max(0.001, level))
|
||||
}
|
||||
updated.insert(peerId)
|
||||
}
|
||||
}
|
||||
for (peerId, pipe) in self.audioLevels {
|
||||
if !updated.contains(peerId) {
|
||||
pipe.putNext(0.0)
|
||||
if !reset {
|
||||
for (peerId, pipe) in self.audioLevels {
|
||||
if !updated.contains(peerId) {
|
||||
pipe.putNext(0.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -377,18 +382,21 @@ public final class VoiceChatController: ViewController {
|
|||
private let backgroundNode: ASDisplayNode
|
||||
private let listNode: ListView
|
||||
private let topPanelNode: ASDisplayNode
|
||||
private let topPanelEdgeNode: ASDisplayNode
|
||||
private let topPanelBackgroundNode: ASDisplayNode
|
||||
private let optionsButton: VoiceChatHeaderButton
|
||||
private let closeButton: VoiceChatHeaderButton
|
||||
private let topCornersNode: ASImageNode
|
||||
private let bottomPanelNode: ASDisplayNode
|
||||
fileprivate let bottomPanelNode: ASDisplayNode
|
||||
private let bottomPanelBackgroundNode: ASDisplayNode
|
||||
private let bottomCornersNode: ASImageNode
|
||||
private let audioOutputNode: CallControllerButtonItemNode
|
||||
private let leaveNode: CallControllerButtonItemNode
|
||||
private let actionButton: VoiceChatActionButton
|
||||
fileprivate let actionButton: VoiceChatActionButton
|
||||
private let leftBorderNode: ASDisplayNode
|
||||
private let rightBorderNode: ASDisplayNode
|
||||
|
||||
private let titleView: VoiceChatControllerTitleView
|
||||
private let titleNode: VoiceChatControllerTitleNode
|
||||
|
||||
private var enqueuedTransitions: [ListTransition] = []
|
||||
private var floatingHeaderOffset: CGFloat?
|
||||
|
|
@ -397,10 +405,13 @@ public final class VoiceChatController: ViewController {
|
|||
private var didSetContentsReady: Bool = false
|
||||
private var didSetDataReady: Bool = false
|
||||
|
||||
private var currentTitle: String = ""
|
||||
private var currentSubtitle: String = ""
|
||||
private var currentCallMembers: [GroupCallParticipantsContext.Participant]?
|
||||
private var currentInvitedPeers: [Peer]?
|
||||
private var currentSpeakingPeers: Set<PeerId>?
|
||||
private var accountPeer: Peer?
|
||||
private var currentAudioButtonColor: UIColor?
|
||||
|
||||
private var currentEntries: [ListEntry] = []
|
||||
|
||||
|
|
@ -429,9 +440,10 @@ public final class VoiceChatController: ViewController {
|
|||
private var audioLevelsDisposable: Disposable?
|
||||
private var myAudioLevelDisposable: Disposable?
|
||||
private var memberStatesDisposable: Disposable?
|
||||
private var actionButtonColorDisposable: Disposable?
|
||||
|
||||
private var itemInteraction: Interaction?
|
||||
|
||||
|
||||
private let inviteDisposable = MetaDisposable()
|
||||
|
||||
init(controller: VoiceChatController, sharedContext: SharedAccountContext, call: PresentationGroupCall) {
|
||||
|
|
@ -442,7 +454,8 @@ public final class VoiceChatController: ViewController {
|
|||
|
||||
self.presentationData = sharedContext.currentPresentationData.with { $0 }
|
||||
self.darkTheme = defaultDarkColorPresentationTheme
|
||||
|
||||
self.currentSubtitle = self.presentationData.strings.SocksProxySetup_ProxyStatusConnecting
|
||||
|
||||
self.dimNode = ASDisplayNode()
|
||||
self.dimNode.backgroundColor = dimColor
|
||||
|
||||
|
|
@ -458,18 +471,22 @@ public final class VoiceChatController: ViewController {
|
|||
self.listNode.keepMinimalScrollHeightWithTopInset = 0
|
||||
|
||||
self.topPanelNode = ASDisplayNode()
|
||||
self.topPanelNode.backgroundColor = panelBackgroundColor
|
||||
self.topPanelNode.clipsToBounds = false
|
||||
self.topPanelNode.layer.cornerRadius = 12.0
|
||||
|
||||
self.topPanelBackgroundNode = ASDisplayNode()
|
||||
self.topPanelBackgroundNode.backgroundColor = panelBackgroundColor
|
||||
|
||||
self.topPanelEdgeNode = ASDisplayNode()
|
||||
self.topPanelEdgeNode.backgroundColor = panelBackgroundColor
|
||||
self.topPanelEdgeNode.layer.cornerRadius = 12.0
|
||||
|
||||
self.optionsButton = VoiceChatHeaderButton()
|
||||
self.optionsButton.setImage(optionsButtonImage(dark: false))
|
||||
self.closeButton = VoiceChatHeaderButton()
|
||||
self.closeButton.setImage(closeButtonImage(dark: false))
|
||||
|
||||
self.titleView = VoiceChatControllerTitleView(theme: self.presentationData.theme)
|
||||
self.titleView.set(title: self.presentationData.strings.VoiceChat_Title, subtitle: self.presentationData.strings.SocksProxySetup_ProxyStatusConnecting)
|
||||
self.titleView.isUserInteractionEnabled = false
|
||||
self.titleNode = VoiceChatControllerTitleNode(theme: self.presentationData.theme)
|
||||
self.titleNode.isUserInteractionEnabled = false
|
||||
|
||||
self.topCornersNode = ASImageNode()
|
||||
self.topCornersNode.displaysAsynchronously = false
|
||||
|
|
@ -477,9 +494,11 @@ public final class VoiceChatController: ViewController {
|
|||
self.topCornersNode.image = cornersImage(top: true, bottom: false, dark: false)
|
||||
|
||||
self.bottomPanelNode = ASDisplayNode()
|
||||
self.bottomPanelNode.backgroundColor = panelBackgroundColor
|
||||
self.bottomPanelNode.clipsToBounds = false
|
||||
|
||||
self.bottomPanelBackgroundNode = ASDisplayNode()
|
||||
self.bottomPanelBackgroundNode.backgroundColor = panelBackgroundColor
|
||||
|
||||
self.bottomCornersNode = ASImageNode()
|
||||
self.bottomCornersNode.displaysAsynchronously = false
|
||||
self.bottomCornersNode.displayWithoutProcessing = true
|
||||
|
|
@ -777,12 +796,15 @@ public final class VoiceChatController: ViewController {
|
|||
}
|
||||
})
|
||||
|
||||
self.topPanelNode.view.addSubview(self.titleView)
|
||||
self.topPanelNode.addSubnode(self.topPanelEdgeNode)
|
||||
self.topPanelNode.addSubnode(self.topPanelBackgroundNode)
|
||||
self.topPanelNode.addSubnode(self.titleNode)
|
||||
self.topPanelNode.addSubnode(self.optionsButton)
|
||||
self.topPanelNode.addSubnode(self.closeButton)
|
||||
self.topPanelNode.addSubnode(self.topCornersNode)
|
||||
|
||||
self.bottomPanelNode.addSubnode(self.bottomCornersNode)
|
||||
self.bottomPanelNode.addSubnode(self.bottomPanelBackgroundNode)
|
||||
self.bottomPanelNode.addSubnode(self.audioOutputNode)
|
||||
self.bottomPanelNode.addSubnode(self.leaveNode)
|
||||
self.bottomPanelNode.addSubnode(self.actionButton)
|
||||
|
|
@ -836,7 +858,7 @@ public final class VoiceChatController: ViewController {
|
|||
strongSelf.updateMembers(muteState: strongSelf.effectiveMuteState, callMembers: callMembers?.participants ?? [], invitedPeers: invitedPeers, speakingPeers: callMembers?.speakingParticipants ?? [])
|
||||
|
||||
let subtitle = strongSelf.presentationData.strings.VoiceChat_Panel_Members(Int32(max(1, callMembers?.totalCount ?? 0)))
|
||||
strongSelf.titleView.set(title: strongSelf.presentationData.strings.VoiceChat_Title, subtitle: subtitle)
|
||||
strongSelf.currentSubtitle = subtitle
|
||||
|
||||
if let (layout, navigationHeight) = strongSelf.validLayout {
|
||||
strongSelf.containerLayoutUpdated(layout, navigationHeight: navigationHeight, transition: .immediate)
|
||||
|
|
@ -848,7 +870,10 @@ public final class VoiceChatController: ViewController {
|
|||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if let peer = peerViewMainPeer(view) {
|
||||
strongSelf.currentTitle = peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)
|
||||
}
|
||||
if !strongSelf.didSetDataReady {
|
||||
strongSelf.accountPeer = accountPeer
|
||||
strongSelf.updateMembers(muteState: strongSelf.effectiveMuteState, callMembers: strongSelf.currentCallMembers ?? [], invitedPeers: strongSelf.currentInvitedPeers ?? [], speakingPeers: strongSelf.currentSpeakingPeers ?? Set())
|
||||
|
|
@ -886,6 +911,10 @@ public final class VoiceChatController: ViewController {
|
|||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
var levels = levels
|
||||
if strongSelf.effectiveMuteState != nil {
|
||||
levels = levels.filter { $0.0 != strongSelf.context.account.peerId }
|
||||
}
|
||||
strongSelf.itemInteraction?.updateAudioLevels(levels)
|
||||
})
|
||||
|
||||
|
|
@ -1018,6 +1047,14 @@ public final class VoiceChatController: ViewController {
|
|||
self.optionsButton.addTarget(self, action: #selector(self.optionsPressed), forControlEvents: .touchUpInside)
|
||||
self.closeButton.addTarget(self, action: #selector(self.closePressed), forControlEvents: .touchUpInside)
|
||||
|
||||
self.actionButtonColorDisposable = (self.actionButton.outerColor
|
||||
|> deliverOnMainQueue).start(next: { [weak self] color in
|
||||
if let strongSelf = self {
|
||||
strongSelf.currentAudioButtonColor = color
|
||||
strongSelf.updateButtons(transition: .immediate)
|
||||
}
|
||||
})
|
||||
|
||||
self.listNode.updateFloatingHeaderOffset = { [weak self] offset, transition in
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateFloatingHeaderOffset(offset: offset, transition: transition)
|
||||
|
|
@ -1068,7 +1105,7 @@ public final class VoiceChatController: ViewController {
|
|||
panRecognizer.delegate = self
|
||||
panRecognizer.delaysTouchesBegan = false
|
||||
panRecognizer.cancelsTouchesInView = true
|
||||
self.view.addGestureRecognizer(panRecognizer)
|
||||
// self.view.addGestureRecognizer(panRecognizer)
|
||||
}
|
||||
|
||||
@objc private func optionsPressed() {
|
||||
|
|
@ -1078,7 +1115,7 @@ public final class VoiceChatController: ViewController {
|
|||
}
|
||||
|
||||
@objc private func closePressed() {
|
||||
self.controller?.dismiss()
|
||||
self.controller?.dismiss(closing: false)
|
||||
}
|
||||
|
||||
@objc private func leavePressed() {
|
||||
|
|
@ -1086,51 +1123,84 @@ public final class VoiceChatController: ViewController {
|
|||
|
||||
self.leaveDisposable.set((self.call.leave(terminateIfPossible: false)
|
||||
|> deliverOnMainQueue).start(completed: { [weak self] in
|
||||
self?.controller?.dismiss()
|
||||
self?.controller?.dismiss(closing: true)
|
||||
}))
|
||||
}
|
||||
|
||||
@objc func dimTapGesture(_ recognizer: UITapGestureRecognizer) {
|
||||
if case .ended = recognizer.state {
|
||||
self.controller?.dismiss()
|
||||
self.controller?.dismiss(closing: false)
|
||||
}
|
||||
}
|
||||
|
||||
private var actionButtonPressGestureStartTime: Double = 0.0
|
||||
private var pressTimer: SwiftSignalKit.Timer?
|
||||
private func startPressTimer() {
|
||||
self.pressTimer?.invalidate()
|
||||
let pressTimer = SwiftSignalKit.Timer(timeout: 0.2, repeat: false, completion: { [weak self] in
|
||||
self?.pressTimerFired()
|
||||
self?.pressTimer = nil
|
||||
}, queue: Queue.mainQueue())
|
||||
self.pressTimer = pressTimer
|
||||
pressTimer.start()
|
||||
}
|
||||
|
||||
private func stopPressTimer() {
|
||||
self.pressTimer?.invalidate()
|
||||
self.pressTimer = nil
|
||||
}
|
||||
|
||||
private func pressTimerFired() {
|
||||
guard let callState = self.callState else {
|
||||
return
|
||||
}
|
||||
if callState.muteState != nil {
|
||||
self.pushingToTalk = true
|
||||
self.call.setIsMuted(action: .muted(isPushToTalkActive: true))
|
||||
}
|
||||
|
||||
if let (layout, navigationHeight) = self.validLayout {
|
||||
self.containerLayoutUpdated(layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.3, curve: .spring))
|
||||
}
|
||||
|
||||
self.updateMembers(muteState: self.effectiveMuteState, callMembers: self.currentCallMembers ?? [], invitedPeers: self.currentInvitedPeers ?? [], speakingPeers: self.currentSpeakingPeers ?? Set())
|
||||
}
|
||||
|
||||
@objc private func actionButtonPressGesture(_ gestureRecognizer: UILongPressGestureRecognizer) {
|
||||
guard let callState = self.callState else {
|
||||
return
|
||||
}
|
||||
if let muteState = callState.muteState {
|
||||
if !muteState.canUnmute {
|
||||
if case .ended = gestureRecognizer.state {
|
||||
self.hapticFeedback.error()
|
||||
self.actionButton.layer.addShakeAnimation()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
switch gestureRecognizer.state {
|
||||
case .began:
|
||||
self.hapticFeedback.impact(.light)
|
||||
self.startPressTimer()
|
||||
|
||||
self.actionButtonPressGestureStartTime = CACurrentMediaTime()
|
||||
self.actionButton.pressing = true
|
||||
if callState.muteState != nil {
|
||||
self.pushingToTalk = true
|
||||
self.call.setIsMuted(action: .muted(isPushToTalkActive: true))
|
||||
}
|
||||
if let (layout, navigationHeight) = self.validLayout {
|
||||
self.containerLayoutUpdated(layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.3, curve: .spring))
|
||||
}
|
||||
self.updateMembers(muteState: self.effectiveMuteState, callMembers: self.currentCallMembers ?? [], invitedPeers: self.currentInvitedPeers ?? [], speakingPeers: self.currentSpeakingPeers ?? Set())
|
||||
case .ended, .cancelled:
|
||||
self.pushingToTalk = false
|
||||
self.actionButton.pressing = false
|
||||
let timestamp = CACurrentMediaTime()
|
||||
if timestamp - self.actionButtonPressGestureStartTime < 0.2 {
|
||||
|
||||
if self.pressTimer != nil {
|
||||
self.stopPressTimer()
|
||||
self.call.toggleIsMuted()
|
||||
} else {
|
||||
self.hapticFeedback.impact(.light)
|
||||
self.call.setIsMuted(action: .muted(isPushToTalkActive: false))
|
||||
}
|
||||
|
||||
self.itemInteraction?.updateAudioLevels([(self.context.account.peerId, 0.0)], reset: true)
|
||||
|
||||
if let (layout, navigationHeight) = self.validLayout {
|
||||
self.containerLayoutUpdated(layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.3, curve: .spring))
|
||||
}
|
||||
|
|
@ -1141,13 +1211,6 @@ public final class VoiceChatController: ViewController {
|
|||
}
|
||||
|
||||
@objc private func actionButtonPressed() {
|
||||
if let callState = self.callState, case .connected = callState.networkState, let muteState = callState.muteState, !muteState.canUnmute {
|
||||
self.hapticFeedback.error()
|
||||
self.actionButton.layer.addShakeAnimation()
|
||||
return
|
||||
}
|
||||
|
||||
self.call.toggleIsMuted()
|
||||
}
|
||||
|
||||
@objc private func audioOutputPressed() {
|
||||
|
|
@ -1230,20 +1293,48 @@ public final class VoiceChatController: ViewController {
|
|||
let panelOffset = max(layoutTopInset, rawPanelOffset)
|
||||
let topPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: panelOffset), size: CGSize(width: validLayout.size.width, height: topPanelHeight))
|
||||
|
||||
let previousFrame = self.topPanelNode.frame
|
||||
if !topPanelFrame.equalTo(previousFrame) {
|
||||
let previousTopPanelFrame = self.topPanelNode.frame
|
||||
if !topPanelFrame.equalTo(previousTopPanelFrame) {
|
||||
self.topPanelNode.frame = topPanelFrame
|
||||
|
||||
let positionDelta = CGPoint(x: topPanelFrame.minX - previousFrame.minX, y: topPanelFrame.minY - previousFrame.minY)
|
||||
let positionDelta = CGPoint(x: topPanelFrame.minX - previousTopPanelFrame.minX, y: topPanelFrame.minY - previousTopPanelFrame.minY)
|
||||
transition.animateOffsetAdditive(node: self.topPanelNode, offset: positionDelta.y)
|
||||
}
|
||||
|
||||
self.topPanelBackgroundNode.frame = CGRect(x: 0.0, y: topPanelHeight - 24.0, width: validLayout.size.width, height: 24.0)
|
||||
self.topPanelEdgeNode.frame = CGRect(x: 0.0, y: 0.0, width: validLayout.size.width, height: topPanelHeight)
|
||||
|
||||
let backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: topPanelFrame.maxY), size: CGSize(width: validLayout.size.width, height: validLayout.size.height))
|
||||
|
||||
let sideInset: CGFloat = 16.0
|
||||
let leftBorderFrame = CGRect(origin: CGPoint(x: 0.0, y: topPanelFrame.maxY - 16.0), size: CGSize(width: sideInset, height: validLayout.size.height))
|
||||
let rightBorderFrame = CGRect(origin: CGPoint(x: validLayout.size.width - sideInset, y: topPanelFrame.maxY - 16.0), size: CGSize(width: sideInset, height: validLayout.size.height))
|
||||
|
||||
var bottomEdge: CGFloat = 0.0
|
||||
self.listNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? ListViewItemNode {
|
||||
let convertedFrame = self.listNode.view.convert(itemNode.apparentFrame, to: self.view)
|
||||
if convertedFrame.maxY > bottomEdge {
|
||||
bottomEdge = convertedFrame.maxY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var bottomOffset: CGFloat = 0.0
|
||||
if bottomEdge < self.listNode.frame.maxY {
|
||||
bottomOffset = bottomEdge - self.listNode.frame.maxY
|
||||
}
|
||||
|
||||
let bottomCornersFrame = CGRect(origin: CGPoint(x: sideInset, y: -50.0 + bottomOffset), size: CGSize(width: validLayout.size.width - sideInset * 2.0, height: 50.0))
|
||||
let previousBottomCornersFrame = self.bottomCornersNode.frame
|
||||
if !bottomCornersFrame.equalTo(previousBottomCornersFrame) {
|
||||
self.bottomCornersNode.frame = bottomCornersFrame
|
||||
self.bottomPanelBackgroundNode.frame = CGRect(x: 0.0, y: bottomOffset, width: validLayout.size.width, height: 2000.0)
|
||||
|
||||
let positionDelta = CGPoint(x: bottomCornersFrame.minX - previousBottomCornersFrame.minX, y: bottomCornersFrame.minY - previousBottomCornersFrame.minY)
|
||||
transition.animateOffsetAdditive(node: self.bottomCornersNode, offset: positionDelta.y)
|
||||
transition.animateOffsetAdditive(node: self.bottomPanelBackgroundNode, offset: positionDelta.y)
|
||||
}
|
||||
|
||||
let previousBackgroundFrame = self.backgroundNode.frame
|
||||
let previousLeftBorderFrame = self.leftBorderNode.frame
|
||||
let previousRightBorderFrame = self.rightBorderNode.frame
|
||||
|
|
@ -1268,7 +1359,7 @@ public final class VoiceChatController: ViewController {
|
|||
|
||||
var isFullscreen = false
|
||||
func updateColors(fullscreen: Bool) {
|
||||
guard self.isFullscreen != fullscreen else {
|
||||
guard self.isFullscreen != fullscreen, let (layout, _) = self.validLayout else {
|
||||
return
|
||||
}
|
||||
self.isFullscreen = fullscreen
|
||||
|
|
@ -1277,10 +1368,12 @@ public final class VoiceChatController: ViewController {
|
|||
|
||||
let transition: ContainedViewLayoutTransition = .animated(duration: 0.3, curve: .linear)
|
||||
|
||||
// transition.updateCornerRadius(node: self.topPanelEdgeNode, cornerRadius: fullscreen ? layout.deviceMetrics.screenCornerRadius : 12.0)
|
||||
transition.updateBackgroundColor(node: self.dimNode, color: fullscreen ? fullscreenBackgroundColor : dimColor)
|
||||
transition.updateBackgroundColor(node: self.topPanelBackgroundNode, color: fullscreen ? fullscreenBackgroundColor : panelBackgroundColor)
|
||||
transition.updateBackgroundColor(node: self.topPanelEdgeNode, color: fullscreen ? fullscreenBackgroundColor : panelBackgroundColor)
|
||||
transition.updateBackgroundColor(node: self.backgroundNode, color: fullscreen ? panelBackgroundColor : secondaryPanelBackgroundColor)
|
||||
transition.updateBackgroundColor(node: self.topPanelNode, color: fullscreen ? fullscreenBackgroundColor : panelBackgroundColor)
|
||||
transition.updateBackgroundColor(node: self.bottomPanelNode, color: fullscreen ? fullscreenBackgroundColor : panelBackgroundColor)
|
||||
transition.updateBackgroundColor(node: self.bottomPanelBackgroundNode, color: fullscreen ? fullscreenBackgroundColor : panelBackgroundColor)
|
||||
transition.updateBackgroundColor(node: self.leftBorderNode, color: fullscreen ? fullscreenBackgroundColor : panelBackgroundColor)
|
||||
transition.updateBackgroundColor(node: self.rightBorderNode, color: fullscreen ? fullscreenBackgroundColor : panelBackgroundColor)
|
||||
transition.updateBackgroundColor(node: self.rightBorderNode, color: fullscreen ? fullscreenBackgroundColor : panelBackgroundColor)
|
||||
|
|
@ -1296,8 +1389,8 @@ public final class VoiceChatController: ViewController {
|
|||
self.topCornersNode.image = cornersImage(top: true, bottom: false, dark: fullscreen)
|
||||
|
||||
if let snapshotView = self.bottomCornersNode.view.snapshotContentTree() {
|
||||
snapshotView.frame = self.bottomCornersNode.frame
|
||||
self.bottomPanelNode.view.addSubview(snapshotView)
|
||||
snapshotView.frame = self.bottomCornersNode.bounds
|
||||
self.bottomCornersNode.view.addSubview(snapshotView)
|
||||
|
||||
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
||||
snapshotView?.removeFromSuperview()
|
||||
|
|
@ -1307,100 +1400,36 @@ public final class VoiceChatController: ViewController {
|
|||
|
||||
self.optionsButton.setImage(optionsButtonImage(dark: fullscreen), animated: transition.isAnimated)
|
||||
self.closeButton.setImage(closeButtonImage(dark: fullscreen), animated: transition.isAnimated)
|
||||
|
||||
self.updateTitle(transition: transition)
|
||||
}
|
||||
|
||||
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
let isFirstTime = self.validLayout == nil
|
||||
self.validLayout = (layout, navigationHeight)
|
||||
|
||||
transition.updateFrame(view: self.titleView, frame: CGRect(origin: CGPoint(x: 0.0, y: 10.0), size: CGSize(width: layout.size.width, height: 44.0)))
|
||||
transition.updateFrame(node: self.optionsButton, frame: CGRect(origin: CGPoint(x: 20.0, y: 18.0), size: CGSize(width: 28.0, height: 28.0)))
|
||||
transition.updateFrame(node: self.closeButton, frame: CGRect(origin: CGPoint(x: layout.size.width - 20.0 - 28.0, y: 18.0), size: CGSize(width: 28.0, height: 28.0)))
|
||||
|
||||
transition.updateFrame(node: self.dimNode, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
|
||||
transition.updateFrame(node: self.contentContainer, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
|
||||
let bottomAreaHeight: CGFloat = 268.0
|
||||
let layoutTopInset: CGFloat = max(layout.statusBarHeight ?? 0.0, layout.safeInsets.top)
|
||||
|
||||
let sideInset: CGFloat = 16.0
|
||||
var insets = UIEdgeInsets()
|
||||
insets.left = layout.safeInsets.left + sideInset
|
||||
insets.right = layout.safeInsets.right + sideInset
|
||||
|
||||
let bottomPanelHeight = bottomAreaHeight + layout.intrinsicInsets.bottom
|
||||
let listTopInset = layoutTopInset + 63.0
|
||||
let listSize = CGSize(width: layout.size.width, height: layout.size.height - listTopInset - bottomPanelHeight)
|
||||
|
||||
insets.top = max(0.0, listSize.height - 44.0 - floor(56.0 * 3.5))
|
||||
|
||||
transition.updateFrame(node: self.listNode, frame: CGRect(origin: CGPoint(x: 0.0, y: listTopInset), size: listSize))
|
||||
|
||||
let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition)
|
||||
let updateSizeAndInsets = ListViewUpdateSizeAndInsets(size: listSize, insets: insets, duration: duration, curve: curve)
|
||||
|
||||
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: nil, updateSizeAndInsets: updateSizeAndInsets, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
|
||||
|
||||
transition.updateFrame(node: self.topCornersNode, frame: CGRect(origin: CGPoint(x: sideInset, y: 63.0), size: CGSize(width: layout.size.width - sideInset * 2.0, height: 50.0)))
|
||||
|
||||
let bottomPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - bottomPanelHeight), size: CGSize(width: layout.size.width, height: bottomPanelHeight))
|
||||
transition.updateFrame(node: self.bottomPanelNode, frame: bottomPanelFrame)
|
||||
transition.updateFrame(node: self.bottomCornersNode, frame: CGRect(origin: CGPoint(x: sideInset, y: -50.0), size: CGSize(width: layout.size.width - sideInset * 2.0, height: 50.0)))
|
||||
|
||||
let sideButtonSize = CGSize(width: 60.0, height: 60.0)
|
||||
let centralButtonSize = CGSize(width: 440.0, height: 440.0)
|
||||
|
||||
let actionButtonFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - centralButtonSize.width) / 2.0), y: floorToScreenPixels((bottomAreaHeight - centralButtonSize.height) / 2.0)), size: centralButtonSize)
|
||||
|
||||
let actionButtonState: VoiceChatActionButton.State
|
||||
let actionButtonTitle: String
|
||||
let actionButtonSubtitle: String
|
||||
let audioButtonAppearance: CallControllerButtonItemNode.Content.Appearance
|
||||
var actionButtonEnabled = true
|
||||
if let callState = self.callState {
|
||||
switch callState.networkState {
|
||||
case .connecting:
|
||||
actionButtonState = .connecting
|
||||
actionButtonTitle = self.presentationData.strings.VoiceChat_Connecting
|
||||
actionButtonSubtitle = ""
|
||||
audioButtonAppearance = .color(.custom(0x2c2c2e))
|
||||
actionButtonEnabled = false
|
||||
case .connected:
|
||||
if let muteState = callState.muteState, !self.pushingToTalk {
|
||||
if muteState.canUnmute {
|
||||
actionButtonState = .active(state: .muted)
|
||||
|
||||
actionButtonTitle = self.presentationData.strings.VoiceChat_Unmute
|
||||
actionButtonSubtitle = self.presentationData.strings.VoiceChat_UnmuteHelp
|
||||
audioButtonAppearance = .color(.custom(0x00274d))
|
||||
} else {
|
||||
actionButtonState = .active(state: .cantSpeak)
|
||||
|
||||
actionButtonTitle = self.presentationData.strings.VoiceChat_Muted
|
||||
actionButtonSubtitle = self.presentationData.strings.VoiceChat_MutedHelp
|
||||
audioButtonAppearance = .color(.custom(0x00274d))
|
||||
private func updateTitle(transition: ContainedViewLayoutTransition) {
|
||||
guard let (layout, _) = self.validLayout else {
|
||||
return
|
||||
}
|
||||
var title = self.currentTitle
|
||||
if !self.isFullscreen {
|
||||
if let navigationController = self.controller?.navigationController as? NavigationController {
|
||||
for controller in navigationController.viewControllers.reversed() {
|
||||
if let controller = controller as? ChatController, case let .peer(peerId) = controller.chatLocation, peerId == self.call.peerId {
|
||||
title = self.presentationData.strings.VoiceChat_Title
|
||||
}
|
||||
} else {
|
||||
actionButtonState = .active(state: .on)
|
||||
|
||||
actionButtonTitle = self.pushingToTalk ? self.presentationData.strings.VoiceChat_Live : self.presentationData.strings.VoiceChat_Mute
|
||||
actionButtonSubtitle = ""
|
||||
audioButtonAppearance = .color(.custom(0x005720))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
actionButtonState = .connecting
|
||||
actionButtonTitle = self.presentationData.strings.VoiceChat_Connecting
|
||||
actionButtonSubtitle = ""
|
||||
audioButtonAppearance = .color(.custom(0x1c1c1e))
|
||||
actionButtonEnabled = false
|
||||
}
|
||||
|
||||
self.actionButton.isUserInteractionEnabled = actionButtonEnabled
|
||||
self.actionButton.update(size: centralButtonSize, buttonSize: CGSize(width: 144.0, height: 144.0), state: actionButtonState, title: actionButtonTitle, subtitle: actionButtonSubtitle, dark: false, small: layout.size.width < 330.0, animated: true)
|
||||
transition.updateFrame(node: self.actionButton, frame: actionButtonFrame)
|
||||
|
||||
self.titleNode.update(size: CGSize(width: layout.size.width, height: 44.0), title: title, subtitle: self.currentSubtitle, transition: transition)
|
||||
}
|
||||
|
||||
private func updateButtons(transition: ContainedViewLayoutTransition) {
|
||||
let audioButtonAppearance: CallControllerButtonItemNode.Content.Appearance
|
||||
if let color = self.currentAudioButtonColor {
|
||||
audioButtonAppearance = .color(.custom(color.rgb))
|
||||
} else {
|
||||
audioButtonAppearance = .color(.custom(self.isFullscreen ? 0x1c1c1e : 0x2c2c2e))
|
||||
}
|
||||
|
||||
var audioMode: CallControllerButtonsSpeakerMode = .none
|
||||
//var hasAudioRouteMenu: Bool = false
|
||||
if let (availableOutputs, maybeCurrentOutput) = self.audioOutputState, let currentOutput = maybeCurrentOutput {
|
||||
|
|
@ -1448,9 +1477,102 @@ public final class VoiceChatController: ViewController {
|
|||
}
|
||||
}
|
||||
|
||||
let sideButtonSize = CGSize(width: 60.0, height: 60.0)
|
||||
self.audioOutputNode.update(size: sideButtonSize, content: CallControllerButtonItemNode.Content(appearance: soundAppearance, image: soundImage), text: self.presentationData.strings.VoiceChat_Audio, transition: .animated(duration: 0.3, curve: .linear))
|
||||
|
||||
self.leaveNode.update(size: sideButtonSize, content: CallControllerButtonItemNode.Content(appearance: .color(.custom(0x602522)), image: .end), text: self.presentationData.strings.VoiceChat_Leave, transition: .immediate)
|
||||
}
|
||||
|
||||
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
let isFirstTime = self.validLayout == nil
|
||||
self.validLayout = (layout, navigationHeight)
|
||||
|
||||
self.updateTitle(transition: transition)
|
||||
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 10.0), size: CGSize(width: layout.size.width, height: 44.0)))
|
||||
transition.updateFrame(node: self.optionsButton, frame: CGRect(origin: CGPoint(x: 20.0, y: 18.0), size: CGSize(width: 28.0, height: 28.0)))
|
||||
transition.updateFrame(node: self.closeButton, frame: CGRect(origin: CGPoint(x: layout.size.width - 20.0 - 28.0, y: 18.0), size: CGSize(width: 28.0, height: 28.0)))
|
||||
|
||||
transition.updateFrame(node: self.dimNode, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
|
||||
transition.updateFrame(node: self.contentContainer, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
|
||||
let bottomAreaHeight: CGFloat = 268.0
|
||||
let layoutTopInset: CGFloat = max(layout.statusBarHeight ?? 0.0, layout.safeInsets.top)
|
||||
|
||||
let sideInset: CGFloat = 16.0
|
||||
var insets = UIEdgeInsets()
|
||||
insets.left = layout.safeInsets.left + sideInset
|
||||
insets.right = layout.safeInsets.right + sideInset
|
||||
|
||||
let bottomPanelHeight = bottomAreaHeight + layout.intrinsicInsets.bottom
|
||||
let listTopInset = layoutTopInset + 63.0
|
||||
let listSize = CGSize(width: layout.size.width, height: layout.size.height - listTopInset - bottomPanelHeight)
|
||||
|
||||
insets.top = max(0.0, listSize.height - 44.0 - floor(56.0 * 3.5))
|
||||
|
||||
transition.updateFrame(node: self.listNode, frame: CGRect(origin: CGPoint(x: 0.0, y: listTopInset), size: listSize))
|
||||
|
||||
let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition)
|
||||
let updateSizeAndInsets = ListViewUpdateSizeAndInsets(size: listSize, insets: insets, duration: duration, curve: curve)
|
||||
|
||||
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: nil, updateSizeAndInsets: updateSizeAndInsets, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
|
||||
|
||||
transition.updateFrame(node: self.topCornersNode, frame: CGRect(origin: CGPoint(x: sideInset, y: 63.0), size: CGSize(width: layout.size.width - sideInset * 2.0, height: 50.0)))
|
||||
|
||||
let bottomPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - bottomPanelHeight), size: CGSize(width: layout.size.width, height: bottomPanelHeight))
|
||||
transition.updateFrame(node: self.bottomPanelNode, frame: bottomPanelFrame)
|
||||
|
||||
let sideButtonSize = CGSize(width: 60.0, height: 60.0)
|
||||
let centralButtonSize = CGSize(width: 440.0, height: 440.0)
|
||||
|
||||
let actionButtonFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - centralButtonSize.width) / 2.0), y: floorToScreenPixels((bottomAreaHeight - centralButtonSize.height) / 2.0)), size: centralButtonSize)
|
||||
|
||||
let actionButtonState: VoiceChatActionButton.State
|
||||
let actionButtonTitle: String
|
||||
let actionButtonSubtitle: String
|
||||
var actionButtonEnabled = true
|
||||
if let callState = self.callState {
|
||||
switch callState.networkState {
|
||||
case .connecting:
|
||||
actionButtonState = .connecting
|
||||
actionButtonTitle = self.presentationData.strings.VoiceChat_Connecting
|
||||
actionButtonSubtitle = ""
|
||||
actionButtonEnabled = false
|
||||
case .connected:
|
||||
if let muteState = callState.muteState, !self.pushingToTalk {
|
||||
if muteState.canUnmute {
|
||||
actionButtonState = .active(state: .muted)
|
||||
|
||||
actionButtonTitle = self.presentationData.strings.VoiceChat_Unmute
|
||||
actionButtonSubtitle = self.presentationData.strings.VoiceChat_UnmuteHelp
|
||||
} else {
|
||||
actionButtonState = .active(state: .cantSpeak)
|
||||
|
||||
actionButtonTitle = self.presentationData.strings.VoiceChat_Muted
|
||||
actionButtonSubtitle = self.presentationData.strings.VoiceChat_MutedHelp
|
||||
}
|
||||
} else {
|
||||
actionButtonState = .active(state: .on)
|
||||
|
||||
actionButtonTitle = self.pushingToTalk ? self.presentationData.strings.VoiceChat_Live : self.presentationData.strings.VoiceChat_Mute
|
||||
actionButtonSubtitle = ""
|
||||
}
|
||||
}
|
||||
} else {
|
||||
actionButtonState = .connecting
|
||||
actionButtonTitle = self.presentationData.strings.VoiceChat_Connecting
|
||||
actionButtonSubtitle = ""
|
||||
actionButtonEnabled = false
|
||||
}
|
||||
|
||||
self.actionButton.isUserInteractionEnabled = actionButtonEnabled
|
||||
self.actionButton.update(size: centralButtonSize, buttonSize: CGSize(width: 144.0, height: 144.0), state: actionButtonState, title: actionButtonTitle, subtitle: actionButtonSubtitle, dark: self.isFullscreen, small: layout.size.width < 330.0, animated: true)
|
||||
|
||||
if self.actionButton.supernode === self.bottomPanelNode {
|
||||
transition.updateFrame(node: self.actionButton, frame: actionButtonFrame)
|
||||
}
|
||||
|
||||
self.updateButtons(transition: transition)
|
||||
|
||||
let sideButtonMinimalInset: CGFloat = 16.0
|
||||
let sideButtonOffset = min(36.0, floor((((layout.size.width - 144.0) / 2.0) - sideButtonSize.width) / 2.0))
|
||||
|
|
@ -1670,7 +1792,7 @@ public final class VoiceChatController: ViewController {
|
|||
let velocity = recognizer.velocity(in: self.contentContainer.view)
|
||||
|
||||
if (bounds.minY < -60.0 || velocity.y > 300.0) {
|
||||
self.controller?.dismiss()
|
||||
self.controller?.dismiss(closing: false)
|
||||
} else {
|
||||
var bounds = self.contentContainer.bounds
|
||||
let previousBounds = bounds
|
||||
|
|
@ -1724,6 +1846,7 @@ public final class VoiceChatController: ViewController {
|
|||
|
||||
public var onViewDidAppear: (() -> Void)?
|
||||
public var onViewDidDisappear: (() -> Void)?
|
||||
private var reclaimActionButton: (() -> Void)?
|
||||
|
||||
private var didAppearOnce: Bool = false
|
||||
private var isDismissed: Bool = false
|
||||
|
|
@ -1734,6 +1857,10 @@ public final class VoiceChatController: ViewController {
|
|||
|
||||
private let idleTimerExtensionDisposable = MetaDisposable()
|
||||
|
||||
private var currentOverlayController: VoiceChatOverlayController?
|
||||
|
||||
private var validLayout: ContainerViewLayout?
|
||||
|
||||
public init(sharedContext: SharedAccountContext, accountContext: AccountContext, call: PresentationGroupCall) {
|
||||
self.sharedContext = sharedContext
|
||||
self.call = call
|
||||
|
|
@ -1766,6 +1893,10 @@ public final class VoiceChatController: ViewController {
|
|||
|
||||
deinit {
|
||||
self.idleTimerExtensionDisposable.dispose()
|
||||
|
||||
if let currentOverlayController = self.currentOverlayController {
|
||||
currentOverlayController.animateOut(reclaim: false, completion: {})
|
||||
}
|
||||
}
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
|
|
@ -1782,6 +1913,7 @@ public final class VoiceChatController: ViewController {
|
|||
if !self.didAppearOnce {
|
||||
self.didAppearOnce = true
|
||||
|
||||
self.reclaimActionButton?()
|
||||
self.controllerNode.animateIn()
|
||||
|
||||
self.idleTimerExtensionDisposable.set(self.sharedContext.applicationBindings.pushIdleTimerExtension())
|
||||
|
|
@ -1796,16 +1928,41 @@ public final class VoiceChatController: ViewController {
|
|||
super.viewDidDisappear(animated)
|
||||
|
||||
self.idleTimerExtensionDisposable.set(nil)
|
||||
self.onViewDidDisappear?()
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.onViewDidDisappear?()
|
||||
}
|
||||
}
|
||||
|
||||
func dismissInteractively(completion: (() -> Void)? = nil) {
|
||||
if !self.isDismissed {
|
||||
self.isDismissed = true
|
||||
self.didAppearOnce = false
|
||||
|
||||
public func dismiss(closing: Bool) {
|
||||
if closing {
|
||||
self.dismiss()
|
||||
} else {
|
||||
let overlayController = VoiceChatOverlayController(actionButton: self.controllerNode.actionButton)
|
||||
if let navigationController = self.navigationController as? NavigationController {
|
||||
navigationController.presentOverlay(controller: overlayController, inGlobal: true, blockInteraction: false)
|
||||
}
|
||||
self.sharedContext.presentGlobalController(overlayController, nil)
|
||||
|
||||
completion?()
|
||||
self.dismiss(animated: false)
|
||||
self.currentOverlayController = overlayController
|
||||
|
||||
self.reclaimActionButton = { [weak self, weak overlayController] in
|
||||
if let strongSelf = self {
|
||||
let actionButton = strongSelf.controllerNode.actionButton
|
||||
overlayController?.animateOut(reclaim: true, completion: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controllerNode.bottomPanelNode.addSubnode(actionButton)
|
||||
if let validLayout = strongSelf.validLayout {
|
||||
strongSelf.containerLayoutUpdated(validLayout, transition: .immediate)
|
||||
}
|
||||
}
|
||||
})
|
||||
strongSelf.currentOverlayController = nil
|
||||
strongSelf.reclaimActionButton = nil
|
||||
}
|
||||
}
|
||||
|
||||
self.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1827,7 +1984,7 @@ public final class VoiceChatController: ViewController {
|
|||
|
||||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
super.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
self.validLayout = layout
|
||||
self.controllerNode.containerLayoutUpdated(layout, navigationHeight: self.navigationHeight, transition: transition)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,161 @@
|
|||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import AsyncDisplayKit
|
||||
import SwiftSignalKit
|
||||
import TelegramPresentationData
|
||||
import TelegramUIPreferences
|
||||
import TelegramVoip
|
||||
import TelegramAudio
|
||||
import AccountContext
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import SyncCore
|
||||
import AppBundle
|
||||
import ContextUI
|
||||
import PresentationDataUtils
|
||||
|
||||
final class VoiceChatOverlayController: ViewController {
|
||||
private final class Node: ViewControllerTracingNode, UIGestureRecognizerDelegate {
|
||||
private weak var controller: VoiceChatOverlayController?
|
||||
|
||||
private var validLayout: ContainerViewLayout?
|
||||
|
||||
init(controller: VoiceChatOverlayController) {
|
||||
self.controller = controller
|
||||
}
|
||||
|
||||
func animateIn(from: CGRect) {
|
||||
guard let actionButton = self.controller?.actionButton else {
|
||||
return
|
||||
}
|
||||
|
||||
let targetPosition = actionButton.position
|
||||
let sourcePoint = CGPoint(x: from.midX, y: from.midY)
|
||||
let midPoint = CGPoint(x: (sourcePoint.x + targetPosition.x) / 2.0, y: sourcePoint.y + 120.0)
|
||||
|
||||
let x1 = sourcePoint.x
|
||||
let y1 = sourcePoint.y
|
||||
let x2 = midPoint.x
|
||||
let y2 = midPoint.y
|
||||
let x3 = targetPosition.x
|
||||
let y3 = targetPosition.y
|
||||
|
||||
let a = (x3 * (y2 - y1) + x2 * (y1 - y3) + x1 * (y3 - y2)) / ((x1 - x2) * (x1 - x3) * (x2 - x3))
|
||||
let b = (x1 * x1 * (y2 - y3) + x3 * x3 * (y1 - y2) + x2 * x2 * (y3 - y1)) / ((x1 - x2) * (x1 - x3) * (x2 - x3))
|
||||
let c = (x2 * x2 * (x3 * y1 - x1 * y3) + x2 * (x1 * x1 * y3 - x3 * x3 * y1) + x1 * x3 * (x3 - x1) * y2) / ((x1 - x2) * (x1 - x3) * (x2 - x3))
|
||||
|
||||
var keyframes: [AnyObject] = []
|
||||
for i in 0 ..< 10 {
|
||||
let k = CGFloat(i) / CGFloat(10 - 1)
|
||||
let x = sourcePoint.x * (1.0 - k) + targetPosition.x * k
|
||||
let y = a * x * x + b * x + c
|
||||
keyframes.append(NSValue(cgPoint: CGPoint(x: x, y: y)))
|
||||
}
|
||||
|
||||
actionButton.layer.animateKeyframes(values: keyframes, duration: 0.3, keyPath: "position", timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, completion: { [weak self] _ in
|
||||
})
|
||||
}
|
||||
|
||||
func animateOut(reclaim: Bool, completion: @escaping () -> Void) {
|
||||
guard let actionButton = self.controller?.actionButton, let layout = self.validLayout else {
|
||||
return
|
||||
}
|
||||
|
||||
if reclaim {
|
||||
let targetPosition = CGPoint(x: layout.size.width / 2.0, y: layout.size.height - layout.intrinsicInsets.bottom - 268.0 / 2.0)
|
||||
let sourcePoint = actionButton.position
|
||||
let midPoint = CGPoint(x: (sourcePoint.x + targetPosition.x) / 2.0 - 20.0, y: sourcePoint.y + 10.0)
|
||||
|
||||
let x1 = sourcePoint.x
|
||||
let y1 = sourcePoint.y
|
||||
let x2 = midPoint.x
|
||||
let y2 = midPoint.y
|
||||
let x3 = targetPosition.x
|
||||
let y3 = targetPosition.y
|
||||
|
||||
let a = (x3 * (y2 - y1) + x2 * (y1 - y3) + x1 * (y3 - y2)) / ((x1 - x2) * (x1 - x3) * (x2 - x3))
|
||||
let b = (x1 * x1 * (y2 - y3) + x3 * x3 * (y1 - y2) + x2 * x2 * (y3 - y1)) / ((x1 - x2) * (x1 - x3) * (x2 - x3))
|
||||
let c = (x2 * x2 * (x3 * y1 - x1 * y3) + x2 * (x1 * x1 * y3 - x3 * x3 * y1) + x1 * x3 * (x3 - x1) * y2) / ((x1 - x2) * (x1 - x3) * (x2 - x3))
|
||||
|
||||
var keyframes: [AnyObject] = []
|
||||
for i in 0 ..< 10 {
|
||||
let k = CGFloat(i) / CGFloat(10 - 1)
|
||||
let x = sourcePoint.x * (1.0 - k) + targetPosition.x * k
|
||||
let y = a * x * x + b * x + c
|
||||
keyframes.append(NSValue(cgPoint: CGPoint(x: x, y: y)))
|
||||
}
|
||||
|
||||
actionButton.update(snap: false)
|
||||
actionButton.position = targetPosition
|
||||
actionButton.layer.animateKeyframes(values: keyframes, duration: 0.4, keyPath: "position", timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, completion: { [weak self] _ in
|
||||
completion()
|
||||
self?.controller?.dismiss()
|
||||
})
|
||||
} else {
|
||||
actionButton.layer.animateScale(from: 1.0, to: 0.001, duration: 0.2, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, completion: { [weak self, weak actionButton] _ in
|
||||
actionButton?.removeFromSupernode()
|
||||
self?.controller?.dismiss()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
if let actionButton = self.controller?.actionButton, actionButton.frame.contains(point) {
|
||||
return actionButton.hitTest(self.view.convert(point, to: actionButton.view), with: event)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
self.validLayout = layout
|
||||
|
||||
if let actionButton = self.controller?.actionButton {
|
||||
let convertedRect = actionButton.view.convert(actionButton.bounds, to: self.view)
|
||||
let insets = layout.insets(options: [.input])
|
||||
actionButton.position = CGPoint(x: layout.size.width - layout.safeInsets.right - 21.0, y: layout.size.height - insets.bottom - 22.0)
|
||||
if actionButton.supernode !== self {
|
||||
self.addSubnode(actionButton)
|
||||
|
||||
actionButton.update(snap: true)
|
||||
self.animateIn(from: convertedRect)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private weak var actionButton: VoiceChatActionButton?
|
||||
|
||||
private var controllerNode: Node {
|
||||
return self.displayNode as! Node
|
||||
}
|
||||
|
||||
init(actionButton: VoiceChatActionButton) {
|
||||
self.actionButton = actionButton
|
||||
|
||||
super.init(navigationBarPresentationData: nil)
|
||||
|
||||
self.statusBar.statusBarStyle = .Ignore
|
||||
self.additionalSideInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 75.0)
|
||||
}
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
self.displayNode = Node(controller: self)
|
||||
self.displayNodeDidLoad()
|
||||
}
|
||||
|
||||
func animateOut(reclaim: Bool, completion: @escaping () -> Void) {
|
||||
self.controllerNode.animateOut(reclaim: reclaim, completion: completion)
|
||||
}
|
||||
|
||||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
super.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
self.controllerNode.containerLayoutUpdated(layout, transition: transition)
|
||||
}
|
||||
}
|
||||
|
|
@ -464,8 +464,8 @@ public class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
|
|||
strongSelf.accessibilityValue = combinedValueString
|
||||
|
||||
if let _ = updatedTheme {
|
||||
strongSelf.topStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.topStripeNode.backgroundColor = UIColor(rgb: 0xffffff, alpha: 0.08)
|
||||
strongSelf.bottomStripeNode.backgroundColor = UIColor(rgb: 0xffffff, alpha: 0.08)
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
}
|
||||
|
||||
|
|
@ -531,7 +531,7 @@ public class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
|
|||
let avatarFrame = CGRect(origin: CGPoint(x: params.leftInset + 15.0, y: floorToScreenPixels((layout.contentSize.height - avatarSize) / 2.0)), size: CGSize(width: avatarSize, height: avatarSize))
|
||||
transition.updateFrameAsPositionAndBounds(node: strongSelf.avatarNode, frame: avatarFrame)
|
||||
|
||||
let blobFrame = avatarFrame.insetBy(dx: -12.0, dy: -12.0)
|
||||
let blobFrame = avatarFrame.insetBy(dx: -14.0, dy: -14.0)
|
||||
if let getAudioLevel = item.getAudioLevel {
|
||||
if !strongSelf.didSetupAudioLevel || currentItem?.peer.id != item.peer.id {
|
||||
strongSelf.audioLevelView?.frame = blobFrame
|
||||
|
|
@ -545,10 +545,10 @@ public class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
|
|||
if strongSelf.audioLevelView == nil, value > 0.0 {
|
||||
let audioLevelView = VoiceBlobView(
|
||||
frame: blobFrame,
|
||||
maxLevel: 0.3,
|
||||
maxLevel: 1.5,
|
||||
smallBlobRange: (0, 0),
|
||||
mediumBlobRange: (0.7, 0.8),
|
||||
bigBlobRange: (0.8, 0.9)
|
||||
mediumBlobRange: (0.69, 0.87),
|
||||
bigBlobRange: (0.71, 1.0)
|
||||
)
|
||||
|
||||
let maskRect = CGRect(origin: .zero, size: blobFrame.size)
|
||||
|
|
@ -556,7 +556,7 @@ public class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
|
|||
playbackMaskLayer.frame = maskRect
|
||||
playbackMaskLayer.fillRule = .evenOdd
|
||||
let maskPath = UIBezierPath()
|
||||
maskPath.append(UIBezierPath(roundedRect: maskRect.insetBy(dx: 12, dy: 12), cornerRadius: 22))
|
||||
maskPath.append(UIBezierPath(roundedRect: maskRect.insetBy(dx: 14, dy: 14), cornerRadius: 22))
|
||||
maskPath.append(UIBezierPath(rect: maskRect))
|
||||
playbackMaskLayer.path = maskPath.cgPath
|
||||
audioLevelView.layer.mask = playbackMaskLayer
|
||||
|
|
@ -568,18 +568,18 @@ public class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
|
|||
|
||||
let level = min(1.0, max(0.0, CGFloat(value)))
|
||||
if let audioLevelView = strongSelf.audioLevelView {
|
||||
audioLevelView.updateLevel(CGFloat(value) * 2.0)
|
||||
audioLevelView.updateLevel(CGFloat(value))
|
||||
|
||||
let avatarScale: CGFloat
|
||||
if value > 0.0 {
|
||||
audioLevelView.startAnimating()
|
||||
avatarScale = 1.03 + level * 0.07
|
||||
avatarScale = 1.03 + level * 0.13
|
||||
} else {
|
||||
audioLevelView.stopAnimating(duration: 0.5)
|
||||
avatarScale = 1.0
|
||||
}
|
||||
|
||||
let transition: ContainedViewLayoutTransition = .animated(duration: 0.2, curve: .easeInOut)
|
||||
let transition: ContainedViewLayoutTransition = .animated(duration: 0.15, curve: .easeInOut)
|
||||
transition.updateTransformScale(node: strongSelf.avatarNode, scale: avatarScale, beginWithCurrentState: true)
|
||||
}
|
||||
}))
|
||||
|
|
|
|||
|
|
@ -412,7 +412,9 @@ public func makeDefaultDarkPresentationTheme(extendingThemeReference: Presentati
|
|||
mediaOverlayControlColors: PresentationThemeFillForeground(fillColor: UIColor(rgb: 0x000000, alpha: 0.6), foregroundColor: UIColor(rgb: 0xffffff)),
|
||||
selectionControlColors: PresentationThemeFillStrokeForeground(fillColor: UIColor(rgb: 0xffffff), strokeColor: UIColor(rgb: 0xffffff), foregroundColor: UIColor(rgb: 0x000000)),
|
||||
deliveryFailedColors: PresentationThemeFillForeground(fillColor: UIColor(rgb: 0xeb5545), foregroundColor: UIColor(rgb: 0xffffff)),
|
||||
mediaHighlightOverlayColor: UIColor(white: 1.0, alpha: 0.6)
|
||||
mediaHighlightOverlayColor: UIColor(white: 1.0, alpha: 0.6),
|
||||
stickerPlaceholderColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)),
|
||||
stickerPlaceholderShimmerColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5))
|
||||
)
|
||||
|
||||
let serviceMessage = PresentationThemeServiceMessage(
|
||||
|
|
|
|||
|
|
@ -667,7 +667,9 @@ public func makeDefaultDarkTintedPresentationTheme(extendingThemeReference: Pres
|
|||
mediaOverlayControlColors: PresentationThemeFillForeground(fillColor: UIColor(rgb: 0x000000, alpha: 0.6), foregroundColor: .white),
|
||||
selectionControlColors: PresentationThemeFillStrokeForeground(fillColor: accentColor, strokeColor: .white, foregroundColor: .white),
|
||||
deliveryFailedColors: PresentationThemeFillForeground(fillColor: UIColor(rgb: 0xff6767), foregroundColor: .white),
|
||||
mediaHighlightOverlayColor: UIColor(white: 1.0, alpha: 0.6)
|
||||
mediaHighlightOverlayColor: UIColor(white: 1.0, alpha: 0.6),
|
||||
stickerPlaceholderColor: PresentationThemeVariableColor(color: additionalBackgroundColor.withAlphaComponent(0.5)),
|
||||
stickerPlaceholderShimmerColor: PresentationThemeVariableColor(color: additionalBackgroundColor.withAlphaComponent(0.5))
|
||||
)
|
||||
|
||||
let serviceMessage = PresentationThemeServiceMessage(
|
||||
|
|
|
|||
|
|
@ -548,7 +548,9 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio
|
|||
mediaOverlayControlColors: PresentationThemeFillForeground(fillColor: UIColor(rgb: 0x000000, alpha: 0.6), foregroundColor: UIColor(rgb: 0xffffff)),
|
||||
selectionControlColors: PresentationThemeFillStrokeForeground(fillColor: UIColor(rgb: 0x007ee5), strokeColor: UIColor(rgb: 0xc7c7cc), foregroundColor: UIColor(rgb: 0xffffff)),
|
||||
deliveryFailedColors: PresentationThemeFillForeground(fillColor: UIColor(rgb: 0xff3b30), foregroundColor: UIColor(rgb: 0xffffff)),
|
||||
mediaHighlightOverlayColor: UIColor(white: 1.0, alpha: 0.6)
|
||||
mediaHighlightOverlayColor: UIColor(white: 1.0, alpha: 0.6),
|
||||
stickerPlaceholderColor: PresentationThemeVariableColor(withWallpaper: serviceBackgroundColor, withoutWallpaper: UIColor(rgb: 0x748391, alpha: 0.45)),
|
||||
stickerPlaceholderShimmerColor: PresentationThemeVariableColor(withWallpaper: serviceBackgroundColor, withoutWallpaper: UIColor(rgb: 0x748391, alpha: 0.45))
|
||||
)
|
||||
|
||||
let messageDay = PresentationThemeChatMessage(
|
||||
|
|
@ -614,7 +616,9 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio
|
|||
mediaOverlayControlColors: PresentationThemeFillForeground(fillColor: UIColor(rgb: 0x000000, alpha: 0.6), foregroundColor: UIColor(rgb: 0xffffff)),
|
||||
selectionControlColors: PresentationThemeFillStrokeForeground(fillColor: UIColor(rgb: 0x007ee5), strokeColor: UIColor(rgb: 0xc7c7cc), foregroundColor: UIColor(rgb: 0xffffff)),
|
||||
deliveryFailedColors: PresentationThemeFillForeground(fillColor: UIColor(rgb: 0xff3b30), foregroundColor: UIColor(rgb: 0xffffff)),
|
||||
mediaHighlightOverlayColor: UIColor(rgb: 0xffffff, alpha: 0.6)
|
||||
mediaHighlightOverlayColor: UIColor(rgb: 0xffffff, alpha: 0.6),
|
||||
stickerPlaceholderColor: PresentationThemeVariableColor(withWallpaper: serviceBackgroundColor, withoutWallpaper: UIColor(rgb: 0x748391, alpha: 0.45)),
|
||||
stickerPlaceholderShimmerColor: PresentationThemeVariableColor(withWallpaper: serviceBackgroundColor, withoutWallpaper: UIColor(rgb: 0x748391, alpha: 0.45))
|
||||
)
|
||||
|
||||
let serviceMessage = PresentationThemeServiceMessage(
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -755,8 +755,10 @@ public final class PresentationThemeChatMessage {
|
|||
public let selectionControlColors: PresentationThemeFillStrokeForeground
|
||||
public let deliveryFailedColors: PresentationThemeFillForeground
|
||||
public let mediaHighlightOverlayColor: UIColor
|
||||
public let stickerPlaceholderColor: PresentationThemeVariableColor
|
||||
public let stickerPlaceholderShimmerColor: PresentationThemeVariableColor
|
||||
|
||||
public init(incoming: PresentationThemePartedColors, outgoing: PresentationThemePartedColors, freeform: PresentationThemeBubbleColor, infoPrimaryTextColor: UIColor, infoLinkTextColor: UIColor, outgoingCheckColor: UIColor, mediaDateAndStatusFillColor: UIColor, mediaDateAndStatusTextColor: UIColor, shareButtonFillColor: PresentationThemeVariableColor, shareButtonStrokeColor: PresentationThemeVariableColor, shareButtonForegroundColor: PresentationThemeVariableColor, mediaOverlayControlColors: PresentationThemeFillForeground, selectionControlColors: PresentationThemeFillStrokeForeground, deliveryFailedColors: PresentationThemeFillForeground, mediaHighlightOverlayColor: UIColor) {
|
||||
public init(incoming: PresentationThemePartedColors, outgoing: PresentationThemePartedColors, freeform: PresentationThemeBubbleColor, infoPrimaryTextColor: UIColor, infoLinkTextColor: UIColor, outgoingCheckColor: UIColor, mediaDateAndStatusFillColor: UIColor, mediaDateAndStatusTextColor: UIColor, shareButtonFillColor: PresentationThemeVariableColor, shareButtonStrokeColor: PresentationThemeVariableColor, shareButtonForegroundColor: PresentationThemeVariableColor, mediaOverlayControlColors: PresentationThemeFillForeground, selectionControlColors: PresentationThemeFillStrokeForeground, deliveryFailedColors: PresentationThemeFillForeground, mediaHighlightOverlayColor: UIColor, stickerPlaceholderColor: PresentationThemeVariableColor, stickerPlaceholderShimmerColor: PresentationThemeVariableColor) {
|
||||
self.incoming = incoming
|
||||
self.outgoing = outgoing
|
||||
self.freeform = freeform
|
||||
|
|
@ -772,10 +774,12 @@ public final class PresentationThemeChatMessage {
|
|||
self.selectionControlColors = selectionControlColors
|
||||
self.deliveryFailedColors = deliveryFailedColors
|
||||
self.mediaHighlightOverlayColor = mediaHighlightOverlayColor
|
||||
self.stickerPlaceholderColor = stickerPlaceholderColor
|
||||
self.stickerPlaceholderShimmerColor = stickerPlaceholderShimmerColor
|
||||
}
|
||||
|
||||
public func withUpdated(incoming: PresentationThemePartedColors? = nil, outgoing: PresentationThemePartedColors? = nil, freeform: PresentationThemeBubbleColor? = nil, infoPrimaryTextColor: UIColor? = nil, infoLinkTextColor: UIColor? = nil, outgoingCheckColor: UIColor? = nil, mediaDateAndStatusFillColor: UIColor? = nil, mediaDateAndStatusTextColor: UIColor? = nil, shareButtonFillColor: PresentationThemeVariableColor? = nil, shareButtonStrokeColor: PresentationThemeVariableColor? = nil, shareButtonForegroundColor: PresentationThemeVariableColor? = nil, mediaOverlayControlColors: PresentationThemeFillForeground? = nil, selectionControlColors: PresentationThemeFillStrokeForeground? = nil, deliveryFailedColors: PresentationThemeFillForeground? = nil, mediaHighlightOverlayColor: UIColor? = nil) -> PresentationThemeChatMessage {
|
||||
return PresentationThemeChatMessage(incoming: incoming ?? self.incoming, outgoing: outgoing ?? self.outgoing, freeform: freeform ?? self.freeform, infoPrimaryTextColor: infoPrimaryTextColor ?? self.infoPrimaryTextColor, infoLinkTextColor: infoLinkTextColor ?? self.infoLinkTextColor, outgoingCheckColor: outgoingCheckColor ?? self.outgoingCheckColor, mediaDateAndStatusFillColor: mediaDateAndStatusFillColor ?? self.mediaDateAndStatusFillColor, mediaDateAndStatusTextColor: mediaDateAndStatusTextColor ?? self.mediaDateAndStatusTextColor, shareButtonFillColor: shareButtonFillColor ?? self.shareButtonFillColor, shareButtonStrokeColor: shareButtonStrokeColor ?? self.shareButtonStrokeColor, shareButtonForegroundColor: shareButtonForegroundColor ?? self.shareButtonForegroundColor, mediaOverlayControlColors: mediaOverlayControlColors ?? self.mediaOverlayControlColors, selectionControlColors: selectionControlColors ?? self.selectionControlColors, deliveryFailedColors: deliveryFailedColors ?? self.deliveryFailedColors, mediaHighlightOverlayColor: mediaHighlightOverlayColor ?? self.mediaHighlightOverlayColor)
|
||||
return PresentationThemeChatMessage(incoming: incoming ?? self.incoming, outgoing: outgoing ?? self.outgoing, freeform: freeform ?? self.freeform, infoPrimaryTextColor: infoPrimaryTextColor ?? self.infoPrimaryTextColor, infoLinkTextColor: infoLinkTextColor ?? self.infoLinkTextColor, outgoingCheckColor: outgoingCheckColor ?? self.outgoingCheckColor, mediaDateAndStatusFillColor: mediaDateAndStatusFillColor ?? self.mediaDateAndStatusFillColor, mediaDateAndStatusTextColor: mediaDateAndStatusTextColor ?? self.mediaDateAndStatusTextColor, shareButtonFillColor: shareButtonFillColor ?? self.shareButtonFillColor, shareButtonStrokeColor: shareButtonStrokeColor ?? self.shareButtonStrokeColor, shareButtonForegroundColor: shareButtonForegroundColor ?? self.shareButtonForegroundColor, mediaOverlayControlColors: mediaOverlayControlColors ?? self.mediaOverlayControlColors, selectionControlColors: selectionControlColors ?? self.selectionControlColors, deliveryFailedColors: deliveryFailedColors ?? self.deliveryFailedColors, mediaHighlightOverlayColor: mediaHighlightOverlayColor ?? self.mediaHighlightOverlayColor, stickerPlaceholderColor: stickerPlaceholderColor ?? self.stickerPlaceholderColor, stickerPlaceholderShimmerColor: stickerPlaceholderShimmerColor ?? self.stickerPlaceholderShimmerColor)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1233,6 +1233,8 @@ extension PresentationThemeChatMessage: Codable {
|
|||
case selectionControl
|
||||
case deliveryFailed
|
||||
case mediaHighlightOverlay
|
||||
case stickerPlaceholder
|
||||
case stickerPlaceholderShimmer
|
||||
}
|
||||
|
||||
public convenience init(from decoder: Decoder) throws {
|
||||
|
|
@ -1251,7 +1253,10 @@ extension PresentationThemeChatMessage: Codable {
|
|||
mediaOverlayControlColors: try values.decode(PresentationThemeFillForeground.self, forKey: .mediaOverlayControl),
|
||||
selectionControlColors: try values.decode(PresentationThemeFillStrokeForeground.self, forKey: .selectionControl),
|
||||
deliveryFailedColors: try values.decode(PresentationThemeFillForeground.self, forKey: .deliveryFailed),
|
||||
mediaHighlightOverlayColor: try decodeColor(values, .mediaHighlightOverlay))
|
||||
mediaHighlightOverlayColor: try decodeColor(values, .mediaHighlightOverlay),
|
||||
stickerPlaceholderColor: try values.decode(PresentationThemeVariableColor.self, forKey: .stickerPlaceholder),
|
||||
stickerPlaceholderShimmerColor: try values.decode(PresentationThemeVariableColor.self, forKey: .stickerPlaceholderShimmer)
|
||||
)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -300,11 +300,11 @@ public final class AccountContextImpl: AccountContext {
|
|||
}
|
||||
}
|
||||
|
||||
public func joinGroupCall(peerId: PeerId, activeCall: CachedChannelData.ActiveCall, sourcePanel: ASDisplayNode?) {
|
||||
let callResult = self.sharedContext.callManager?.joinGroupCall(context: self, peerId: peerId, initialCall: activeCall, endCurrentIfAny: false, sourcePanel: nil)
|
||||
public func joinGroupCall(peerId: PeerId, activeCall: CachedChannelData.ActiveCall) {
|
||||
let callResult = self.sharedContext.callManager?.joinGroupCall(context: self, peerId: peerId, initialCall: activeCall, endCurrentIfAny: false)
|
||||
if let callResult = callResult, case let .alreadyInProgress(currentPeerId) = callResult {
|
||||
if currentPeerId == peerId {
|
||||
self.sharedContext.navigateToCurrentCall(sourcePanel: nil)
|
||||
self.sharedContext.navigateToCurrentCall()
|
||||
} else {
|
||||
let _ = (self.account.postbox.transaction { transaction -> (Peer?, Peer?) in
|
||||
return (transaction.getPeer(peerId), currentPeerId.flatMap(transaction.getPeer))
|
||||
|
|
@ -323,14 +323,14 @@ public final class AccountContextImpl: AccountContext {
|
|||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = strongSelf.sharedContext.callManager?.joinGroupCall(context: strongSelf, peerId: peer.id, initialCall: activeCall, endCurrentIfAny: true, sourcePanel: nil)
|
||||
let _ = strongSelf.sharedContext.callManager?.joinGroupCall(context: strongSelf, peerId: peer.id, initialCall: activeCall, endCurrentIfAny: true)
|
||||
})]), on: .root)
|
||||
} else {
|
||||
strongSelf.sharedContext.mainWindow?.present(textAlertController(context: strongSelf, title: presentationData.strings.Call_CallInProgressTitle, text: presentationData.strings.Call_CallInProgressVoiceChatMessage(current.compactDisplayTitle, peer.compactDisplayTitle).0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = strongSelf.sharedContext.callManager?.joinGroupCall(context: strongSelf, peerId: peer.id, initialCall: activeCall, endCurrentIfAny: true, sourcePanel: nil)
|
||||
let _ = strongSelf.sharedContext.callManager?.joinGroupCall(context: strongSelf, peerId: peer.id, initialCall: activeCall, endCurrentIfAny: true)
|
||||
})]), on: .root)
|
||||
}
|
||||
} else {
|
||||
|
|
@ -350,7 +350,7 @@ public final class AccountContextImpl: AccountContext {
|
|||
if case let .alreadyInProgress(currentPeerId) = callResult {
|
||||
if currentPeerId == peerId {
|
||||
completion()
|
||||
self.sharedContext.navigateToCurrentCall(sourcePanel: nil)
|
||||
self.sharedContext.navigateToCurrentCall()
|
||||
} else {
|
||||
let _ = (self.account.postbox.transaction { transaction -> (Peer?, Peer?) in
|
||||
return (transaction.getPeer(peerId), currentPeerId.flatMap(transaction.getPeer))
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ final class ChatBotStartInputPanelNode: ChatInputPanelNode {
|
|||
self.interfaceInteraction?.sendBotStart(presentationInterfaceState.botStartPayload)
|
||||
}
|
||||
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
if self.presentationInterfaceState != interfaceState {
|
||||
let previousState = self.presentationInterfaceState
|
||||
self.presentationInterfaceState = interfaceState
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ final class ChatChannelSubscriberInputPanelNode: ChatInputPanelNode {
|
|||
}
|
||||
}
|
||||
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
self.layoutData = (width, leftInset, rightInset)
|
||||
|
||||
if self.presentationInterfaceState != interfaceState {
|
||||
|
|
|
|||
|
|
@ -508,7 +508,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
|
||||
let peerId = message.id.peerId
|
||||
|
||||
strongSelf.context.joinGroupCall(peerId: peerId, activeCall: CachedChannelData.ActiveCall(id: callId, accessHash: accessHash), sourcePanel: nil)
|
||||
strongSelf.context.joinGroupCall(peerId: peerId, activeCall: CachedChannelData.ActiveCall(id: callId, accessHash: accessHash))
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
|
@ -4445,12 +4445,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
|
||||
if let selectionState = strongSelf.presentationInterfaceState.interfaceState.selectionState {
|
||||
let count = selectionState.selectedIds.count
|
||||
let text: String
|
||||
if count == 1 {
|
||||
text = "1 message selected"
|
||||
} else {
|
||||
text = "\(count) messages selected"
|
||||
}
|
||||
let text = strongSelf.presentationData.strings.VoiceOver_Chat_MessagesSelected(Int32(count))
|
||||
UIAccessibility.post(notification: UIAccessibility.Notification.announcement, argument: text)
|
||||
}
|
||||
} else {
|
||||
|
|
@ -5984,7 +5979,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
guard let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else {
|
||||
return
|
||||
}
|
||||
strongSelf.context.joinGroupCall(peerId: peer.id, activeCall: activeCall, sourcePanel: nil)
|
||||
strongSelf.context.joinGroupCall(peerId: peer.id, activeCall: activeCall)
|
||||
}, editMessageMedia: { [weak self] messageId, draw in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controllerInteraction?.editMessageMedia(messageId, draw)
|
||||
|
|
@ -7649,6 +7644,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
})
|
||||
}, openCamera: { [weak self] cameraView, menuController in
|
||||
if let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
|
||||
if let callManager = strongSelf.context.sharedContext.callManager as? PresentationCallManagerImpl, callManager.hasActiveGroupCall {
|
||||
return
|
||||
}
|
||||
|
||||
presentedLegacyCamera(context: strongSelf.context, peer: peer, chatLocation: strongSelf.chatLocation, cameraView: cameraView, menuController: menuController, parentController: strongSelf, editingMedia: editMediaOptions != nil, saveCapturedPhotos: settings.storeEditedPhotos, mediaGrouping: true, initialCaption: inputText.string, hasSchedule: strongSelf.presentationInterfaceState.subject != .scheduledMessages && peer.id.namespace != Namespaces.Peer.SecretChat, sendMessagesWithSignals: { [weak self] signals, silentPosting, scheduleTime in
|
||||
if let strongSelf = self {
|
||||
if editMediaOptions != nil {
|
||||
|
|
@ -10360,7 +10359,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
let galleryController = AvatarGalleryController(context: self.context, peer: peer, remoteEntries: nil, replaceRootController: { controller, ready in
|
||||
}, synchronousLoad: true)
|
||||
galleryController.setHintWillBePresentedInPreviewingContext(true)
|
||||
galleryController.containerLayoutUpdated(ContainerViewLayout(size: CGSize(width: self.view.bounds.size.width, height: self.view.bounds.size.height), metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: .immediate)
|
||||
galleryController.containerLayoutUpdated(ContainerViewLayout(size: CGSize(width: self.view.bounds.size.width, height: self.view.bounds.size.height), metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: .immediate)
|
||||
return (galleryController, buttonView.convert(buttonView.bounds, to: sourceView))
|
||||
}
|
||||
return nil
|
||||
|
|
@ -10401,7 +10400,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
gallery.setHintWillBePresentedInPreviewingContext(true)
|
||||
let rect = selectedTransitionNode.0.view.convert(selectedTransitionNode.0.bounds, to: sourceView)
|
||||
let sourceRect = rect.insetBy(dx: -2.0, dy: -2.0)
|
||||
gallery.containerLayoutUpdated(ContainerViewLayout(size: CGSize(width: self.view.bounds.size.width, height: self.view.bounds.size.height), metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: .immediate)
|
||||
gallery.containerLayoutUpdated(ContainerViewLayout(size: CGSize(width: self.view.bounds.size.width, height: self.view.bounds.size.height), metrics: LayoutMetrics(), deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: .immediate)
|
||||
return (gallery, sourceRect)
|
||||
case .instantPage:
|
||||
break
|
||||
|
|
|
|||
|
|
@ -1139,7 +1139,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||
if inputTextPanelNode.isFocused {
|
||||
self.context.sharedContext.mainWindow?.simulateKeyboardDismiss(transition: .animated(duration: 0.5, curve: .spring))
|
||||
}
|
||||
let _ = inputTextPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, maxHeight: layout.size.height - insets.top - insets.bottom, isSecondary: false, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics)
|
||||
let _ = inputTextPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - insets.bottom, isSecondary: false, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics)
|
||||
}
|
||||
if let prevInputPanelNode = self.inputPanelNode, inputPanelNode.canHandleTransition(from: prevInputPanelNode) {
|
||||
inputPanelNodeHandlesTransition = true
|
||||
|
|
@ -1149,7 +1149,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||
} else {
|
||||
dismissedInputPanelNode = self.inputPanelNode
|
||||
}
|
||||
let inputPanelHeight = inputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, maxHeight: layout.size.height - insets.top - insets.bottom, isSecondary: false, transition: inputPanelNode.supernode !== self ? .immediate : transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics)
|
||||
let inputPanelHeight = inputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - insets.bottom, isSecondary: false, transition: inputPanelNode.supernode !== self ? .immediate : transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics)
|
||||
inputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight)
|
||||
self.inputPanelNode = inputPanelNode
|
||||
if inputPanelNode.supernode !== self {
|
||||
|
|
@ -1157,7 +1157,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||
self.insertSubnode(inputPanelNode, aboveSubnode: self.inputPanelBackgroundNode)
|
||||
}
|
||||
} else {
|
||||
let inputPanelHeight = inputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, maxHeight: layout.size.height - insets.top - insets.bottom, isSecondary: false, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics)
|
||||
let inputPanelHeight = inputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - insets.bottom, isSecondary: false, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics)
|
||||
inputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight)
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1168,7 +1168,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||
if let secondaryInputPanelNode = inputPanelNodes.secondary, !previewing {
|
||||
if secondaryInputPanelNode !== self.secondaryInputPanelNode {
|
||||
dismissedSecondaryInputPanelNode = self.secondaryInputPanelNode
|
||||
let inputPanelHeight = secondaryInputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, maxHeight: layout.size.height - insets.top - insets.bottom, isSecondary: true, transition: .immediate, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics)
|
||||
let inputPanelHeight = secondaryInputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - insets.bottom, isSecondary: true, transition: .immediate, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics)
|
||||
secondaryInputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight)
|
||||
self.secondaryInputPanelNode = secondaryInputPanelNode
|
||||
if secondaryInputPanelNode.supernode == nil {
|
||||
|
|
@ -1176,7 +1176,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||
self.insertSubnode(secondaryInputPanelNode, aboveSubnode: self.inputPanelBackgroundNode)
|
||||
}
|
||||
} else {
|
||||
let inputPanelHeight = secondaryInputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, maxHeight: layout.size.height - insets.top - insets.bottom, isSecondary: true, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics)
|
||||
let inputPanelHeight = secondaryInputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - insets.bottom, isSecondary: true, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics)
|
||||
secondaryInputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight)
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1528,9 +1528,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||
listInsets.top = listInsets.top + messageActionSheetControllerAdditionalInset
|
||||
}
|
||||
|
||||
var childredLayout = layout
|
||||
childredLayout.intrinsicInsets = UIEdgeInsets(top: listInsets.bottom, left: listInsets.right, bottom: listInsets.top, right: listInsets.left)
|
||||
self.controller?.presentationContext.containerLayoutUpdated(childredLayout, transition: transition)
|
||||
var childrenLayout = layout
|
||||
childrenLayout.intrinsicInsets = UIEdgeInsets(top: listInsets.bottom, left: listInsets.right, bottom: listInsets.top, right: listInsets.left)
|
||||
self.controller?.presentationContext.containerLayoutUpdated(childrenLayout, transition: transition)
|
||||
|
||||
listViewTransaction(ListViewUpdateSizeAndInsets(size: contentBounds.size, insets: listInsets, scrollIndicatorInsets: listScrollIndicatorInsets, duration: duration, curve: curve, ensureTopInsetForOverlayHighlightedItems: ensureTopInsetForOverlayHighlightedItems), additionalScrollDistance, scrollToTop, { [weak self] in
|
||||
if let strongSelf = self {
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ final class ChatFeedNavigationInputPanelNode: ChatInputPanelNode {
|
|||
self.interfaceInteraction?.navigateFeed()
|
||||
}
|
||||
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
if self.presentationInterfaceState != interfaceState {
|
||||
self.presentationInterfaceState = interfaceState
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class ChatInputPanelNode: ASDisplayNode {
|
|||
var interfaceInteraction: ChatPanelInterfaceInteraction?
|
||||
var prevInputPanelNode: ChatInputPanelNode?
|
||||
|
||||
func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode {
|
|||
if self.selectedMessages.isEmpty {
|
||||
self.actions = nil
|
||||
if let (width, leftInset, rightInset, maxHeight, metrics, isSecondary) = self.validLayout, let interfaceState = self.presentationInterfaceState {
|
||||
let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: interfaceState, metrics: metrics)
|
||||
let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, additionalSideInsets: UIEdgeInsets(), maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: interfaceState, metrics: metrics)
|
||||
}
|
||||
self.canDeleteMessagesDisposable.set(nil)
|
||||
} else if let context = self.context {
|
||||
|
|
@ -43,7 +43,7 @@ final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode {
|
|||
if let strongSelf = self {
|
||||
strongSelf.actions = actions
|
||||
if let (width, leftInset, rightInset, maxHeight, metrics, isSecondary) = strongSelf.validLayout, let interfaceState = strongSelf.presentationInterfaceState {
|
||||
let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: interfaceState, metrics: metrics)
|
||||
let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, additionalSideInsets: UIEdgeInsets(), maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: interfaceState, metrics: metrics)
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
|
@ -138,7 +138,7 @@ final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode {
|
|||
self.interfaceInteraction?.shareSelectedMessages()
|
||||
}
|
||||
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
self.validLayout = (width, leftInset, rightInset, maxHeight, metrics, isSecondary)
|
||||
|
||||
let panelHeight = defaultHeight(metrics: metrics)
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode {
|
|||
}
|
||||
}
|
||||
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
if self.presentationInterfaceState != interfaceState {
|
||||
var updateWaveform = false
|
||||
if self.presentationInterfaceState?.recordedMediaPreview != interfaceState.recordedMediaPreview {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ final class ChatRestrictedInputPanelNode: ChatInputPanelNode {
|
|||
self.addSubnode(self.textNode)
|
||||
}
|
||||
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
if self.presentationInterfaceState != interfaceState {
|
||||
self.presentationInterfaceState = interfaceState
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ final class ChatSearchInputPanelNode: ChatInputPanelNode {
|
|||
strongSelf.displayActivity = value
|
||||
strongSelf.activityIndicator.isHidden = !value
|
||||
if let interfaceState = strongSelf.presentationInterfaceState, let validLayout = strongSelf.validLayout {
|
||||
strongSelf.updateLayout(width: validLayout.0, leftInset: validLayout.1, rightInset: validLayout.2, maxHeight: validLayout.3, isSecondary: validLayout.5, transition: .immediate, interfaceState: interfaceState, metrics: validLayout.4)
|
||||
strongSelf.updateLayout(width: validLayout.0, leftInset: validLayout.1, rightInset: validLayout.2, additionalSideInsets: UIEdgeInsets(), maxHeight: validLayout.3, isSecondary: validLayout.5, transition: .immediate, interfaceState: interfaceState, metrics: validLayout.4)
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
|
@ -127,7 +127,7 @@ final class ChatSearchInputPanelNode: ChatInputPanelNode {
|
|||
}
|
||||
}
|
||||
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
self.validLayout = (width, leftInset, rightInset, maxHeight, metrics, isSecondary)
|
||||
|
||||
if self.presentationInterfaceState != interfaceState {
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||
|
||||
private var accessoryItemButtons: [(ChatTextInputAccessoryItem, AccessoryItemIconButton)] = []
|
||||
|
||||
private var validLayout: (CGFloat, CGFloat, CGFloat, CGFloat, LayoutMetrics, Bool)?
|
||||
private var validLayout: (CGFloat, CGFloat, CGFloat, UIEdgeInsets, CGFloat, LayoutMetrics, Bool)?
|
||||
|
||||
var displayAttachmentMenu: () -> Void = { }
|
||||
var sendMessage: () -> Void = { }
|
||||
|
|
@ -450,15 +450,15 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||
}
|
||||
self.actionButtons.micButton.offsetRecordingControls = { [weak self] in
|
||||
if let strongSelf = self, let presentationInterfaceState = strongSelf.presentationInterfaceState {
|
||||
if let (width, leftInset, rightInset, maxHeight, metrics, isSecondary) = strongSelf.validLayout {
|
||||
let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: presentationInterfaceState, metrics: metrics)
|
||||
if let (width, leftInset, rightInset, additionalSideInsets, maxHeight, metrics, isSecondary) = strongSelf.validLayout {
|
||||
let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: presentationInterfaceState, metrics: metrics)
|
||||
}
|
||||
}
|
||||
}
|
||||
self.actionButtons.micButton.updateCancelTranslation = { [weak self] in
|
||||
if let strongSelf = self, let presentationInterfaceState = strongSelf.presentationInterfaceState {
|
||||
if let (width, leftInset, rightInset, maxHeight, metrics, isSecondary) = strongSelf.validLayout {
|
||||
let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: presentationInterfaceState, metrics: metrics)
|
||||
if let (width, leftInset, rightInset, additionalSideInsets, maxHeight, metrics, isSecondary) = strongSelf.validLayout {
|
||||
let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: presentationInterfaceState, metrics: metrics)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -667,8 +667,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||
return minimalHeight
|
||||
}
|
||||
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
self.validLayout = (width, leftInset, rightInset, maxHeight, metrics, isSecondary)
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
self.validLayout = (width, leftInset, rightInset, additionalSideInsets, maxHeight, metrics, isSecondary)
|
||||
let baseWidth = width - leftInset - rightInset
|
||||
|
||||
var wasEditingMedia = false
|
||||
|
|
@ -1235,7 +1235,10 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||
}
|
||||
|
||||
let searchLayoutClearButtonSize = CGSize(width: 44.0, height: minimalHeight)
|
||||
let textFieldInsets = self.textFieldInsets(metrics: metrics)
|
||||
var textFieldInsets = self.textFieldInsets(metrics: metrics)
|
||||
if additionalSideInsets.right > 0.0 && self.text.isEmpty {
|
||||
textFieldInsets.right += additionalSideInsets.right / 3.0
|
||||
}
|
||||
transition.updateFrame(layer: self.searchLayoutClearButton.layer, frame: CGRect(origin: CGPoint(x: width - rightInset - textFieldInsets.left - textFieldInsets.right + textInputBackgroundWidthOffset + 3.0, y: panelHeight - minimalHeight), size: searchLayoutClearButtonSize))
|
||||
if let image = self.searchLayoutClearImageNode.image {
|
||||
self.searchLayoutClearImageNode.frame = CGRect(origin: CGPoint(x: floor((searchLayoutClearButtonSize.width - image.size.width) / 2.0), y: floor((searchLayoutClearButtonSize.height - image.size.height) / 2.0)), size: image.size)
|
||||
|
|
@ -1480,7 +1483,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||
self.counterTextNode.attributedText = NSAttributedString(string: "", font: counterFont, textColor: .black)
|
||||
}
|
||||
|
||||
if let (width, leftInset, rightInset, maxHeight, metrics, _) = self.validLayout {
|
||||
if let (width, leftInset, rightInset, additionalSideInsets, maxHeight, metrics, _) = self.validLayout {
|
||||
var composeButtonsOffset: CGFloat = 0.0
|
||||
if self.extendedSearchLayout {
|
||||
composeButtonsOffset = 44.0
|
||||
|
|
@ -1672,8 +1675,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||
}
|
||||
|
||||
private func updateTextHeight(animated: Bool) {
|
||||
if let (width, leftInset, rightInset, maxHeight, metrics, _) = self.validLayout {
|
||||
let (_, textFieldHeight) = self.calculateTextFieldMetrics(width: width - leftInset - rightInset, maxHeight: maxHeight, metrics: metrics)
|
||||
if let (width, leftInset, rightInset, additionalSideInsets, maxHeight, metrics, _) = self.validLayout {
|
||||
let (_, textFieldHeight) = self.calculateTextFieldMetrics(width: width - leftInset - rightInset - additionalSideInsets.right, maxHeight: maxHeight, metrics: metrics)
|
||||
let panelHeight = self.panelHeight(textFieldHeight: textFieldHeight, metrics: metrics)
|
||||
if !self.bounds.size.height.isEqual(to: panelHeight) {
|
||||
self.updateHeight(animated)
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ final class ChatUnblockInputPanelNode: ChatInputPanelNode {
|
|||
self.interfaceInteraction?.unblockPeer()
|
||||
}
|
||||
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
if self.presentationInterfaceState != interfaceState {
|
||||
self.presentationInterfaceState = interfaceState
|
||||
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ final class ComposeControllerNode: ASDisplayNode {
|
|||
searchDisplayController.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: transition)
|
||||
}
|
||||
|
||||
self.contactListNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: insets, safeInsets: layout.safeInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), headerInsets: headerInsets, transition: transition)
|
||||
self.contactListNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: insets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), headerInsets: headerInsets, transition: transition)
|
||||
|
||||
self.contactListNode.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ final class ContactMultiselectionControllerNode: ASDisplayNode {
|
|||
var headerInsets = layout.insets(options: [.input])
|
||||
headerInsets.top += actualNavigationBarHeight
|
||||
headerInsets.top += strongSelf.tokenListNode.bounds.size.height
|
||||
searchResultsNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: insets, safeInsets: layout.safeInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), headerInsets: headerInsets, transition: .immediate)
|
||||
searchResultsNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: insets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), headerInsets: headerInsets, transition: .immediate)
|
||||
searchResultsNode.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
}
|
||||
|
||||
|
|
@ -265,7 +265,7 @@ final class ContactMultiselectionControllerNode: ASDisplayNode {
|
|||
|
||||
switch self.contentNode {
|
||||
case let .contacts(contactsNode):
|
||||
contactsNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: insets, safeInsets: layout.safeInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), headerInsets: headerInsets, transition: transition)
|
||||
contactsNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: insets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), headerInsets: headerInsets, transition: transition)
|
||||
case let .chats(chatsNode):
|
||||
var combinedInsets = insets
|
||||
combinedInsets.left += layout.safeInsets.left
|
||||
|
|
@ -277,7 +277,7 @@ final class ContactMultiselectionControllerNode: ASDisplayNode {
|
|||
self.contentNode.node.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
|
||||
if let searchResultsNode = self.searchResultsNode {
|
||||
searchResultsNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: insets, safeInsets: layout.safeInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), headerInsets: headerInsets, transition: transition)
|
||||
searchResultsNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: insets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), headerInsets: headerInsets, transition: transition)
|
||||
searchResultsNode.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ final class ContactSelectionControllerNode: ASDisplayNode {
|
|||
searchDisplayController.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: transition)
|
||||
}
|
||||
|
||||
self.contactListNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: insets, safeInsets: layout.safeInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), headerInsets: headerInsets, transition: transition)
|
||||
self.contactListNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: insets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), headerInsets: headerInsets, transition: transition)
|
||||
|
||||
self.contactListNode.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ final class DeleteChatInputPanelNode: ChatInputPanelNode {
|
|||
self.interfaceInteraction?.deleteChat()
|
||||
}
|
||||
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
if self.presentationInterfaceState != interfaceState {
|
||||
self.presentationInterfaceState = interfaceState
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ public final class OverlayMediaControllerImpl: ViewController, OverlayMediaContr
|
|||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
super.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
let updatedLayout = ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(top: (layout.statusBarHeight ?? 0.0) + 44.0, left: layout.intrinsicInsets.left, bottom: layout.intrinsicInsets.bottom, right: layout.intrinsicInsets.right), safeInsets: layout.safeInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver)
|
||||
let updatedLayout = ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: UIEdgeInsets(top: (layout.statusBarHeight ?? 0.0) + 44.0, left: layout.intrinsicInsets.left, bottom: layout.intrinsicInsets.bottom, right: layout.intrinsicInsets.right), safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver)
|
||||
self.controllerNode.containerLayoutUpdated(updatedLayout, transition: transition)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ private final class PeerInfoScreenSwitchItemNode: PeerInfoScreenItemNode {
|
|||
|
||||
self.activateArea.accessibilityLabel = item.text
|
||||
self.activateArea.accessibilityValue = item.value ? presentationData.strings.VoiceOver_Common_On : presentationData.strings.VoiceOver_Common_Off
|
||||
self.activateArea.accessibilityHint = presentationData.strings.VoiceOver_Common_TapToChange
|
||||
self.activateArea.accessibilityHint = presentationData.strings.VoiceOver_Common_SwitchHint
|
||||
|
||||
let textSize = self.textNode.updateLayout(CGSize(width: width - sideInset * 2.0 - 56.0, height: .greatestFiniteMagnitude))
|
||||
let textFrame = CGRect(origin: CGPoint(x: sideInset, y: 12.0), size: textSize)
|
||||
|
|
|
|||
|
|
@ -460,7 +460,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
|
|||
self.separatorNode.backgroundColor = presentationData.theme.rootController.navigationBar.separatorColor
|
||||
|
||||
let interfaceState = ChatPresentationInterfaceState(chatWallpaper: .color(0), theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, limitsConfiguration: .defaultValue, fontSize: .regular, bubbleCorners: PresentationChatBubbleCorners(mainRadius: 16.0, auxiliaryRadius: 8.0, mergeBubbleCorners: true), accountPeerId: self.context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(self.peerId), subject: nil, peerNearbyData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil)
|
||||
let panelHeight = self.selectionPanel.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, maxHeight: 0.0, isSecondary: false, transition: transition, interfaceState: interfaceState, metrics: layout.metrics)
|
||||
let panelHeight = self.selectionPanel.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, additionalSideInsets: UIEdgeInsets(), maxHeight: 0.0, isSecondary: false, transition: transition, interfaceState: interfaceState, metrics: layout.metrics)
|
||||
|
||||
transition.updateFrame(node: self.selectionPanel, frame: CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: panelHeight)))
|
||||
|
||||
|
|
@ -3207,7 +3207,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||
}
|
||||
|
||||
if let activeCall = cachedChannelData.activeCall {
|
||||
self.context.joinGroupCall(peerId: peer.id, activeCall: activeCall, sourcePanel: nil)
|
||||
self.context.joinGroupCall(peerId: peer.id, activeCall: activeCall)
|
||||
} else {
|
||||
self.createAndJoinGroupCall(peerId: peer.id)
|
||||
}
|
||||
|
|
@ -3246,7 +3246,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.context.joinGroupCall(peerId: peerId, activeCall: CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash), sourcePanel: nil)
|
||||
strongSelf.context.joinGroupCall(peerId: peerId, activeCall: CachedChannelData.ActiveCall(id: info.id, accessHash: info.accessHash))
|
||||
}, error: { [weak self] error in
|
||||
dismissStatus?()
|
||||
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
|||
|
||||
let contactsInsets = insets
|
||||
|
||||
contactListNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: contactsInsets, safeInsets: layout.safeInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), headerInsets: headerInsets, transition: transition)
|
||||
contactListNode.containerLayoutUpdated(ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: contactsInsets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), headerInsets: headerInsets, transition: transition)
|
||||
}
|
||||
|
||||
if let searchDisplayController = self.searchDisplayController {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ final class SecretChatHandshakeStatusInputPanelNode: ChatInputPanelNode {
|
|||
self.interfaceInteraction?.unblockPeer()
|
||||
}
|
||||
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
|
||||
if self.presentationInterfaceState != interfaceState {
|
||||
self.presentationInterfaceState = interfaceState
|
||||
|
||||
|
|
|
|||
|
|
@ -987,7 +987,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||
return openChatMessageImpl(params)
|
||||
}
|
||||
|
||||
public func navigateToCurrentCall(sourcePanel: ASDisplayNode? = nil) {
|
||||
public func navigateToCurrentCall() {
|
||||
guard let mainWindow = self.mainWindow else {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue