Various fixes

This commit is contained in:
Ilya Laktyushin 2023-02-20 04:30:51 +04:00
parent b529625219
commit 980a2c47bc
25 changed files with 262 additions and 113 deletions

View File

@ -246,7 +246,7 @@ public final class AuthorizationSequencePhoneEntryController: ViewController, MF
} }
} }
func dismissConfirmation() { public func dismissConfirmation() {
self.confirmationController?.dismissAnimated() self.confirmationController?.dismissAnimated()
self.confirmationController = nil self.confirmationController = nil
} }

View File

@ -1354,11 +1354,25 @@ open class NavigationController: UINavigationController, ContainableController,
public func replaceControllersAndPush(controllers: [UIViewController], controller: ViewController, animated: Bool, options: NavigationAnimationOptions = [], ready: ValuePromise<Bool>? = nil, completion: @escaping () -> Void = {}) { public func replaceControllersAndPush(controllers: [UIViewController], controller: ViewController, animated: Bool, options: NavigationAnimationOptions = [], ready: ValuePromise<Bool>? = nil, completion: @escaping () -> Void = {}) {
ready?.set(true) ready?.set(true)
let action = { [weak self] in
guard let self else {
return
}
var controllers = controllers var controllers = controllers
controllers.append(controller) controllers.append(controller)
self.setViewControllers(controllers, animated: animated) self.setViewControllers(controllers, animated: animated)
completion() completion()
} }
if let rootContainer = self.rootContainer, case let .split(container) = rootContainer, let topController = container.detailControllers.last {
if topController.attemptNavigation({
action()
}) {
action()
}
} else {
action()
}
}
public func replaceControllers(controllers: [UIViewController], animated: Bool, options: NavigationAnimationOptions = [], ready: ValuePromise<Bool>? = nil, completion: @escaping () -> Void = {}) { public func replaceControllers(controllers: [UIViewController], animated: Bool, options: NavigationAnimationOptions = [], ready: ValuePromise<Bool>? = nil, completion: @escaping () -> Void = {}) {
ready?.set(true) ready?.set(true)

View File

@ -1654,7 +1654,7 @@ open class TextNode: ASDisplayNode {
return (layout, { return (layout, {
node.cachedLayout = layout node.cachedLayout = layout
if updated { if updated {
if layout.size.width.isZero && layout.size.height.isZero { if layout.size.width.isZero || layout.size.height.isZero {
node.contents = nil node.contents = nil
} }
node.setNeedsDisplay() node.setNeedsDisplay()

View File

@ -183,6 +183,10 @@ final class JoinLinkPreviewPeerContentNode: ASDisplayNode, ShareContentContainer
self.contentOffsetUpdated = f self.contentOffsetUpdated = f
} }
func updateTheme(_ theme: PresentationTheme) {
}
func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) { func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
let showPeers = !self.peerNodes.isEmpty && !isLandscape let showPeers = !self.peerNodes.isEmpty && !isLandscape
var nodeHeight: CGFloat = (!showPeers ? 236.0 : 320.0) var nodeHeight: CGFloat = (!showPeers ? 236.0 : 320.0)
@ -283,7 +287,7 @@ public enum ShareLoadingState {
public final class JoinLinkPreviewLoadingContainerNode: ASDisplayNode, ShareContentContainerNode { public final class JoinLinkPreviewLoadingContainerNode: ASDisplayNode, ShareContentContainerNode {
private var contentOffsetUpdated: ((CGFloat, ContainedViewLayoutTransition) -> Void)? private var contentOffsetUpdated: ((CGFloat, ContainedViewLayoutTransition) -> Void)?
private let theme: PresentationTheme private var theme: PresentationTheme
private let activityIndicator: ActivityIndicator private let activityIndicator: ActivityIndicator
public init(theme: PresentationTheme) { public init(theme: PresentationTheme) {
@ -308,6 +312,11 @@ public final class JoinLinkPreviewLoadingContainerNode: ASDisplayNode, ShareCont
self.contentOffsetUpdated = f self.contentOffsetUpdated = f
} }
public func updateTheme(_ theme: PresentationTheme) {
self.theme = theme
self.activityIndicator.type = .custom(theme.actionSheet.controlAccentColor, 22.0, 2.0, false)
}
public func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) { public func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
let nodeHeight: CGFloat = 125.0 let nodeHeight: CGFloat = 125.0

View File

@ -82,6 +82,10 @@ final class LanguageLinkPreviewContentNode: ASDisplayNode, ShareContentContainer
self.contentOffsetUpdated = f self.contentOffsetUpdated = f
} }
func updateTheme(_ theme: PresentationTheme) {
}
func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) { func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
let insets = UIEdgeInsets(top: 12.0, left: 10.0, bottom: 12.0 + bottomInset, right: 10.0) let insets = UIEdgeInsets(top: 12.0, left: 10.0, bottom: 12.0 + bottomInset, right: 10.0)
let titleSpacing: CGFloat = 12.0 let titleSpacing: CGFloat = 12.0

View File

@ -110,7 +110,9 @@ class EmojiHeaderComponent: Component {
} }
self.statusView.isHidden = false self.statusView.isHidden = false
if containerView.subviews.count > 1 && containerView.subviews[1].subviews.count > 1 {
containerView = containerView.subviews[1].subviews[1] containerView = containerView.subviews[1].subviews[1]
}
let initialPosition = self.statusView.center let initialPosition = self.statusView.center
let targetPosition = self.statusView.superview!.convert(self.statusView.center, to: containerView) let targetPosition = self.statusView.superview!.convert(self.statusView.center, to: containerView)

View File

@ -166,7 +166,7 @@ final class ReactionContextBackgroundNode: ASDisplayNode {
backgroundMaskNodeFrame = backgroundMaskNodeFrame.offsetBy(dx: 0.0, dy: (updatedHeight - backgroundMaskNodeFrame.height) * 0.5) backgroundMaskNodeFrame = backgroundMaskNodeFrame.offsetBy(dx: 0.0, dy: (updatedHeight - backgroundMaskNodeFrame.height) * 0.5)
} }
transition.updateCornerRadius(layer: self.backgroundClippingLayer, cornerRadius: 46.0 / 2.0) transition.updateCornerRadius(layer: self.backgroundClippingLayer, cornerRadius: min(46.0 / 2.0, backgroundFrame.height / 2.0))
let largeCircleFrame: CGRect let largeCircleFrame: CGRect
let smallCircleFrame: CGRect let smallCircleFrame: CGRect

View File

@ -2276,6 +2276,9 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
} }
} }
if let closestItem = closestItem, let closestItemNode = self.visibleItemNodes[closestItem.index] as? ReactionNode { if let closestItem = closestItem, let closestItemNode = self.visibleItemNodes[closestItem.index] as? ReactionNode {
if let expandItemView = self.expandItemView, expandItemView.frame.insetBy(dx: -20.0, dy: -20.0).contains(scrollPoint) {
return nil
}
return closestItemNode.item return closestItemNode.item
} }
return nil return nil

View File

@ -137,6 +137,7 @@ public func ChangePhoneNumberController(context: AccountContext) -> ViewControll
actions.append(TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})) actions.append(TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {}))
} }
controller?.dismissConfirmation()
controller?.present(textAlertController(context: context, title: nil, text: text, actions: actions), in: .window(.root)) controller?.present(textAlertController(context: context, title: nil, text: text, actions: actions), in: .window(.root))
})) }))
} }

