mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
[WIP] Business
This commit is contained in:
parent
a603c138e9
commit
50339b3c4c
@ -94,11 +94,13 @@ public enum ChatListItemContent {
|
||||
public var commandPrefix: String?
|
||||
public var searchQuery: String?
|
||||
public var messageCount: Int?
|
||||
public var hideSeparator: Bool
|
||||
|
||||
public init(commandPrefix: String?, searchQuery: String?, messageCount: Int?) {
|
||||
public init(commandPrefix: String?, searchQuery: String?, messageCount: Int?, hideSeparator: Bool) {
|
||||
self.commandPrefix = commandPrefix
|
||||
self.searchQuery = searchQuery
|
||||
self.messageCount = messageCount
|
||||
self.hideSeparator = hideSeparator
|
||||
}
|
||||
}
|
||||
|
||||
@ -1166,6 +1168,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
private var currentItemHeight: CGFloat?
|
||||
let forwardedIconNode: ASImageNode
|
||||
let textNode: TextNodeWithEntities
|
||||
var trailingTextBadgeNode: TextNode?
|
||||
var trailingTextBadgeBackground: UIImageView?
|
||||
var dustNode: InvisibleInkDustNode?
|
||||
let inputActivitiesNode: ChatListInputActivitiesNode
|
||||
let dateNode: TextNode
|
||||
@ -1437,6 +1441,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
self.textNode = TextNodeWithEntities()
|
||||
self.textNode.textNode.isUserInteractionEnabled = false
|
||||
self.textNode.textNode.displaysAsynchronously = true
|
||||
self.textNode.textNode.layer.anchorPoint = CGPoint()
|
||||
|
||||
self.inputActivitiesNode = ChatListInputActivitiesNode()
|
||||
self.inputActivitiesNode.isUserInteractionEnabled = false
|
||||
@ -1823,6 +1828,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
func asyncLayout() -> (_ item: ChatListItem, _ params: ListViewItemLayoutParams, _ first: Bool, _ last: Bool, _ firstWithHeader: Bool, _ nextIsPinned: Bool) -> (ListViewItemNodeLayout, (Bool, Bool) -> Void) {
|
||||
let dateLayout = TextNode.asyncLayout(self.dateNode)
|
||||
let textLayout = TextNodeWithEntities.asyncLayout(self.textNode)
|
||||
let makeTrailingTextBadgeLayout = TextNode.asyncLayout(self.trailingTextBadgeNode)
|
||||
let titleLayout = TextNode.asyncLayout(self.titleNode)
|
||||
let authorLayout = self.authorNode.asyncLayout()
|
||||
let makeMeasureLayout = TextNode.asyncLayout(self.measureNode)
|
||||
@ -2073,7 +2079,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
if case let .peer(peerData) = item.content, let customMessageListData = peerData.customMessageListData, customMessageListData.commandPrefix != nil {
|
||||
avatarDiameter = 40.0
|
||||
avatarLeftInset = 18.0 + avatarDiameter
|
||||
avatarLeftInset = 17.0 + avatarDiameter
|
||||
} else {
|
||||
if item.interaction.isInlineMode {
|
||||
avatarLeftInset = 12.0
|
||||
@ -2666,7 +2672,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
topIndex = peerData.messages.first?.index
|
||||
}
|
||||
if case let .peer(peerData) = item.content, let customMessageListData = peerData.customMessageListData {
|
||||
if let messageCount = customMessageListData.messageCount {
|
||||
if let messageCount = customMessageListData.messageCount, customMessageListData.commandPrefix == nil {
|
||||
dateText = "\(messageCount)"
|
||||
} else {
|
||||
dateText = " "
|
||||
@ -2990,9 +2996,23 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
let (authorLayout, authorApply) = authorLayout(item.context, rawContentWidth - badgeSize, item.presentationData.theme, effectiveAuthorTitle, forumThreads)
|
||||
|
||||
var textBottomRightCutout: CGFloat = 0.0
|
||||
|
||||
let trailingTextBadgeInsets = UIEdgeInsets(top: 2.0 - UIScreenPixel, left: 5.0, bottom: 2.0 - UIScreenPixel, right: 5.0)
|
||||
var trailingTextBadgeLayoutAndApply: (TextNodeLayout, () -> TextNode)?
|
||||
if case let .peer(peerData) = item.content, let customMessageListData = peerData.customMessageListData, customMessageListData.commandPrefix != nil, let messageCount = customMessageListData.messageCount, messageCount > 1 {
|
||||
let trailingText: String
|
||||
//TODO:localize
|
||||
trailingText = "+\(messageCount - 1) MORE"
|
||||
let trailingAttributedText = NSAttributedString(string: trailingText, font: Font.regular(12.0), textColor: theme.messageTextColor)
|
||||
let (layout, apply) = makeTrailingTextBadgeLayout(TextNodeLayoutArguments(attributedString: trailingAttributedText, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: rawContentWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
trailingTextBadgeLayoutAndApply = (layout, apply)
|
||||
textBottomRightCutout += layout.size.width + 4.0 + trailingTextBadgeInsets.left + trailingTextBadgeInsets.right
|
||||
}
|
||||
|
||||
var textCutout: TextNodeCutout?
|
||||
if !textLeftCutout.isZero {
|
||||
textCutout = TextNodeCutout(topLeft: CGSize(width: textLeftCutout, height: 10.0), topRight: nil, bottomRight: nil)
|
||||
if !textLeftCutout.isZero || !textBottomRightCutout.isZero {
|
||||
textCutout = TextNodeCutout(topLeft: textLeftCutout.isZero ? nil : CGSize(width: textLeftCutout, height: 10.0), topRight: nil, bottomRight: textBottomRightCutout.isZero ? nil : CGSize(width: textBottomRightCutout, height: 10.0))
|
||||
}
|
||||
|
||||
var textMaxWidth = rawContentWidth - badgeSize
|
||||
@ -3552,6 +3572,19 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
let _ = measureApply()
|
||||
let _ = dateApply()
|
||||
|
||||
var currentTextSnapshotView: UIView?
|
||||
if transition.isAnimated, let currentItem, currentItem.editing != item.editing, strongSelf.textNode.textNode.cachedLayout?.linesRects() != textLayout.linesRects() {
|
||||
if let textSnapshotView = strongSelf.textNode.textNode.view.snapshotContentTree() {
|
||||
textSnapshotView.layer.anchorPoint = CGPoint()
|
||||
currentTextSnapshotView = textSnapshotView
|
||||
strongSelf.textNode.textNode.view.superview?.insertSubview(textSnapshotView, aboveSubview: strongSelf.textNode.textNode.view)
|
||||
textSnapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak textSnapshotView] _ in
|
||||
textSnapshotView?.removeFromSuperview()
|
||||
})
|
||||
strongSelf.textNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.18)
|
||||
}
|
||||
}
|
||||
|
||||
let _ = textApply(TextNodeWithEntities.Arguments(
|
||||
context: item.context,
|
||||
cache: item.interaction.animationCache,
|
||||
@ -3572,7 +3605,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
var dateFrame = CGRect(origin: CGPoint(x: contentRect.origin.x + contentRect.size.width - dateLayout.size.width, y: contentRect.origin.y + 2.0), size: dateLayout.size)
|
||||
|
||||
if case let .peer(peerData) = item.content, let customMessageListData = peerData.customMessageListData, customMessageListData.messageCount != nil {
|
||||
if case let .peer(peerData) = item.content, let customMessageListData = peerData.customMessageListData, customMessageListData.messageCount != nil, customMessageListData.commandPrefix == nil {
|
||||
dateFrame.origin.x -= 10.0
|
||||
|
||||
let dateDisclosureIconView: UIImageView
|
||||
@ -3818,6 +3851,60 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.authorNode.assignParentNode(parentNode: nil)
|
||||
}
|
||||
|
||||
if let currentTextSnapshotView {
|
||||
transition.updatePosition(layer: currentTextSnapshotView.layer, position: textNodeFrame.origin)
|
||||
}
|
||||
|
||||
if let trailingTextBadgeLayoutAndApply {
|
||||
let badgeSize = CGSize(width: trailingTextBadgeLayoutAndApply.0.size.width + trailingTextBadgeInsets.left + trailingTextBadgeInsets.right, height: trailingTextBadgeLayoutAndApply.0.size.height + trailingTextBadgeInsets.top + trailingTextBadgeInsets.bottom - UIScreenPixel)
|
||||
|
||||
var badgeFrame: CGRect
|
||||
if textLayout.numberOfLines > 1 {
|
||||
badgeFrame = CGRect(origin: CGPoint(x: textLayout.trailingLineWidth, y: textNodeFrame.height - 3.0 - badgeSize.height), size: badgeSize)
|
||||
} else {
|
||||
let firstLineFrame = textLayout.linesRects().first ?? CGRect(origin: CGPoint(), size: textNodeFrame.size)
|
||||
badgeFrame = CGRect(origin: CGPoint(x: 0.0, y: firstLineFrame.height + 5.0), size: badgeSize)
|
||||
}
|
||||
|
||||
if badgeFrame.origin.x + badgeFrame.width >= textNodeFrame.width - 2.0 - 10.0 {
|
||||
badgeFrame.origin.x = textNodeFrame.width - 2.0 - badgeFrame.width
|
||||
}
|
||||
|
||||
let trailingTextBadgeBackground: UIImageView
|
||||
if let current = strongSelf.trailingTextBadgeBackground {
|
||||
trailingTextBadgeBackground = current
|
||||
} else {
|
||||
trailingTextBadgeBackground = UIImageView(image: tagBackgroundImage)
|
||||
strongSelf.trailingTextBadgeBackground = trailingTextBadgeBackground
|
||||
strongSelf.textNode.textNode.view.addSubview(trailingTextBadgeBackground)
|
||||
}
|
||||
trailingTextBadgeBackground.tintColor = theme.pinnedItemBackgroundColor.mixedWith(theme.unreadBadgeInactiveBackgroundColor, alpha: 0.1)
|
||||
|
||||
trailingTextBadgeBackground.frame = badgeFrame
|
||||
|
||||
let trailingTextBadgeFrame = CGRect(origin: CGPoint(x: badgeFrame.minX + trailingTextBadgeInsets.left, y: badgeFrame.minY + trailingTextBadgeInsets.top), size: trailingTextBadgeLayoutAndApply.0.size)
|
||||
let trailingTextBadgeNode = trailingTextBadgeLayoutAndApply.1()
|
||||
if strongSelf.trailingTextBadgeNode !== trailingTextBadgeNode {
|
||||
strongSelf.trailingTextBadgeNode?.removeFromSupernode()
|
||||
strongSelf.trailingTextBadgeNode = trailingTextBadgeNode
|
||||
|
||||
strongSelf.textNode.textNode.addSubnode(trailingTextBadgeNode)
|
||||
|
||||
trailingTextBadgeNode.layer.anchorPoint = CGPoint()
|
||||
}
|
||||
|
||||
trailingTextBadgeNode.frame = trailingTextBadgeFrame
|
||||
} else {
|
||||
if let trailingTextBadgeNode = strongSelf.trailingTextBadgeNode {
|
||||
strongSelf.trailingTextBadgeNode = nil
|
||||
trailingTextBadgeNode.removeFromSupernode()
|
||||
}
|
||||
if let trailingTextBadgeBackground = strongSelf.trailingTextBadgeBackground {
|
||||
strongSelf.trailingTextBadgeBackground = nil
|
||||
trailingTextBadgeBackground.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
if !itemTags.isEmpty {
|
||||
let itemTagListFrame = CGRect(origin: CGPoint(x: contentRect.minX, y: contentRect.maxY - 12.0), size: CGSize(width: contentRect.width, height: 20.0))
|
||||
|
||||
@ -4127,7 +4214,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
|
||||
if case let .peer(peerData) = item.content, let customMessageListData = peerData.customMessageListData {
|
||||
if customMessageListData.messageCount != nil {
|
||||
if customMessageListData.hideSeparator {
|
||||
strongSelf.separatorNode.isHidden = true
|
||||
}
|
||||
}
|
||||
|
@ -433,7 +433,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
},
|
||||
requiresPremiumForMessaging: peerEntry.requiresPremiumForMessaging,
|
||||
displayAsTopicList: peerEntry.displayAsTopicList,
|
||||
tags: chatListItemTags(accountPeerId: context.account.peerId, peer: peer.chatMainPeer, isUnread: combinedReadState?.isUnread ?? false, isMuted: isRemovedFromTotalUnreadCount, isContact: isContact, hasUnseenMentions: hasUnseenMentions, chatListFilters: chatListFilters)
|
||||
tags: chatListItemTags(location: location, accountPeerId: context.account.peerId, peer: peer.chatMainPeer, isUnread: combinedReadState?.isUnread ?? false, isMuted: isRemovedFromTotalUnreadCount, isContact: isContact, hasUnseenMentions: hasUnseenMentions, chatListFilters: chatListFilters)
|
||||
)),
|
||||
editing: editing,
|
||||
hasActiveRevealControls: hasActiveRevealControls,
|
||||
@ -811,7 +811,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
},
|
||||
requiresPremiumForMessaging: peerEntry.requiresPremiumForMessaging,
|
||||
displayAsTopicList: peerEntry.displayAsTopicList,
|
||||
tags: chatListItemTags(accountPeerId: context.account.peerId, peer: peer.chatMainPeer, isUnread: combinedReadState?.isUnread ?? false, isMuted: isRemovedFromTotalUnreadCount, isContact: isContact, hasUnseenMentions: hasUnseenMentions, chatListFilters: chatListFilters)
|
||||
tags: chatListItemTags(location: location, accountPeerId: context.account.peerId, peer: peer.chatMainPeer, isUnread: combinedReadState?.isUnread ?? false, isMuted: isRemovedFromTotalUnreadCount, isContact: isContact, hasUnseenMentions: hasUnseenMentions, chatListFilters: chatListFilters)
|
||||
)),
|
||||
editing: editing,
|
||||
hasActiveRevealControls: hasActiveRevealControls,
|
||||
@ -4206,7 +4206,11 @@ func hideChatListContacts(context: AccountContext) {
|
||||
let _ = ApplicationSpecificNotice.setDisplayChatListContacts(accountManager: context.sharedContext.accountManager).startStandalone()
|
||||
}
|
||||
|
||||
func chatListItemTags(accountPeerId: EnginePeer.Id, peer: EnginePeer?, isUnread: Bool, isMuted: Bool, isContact: Bool, hasUnseenMentions: Bool, chatListFilters: [ChatListFilter]?) -> [ChatListItemContent.Tag] {
|
||||
func chatListItemTags(location: ChatListControllerLocation, accountPeerId: EnginePeer.Id, peer: EnginePeer?, isUnread: Bool, isMuted: Bool, isContact: Bool, hasUnseenMentions: Bool, chatListFilters: [ChatListFilter]?) -> [ChatListItemContent.Tag] {
|
||||
if case .chatList = location {
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
guard let chatListFilters, !chatListFilters.isEmpty else {
|
||||
return []
|
||||
}
|
||||
|
@ -1202,6 +1202,8 @@ public func canSendMessagesToChat(_ state: ChatPresentationInterfaceState) -> Bo
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} else if case .customChatContents = state.chatLocation {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
|
@ -816,6 +816,11 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
||||
func setMessage(_ message: Message, displayInfo: Bool = true, translateToLanguage: String? = nil, peerIsCopyProtected: Bool = false) {
|
||||
self.currentMessage = message
|
||||
|
||||
var displayInfo = displayInfo
|
||||
if Namespaces.Message.allNonRegular.contains(message.id.namespace) {
|
||||
displayInfo = false
|
||||
}
|
||||
|
||||
var canDelete: Bool
|
||||
var canShare = !message.containsSecretMedia
|
||||
|
||||
|
@ -285,6 +285,7 @@ private enum PreferencesKeyValues: Int32 {
|
||||
case didCacheSavedMessageTagsPrefix = 34
|
||||
case displaySavedChatsAsTopics = 35
|
||||
case shortcutMessages = 37
|
||||
case timezoneList = 38
|
||||
}
|
||||
|
||||
public func applicationSpecificPreferencesKey(_ value: Int32) -> ValueBoxKey {
|
||||
@ -474,6 +475,12 @@ public struct PreferencesKeys {
|
||||
key.setInt32(0, value: PreferencesKeyValues.shortcutMessages.rawValue)
|
||||
return key
|
||||
}
|
||||
|
||||
public static func timezoneList() -> ValueBoxKey {
|
||||
let key = ValueBoxKey(length: 4)
|
||||
key.setInt32(0, value: PreferencesKeyValues.timezoneList.rawValue)
|
||||
return key
|
||||
}
|
||||
}
|
||||
|
||||
private enum SharedDataKeyValues: Int32 {
|
||||
|
@ -185,5 +185,13 @@ public extension TelegramEngine {
|
||||
public func sendMessageShortcut(peerId: EnginePeer.Id, id: Int32) {
|
||||
let _ = _internal_sendMessageShortcut(account: self.account, peerId: peerId, id: id).startStandalone()
|
||||
}
|
||||
|
||||
public func cachedTimeZoneList() -> Signal<TimeZoneList?, NoError> {
|
||||
return _internal_cachedTimeZoneList(account: self.account)
|
||||
}
|
||||
|
||||
public func keepCachedTimeZoneListUpdated() -> Signal<Never, NoError> {
|
||||
return _internal_keepCachedTimeZoneListUpdated(account: self.account)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -229,7 +229,7 @@ func _internal_shortcutMessageList(account: Account) -> Signal<ShortcutMessageLi
|
||||
historyViewKeys[shortcut.id] = historyViewKey
|
||||
keys.append(historyViewKey)
|
||||
|
||||
let summaryKey: PostboxViewKey = .historyTagSummaryView(tag: [], peerId: account.peerId, threadId: Int64(shortcut.id), namespace: Namespaces.Message.ScheduledCloud, customTag: nil)
|
||||
let summaryKey: PostboxViewKey = .historyTagSummaryView(tag: [], peerId: account.peerId, threadId: Int64(shortcut.id), namespace: Namespaces.Message.QuickReplyCloud, customTag: nil)
|
||||
summaryKeys[shortcut.id] = summaryKey
|
||||
keys.append(summaryKey)
|
||||
}
|
||||
|
@ -0,0 +1,106 @@
|
||||
import Foundation
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
import TelegramApi
|
||||
import MtProtoKit
|
||||
|
||||
public final class TimeZoneList: Codable, Equatable {
|
||||
public final class Item: Codable, Equatable {
|
||||
public let id: String
|
||||
public let title: String
|
||||
public let utcOffset: Int32
|
||||
|
||||
public init(id: String, title: String, utcOffset: Int32) {
|
||||
self.id = id
|
||||
self.title = title
|
||||
self.utcOffset = utcOffset
|
||||
}
|
||||
|
||||
public static func ==(lhs: Item, rhs: Item) -> Bool {
|
||||
if lhs === rhs {
|
||||
return true
|
||||
}
|
||||
if lhs.id != rhs.id {
|
||||
return false
|
||||
}
|
||||
if lhs.title != rhs.title {
|
||||
return false
|
||||
}
|
||||
if lhs.utcOffset != rhs.utcOffset {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public let items: [Item]
|
||||
public let hashValue: Int32
|
||||
|
||||
public init(items: [Item], hashValue: Int32) {
|
||||
self.items = items
|
||||
self.hashValue = hashValue
|
||||
}
|
||||
|
||||
public static func ==(lhs: TimeZoneList, rhs: TimeZoneList) -> Bool {
|
||||
if lhs === rhs {
|
||||
return true
|
||||
}
|
||||
if lhs.items != rhs.items {
|
||||
return false
|
||||
}
|
||||
if lhs.hashValue != rhs.hashValue {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_cachedTimeZoneList(account: Account) -> Signal<TimeZoneList?, NoError> {
|
||||
let viewKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.timezoneList()]))
|
||||
return account.postbox.combinedView(keys: [viewKey])
|
||||
|> map { views -> TimeZoneList? in
|
||||
guard let view = views.views[viewKey] as? PreferencesView else {
|
||||
return nil
|
||||
}
|
||||
guard let value = view.values[PreferencesKeys.timezoneList()]?.get(TimeZoneList.self) else {
|
||||
return nil
|
||||
}
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_keepCachedTimeZoneListUpdated(account: Account) -> Signal<Never, NoError> {
|
||||
let updateSignal = _internal_cachedTimeZoneList(account: account)
|
||||
|> take(1)
|
||||
|> mapToSignal { list -> Signal<Never, NoError> in
|
||||
return account.network.request(Api.functions.help.getTimezonesList(hash: list?.hashValue ?? 0))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.help.TimezonesList?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Never, NoError> in
|
||||
guard let result else {
|
||||
return .complete()
|
||||
}
|
||||
|
||||
return account.postbox.transaction { transaction in
|
||||
switch result {
|
||||
case let .timezonesList(timezones, hash):
|
||||
var items: [TimeZoneList.Item] = []
|
||||
for item in timezones {
|
||||
switch item {
|
||||
case let .timezone(id, name, utcOffset):
|
||||
items.append(TimeZoneList.Item(id: id, title: name, utcOffset: utcOffset))
|
||||
}
|
||||
}
|
||||
transaction.setPreferencesEntry(key: PreferencesKeys.timezoneList(), value: PreferencesEntry(TimeZoneList(items: items, hashValue: hash)))
|
||||
case .timezonesListNotModified:
|
||||
break
|
||||
}
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
}
|
||||
|
||||
return updateSignal
|
||||
}
|
@ -267,7 +267,9 @@ public final class ChatListHeaderComponent: Component {
|
||||
}
|
||||
|
||||
func update(title: String, theme: PresentationTheme, availableSize: CGSize, transition: Transition) -> CGSize {
|
||||
self.titleView.attributedText = NSAttributedString(string: title, font: Font.regular(17.0), textColor: theme.rootController.navigationBar.accentTextColor)
|
||||
let titleText = NSAttributedString(string: title, font: Font.regular(17.0), textColor: theme.rootController.navigationBar.accentTextColor)
|
||||
let titleTextUpdated = self.titleView.attributedText != titleText
|
||||
self.titleView.attributedText = titleText
|
||||
let titleSize = self.titleView.updateLayout(CGSize(width: 100.0, height: 44.0))
|
||||
|
||||
self.accessibilityLabel = title
|
||||
@ -287,7 +289,12 @@ public final class ChatListHeaderComponent: Component {
|
||||
transition.setPosition(view: self.arrowView, position: arrowFrame.center)
|
||||
transition.setBounds(view: self.arrowView, bounds: CGRect(origin: CGPoint(), size: arrowFrame.size))
|
||||
|
||||
transition.setFrame(view: self.titleView, frame: CGRect(origin: CGPoint(x: iconOffset - 3.0 + arrowSize.width + iconSpacing, y: floor((availableSize.height - titleSize.height) / 2.0)), size: titleSize))
|
||||
let titleFrame = CGRect(origin: CGPoint(x: iconOffset - 3.0 + arrowSize.width + iconSpacing, y: floor((availableSize.height - titleSize.height) / 2.0)), size: titleSize)
|
||||
if titleTextUpdated {
|
||||
self.titleView.frame = titleFrame
|
||||
} else {
|
||||
transition.setFrame(view: self.titleView, frame: titleFrame)
|
||||
}
|
||||
|
||||
return CGSize(width: iconOffset + arrowSize.width + iconSpacing + titleSize.width, height: availableSize.height)
|
||||
}
|
||||
@ -479,7 +486,9 @@ public final class ChatListHeaderComponent: Component {
|
||||
transition.setPosition(view: self.titleScaleContainer, position: CGPoint(x: size.width * 0.5, y: size.height * 0.5))
|
||||
transition.setBounds(view: self.titleScaleContainer, bounds: CGRect(origin: self.titleScaleContainer.bounds.origin, size: size))
|
||||
|
||||
self.titleTextView.attributedText = NSAttributedString(string: content.title, font: Font.semibold(17.0), textColor: theme.rootController.navigationBar.primaryTextColor)
|
||||
let titleText = NSAttributedString(string: content.title, font: Font.semibold(17.0), textColor: theme.rootController.navigationBar.primaryTextColor)
|
||||
let titleTextUpdated = self.titleTextView.attributedText != titleText
|
||||
self.titleTextView.attributedText = titleText
|
||||
|
||||
let buttonSpacing: CGFloat = 8.0
|
||||
|
||||
@ -616,7 +625,11 @@ public final class ChatListHeaderComponent: Component {
|
||||
let titleTextSize = self.titleTextView.updateLayout(CGSize(width: remainingWidth, height: size.height))
|
||||
|
||||
let titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleTextSize.width) / 2.0) + sideContentWidth, y: floor((size.height - titleTextSize.height) / 2.0)), size: titleTextSize)
|
||||
transition.setFrame(view: self.titleTextView, frame: titleFrame)
|
||||
if titleTextUpdated {
|
||||
self.titleTextView.frame = titleFrame
|
||||
} else {
|
||||
transition.setFrame(view: self.titleTextView, frame: titleFrame)
|
||||
}
|
||||
|
||||
if let titleComponent = content.titleComponent {
|
||||
var titleContentTransition = transition
|
||||
|
@ -227,7 +227,12 @@ public final class PlainButtonComponent: Component {
|
||||
}
|
||||
let contentFrame = CGRect(origin: CGPoint(x: component.contentInsets.left + floor((size.width - component.contentInsets.left - component.contentInsets.right - contentSize.width) * 0.5), y: component.contentInsets.top + floor((size.height - component.contentInsets.top - component.contentInsets.bottom - contentSize.height) * 0.5)), size: contentSize)
|
||||
|
||||
contentTransition.setPosition(view: contentView, position: CGPoint(x: contentFrame.minX + contentFrame.width * contentView.layer.anchorPoint.x, y: contentFrame.minY + contentFrame.height * contentView.layer.anchorPoint.y))
|
||||
let contentPosition = CGPoint(x: contentFrame.minX + contentFrame.width * contentView.layer.anchorPoint.x, y: contentFrame.minY + contentFrame.height * contentView.layer.anchorPoint.y)
|
||||
if !component.animateContents && (abs(contentView.center.x - contentPosition.x) <= 2.0 && abs(contentView.center.y - contentPosition.y) <= 2.0){
|
||||
contentView.center = contentPosition
|
||||
} else {
|
||||
contentTransition.setPosition(view: contentView, position: contentPosition)
|
||||
}
|
||||
|
||||
if component.animateContents {
|
||||
contentTransition.setBounds(view: contentView, bounds: CGRect(origin: CGPoint(), size: contentFrame.size))
|
||||
|
@ -238,7 +238,8 @@ final class GreetingMessageListItemComponent: Component {
|
||||
customMessageListData: ChatListItemContent.CustomMessageListData(
|
||||
commandPrefix: nil,
|
||||
searchQuery: nil,
|
||||
messageCount: component.count
|
||||
messageCount: component.count,
|
||||
hideSeparator: true
|
||||
)
|
||||
)),
|
||||
editing: false,
|
||||
|
@ -109,7 +109,7 @@ final class QuickReplyEmptyStateComponent: Component {
|
||||
transition: .immediate,
|
||||
component: AnyComponent(LottieComponent(
|
||||
content: LottieComponent.AppBundleContent(name: "WriteEmoji"),
|
||||
loop: false
|
||||
loop: true
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 120.0, height: 120.0)
|
||||
|
@ -250,7 +250,8 @@ final class QuickReplySetupScreenComponent: Component {
|
||||
customMessageListData: ChatListItemContent.CustomMessageListData(
|
||||
commandPrefix: "/\(item.shortcut)",
|
||||
searchQuery: nil,
|
||||
messageCount: nil
|
||||
messageCount: item.totalCount,
|
||||
hideSeparator: false
|
||||
)
|
||||
)),
|
||||
editing: isEditing,
|
||||
@ -744,13 +745,14 @@ final class QuickReplySetupScreenComponent: Component {
|
||||
tabsNodeIsSearch: false,
|
||||
accessoryPanelContainer: nil,
|
||||
accessoryPanelContainerHeight: 0.0,
|
||||
activateSearch: { [weak self] searchContentNode in
|
||||
activateSearch: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
self.isSearchDisplayControllerActive = true
|
||||
self.state?.updated(transition: .spring(duration: 0.4))
|
||||
let _ = self
|
||||
//self.isSearchDisplayControllerActive = true
|
||||
//self.state?.updated(transition: .spring(duration: 0.4))
|
||||
},
|
||||
openStatusSetup: { _ in
|
||||
},
|
||||
|
@ -82,11 +82,14 @@ final class BusinessHoursSetupScreenComponent: Component {
|
||||
}
|
||||
|
||||
var timezoneId: String
|
||||
var days: [Day]
|
||||
private(set) var days: [Day]
|
||||
private(set) var intersectingDays = Set<Int>()
|
||||
|
||||
init(timezoneId: String, days: [Day]) {
|
||||
self.timezoneId = timezoneId
|
||||
self.days = days
|
||||
|
||||
self.validate()
|
||||
}
|
||||
|
||||
init(businessHours: TelegramBusinessHours) {
|
||||
@ -107,6 +110,19 @@ final class BusinessHoursSetupScreenComponent: Component {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
self.validate()
|
||||
}
|
||||
|
||||
mutating func validate() {
|
||||
self.intersectingDays.removeAll()
|
||||
|
||||
|
||||
}
|
||||
|
||||
mutating func update(days: [Day]) {
|
||||
self.days = days
|
||||
self.validate()
|
||||
}
|
||||
|
||||
func asBusinessHours() throws -> TelegramBusinessHours {
|
||||
@ -165,6 +181,10 @@ final class BusinessHoursSetupScreenComponent: Component {
|
||||
private var showHours: Bool = false
|
||||
private var daysState = DaysState(timezoneId: "", days: [])
|
||||
|
||||
private var timeZoneList: TimeZoneList?
|
||||
private var timezonesDisposable: Disposable?
|
||||
private var keepTimezonesUpdatedDisposable: Disposable?
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.scrollView = ScrollView()
|
||||
self.scrollView.showsVerticalScrollIndicator = true
|
||||
@ -191,6 +211,8 @@ final class BusinessHoursSetupScreenComponent: Component {
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.timezonesDisposable?.dispose()
|
||||
self.keepTimezonesUpdatedDisposable?.dispose()
|
||||
}
|
||||
|
||||
func scrollToTop() {
|
||||
@ -210,6 +232,21 @@ final class BusinessHoursSetupScreenComponent: Component {
|
||||
} catch let error {
|
||||
let _ = error
|
||||
//TODO:localize
|
||||
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||
//TODO:localize
|
||||
self.environment?.controller()?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: "Business hours are intersecting. Reset?", actions: [
|
||||
TextAlertAction(type: .genericAction, title: "Cancel", action: {
|
||||
}),
|
||||
TextAlertAction(type: .defaultAction, title: "Reset", action: { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
let _ = self
|
||||
complete()
|
||||
})
|
||||
]), in: .window(.root))
|
||||
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
@ -271,10 +308,20 @@ final class BusinessHoursSetupScreenComponent: Component {
|
||||
} else {
|
||||
self.showHours = false
|
||||
self.daysState.timezoneId = TimeZone.current.identifier
|
||||
self.daysState.days = (0 ..< 7).map { _ in
|
||||
self.daysState.update(days: (0 ..< 7).map { _ in
|
||||
return Day(ranges: [])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
self.timezonesDisposable = (component.context.engine.accountData.cachedTimeZoneList()
|
||||
|> deliverOnMainQueue).start(next: { [weak self] timeZoneList in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.timeZoneList = timeZoneList
|
||||
self.state?.updated(transition: .immediate)
|
||||
})
|
||||
self.keepTimezonesUpdatedDisposable = component.context.engine.accountData.keepCachedTimeZoneListUpdated().startStrict()
|
||||
}
|
||||
|
||||
let environment = environment[EnvironmentType.self].value
|
||||
@ -508,11 +555,13 @@ final class BusinessHoursSetupScreenComponent: Component {
|
||||
return
|
||||
}
|
||||
if dayIndex < self.daysState.days.count {
|
||||
if self.daysState.days[dayIndex].ranges == nil {
|
||||
self.daysState.days[dayIndex].ranges = []
|
||||
var days = self.daysState.days
|
||||
if days[dayIndex].ranges == nil {
|
||||
days[dayIndex].ranges = []
|
||||
} else {
|
||||
self.daysState.days[dayIndex].ranges = nil
|
||||
days[dayIndex].ranges = nil
|
||||
}
|
||||
self.daysState.update(days: days)
|
||||
}
|
||||
self.state?.updated(transition: .immediate)
|
||||
})),
|
||||
@ -529,7 +578,9 @@ final class BusinessHoursSetupScreenComponent: Component {
|
||||
return
|
||||
}
|
||||
if self.daysState.days[dayIndex] != day {
|
||||
self.daysState.days[dayIndex] = day
|
||||
var days = self.daysState.days
|
||||
days[dayIndex] = day
|
||||
self.daysState.update(days: days)
|
||||
self.state?.updated(transition: .immediate)
|
||||
}
|
||||
}
|
||||
@ -569,6 +620,18 @@ final class BusinessHoursSetupScreenComponent: Component {
|
||||
daysContentHeight += daysSectionSize.height
|
||||
daysContentHeight += sectionSpacing
|
||||
|
||||
let timezoneValueText: String
|
||||
if let timeZoneList = self.timeZoneList {
|
||||
if let item = timeZoneList.items.first(where: { $0.id == self.daysState.timezoneId }) {
|
||||
timezoneValueText = item.title
|
||||
} else {
|
||||
timezoneValueText = TimeZone(identifier: self.daysState.timezoneId)?.localizedName(for: .shortStandard, locale: Locale.current) ?? " "
|
||||
}
|
||||
} else {
|
||||
//TODO:localize
|
||||
timezoneValueText = "Loading..."
|
||||
}
|
||||
|
||||
let timezoneSectionSize = self.timezoneSection.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(ListSectionComponent(
|
||||
@ -588,7 +651,7 @@ final class BusinessHoursSetupScreenComponent: Component {
|
||||
)),
|
||||
icon: ListActionItemComponent.Icon(component: AnyComponentWithIdentity(id: 0, component: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(
|
||||
string: TimeZone(identifier: self.daysState.timezoneId)?.localizedName(for: .shortStandard, locale: Locale.current) ?? self.daysState.timezoneId,
|
||||
string: timezoneValueText,
|
||||
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
|
||||
textColor: environment.theme.list.itemSecondaryTextColor
|
||||
)),
|
||||
|
@ -58,8 +58,7 @@ private func preparedLanguageListSearchContainerTransition(presentationData: Pre
|
||||
}
|
||||
|
||||
private final class TimezoneListSearchContainerNode: SearchDisplayControllerContentNode {
|
||||
private let timezoneData: TimezoneData
|
||||
|
||||
private let timeZoneList: TimeZoneList
|
||||
private let dimNode: ASDisplayNode
|
||||
private let listNode: ListView
|
||||
|
||||
@ -78,8 +77,8 @@ private final class TimezoneListSearchContainerNode: SearchDisplayControllerCont
|
||||
return true
|
||||
}
|
||||
|
||||
init(context: AccountContext, timezoneData: TimezoneData, action: @escaping (String) -> Void) {
|
||||
self.timezoneData = timezoneData
|
||||
init(context: AccountContext, timeZoneList: TimeZoneList, action: @escaping (String) -> Void) {
|
||||
self.timeZoneList = timeZoneList
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.presentationData = presentationData
|
||||
@ -102,16 +101,18 @@ private final class TimezoneListSearchContainerNode: SearchDisplayControllerCont
|
||||
self.addSubnode(self.dimNode)
|
||||
self.addSubnode(self.listNode)
|
||||
|
||||
let querySplitCharacterSet: CharacterSet = CharacterSet(charactersIn: " /.+")
|
||||
|
||||
let foundItems = self.searchQuery.get()
|
||||
|> mapToSignal { query -> Signal<[TimezoneData.Item]?, NoError> in
|
||||
|> mapToSignal { query -> Signal<[TimeZoneList.Item]?, NoError> in
|
||||
if let query, !query.isEmpty {
|
||||
let query = query.lowercased()
|
||||
|
||||
return .single(timezoneData.items.filter { item in
|
||||
return .single(timeZoneList.items.filter { item in
|
||||
if item.id.lowercased().hasPrefix(query) {
|
||||
return true
|
||||
}
|
||||
if item.title.lowercased().split(separator: " ").contains(where: { $0.hasPrefix(query) }) {
|
||||
if item.title.lowercased().components(separatedBy: querySplitCharacterSet).contains(where: { $0.hasPrefix(query) }) {
|
||||
return true
|
||||
}
|
||||
|
||||
@ -132,7 +133,7 @@ private final class TimezoneListSearchContainerNode: SearchDisplayControllerCont
|
||||
for item in items {
|
||||
entries.append(TimezoneListEntry(
|
||||
id: item.id,
|
||||
offset: item.offset,
|
||||
offset: Int(item.utcOffset),
|
||||
title: item.title
|
||||
))
|
||||
}
|
||||
@ -301,7 +302,7 @@ final class TimezoneSelectionScreenNode: ViewControllerTracingNode {
|
||||
private let requestDeactivateSearch: () -> Void
|
||||
private let present: (ViewController, Any?) -> Void
|
||||
private let push: (ViewController) -> Void
|
||||
private let timezoneData: TimezoneData
|
||||
private var timeZoneList: TimeZoneList?
|
||||
|
||||
private var didSetReady = false
|
||||
let _ready = ValuePromise<Bool>()
|
||||
@ -331,28 +332,32 @@ final class TimezoneSelectionScreenNode: ViewControllerTracingNode {
|
||||
return presentationData.strings.VoiceOver_ScrollStatus(row, count).string
|
||||
}
|
||||
|
||||
let timezoneData = TimezoneData()
|
||||
self.timezoneData = timezoneData
|
||||
|
||||
super.init()
|
||||
|
||||
self.backgroundColor = presentationData.theme.list.plainBackgroundColor
|
||||
self.addSubnode(self.listNode)
|
||||
|
||||
let previousEntriesHolder = Atomic<([TimezoneListEntry], PresentationTheme, PresentationStrings)?>(value: nil)
|
||||
self.listDisposable = (self.presentationDataValue.get()
|
||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
||||
self.listDisposable = (combineLatest(queue: .mainQueue(),
|
||||
self.presentationDataValue.get(),
|
||||
context.engine.accountData.cachedTimeZoneList()
|
||||
)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData, timeZoneList in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
strongSelf.timeZoneList = timeZoneList
|
||||
|
||||
var entries: [TimezoneListEntry] = []
|
||||
for item in timezoneData.items {
|
||||
entries.append(TimezoneListEntry(
|
||||
id: item.id,
|
||||
offset: item.offset,
|
||||
title: item.title
|
||||
))
|
||||
if let timeZoneList {
|
||||
for item in timeZoneList.items {
|
||||
entries.append(TimezoneListEntry(
|
||||
id: item.id,
|
||||
offset: Int(item.utcOffset),
|
||||
title: item.title
|
||||
))
|
||||
}
|
||||
}
|
||||
entries.sort()
|
||||
|
||||
@ -447,8 +452,11 @@ final class TimezoneSelectionScreenNode: ViewControllerTracingNode {
|
||||
guard let (containerLayout, navigationBarHeight) = self.containerLayout, self.searchDisplayController == nil else {
|
||||
return
|
||||
}
|
||||
guard let timeZoneList = self.timeZoneList else {
|
||||
return
|
||||
}
|
||||
|
||||
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: TimezoneListSearchContainerNode(context: self.context, timezoneData: self.timezoneData, action: self.action), inline: true, cancel: { [weak self] in
|
||||
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: TimezoneListSearchContainerNode(context: self.context, timeZoneList: timeZoneList, action: self.action), inline: true, cancel: { [weak self] in
|
||||
self?.requestDeactivateSearch()
|
||||
})
|
||||
|
||||
|
@ -104,6 +104,9 @@ extension ChatControllerImpl {
|
||||
if case let .peer(peerId) = self.chatLocation, messageLocation.peerId == peerId, !isPinnedMessages, !isScheduledMessages {
|
||||
forceInCurrentChat = true
|
||||
}
|
||||
if case .customChatContents = self.chatLocation {
|
||||
forceInCurrentChat = true
|
||||
}
|
||||
|
||||
if isPinnedMessages, let messageId = messageLocation.messageId {
|
||||
let _ = (combineLatest(
|
||||
@ -205,6 +208,7 @@ extension ChatControllerImpl {
|
||||
if case let .id(_, params) = messageLocation {
|
||||
quote = params.quote.flatMap { quote in (string: quote.string, offset: quote.offset) }
|
||||
}
|
||||
|
||||
self.chatDisplayNode.historyNode.scrollToMessage(from: scrollFromIndex, to: message.index, animated: animated, quote: quote, scrollPosition: scrollPosition)
|
||||
|
||||
if delayCompletion {
|
||||
|
@ -1883,7 +1883,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
overlayNavigationBar.updateLayout(size: barFrame.size, transition: transition)
|
||||
}
|
||||
|
||||
var listInsets = UIEdgeInsets(top: containerInsets.bottom + contentBottomInset, left: containerInsets.right, bottom: containerInsets.top, right: containerInsets.left)
|
||||
var listInsets = UIEdgeInsets(top: containerInsets.bottom + contentBottomInset, left: containerInsets.right, bottom: containerInsets.top + 6.0, right: containerInsets.left)
|
||||
let listScrollIndicatorInsets = UIEdgeInsets(top: containerInsets.bottom + inputPanelsHeight, left: containerInsets.right, bottom: containerInsets.top, right: containerInsets.left)
|
||||
|
||||
var childContentInsets: UIEdgeInsets = containerInsets
|
||||
|
@ -546,12 +546,12 @@ func chatHistoryEntriesForView(
|
||||
let message = Message(
|
||||
stableId: UInt32.max - 1001 - UInt32(i),
|
||||
stableVersion: 0,
|
||||
id: MessageId(peerId: context.account.peerId, namespace: Namespaces.Message.Local, id: 123 - Int32(i)),
|
||||
id: MessageId(peerId: context.account.peerId, namespace: Namespaces.Message.Local, id: Int32.max - 100 - Int32(i)),
|
||||
globallyUniqueId: nil,
|
||||
groupingKey: nil,
|
||||
groupInfo: nil,
|
||||
threadId: nil,
|
||||
timestamp: Int32(i),
|
||||
timestamp: -Int32(i),
|
||||
flags: [.Incoming],
|
||||
tags: [],
|
||||
globalTags: [],
|
||||
|
@ -1283,10 +1283,15 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
}
|
||||
return true
|
||||
})
|
||||
|> mapToSignal { _ in
|
||||
|> mapToSignal { location, _ -> Signal<((MessageHistoryView, ViewUpdateType), ChatHistoryLocationInput?), NoError> in
|
||||
return historyView
|
||||
|> map { historyView in
|
||||
return (historyView, location)
|
||||
}
|
||||
}
|
||||
|> map { view, update in
|
||||
|> map { viewAndUpdate, location in
|
||||
let (view, update) = viewAndUpdate
|
||||
|
||||
let version = currentViewVersion.modify({ value in
|
||||
if let value = value {
|
||||
return value + 1
|
||||
@ -1295,11 +1300,21 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
}
|
||||
})!
|
||||
|
||||
var scrollPositionValue: ChatHistoryViewScrollPosition?
|
||||
if let location {
|
||||
switch location.content {
|
||||
case let .Scroll(subject, _, _, scrollPosition, animated, highlight):
|
||||
scrollPositionValue = .index(subject: subject, position: scrollPosition, directionHint: .Up, animated: animated, highlight: highlight, displayLink: false)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
ChatHistoryViewUpdate.HistoryView(
|
||||
view: view,
|
||||
type: .Generic(type: update),
|
||||
scrollPosition: nil,
|
||||
scrollPosition: scrollPositionValue,
|
||||
flashIndicators: false,
|
||||
originalScrollPosition: nil,
|
||||
initialData: ChatHistoryCombinedInitialData(
|
||||
@ -1309,10 +1324,10 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
cachedDataMessages: nil,
|
||||
readStateData: nil
|
||||
),
|
||||
id: 0
|
||||
id: location?.id ?? 0
|
||||
),
|
||||
version,
|
||||
nil,
|
||||
location,
|
||||
nil
|
||||
)
|
||||
}
|
||||
|
@ -76,12 +76,21 @@ func accessoryPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceS
|
||||
replyPanelNode.interfaceInteraction = interfaceInteraction
|
||||
replyPanelNode.updateThemeAndStrings(theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings)
|
||||
return replyPanelNode
|
||||
} else if let peerId = chatPresentationInterfaceState.chatLocation.peerId {
|
||||
let panelNode = ReplyAccessoryPanelNode(context: context, chatPeerId: peerId, messageId: replyMessageSubject.messageId, quote: replyMessageSubject.quote, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, nameDisplayOrder: chatPresentationInterfaceState.nameDisplayOrder, dateTimeFormat: chatPresentationInterfaceState.dateTimeFormat, animationCache: chatControllerInteraction?.presentationContext.animationCache, animationRenderer: chatControllerInteraction?.presentationContext.animationRenderer)
|
||||
panelNode.interfaceInteraction = interfaceInteraction
|
||||
return panelNode
|
||||
} else {
|
||||
return nil
|
||||
var chatPeerId: EnginePeer.Id?
|
||||
if let peerId = chatPresentationInterfaceState.chatLocation.peerId {
|
||||
chatPeerId = peerId
|
||||
} else if case .customChatContents = chatPresentationInterfaceState.chatLocation {
|
||||
chatPeerId = context.account.peerId
|
||||
}
|
||||
|
||||
if let chatPeerId {
|
||||
let panelNode = ReplyAccessoryPanelNode(context: context, chatPeerId: chatPeerId, messageId: replyMessageSubject.messageId, quote: replyMessageSubject.quote, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, nameDisplayOrder: chatPresentationInterfaceState.nameDisplayOrder, dateTimeFormat: chatPresentationInterfaceState.dateTimeFormat, animationCache: chatControllerInteraction?.presentationContext.animationCache, animationRenderer: chatControllerInteraction?.presentationContext.animationRenderer)
|
||||
panelNode.interfaceInteraction = interfaceInteraction
|
||||
return panelNode
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
|
@ -271,6 +271,10 @@ private func canViewReadStats(message: Message, participantCount: Int?, isMessag
|
||||
}
|
||||
|
||||
func canReplyInChat(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, accountPeerId: PeerId) -> Bool {
|
||||
if case .customChatContents = chatPresentationInterfaceState.chatLocation {
|
||||
return true
|
||||
}
|
||||
|
||||
guard let peer = chatPresentationInterfaceState.renderedPeer?.peer else {
|
||||
return false
|
||||
}
|
||||
@ -338,7 +342,7 @@ func canReplyInChat(_ chatPresentationInterfaceState: ChatPresentationInterfaceS
|
||||
case .replyThread:
|
||||
canReply = true
|
||||
case .customChatContents:
|
||||
canReply = false
|
||||
canReply = true
|
||||
}
|
||||
return canReply
|
||||
}
|
||||
|
@ -220,7 +220,8 @@ private struct CommandChatInputContextPanelEntry: Comparable, Identifiable {
|
||||
customMessageListData: ChatListItemContent.CustomMessageListData(
|
||||
commandPrefix: "/\(shortcut.shortcut)",
|
||||
searchQuery: command.searchQuery.flatMap { "/\($0)"},
|
||||
messageCount: nil
|
||||
messageCount: shortcut.totalCount,
|
||||
hideSeparator: false
|
||||
)
|
||||
)),
|
||||
editing: false,
|
||||
|
Loading…
x
Reference in New Issue
Block a user