mirror of
https://github.com/ichmagmaus111/ghostgram.git
synced 2026-06-08 19:13:56 +02:00
chore: migrate to new version + fixed several critical bugs
- Migrated project to latest Telegram iOS base (v12.3.2+) - Fixed circular dependency between GhostModeManager and MiscSettingsManager - Fixed multiple Bazel build configuration errors (select() default conditions) - Fixed duplicate type definitions in PeerInfoScreen - Fixed swiftmodule directory resolution in build scripts - Added Ghostgram Settings tab in main Settings menu with all 5 features - Cleared sensitive credentials from config.json (template-only now) - Excluded bazel-cache from version control
This commit is contained in:
@@ -172,7 +172,7 @@ class ChatListArchiveInfoItemNode: ListViewItemNode, ASScrollViewDelegate {
|
||||
self.infoPageNodes = (0 ..< 3).map({ _ in InfoPageNode() })
|
||||
self.pageControlNode.pagesCount = self.infoPageNodes.count
|
||||
|
||||
super.init(layerBacked: false, dynamicBounce: false)
|
||||
super.init(layerBacked: false)
|
||||
|
||||
self.addSubnode(self.scrollNode)
|
||||
self.infoPageNodes.forEach(self.scrollNode.addSubnode)
|
||||
|
||||
@@ -55,7 +55,7 @@ class ChatListEmptyHeaderItemNode: ListViewItemNode {
|
||||
private var item: ChatListEmptyHeaderItem?
|
||||
|
||||
required init() {
|
||||
super.init(layerBacked: false, dynamicBounce: false)
|
||||
super.init(layerBacked: false)
|
||||
}
|
||||
|
||||
override func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) {
|
||||
|
||||
@@ -92,7 +92,7 @@ class ChatListEmptyInfoItemNode: ListViewItemNode {
|
||||
self.animationNode = DefaultAnimatedStickerNodeImpl()
|
||||
self.textNode = TextNode()
|
||||
|
||||
super.init(layerBacked: false, dynamicBounce: false)
|
||||
super.init(layerBacked: false)
|
||||
|
||||
self.addSubnode(self.animationNode)
|
||||
self.addSubnode(self.textNode)
|
||||
@@ -207,7 +207,7 @@ class ChatListSectionHeaderNode: ListViewItemNode {
|
||||
private var headerNode: ListSectionHeaderNode?
|
||||
|
||||
required init() {
|
||||
super.init(layerBacked: false, dynamicBounce: false)
|
||||
super.init(layerBacked: false)
|
||||
|
||||
self.zPosition = 1.0
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ class ChatListHoleItemNode: ListViewItemNode {
|
||||
var relativePosition: (first: Bool, last: Bool) = (false, false)
|
||||
|
||||
required init() {
|
||||
super.init(layerBacked: false, dynamicBounce: false)
|
||||
super.init(layerBacked: false)
|
||||
}
|
||||
|
||||
override func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) {
|
||||
@@ -153,7 +153,7 @@ class ChatListSearchEmptyFooterItemNode: ListViewItemNode {
|
||||
self.searchAllMessagesTitle = TextNode()
|
||||
self.searchAllMessagesTitle.isUserInteractionEnabled = false
|
||||
|
||||
super.init(layerBacked: false, dynamicBounce: false)
|
||||
super.init(layerBacked: false)
|
||||
|
||||
self.addSubnode(self.contentNode)
|
||||
self.contentNode.addSubnode(self.titleNode)
|
||||
|
||||
@@ -15,7 +15,6 @@ import PeerOnlineMarkerNode
|
||||
import LocalizedPeerData
|
||||
import PeerPresenceStatusManager
|
||||
import PhotoResources
|
||||
import ChatListSearchItemNode
|
||||
import ContextUI
|
||||
import ChatInterfaceState
|
||||
import TextFormat
|
||||
@@ -219,6 +218,7 @@ public enum ChatListItemContent {
|
||||
public var message: EngineMessage?
|
||||
public var unreadCount: Int
|
||||
public var hiddenByDefault: Bool
|
||||
public var appearsPinned: Bool
|
||||
public var storyState: StoryState?
|
||||
|
||||
public init(
|
||||
@@ -227,6 +227,7 @@ public enum ChatListItemContent {
|
||||
message: EngineMessage?,
|
||||
unreadCount: Int,
|
||||
hiddenByDefault: Bool,
|
||||
appearsPinned: Bool,
|
||||
storyState: StoryState?
|
||||
) {
|
||||
self.groupId = groupId
|
||||
@@ -234,6 +235,7 @@ public enum ChatListItemContent {
|
||||
self.message = message
|
||||
self.unreadCount = unreadCount
|
||||
self.hiddenByDefault = hiddenByDefault
|
||||
self.appearsPinned = appearsPinned
|
||||
self.storyState = storyState
|
||||
}
|
||||
}
|
||||
@@ -454,7 +456,7 @@ private final class ChatListItemTagListComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
public class ChatListItem: ListViewItem, ChatListSearchItemNeighbour {
|
||||
public class ChatListItem: ListViewItem {
|
||||
public enum EnabledContextActions {
|
||||
public struct Actions: OptionSet {
|
||||
public var rawValue: Int32
|
||||
@@ -1472,7 +1474,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
} else {
|
||||
result += item.presentationData.strings.VoiceOver_ChatList_OutgoingMessage
|
||||
}
|
||||
let (_, initialHideAuthor, messageText, _, _) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, contentSettings: item.context.currentContentSettings.with { $0 }, messages: messages, chatPeer: peer, accountPeerId: item.context.account.peerId, isPeerGroup: false)
|
||||
let (_, initialHideAuthor, messageText, _, _, _) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, contentSettings: item.context.currentContentSettings.with { $0 }, messages: messages, chatPeer: peer, accountPeerId: item.context.account.peerId, isPeerGroup: false)
|
||||
if message.flags.contains(.Incoming), !initialHideAuthor, let author = message.author, case .user = author {
|
||||
result += "\n\(item.presentationData.strings.VoiceOver_ChatList_MessageFrom(author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)).string)"
|
||||
}
|
||||
@@ -1506,7 +1508,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
} else {
|
||||
result += item.presentationData.strings.VoiceOver_ChatList_OutgoingMessage
|
||||
}
|
||||
let (_, initialHideAuthor, messageText, _, _) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, contentSettings: item.context.currentContentSettings.with { $0 }, messages: peerData.messages, chatPeer: peerData.peer, accountPeerId: item.context.account.peerId, isPeerGroup: false)
|
||||
let (_, initialHideAuthor, messageText, _, _, _) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, contentSettings: item.context.currentContentSettings.with { $0 }, messages: peerData.messages, chatPeer: peerData.peer, accountPeerId: item.context.account.peerId, isPeerGroup: false)
|
||||
if message.flags.contains(.Incoming), !initialHideAuthor, let author = message.author, case .user = author {
|
||||
result += "\n\(item.presentationData.strings.VoiceOver_ChatList_MessageFrom(author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)).string)"
|
||||
}
|
||||
@@ -1656,7 +1658,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
self.separatorNode = ASDisplayNode()
|
||||
self.separatorNode.isLayerBacked = true
|
||||
|
||||
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
|
||||
super.init(layerBacked: false, rotated: false, seeThrough: false)
|
||||
|
||||
self.isAccessibilityElement = true
|
||||
|
||||
@@ -2452,7 +2454,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
let leftInset: CGFloat = params.leftInset + avatarLeftInset
|
||||
|
||||
enum ContentData {
|
||||
case chat(itemPeer: EngineRenderedPeer, threadInfo: ChatListItemContent.ThreadInfo?, peer: EnginePeer?, hideAuthor: Bool, messageText: String, spoilers: [NSRange]?, customEmojiRanges: [(NSRange, ChatTextInputTextCustomEmojiAttribute)]?)
|
||||
case chat(itemPeer: EngineRenderedPeer, threadInfo: ChatListItemContent.ThreadInfo?, peer: EnginePeer?, hideAuthor: Bool, messageText: String, messageEntities: [MessageTextEntity], spoilers: [NSRange]?, customEmojiRanges: [(NSRange, ChatTextInputTextCustomEmojiAttribute)]?)
|
||||
case group(peers: [EngineChatList.GroupItem.Item])
|
||||
}
|
||||
|
||||
@@ -2461,7 +2463,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
var hideAuthor = false
|
||||
switch contentPeer {
|
||||
case let .chat(itemPeer):
|
||||
var (peer, initialHideAuthor, messageText, spoilers, customEmojiRanges) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, contentSettings: item.context.currentContentSettings.with { $0 }, messages: messages, chatPeer: itemPeer, accountPeerId: item.context.account.peerId, enableMediaEmoji: !enableChatListPhotos, isPeerGroup: isPeerGroup)
|
||||
var (peer, initialHideAuthor, messageText, messageEntities, spoilers, customEmojiRanges) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, contentSettings: item.context.currentContentSettings.with { $0 }, messages: messages, chatPeer: itemPeer, accountPeerId: item.context.account.peerId, enableMediaEmoji: !enableChatListPhotos, isPeerGroup: isPeerGroup)
|
||||
|
||||
if case let .psa(_, maybePsaText) = promoInfo, let psaText = maybePsaText {
|
||||
initialHideAuthor = true
|
||||
@@ -2489,7 +2491,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
break
|
||||
}
|
||||
|
||||
contentData = .chat(itemPeer: itemPeer, threadInfo: threadInfo, peer: peer, hideAuthor: hideAuthor, messageText: messageText, spoilers: spoilers, customEmojiRanges: customEmojiRanges)
|
||||
contentData = .chat(itemPeer: itemPeer, threadInfo: threadInfo, peer: peer, hideAuthor: hideAuthor, messageText: messageText, messageEntities: messageEntities, spoilers: spoilers, customEmojiRanges: customEmojiRanges)
|
||||
hideAuthor = initialHideAuthor
|
||||
case let .group(groupPeers):
|
||||
contentData = .group(peers: groupPeers)
|
||||
@@ -2508,7 +2510,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
forumTopicData = nil
|
||||
topForumTopicItems = []
|
||||
|
||||
if case let .chat(itemPeer, _, _, _, _, _, _) = contentData {
|
||||
if case let .chat(itemPeer, _, _, _, _, _, _, _) = contentData {
|
||||
if let messagePeer = itemPeer.chatMainPeer {
|
||||
switch messagePeer {
|
||||
case let .channel(channel):
|
||||
@@ -2556,7 +2558,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
var ignoreForwardedIcon = false
|
||||
|
||||
switch contentData {
|
||||
case let .chat(itemPeer, _, _, _, text, spoilers, customEmojiRanges):
|
||||
case let .chat(itemPeer, _, _, _, text, entities, spoilers, customEmojiRanges):
|
||||
var isUser = false
|
||||
if case .user = itemPeer.chatMainPeer {
|
||||
isUser = true
|
||||
@@ -2639,7 +2641,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
chatListText = (text, messageText)
|
||||
}
|
||||
|
||||
|
||||
if inlineAuthorPrefix == nil, let mediaDraftContentType {
|
||||
hasDraft = true
|
||||
authorAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_Draft, font: textFont, textColor: theme.messageDraftTextColor)
|
||||
@@ -2671,8 +2673,8 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
if let peerText = peerText {
|
||||
authorAttributedString = NSAttributedString(string: peerText, font: textFont, textColor: theme.authorNameColor)
|
||||
}
|
||||
|
||||
var entities = (message._asMessage().textEntitiesAttribute?.entities ?? []).filter { entity in
|
||||
|
||||
var entities = entities.filter { entity in
|
||||
switch entity.type {
|
||||
case .Spoiler, .CustomEmoji:
|
||||
return true
|
||||
@@ -2690,14 +2692,14 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
} else {
|
||||
regex = loginCodeRegex
|
||||
}
|
||||
if let cached = currentCustomTextEntities, cached.matches(text: message.text) {
|
||||
if let cached = currentCustomTextEntities, cached.matches(text: messageText) {
|
||||
customTextEntities = cached
|
||||
} else if let matches = regex?.matches(in: message.text, options: [], range: NSMakeRange(0, (message.text as NSString).length)) {
|
||||
} else if let matches = regex?.matches(in: messageText, options: [], range: NSMakeRange(0, (messageText as NSString).length)) {
|
||||
var entities: [MessageTextEntity] = []
|
||||
if let first = matches.first {
|
||||
entities.append(MessageTextEntity(range: first.range.location ..< first.range.location + first.range.length, type: .Spoiler))
|
||||
}
|
||||
customTextEntities = CachedCustomTextEntities(text: message.text, textEntities: entities)
|
||||
customTextEntities = CachedCustomTextEntities(text: messageText, textEntities: entities)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2706,14 +2708,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
|
||||
let messageString: NSAttributedString
|
||||
if !message.text.isEmpty && entities.count > 0 {
|
||||
var messageText = message.text
|
||||
var entities = entities
|
||||
if !"".isEmpty, let translation = message.attributes.first(where: { $0 is TranslationMessageAttribute }) as? TranslationMessageAttribute, !translation.text.isEmpty {
|
||||
messageText = translation.text
|
||||
entities = translation.entities
|
||||
}
|
||||
|
||||
if !messageText.isEmpty && entities.count > 0 {
|
||||
messageString = foldLineBreaks(stringWithAppliedEntities(messageText, entities: entities, baseColor: theme.messageTextColor, linkColor: theme.messageTextColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: italicTextFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false, message: message._asMessage()))
|
||||
} else if spoilers != nil || customEmojiRanges != nil {
|
||||
let mutableString = NSMutableAttributedString(string: messageText, font: textFont, textColor: theme.messageTextColor)
|
||||
@@ -3100,7 +3095,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
|
||||
switch contentData {
|
||||
case let .chat(itemPeer, threadInfo, _, _, _, _, _):
|
||||
case let .chat(itemPeer, threadInfo, _, _, _, _, _, _):
|
||||
if case let .peer(peerData) = item.content, let customMessageListData = peerData.customMessageListData {
|
||||
if customMessageListData.commandPrefix != nil {
|
||||
titleAttributedString = nil
|
||||
@@ -3854,6 +3849,9 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
transition = .immediate
|
||||
}
|
||||
|
||||
transition.updateAlpha(node: strongSelf, alpha: item.hiddenOffset ? 0.0 : 1.0)
|
||||
ComponentTransition(transition).setBlur(layer: strongSelf.layer, radius: item.hiddenOffset ? 8.0 : 0.0)
|
||||
|
||||
let contextContainerFrame = CGRect(origin: CGPoint(), size: CGSize(width: layout.contentSize.width, height: itemHeight))
|
||||
// strongSelf.contextContainer.position = contextContainerFrame.center
|
||||
transition.updatePosition(node: strongSelf.contextContainer, position: contextContainerFrame.center)
|
||||
@@ -5031,7 +5029,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
if case let .groupReference(groupReferenceData) = item.content, groupReferenceData.hiddenByDefault {
|
||||
separatorInset = 0.0
|
||||
} else if (!nextIsPinned && isPinned) || last {
|
||||
separatorInset = 0.0
|
||||
separatorInset = 0.0
|
||||
} else {
|
||||
separatorInset = editingOffset + leftInset + rawContentRect.origin.x
|
||||
}
|
||||
@@ -5057,8 +5055,8 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
highlightedBackgroundColor = theme.itemHighlightedBackgroundColor
|
||||
} else if isPinned {
|
||||
if case let .groupReference(groupReferenceData) = item.content, groupReferenceData.hiddenByDefault {
|
||||
backgroundColor = theme.itemBackgroundColor
|
||||
highlightedBackgroundColor = theme.itemHighlightedBackgroundColor
|
||||
backgroundColor = groupReferenceData.appearsPinned ? theme.pinnedItemBackgroundColor : theme.itemBackgroundColor
|
||||
highlightedBackgroundColor = groupReferenceData.appearsPinned ? theme.pinnedItemHighlightedBackgroundColor : theme.itemHighlightedBackgroundColor
|
||||
} else {
|
||||
backgroundColor = theme.pinnedItemBackgroundColor
|
||||
highlightedBackgroundColor = theme.pinnedItemHighlightedBackgroundColor
|
||||
|
||||
@@ -77,20 +77,21 @@ private func paidContentGroupType(paidContent: TelegramMediaPaidContent) -> Mess
|
||||
return currentType
|
||||
}
|
||||
|
||||
public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, contentSettings: ContentSettings, messages: [EngineMessage], chatPeer: EngineRenderedPeer, accountPeerId: EnginePeer.Id, enableMediaEmoji: Bool = true, isPeerGroup: Bool = false) -> (peer: EnginePeer?, hideAuthor: Bool, messageText: String, spoilers: [NSRange]?, customEmojiRanges: [(NSRange, ChatTextInputTextCustomEmojiAttribute)]?) {
|
||||
public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, contentSettings: ContentSettings, messages: [EngineMessage], chatPeer: EngineRenderedPeer, accountPeerId: EnginePeer.Id, enableMediaEmoji: Bool = true, isPeerGroup: Bool = false) -> (peer: EnginePeer?, hideAuthor: Bool, messageText: String, messageEntities: [MessageTextEntity], spoilers: [NSRange]?, customEmojiRanges: [(NSRange, ChatTextInputTextCustomEmojiAttribute)]?) {
|
||||
let peer: EnginePeer?
|
||||
|
||||
let message = messages.last
|
||||
|
||||
if let restrictionReason = message?._asMessage().restrictionReason(platform: "ios", contentSettings: contentSettings) {
|
||||
return (nil, false, restrictionReason, nil, nil)
|
||||
return (nil, false, restrictionReason, [], nil, nil)
|
||||
}
|
||||
if let restrictionReason = chatPeer.chatMainPeer?.restrictionText(platform: "ios", contentSettings: contentSettings) {
|
||||
return (nil, false, restrictionReason, nil, nil)
|
||||
return (nil, false, restrictionReason, [], nil, nil)
|
||||
}
|
||||
|
||||
var hideAuthor = false
|
||||
var messageText: String
|
||||
var messageEntities: [MessageTextEntity] = []
|
||||
var spoilers: [NSRange]?
|
||||
var customEmojiRanges: [(NSRange, ChatTextInputTextCustomEmojiAttribute)]?
|
||||
if let message = message {
|
||||
@@ -104,6 +105,7 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder:
|
||||
for message in messages {
|
||||
if !message.text.isEmpty {
|
||||
messageText = message.text
|
||||
messageEntities = message._asMessage().textEntitiesAttribute?.entities ?? []
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -469,5 +471,5 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder:
|
||||
}
|
||||
}
|
||||
|
||||
return (peer, hideAuthor, messageText, spoilers, customEmojiRanges)
|
||||
return (peer, hideAuthor, messageText, messageEntities, spoilers, customEmojiRanges)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import ChatListHeaderComponent
|
||||
import UndoUI
|
||||
import NewSessionInfoScreen
|
||||
import PresentationDataUtils
|
||||
import GlobalControlPanelsContext
|
||||
|
||||
public enum ChatListNodeMode {
|
||||
case chatList(appendContacts: Bool)
|
||||
@@ -110,7 +111,6 @@ public final class ChatListNodeInteraction {
|
||||
let hideChatFolderUpdates: () -> Void
|
||||
let openStories: (ChatListNode.OpenStoriesSubject, ASDisplayNode?) -> Void
|
||||
let openStarsTopup: (Int64?) -> Void
|
||||
let dismissNotice: (ChatListNotice) -> Void
|
||||
let editPeer: (ChatListItem) -> Void
|
||||
let openWebApp: (TelegramUser) -> Void
|
||||
let openPhotoSetup: () -> Void
|
||||
@@ -171,7 +171,6 @@ public final class ChatListNodeInteraction {
|
||||
hideChatFolderUpdates: @escaping () -> Void,
|
||||
openStories: @escaping (ChatListNode.OpenStoriesSubject, ASDisplayNode?) -> Void,
|
||||
openStarsTopup: @escaping (Int64?) -> Void,
|
||||
dismissNotice: @escaping (ChatListNotice) -> Void,
|
||||
editPeer: @escaping (ChatListItem) -> Void,
|
||||
openWebApp: @escaping (TelegramUser) -> Void,
|
||||
openPhotoSetup: @escaping () -> Void,
|
||||
@@ -219,7 +218,6 @@ public final class ChatListNodeInteraction {
|
||||
self.hideChatFolderUpdates = hideChatFolderUpdates
|
||||
self.openStories = openStories
|
||||
self.openStarsTopup = openStarsTopup
|
||||
self.dismissNotice = dismissNotice
|
||||
self.editPeer = editPeer
|
||||
self.openWebApp = openWebApp
|
||||
self.openPhotoSetup = openPhotoSetup
|
||||
@@ -698,6 +696,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
message: groupReferenceEntry.message,
|
||||
unreadCount: groupReferenceEntry.unreadCount,
|
||||
hiddenByDefault: groupReferenceEntry.hiddenByDefault,
|
||||
appearsPinned: groupReferenceEntry.appearsPinned,
|
||||
storyState: groupReferenceEntry.storyState.flatMap { storyState in
|
||||
return ChatListItemContent.StoryState(
|
||||
stats: storyState.stats,
|
||||
@@ -751,47 +750,6 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListSectionHeaderItem(theme: presentationData.theme, strings: presentationData.strings, hide: displayHide ? {
|
||||
hideChatListContacts(context: context)
|
||||
} : nil), directionHint: entry.directionHint)
|
||||
case let .Notice(presentationData, notice):
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListNoticeItem(context: context, theme: presentationData.theme, strings: presentationData.strings, notice: notice, action: { [weak nodeInteraction] action in
|
||||
switch action {
|
||||
case .activate:
|
||||
switch notice {
|
||||
case .clearStorage:
|
||||
nodeInteraction?.openStorageManagement()
|
||||
case .setupPassword:
|
||||
nodeInteraction?.openPasswordSetup()
|
||||
case .premiumUpgrade, .premiumAnnualDiscount, .premiumRestore:
|
||||
nodeInteraction?.openPremiumIntro()
|
||||
case .xmasPremiumGift:
|
||||
nodeInteraction?.openPremiumGift([], nil)
|
||||
case .premiumGrace:
|
||||
nodeInteraction?.openPremiumManagement()
|
||||
case .setupBirthday:
|
||||
nodeInteraction?.openBirthdaySetup()
|
||||
case let .birthdayPremiumGift(peers, birthdays):
|
||||
nodeInteraction?.openPremiumGift(peers, birthdays)
|
||||
case .reviewLogin:
|
||||
break
|
||||
case let .starsSubscriptionLowBalance(amount, _):
|
||||
nodeInteraction?.openStarsTopup(amount.value)
|
||||
case .setupPhoto:
|
||||
nodeInteraction?.openPhotoSetup()
|
||||
case .accountFreeze:
|
||||
nodeInteraction?.openAccountFreezeInfo()
|
||||
case let .link(_, url, _, _):
|
||||
nodeInteraction?.openUrl(url)
|
||||
}
|
||||
case .hide:
|
||||
nodeInteraction?.dismissNotice(notice)
|
||||
case let .buttonChoice(isPositive):
|
||||
switch notice {
|
||||
case let .reviewLogin(newSessionReview, _):
|
||||
nodeInteraction?.performActiveSessionAction(newSessionReview, isPositive)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}), directionHint: entry.directionHint)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1048,6 +1006,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
message: groupReferenceEntry.message,
|
||||
unreadCount: groupReferenceEntry.unreadCount,
|
||||
hiddenByDefault: groupReferenceEntry.hiddenByDefault,
|
||||
appearsPinned: groupReferenceEntry.appearsPinned,
|
||||
storyState: groupReferenceEntry.storyState.flatMap { storyState in
|
||||
return ChatListItemContent.StoryState(
|
||||
stats: storyState.stats,
|
||||
@@ -1101,47 +1060,6 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListSectionHeaderItem(theme: presentationData.theme, strings: presentationData.strings, hide: displayHide ? {
|
||||
hideChatListContacts(context: context)
|
||||
} : nil), directionHint: entry.directionHint)
|
||||
case let .Notice(presentationData, notice):
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListNoticeItem(context: context, theme: presentationData.theme, strings: presentationData.strings, notice: notice, action: { [weak nodeInteraction] action in
|
||||
switch action {
|
||||
case .activate:
|
||||
switch notice {
|
||||
case .clearStorage:
|
||||
nodeInteraction?.openStorageManagement()
|
||||
case .setupPassword:
|
||||
nodeInteraction?.openPasswordSetup()
|
||||
case .premiumUpgrade, .premiumAnnualDiscount, .premiumRestore:
|
||||
nodeInteraction?.openPremiumIntro()
|
||||
case .xmasPremiumGift:
|
||||
nodeInteraction?.openPremiumGift([], nil)
|
||||
case .premiumGrace:
|
||||
nodeInteraction?.openPremiumManagement()
|
||||
case .setupBirthday:
|
||||
nodeInteraction?.openBirthdaySetup()
|
||||
case let .birthdayPremiumGift(peers, birthdays):
|
||||
nodeInteraction?.openPremiumGift(peers, birthdays)
|
||||
case .reviewLogin:
|
||||
break
|
||||
case let .starsSubscriptionLowBalance(amount, _):
|
||||
nodeInteraction?.openStarsTopup(amount.value)
|
||||
case .setupPhoto:
|
||||
nodeInteraction?.openPhotoSetup()
|
||||
case .accountFreeze:
|
||||
nodeInteraction?.openAccountFreezeInfo()
|
||||
case let .link(_, url, _, _):
|
||||
nodeInteraction?.openUrl(url)
|
||||
}
|
||||
case .hide:
|
||||
nodeInteraction?.dismissNotice(notice)
|
||||
case let .buttonChoice(isPositive):
|
||||
switch notice {
|
||||
case let .reviewLogin(newSessionReview, _):
|
||||
nodeInteraction?.performActiveSessionAction(newSessionReview, isPositive)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}), directionHint: entry.directionHint)
|
||||
case .HeaderEntry:
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListEmptyHeaderItem(), directionHint: entry.directionHint)
|
||||
case let .AdditionalCategory(index: _, id, title, image, appearance, selected, presentationData):
|
||||
@@ -1282,7 +1200,7 @@ public final class ChatListNode: ListView {
|
||||
return []
|
||||
}
|
||||
}
|
||||
private var interaction: ChatListNodeInteraction?
|
||||
public private(set) var interaction: ChatListNodeInteraction?
|
||||
|
||||
private var dequeuedInitialTransitionOnLayout = false
|
||||
private var enqueuedTransition: (ChatListNodeListViewTransition, () -> Void)?
|
||||
@@ -1383,7 +1301,6 @@ public final class ChatListNode: ListView {
|
||||
private let autoSetReady: Bool
|
||||
|
||||
public let isMainTab = ValuePromise<Bool>(false, ignoreRepeated: true)
|
||||
private let suggestedChatListNotice = Promise<ChatListNotice?>(nil)
|
||||
|
||||
public var synchronousDrawingWhenNotAnimated: Bool = false
|
||||
|
||||
@@ -1868,38 +1785,6 @@ public final class ChatListNode: ListView {
|
||||
return
|
||||
}
|
||||
self.openStarsTopup?(amount)
|
||||
}, dismissNotice: { [weak self] notice in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
||||
switch notice {
|
||||
case .xmasPremiumGift:
|
||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.xmasPremiumGift.id).startStandalone()
|
||||
self.present?(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gift", scale: 0.058, colors: ["__allcolors__": UIColor.white], title: nil, text: presentationData.strings.ChatList_PremiumGiftInSettingsInfo, customUndoText: nil, timeout: 5.0), elevatedLayout: false, action: { _ in
|
||||
return true
|
||||
}))
|
||||
case .setupBirthday:
|
||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupBirthday.id).startStandalone()
|
||||
self.present?(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gift", scale: 0.058, colors: ["__allcolors__": UIColor.white], title: nil, text: presentationData.strings.ChatList_BirthdayInSettingsInfo, customUndoText: nil, timeout: 5.0), elevatedLayout: false, action: { _ in
|
||||
return true
|
||||
}))
|
||||
case .birthdayPremiumGift:
|
||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.todayBirthdays.id).startStandalone()
|
||||
self.present?(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gift", scale: 0.058, colors: ["__allcolors__": UIColor.white], title: nil, text: presentationData.strings.ChatList_PremiumGiftInSettingsInfo, customUndoText: nil, timeout: 5.0), elevatedLayout: false, action: { _ in
|
||||
return true
|
||||
}))
|
||||
case .premiumGrace:
|
||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.gracePremium.id).startStandalone()
|
||||
case .setupPhoto:
|
||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupPhoto.id).startStandalone()
|
||||
case .starsSubscriptionLowBalance:
|
||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.starsSubscriptionLowBalance.id).startStandalone()
|
||||
case let .link(id, _, _, _):
|
||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: id).startStandalone()
|
||||
default:
|
||||
break
|
||||
}
|
||||
}, editPeer: { _ in
|
||||
}, openWebApp: { [weak self] user in
|
||||
guard let self else {
|
||||
@@ -1992,172 +1877,12 @@ public final class ChatListNode: ListView {
|
||||
} else {
|
||||
displayArchiveIntro = .single(false)
|
||||
}
|
||||
|
||||
let starsSubscriptionsContextPromise = Promise<StarsSubscriptionsContext?>(nil)
|
||||
|
||||
self.updateIsMainTabDisposable = (self.isMainTab.get()
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] isMainTab in
|
||||
guard let self else {
|
||||
return
|
||||
|> deliverOnMainQueue).startStrict(next: { isMainTab in
|
||||
if isMainTab {
|
||||
let _ = context.engine.privacy.cleanupSessionReviews().startStandalone()
|
||||
}
|
||||
|
||||
guard case .chatList(groupId: .root) = location, isMainTab else {
|
||||
self.suggestedChatListNotice.set(.single(nil))
|
||||
return
|
||||
}
|
||||
|
||||
let _ = context.engine.privacy.cleanupSessionReviews().startStandalone()
|
||||
|
||||
let twoStepData: Signal<TwoStepVerificationConfiguration?, NoError> = .single(nil) |> then(context.engine.auth.twoStepVerificationConfiguration() |> map(Optional.init))
|
||||
|
||||
let accountFreezeConfiguration = (context.account.postbox.preferencesView(keys: [PreferencesKeys.appConfiguration])
|
||||
|> map { view -> AppConfiguration in
|
||||
let appConfiguration: AppConfiguration = view.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self) ?? AppConfiguration.defaultValue
|
||||
return appConfiguration
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|> map { appConfiguration -> AccountFreezeConfiguration in
|
||||
return AccountFreezeConfiguration.with(appConfiguration: appConfiguration)
|
||||
})
|
||||
|
||||
let suggestedChatListNoticeSignal: Signal<ChatListNotice?, NoError> = combineLatest(
|
||||
context.engine.notices.getServerProvidedSuggestions(),
|
||||
context.engine.notices.getServerDismissedSuggestions(),
|
||||
twoStepData,
|
||||
newSessionReviews(postbox: context.account.postbox),
|
||||
context.engine.data.subscribe(
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId),
|
||||
TelegramEngine.EngineData.Item.Peer.Birthday(id: context.account.peerId)
|
||||
),
|
||||
context.account.stateManager.contactBirthdays,
|
||||
starsSubscriptionsContextPromise.get(),
|
||||
accountFreezeConfiguration
|
||||
)
|
||||
|> mapToSignal { suggestions, dismissedSuggestions, configuration, newSessionReviews, data, birthdays, starsSubscriptionsContext, accountFreezeConfiguration -> Signal<ChatListNotice?, NoError> in
|
||||
let (accountPeer, birthday) = data
|
||||
|
||||
if let newSessionReview = newSessionReviews.first {
|
||||
return .single(.reviewLogin(newSessionReview: newSessionReview, totalCount: newSessionReviews.count))
|
||||
}
|
||||
if suggestions.contains(.setupPassword), let configuration {
|
||||
var notSet = false
|
||||
switch configuration {
|
||||
case let .notSet(pendingEmail):
|
||||
if pendingEmail == nil {
|
||||
notSet = true
|
||||
}
|
||||
case .set:
|
||||
break
|
||||
}
|
||||
if notSet {
|
||||
return .single(.setupPassword)
|
||||
}
|
||||
}
|
||||
|
||||
let today = Calendar(identifier: .gregorian).component(.day, from: Date())
|
||||
var todayBirthdayPeerIds: [EnginePeer.Id] = []
|
||||
for (peerId, birthday) in birthdays {
|
||||
if birthday.day == today {
|
||||
todayBirthdayPeerIds.append(peerId)
|
||||
}
|
||||
}
|
||||
todayBirthdayPeerIds.sort { lhs, rhs in
|
||||
return lhs < rhs
|
||||
}
|
||||
|
||||
if dismissedSuggestions.contains(ServerProvidedSuggestion.todayBirthdays.id) {
|
||||
todayBirthdayPeerIds = []
|
||||
}
|
||||
|
||||
if let _ = accountFreezeConfiguration.freezeUntilDate {
|
||||
return .single(.accountFreeze)
|
||||
} else if suggestions.contains(.starsSubscriptionLowBalance) {
|
||||
if let starsSubscriptionsContext {
|
||||
return starsSubscriptionsContext.state
|
||||
|> map { state in
|
||||
if state.balance > StarsAmount.zero && !state.subscriptions.isEmpty {
|
||||
return .starsSubscriptionLowBalance(
|
||||
amount: state.balance,
|
||||
peers: state.subscriptions.map { $0.peer }
|
||||
)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
starsSubscriptionsContextPromise.set(.single(context.engine.payments.peerStarsSubscriptionsContext(starsContext: nil, missingBalance: true)))
|
||||
return .single(nil)
|
||||
}
|
||||
} else if suggestions.contains(.setupPhoto), let accountPeer, accountPeer.smallProfileImage == nil {
|
||||
return .single(.setupPhoto(accountPeer))
|
||||
} else if suggestions.contains(.gracePremium) {
|
||||
return .single(.premiumGrace)
|
||||
} else if suggestions.contains(.xmasPremiumGift) {
|
||||
return .single(.xmasPremiumGift)
|
||||
} else if suggestions.contains(.annualPremium) || suggestions.contains(.upgradePremium) || suggestions.contains(.restorePremium), let inAppPurchaseManager = context.inAppPurchaseManager {
|
||||
return inAppPurchaseManager.availableProducts
|
||||
|> map { products -> ChatListNotice? in
|
||||
if products.count > 1 {
|
||||
let shortestOptionPrice: (Int64, NSDecimalNumber)
|
||||
if let product = products.first(where: { $0.id.hasSuffix(".monthly") }) {
|
||||
shortestOptionPrice = (Int64(Float(product.priceCurrencyAndAmount.amount)), product.priceValue)
|
||||
} else {
|
||||
shortestOptionPrice = (1, NSDecimalNumber(decimal: 1))
|
||||
}
|
||||
for product in products {
|
||||
if product.id.hasSuffix(".annual") {
|
||||
let fraction = Float(product.priceCurrencyAndAmount.amount) / Float(12) / Float(shortestOptionPrice.0)
|
||||
let discount = Int32(round((1.0 - fraction) * 20.0) * 5.0)
|
||||
if discount > 0 {
|
||||
if suggestions.contains(.restorePremium) {
|
||||
return .premiumRestore(discount: discount)
|
||||
} else if suggestions.contains(.annualPremium) {
|
||||
return .premiumAnnualDiscount(discount: discount)
|
||||
} else if suggestions.contains(.upgradePremium) {
|
||||
return .premiumUpgrade(discount: discount)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
if !GlobalExperimentalSettings.isAppStoreBuild {
|
||||
if suggestions.contains(.restorePremium) {
|
||||
return .premiumRestore(discount: 0)
|
||||
} else if suggestions.contains(.annualPremium) {
|
||||
return .premiumAnnualDiscount(discount: 0)
|
||||
} else if suggestions.contains(.upgradePremium) {
|
||||
return .premiumUpgrade(discount: 0)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
} else if !todayBirthdayPeerIds.isEmpty {
|
||||
return context.engine.data.get(
|
||||
EngineDataMap(todayBirthdayPeerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init(id:)))
|
||||
)
|
||||
|> map { result -> ChatListNotice? in
|
||||
var todayBirthdayPeers: [EnginePeer] = []
|
||||
for (peerId, _) in birthdays {
|
||||
if let maybePeer = result[peerId], let peer = maybePeer {
|
||||
todayBirthdayPeers.append(peer)
|
||||
}
|
||||
}
|
||||
return .birthdayPremiumGift(peers: todayBirthdayPeers, birthdays: birthdays)
|
||||
}
|
||||
} else if suggestions.contains(.setupBirthday) && birthday == nil {
|
||||
return .single(.setupBirthday)
|
||||
} else if case let .link(id, url, title, subtitle) = suggestions.first(where: { if case .link = $0 { return true } else { return false} }) {
|
||||
return .single(.link(id: id, url: url, title: title, subtitle: subtitle))
|
||||
} else {
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|
||||
self.suggestedChatListNotice.set(suggestedChatListNoticeSignal)
|
||||
}).strict()
|
||||
|
||||
let storageInfo: Signal<Double?, NoError>
|
||||
@@ -2346,7 +2071,6 @@ public final class ChatListNode: ListView {
|
||||
hideArchivedFolderByDefault,
|
||||
displayArchiveIntro,
|
||||
storageInfo,
|
||||
suggestedChatListNotice.get(),
|
||||
savedMessagesPeer,
|
||||
chatListViewUpdate,
|
||||
self.statePromise.get(),
|
||||
@@ -2354,23 +2078,14 @@ public final class ChatListNode: ListView {
|
||||
chatListFilters,
|
||||
accountIsPremium
|
||||
)
|
||||
|> mapToQueue { (hideArchivedFolderByDefault, displayArchiveIntro, storageInfo, suggestedChatListNotice, savedMessagesPeer, updateAndFilter, state, contacts, chatListFilters, accountIsPremium) -> Signal<ChatListNodeListViewTransition, NoError> in
|
||||
|> mapToQueue { (hideArchivedFolderByDefault, displayArchiveIntro, storageInfo, savedMessagesPeer, updateAndFilter, state, contacts, chatListFilters, accountIsPremium) -> Signal<ChatListNodeListViewTransition, NoError> in
|
||||
let (update, filter) = updateAndFilter
|
||||
|
||||
let previousHideArchivedFolderByDefaultValue = previousHideArchivedFolderByDefault.swap(hideArchivedFolderByDefault)
|
||||
|
||||
let notice: ChatListNotice?
|
||||
if let suggestedChatListNotice {
|
||||
notice = suggestedChatListNotice
|
||||
} else if let storageInfo {
|
||||
notice = .clearStorage(sizeFraction: storageInfo)
|
||||
} else {
|
||||
notice = nil
|
||||
}
|
||||
|
||||
let innerIsMainTab = location == .chatList(groupId: .root) && chatListFilter == nil
|
||||
|
||||
let (rawEntries, isLoading) = chatListNodeEntriesForView(view: update.list, state: state, savedMessagesPeer: savedMessagesPeer, foundPeers: state.foundPeers, hideArchivedFolderByDefault: hideArchivedFolderByDefault, displayArchiveIntro: displayArchiveIntro, notice: notice, mode: mode, chatListLocation: location, contacts: contacts, accountPeerId: accountPeerId, isMainTab: innerIsMainTab)
|
||||
let (rawEntries, isLoading) = chatListNodeEntriesForView(view: update.list, state: state, savedMessagesPeer: savedMessagesPeer, foundPeers: state.foundPeers, hideArchivedFolderByDefault: hideArchivedFolderByDefault, displayArchiveIntro: displayArchiveIntro, mode: mode, chatListLocation: location, contacts: contacts, accountPeerId: accountPeerId, isMainTab: innerIsMainTab)
|
||||
var isEmpty = true
|
||||
var entries = rawEntries.filter { entry in
|
||||
switch entry {
|
||||
@@ -2697,7 +2412,6 @@ public final class ChatListNode: ListView {
|
||||
var didIncludeRemovingPeerId = false
|
||||
var didIncludeHiddenByDefaultArchive = false
|
||||
var didIncludeHiddenThread = false
|
||||
var didIncludeNotice = false
|
||||
if let previous = previousView {
|
||||
for entry in previous.filteredEntries {
|
||||
if case let .PeerEntry(peerEntry) = entry {
|
||||
@@ -2724,15 +2438,12 @@ public final class ChatListNode: ListView {
|
||||
}
|
||||
} else if case let .GroupReferenceEntry(groupReferenceEntry) = entry {
|
||||
didIncludeHiddenByDefaultArchive = groupReferenceEntry.hiddenByDefault
|
||||
} else if case .Notice = entry {
|
||||
didIncludeNotice = true
|
||||
}
|
||||
}
|
||||
}
|
||||
var doesIncludeRemovingPeerId = false
|
||||
var doesIncludeArchive = false
|
||||
var doesIncludeHiddenByDefaultArchive = false
|
||||
var doesIncludeNotice = false
|
||||
|
||||
var doesIncludeHiddenThread = false
|
||||
for entry in processedView.filteredEntries {
|
||||
@@ -2761,8 +2472,6 @@ public final class ChatListNode: ListView {
|
||||
} else if case let .GroupReferenceEntry(groupReferenceEntry) = entry {
|
||||
doesIncludeArchive = true
|
||||
doesIncludeHiddenByDefaultArchive = groupReferenceEntry.hiddenByDefault
|
||||
} else if case .Notice = entry {
|
||||
doesIncludeNotice = true
|
||||
}
|
||||
}
|
||||
if previousPinnedChats != updatedPinnedChats || previousPinnedThreads != updatedPinnedThreads {
|
||||
@@ -2789,9 +2498,6 @@ public final class ChatListNode: ListView {
|
||||
if didIncludeHiddenThread != doesIncludeHiddenThread {
|
||||
disableAnimations = false
|
||||
}
|
||||
if didIncludeNotice != doesIncludeNotice {
|
||||
disableAnimations = false
|
||||
}
|
||||
}
|
||||
|
||||
if let _ = previousHideArchivedFolderByDefaultValue, previousHideArchivedFolderByDefaultValue != hideArchivedFolderByDefault {
|
||||
@@ -3547,8 +3253,10 @@ public final class ChatListNode: ListView {
|
||||
if entryCount - 1 - i < 0 {
|
||||
continue
|
||||
}
|
||||
if case .PeerEntry = transition.chatListView.filteredEntries[entryCount - 1 - i] {
|
||||
} else {
|
||||
switch transition.chatListView.filteredEntries[entryCount - 1 - i] {
|
||||
case .PeerEntry, .GroupReferenceEntry:
|
||||
break
|
||||
default:
|
||||
continue
|
||||
}
|
||||
if case let .index(index) = transition.chatListView.filteredEntries[entryCount - 1 - i].sortIndex, case let .chatList(chatListIndex) = index, chatListIndex.pinningIndex != nil {
|
||||
@@ -3658,7 +3366,7 @@ public final class ChatListNode: ListView {
|
||||
} else {
|
||||
break loop
|
||||
}
|
||||
case .ArchiveIntro, .EmptyIntro, .SectionHeader, .Notice, .HeaderEntry, .AdditionalCategory:
|
||||
case .ArchiveIntro, .EmptyIntro, .SectionHeader, .HeaderEntry, .AdditionalCategory:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,23 +79,6 @@ public enum ChatListNodeEntryPromoInfo: Equatable {
|
||||
case psa(type: String, message: String?)
|
||||
}
|
||||
|
||||
public enum ChatListNotice: Equatable {
|
||||
case clearStorage(sizeFraction: Double)
|
||||
case setupPassword
|
||||
case premiumUpgrade(discount: Int32)
|
||||
case premiumAnnualDiscount(discount: Int32)
|
||||
case premiumRestore(discount: Int32)
|
||||
case xmasPremiumGift
|
||||
case setupBirthday
|
||||
case birthdayPremiumGift(peers: [EnginePeer], birthdays: [EnginePeer.Id: TelegramBirthday])
|
||||
case reviewLogin(newSessionReview: NewSessionReview, totalCount: Int)
|
||||
case premiumGrace
|
||||
case starsSubscriptionLowBalance(amount: StarsAmount, peers: [EnginePeer])
|
||||
case setupPhoto(EnginePeer)
|
||||
case accountFreeze
|
||||
case link(id: String, url: String, title: ServerSuggestionInfo.Item.Text, subtitle: ServerSuggestionInfo.Item.Text)
|
||||
}
|
||||
|
||||
enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
struct PeerEntryData: Equatable {
|
||||
var index: EngineChatList.Item.Index
|
||||
@@ -339,6 +322,7 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
var unreadCount: Int
|
||||
var revealed: Bool
|
||||
var hiddenByDefault: Bool
|
||||
var appearsPinned: Bool
|
||||
var storyState: ChatListNodeState.StoryState?
|
||||
|
||||
init(
|
||||
@@ -351,6 +335,7 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
unreadCount: Int,
|
||||
revealed: Bool,
|
||||
hiddenByDefault: Bool,
|
||||
appearsPinned: Bool,
|
||||
storyState: ChatListNodeState.StoryState?
|
||||
) {
|
||||
self.index = index
|
||||
@@ -362,6 +347,7 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
self.unreadCount = unreadCount
|
||||
self.revealed = revealed
|
||||
self.hiddenByDefault = hiddenByDefault
|
||||
self.appearsPinned = appearsPinned
|
||||
self.storyState = storyState
|
||||
}
|
||||
|
||||
@@ -393,6 +379,9 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
if lhs.hiddenByDefault != rhs.hiddenByDefault {
|
||||
return false
|
||||
}
|
||||
if lhs.appearsPinned != rhs.appearsPinned {
|
||||
return false
|
||||
}
|
||||
if lhs.storyState != rhs.storyState {
|
||||
return false
|
||||
}
|
||||
@@ -409,7 +398,6 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
case ArchiveIntro(presentationData: ChatListPresentationData)
|
||||
case EmptyIntro(presentationData: ChatListPresentationData)
|
||||
case SectionHeader(presentationData: ChatListPresentationData, displayHide: Bool)
|
||||
case Notice(presentationData: ChatListPresentationData, notice: ChatListNotice)
|
||||
case AdditionalCategory(index: Int, id: Int, title: String, image: UIImage?, appearance: ChatListNodeAdditionalCategory.Appearance, selected: Bool, presentationData: ChatListPresentationData)
|
||||
|
||||
var sortIndex: ChatListNodeEntrySortIndex {
|
||||
@@ -430,8 +418,6 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
return .index(.chatList(EngineChatList.Item.Index.ChatList.absoluteUpperBound.successor))
|
||||
case .SectionHeader:
|
||||
return .sectionHeader
|
||||
case .Notice:
|
||||
return .index(.chatList(EngineChatList.Item.Index.ChatList.absoluteUpperBound.successor.successor))
|
||||
case let .AdditionalCategory(index, _, _, _, _, _, _):
|
||||
return .additionalCategory(index)
|
||||
}
|
||||
@@ -460,8 +446,6 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
return .EmptyIntro
|
||||
case .SectionHeader:
|
||||
return .SectionHeader
|
||||
case .Notice:
|
||||
return .Notice
|
||||
case let .AdditionalCategory(_, id, _, _, _, _, _):
|
||||
return .additionalCategory(id)
|
||||
}
|
||||
@@ -534,18 +518,6 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .Notice(lhsPresentationData, lhsInfo):
|
||||
if case let .Notice(rhsPresentationData, rhsInfo) = rhs {
|
||||
if lhsPresentationData !== rhsPresentationData {
|
||||
return false
|
||||
}
|
||||
if lhsInfo != rhsInfo {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .AdditionalCategory(lhsIndex, lhsId, lhsTitle, lhsImage, lhsAppearance, lhsSelected, lhsPresentationData):
|
||||
if case let .AdditionalCategory(rhsIndex, rhsId, rhsTitle, rhsImage, rhsAppearance, rhsSelected, rhsPresentationData) = rhs {
|
||||
if lhsIndex != rhsIndex {
|
||||
@@ -595,7 +567,7 @@ struct ChatListContactPeer {
|
||||
}
|
||||
}
|
||||
|
||||
func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState, savedMessagesPeer: EnginePeer?, foundPeers: [(EnginePeer, EnginePeer?)], hideArchivedFolderByDefault: Bool, displayArchiveIntro: Bool, notice: ChatListNotice?, mode: ChatListNodeMode, chatListLocation: ChatListControllerLocation, contacts: [ChatListContactPeer], accountPeerId: EnginePeer.Id, isMainTab: Bool) -> (entries: [ChatListNodeEntry], loading: Bool) {
|
||||
func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState, savedMessagesPeer: EnginePeer?, foundPeers: [(EnginePeer, EnginePeer?)], hideArchivedFolderByDefault: Bool, displayArchiveIntro: Bool, mode: ChatListNodeMode, chatListLocation: ChatListControllerLocation, contacts: [ChatListContactPeer], accountPeerId: EnginePeer.Id, isMainTab: Bool) -> (entries: [ChatListNodeEntry], loading: Bool) {
|
||||
var groupItems = view.groupItems
|
||||
if isMainTab && state.archiveStoryState != nil && groupItems.isEmpty {
|
||||
groupItems.append(EngineChatList.GroupItem(
|
||||
@@ -656,6 +628,8 @@ func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState,
|
||||
|
||||
var hiddenGeneralThread: ChatListNodeEntry?
|
||||
|
||||
var hasPinned = false
|
||||
|
||||
loop: for entry in view.items {
|
||||
var peerId: EnginePeer.Id?
|
||||
var threadId: Int64?
|
||||
@@ -707,6 +681,17 @@ func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState,
|
||||
if let threadData = entry.threadData, let threadId {
|
||||
threadInfo = ChatListItemContent.ThreadInfo(id: threadId, info: threadData.info, isOwnedByMe: threadData.isOwnedByMe, isClosed: threadData.isClosed, isHidden: threadData.isHidden, threadPeer: nil)
|
||||
}
|
||||
|
||||
switch entry.index {
|
||||
case let .chatList(chatList):
|
||||
if chatList.pinningIndex != nil {
|
||||
hasPinned = true
|
||||
}
|
||||
case let .forum(pinnedIndex, _, _, _, _):
|
||||
if case .index = pinnedIndex {
|
||||
hasPinned = true
|
||||
}
|
||||
}
|
||||
|
||||
let entry: ChatListNodeEntry = .PeerEntry(ChatListNodeEntry.PeerEntryData(
|
||||
index: offsetPinnedIndex(entry.index, offset: pinnedIndexOffset),
|
||||
@@ -796,6 +781,7 @@ func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState,
|
||||
)))
|
||||
if foundPinningIndex != 0 {
|
||||
foundPinningIndex -= 1
|
||||
hasPinned = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -886,6 +872,7 @@ func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState,
|
||||
)))
|
||||
if pinningIndex != 0 {
|
||||
pinningIndex -= 1
|
||||
hasPinned = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -908,10 +895,12 @@ func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState,
|
||||
unreadCount: groupReference.unreadCount,
|
||||
revealed: state.hiddenItemShouldBeTemporaryRevealed,
|
||||
hiddenByDefault: hideArchivedFolderByDefault,
|
||||
appearsPinned: hasPinned,
|
||||
storyState: mappedStoryState
|
||||
)))
|
||||
if pinningIndex != 0 {
|
||||
pinningIndex -= 1
|
||||
hasPinned = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -927,10 +916,6 @@ func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState,
|
||||
result.append(.EmptyIntro(presentationData: state.presentationData))
|
||||
}
|
||||
|
||||
if let notice {
|
||||
result.append(.Notice(presentationData: state.presentationData, notice: notice))
|
||||
}
|
||||
|
||||
result.append(.HeaderEntry)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user