mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
Various improvements
This commit is contained in:
@@ -92,6 +92,7 @@ public final class ChatListNodeInteraction {
|
||||
let present: (ViewController) -> Void
|
||||
let openForumThread: (EnginePeer.Id, Int64) -> Void
|
||||
let openStorageManagement: () -> Void
|
||||
let openPasswordSetup: () -> Void
|
||||
|
||||
public var searchTextHighightState: String?
|
||||
var highlightedChatLocation: ChatListHighlightedLocation?
|
||||
@@ -134,7 +135,8 @@ public final class ChatListNodeInteraction {
|
||||
activateChatPreview: @escaping (ChatListItem, Int64?, ASDisplayNode, ContextGesture?, CGPoint?) -> Void,
|
||||
present: @escaping (ViewController) -> Void,
|
||||
openForumThread: @escaping (EnginePeer.Id, Int64) -> Void,
|
||||
openStorageManagement: @escaping () -> Void
|
||||
openStorageManagement: @escaping () -> Void,
|
||||
openPasswordSetup: @escaping () -> Void
|
||||
) {
|
||||
self.activateSearch = activateSearch
|
||||
self.peerSelected = peerSelected
|
||||
@@ -165,6 +167,7 @@ public final class ChatListNodeInteraction {
|
||||
self.animationRenderer = animationRenderer
|
||||
self.openForumThread = openForumThread
|
||||
self.openStorageManagement = openStorageManagement
|
||||
self.openPasswordSetup = openPasswordSetup
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,9 +573,14 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
), directionHint: entry.directionHint)
|
||||
case let .ArchiveIntro(presentationData):
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListArchiveInfoItem(theme: presentationData.theme, strings: presentationData.strings), directionHint: entry.directionHint)
|
||||
case let .StorageInfo(presentationData, sizeFraction):
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListStorageInfoItem(theme: presentationData.theme, strings: presentationData.strings, sizeFraction: sizeFraction, action: { [weak nodeInteraction] in
|
||||
nodeInteraction?.openStorageManagement()
|
||||
case let .Notice(presentationData, notice):
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListStorageInfoItem(theme: presentationData.theme, strings: presentationData.strings, notice: notice, action: { [weak nodeInteraction] in
|
||||
switch notice {
|
||||
case .clearStorage:
|
||||
nodeInteraction?.openStorageManagement()
|
||||
case .setupPassword:
|
||||
nodeInteraction?.openPasswordSetup()
|
||||
}
|
||||
}), directionHint: entry.directionHint)
|
||||
}
|
||||
}
|
||||
@@ -785,9 +793,14 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
), directionHint: entry.directionHint)
|
||||
case let .ArchiveIntro(presentationData):
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListArchiveInfoItem(theme: presentationData.theme, strings: presentationData.strings), directionHint: entry.directionHint)
|
||||
case let .StorageInfo(presentationData, sizeFraction):
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListStorageInfoItem(theme: presentationData.theme, strings: presentationData.strings, sizeFraction: sizeFraction, action: { [weak nodeInteraction] in
|
||||
nodeInteraction?.openStorageManagement()
|
||||
case let .Notice(presentationData, notice):
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListStorageInfoItem(theme: presentationData.theme, strings: presentationData.strings, notice: notice, action: { [weak nodeInteraction] in
|
||||
switch notice {
|
||||
case .clearStorage:
|
||||
nodeInteraction?.openStorageManagement()
|
||||
case .setupPassword:
|
||||
nodeInteraction?.openPasswordSetup()
|
||||
}
|
||||
}), directionHint: entry.directionHint)
|
||||
case .HeaderEntry:
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListEmptyHeaderItem(), directionHint: entry.directionHint)
|
||||
@@ -1277,6 +1290,20 @@ public final class ChatListNode: ListView {
|
||||
}
|
||||
let controller = self.context.sharedContext.makeStorageManagementController(context: self.context)
|
||||
self.push?(controller)
|
||||
}, openPasswordSetup: { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.6, execute: { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
let _ = dismissServerProvidedSuggestion(account: self.context.account, suggestion: .setupPassword).start()
|
||||
})
|
||||
|
||||
let controller = self.context.sharedContext.makeSetupTwoFactorAuthController(context: self.context)
|
||||
self.push?(controller)
|
||||
})
|
||||
nodeInteraction.isInlineMode = isInlineMode
|
||||
|
||||
@@ -1342,6 +1369,32 @@ public final class ChatListNode: ListView {
|
||||
displayArchiveIntro = .single(false)
|
||||
}
|
||||
|
||||
let suggestPasswordSetup: Signal<Bool, NoError>
|
||||
if case .chatList(groupId: .root) = location, chatListFilter == nil {
|
||||
suggestPasswordSetup = combineLatest(
|
||||
getServerProvidedSuggestions(account: context.account),
|
||||
context.engine.auth.twoStepVerificationConfiguration()
|
||||
)
|
||||
|> map { suggestions, configuration -> Bool in
|
||||
var notSet = false
|
||||
switch configuration {
|
||||
case let .notSet(pendingEmail):
|
||||
if pendingEmail == nil {
|
||||
notSet = true
|
||||
}
|
||||
case .set:
|
||||
break
|
||||
}
|
||||
if !notSet {
|
||||
return false
|
||||
}
|
||||
return suggestions.contains(.setupPassword)
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
} else {
|
||||
suggestPasswordSetup = .single(false)
|
||||
}
|
||||
|
||||
let storageInfo: Signal<Double?, NoError>
|
||||
if !"".isEmpty, case .chatList(groupId: .root) = location, chatListFilter == nil {
|
||||
let totalSizeSignal = combineLatest(context.account.postbox.mediaBox.storageBox.totalSize(), context.account.postbox.mediaBox.cacheStorageBox.totalSize())
|
||||
@@ -1431,13 +1484,13 @@ public final class ChatListNode: ListView {
|
||||
|
||||
let currentPeerId: EnginePeer.Id = context.account.peerId
|
||||
|
||||
let chatListNodeViewTransition = combineLatest(queue: viewProcessingQueue, hideArchivedFolderByDefault, displayArchiveIntro, storageInfo, savedMessagesPeer, chatListViewUpdate, self.statePromise.get())
|
||||
|> mapToQueue { (hideArchivedFolderByDefault, displayArchiveIntro, storageInfo, savedMessagesPeer, updateAndFilter, state) -> Signal<ChatListNodeListViewTransition, NoError> in
|
||||
let chatListNodeViewTransition = combineLatest(queue: viewProcessingQueue, hideArchivedFolderByDefault, displayArchiveIntro, storageInfo, suggestPasswordSetup, savedMessagesPeer, chatListViewUpdate, self.statePromise.get())
|
||||
|> mapToQueue { (hideArchivedFolderByDefault, displayArchiveIntro, storageInfo, suggestPasswordSetup, savedMessagesPeer, updateAndFilter, state) -> Signal<ChatListNodeListViewTransition, NoError> in
|
||||
let (update, filter) = updateAndFilter
|
||||
|
||||
let previousHideArchivedFolderByDefaultValue = previousHideArchivedFolderByDefault.swap(hideArchivedFolderByDefault)
|
||||
|
||||
let (rawEntries, isLoading) = chatListNodeEntriesForView(update.list, state: state, savedMessagesPeer: savedMessagesPeer, foundPeers: state.foundPeers, hideArchivedFolderByDefault: hideArchivedFolderByDefault, displayArchiveIntro: displayArchiveIntro, storageInfo: storageInfo, mode: mode, chatListLocation: location)
|
||||
let (rawEntries, isLoading) = chatListNodeEntriesForView(update.list, state: state, savedMessagesPeer: savedMessagesPeer, foundPeers: state.foundPeers, hideArchivedFolderByDefault: hideArchivedFolderByDefault, displayArchiveIntro: displayArchiveIntro, storageInfo: storageInfo, suggestPasswordSetup: suggestPasswordSetup, mode: mode, chatListLocation: location)
|
||||
let entries = rawEntries.filter { entry in
|
||||
switch entry {
|
||||
case let .PeerEntry(peerEntry):
|
||||
@@ -2467,7 +2520,7 @@ public final class ChatListNode: ListView {
|
||||
} else {
|
||||
break loop
|
||||
}
|
||||
case .ArchiveIntro, .StorageInfo, .HeaderEntry, .AdditionalCategory:
|
||||
case .ArchiveIntro, .Notice, .HeaderEntry, .AdditionalCategory:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ enum ChatListNodeEntryId: Hashable {
|
||||
case ThreadId(Int64)
|
||||
case GroupId(EngineChatList.Group)
|
||||
case ArchiveIntro
|
||||
case StorageInfo
|
||||
case Notice
|
||||
case additionalCategory(Int)
|
||||
}
|
||||
|
||||
@@ -46,6 +46,11 @@ public enum ChatListNodeEntryPromoInfo: Equatable {
|
||||
case psa(type: String, message: String?)
|
||||
}
|
||||
|
||||
enum ChatListNotice: Equatable {
|
||||
case clearStorage(sizeFraction: Double)
|
||||
case setupPassword
|
||||
}
|
||||
|
||||
enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
struct PeerEntryData: Equatable {
|
||||
var index: EngineChatList.Item.Index
|
||||
@@ -235,7 +240,7 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
case HoleEntry(EngineMessage.Index, theme: PresentationTheme)
|
||||
case GroupReferenceEntry(index: EngineChatList.Item.Index, presentationData: ChatListPresentationData, groupId: EngineChatList.Group, peers: [EngineChatList.GroupItem.Item], message: EngineMessage?, editing: Bool, unreadCount: Int, revealed: Bool, hiddenByDefault: Bool)
|
||||
case ArchiveIntro(presentationData: ChatListPresentationData)
|
||||
case StorageInfo(presentationData: ChatListPresentationData, sizeFraction: Double)
|
||||
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 {
|
||||
@@ -250,7 +255,7 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
return .index(index)
|
||||
case .ArchiveIntro:
|
||||
return .index(.chatList(EngineChatList.Item.Index.ChatList.absoluteUpperBound.successor))
|
||||
case .StorageInfo:
|
||||
case .Notice:
|
||||
return .index(.chatList(EngineChatList.Item.Index.ChatList.absoluteUpperBound.successor.successor))
|
||||
case let .AdditionalCategory(index, _, _, _, _, _, _):
|
||||
return .additionalCategory(index)
|
||||
@@ -274,8 +279,8 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
return .GroupId(groupId)
|
||||
case .ArchiveIntro:
|
||||
return .ArchiveIntro
|
||||
case .StorageInfo:
|
||||
return .StorageInfo
|
||||
case .Notice:
|
||||
return .Notice
|
||||
case let .AdditionalCategory(_, id, _, _, _, _, _):
|
||||
return .additionalCategory(id)
|
||||
}
|
||||
@@ -348,8 +353,8 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .StorageInfo(lhsPresentationData, lhsInfo):
|
||||
if case let .StorageInfo(rhsPresentationData, rhsInfo) = rhs {
|
||||
case let .Notice(lhsPresentationData, lhsInfo):
|
||||
if case let .Notice(rhsPresentationData, rhsInfo) = rhs {
|
||||
if lhsPresentationData !== rhsPresentationData {
|
||||
return false
|
||||
}
|
||||
@@ -399,7 +404,7 @@ private func offsetPinnedIndex(_ index: EngineChatList.Item.Index, offset: UInt1
|
||||
}
|
||||
}
|
||||
|
||||
func chatListNodeEntriesForView(_ view: EngineChatList, state: ChatListNodeState, savedMessagesPeer: EnginePeer?, foundPeers: [(EnginePeer, EnginePeer?)], hideArchivedFolderByDefault: Bool, displayArchiveIntro: Bool, storageInfo: Double?, mode: ChatListNodeMode, chatListLocation: ChatListControllerLocation) -> (entries: [ChatListNodeEntry], loading: Bool) {
|
||||
func chatListNodeEntriesForView(_ view: EngineChatList, state: ChatListNodeState, savedMessagesPeer: EnginePeer?, foundPeers: [(EnginePeer, EnginePeer?)], hideArchivedFolderByDefault: Bool, displayArchiveIntro: Bool, storageInfo: Double?, suggestPasswordSetup: Bool, mode: ChatListNodeMode, chatListLocation: ChatListControllerLocation) -> (entries: [ChatListNodeEntry], loading: Bool) {
|
||||
var result: [ChatListNodeEntry] = []
|
||||
|
||||
var pinnedIndexOffset: UInt16 = 0
|
||||
@@ -661,8 +666,10 @@ func chatListNodeEntriesForView(_ view: EngineChatList, state: ChatListNodeState
|
||||
if displayArchiveIntro {
|
||||
result.append(.ArchiveIntro(presentationData: state.presentationData))
|
||||
}
|
||||
if let storageInfo {
|
||||
result.append(.StorageInfo(presentationData: state.presentationData, sizeFraction: storageInfo))
|
||||
if suggestPasswordSetup {
|
||||
result.append(.Notice(presentationData: state.presentationData, notice: .setupPassword))
|
||||
} else if let storageInfo {
|
||||
result.append(.Notice(presentationData: state.presentationData, notice: .clearStorage(sizeFraction: storageInfo)))
|
||||
}
|
||||
|
||||
result.append(.HeaderEntry)
|
||||
|
||||
@@ -11,15 +11,15 @@ import AppBundle
|
||||
class ChatListStorageInfoItem: ListViewItem {
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
let sizeFraction: Double
|
||||
let notice: ChatListNotice
|
||||
let action: () -> Void
|
||||
|
||||
let selectable: Bool = true
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, sizeFraction: Double, action: @escaping () -> Void) {
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, notice: ChatListNotice, action: @escaping () -> Void) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.sizeFraction = sizeFraction
|
||||
self.notice = notice
|
||||
self.action = action
|
||||
}
|
||||
|
||||
@@ -117,23 +117,37 @@ class ChatListStorageInfoItemNode: ListViewItemNode {
|
||||
let _ = baseWidth
|
||||
|
||||
let sideInset: CGFloat = params.leftInset + 16.0
|
||||
let height: CGFloat = 54.0
|
||||
let rightInset: CGFloat = sideInset + 24.0
|
||||
let verticalInset: CGFloat = 8.0
|
||||
let spacing: CGFloat = 0.0
|
||||
|
||||
let themeUpdated = item.theme !== previousItem?.theme
|
||||
|
||||
let sizeString = dataSizeString(Int64(item.sizeFraction), formatting: DataSizeStringFormatting(strings: item.strings, decimalSeparator: "."))
|
||||
let rawTitleString = item.strings.ChatList_StorageHintTitle(sizeString)
|
||||
let titleString = NSMutableAttributedString(attributedString: NSAttributedString(string: rawTitleString.string, font: titleFont, textColor: item.theme.rootController.navigationBar.primaryTextColor))
|
||||
if let range = rawTitleString.ranges.first {
|
||||
titleString.addAttribute(.foregroundColor, value: item.theme.rootController.navigationBar.accentTextColor, range: range.range)
|
||||
let titleString: NSAttributedString
|
||||
let textString: NSAttributedString
|
||||
|
||||
switch item.notice {
|
||||
case let .clearStorage(sizeFraction):
|
||||
let sizeString = dataSizeString(Int64(sizeFraction), formatting: DataSizeStringFormatting(strings: item.strings, decimalSeparator: "."))
|
||||
let rawTitleString = item.strings.ChatList_StorageHintTitle(sizeString)
|
||||
let titleStringValue = NSMutableAttributedString(attributedString: NSAttributedString(string: rawTitleString.string, font: titleFont, textColor: item.theme.rootController.navigationBar.primaryTextColor))
|
||||
if let range = rawTitleString.ranges.first {
|
||||
titleStringValue.addAttribute(.foregroundColor, value: item.theme.rootController.navigationBar.accentTextColor, range: range.range)
|
||||
}
|
||||
titleString = titleStringValue
|
||||
|
||||
textString = NSAttributedString(string: item.strings.ChatList_StorageHintText, font: textFont, textColor: item.theme.rootController.navigationBar.secondaryTextColor)
|
||||
case .setupPassword:
|
||||
//TODO:localize
|
||||
titleString = NSAttributedString(string: "Protect Your Account", font: titleFont, textColor: item.theme.rootController.navigationBar.primaryTextColor)
|
||||
textString = NSAttributedString(string: "Set a password that will be required each time you log in with this phone number.", font: textFont, textColor: item.theme.rootController.navigationBar.secondaryTextColor)
|
||||
}
|
||||
|
||||
let titleLayout = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleString, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - sideInset - rightInset, height: 100.0)))
|
||||
|
||||
let textLayout = makeTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.strings.ChatList_StorageHintText, font: textFont, textColor: item.theme.rootController.navigationBar.secondaryTextColor), maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - sideInset - rightInset, height: 100.0)))
|
||||
let textLayout = makeTextLayout(TextNodeLayoutArguments(attributedString: textString, maximumNumberOfLines: 5, truncationType: .end, constrainedSize: CGSize(width: params.width - sideInset - rightInset, height: 100.0)))
|
||||
|
||||
let layout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: height), insets: UIEdgeInsets())
|
||||
let layout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: verticalInset * 2.0 + titleLayout.0.size.height + textLayout.0.size.height), insets: UIEdgeInsets())
|
||||
|
||||
return (layout, { [weak self] in
|
||||
if let strongSelf = self {
|
||||
@@ -148,10 +162,10 @@ class ChatListStorageInfoItemNode: ListViewItemNode {
|
||||
strongSelf.separatorNode.frame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - UIScreenPixel), size: CGSize(width: layout.size.width, height: UIScreenPixel))
|
||||
|
||||
let _ = titleLayout.1()
|
||||
strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: sideInset, y: 9.0), size: titleLayout.0.size)
|
||||
strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: sideInset, y: verticalInset), size: titleLayout.0.size)
|
||||
|
||||
let _ = textLayout.1()
|
||||
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: sideInset, y: strongSelf.titleNode.frame.maxY - 0.0), size: textLayout.0.size)
|
||||
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: sideInset, y: strongSelf.titleNode.frame.maxY + spacing), size: textLayout.0.size)
|
||||
|
||||
if let image = strongSelf.arrowNode.image {
|
||||
strongSelf.arrowNode.frame = CGRect(origin: CGPoint(x: layout.size.width - sideInset - image.size.width + 8.0, y: floor((layout.size.height - image.size.height) / 2.0)), size: image.size)
|
||||
|
||||
Reference in New Issue
Block a user