View File

@ -3,6 +3,7 @@ import UIKit
import Display import Display
import Postbox import Postbox
import TelegramCore import TelegramCore
import TelegramPresentationData
public protocol ShareContentContainerNode: AnyObject { public protocol ShareContentContainerNode: AnyObject {
func activate() func activate()
@ -10,5 +11,6 @@ public protocol ShareContentContainerNode: AnyObject {
func setEnsurePeerVisibleOnLayout(_ peerId: EnginePeer.Id?) func setEnsurePeerVisibleOnLayout(_ peerId: EnginePeer.Id?)
func setContentOffsetUpdated(_ f: ((CGFloat, ContainedViewLayoutTransition) -> Void)?) func setContentOffsetUpdated(_ f: ((CGFloat, ContainedViewLayoutTransition) -> Void)?)
func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition)
func updateTheme(_ theme: PresentationTheme)
func updateSelectedPeers(animated: Bool) func updateSelectedPeers(animated: Bool)
} }

View File

@ -524,6 +524,8 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
self.actionButtonNode.badgeBackgroundColor = presentationData.theme.actionSheet.controlAccentColor self.actionButtonNode.badgeBackgroundColor = presentationData.theme.actionSheet.controlAccentColor
self.actionButtonNode.badgeTextColor = presentationData.theme.actionSheet.opaqueItemBackgroundColor self.actionButtonNode.badgeTextColor = presentationData.theme.actionSheet.opaqueItemBackgroundColor
self.contentNode?.updateTheme(presentationData.theme)
} }
func setActionNodesHidden(_ hidden: Bool, inputField: Bool = false, actions: Bool = false, animated: Bool = true) { func setActionNodesHidden(_ hidden: Bool, inputField: Bool = false, actions: Bool = false, animated: Bool = true) {

View File

@ -45,7 +45,7 @@ final class ShareControllerGridSection: GridSection {
func isEqual(to: GridSection) -> Bool { func isEqual(to: GridSection) -> Bool {
if let to = to as? ShareControllerGridSection { if let to = to as? ShareControllerGridSection {
return self.title == to.title return self.title == to.title && self.theme === to.theme
} else { } else {
return false return false
} }
@ -185,7 +185,7 @@ final class ShareControllerPeerGridItemNode: GridItemNode {
} }
func setup(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, peer: EngineRenderedPeer?, presence: EnginePeer.Presence?, topicId: Int64?, threadData: MessageHistoryThreadData?, search: Bool, synchronousLoad: Bool, force: Bool) { func setup(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, peer: EngineRenderedPeer?, presence: EnginePeer.Presence?, topicId: Int64?, threadData: MessageHistoryThreadData?, search: Bool, synchronousLoad: Bool, force: Bool) {
if force || self.currentState == nil || self.currentState!.0 !== context || self.currentState!.3 != peer || self.currentState!.5 != presence || self.currentState!.6 != topicId { if force || self.currentState == nil || self.currentState!.0 !== context || self.currentState!.2 !== theme || self.currentState!.3 != peer || self.currentState!.5 != presence || self.currentState!.6 != topicId {
let itemTheme = SelectablePeerNodeTheme(textColor: theme.actionSheet.primaryTextColor, secretTextColor: theme.chatList.secretTitleColor, selectedTextColor: theme.actionSheet.controlAccentColor, checkBackgroundColor: theme.actionSheet.opaqueItemBackgroundColor, checkFillColor: theme.actionSheet.controlAccentColor, checkColor: theme.actionSheet.checkContentColor, avatarPlaceholderColor: theme.list.mediaPlaceholderColor) let itemTheme = SelectablePeerNodeTheme(textColor: theme.actionSheet.primaryTextColor, secretTextColor: theme.chatList.secretTitleColor, selectedTextColor: theme.actionSheet.controlAccentColor, checkBackgroundColor: theme.actionSheet.opaqueItemBackgroundColor, checkFillColor: theme.actionSheet.controlAccentColor, checkColor: theme.actionSheet.checkContentColor, avatarPlaceholderColor: theme.list.mediaPlaceholderColor)
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)

View File

@ -54,7 +54,7 @@ final class ShareControllerRecentPeersGridItemNode: GridItemNode {
} }
func setup(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings) { func setup(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings) {
if self.currentState == nil || self.currentState!.0 !== context { if self.currentState == nil || self.currentState!.0 !== context || self.currentState!.1 !== theme {
let peersNode: ChatListSearchRecentPeersNode let peersNode: ChatListSearchRecentPeersNode
if let currentPeersNode = self.peersNode { if let currentPeersNode = self.peersNode {
peersNode = currentPeersNode peersNode = currentPeersNode

View File

@ -27,7 +27,7 @@ protocol ShareLoadingContainer: ASDisplayNode {
public final class ShareLoadingContainerNode: ASDisplayNode, ShareContentContainerNode, ShareLoadingContainer { public final class ShareLoadingContainerNode: ASDisplayNode, ShareContentContainerNode, ShareLoadingContainer {
private var contentOffsetUpdated: ((CGFloat, ContainedViewLayoutTransition) -> Void)? private var contentOffsetUpdated: ((CGFloat, ContainedViewLayoutTransition) -> Void)?
private let theme: PresentationTheme private var theme: PresentationTheme
private let activityIndicator: ActivityIndicator private let activityIndicator: ActivityIndicator
private let statusNode: RadialStatusNode private let statusNode: RadialStatusNode
private let doneStatusNode: RadialStatusNode private let doneStatusNode: RadialStatusNode
@ -78,6 +78,10 @@ public final class ShareLoadingContainerNode: ASDisplayNode, ShareContentContain
self.contentOffsetUpdated = f self.contentOffsetUpdated = f
} }
public func updateTheme(_ theme: PresentationTheme) {
self.theme = theme
}
public func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) { public func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
let nodeHeight: CGFloat = 125.0 let nodeHeight: CGFloat = 125.0
@ -98,7 +102,7 @@ public final class ShareLoadingContainerNode: ASDisplayNode, ShareContentContain
public final class ShareProlongedLoadingContainerNode: ASDisplayNode, ShareContentContainerNode, ShareLoadingContainer { public final class ShareProlongedLoadingContainerNode: ASDisplayNode, ShareContentContainerNode, ShareLoadingContainer {
private var contentOffsetUpdated: ((CGFloat, ContainedViewLayoutTransition) -> Void)? private var contentOffsetUpdated: ((CGFloat, ContainedViewLayoutTransition) -> Void)?
private let theme: PresentationTheme private var theme: PresentationTheme
private let strings: PresentationStrings private let strings: PresentationStrings
private let animationNode: AnimatedStickerNode private let animationNode: AnimatedStickerNode
@ -271,6 +275,10 @@ public final class ShareProlongedLoadingContainerNode: ASDisplayNode, ShareConte
self.animationStatusDisposable.dispose() self.animationStatusDisposable.dispose()
} }
public func updateTheme(_ theme: PresentationTheme) {
self.theme = theme
}
public func activate() { public func activate() {
} }

View File

@ -65,6 +65,9 @@ private struct SharePeerEntry: Comparable, Identifiable {
if lhs.threadData != rhs.threadData { if lhs.threadData != rhs.threadData {
return false return false
} }
if lhs.theme !== rhs.theme {
return false
}
return true return true
} }
@ -100,7 +103,8 @@ private func preparedGridEntryTransition(context: AccountContext, from fromEntri
final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode { final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode {
private let sharedContext: SharedAccountContext private let sharedContext: SharedAccountContext
private let context: AccountContext private let context: AccountContext
private let theme: PresentationTheme private var theme: PresentationTheme
private let themePromise: Promise<PresentationTheme>
private let strings: PresentationStrings private let strings: PresentationStrings
private let nameDisplayOrder: PresentationPersonNameOrder private let nameDisplayOrder: PresentationPersonNameOrder
private let controllerInteraction: ShareControllerInteraction private let controllerInteraction: ShareControllerInteraction
@ -153,6 +157,8 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode {
self.sharedContext = sharedContext self.sharedContext = sharedContext
self.context = context self.context = context
self.theme = theme self.theme = theme
self.themePromise = Promise()
self.themePromise.set(.single(theme))
self.strings = strings self.strings = strings
self.nameDisplayOrder = nameDisplayOrder self.nameDisplayOrder = nameDisplayOrder
self.controllerInteraction = controllerInteraction self.controllerInteraction = controllerInteraction
@ -164,8 +170,8 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode {
self.peersValue.set(.single(peers)) self.peersValue.set(.single(peers))
let items: Signal<[SharePeerEntry], NoError> = combineLatest(self.peersValue.get(), self.foundPeers.get(), self.tick.get()) let items: Signal<[SharePeerEntry], NoError> = combineLatest(self.peersValue.get(), self.foundPeers.get(), self.tick.get(), self.themePromise.get())
|> map { [weak controllerInteraction] initialPeers, foundPeers, _ -> [SharePeerEntry] in |> map { [weak controllerInteraction] initialPeers, foundPeers, _, theme -> [SharePeerEntry] in
var entries: [SharePeerEntry] = [] var entries: [SharePeerEntry] = []
var index: Int32 = 0 var index: Int32 = 0
@ -303,6 +309,13 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode {
self.disposable.dispose() self.disposable.dispose()
} }
func updateTheme(_ theme: PresentationTheme) {
self.theme = theme
self.themePromise.set(.single(theme))
self.contentTitleNode.attributedText = NSAttributedString(string: self.strings.ShareMenu_ShareTo, font: Font.medium(20.0), textColor: self.theme.actionSheet.primaryTextColor)
self.updateSelectedPeers(animated: false)
}
private func enqueueTransition(_ transition: ShareGridTransaction, firstTime: Bool) { private func enqueueTransition(_ transition: ShareGridTransaction, firstTime: Bool) {
self.enqueuedTransitions.append((transition, firstTime)) self.enqueuedTransitions.append((transition, firstTime))

View File

@ -42,12 +42,10 @@ final class ShareSearchBarNode: ASDisplayNode, UITextFieldDelegate {
self.textInputNode = TextFieldNode() self.textInputNode = TextFieldNode()
self.textInputNode.fixOffset = false self.textInputNode.fixOffset = false
let textColor: UIColor = theme.actionSheet.inputTextColor let textColor: UIColor = theme.actionSheet.inputTextColor
let keyboardAppearance: UIKeyboardAppearance = UIKeyboardAppearance.default
self.textInputNode.textField.font = Font.regular(16.0) self.textInputNode.textField.font = Font.regular(16.0)
self.textInputNode.textField.textColor = textColor self.textInputNode.textField.textColor = textColor
self.textInputNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(16.0), NSAttributedString.Key.foregroundColor: textColor] self.textInputNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(16.0), NSAttributedString.Key.foregroundColor: textColor]
self.textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0) self.textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
self.textInputNode.textField.keyboardAppearance = keyboardAppearance
self.textInputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(16.0), textColor: theme.actionSheet.inputPlaceholderColor) self.textInputNode.textField.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(16.0), textColor: theme.actionSheet.inputPlaceholderColor)
self.textInputNode.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance self.textInputNode.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.textInputNode.textField.tintColor = theme.actionSheet.controlAccentColor self.textInputNode.textField.tintColor = theme.actionSheet.controlAccentColor
@ -88,6 +86,19 @@ final class ShareSearchBarNode: ASDisplayNode, UITextFieldDelegate {
transition.updateFrame(node: self.textInputNode, frame: CGRect(origin: CGPoint(x: backgroundFrame.minX + inputInsets.left, y: backgroundFrame.minY + UIScreenPixel), size: CGSize(width: backgroundFrame.size.width - inputInsets.left - inputInsets.right, height: backgroundFrame.size.height))) transition.updateFrame(node: self.textInputNode, frame: CGRect(origin: CGPoint(x: backgroundFrame.minX + inputInsets.left, y: backgroundFrame.minY + UIScreenPixel), size: CGSize(width: backgroundFrame.size.width - inputInsets.left - inputInsets.right, height: backgroundFrame.size.height)))
} }
func updateTheme(_ theme: PresentationTheme) {
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 16.0, color: theme.actionSheet.inputBackgroundColor)
self.searchIconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Share/SearchBarSearchIcon"), color: theme.actionSheet.inputPlaceholderColor)
self.clearButton.setImage(generateClearIcon(color: theme.actionSheet.inputClearButtonColor), for: [])
let textColor: UIColor = theme.actionSheet.inputTextColor
self.textInputNode.textField.textColor = textColor
self.textInputNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(16.0), NSAttributedString.Key.foregroundColor: textColor]
self.textInputNode.textField.attributedPlaceholder = NSAttributedString(string: self.textInputNode.textField.attributedPlaceholder?.string ?? "", font: Font.regular(16.0), textColor: theme.actionSheet.inputPlaceholderColor)
self.textInputNode.textField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.textInputNode.textField.tintColor = theme.actionSheet.controlAccentColor
}
func activateInput() { func activateInput() {
self.textInputNode.textField.becomeFirstResponder() self.textInputNode.textField.becomeFirstResponder()
} }

View File

@ -121,6 +121,9 @@ private struct ShareSearchPeerEntry: Comparable, Identifiable {
if lhs.peer != rhs.peer { if lhs.peer != rhs.peer {
return false return false
} }
if lhs.theme !== rhs.theme {
return false
}
return true return true
} }
@ -164,6 +167,8 @@ private func preparedRecentEntryTransition(context: AccountContext, from fromEnt
final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
private let sharedContext: SharedAccountContext private let sharedContext: SharedAccountContext
private let context: AccountContext private let context: AccountContext
private var theme: PresentationTheme
private let themePromise: Promise<PresentationTheme>
private let strings: PresentationStrings private let strings: PresentationStrings
private let controllerInteraction: ShareControllerInteraction private let controllerInteraction: ShareControllerInteraction
@ -196,6 +201,9 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
init(sharedContext: SharedAccountContext, context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, controllerInteraction: ShareControllerInteraction, recentPeers recentPeerList: [RenderedPeer]) { init(sharedContext: SharedAccountContext, context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, controllerInteraction: ShareControllerInteraction, recentPeers recentPeerList: [RenderedPeer]) {
self.sharedContext = sharedContext self.sharedContext = sharedContext
self.context = context self.context = context
self.theme = theme
self.themePromise = Promise<PresentationTheme>()
self.themePromise.set(.single(theme))
self.strings = strings self.strings = strings
self.controllerInteraction = controllerInteraction self.controllerInteraction = controllerInteraction
@ -237,8 +245,8 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
self.cancelButtonNode.addTarget(self, action: #selector(self.cancelPressed), forControlEvents: .touchUpInside) self.cancelButtonNode.addTarget(self, action: #selector(self.cancelPressed), forControlEvents: .touchUpInside)
let foundItems = self.searchQuery.get() let foundItems = combineLatest(self.searchQuery.get(), self.themePromise.get())
|> mapToSignal { query -> Signal<([ShareSearchPeerEntry]?, Bool), NoError> in |> mapToSignal { query, theme -> Signal<([ShareSearchPeerEntry]?, Bool), NoError> in
if !query.isEmpty { if !query.isEmpty {
let accountPeer = context.account.postbox.loadedPeerWithId(context.account.peerId) |> take(1) let accountPeer = context.account.postbox.loadedPeerWithId(context.account.peerId) |> take(1)
let foundLocalPeers = context.account.postbox.searchPeers(query: query.lowercased()) let foundLocalPeers = context.account.postbox.searchPeers(query: query.lowercased())
@ -354,8 +362,8 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
} }
|> distinctUntilChanged |> distinctUntilChanged
let recentItems: Signal<[ShareSearchRecentEntry], NoError> = hasRecentPeers let recentItems: Signal<[ShareSearchRecentEntry], NoError> = combineLatest(hasRecentPeers, self.themePromise.get())
|> map { hasRecentPeers -> [ShareSearchRecentEntry] in |> map { hasRecentPeers, theme -> [ShareSearchRecentEntry] in
var recentItemList: [ShareSearchRecentEntry] = [] var recentItemList: [ShareSearchRecentEntry] = []
if hasRecentPeers { if hasRecentPeers {
recentItemList.append(.topPeers(theme, strings)) recentItemList.append(.topPeers(theme, strings))
@ -404,6 +412,14 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
self.searchNode.deactivateInput() self.searchNode.deactivateInput()
} }
func updateTheme(_ theme: PresentationTheme) {
self.theme = theme
self.themePromise.set(.single(theme))
self.searchNode.updateTheme(theme)
self.contentSeparatorNode.backgroundColor = theme.actionSheet.opaqueItemSeparatorColor
self.cancelButtonNode.setTitle(self.strings.Common_Cancel, with: cancelFont, with: self.theme.actionSheet.controlAccentColor, for: [])
}
private func calculateMetrics(size: CGSize) -> (topInset: CGFloat, itemWidth: CGFloat) { private func calculateMetrics(size: CGSize) -> (topInset: CGFloat, itemWidth: CGFloat) {
let itemCount: Int let itemCount: Int
if self.contentGridNode.isHidden { if self.contentGridNode.isHidden {

View File

@ -42,6 +42,9 @@ private struct ShareTopicEntry: Comparable, Identifiable {
if lhs.threadData != rhs.threadData { if lhs.threadData != rhs.threadData {
return false return false
} }
if lhs.theme !== rhs.theme {
return false
}
return true return true
} }
@ -157,7 +160,8 @@ final class ShareTopicsContainerNode: ASDisplayNode, ShareContentContainerNode {
private let sharedContext: SharedAccountContext private let sharedContext: SharedAccountContext
private let context: AccountContext private let context: AccountContext
private let theme: PresentationTheme private var theme: PresentationTheme
private let themePromise: Promise<PresentationTheme>
private let strings: PresentationStrings private let strings: PresentationStrings
private let controllerInteraction: ShareControllerInteraction private let controllerInteraction: ShareControllerInteraction
@ -184,6 +188,8 @@ final class ShareTopicsContainerNode: ASDisplayNode, ShareContentContainerNode {
self.sharedContext = sharedContext self.sharedContext = sharedContext
self.context = context self.context = context
self.theme = theme self.theme = theme
self.themePromise = Promise()
self.themePromise.set(.single(theme))
self.strings = strings self.strings = strings
self.controllerInteraction = controllerInteraction self.controllerInteraction = controllerInteraction
@ -192,8 +198,8 @@ final class ShareTopicsContainerNode: ASDisplayNode, ShareContentContainerNode {
return $0.items return $0.items
}) })
let items: Signal<[ShareTopicEntry], NoError> = self.topicsValue.get() let items: Signal<[ShareTopicEntry], NoError> = (combineLatest(self.topicsValue.get(), self.themePromise.get()))
|> map { topics -> [ShareTopicEntry] in |> map { topics, theme -> [ShareTopicEntry] in
var entries: [ShareTopicEntry] = [] var entries: [ShareTopicEntry] = []
var index: Int32 = 0 var index: Int32 = 0
@ -368,6 +374,13 @@ final class ShareTopicsContainerNode: ASDisplayNode, ShareContentContainerNode {
} }
} }
public func updateTheme(_ theme: PresentationTheme) {
self.theme = theme
self.themePromise.set(.single(theme))
self.contentTitleNode.attributedText = NSAttributedString(string: self.contentTitleNode.attributedText?.string ?? "", font: Font.medium(20.0), textColor: self.theme.actionSheet.primaryTextColor)
self.contentSubtitleNode.attributedText = NSAttributedString(string: self.contentSubtitleNode.attributedText?.string ?? "", font: subtitleFont, textColor: self.theme.actionSheet.secondaryTextColor)
}
func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) { func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
let firstLayout = self.validLayout == nil let firstLayout = self.validLayout == nil
self.validLayout = (size, bottomInset) self.validLayout = (size, bottomInset)

View File

@ -690,6 +690,11 @@ final class VoiceChatPreviewContentNode: ASDisplayNode, ShareContentContainerNod
self.contentOffsetUpdated = f self.contentOffsetUpdated = f
} }
func updateTheme(_ theme: PresentationTheme) {
self.titleNode.attributedText = NSAttributedString(string: self.titleNode.attributedText?.string ?? "", font: Font.semibold(16.0), textColor: theme.actionSheet.primaryTextColor)
self.countNode.attributedText = NSAttributedString(string: self.countNode.attributedText?.string ?? "", font: Font.regular(16.0), textColor: theme.actionSheet.secondaryTextColor)
}
func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) { func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
let sideInset: CGFloat = 16.0 let sideInset: CGFloat = 16.0
let titleSize = self.titleNode.updateLayout(CGSize(width: size.width - sideInset * 2.0, height: size.height)) let titleSize = self.titleNode.updateLayout(CGSize(width: size.width - sideInset * 2.0, height: size.height))

View File

@ -895,9 +895,60 @@ private final class GroupHeaderLayer: UIView {
} }
} }
var clearSize: CGSize = .zero
var clearWidth: CGFloat = 0.0
if hasClear {
var updateImage = themeUpdated
let clearIconLayer: SimpleLayer
if let current = self.clearIconLayer {
clearIconLayer = current
} else {
updateImage = true
clearIconLayer = SimpleLayer()
self.clearIconLayer = clearIconLayer
self.layer.addSublayer(clearIconLayer)
}
let tintClearIconLayer: SimpleLayer
if let current = self.tintClearIconLayer {
tintClearIconLayer = current
} else {
updateImage = true
tintClearIconLayer = SimpleLayer()
self.tintClearIconLayer = tintClearIconLayer
self.tintContentLayer.addSublayer(tintClearIconLayer)
}
tintClearIconLayer.isHidden = !needsVibrancy
clearSize = clearIconLayer.bounds.size
if updateImage, let image = PresentationResourcesChat.chatInputMediaPanelGridDismissImage(theme, color: theme.chat.inputMediaPanel.panelContentVibrantOverlayColor) {
clearSize = image.size
clearIconLayer.contents = image.cgImage
}
if updateImage, let image = PresentationResourcesChat.chatInputMediaPanelGridDismissImage(theme, color: .white) {
tintClearIconLayer.contents = image.cgImage
}
tintClearIconLayer.frame = clearIconLayer.frame
clearWidth = 4.0 + clearSize.width
} else {
if let clearIconLayer = self.clearIconLayer {
self.clearIconLayer = nil
clearIconLayer.removeFromSuperlayer()
}
if let tintClearIconLayer = self.tintClearIconLayer {
self.tintClearIconLayer = nil
tintClearIconLayer.removeFromSuperlayer()
}
}
var textConstrainedWidth = constrainedSize.width - titleHorizontalOffset - 10.0 var textConstrainedWidth = constrainedSize.width - titleHorizontalOffset - 10.0
if let actionButtonSize = actionButtonSize { if let actionButtonSize = actionButtonSize {
textConstrainedWidth -= actionButtonSize.width - 8.0 textConstrainedWidth -= actionButtonSize.width - 10.0
}
if clearWidth > 0.0 {
textConstrainedWidth -= clearWidth + 8.0
} }
let textSize: CGSize let textSize: CGSize
@ -915,13 +966,14 @@ private final class GroupHeaderLayer: UIView {
} }
let string = NSAttributedString(string: stringValue, font: font, textColor: color) let string = NSAttributedString(string: stringValue, font: font, textColor: color)
let whiteString = NSAttributedString(string: stringValue, font: font, textColor: .white) let whiteString = NSAttributedString(string: stringValue, font: font, textColor: .white)
let stringBounds = string.boundingRect(with: CGSize(width: textConstrainedWidth, height: 100.0), options: .usesLineFragmentOrigin, context: nil) let stringBounds = string.boundingRect(with: CGSize(width: textConstrainedWidth, height: 18.0), options: [.usesLineFragmentOrigin, .truncatesLastVisibleLine], context: nil)
textSize = CGSize(width: ceil(stringBounds.width), height: ceil(stringBounds.height)) textSize = CGSize(width: ceil(stringBounds.width), height: ceil(stringBounds.height))
self.textLayer.contents = generateImage(textSize, opaque: false, scale: 0.0, rotatedContext: { size, context in self.textLayer.contents = generateImage(textSize, opaque: false, scale: 0.0, rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size)) context.clear(CGRect(origin: CGPoint(), size: size))
UIGraphicsPushContext(context) UIGraphicsPushContext(context)
string.draw(in: stringBounds) //string.draw(in: stringBounds)
string.draw(with: stringBounds, options: [.usesLineFragmentOrigin, .truncatesLastVisibleLine], context: nil)
UIGraphicsPopContext() UIGraphicsPopContext()
})?.cgImage })?.cgImage
@ -929,7 +981,8 @@ private final class GroupHeaderLayer: UIView {
context.clear(CGRect(origin: CGPoint(), size: size)) context.clear(CGRect(origin: CGPoint(), size: size))
UIGraphicsPushContext(context) UIGraphicsPushContext(context)
whiteString.draw(in: stringBounds) //whiteString.draw(in: stringBounds)
whiteString.draw(with: stringBounds, options: [.usesLineFragmentOrigin, .truncatesLastVisibleLine], context: nil)
UIGraphicsPopContext() UIGraphicsPopContext()
})?.cgImage })?.cgImage
@ -1062,54 +1115,7 @@ private final class GroupHeaderLayer: UIView {
} }
} }
var clearWidth: CGFloat = 0.0 self.clearIconLayer?.frame = CGRect(origin: CGPoint(x: constrainedSize.width - clearSize.width, y: floorToScreenPixels((textSize.height - clearSize.height) / 2.0)), size: clearSize)
if hasClear {
var updateImage = themeUpdated
let clearIconLayer: SimpleLayer
if let current = self.clearIconLayer {
clearIconLayer = current
} else {
updateImage = true
clearIconLayer = SimpleLayer()
self.clearIconLayer = clearIconLayer
self.layer.addSublayer(clearIconLayer)
}
let tintClearIconLayer: SimpleLayer
if let current = self.tintClearIconLayer {
tintClearIconLayer = current
} else {
updateImage = true
tintClearIconLayer = SimpleLayer()
self.tintClearIconLayer = tintClearIconLayer
self.tintContentLayer.addSublayer(tintClearIconLayer)
}
tintClearIconLayer.isHidden = !needsVibrancy
var clearSize = clearIconLayer.bounds.size
if updateImage, let image = PresentationResourcesChat.chatInputMediaPanelGridDismissImage(theme, color: theme.chat.inputMediaPanel.panelContentVibrantOverlayColor) {
clearSize = image.size
clearIconLayer.contents = image.cgImage
}
if updateImage, let image = PresentationResourcesChat.chatInputMediaPanelGridDismissImage(theme, color: .white) {
tintClearIconLayer.contents = image.cgImage
}
clearIconLayer.frame = CGRect(origin: CGPoint(x: constrainedSize.width - clearSize.width, y: floorToScreenPixels((textSize.height - clearSize.height) / 2.0)), size: clearSize)
tintClearIconLayer.frame = clearIconLayer.frame
clearWidth = 4.0 + clearSize.width
} else {
if let clearIconLayer = self.clearIconLayer {
self.clearIconLayer = nil
clearIconLayer.removeFromSuperlayer()
}
if let tintClearIconLayer = self.tintClearIconLayer {
self.tintClearIconLayer = nil
tintClearIconLayer.removeFromSuperlayer()
}
}
var size: CGSize var size: CGSize
size = CGSize(width: constrainedSize.width, height: constrainedSize.height) size = CGSize(width: constrainedSize.width, height: constrainedSize.height)

View File

@ -14577,8 +14577,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return return
} }
let replyMessageId = self.presentationInterfaceState.interfaceState.replyMessageId var isScheduledMessages = false
if case .scheduledMessages = self.presentationInterfaceState.subject {
isScheduledMessages = true
}
let sendMessage: (Int32?) -> Void = { [weak self] scheduleTime in
guard let self else {
return
}
let replyMessageId = self.presentationInterfaceState.interfaceState.replyMessageId
if self.context.engine.messages.enqueueOutgoingMessageWithChatContextResult(to: peerId, threadId: self.chatLocation.threadId, botId: results.botId, result: result, replyToMessageId: replyMessageId, hideVia: hideVia, silentPosting: silentPosting) { if self.context.engine.messages.enqueueOutgoingMessageWithChatContextResult(to: peerId, threadId: self.chatLocation.threadId, botId: results.botId, result: result, replyToMessageId: replyMessageId, hideVia: hideVia, silentPosting: silentPosting) {
self.chatDisplayNode.setupSendActionOnViewUpdate({ [weak self] in self.chatDisplayNode.setupSendActionOnViewUpdate({ [weak self] in
if let strongSelf = self { if let strongSelf = self {
@ -14606,6 +14614,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
} }
if isScheduledMessages {
self.presentScheduleTimePicker(style: .default, dismissByTapOutside: false, completion: { time in
sendMessage(time)
})
} else {
sendMessage(nil)
}
}
private func firstLoadedMessageToListen() -> Message? { private func firstLoadedMessageToListen() -> Message? {
var messageToListen: Message? var messageToListen: Message?
self.chatDisplayNode.historyNode.forEachMessageInCurrentHistoryView { message in self.chatDisplayNode.historyNode.forEachMessageInCurrentHistoryView { message in
@ -14750,6 +14767,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.chatDisplayNode.updateRecordedMediaDeleted(true) self.chatDisplayNode.updateRecordedMediaDeleted(true)
self.audioRecorder.set(.single(nil)) self.audioRecorder.set(.single(nil))
case .preview: case .preview:
self.audioRecorder.set(.single(nil))
self.updateChatPresentationInterfaceState(animated: true, interactive: true, { self.updateChatPresentationInterfaceState(animated: true, interactive: true, {
$0.updatedInputTextPanelState { panelState in $0.updatedInputTextPanelState { panelState in
return panelState.withUpdatedMediaRecordingState(.waitingForPreview) return panelState.withUpdatedMediaRecordingState(.waitingForPreview)
@ -14779,7 +14797,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
} }
}) })
self.audioRecorder.set(.single(nil))
case .send: case .send:
self.chatDisplayNode.updateRecordedMediaDeleted(false) self.chatDisplayNode.updateRecordedMediaDeleted(false)
let _ = (audioRecorderValue.takenRecordedData() let _ = (audioRecorderValue.takenRecordedData()

View File

@ -474,14 +474,29 @@ func searchQuerySuggestionResultStateForChatInterfacePresentationState(_ chatPre
} }
} }
let participants = searchPeerMembers(context: context, peerId: peer.id, chatLocation: chatPresentationInterfaceState.chatLocation, query: query, scope: .memberSuggestion) let participants = combineLatest(
|> map { peers -> (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult? in context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)),
searchPeerMembers(context: context, peerId: peer.id, chatLocation: chatPresentationInterfaceState.chatLocation, query: query, scope: .memberSuggestion)
)
|> map { accountPeer, peers -> (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult? in
let filteredPeers = peers let filteredPeers = peers
var sortedPeers: [EnginePeer] = [] var sortedPeers: [EnginePeer] = []
sortedPeers.append(contentsOf: filteredPeers.sorted(by: { lhs, rhs in sortedPeers.append(contentsOf: filteredPeers.sorted(by: { lhs, rhs in
let result = lhs.indexName.stringRepresentation(lastNameFirst: true).compare(rhs.indexName.stringRepresentation(lastNameFirst: true)) let result = lhs.indexName.stringRepresentation(lastNameFirst: true).compare(rhs.indexName.stringRepresentation(lastNameFirst: true))
return result == .orderedAscending return result == .orderedAscending
})) }))
if let accountPeer {
var hasOwnPeer = false
for peer in sortedPeers {
if peer.id == accountPeer.id {
hasOwnPeer = true
break
}
}
if !hasOwnPeer {
sortedPeers.append(accountPeer)
}
}
return { _ in return .mentions(sortedPeers) } return { _ in return .mentions(sortedPeers) }
} }

View File

@ -401,7 +401,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
reactionPeers: dateReactionsAndPeers.peers, reactionPeers: dateReactionsAndPeers.peers,
displayAllReactionPeers: item.message.id.peerId.namespace == Namespaces.Peer.CloudUser, displayAllReactionPeers: item.message.id.peerId.namespace == Namespaces.Peer.CloudUser,
replyCount: dateReplies, replyCount: dateReplies,
isPinned: item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && isReplyThread, isPinned: item.message.tags.contains(.pinned) && (!item.associatedData.isInPinnedListMode || isReplyThread),
hasAutoremove: item.message.isSelfExpiring, hasAutoremove: item.message.isSelfExpiring,
canViewReactionList: canViewMessageReactionList(message: item.message), canViewReactionList: canViewMessageReactionList(message: item.message),
animationCache: item.controllerInteraction.presentationContext.animationCache, animationCache: item.controllerInteraction.presentationContext.animationCache,

View File

@ -388,8 +388,12 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
let titleHeight: CGFloat = 54.0 let titleHeight: CGFloat = 54.0
var contentHeight = titleHeight + bottomInset + 52.0 + 17.0 var contentHeight = titleHeight + bottomInset + 52.0 + 17.0
let pickerHeight: CGFloat = min(216.0, layout.size.height - contentHeight) let pickerHeight: CGFloat = min(216.0, layout.size.height - contentHeight)
if let inputHeight = layout.inputHeight, inputHeight > 0.0, case .compact = layout.metrics.widthClass {
contentHeight = titleHeight + 52.0 + 17.0 + pickerHeight + inputHeight
buttonOffset = 0.0
} else {
contentHeight = titleHeight + bottomInset + 52.0 + 17.0 + pickerHeight + buttonOffset contentHeight = titleHeight + bottomInset + 52.0 + 17.0 + pickerHeight + buttonOffset
}
let width = horizontalContainerFillingSizeForLayout(layout: layout, sideInset: 0.0) let width = horizontalContainerFillingSizeForLayout(layout: layout, sideInset: 0.0)
let sideInset = floor((layout.size.width - width) / 2.0) let sideInset = floor((layout.size.width - width) / 2.0)
@ -419,7 +423,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
transition.updateFrame(node: self.doneButton, frame: CGRect(x: buttonInset, y: contentHeight - doneButtonHeight - insets.bottom - 16.0 - buttonOffset, width: contentFrame.width, height: doneButtonHeight)) transition.updateFrame(node: self.doneButton, frame: CGRect(x: buttonInset, y: contentHeight - doneButtonHeight - insets.bottom - 16.0 - buttonOffset, width: contentFrame.width, height: doneButtonHeight))
let onlineButtonHeight = self.onlineButton.updateLayout(width: contentFrame.width - buttonInset * 2.0, transition: transition) let onlineButtonHeight = self.onlineButton.updateLayout(width: contentFrame.width - buttonInset * 2.0, transition: transition)
transition.updateFrame(node: self.onlineButton, frame: CGRect(x: buttonInset, y: contentHeight - onlineButtonHeight - insets.bottom - 16.0, width: contentFrame.width, height: onlineButtonHeight)) transition.updateFrame(node: self.onlineButton, frame: CGRect(x: buttonInset, y: contentHeight - onlineButtonHeight - cleanInsets.bottom - 16.0, width: contentFrame.width, height: onlineButtonHeight))
self.pickerView?.frame = CGRect(origin: CGPoint(x: 0.0, y: 54.0), size: CGSize(width: contentFrame.width, height: pickerHeight)) self.pickerView?.frame = CGRect(origin: CGPoint(x: 0.0, y: 54.0), size: CGSize(width: contentFrame.width, height: pickerHeight))

View File

@ -1064,6 +1064,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
let textFieldWaitsForTouchUp: Bool let textFieldWaitsForTouchUp: Bool
if case .regular = metrics.widthClass, bottomInset.isZero { if case .regular = metrics.widthClass, bottomInset.isZero {
textFieldWaitsForTouchUp = true textFieldWaitsForTouchUp = true
} else if !textInputNode.textView.text.isEmpty {
textFieldWaitsForTouchUp = true
} else { } else {
textFieldWaitsForTouchUp = false textFieldWaitsForTouchUp = false
} }
@ -1700,7 +1702,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
hideInfo = true hideInfo = true
} }
case .waitingForPreview: case .waitingForPreview:
break Queue.mainQueue().after(0.3, {
self.actionButtons.micButton.audioRecorder = nil
})
} }
} }