mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 13:35:19 +00:00
Various improvements
This commit is contained in:
parent
d046176912
commit
ed86e369eb
@ -9041,3 +9041,14 @@ Sorry for the inconvenience.";
|
||||
"Premium.Gift.TitleShort" = "Telegram Premium";
|
||||
|
||||
"VoiceOver.GiftPremium" = "Gift Telegram Premium";
|
||||
|
||||
"Login.Email.CantAccess" = "Can't access this email?";
|
||||
"Login.Email.ResetTitle" = "Reset Email";
|
||||
"Login.Email.ResetText" = "You can change your login email if you are logged into Telegram from another device. Otherwise, if you don't have access to email %@, you can reset this email with an SMS code in 7 days.";
|
||||
"Login.Email.Reset" = "Reset";
|
||||
"Login.Email.ResetNowViaSMS" = "Reset now via SMS";
|
||||
"Login.Email.WillBeResetIn" = "Email will be reset in %@";
|
||||
"Login.Email.PremiumRequiredTitle" = "Telegram Premium Required";
|
||||
"Login.Email.PremiumRequiredText" = "Due to high cost of SMS in your country, you need to have a **Telegram Premium** account to reset this email via an SMS code. You can ask a friend to a gift a Premium subscription for your account %@";
|
||||
|
||||
"ChatList.StartMessaging" = "Select a chat to start messaging";
|
||||
|
@ -433,7 +433,7 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
let containerFrame: CGRect
|
||||
let clipFrame: CGRect
|
||||
let containerScale: CGFloat
|
||||
if layout.metrics.widthClass == .compact {
|
||||
if case .compact = layout.metrics.widthClass {
|
||||
self.clipNode.clipsToBounds = true
|
||||
|
||||
if isLandscape {
|
||||
|
@ -4811,7 +4811,7 @@ private final class ChatListLocationContext {
|
||||
strings: presentationData.strings,
|
||||
dateTimeFormat: presentationData.dateTimeFormat,
|
||||
nameDisplayOrder: presentationData.nameDisplayOrder,
|
||||
content: .peer(peerView: peerView, customTitle: nil, onlineMemberCount: onlineMemberCount, isScheduledMessages: false, isMuted: nil, customMessageCount: nil),
|
||||
content: .peer(peerView: peerView, customTitle: nil, onlineMemberCount: onlineMemberCount, isScheduledMessages: false, isMuted: nil, customMessageCount: nil, isEnabled: true),
|
||||
tapped: { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
|
@ -34,11 +34,6 @@ public struct NavigationAnimationOptions : OptionSet {
|
||||
public static let removeOnMasterDetails = NavigationAnimationOptions(rawValue: 1 << 0)
|
||||
}
|
||||
|
||||
public enum NavigationEmptyDetailsBackgoundMode {
|
||||
case image(UIImage)
|
||||
case wallpaper(UIImage)
|
||||
}
|
||||
|
||||
private enum ControllerTransition {
|
||||
case none
|
||||
case appearance
|
||||
@ -120,6 +115,10 @@ public final class NavigationControllerDropContent {
|
||||
}
|
||||
}
|
||||
|
||||
public protocol NavigationDetailsPlaceholderNode: ASDisplayNode {
|
||||
func updateLayout(size: CGSize, needsTiling: Bool, transition: ContainedViewLayoutTransition)
|
||||
}
|
||||
|
||||
open class NavigationController: UINavigationController, ContainableController, UIGestureRecognizerDelegate {
|
||||
public var isOpaqueWhenInOverlay: Bool = true
|
||||
public var blocksBackgroundWhenInOverlay: Bool = true
|
||||
@ -131,7 +130,6 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
}
|
||||
|
||||
private var masterDetailsBlackout: MasterDetailLayoutBlackout?
|
||||
private var backgroundDetailsMode: NavigationEmptyDetailsBackgoundMode?
|
||||
|
||||
public var lockOrientation: Bool = false
|
||||
|
||||
@ -232,16 +230,21 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
self.requestLayout(transition: transition)
|
||||
}
|
||||
|
||||
public func updateBackgroundDetailsMode(_ mode: NavigationEmptyDetailsBackgoundMode?, transition: ContainedViewLayoutTransition) {
|
||||
self.backgroundDetailsMode = mode
|
||||
self.requestLayout(transition: transition)
|
||||
private weak var detailsPlaceholderNode: NavigationDetailsPlaceholderNode?
|
||||
public func updateDetailsPlaceholderNode(_ node: NavigationDetailsPlaceholderNode?) {
|
||||
if self.detailsPlaceholderNode !== node {
|
||||
self.detailsPlaceholderNode?.removeFromSupernode()
|
||||
self.detailsPlaceholderNode = node
|
||||
if let node {
|
||||
self.displayNode.insertSubnode(node, at: 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public init(mode: NavigationControllerMode, theme: NavigationControllerTheme, isFlat: Bool = false, backgroundDetailsMode: NavigationEmptyDetailsBackgoundMode? = nil) {
|
||||
public init(mode: NavigationControllerMode, theme: NavigationControllerTheme, isFlat: Bool = false) {
|
||||
self.mode = mode
|
||||
self.theme = theme
|
||||
self.isFlat = isFlat
|
||||
self.backgroundDetailsMode = backgroundDetailsMode
|
||||
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
}
|
||||
@ -340,7 +343,7 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
return nil
|
||||
}
|
||||
|
||||
public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
open func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
if !self.isViewLoaded {
|
||||
self.loadView()
|
||||
}
|
||||
@ -836,7 +839,11 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
flatContainer.keyboardViewManager = nil
|
||||
flatContainer.canHaveKeyboardFocus = false
|
||||
}
|
||||
self.displayNode.insertSubnode(flatContainer, at: 0)
|
||||
if let detailsPlaceholderNode = self.detailsPlaceholderNode {
|
||||
self.displayNode.insertSubnode(flatContainer, aboveSubnode: detailsPlaceholderNode)
|
||||
} else {
|
||||
self.displayNode.insertSubnode(flatContainer, at: 0)
|
||||
}
|
||||
self.rootContainer = .flat(flatContainer)
|
||||
flatContainer.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
flatContainer.update(layout: layout, canBeClosed: false, controllers: controllers, transition: .immediate)
|
||||
@ -859,7 +866,11 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
flatContainer.keyboardViewManager = nil
|
||||
flatContainer.canHaveKeyboardFocus = false
|
||||
}
|
||||
self.displayNode.insertSubnode(flatContainer, at: 0)
|
||||
if let detailsPlaceholderNode = self.detailsPlaceholderNode {
|
||||
self.displayNode.insertSubnode(flatContainer, aboveSubnode: detailsPlaceholderNode)
|
||||
} else {
|
||||
self.displayNode.insertSubnode(flatContainer, at: 0)
|
||||
}
|
||||
self.rootContainer = .flat(flatContainer)
|
||||
flatContainer.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
flatContainer.update(layout: layout, canBeClosed: false, controllers: controllers, transition: .immediate)
|
||||
@ -873,7 +884,11 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
}, scrollToTop: { [weak self] subject in
|
||||
self?.scrollToTop(subject)
|
||||
})
|
||||
self.displayNode.insertSubnode(splitContainer, at: 0)
|
||||
if let detailsPlaceholderNode = self.detailsPlaceholderNode {
|
||||
self.displayNode.insertSubnode(splitContainer, aboveSubnode: detailsPlaceholderNode)
|
||||
} else {
|
||||
self.displayNode.insertSubnode(splitContainer, at: 0)
|
||||
}
|
||||
self.rootContainer = .split(splitContainer)
|
||||
if previousModalContainer == nil {
|
||||
splitContainer.canHaveKeyboardFocus = true
|
||||
@ -881,7 +896,7 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
splitContainer.canHaveKeyboardFocus = false
|
||||
}
|
||||
splitContainer.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
splitContainer.update(layout: layout, masterControllers: masterControllers, detailControllers: detailControllers, transition: .immediate)
|
||||
splitContainer.update(layout: layout, masterControllers: masterControllers, detailControllers: detailControllers, detailsPlaceholderNode: self.detailsPlaceholderNode, transition: .immediate)
|
||||
flatContainer.statusBarStyleUpdated = nil
|
||||
flatContainer.removeFromSupernode()
|
||||
case let .split(splitContainer):
|
||||
@ -891,7 +906,7 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
splitContainer.canHaveKeyboardFocus = false
|
||||
}
|
||||
transition.updateFrame(node: splitContainer, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
splitContainer.update(layout: layout, masterControllers: masterControllers, detailControllers: detailControllers, transition: transition)
|
||||
splitContainer.update(layout: layout, masterControllers: masterControllers, detailControllers: detailControllers, detailsPlaceholderNode: self.detailsPlaceholderNode, transition: transition)
|
||||
}
|
||||
} else {
|
||||
let splitContainer = NavigationSplitContainer(theme: self.theme, controllerRemoved: { [weak self] controller in
|
||||
@ -899,7 +914,11 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
}, scrollToTop: { [weak self] subject in
|
||||
self?.scrollToTop(subject)
|
||||
})
|
||||
self.displayNode.insertSubnode(splitContainer, at: 0)
|
||||
if let detailsPlaceholderNode = self.detailsPlaceholderNode {
|
||||
self.displayNode.insertSubnode(splitContainer, aboveSubnode: detailsPlaceholderNode)
|
||||
} else {
|
||||
self.displayNode.insertSubnode(splitContainer, at: 0)
|
||||
}
|
||||
self.rootContainer = .split(splitContainer)
|
||||
if previousModalContainer == nil {
|
||||
splitContainer.canHaveKeyboardFocus = true
|
||||
@ -907,7 +926,7 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
splitContainer.canHaveKeyboardFocus = false
|
||||
}
|
||||
splitContainer.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
splitContainer.update(layout: layout, masterControllers: masterControllers, detailControllers: detailControllers, transition: .immediate)
|
||||
splitContainer.update(layout: layout, masterControllers: masterControllers, detailControllers: detailControllers, detailsPlaceholderNode: self.detailsPlaceholderNode, transition: .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ final class NavigationSplitContainer: ASDisplayNode {
|
||||
self.separator.backgroundColor = theme.navigationBar.separatorColor
|
||||
}
|
||||
|
||||
func update(layout: ContainerViewLayout, masterControllers: [ViewController], detailControllers: [ViewController], transition: ContainedViewLayoutTransition) {
|
||||
func update(layout: ContainerViewLayout, masterControllers: [ViewController], detailControllers: [ViewController], detailsPlaceholderNode: NavigationDetailsPlaceholderNode?, transition: ContainedViewLayoutTransition) {
|
||||
let masterWidth: CGFloat = min(max(320.0, floor(layout.size.width / 3.0)), floor(layout.size.width / 2.0))
|
||||
let detailWidth = layout.size.width - masterWidth
|
||||
|
||||
@ -94,6 +94,12 @@ 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)))
|
||||
|
||||
if let detailsPlaceholderNode {
|
||||
let needsTiling = layout.size.width > layout.size.height
|
||||
detailsPlaceholderNode.updateLayout(size: CGSize(width: detailWidth, height: layout.size.height), needsTiling: needsTiling, transition: transition)
|
||||
transition.updateFrame(node: detailsPlaceholderNode, frame: CGRect(origin: CGPoint(x: masterWidth, y: 0.0), size: CGSize(width: detailWidth, 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, additionalInsets: UIEdgeInsets(), 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)
|
||||
|
||||
|
@ -271,6 +271,22 @@ public final class GradientBackgroundNode: ASDisplayNode {
|
||||
|
||||
private var patternOverlayLayer: GradientBackgroundPatternOverlayLayer?
|
||||
|
||||
private class SharedAnimationUpdate {
|
||||
let phase: Int
|
||||
let sender: AnyObject
|
||||
|
||||
init(
|
||||
phase: Int,
|
||||
sender: AnyObject
|
||||
) {
|
||||
self.phase = phase
|
||||
self.sender = sender
|
||||
}
|
||||
}
|
||||
|
||||
private static let sharedAnimationSyncPipe = ValuePipe<SharedAnimationUpdate>()
|
||||
private var sharedAnimationSyncDisposable: Disposable?
|
||||
|
||||
public init(colors: [UIColor]? = nil, useSharedAnimationPhase: Bool = false, adjustSaturation: Bool = true) {
|
||||
self.useSharedAnimationPhase = useSharedAnimationPhase
|
||||
self.saturation = adjustSaturation ? 1.7 : 1.0
|
||||
@ -289,12 +305,26 @@ public final class GradientBackgroundNode: ASDisplayNode {
|
||||
|
||||
if useSharedAnimationPhase {
|
||||
self.phase = GradientBackgroundNode.sharedPhase
|
||||
|
||||
self.sharedAnimationSyncDisposable = (GradientBackgroundNode.sharedAnimationSyncPipe.signal()
|
||||
|> filter { [weak self] update in
|
||||
return update.sender !== self
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { [weak self] update in
|
||||
if let self {
|
||||
self.phase = update.phase
|
||||
if let size = self.validLayout {
|
||||
self.updateLayout(size: size, transition: .immediate, extendAnimation: false, backwards: false, completion: {})
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
self.phase = 0
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.sharedAnimationSyncDisposable?.dispose()
|
||||
}
|
||||
|
||||
public func setPatternOverlay(layer: GradientBackgroundPatternOverlayLayer?) {
|
||||
@ -422,8 +452,7 @@ public final class GradientBackgroundNode: ASDisplayNode {
|
||||
animation.fillMode = .backwards
|
||||
animation.beginTime = self.contentView.layer.convertTime(CACurrentMediaTime(), from: nil) + 0.25
|
||||
}
|
||||
|
||||
|
||||
|
||||
self.isAnimating = true
|
||||
if let patternOverlayLayer = self.patternOverlayLayer {
|
||||
patternOverlayLayer.isAnimating = true
|
||||
@ -542,6 +571,8 @@ public final class GradientBackgroundNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public func animateEvent(transition: ContainedViewLayoutTransition, extendAnimation: Bool, backwards: Bool, completion: @escaping () -> Void) {
|
||||
guard case let .animated(duration, _) = transition, duration > 0.001 else {
|
||||
@ -560,6 +591,7 @@ public final class GradientBackgroundNode: ASDisplayNode {
|
||||
}
|
||||
if self.useSharedAnimationPhase {
|
||||
GradientBackgroundNode.sharedPhase = self.phase
|
||||
GradientBackgroundNode.sharedAnimationSyncPipe.putNext(SharedAnimationUpdate(phase: self.phase, sender: self))
|
||||
}
|
||||
if let size = self.validLayout {
|
||||
self.updateLayout(size: size, transition: transition, extendAnimation: extendAnimation, backwards: backwards, completion: completion)
|
||||
|
@ -287,9 +287,7 @@ public class InvisibleInkDustNode: ASDisplayNode {
|
||||
return
|
||||
}
|
||||
self.staticParams = (size, color, lineRects)
|
||||
|
||||
let start = CACurrentMediaTime()
|
||||
|
||||
|
||||
var combinedRect: CGRect?
|
||||
var combinedRects: [CGRect] = []
|
||||
for rect in lineRects {
|
||||
@ -308,7 +306,6 @@ public class InvisibleInkDustNode: ASDisplayNode {
|
||||
combinedRects.append(combinedRect.insetBy(dx: 0.0, dy: -1.0))
|
||||
}
|
||||
|
||||
print("combining \(CACurrentMediaTime() - start)")
|
||||
Queue.concurrentDefaultQueue().async {
|
||||
var generator = ArbitraryRandomNumberGenerator(seed: 1)
|
||||
let image = generateImage(size, rotatedContext: { size, context in
|
||||
@ -331,8 +328,6 @@ public class InvisibleInkDustNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
self.staticNode?.frame = CGRect(origin: CGPoint(), size: size)
|
||||
|
||||
print("total draw \(CACurrentMediaTime() - start)")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,14 +32,14 @@ public enum ChatTitleContent: Equatable {
|
||||
case replies
|
||||
}
|
||||
|
||||
case peer(peerView: PeerView, customTitle: String?, onlineMemberCount: Int32?, isScheduledMessages: Bool, isMuted: Bool?, customMessageCount: Int?)
|
||||
case peer(peerView: PeerView, customTitle: String?, onlineMemberCount: Int32?, isScheduledMessages: Bool, isMuted: Bool?, customMessageCount: Int?, isEnabled: Bool)
|
||||
case replyThread(type: ReplyThreadType, count: Int)
|
||||
case custom(String, String?, Bool)
|
||||
|
||||
public static func ==(lhs: ChatTitleContent, rhs: ChatTitleContent) -> Bool {
|
||||
switch lhs {
|
||||
case let .peer(peerView, customTitle, onlineMemberCount, isScheduledMessages, isMuted, customMessageCount):
|
||||
if case let .peer(rhsPeerView, rhsCustomTitle, rhsOnlineMemberCount, rhsIsScheduledMessages, rhsIsMuted, rhsCustomMessageCount) = rhs {
|
||||
case let .peer(peerView, customTitle, onlineMemberCount, isScheduledMessages, isMuted, customMessageCount, isEnabled):
|
||||
if case let .peer(rhsPeerView, rhsCustomTitle, rhsOnlineMemberCount, rhsIsScheduledMessages, rhsIsMuted, rhsCustomMessageCount, rhsIsEnabled) = rhs {
|
||||
if peerView !== rhsPeerView {
|
||||
return false
|
||||
}
|
||||
@ -58,7 +58,9 @@ public enum ChatTitleContent: Equatable {
|
||||
if customMessageCount != rhsCustomMessageCount {
|
||||
return false
|
||||
}
|
||||
|
||||
if isEnabled != rhsIsEnabled {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -169,7 +171,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
var titleCredibilityIcon: ChatTitleCredibilityIcon = .none
|
||||
var isEnabled = true
|
||||
switch titleContent {
|
||||
case let .peer(peerView, customTitle, _, isScheduledMessages, isMuted, _):
|
||||
case let .peer(peerView, customTitle, _, isScheduledMessages, isMuted, _, isEnabledValue):
|
||||
if peerView.peerId.isReplies {
|
||||
let typeText: String = self.strings.DialogList_Replies
|
||||
segments = [.text(0, NSAttributedString(string: typeText, font: titleFont, textColor: titleTheme.rootController.navigationBar.primaryTextColor))]
|
||||
@ -225,6 +227,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
}
|
||||
}
|
||||
}
|
||||
isEnabled = isEnabledValue
|
||||
}
|
||||
case let .replyThread(type, count):
|
||||
let textFont = titleFont
|
||||
@ -365,7 +368,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
var inputActivitiesAllowed = true
|
||||
if let titleContent = self.titleContent {
|
||||
switch titleContent {
|
||||
case let .peer(peerView, _, _, isScheduledMessages, _, customMessageCount):
|
||||
case let .peer(peerView, _, _, isScheduledMessages, _, customMessageCount, _):
|
||||
if let peer = peerViewMainPeer(peerView) {
|
||||
if peer.id == self.context.account.peerId || isScheduledMessages || peer.id.isReplies {
|
||||
inputActivitiesAllowed = false
|
||||
@ -469,7 +472,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
} else {
|
||||
if let titleContent = self.titleContent {
|
||||
switch titleContent {
|
||||
case let .peer(peerView, customTitle, onlineMemberCount, isScheduledMessages, _, customMessageCount):
|
||||
case let .peer(peerView, customTitle, onlineMemberCount, isScheduledMessages, _, customMessageCount, _):
|
||||
if let customMessageCount = customMessageCount, customMessageCount != 0 {
|
||||
let string = NSAttributedString(string: self.strings.Conversation_Messages(Int32(customMessageCount)), font: subtitleFont, textColor: titleTheme.rootController.navigationBar.secondaryTextColor)
|
||||
state = .info(string, .generic)
|
||||
|
@ -4670,9 +4670,18 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
}
|
||||
|
||||
let hasPeerInfo: Signal<Bool, NoError>
|
||||
if peerId == context.account.peerId {
|
||||
hasPeerInfo = .single(true)
|
||||
|> then(
|
||||
hasAvailablePeerInfoMediaPanes(context: context, peerId: peerId)
|
||||
)
|
||||
} else {
|
||||
hasPeerInfo = .single(true)
|
||||
}
|
||||
|
||||
self.titleDisposable.set((combineLatest(queue: Queue.mainQueue(), peerView.get(), onlineMemberCount, displayedCountSignal, subtitleTextSignal, self.presentationInterfaceStatePromise.get())
|
||||
|> deliverOnMainQueue).start(next: { [weak self] peerView, onlineMemberCount, displayedCount, subtitleText, presentationInterfaceState in
|
||||
self.titleDisposable.set((combineLatest(queue: Queue.mainQueue(), peerView.get(), onlineMemberCount, displayedCountSignal, subtitleTextSignal, self.presentationInterfaceStatePromise.get(), hasPeerInfo)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] peerView, onlineMemberCount, displayedCount, subtitleText, presentationInterfaceState, hasPeerInfo in
|
||||
if let strongSelf = self {
|
||||
var isScheduledMessages = false
|
||||
if case .scheduledMessages = presentationInterfaceState.subject {
|
||||
@ -4723,7 +4732,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if case .pinnedMessages = presentationInterfaceState.subject {
|
||||
strongSelf.chatTitleView?.titleContent = .custom(presentationInterfaceState.strings.Chat_TitlePinnedMessages(Int32(displayedCount ?? 1)), nil, false)
|
||||
} else {
|
||||
strongSelf.chatTitleView?.titleContent = .peer(peerView: peerView, customTitle: nil, onlineMemberCount: onlineMemberCount, isScheduledMessages: isScheduledMessages, isMuted: nil, customMessageCount: nil)
|
||||
strongSelf.chatTitleView?.titleContent = .peer(peerView: peerView, customTitle: nil, onlineMemberCount: onlineMemberCount, isScheduledMessages: isScheduledMessages, isMuted: nil, customMessageCount: nil, isEnabled: hasPeerInfo)
|
||||
let imageOverride: AvatarNodeImageOverride?
|
||||
if strongSelf.context.account.peerId == peer.id {
|
||||
imageOverride = .savedMessagesIcon
|
||||
@ -5278,7 +5287,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
|
||||
if let threadInfo = messageAndTopic.threadData?.info {
|
||||
strongSelf.chatTitleView?.titleContent = .peer(peerView: peerView, customTitle: threadInfo.title, onlineMemberCount: onlineMemberCount, isScheduledMessages: false, isMuted: peerIsMuted, customMessageCount: messageAndTopic.messageCount == 0 ? nil : messageAndTopic.messageCount)
|
||||
strongSelf.chatTitleView?.titleContent = .peer(peerView: peerView, customTitle: threadInfo.title, onlineMemberCount: onlineMemberCount, isScheduledMessages: false, isMuted: peerIsMuted, customMessageCount: messageAndTopic.messageCount == 0 ? nil : messageAndTopic.messageCount, isEnabled: true)
|
||||
|
||||
let avatarContent: EmojiStatusComponent.Content
|
||||
if strongSelf.chatLocation.threadId == 1 {
|
||||
|
@ -801,7 +801,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
self.emptyNode = emptyNode
|
||||
self.historyNodeContainer.supernode?.insertSubnode(emptyNode, aboveSubnode: self.historyNodeContainer)
|
||||
if let (size, insets) = self.validEmptyNodeLayout {
|
||||
emptyNode.updateLayout(interfaceState: self.chatPresentationInterfaceState, emptyType: emptyType, loadingNode: wasLoading && self.loadingNode.supernode != nil ? self.loadingNode : nil, backgroundNode: self.backgroundNode, size: size, insets: insets, transition: .immediate)
|
||||
emptyNode.updateLayout(interfaceState: self.chatPresentationInterfaceState, subject: .emptyChat(emptyType), loadingNode: wasLoading && self.loadingNode.supernode != nil ? self.loadingNode : nil, backgroundNode: self.backgroundNode, size: size, insets: insets, transition: .immediate)
|
||||
}
|
||||
if animated {
|
||||
emptyNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
@ -1622,7 +1622,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
emptyNodeInsets.bottom += inputPanelsHeight
|
||||
self.validEmptyNodeLayout = (contentBounds.size, emptyNodeInsets)
|
||||
if let emptyNode = self.emptyNode, let emptyType = self.emptyType {
|
||||
emptyNode.updateLayout(interfaceState: self.chatPresentationInterfaceState, emptyType: emptyType, loadingNode: nil, backgroundNode: self.backgroundNode, size: contentBounds.size, insets: emptyNodeInsets, transition: transition)
|
||||
emptyNode.updateLayout(interfaceState: self.chatPresentationInterfaceState, subject: .emptyChat(emptyType), loadingNode: nil, backgroundNode: self.backgroundNode, size: contentBounds.size, insets: emptyNodeInsets, transition: transition)
|
||||
transition.updateFrame(node: emptyNode, frame: contentBounds)
|
||||
emptyNode.update(rect: contentBounds, within: contentBounds.size, transition: transition)
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import ComponentFlow
|
||||
import EmojiStatusComponent
|
||||
|
||||
private protocol ChatEmptyNodeContent {
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize
|
||||
}
|
||||
|
||||
private let titleFont = Font.medium(15.0)
|
||||
@ -36,7 +36,7 @@ private final class ChatEmptyNodeRegularChatContent: ASDisplayNode, ChatEmptyNod
|
||||
self.addSubnode(self.textNode)
|
||||
}
|
||||
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings {
|
||||
self.currentTheme = interfaceState.theme
|
||||
self.currentStrings = interfaceState.strings
|
||||
@ -44,12 +44,16 @@ private final class ChatEmptyNodeRegularChatContent: ASDisplayNode, ChatEmptyNod
|
||||
let serviceColor = serviceMessageColorComponents(theme: interfaceState.theme, wallpaper: interfaceState.chatWallpaper)
|
||||
|
||||
let text: String
|
||||
switch interfaceState.chatLocation {
|
||||
case .peer, .replyThread, .feed:
|
||||
if case .scheduledMessages = interfaceState.subject {
|
||||
text = interfaceState.strings.ScheduledMessages_EmptyPlaceholder
|
||||
} else {
|
||||
text = interfaceState.strings.Conversation_EmptyPlaceholder
|
||||
if case .detailsPlaceholder = subject {
|
||||
text = interfaceState.strings.ChatList_StartMessaging
|
||||
} else {
|
||||
switch interfaceState.chatLocation {
|
||||
case .peer, .replyThread, .feed:
|
||||
if case .scheduledMessages = interfaceState.subject {
|
||||
text = interfaceState.strings.ScheduledMessages_EmptyPlaceholder
|
||||
} else {
|
||||
text = interfaceState.strings.Conversation_EmptyPlaceholder
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,7 +144,7 @@ final class ChatEmptyNodeGreetingChatContent: ASDisplayNode, ChatEmptyNodeSticke
|
||||
let _ = self.interaction?.sendSticker(.standalone(media: stickerItem.stickerItem.file), false, self.view, self.stickerNode.bounds, nil, [])
|
||||
}
|
||||
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings {
|
||||
self.currentTheme = interfaceState.theme
|
||||
self.currentStrings = interfaceState.strings
|
||||
@ -309,7 +313,7 @@ final class ChatEmptyNodeNearbyChatContent: ASDisplayNode, ChatEmptyNodeStickerC
|
||||
let _ = self.interaction?.sendSticker(.standalone(media: stickerItem.stickerItem.file), false, self.view, self.stickerNode.bounds, nil, [])
|
||||
}
|
||||
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings {
|
||||
self.currentTheme = interfaceState.theme
|
||||
self.currentStrings = interfaceState.strings
|
||||
@ -442,7 +446,7 @@ private final class ChatEmptyNodeSecretChatContent: ASDisplayNode, ChatEmptyNode
|
||||
self.addSubnode(self.subtitleNode)
|
||||
}
|
||||
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings {
|
||||
self.currentTheme = interfaceState.theme
|
||||
self.currentStrings = interfaceState.strings
|
||||
@ -576,7 +580,7 @@ private final class ChatEmptyNodeGroupChatContent: ASDisplayNode, ChatEmptyNodeC
|
||||
self.addSubnode(self.subtitleNode)
|
||||
}
|
||||
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings {
|
||||
self.currentTheme = interfaceState.theme
|
||||
self.currentStrings = interfaceState.strings
|
||||
@ -691,7 +695,7 @@ private final class ChatEmptyNodeCloudChatContent: ASDisplayNode, ChatEmptyNodeC
|
||||
self.addSubnode(self.titleNode)
|
||||
}
|
||||
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings {
|
||||
self.currentTheme = interfaceState.theme
|
||||
self.currentStrings = interfaceState.strings
|
||||
@ -813,7 +817,7 @@ final class ChatEmptyNodeTopicChatContent: ASDisplayNode, ChatEmptyNodeContent,
|
||||
self.addSubnode(self.textNode)
|
||||
}
|
||||
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
let serviceColor = serviceMessageColorComponents(theme: interfaceState.theme, wallpaper: interfaceState.chatWallpaper)
|
||||
if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings {
|
||||
self.currentTheme = interfaceState.theme
|
||||
@ -900,6 +904,10 @@ private enum ChatEmptyNodeContentType: Equatable {
|
||||
}
|
||||
|
||||
final class ChatEmptyNode: ASDisplayNode {
|
||||
enum Subject {
|
||||
case emptyChat(ChatHistoryNodeLoadState.EmptyType)
|
||||
case detailsPlaceholder
|
||||
}
|
||||
private let context: AccountContext
|
||||
private let interaction: ChatPanelInterfaceInteraction?
|
||||
|
||||
@ -953,7 +961,7 @@ final class ChatEmptyNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, emptyType: ChatHistoryNodeLoadState.EmptyType, loadingNode: ChatLoadingNode?, backgroundNode: WallpaperBackgroundNode?, size: CGSize, insets: UIEdgeInsets, transition: ContainedViewLayoutTransition) {
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: Subject, loadingNode: ChatLoadingNode?, backgroundNode: WallpaperBackgroundNode?, size: CGSize, insets: UIEdgeInsets, transition: ContainedViewLayoutTransition) {
|
||||
self.wallpaperBackgroundNode = backgroundNode
|
||||
|
||||
if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings {
|
||||
@ -969,38 +977,43 @@ final class ChatEmptyNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
let contentType: ChatEmptyNodeContentType
|
||||
if case .replyThread = interfaceState.chatLocation {
|
||||
if case .topic = emptyType {
|
||||
contentType = .topic
|
||||
} else {
|
||||
contentType = .regular
|
||||
}
|
||||
} else if let peer = interfaceState.renderedPeer?.peer, !isScheduledMessages {
|
||||
if peer.id == self.context.account.peerId {
|
||||
contentType = .cloud
|
||||
} else if let _ = peer as? TelegramSecretChat {
|
||||
contentType = .secret
|
||||
} else if let group = peer as? TelegramGroup, case .creator = group.role {
|
||||
contentType = .group
|
||||
} else if let channel = peer as? TelegramChannel, case .group = channel.info, channel.flags.contains(.isCreator) && !channel.flags.contains(.isGigagroup) {
|
||||
contentType = .group
|
||||
} else if let _ = interfaceState.peerNearbyData {
|
||||
contentType = .peerNearby
|
||||
} else if let peer = peer as? TelegramUser {
|
||||
if peer.isDeleted || peer.botInfo != nil || peer.flags.contains(.isSupport) || peer.isScam || interfaceState.peerIsBlocked {
|
||||
contentType = .regular
|
||||
} else if case .clearedHistory = emptyType {
|
||||
contentType = .regular
|
||||
switch subject {
|
||||
case .detailsPlaceholder:
|
||||
contentType = .regular
|
||||
case let .emptyChat(emptyType):
|
||||
if case .replyThread = interfaceState.chatLocation {
|
||||
if case .topic = emptyType {
|
||||
contentType = .topic
|
||||
} else {
|
||||
contentType = .greeting
|
||||
contentType = .regular
|
||||
}
|
||||
} else if let peer = interfaceState.renderedPeer?.peer, !isScheduledMessages {
|
||||
if peer.id == self.context.account.peerId {
|
||||
contentType = .cloud
|
||||
} else if let _ = peer as? TelegramSecretChat {
|
||||
contentType = .secret
|
||||
} else if let group = peer as? TelegramGroup, case .creator = group.role {
|
||||
contentType = .group
|
||||
} else if let channel = peer as? TelegramChannel, case .group = channel.info, channel.flags.contains(.isCreator) && !channel.flags.contains(.isGigagroup) {
|
||||
contentType = .group
|
||||
} else if let _ = interfaceState.peerNearbyData {
|
||||
contentType = .peerNearby
|
||||
} else if let peer = peer as? TelegramUser {
|
||||
if peer.isDeleted || peer.botInfo != nil || peer.flags.contains(.isSupport) || peer.isScam || interfaceState.peerIsBlocked {
|
||||
contentType = .regular
|
||||
} else if case .clearedHistory = emptyType {
|
||||
contentType = .regular
|
||||
} else {
|
||||
contentType = .greeting
|
||||
}
|
||||
} else {
|
||||
contentType = .regular
|
||||
}
|
||||
} else {
|
||||
contentType = .regular
|
||||
}
|
||||
} else {
|
||||
contentType = .regular
|
||||
}
|
||||
|
||||
|
||||
var updateGreetingSticker = false
|
||||
var contentTransition = transition
|
||||
if self.content?.0 != contentType {
|
||||
@ -1044,7 +1057,7 @@ final class ChatEmptyNode: ASDisplayNode {
|
||||
|
||||
var contentSize = CGSize()
|
||||
if let contentNode = self.content?.1 {
|
||||
contentSize = contentNode.updateLayout(interfaceState: interfaceState, size: displayRect.size, transition: contentTransition)
|
||||
contentSize = contentNode.updateLayout(interfaceState: interfaceState, subject: subject, size: displayRect.size, transition: contentTransition)
|
||||
|
||||
if updateGreetingSticker {
|
||||
self.context.prefetchManager?.prepareNextGreetingSticker()
|
||||
|
@ -257,6 +257,18 @@ private enum PeerInfoScreenInputData: Equatable {
|
||||
case group(groupId: PeerId)
|
||||
}
|
||||
|
||||
public func hasAvailablePeerInfoMediaPanes(context: AccountContext, peerId: PeerId) -> Signal<Bool, NoError> {
|
||||
let chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(value: nil)
|
||||
return peerInfoAvailableMediaPanes(context: context, peerId: peerId, chatLocation: .peer(id: peerId), chatLocationContextHolder: chatLocationContextHolder)
|
||||
|> map { panes -> Bool in
|
||||
if let panes {
|
||||
return !panes.isEmpty
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func peerInfoAvailableMediaPanes(context: AccountContext, peerId: PeerId, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>) -> Signal<[PeerInfoPaneKey]?, NoError> {
|
||||
let tags: [(MessageTags, PeerInfoPaneKey)] = [
|
||||
(.photoOrVideo, .media),
|
||||
|
@ -15,6 +15,46 @@ import AppBundle
|
||||
import DatePickerNode
|
||||
import DebugSettingsUI
|
||||
import TabBarUI
|
||||
import WallpaperBackgroundNode
|
||||
import ChatPresentationInterfaceState
|
||||
|
||||
private class DetailsChatPlaceholderNode: ASDisplayNode, NavigationDetailsPlaceholderNode {
|
||||
private var presentationData: PresentationData
|
||||
private var presentationInterfaceState: ChatPresentationInterfaceState
|
||||
|
||||
let wallpaperBackgroundNode: WallpaperBackgroundNode
|
||||
let emptyNode: ChatEmptyNode
|
||||
|
||||
init(context: AccountContext) {
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(id: context.account.peerId), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil)
|
||||
|
||||
self.wallpaperBackgroundNode = createWallpaperBackgroundNode(context: context, forChatDisplay: true, useSharedAnimationPhase: true)
|
||||
self.emptyNode = ChatEmptyNode(context: context, interaction: nil)
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.wallpaperBackgroundNode)
|
||||
self.addSubnode(self.emptyNode)
|
||||
}
|
||||
|
||||
func updatePresentationData(_ presentationData: PresentationData) {
|
||||
self.presentationData = presentationData
|
||||
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: self.presentationInterfaceState.limitsConfiguration, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: self.presentationInterfaceState.accountPeerId, mode: .standard(previewing: false), chatLocation: self.presentationInterfaceState.chatLocation, subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil)
|
||||
|
||||
self.wallpaperBackgroundNode.update(wallpaper: presentationData.chatWallpaper)
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize, needsTiling: Bool, transition: ContainedViewLayoutTransition) {
|
||||
let contentBounds = CGRect(origin: .zero, size: size)
|
||||
self.wallpaperBackgroundNode.updateLayout(size: size, displayMode: needsTiling ? .aspectFit : .aspectFill, transition: transition)
|
||||
transition.updateFrame(node: self.wallpaperBackgroundNode, frame: contentBounds)
|
||||
|
||||
self.emptyNode.updateLayout(interfaceState: self.presentationInterfaceState, subject: .detailsPlaceholder, loadingNode: nil, backgroundNode: self.wallpaperBackgroundNode, size: contentBounds.size, insets: .zero, transition: transition)
|
||||
transition.updateFrame(node: self.emptyNode, frame: CGRect(origin: .zero, size: size))
|
||||
self.emptyNode.update(rect: contentBounds, within: contentBounds.size, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
public final class TelegramRootController: NavigationController {
|
||||
private let context: AccountContext
|
||||
@ -30,6 +70,8 @@ public final class TelegramRootController: NavigationController {
|
||||
private var presentationDataDisposable: Disposable?
|
||||
private var presentationData: PresentationData
|
||||
|
||||
private var detailsPlaceholderNode: DetailsChatPlaceholderNode?
|
||||
|
||||
private var applicationInFocusDisposable: Disposable?
|
||||
|
||||
public init(context: AccountContext) {
|
||||
@ -37,33 +79,13 @@ public final class TelegramRootController: NavigationController {
|
||||
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
let navigationDetailsBackgroundMode: NavigationEmptyDetailsBackgoundMode?
|
||||
switch presentationData.chatWallpaper {
|
||||
case .color:
|
||||
let image = generateTintedImage(image: UIImage(bundleImageName: "Chat List/EmptyMasterDetailIcon"), color: presentationData.theme.chatList.messageTextColor.withAlphaComponent(0.2))
|
||||
navigationDetailsBackgroundMode = image != nil ? .image(image!) : nil
|
||||
default:
|
||||
let image = chatControllerBackgroundImage(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper, mediaBox: context.account.postbox.mediaBox, knockoutMode: context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper)
|
||||
navigationDetailsBackgroundMode = image != nil ? .wallpaper(image!) : nil
|
||||
}
|
||||
|
||||
super.init(mode: .automaticMasterDetail, theme: NavigationControllerTheme(presentationTheme: self.presentationData.theme), backgroundDetailsMode: navigationDetailsBackgroundMode)
|
||||
super.init(mode: .automaticMasterDetail, theme: NavigationControllerTheme(presentationTheme: self.presentationData.theme))
|
||||
|
||||
self.presentationDataDisposable = (context.sharedContext.presentationData
|
||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
if presentationData.chatWallpaper != strongSelf.presentationData.chatWallpaper {
|
||||
let navigationDetailsBackgroundMode: NavigationEmptyDetailsBackgoundMode?
|
||||
switch presentationData.chatWallpaper {
|
||||
case .color:
|
||||
let image = generateTintedImage(image: UIImage(bundleImageName: "Chat List/EmptyMasterDetailIcon"), color: presentationData.theme.chatList.messageTextColor.withAlphaComponent(0.2))
|
||||
navigationDetailsBackgroundMode = image != nil ? .image(image!) : nil
|
||||
default:
|
||||
navigationDetailsBackgroundMode = chatControllerBackgroundImage(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper, mediaBox: strongSelf.context.sharedContext.accountManager.mediaBox, knockoutMode: strongSelf.context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper).flatMap(NavigationEmptyDetailsBackgoundMode.wallpaper)
|
||||
}
|
||||
strongSelf.updateBackgroundDetailsMode(navigationDetailsBackgroundMode, transition: .immediate)
|
||||
}
|
||||
|
||||
strongSelf.detailsPlaceholderNode?.updatePresentationData(presentationData)
|
||||
|
||||
let previousTheme = strongSelf.presentationData.theme
|
||||
strongSelf.presentationData = presentationData
|
||||
if previousTheme !== presentationData.theme {
|
||||
@ -92,6 +114,32 @@ public final class TelegramRootController: NavigationController {
|
||||
self.applicationInFocusDisposable?.dispose()
|
||||
}
|
||||
|
||||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
let needsRootWallpaperBackgroundNode: Bool
|
||||
if case .regular = layout.metrics.widthClass {
|
||||
needsRootWallpaperBackgroundNode = true
|
||||
} else {
|
||||
needsRootWallpaperBackgroundNode = false
|
||||
}
|
||||
|
||||
if needsRootWallpaperBackgroundNode {
|
||||
let detailsPlaceholderNode: DetailsChatPlaceholderNode
|
||||
if let current = self.detailsPlaceholderNode {
|
||||
detailsPlaceholderNode = current
|
||||
} else {
|
||||
detailsPlaceholderNode = DetailsChatPlaceholderNode(context: self.context)
|
||||
detailsPlaceholderNode.wallpaperBackgroundNode.update(wallpaper: self.presentationData.chatWallpaper)
|
||||
self.detailsPlaceholderNode = detailsPlaceholderNode
|
||||
}
|
||||
self.updateDetailsPlaceholderNode(detailsPlaceholderNode)
|
||||
} else if let _ = self.detailsPlaceholderNode {
|
||||
self.detailsPlaceholderNode = nil
|
||||
self.updateDetailsPlaceholderNode(nil)
|
||||
}
|
||||
|
||||
super.containerLayoutUpdated(layout, transition: transition)
|
||||
}
|
||||
|
||||
public func addRootControllers(showCallsTab: Bool) {
|
||||
let tabBarController = TabBarControllerImpl(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData), theme: TabBarControllerTheme(rootControllerTheme: self.presentationData.theme))
|
||||
tabBarController.navigationPresentation = .master
|
||||
|
Loading…
x
Reference in New Issue
Block a user