Merge commit '472699a7afb885fd9026772cad0968628c8f71c8'

This commit is contained in:
Ali 2021-03-23 19:07:18 +04:00
commit 088fdc247a
21 changed files with 220 additions and 128 deletions

View File

@ -302,7 +302,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
let previousEditingAndNetworkState = previousEditingAndNetworkStateValue.swap((stateAndFilterId.state.editing, networkState)) let previousEditingAndNetworkState = previousEditingAndNetworkStateValue.swap((stateAndFilterId.state.editing, networkState))
if stateAndFilterId.state.editing { if stateAndFilterId.state.editing {
if strongSelf.groupId == .root { if strongSelf.groupId == .root {
strongSelf.navigationItem.rightBarButtonItem = nil strongSelf.navigationItem.setRightBarButton(nil, animated: true)
} }
let title = !stateAndFilterId.state.selectedPeerIds.isEmpty ? strongSelf.presentationData.strings.ChatList_SelectedChats(Int32(stateAndFilterId.state.selectedPeerIds.count)) : defaultTitle let title = !stateAndFilterId.state.selectedPeerIds.isEmpty ? strongSelf.presentationData.strings.ChatList_SelectedChats(Int32(stateAndFilterId.state.selectedPeerIds.count)) : defaultTitle
@ -315,10 +315,10 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
strongSelf.titleView.setTitle(NetworkStatusTitle(text: title, activity: false, hasProxy: false, connectsViaProxy: false, isPasscodeSet: false, isManuallyLocked: false), animated: animated) strongSelf.titleView.setTitle(NetworkStatusTitle(text: title, activity: false, hasProxy: false, connectsViaProxy: false, isPasscodeSet: false, isManuallyLocked: false), animated: animated)
} else if isReorderingTabs { } else if isReorderingTabs {
if strongSelf.groupId == .root { if strongSelf.groupId == .root {
strongSelf.navigationItem.rightBarButtonItem = nil strongSelf.navigationItem.setRightBarButton(nil, animated: true)
} }
let leftBarButtonItem = UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Done, style: .done, target: strongSelf, action: #selector(strongSelf.reorderingDonePressed)) let leftBarButtonItem = UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Done, style: .done, target: strongSelf, action: #selector(strongSelf.reorderingDonePressed))
strongSelf.navigationItem.leftBarButtonItem = leftBarButtonItem strongSelf.navigationItem.setLeftBarButton(leftBarButtonItem, animated: true)
let (_, connectsViaProxy) = proxy let (_, connectsViaProxy) = proxy
switch networkState { switch networkState {
@ -341,16 +341,21 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
isRoot = true isRoot = true
if isReorderingTabs { if isReorderingTabs {
strongSelf.navigationItem.rightBarButtonItem = nil strongSelf.navigationItem.setRightBarButton(nil, animated: true)
} else { } else {
let rightBarButtonItem = UIBarButtonItem(image: PresentationResourcesRootController.navigationComposeIcon(strongSelf.presentationData.theme), style: .plain, target: strongSelf, action: #selector(strongSelf.composePressed)) let rightBarButtonItem = UIBarButtonItem(image: PresentationResourcesRootController.navigationComposeIcon(strongSelf.presentationData.theme), style: .plain, target: strongSelf, action: #selector(strongSelf.composePressed))
rightBarButtonItem.accessibilityLabel = strongSelf.presentationData.strings.VoiceOver_Navigation_Compose rightBarButtonItem.accessibilityLabel = strongSelf.presentationData.strings.VoiceOver_Navigation_Compose
strongSelf.navigationItem.rightBarButtonItem = rightBarButtonItem if strongSelf.navigationItem.rightBarButtonItem?.accessibilityLabel != rightBarButtonItem.accessibilityLabel {
strongSelf.navigationItem.setRightBarButton(rightBarButtonItem, animated: true)
}
} }
if isReorderingTabs { if isReorderingTabs {
let leftBarButtonItem = UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Done, style: .done, target: strongSelf, action: #selector(strongSelf.reorderingDonePressed)) let leftBarButtonItem = UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Done, style: .done, target: strongSelf, action: #selector(strongSelf.reorderingDonePressed))
strongSelf.navigationItem.leftBarButtonItem = leftBarButtonItem leftBarButtonItem.accessibilityLabel = strongSelf.presentationData.strings.Common_Done
if strongSelf.navigationItem.leftBarButtonItem?.accessibilityLabel != leftBarButtonItem.accessibilityLabel {
strongSelf.navigationItem.setLeftBarButton(leftBarButtonItem, animated: true)
}
} else { } else {
let editItem: UIBarButtonItem let editItem: UIBarButtonItem
if stateAndFilterId.state.editing { if stateAndFilterId.state.editing {
@ -360,7 +365,9 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
editItem = UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Edit, style: .plain, target: self, action: #selector(strongSelf.editPressed)) editItem = UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Edit, style: .plain, target: self, action: #selector(strongSelf.editPressed))
editItem.accessibilityLabel = strongSelf.presentationData.strings.Common_Edit editItem.accessibilityLabel = strongSelf.presentationData.strings.Common_Edit
} }
strongSelf.navigationItem.leftBarButtonItem = editItem if strongSelf.navigationItem.leftBarButtonItem?.accessibilityLabel != editItem.accessibilityLabel {
strongSelf.navigationItem.setLeftBarButton(editItem, animated: true)
}
} }
} }
@ -904,6 +911,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
} }
} }
let previousToolbarValue = Atomic<Toolbar?>(value: nil)
self.stateDisposable.set(combineLatest(queue: .mainQueue(), self.stateDisposable.set(combineLatest(queue: .mainQueue(),
self.presentationDataValue.get(), self.presentationDataValue.get(),
peerIdsAndOptions peerIdsAndOptions
@ -954,7 +962,12 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
toolbar = Toolbar(leftAction: leftAction, rightAction: ToolbarAction(title: presentationData.strings.Common_Delete, isEnabled: options.delete), middleAction: middleAction) toolbar = Toolbar(leftAction: leftAction, rightAction: ToolbarAction(title: presentationData.strings.Common_Delete, isEnabled: options.delete), middleAction: middleAction)
} }
} }
strongSelf.setToolbar(toolbar, transition: .animated(duration: 0.3, curve: .easeInOut)) var transition: ContainedViewLayoutTransition = .immediate
let previousToolbar = previousToolbarValue.swap(toolbar)
if (previousToolbar == nil) != (toolbar == nil) {
transition = .animated(duration: 0.3, curve: .easeInOut)
}
strongSelf.setToolbar(toolbar, transition: transition)
})) }))
self.tabContainerNode.tabSelected = { [weak self] id in self.tabContainerNode.tabSelected = { [weak self] id in
@ -1445,13 +1458,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
@objc private func donePressed() { @objc private func donePressed() {
self.reorderingDonePressed() self.reorderingDonePressed()
let editItem = UIBarButtonItem(title: self.presentationData.strings.Common_Edit, style: .plain, target: self, action: #selector(self.editPressed))
editItem.accessibilityLabel = self.presentationData.strings.Common_Edit
if case .root = self.groupId, self.filter == nil {
self.navigationItem.setLeftBarButton(editItem, animated: true)
} else {
self.navigationItem.setRightBarButton(editItem, animated: true)
}
(self.navigationController as? NavigationController)?.updateMasterDetailsBlackout(nil, transition: .animated(duration: 0.4, curve: .spring)) (self.navigationController as? NavigationController)?.updateMasterDetailsBlackout(nil, transition: .animated(duration: 0.4, curve: .spring))
self.searchContentNode?.setIsEnabled(true, animated: true) self.searchContentNode?.setIsEnabled(true, animated: true)
self.chatListDisplayNode.didBeginSelectingChatsWhileEditing = false self.chatListDisplayNode.didBeginSelectingChatsWhileEditing = false

View File

@ -1,6 +1,8 @@
import UIKit import UIKit
import AsyncDisplayKit import AsyncDisplayKit
private let titleFont = Font.with(size: 17.0, design: .regular, weight: .semibold, traits: [.monospacedNumbers])
private var backArrowImageCache: [Int32: UIImage] = [:] private var backArrowImageCache: [Int32: UIImage] = [:]
class SparseNode: ASDisplayNode { class SparseNode: ASDisplayNode {
@ -269,7 +271,7 @@ open class NavigationBar: ASDisplayNode {
private var title: String? { private var title: String? {
didSet { didSet {
if let title = self.title { if let title = self.title {
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(17.0), textColor: self.presentationData.theme.primaryTextColor) self.titleNode.attributedText = NSAttributedString(string: title, font: titleFont, textColor: self.presentationData.theme.primaryTextColor)
self.titleNode.accessibilityLabel = title self.titleNode.accessibilityLabel = title
if self.titleNode.supernode == nil { if self.titleNode.supernode == nil {
self.buttonsContainerNode.addSubnode(self.titleNode) self.buttonsContainerNode.addSubnode(self.titleNode)
@ -744,7 +746,7 @@ open class NavigationBar: ASDisplayNode {
self.rightButtonNode.rippleColor = self.presentationData.theme.primaryTextColor.withAlphaComponent(0.05) self.rightButtonNode.rippleColor = self.presentationData.theme.primaryTextColor.withAlphaComponent(0.05)
self.backButtonArrow.image = backArrowImage(color: self.presentationData.theme.buttonColor) self.backButtonArrow.image = backArrowImage(color: self.presentationData.theme.buttonColor)
if let title = self.title { if let title = self.title {
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(17.0), textColor: self.presentationData.theme.primaryTextColor) self.titleNode.attributedText = NSAttributedString(string: title, font: titleFont, textColor: self.presentationData.theme.primaryTextColor)
self.titleNode.accessibilityLabel = title self.titleNode.accessibilityLabel = title
} }
self.stripeNode.backgroundColor = self.presentationData.theme.separatorColor self.stripeNode.backgroundColor = self.presentationData.theme.separatorColor
@ -820,7 +822,7 @@ open class NavigationBar: ASDisplayNode {
self.rightButtonNode.rippleColor = self.presentationData.theme.primaryTextColor.withAlphaComponent(0.05) self.rightButtonNode.rippleColor = self.presentationData.theme.primaryTextColor.withAlphaComponent(0.05)
self.backButtonArrow.image = backArrowImage(color: self.presentationData.theme.buttonColor) self.backButtonArrow.image = backArrowImage(color: self.presentationData.theme.buttonColor)
if let title = self.title { if let title = self.title {
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(17.0), textColor: self.presentationData.theme.primaryTextColor) self.titleNode.attributedText = NSAttributedString(string: title, font: titleFont, textColor: self.presentationData.theme.primaryTextColor)
self.titleNode.accessibilityLabel = title self.titleNode.accessibilityLabel = title
} }
self.stripeNode.backgroundColor = self.presentationData.theme.separatorColor self.stripeNode.backgroundColor = self.presentationData.theme.separatorColor
@ -1079,7 +1081,7 @@ open class NavigationBar: ASDisplayNode {
} }
} else if let title = self.title { } else if let title = self.title {
let node = ImmediateTextNode() let node = ImmediateTextNode()
node.attributedText = NSAttributedString(string: title, font: Font.semibold(17.0), textColor: foregroundColor) node.attributedText = NSAttributedString(string: title, font: titleFont, textColor: foregroundColor)
return node return node
} else { } else {
return nil return nil

View File

@ -154,6 +154,8 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
var setPlayRate: ((Double) -> Void)? var setPlayRate: ((Double) -> Void)?
var fetchControl: (() -> Void)? var fetchControl: (() -> Void)?
var interacting: ((Bool) -> Void)?
private var seekTimer: SwiftSignalKit.Timer? private var seekTimer: SwiftSignalKit.Timer?
private var currentIsPaused: Bool = true private var currentIsPaused: Bool = true
private var seekRate: Double = 1.0 private var seekRate: Double = 1.0
@ -892,6 +894,8 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
if messages.count == 1 { if messages.count == 1 {
strongSelf.commitDeleteMessages(messages, ask: true) strongSelf.commitDeleteMessages(messages, ask: true)
} else { } else {
strongSelf.interacting?(true)
var presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } var presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
if !presentationData.theme.overallDarkAppearance { if !presentationData.theme.overallDarkAppearance {
presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme) presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
@ -930,8 +934,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
} }
} }
let actionSheet = ActionSheetController(presentationData: presentationData) let actionSheet = ActionSheetController(presentationData: presentationData)
actionSheet.dismissed = { [weak self] _ in
self?.interacting?(false)
}
let items: [ActionSheetItem] = [ let items: [ActionSheetItem] = [
ActionSheetButtonItem(title: singleText, color: .destructive, action: { [weak actionSheet] in ActionSheetButtonItem(title: singleText, color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
@ -1012,6 +1018,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: messages.map { $0.id }, type: .forEveryone).start() let _ = deleteMessagesInteractively(account: strongSelf.context.account, messageIds: messages.map { $0.id }, type: .forEveryone).start()
strongSelf.controllerInteraction?.dismissController() strongSelf.controllerInteraction?.dismissController()
} else if !items.isEmpty { } else if !items.isEmpty {
strongSelf.interacting?(true)
actionSheet.dismissed = { [weak self] _ in
self?.interacting?(false)
}
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: strongSelf.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in ActionSheetButtonItem(title: strongSelf.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
@ -1024,13 +1034,17 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
} }
@objc func actionButtonPressed() { @objc func actionButtonPressed() {
self.interacting?(true)
if let currentMessage = self.currentMessage { if let currentMessage = self.currentMessage {
let _ = (self.context.account.postbox.transaction { transaction -> [Message] in let _ = (self.context.account.postbox.transaction { transaction -> [Message] in
return transaction.getMessageGroup(currentMessage.id) ?? [] return transaction.getMessageGroup(currentMessage.id) ?? []
} |> deliverOnMainQueue).start(next: { [weak self] messages in } |> deliverOnMainQueue).start(next: { [weak self] messages in
if let strongSelf = self, !messages.isEmpty { if let strongSelf = self, !messages.isEmpty {
var presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } var presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
var forceTheme: PresentationTheme?
if !presentationData.theme.overallDarkAppearance { if !presentationData.theme.overallDarkAppearance {
forceTheme = defaultDarkColorPresentationTheme
presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme) presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
} }
var generalMessageContentKind: MessageContentKind? var generalMessageContentKind: MessageContentKind?
@ -1109,7 +1123,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
} }
} }
} }
let shareController = ShareController(context: strongSelf.context, subject: subject, preferredAction: preferredAction, forcedTheme: presentationData.theme.overallDarkAppearance ? nil : defaultDarkColorPresentationTheme) let shareController = ShareController(context: strongSelf.context, subject: subject, preferredAction: preferredAction, forceTheme: forceTheme)
shareController.dismissed = { [weak self] _ in
self?.interacting?(false)
}
shareController.completed = { [weak self] peerIds in shareController.completed = { [weak self] peerIds in
if let strongSelf = self { if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in
@ -1170,7 +1187,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
let shareAction: ([Message]) -> Void = { messages in let shareAction: ([Message]) -> Void = { messages in
if let strongSelf = self { if let strongSelf = self {
let shareController = ShareController(context: strongSelf.context, subject: .messages(messages), preferredAction: preferredAction, forcedTheme: presentationData.theme.overallDarkAppearance ? nil : defaultDarkColorPresentationTheme) let shareController = ShareController(context: strongSelf.context, subject: .messages(messages), preferredAction: preferredAction, forceTheme: forceTheme)
shareController.dismissed = { [weak self] _ in
self?.interacting?(false)
}
shareController.completed = { [weak self] peerIds in shareController.completed = { [weak self] peerIds in
if let strongSelf = self { if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in
@ -1240,7 +1260,9 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
}) })
} else if let (webPage, media) = self.currentWebPageAndMedia { } else if let (webPage, media) = self.currentWebPageAndMedia {
var presentationData = self.context.sharedContext.currentPresentationData.with { $0 } var presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
var forceTheme: PresentationTheme?
if !presentationData.theme.overallDarkAppearance { if !presentationData.theme.overallDarkAppearance {
forceTheme = defaultDarkColorPresentationTheme
presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme) presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
} }
@ -1265,7 +1287,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
if availableOpenInOptions(context: self.context, item: item).count > 1 { if availableOpenInOptions(context: self.context, item: item).count > 1 {
preferredAction = .custom(action: ShareControllerAction(title: presentationData.strings.Conversation_FileOpenIn, action: { [weak self] in preferredAction = .custom(action: ShareControllerAction(title: presentationData.strings.Conversation_FileOpenIn, action: { [weak self] in
if let strongSelf = self { if let strongSelf = self {
let openInController = OpenInActionSheetController(context: strongSelf.context, forceTheme: presentationData.theme.overallDarkAppearance ? nil : defaultDarkColorPresentationTheme, item: item, additionalAction: nil, openUrl: { [weak self] url in let openInController = OpenInActionSheetController(context: strongSelf.context, forceTheme: forceTheme, item: item, additionalAction: nil, openUrl: { [weak self] url in
if let strongSelf = self { if let strongSelf = self {
strongSelf.context.sharedContext.openExternalUrl(context: strongSelf.context, urlContext: .generic, url: url, forceExternal: true, presentationData: presentationData, navigationController: nil, dismissInput: {}) strongSelf.context.sharedContext.openExternalUrl(context: strongSelf.context, urlContext: .generic, url: url, forceExternal: true, presentationData: presentationData, navigationController: nil, dismissInput: {})
} }
@ -1290,7 +1312,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
} }
} }
} }
let shareController = ShareController(context: self.context, subject: subject, preferredAction: preferredAction, forcedTheme: presentationData.theme.overallDarkAppearance ? nil : defaultDarkColorPresentationTheme) let shareController = ShareController(context: self.context, subject: subject, preferredAction: preferredAction, forceTheme: forceTheme)
shareController.dismissed = { [weak self] _ in
self?.interacting?(false)
}
shareController.completed = { [weak self] peerIds in shareController.completed = { [weak self] peerIds in
if let strongSelf = self { if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in

View File

@ -120,7 +120,7 @@ final class ChatVideoGalleryItemScrubberView: UIView {
self.fetchStatusDisposable.dispose() self.fetchStatusDisposable.dispose()
} }
var collapsed: Bool = false var collapsed: Bool?
func setCollapsed(_ collapsed: Bool, animated: Bool) { func setCollapsed(_ collapsed: Bool, animated: Bool) {
guard self.collapsed != collapsed else { guard self.collapsed != collapsed else {
return return
@ -128,15 +128,14 @@ final class ChatVideoGalleryItemScrubberView: UIView {
self.collapsed = collapsed self.collapsed = collapsed
guard let (size, _, _) = self.containerLayout else {
return
}
let alpha: CGFloat = collapsed ? 0.0 : 1.0 let alpha: CGFloat = collapsed ? 0.0 : 1.0
self.leftTimestampNode.alpha = alpha self.leftTimestampNode.alpha = alpha
self.rightTimestampNode.alpha = alpha self.rightTimestampNode.alpha = alpha
self.infoNode.alpha = size.width < size.height && !self.collapsed ? 1.0 : 0.0
self.updateScrubberVisibility(animated: animated) self.updateScrubberVisibility(animated: animated)
if let (size, _, _) = self.containerLayout {
self.infoNode.alpha = size.width < size.height && !collapsed ? 1.0 : 0.0
}
} }
private func updateScrubberVisibility(animated: Bool) { private func updateScrubberVisibility(animated: Bool) {
@ -144,10 +143,10 @@ final class ChatVideoGalleryItemScrubberView: UIView {
var alpha: CGFloat = 1.0 var alpha: CGFloat = 1.0
if let playbackStatus = self.playbackStatus, playbackStatus.duration <= 30.0 { if let playbackStatus = self.playbackStatus, playbackStatus.duration <= 30.0 {
} else { } else {
alpha = self.collapsed ? 0.0 : 1.0 alpha = self.collapsed == true ? 0.0 : 1.0
collapsed = false collapsed = false
} }
self.scrubberNode.setCollapsed(collapsed, animated: animated) self.scrubberNode.setCollapsed(collapsed == true, animated: animated)
let transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.3, curve: .linear) : .immediate let transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.3, curve: .linear) : .immediate
transition.updateAlpha(node: self.scrubberNode, alpha: alpha) transition.updateAlpha(node: self.scrubberNode, alpha: alpha)
} }
@ -285,7 +284,7 @@ final class ChatVideoGalleryItemScrubberView: UIView {
let infoSize = self.infoNode.measure(infoConstrainedSize) let infoSize = self.infoNode.measure(infoConstrainedSize)
self.infoNode.bounds = CGRect(origin: CGPoint(), size: infoSize) self.infoNode.bounds = CGRect(origin: CGPoint(), size: infoSize)
transition.updatePosition(node: self.infoNode, position: CGPoint(x: size.width / 2.0, y: infoOffset + infoSize.height / 2.0)) transition.updatePosition(node: self.infoNode, position: CGPoint(x: size.width / 2.0, y: infoOffset + infoSize.height / 2.0))
self.infoNode.alpha = size.width < size.height && !self.collapsed ? 1.0 : 0.0 self.infoNode.alpha = size.width < size.height && self.collapsed == false ? 1.0 : 0.0
self.scrubberNode.frame = CGRect(origin: CGPoint(x: scrubberInset, y: 6.0), size: CGSize(width: size.width - leftInset - rightInset - scrubberInset * 2.0, height: scrubberHeight)) self.scrubberNode.frame = CGRect(origin: CGPoint(x: scrubberInset, y: 6.0), size: CGSize(width: size.width - leftInset - rightInset - scrubberInset * 2.0, height: scrubberHeight))
} }

View File

@ -6,6 +6,7 @@ import Display
public final class GalleryFooterNode: ASDisplayNode { public final class GalleryFooterNode: ASDisplayNode {
private let backgroundNode: ASDisplayNode private let backgroundNode: ASDisplayNode
private var currentThumbnailPanelHeight: CGFloat?
private var currentFooterContentNode: GalleryFooterContentNode? private var currentFooterContentNode: GalleryFooterContentNode?
private var currentOverlayContentNode: GalleryOverlayContentNode? private var currentOverlayContentNode: GalleryOverlayContentNode?
private var currentLayout: (ContainerViewLayout, CGFloat, Bool)? private var currentLayout: (ContainerViewLayout, CGFloat, Bool)?
@ -36,11 +37,16 @@ public final class GalleryFooterNode: ASDisplayNode {
let cleanInsets = layout.insets(options: []) let cleanInsets = layout.insets(options: [])
var dismissedCurrentFooterContentNode: GalleryFooterContentNode? var dismissedCurrentFooterContentNode: GalleryFooterContentNode?
var dismissedThumbnailPanelHeight: CGFloat?
if self.currentFooterContentNode !== footerContentNode { if self.currentFooterContentNode !== footerContentNode {
if let currentFooterContentNode = self.currentFooterContentNode { if let currentFooterContentNode = self.currentFooterContentNode {
currentFooterContentNode.requestLayout = nil currentFooterContentNode.requestLayout = nil
dismissedCurrentFooterContentNode = currentFooterContentNode dismissedCurrentFooterContentNode = currentFooterContentNode
} }
if let currentThumbnailPanelHeight = self.currentThumbnailPanelHeight {
dismissedThumbnailPanelHeight = currentThumbnailPanelHeight
}
self.currentThumbnailPanelHeight = thumbnailPanelHeight
self.currentFooterContentNode = footerContentNode self.currentFooterContentNode = footerContentNode
if let footerContentNode = footerContentNode { if let footerContentNode = footerContentNode {
footerContentNode.setVisibilityAlpha(self.visibilityAlpha, animated: transition.isAnimated) footerContentNode.setVisibilityAlpha(self.visibilityAlpha, animated: transition.isAnimated)
@ -68,10 +74,11 @@ public final class GalleryFooterNode: ASDisplayNode {
} }
} }
let effectiveThumbnailPanelHeight = self.currentThumbnailPanelHeight ?? thumbnailPanelHeight
var backgroundHeight: CGFloat = 0.0 var backgroundHeight: CGFloat = 0.0
let verticalOffset: CGFloat = isHidden ? (layout.size.width > layout.size.height ? 44.0 : (thumbnailPanelHeight > 0.0 ? 106.0 : 54.0)) : 0.0 let verticalOffset: CGFloat = isHidden ? (layout.size.width > layout.size.height ? 44.0 : (effectiveThumbnailPanelHeight > 0.0 ? 106.0 : 54.0)) : 0.0
if let footerContentNode = self.currentFooterContentNode { if let footerContentNode = self.currentFooterContentNode {
backgroundHeight = footerContentNode.updateLayout(size: layout.size, metrics: layout.metrics, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: cleanInsets.bottom, contentInset: thumbnailPanelHeight, transition: transition) backgroundHeight = footerContentNode.updateLayout(size: layout.size, metrics: layout.metrics, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: cleanInsets.bottom, contentInset: effectiveThumbnailPanelHeight, transition: transition)
transition.updateFrame(node: footerContentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - backgroundHeight + verticalOffset), size: CGSize(width: layout.size.width, height: backgroundHeight))) transition.updateFrame(node: footerContentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - backgroundHeight + verticalOffset), size: CGSize(width: layout.size.width, height: backgroundHeight)))
if let dismissedCurrentFooterContentNode = dismissedCurrentFooterContentNode { if let dismissedCurrentFooterContentNode = dismissedCurrentFooterContentNode {
let contentTransition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring) let contentTransition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring)

View File

@ -205,7 +205,9 @@ private final class UniversalVideoGalleryItemOverlayNode: GalleryOverlayContentN
} }
override func animateIn(previousContentNode: GalleryOverlayContentNode?, transition: ContainedViewLayoutTransition) { override func animateIn(previousContentNode: GalleryOverlayContentNode?, transition: ContainedViewLayoutTransition) {
transition.updateAlpha(node: self.wrapperNode, alpha: 1.0) if !self.visibilityAlpha.isZero {
transition.updateAlpha(node: self.wrapperNode, alpha: 1.0)
}
} }
override func animateOut(nextContentNode: GalleryOverlayContentNode?, transition: ContainedViewLayoutTransition, completion: @escaping () -> Void) { override func animateOut(nextContentNode: GalleryOverlayContentNode?, transition: ContainedViewLayoutTransition, completion: @escaping () -> Void) {
@ -271,12 +273,13 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
private let statusNode: RadialStatusNode private let statusNode: RadialStatusNode
private var statusNodeShouldBeHidden = true private var statusNodeShouldBeHidden = true
private var isCentral = false private var isCentral: Bool?
private var _isVisible: Bool? private var _isVisible: Bool?
private var initiallyActivated = false private var initiallyActivated = false
private var hideStatusNodeUntilCentrality = false private var hideStatusNodeUntilCentrality = false
private var playOnContentOwnership = false private var playOnContentOwnership = false
private var skipInitialPause = false private var skipInitialPause = false
private var ignorePauseStatus = false
private var validLayout: (ContainerViewLayout, CGFloat)? private var validLayout: (ContainerViewLayout, CGFloat)?
private var didPause = false private var didPause = false
private var isPaused = true private var isPaused = true
@ -299,6 +302,11 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
private var scrubbingFrames = false private var scrubbingFrames = false
private var scrubbingFrameDisposable: Disposable? private var scrubbingFrameDisposable: Disposable?
private let isPlayingPromise = ValuePromise<Bool>(false, ignoreRepeated: true)
private let isInteractingPromise = ValuePromise<Bool>(false, ignoreRepeated: true)
private let controlsVisiblePromise = ValuePromise<Bool>(true, ignoreRepeated: true)
private var hideControlsDisposable: Disposable?
var playbackCompleted: (() -> Void)? var playbackCompleted: (() -> Void)?
private var customUnembedWhenPortrait: ((OverlayMediaItemNode) -> Bool)? private var customUnembedWhenPortrait: ((OverlayMediaItemNode) -> Bool)?
@ -323,6 +331,10 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
super.init() super.init()
self.footerContentNode.interacting = { [weak self] value in
self?.isInteractingPromise.set(value)
}
self.overlayContentNode.action = { [weak self] toLandscape in self.overlayContentNode.action = { [weak self] toLandscape in
self?.updateControlsVisibility(!toLandscape) self?.updateControlsVisibility(!toLandscape)
context.sharedContext.applicationBindings.forceOrientation(toLandscape ? .landscapeRight : .portrait) context.sharedContext.applicationBindings.forceOrientation(toLandscape ? .landscapeRight : .portrait)
@ -436,12 +448,30 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
self.titleContentView = GalleryTitleView(frame: CGRect()) self.titleContentView = GalleryTitleView(frame: CGRect())
self._titleView.set(.single(self.titleContentView)) self._titleView.set(.single(self.titleContentView))
let shouldHideControlsSignal: Signal<Void, NoError> = combineLatest(self.isPlayingPromise.get(), self.isInteractingPromise.get(), self.controlsVisiblePromise.get())
|> mapToSignal { isPlaying, isIntracting, controlsVisible -> Signal<Void, NoError> in
if isPlaying && !isIntracting && controlsVisible {
return .single(Void())
|> delay(4.0, queue: Queue.mainQueue())
} else {
return .complete()
}
}
self.hideControlsDisposable = (shouldHideControlsSignal
|> deliverOnMainQueue).start(next: { [weak self] _ in
if let strongSelf = self {
strongSelf.updateControlsVisibility(false)
}
})
} }
deinit { deinit {
self.statusDisposable.dispose() self.statusDisposable.dispose()
self.mediaPlaybackStateDisposable.dispose() self.mediaPlaybackStateDisposable.dispose()
self.scrubbingFrameDisposable?.dispose() self.scrubbingFrameDisposable?.dispose()
self.hideControlsDisposable?.dispose()
} }
override func ready() -> Signal<Void, NoError> { override func ready() -> Signal<Void, NoError> {
@ -484,21 +514,9 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
} }
} }
private var controlsTimer: SwiftSignalKit.Timer?
private var previousPlaying: Bool?
private func setupControlsTimer() {
let timer = SwiftSignalKit.Timer(timeout: 3.0, repeat: false, completion: { [weak self] in
self?.updateControlsVisibility(false)
self?.controlsTimer = nil
}, queue: Queue.mainQueue())
timer.start()
self.controlsTimer = timer
}
func setupItem(_ item: UniversalVideoGalleryItem) { func setupItem(_ item: UniversalVideoGalleryItem) {
if self.item?.content.id != item.content.id { if self.item?.content.id != item.content.id {
self.previousPlaying = nil self.isPlayingPromise.set(false)
if item.hideControls { if item.hideControls {
self.statusButtonNode.isHidden = true self.statusButtonNode.isHidden = true
@ -665,7 +683,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|> deliverOnMainQueue).start(next: { [weak self] value, fetchStatus in |> deliverOnMainQueue).start(next: { [weak self] value, fetchStatus in
if let strongSelf = self { if let strongSelf = self {
var initialBuffering = false var initialBuffering = false
var playing = false var isPlaying = false
var isPaused = true var isPaused = true
var seekable = hintSeekable var seekable = hintSeekable
var hasStarted = false var hasStarted = false
@ -683,7 +701,8 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
switch value.status { switch value.status {
case .playing: case .playing:
isPaused = false isPaused = false
playing = true isPlaying = true
strongSelf.ignorePauseStatus = false
case let .buffering(_, whilePlaying, _, display): case let .buffering(_, whilePlaying, _, display):
displayProgress = display displayProgress = display
initialBuffering = !whilePlaying initialBuffering = !whilePlaying
@ -716,9 +735,10 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
isPaused = false isPaused = false
} }
} else if strongSelf.actionAtEnd == .stop { } else if strongSelf.actionAtEnd == .stop {
strongSelf.updateControlsVisibility(true) strongSelf.isPlayingPromise.set(false)
strongSelf.controlsTimer?.invalidate() if strongSelf.isCentral == true {
strongSelf.controlsTimer = nil strongSelf.updateControlsVisibility(true)
}
} }
} }
if !value.duration.isZero { if !value.duration.isZero {
@ -726,14 +746,11 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
} }
} }
if strongSelf.isCentral && playing && strongSelf.previousPlaying != true && !disablePlayerControls { if !disablePlayerControls && strongSelf.isCentral == true && isPlaying {
strongSelf.controlsTimer?.invalidate() strongSelf.isPlayingPromise.set(true)
strongSelf.setupControlsTimer() } else if !isPlaying {
} else if !playing { strongSelf.isPlayingPromise.set(false)
strongSelf.controlsTimer?.invalidate()
strongSelf.controlsTimer = nil
} }
strongSelf.previousPlaying = playing
var fetching = false var fetching = false
if initialBuffering { if initialBuffering {
@ -751,7 +768,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
case .Remote: case .Remote:
state = .download(.white) state = .download(.white)
case let .Fetching(_, progress): case let .Fetching(_, progress):
if !playing { if !isPlaying {
fetching = true fetching = true
isPaused = true isPaused = true
} }
@ -768,13 +785,13 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
strongSelf.fetchStatus = fetchStatus strongSelf.fetchStatus = fetchStatus
if !item.hideControls { if !item.hideControls {
strongSelf.statusNodeShouldBeHidden = (!initialBuffering && (strongSelf.didPause || !isPaused) && !fetching) strongSelf.statusNodeShouldBeHidden = strongSelf.ignorePauseStatus || (!initialBuffering && (strongSelf.didPause || !isPaused) && !fetching)
strongSelf.statusButtonNode.isHidden = strongSelf.hideStatusNodeUntilCentrality || strongSelf.statusNodeShouldBeHidden strongSelf.statusButtonNode.isHidden = strongSelf.hideStatusNodeUntilCentrality || strongSelf.statusNodeShouldBeHidden
} }
if isAnimated || disablePlayerControls { if isAnimated || disablePlayerControls {
strongSelf.footerContentNode.content = .info strongSelf.footerContentNode.content = .info
} else if isPaused { } else if isPaused && !strongSelf.ignorePauseStatus {
if hasStarted || strongSelf.didPause { if hasStarted || strongSelf.didPause {
strongSelf.footerContentNode.content = .playback(paused: true, seekable: seekable) strongSelf.footerContentNode.content = .playback(paused: true, seekable: seekable)
} else if let fetchStatus = fetchStatus, !strongSelf.requiresDownload { } else if let fetchStatus = fetchStatus, !strongSelf.requiresDownload {
@ -808,10 +825,9 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
if let strongSelf = self, !isAnimated { if let strongSelf = self, !isAnimated {
videoNode?.seek(0.0) videoNode?.seek(0.0)
if strongSelf.actionAtEnd == .stop && strongSelf.isCentral { if strongSelf.actionAtEnd == .stop && strongSelf.isCentral == true {
strongSelf.isPlayingPromise.set(false)
strongSelf.updateControlsVisibility(true) strongSelf.updateControlsVisibility(true)
strongSelf.controlsTimer?.invalidate()
strongSelf.controlsTimer = nil
} }
} }
} }
@ -834,8 +850,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
} }
override func controlsVisibilityUpdated(isVisible: Bool) { override func controlsVisibilityUpdated(isVisible: Bool) {
self.controlsTimer?.invalidate() self.controlsVisiblePromise.set(isVisible)
self.controlsTimer = nil
self.videoNode?.isUserInteractionEnabled = isVisible ? self.videoNodeUserInteractionEnabled : false self.videoNode?.isUserInteractionEnabled = isVisible ? self.videoNodeUserInteractionEnabled : false
self.videoNode?.notifyPlaybackControlsHidden(!isVisible) self.videoNode?.notifyPlaybackControlsHidden(!isVisible)
@ -915,8 +930,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
} }
} }
} else { } else {
self.controlsTimer?.invalidate() self.isPlayingPromise.set(false)
self.controlsTimer = nil
self.dismissOnOrientationChange = false self.dismissOnOrientationChange = false
if videoNode.ownsContentNode { if videoNode.ownsContentNode {
@ -941,6 +955,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
if self.skipInitialPause { if self.skipInitialPause {
self.skipInitialPause = false self.skipInitialPause = false
} else { } else {
self.ignorePauseStatus = true
videoNode.pause() videoNode.pause()
videoNode.seek(0.0) videoNode.seek(0.0)
} }
@ -973,7 +988,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
} }
override func activateAsInitial() { override func activateAsInitial() {
if let videoNode = self.videoNode, self.isCentral { if let videoNode = self.videoNode, self.isCentral == true {
self.initiallyActivated = true self.initiallyActivated = true
var isAnimated = false var isAnimated = false
@ -1614,6 +1629,8 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|> delay(0.15, queue: Queue.mainQueue()) |> delay(0.15, queue: Queue.mainQueue())
let progressDisposable = progressSignal.start() let progressDisposable = progressSignal.start()
self.isInteractingPromise.set(true)
let signal = stickerPacksAttachedToMedia(account: self.context.account, media: media) let signal = stickerPacksAttachedToMedia(account: self.context.account, media: media)
|> afterDisposed { |> afterDisposed {
Queue.mainQueue().async { Queue.mainQueue().async {
@ -1627,7 +1644,9 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
} }
let baseNavigationController = strongSelf.baseNavigationController() let baseNavigationController = strongSelf.baseNavigationController()
baseNavigationController?.view.endEditing(true) baseNavigationController?.view.endEditing(true)
let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packs[0], stickerPacks: packs, sendSticker: nil) let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packs[0], stickerPacks: packs, sendSticker: nil, dismissed: { [weak self] in
self?.isInteractingPromise.set(false)
})
(baseNavigationController?.topViewController as? ViewController)?.present(controller, in: .window(.root), with: nil) (baseNavigationController?.topViewController as? ViewController)?.present(controller, in: .window(.root), with: nil)
}) })
} }

View File

@ -575,6 +575,13 @@ public final class ListMessageFileItemNode: ListMessageNode {
if statusUpdated { if statusUpdated {
updatedStatusSignal = messageFileMediaResourceStatus(context: item.context, file: selectedMedia, message: message, isRecentActions: false, isSharedMedia: true, isGlobalSearch: item.isGlobalSearchResult) updatedStatusSignal = messageFileMediaResourceStatus(context: item.context, file: selectedMedia, message: message, isRecentActions: false, isSharedMedia: true, isGlobalSearch: item.isGlobalSearchResult)
|> mapToSignal { value -> Signal<FileMediaResourceStatus, NoError> in
if case .Fetching = value.fetchStatus {
return .single(value) |> delay(0.25, queue: Queue.concurrentDefaultQueue())
} else {
return .single(value)
}
}
if isAudio || isInstantVideo { if isAudio || isInstantVideo {
if let currentUpdatedStatusSignal = updatedStatusSignal { if let currentUpdatedStatusSignal = updatedStatusSignal {

View File

@ -231,6 +231,9 @@ public final class SearchDisplayController {
self.searchBar.activate() self.searchBar.activate()
if let placeholder = placeholder { if let placeholder = placeholder {
self.searchBar.animateIn(from: placeholder, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring) self.searchBar.animateIn(from: placeholder, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring)
if self.contentNode.hasDim {
self.contentNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
}
} else { } else {
self.searchBar.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue) self.searchBar.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
self.contentNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue) self.contentNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
@ -255,17 +258,6 @@ public final class SearchDisplayController {
let backgroundNode = self.backgroundNode let backgroundNode = self.backgroundNode
let contentNode = self.contentNode let contentNode = self.contentNode
if animated { if animated {
if let placeholder = placeholder, let (layout, navigationBarHeight) = self.containerLayout {
let contentNodePosition = self.backgroundNode.layer.position
let targetTextBackgroundFrame = placeholder.convert(placeholder.backgroundNode.frame, to: nil)
var contentNavigationBarHeight = navigationBarHeight
if layout.statusBarHeight == nil {
contentNavigationBarHeight += 28.0
}
self.backgroundNode.layer.animatePosition(from: contentNodePosition, to: CGPoint(x: contentNodePosition.x, y: contentNodePosition.y + (targetTextBackgroundFrame.maxY + 8.0 - contentNavigationBarHeight)), duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
}
backgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak backgroundNode] _ in backgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak backgroundNode] _ in
backgroundNode?.removeFromSupernode() backgroundNode?.removeFromSupernode()
}) })

View File

@ -93,7 +93,11 @@ final class ThemeGridSearchColorsNode: ASDisplayNode {
return CGSize(width: constrainedSize.width, height: 100.0) return CGSize(width: constrainedSize.width, height: 100.0)
} }
private var validLayout: (CGSize, CGFloat, CGFloat)?
func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat) { func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat) {
let hadLayout = self.validLayout != nil
self.validLayout = (size, leftInset, rightInset)
self.sectionHeaderNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: 29.0)) self.sectionHeaderNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: 29.0))
self.sectionHeaderNode.updateLayout(size: CGSize(width: size.width, height: 29.0), leftInset: leftInset, rightInset: rightInset) self.sectionHeaderNode.updateLayout(size: CGSize(width: size.width, height: 29.0), leftInset: leftInset, rightInset: rightInset)
@ -103,6 +107,9 @@ final class ThemeGridSearchColorsNode: ASDisplayNode {
self.scrollNode.frame = CGRect(x: 0.0, y: 29.0, width: size.width, height: size.height - 29.0) self.scrollNode.frame = CGRect(x: 0.0, y: 29.0, width: size.width, height: size.height - 29.0)
self.scrollNode.view.contentInset = insets self.scrollNode.view.contentInset = insets
if !hadLayout {
self.scrollNode.view.contentOffset = CGPoint(x: -leftInset, y: 0.0)
}
var offset: CGFloat = inset var offset: CGFloat = inset
if let subnodes = self.scrollNode.subnodes { if let subnodes = self.scrollNode.subnodes {

View File

@ -299,7 +299,7 @@ public final class ShareController: ViewController {
private var currentAccount: Account private var currentAccount: Account
private var presentationData: PresentationData private var presentationData: PresentationData
private var presentationDataDisposable: Disposable? private var presentationDataDisposable: Disposable?
private let forcedTheme: PresentationTheme? private let forceTheme: PresentationTheme?
private let externalShare: Bool private let externalShare: Bool
private let immediateExternalShare: Bool private let immediateExternalShare: Bool
@ -327,11 +327,11 @@ public final class ShareController: ViewController {
} }
} }
public convenience init(context: AccountContext, subject: ShareControllerSubject, presetText: String? = nil, preferredAction: ShareControllerPreferredAction = .default, showInChat: ((Message) -> Void)? = nil, fromForeignApp: Bool = false, segmentedValues: [ShareControllerSegmentedValue]? = nil, externalShare: Bool = true, immediateExternalShare: Bool = false, switchableAccounts: [AccountWithInfo] = [], immediatePeerId: PeerId? = nil, forcedTheme: PresentationTheme? = nil, forcedActionTitle: String? = nil) { public convenience init(context: AccountContext, subject: ShareControllerSubject, presetText: String? = nil, preferredAction: ShareControllerPreferredAction = .default, showInChat: ((Message) -> Void)? = nil, fromForeignApp: Bool = false, segmentedValues: [ShareControllerSegmentedValue]? = nil, externalShare: Bool = true, immediateExternalShare: Bool = false, switchableAccounts: [AccountWithInfo] = [], immediatePeerId: PeerId? = nil, forceTheme: PresentationTheme? = nil, forcedActionTitle: String? = nil) {
self.init(sharedContext: context.sharedContext, currentContext: context, subject: subject, presetText: presetText, preferredAction: preferredAction, showInChat: showInChat, fromForeignApp: fromForeignApp, segmentedValues: segmentedValues, externalShare: externalShare, immediateExternalShare: immediateExternalShare, switchableAccounts: switchableAccounts, immediatePeerId: immediatePeerId, forcedTheme: forcedTheme, forcedActionTitle: forcedActionTitle) self.init(sharedContext: context.sharedContext, currentContext: context, subject: subject, presetText: presetText, preferredAction: preferredAction, showInChat: showInChat, fromForeignApp: fromForeignApp, segmentedValues: segmentedValues, externalShare: externalShare, immediateExternalShare: immediateExternalShare, switchableAccounts: switchableAccounts, immediatePeerId: immediatePeerId, forceTheme: forceTheme, forcedActionTitle: forcedActionTitle)
} }
public init(sharedContext: SharedAccountContext, currentContext: AccountContext, subject: ShareControllerSubject, presetText: String? = nil, preferredAction: ShareControllerPreferredAction = .default, showInChat: ((Message) -> Void)? = nil, fromForeignApp: Bool = false, segmentedValues: [ShareControllerSegmentedValue]? = nil, externalShare: Bool = true, immediateExternalShare: Bool = false, switchableAccounts: [AccountWithInfo] = [], immediatePeerId: PeerId? = nil, forcedTheme: PresentationTheme? = nil, forcedActionTitle: String? = nil) { public init(sharedContext: SharedAccountContext, currentContext: AccountContext, subject: ShareControllerSubject, presetText: String? = nil, preferredAction: ShareControllerPreferredAction = .default, showInChat: ((Message) -> Void)? = nil, fromForeignApp: Bool = false, segmentedValues: [ShareControllerSegmentedValue]? = nil, externalShare: Bool = true, immediateExternalShare: Bool = false, switchableAccounts: [AccountWithInfo] = [], immediatePeerId: PeerId? = nil, forceTheme: PresentationTheme? = nil, forcedActionTitle: String? = nil) {
self.sharedContext = sharedContext self.sharedContext = sharedContext
self.currentContext = currentContext self.currentContext = currentContext
self.currentAccount = currentContext.account self.currentAccount = currentContext.account
@ -343,11 +343,11 @@ public final class ShareController: ViewController {
self.immediatePeerId = immediatePeerId self.immediatePeerId = immediatePeerId
self.fromForeignApp = fromForeignApp self.fromForeignApp = fromForeignApp
self.segmentedValues = segmentedValues self.segmentedValues = segmentedValues
self.forcedTheme = forcedTheme self.forceTheme = forceTheme
self.presentationData = self.sharedContext.currentPresentationData.with { $0 } self.presentationData = self.sharedContext.currentPresentationData.with { $0 }
if let forcedTheme = self.forcedTheme { if let forceTheme = self.forceTheme {
self.presentationData = self.presentationData.withUpdated(theme: forcedTheme) self.presentationData = self.presentationData.withUpdated(theme: forceTheme)
} }
super.init(navigationBarPresentationData: nil) super.init(navigationBarPresentationData: nil)
@ -487,17 +487,17 @@ public final class ShareController: ViewController {
return return
} }
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: title, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: title, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}, externalShare: self.externalShare, immediateExternalShare: self.immediateExternalShare, immediatePeerId: self.immediatePeerId, fromForeignApp: self.fromForeignApp, forcedTheme: self.forcedTheme, segmentedValues: self.segmentedValues) }, externalShare: self.externalShare, immediateExternalShare: self.immediateExternalShare, immediatePeerId: self.immediatePeerId, fromForeignApp: self.fromForeignApp, forceTheme: self.forceTheme, segmentedValues: self.segmentedValues)
self.controllerNode.completed = self.completed self.controllerNode.completed = self.completed
self.controllerNode.dismiss = { [weak self] shared in self.controllerNode.dismiss = { [weak self] shared in
self?.presentingViewController?.dismiss(animated: false, completion: nil)
self?.dismissed?(shared) self?.dismissed?(shared)
self?.presentingViewController?.dismiss(animated: false, completion: nil)
} }
self.controllerNode.cancel = { [weak self] in self.controllerNode.cancel = { [weak self] in
self?.controllerNode.view.endEditing(true) self?.controllerNode.view.endEditing(true)
self?.controllerNode.animateOut(shared: false, completion: { self?.controllerNode.animateOut(shared: false, completion: {
self?.presentingViewController?.dismiss(animated: false, completion: nil)
self?.dismissed?(false) self?.dismissed?(false)
self?.presentingViewController?.dismiss(animated: false, completion: nil)
}) })
} }
self.controllerNode.share = { [weak self] text, peerIds in self.controllerNode.share = { [weak self] text, peerIds in

View File

@ -25,7 +25,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
private let sharedContext: SharedAccountContext private let sharedContext: SharedAccountContext
private var context: AccountContext? private var context: AccountContext?
private var presentationData: PresentationData private var presentationData: PresentationData
private let forcedTheme: PresentationTheme? private let forceTheme: PresentationTheme?
private let externalShare: Bool private let externalShare: Bool
private let immediateExternalShare: Bool private let immediateExternalShare: Bool
private var immediatePeerId: PeerId? private var immediatePeerId: PeerId?
@ -80,10 +80,10 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
private let presetText: String? private let presetText: String?
init(sharedContext: SharedAccountContext, presetText: String?, defaultAction: ShareControllerAction?, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, presentError: @escaping (String?, String) -> Void, externalShare: Bool, immediateExternalShare: Bool, immediatePeerId: PeerId?, fromForeignApp: Bool, forcedTheme: PresentationTheme?, segmentedValues: [ShareControllerSegmentedValue]?) { init(sharedContext: SharedAccountContext, presetText: String?, defaultAction: ShareControllerAction?, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, presentError: @escaping (String?, String) -> Void, externalShare: Bool, immediateExternalShare: Bool, immediatePeerId: PeerId?, fromForeignApp: Bool, forceTheme: PresentationTheme?, segmentedValues: [ShareControllerSegmentedValue]?) {
self.sharedContext = sharedContext self.sharedContext = sharedContext
self.presentationData = sharedContext.currentPresentationData.with { $0 } self.presentationData = sharedContext.currentPresentationData.with { $0 }
self.forcedTheme = forcedTheme self.forceTheme = forceTheme
self.externalShare = externalShare self.externalShare = externalShare
self.immediateExternalShare = immediateExternalShare self.immediateExternalShare = immediateExternalShare
self.immediatePeerId = immediatePeerId self.immediatePeerId = immediatePeerId
@ -96,8 +96,8 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
self.defaultAction = defaultAction self.defaultAction = defaultAction
self.requestLayout = requestLayout self.requestLayout = requestLayout
if let forcedTheme = self.forcedTheme { if let forceTheme = self.forceTheme {
self.presentationData = self.presentationData.withUpdated(theme: forcedTheme) self.presentationData = self.presentationData.withUpdated(theme: forceTheme)
} }
let roundedBackground = generateStretchableFilledCircleImage(radius: 16.0, color: self.presentationData.theme.actionSheet.opaqueItemBackgroundColor) let roundedBackground = generateStretchableFilledCircleImage(radius: 16.0, color: self.presentationData.theme.actionSheet.opaqueItemBackgroundColor)
@ -272,8 +272,8 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
return return
} }
self.presentationData = presentationData self.presentationData = presentationData
if let forcedTheme = self.forcedTheme { if let forceTheme = self.forceTheme {
self.presentationData = self.presentationData.withUpdated(theme: forcedTheme) self.presentationData = self.presentationData.withUpdated(theme: forceTheme)
} }
let roundedBackground = generateStretchableFilledCircleImage(radius: 16.0, color: self.presentationData.theme.actionSheet.opaqueItemBackgroundColor) let roundedBackground = generateStretchableFilledCircleImage(radius: 16.0, color: self.presentationData.theme.actionSheet.opaqueItemBackgroundColor)

View File

@ -25,7 +25,9 @@ public final class StickerPackPreviewController: ViewController, StandalonePrese
} }
private var animatedIn = false private var animatedIn = false
private var dismissed = false private var isDismissed = false
public var dismissed: (() -> Void)?
private let context: AccountContext private let context: AccountContext
private let mode: StickerPackPreviewControllerMode private let mode: StickerPackPreviewControllerMode
@ -150,6 +152,7 @@ public final class StickerPackPreviewController: ViewController, StandalonePrese
})) }))
}, actionPerformed: self.actionPerformed) }, actionPerformed: self.actionPerformed)
self.controllerNode.dismiss = { [weak self] in self.controllerNode.dismiss = { [weak self] in
self?.dismissed?()
self?.presentingViewController?.dismiss(animated: false, completion: nil) self?.presentingViewController?.dismiss(animated: false, completion: nil)
} }
self.controllerNode.cancel = { [weak self] in self.controllerNode.cancel = { [weak self] in
@ -264,8 +267,8 @@ public final class StickerPackPreviewController: ViewController, StandalonePrese
} }
override public func dismiss(completion: (() -> Void)? = nil) { override public func dismiss(completion: (() -> Void)? = nil) {
if !self.dismissed { if !self.isDismissed {
self.dismissed = true self.isDismissed = true
} else { } else {
return return
} }

View File

@ -988,6 +988,8 @@ public final class StickerPackScreenImpl: ViewController {
return self.displayNode as! StickerPackScreenNode return self.displayNode as! StickerPackScreenNode
} }
public var dismissed: (() -> Void)?
private let _ready = Promise<Bool>() private let _ready = Promise<Bool>()
override public var ready: Promise<Bool> { override public var ready: Promise<Bool> {
return self._ready return self._ready
@ -1020,6 +1022,7 @@ public final class StickerPackScreenImpl: ViewController {
strongSelf.updateModalStyleOverlayTransitionFactor(value, transition: transition) strongSelf.updateModalStyleOverlayTransitionFactor(value, transition: transition)
} }
}, dismissed: { [weak self] in }, dismissed: { [weak self] in
self?.dismissed?()
self?.dismiss() self?.dismiss()
}, presentInGlobalOverlay: { [weak self] c, a in }, presentInGlobalOverlay: { [weak self] c, a in
self?.presentInGlobalOverlay(c, with: a) self?.presentInGlobalOverlay(c, with: a)
@ -1060,10 +1063,11 @@ public enum StickerPackScreenPerformedAction {
case remove(positionInList: Int) case remove(positionInList: Int)
} }
public func StickerPackScreen(context: AccountContext, mode: StickerPackPreviewControllerMode = .default, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? = nil, actionPerformed: ((StickerPackCollectionInfo, [ItemCollectionItem], StickerPackScreenPerformedAction) -> Void)? = nil) -> ViewController { public func StickerPackScreen(context: AccountContext, mode: StickerPackPreviewControllerMode = .default, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? = nil, actionPerformed: ((StickerPackCollectionInfo, [ItemCollectionItem], StickerPackScreenPerformedAction) -> Void)? = nil, dismissed: (() -> Void)? = nil) -> ViewController {
//return StickerPackScreenImpl(context: context, stickerPacks: stickerPacks, selectedStickerPackIndex: stickerPacks.firstIndex(of: mainStickerPack) ?? 0, parentNavigationController: parentNavigationController, sendSticker: sendSticker) //return StickerPackScreenImpl(context: context, stickerPacks: stickerPacks, selectedStickerPackIndex: stickerPacks.firstIndex(of: mainStickerPack) ?? 0, parentNavigationController: parentNavigationController, sendSticker: sendSticker)
let controller = StickerPackPreviewController(context: context, stickerPack: mainStickerPack, mode: mode, parentNavigationController: parentNavigationController, actionPerformed: actionPerformed) let controller = StickerPackPreviewController(context: context, stickerPack: mainStickerPack, mode: mode, parentNavigationController: parentNavigationController, actionPerformed: actionPerformed)
controller.dismissed = dismissed
controller.sendSticker = sendSticker controller.sendSticker = sendSticker
return controller return controller
} }

View File

@ -563,7 +563,12 @@ public final class VoiceChatController: ViewController {
var text: VoiceChatParticipantItem.ParticipantText var text: VoiceChatParticipantItem.ParticipantText
var expandedText: VoiceChatParticipantItem.ParticipantText? var expandedText: VoiceChatParticipantItem.ParticipantText?
let icon: VoiceChatParticipantItem.Icon let icon: VoiceChatParticipantItem.Icon
switch peerEntry.state {
var state = peerEntry.state
if let muteState = peerEntry.muteState, case .speaking = state, muteState.mutedByYou || !muteState.canUnmute {
state = .listening
}
switch state {
case .listening: case .listening:
if let muteState = peerEntry.muteState, muteState.mutedByYou { if let muteState = peerEntry.muteState, muteState.mutedByYou {
text = .text(presentationData.strings.VoiceChat_StatusMutedForYou, .destructive) text = .text(presentationData.strings.VoiceChat_StatusMutedForYou, .destructive)
@ -1268,7 +1273,7 @@ public final class VoiceChatController: ViewController {
openIcon = UIImage(bundleImageName: "Chat/Context Menu/Channels") openIcon = UIImage(bundleImageName: "Chat/Context Menu/Channels")
} else { } else {
openTitle = strongSelf.presentationData.strings.Conversation_ContextMenuOpenProfile openTitle = strongSelf.presentationData.strings.Conversation_ContextMenuOpenProfile
openIcon = UIImage(bundleImageName: "Chat/Context Menu/Info") openIcon = UIImage(bundleImageName: "Chat/Context Menu/User")
} }
items.append(.action(ContextMenuActionItem(text: openTitle, icon: { theme in items.append(.action(ContextMenuActionItem(text: openTitle, icon: { theme in
return generateTintedImage(image: openIcon, color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: openIcon, color: theme.actionSheet.primaryTextColor)
@ -2236,7 +2241,7 @@ public final class VoiceChatController: ViewController {
return formatSendTitle(presentationData.strings.VoiceChat_InviteLink_InviteListeners(Int32(count))) return formatSendTitle(presentationData.strings.VoiceChat_InviteLink_InviteListeners(Int32(count)))
})] })]
} }
let shareController = ShareController(context: strongSelf.context, subject: .url(inviteLinks.listenerLink), segmentedValues: segmentedValues, forcedTheme: strongSelf.darkTheme, forcedActionTitle: presentationData.strings.VoiceChat_CopyInviteLink) let shareController = ShareController(context: strongSelf.context, subject: .url(inviteLinks.listenerLink), segmentedValues: segmentedValues, forceTheme: strongSelf.darkTheme, forcedActionTitle: presentationData.strings.VoiceChat_CopyInviteLink)
shareController.completed = { [weak self] peerIds in shareController.completed = { [weak self] peerIds in
if let strongSelf = self { if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in

View File

@ -179,6 +179,7 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
private var peerPresenceManager: PeerPresenceStatusManager? private var peerPresenceManager: PeerPresenceStatusManager?
private var layoutParams: (VoiceChatParticipantItem, ListViewItemLayoutParams, Bool, Bool)? private var layoutParams: (VoiceChatParticipantItem, ListViewItemLayoutParams, Bool, Bool)?
private var isExtracted = false
private var wavesColor: UIColor? private var wavesColor: UIColor?
private var videoNode: GroupVideoNode? private var videoNode: GroupVideoNode?
@ -279,6 +280,8 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
return return
} }
strongSelf.isExtracted = isExtracted
if isExtracted { if isExtracted {
strongSelf.extractedBackgroundImageNode.image = generateStretchableFilledCircleImage(diameter: 28.0, color: item.presentationData.theme.list.itemBlocksBackgroundColor) strongSelf.extractedBackgroundImageNode.image = generateStretchableFilledCircleImage(diameter: 28.0, color: item.presentationData.theme.list.itemBlocksBackgroundColor)
} }
@ -521,7 +524,7 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
strongSelf.extractedRect = extractedRect strongSelf.extractedRect = extractedRect
strongSelf.nonExtractedRect = nonExtractedRect strongSelf.nonExtractedRect = nonExtractedRect
if strongSelf.contextSourceNode.isExtractedToContextPreview { if strongSelf.isExtracted {
strongSelf.extractedBackgroundImageNode.frame = extractedRect strongSelf.extractedBackgroundImageNode.frame = extractedRect
} else { } else {
strongSelf.extractedBackgroundImageNode.frame = nonExtractedRect strongSelf.extractedBackgroundImageNode.frame = nonExtractedRect

View File

@ -30,7 +30,9 @@ func updateAppConfigurationOnce(postbox: Postbox, network: Network) -> Signal<Vo
func managedAppConfigurationUpdates(postbox: Postbox, network: Network) -> Signal<Void, NoError> { func managedAppConfigurationUpdates(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
let poll = Signal<Void, NoError> { subscriber in let poll = Signal<Void, NoError> { subscriber in
return updateAppConfigurationOnce(postbox: postbox, network: network).start() return updateAppConfigurationOnce(postbox: postbox, network: network).start(completed: {
subscriber.putCompletion()
})
} }
return (poll |> then(.complete() |> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart return (poll |> then(.complete() |> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
} }

View File

@ -14,7 +14,9 @@ func managedAutodownloadSettingsUpdates(accountManager: AccountManager, network:
return updateAutodownloadSettingsInteractively(accountManager: accountManager, { _ -> AutodownloadSettings in return updateAutodownloadSettingsInteractively(accountManager: accountManager, { _ -> AutodownloadSettings in
return AutodownloadSettings(apiAutodownloadSettings: result) return AutodownloadSettings(apiAutodownloadSettings: result)
}) })
}).start() }).start(completed: {
subscriber.putCompletion()
})
} }
return (poll |> then(.complete() |> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart return (poll |> then(.complete() |> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
} }

View File

@ -90,7 +90,9 @@ func managedConfigurationUpdates(accountManager: AccountManager, postbox: Postbo
} }
} }
|> switchToLatest |> switchToLatest
}).start() }).start(completed: {
subscriber.putCompletion()
})
} }
return (poll |> then(.complete() |> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart return (poll |> then(.complete() |> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart

View File

@ -19,7 +19,9 @@ func managedVoipConfigurationUpdates(postbox: Postbox, network: Network) -> Sign
}) })
} }
} }
}).start() }).start(completed: {
subscriber.putCompletion()
})
} }
return (poll |> then(.complete() |> suspendAwareDelay(12.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart return (poll |> then(.complete() |> suspendAwareDelay(12.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
} }

View File

@ -763,6 +763,7 @@ final class AuthorizedApplicationContext {
self.rootController.setForceInCallStatusBar((self.context.sharedContext as! SharedAccountContextImpl).currentCallStatusBarNode) self.rootController.setForceInCallStatusBar((self.context.sharedContext as! SharedAccountContextImpl).currentCallStatusBarNode)
if let groupCallController = self.context.sharedContext.currentGroupCallController as? VoiceChatController { if let groupCallController = self.context.sharedContext.currentGroupCallController as? VoiceChatController {
if let overlayController = groupCallController.currentOverlayController { if let overlayController = groupCallController.currentOverlayController {
groupCallController.parentNavigationController = self.rootController
self.rootController.presentOverlay(controller: overlayController, inGlobal: true, blockInteraction: false) self.rootController.presentOverlay(controller: overlayController, inGlobal: true, blockInteraction: false)
} }
} }

View File

@ -1364,6 +1364,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
case .replyThread: case .replyThread:
postAsReply = true postAsReply = true
} }
if let messageId = messageId, let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(messageId) {
if let author = message.author as? TelegramUser, author.botInfo != nil {
} else {
postAsReply = false
}
}
} }
strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({
@ -2423,7 +2430,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
var items: [ContextMenuItem] = [ var items: [ContextMenuItem] = [
.action(ContextMenuActionItem(text: isChannel ? strongSelf.presentationData.strings.Conversation_ContextMenuOpenChannelProfile : strongSelf.presentationData.strings.Conversation_ContextMenuOpenProfile, icon: { theme in .action(ContextMenuActionItem(text: isChannel ? strongSelf.presentationData.strings.Conversation_ContextMenuOpenChannelProfile : strongSelf.presentationData.strings.Conversation_ContextMenuOpenProfile, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/User"), color: theme.actionSheet.primaryTextColor)
}, action: { _, f in }, action: { _, f in
f(.dismissWithoutContent) f(.dismissWithoutContent)
self?.openPeer(peerId: peer.id, navigation: .info, fromMessage: nil) self?.openPeer(peerId: peer.id, navigation: .info, fromMessage: nil)
@ -7266,19 +7273,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.chatDisplayNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationHeight, transition: transition, listViewTransaction: { updateSizeAndInsets, additionalScrollDistance, scrollToTop, completion in self.chatDisplayNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationHeight, transition: transition, listViewTransaction: { updateSizeAndInsets, additionalScrollDistance, scrollToTop, completion in
self.chatDisplayNode.historyNode.updateLayout(transition: transition, updateSizeAndInsets: updateSizeAndInsets, additionalScrollDistance: additionalScrollDistance, scrollToTop: scrollToTop, completion: completion) self.chatDisplayNode.historyNode.updateLayout(transition: transition, updateSizeAndInsets: updateSizeAndInsets, additionalScrollDistance: additionalScrollDistance, scrollToTop: scrollToTop, completion: completion)
}) })
}
if case .compact = layout.metrics.widthClass {
override public func updateToInterfaceOrientation(_ orientation: UIInterfaceOrientation) { let hasOverlayNodes = self.context.sharedContext.mediaManager.overlayMediaManager.controller?.hasNodes ?? false
guard let layout = self.validLayout, case .compact = layout.metrics.widthClass else { if self.validLayout != nil && layout.size.width > layout.size.height && !hasOverlayNodes && self.traceVisibility() && isTopmostChatController(self) {
return var completed = false
} self.chatDisplayNode.historyNode.forEachVisibleItemNode { itemNode in
let hasOverlayNodes = self.context.sharedContext.mediaManager.overlayMediaManager.controller?.hasNodes ?? false if !completed, let itemNode = itemNode as? ChatMessageItemView, let message = itemNode.item?.message, let (_, soundEnabled, _, _, _) = itemNode.playMediaWithSound(), soundEnabled {
if self.validLayout != nil && orientation.isLandscape && !hasOverlayNodes && self.traceVisibility() && isTopmostChatController(self) { let _ = self.controllerInteraction?.openMessage(message, .landscape)
var completed = false completed = true
self.chatDisplayNode.historyNode.forEachVisibleItemNode { itemNode in }
if !completed, let itemNode = itemNode as? ChatMessageItemView, let message = itemNode.item?.message, let (_, soundEnabled, _, _, _) = itemNode.playMediaWithSound(), soundEnabled {
let _ = self.controllerInteraction?.openMessage(message, .landscape)
completed = true
} }
} }
} }