mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Storage management improvements
This commit is contained in:
parent
3566377d68
commit
bf5382c9b4
@ -791,6 +791,7 @@ public protocol SharedAccountContext: AnyObject {
|
|||||||
func makeCreateGroupController(context: AccountContext, peerIds: [PeerId], initialTitle: String?, mode: CreateGroupMode, completion: ((PeerId, @escaping () -> Void) -> Void)?) -> ViewController
|
func makeCreateGroupController(context: AccountContext, peerIds: [PeerId], initialTitle: String?, mode: CreateGroupMode, completion: ((PeerId, @escaping () -> Void) -> Void)?) -> ViewController
|
||||||
func makeChatRecentActionsController(context: AccountContext, peer: Peer, adminPeerId: PeerId?) -> ViewController
|
func makeChatRecentActionsController(context: AccountContext, peer: Peer, adminPeerId: PeerId?) -> ViewController
|
||||||
func makePrivacyAndSecurityController(context: AccountContext) -> ViewController
|
func makePrivacyAndSecurityController(context: AccountContext) -> ViewController
|
||||||
|
func makeStorageManagementController(context: AccountContext) -> ViewController
|
||||||
func navigateToChatController(_ params: NavigateToChatControllerParams)
|
func navigateToChatController(_ params: NavigateToChatControllerParams)
|
||||||
func navigateToForumChannel(context: AccountContext, peerId: EnginePeer.Id, navigationController: NavigationController)
|
func navigateToForumChannel(context: AccountContext, peerId: EnginePeer.Id, navigationController: NavigationController)
|
||||||
func navigateToForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, messageId: EngineMessage.Id?, navigationController: NavigationController, activateInput: ChatControllerActivateInput?, keepStack: NavigateToChatKeepStack) -> Signal<Never, NoError>
|
func navigateToForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, messageId: EngineMessage.Id?, navigationController: NavigationController, activateInput: ChatControllerActivateInput?, keepStack: NavigateToChatKeepStack) -> Signal<Never, NoError>
|
||||||
|
@ -185,7 +185,7 @@ private final class ChatListShimmerNode: ASDisplayNode {
|
|||||||
let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
||||||
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in }, activateChatPreview: { _, _, _, gesture, _ in
|
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in }, activateChatPreview: { _, _, _, gesture, _ in
|
||||||
gesture?.cancel()
|
gesture?.cancel()
|
||||||
}, present: { _ in }, openForumThread: { _, _ in })
|
}, present: { _ in }, openForumThread: { _, _ in }, openStorageManagement: {})
|
||||||
interaction.isInlineMode = isInlineMode
|
interaction.isInlineMode = isInlineMode
|
||||||
|
|
||||||
let items = (0 ..< 2).map { _ -> ChatListItem in
|
let items = (0 ..< 2).map { _ -> ChatListItem in
|
||||||
|
@ -2004,6 +2004,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
interaction.openPeer(peer, peer, threadId, false)
|
interaction.openPeer(peer, peer, threadId, false)
|
||||||
self.listNode.clearHighlightAnimated(true)
|
self.listNode.clearHighlightAnimated(true)
|
||||||
})
|
})
|
||||||
|
}, openStorageManagement: {
|
||||||
})
|
})
|
||||||
chatListInteraction.isSearchMode = true
|
chatListInteraction.isSearchMode = true
|
||||||
|
|
||||||
@ -3199,7 +3200,7 @@ private final class ChatListSearchShimmerNode: ASDisplayNode {
|
|||||||
let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in
|
||||||
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in }, activateChatPreview: { _, _, _, gesture, _ in
|
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in }, activateChatPreview: { _, _, _, gesture, _ in
|
||||||
gesture?.cancel()
|
gesture?.cancel()
|
||||||
}, present: { _ in }, openForumThread: { _, _ in })
|
}, present: { _ in }, openForumThread: { _, _ in }, openStorageManagement: {})
|
||||||
var isInlineMode = false
|
var isInlineMode = false
|
||||||
if case .topics = key {
|
if case .topics = key {
|
||||||
isInlineMode = false
|
isInlineMode = false
|
||||||
|
@ -91,6 +91,7 @@ public final class ChatListNodeInteraction {
|
|||||||
let activateChatPreview: (ChatListItem, Int64?, ASDisplayNode, ContextGesture?, CGPoint?) -> Void
|
let activateChatPreview: (ChatListItem, Int64?, ASDisplayNode, ContextGesture?, CGPoint?) -> Void
|
||||||
let present: (ViewController) -> Void
|
let present: (ViewController) -> Void
|
||||||
let openForumThread: (EnginePeer.Id, Int64) -> Void
|
let openForumThread: (EnginePeer.Id, Int64) -> Void
|
||||||
|
let openStorageManagement: () -> Void
|
||||||
|
|
||||||
public var searchTextHighightState: String?
|
public var searchTextHighightState: String?
|
||||||
var highlightedChatLocation: ChatListHighlightedLocation?
|
var highlightedChatLocation: ChatListHighlightedLocation?
|
||||||
@ -132,7 +133,8 @@ public final class ChatListNodeInteraction {
|
|||||||
hidePsa: @escaping (EnginePeer.Id) -> Void,
|
hidePsa: @escaping (EnginePeer.Id) -> Void,
|
||||||
activateChatPreview: @escaping (ChatListItem, Int64?, ASDisplayNode, ContextGesture?, CGPoint?) -> Void,
|
activateChatPreview: @escaping (ChatListItem, Int64?, ASDisplayNode, ContextGesture?, CGPoint?) -> Void,
|
||||||
present: @escaping (ViewController) -> Void,
|
present: @escaping (ViewController) -> Void,
|
||||||
openForumThread: @escaping (EnginePeer.Id, Int64) -> Void
|
openForumThread: @escaping (EnginePeer.Id, Int64) -> Void,
|
||||||
|
openStorageManagement: @escaping () -> Void
|
||||||
) {
|
) {
|
||||||
self.activateSearch = activateSearch
|
self.activateSearch = activateSearch
|
||||||
self.peerSelected = peerSelected
|
self.peerSelected = peerSelected
|
||||||
@ -162,6 +164,7 @@ public final class ChatListNodeInteraction {
|
|||||||
self.animationCache = animationCache
|
self.animationCache = animationCache
|
||||||
self.animationRenderer = animationRenderer
|
self.animationRenderer = animationRenderer
|
||||||
self.openForumThread = openForumThread
|
self.openForumThread = openForumThread
|
||||||
|
self.openStorageManagement = openStorageManagement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -567,6 +570,10 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
), directionHint: entry.directionHint)
|
), directionHint: entry.directionHint)
|
||||||
case let .ArchiveIntro(presentationData):
|
case let .ArchiveIntro(presentationData):
|
||||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListArchiveInfoItem(theme: presentationData.theme, strings: presentationData.strings), directionHint: entry.directionHint)
|
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()
|
||||||
|
}), directionHint: entry.directionHint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -778,6 +785,10 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
), directionHint: entry.directionHint)
|
), directionHint: entry.directionHint)
|
||||||
case let .ArchiveIntro(presentationData):
|
case let .ArchiveIntro(presentationData):
|
||||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListArchiveInfoItem(theme: presentationData.theme, strings: presentationData.strings), directionHint: entry.directionHint)
|
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()
|
||||||
|
}), directionHint: entry.directionHint)
|
||||||
case .HeaderEntry:
|
case .HeaderEntry:
|
||||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListEmptyHeaderItem(), directionHint: entry.directionHint)
|
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListEmptyHeaderItem(), directionHint: entry.directionHint)
|
||||||
case let .AdditionalCategory(index: _, id, title, image, appearance, selected, presentationData):
|
case let .AdditionalCategory(index: _, id, title, image, appearance, selected, presentationData):
|
||||||
@ -1258,6 +1269,12 @@ public final class ChatListNode: ListView {
|
|||||||
}
|
}
|
||||||
self.peerSelected?(peer, threadId, true, true, nil)
|
self.peerSelected?(peer, threadId, true, true, nil)
|
||||||
})
|
})
|
||||||
|
}, openStorageManagement: { [weak self] in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let controller = self.context.sharedContext.makeStorageManagementController(context: self.context)
|
||||||
|
self.push?(controller)
|
||||||
})
|
})
|
||||||
nodeInteraction.isInlineMode = isInlineMode
|
nodeInteraction.isInlineMode = isInlineMode
|
||||||
|
|
||||||
@ -1323,15 +1340,94 @@ public final class ChatListNode: ListView {
|
|||||||
displayArchiveIntro = .single(false)
|
displayArchiveIntro = .single(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let storageInfo: Signal<Double?, NoError>
|
||||||
|
if case .chatList(groupId: .root) = location, chatListFilter == nil {
|
||||||
|
let storageBox = context.account.postbox.mediaBox.storageBox
|
||||||
|
storageInfo = storageBox.totalSize()
|
||||||
|
|> take(1)
|
||||||
|
|> mapToSignal { initialSize -> Signal<Double?, NoError> in
|
||||||
|
let fractionLimit: Double = 0.3
|
||||||
|
|
||||||
|
let systemAttributes = try? FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory() as String)
|
||||||
|
let deviceFreeSpace = (systemAttributes?[FileAttributeKey.systemFreeSize] as? NSNumber)?.int64Value ?? 0
|
||||||
|
|
||||||
|
let initialFraction: Double
|
||||||
|
if deviceFreeSpace != 0 && initialSize != 0 {
|
||||||
|
initialFraction = Double(initialSize) / Double(deviceFreeSpace + initialSize)
|
||||||
|
} else {
|
||||||
|
initialFraction = 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
let initialReportSize: Double?
|
||||||
|
if initialFraction > fractionLimit {
|
||||||
|
initialReportSize = Double(initialSize)
|
||||||
|
} else {
|
||||||
|
initialReportSize = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
final class ReportState {
|
||||||
|
var lastSize: Int64
|
||||||
|
|
||||||
|
init(lastSize: Int64) {
|
||||||
|
self.lastSize = lastSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let state = Atomic(value: ReportState(lastSize: initialSize))
|
||||||
|
let updatedReportSize: Signal<Double?, NoError> = Signal { subscriber in
|
||||||
|
let disposable = storageBox.totalSize().start(next: { size in
|
||||||
|
let updatedSize = state.with { state -> Int64 in
|
||||||
|
if abs(initialSize - size) > 50 * 1024 * 1024 {
|
||||||
|
state.lastSize = size
|
||||||
|
return size
|
||||||
|
} else {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if updatedSize >= 0 {
|
||||||
|
let deviceFreeSpace = (systemAttributes?[FileAttributeKey.systemFreeSize] as? NSNumber)?.int64Value ?? 0
|
||||||
|
|
||||||
|
let updatedFraction: Double
|
||||||
|
if deviceFreeSpace != 0 && updatedSize != 0 {
|
||||||
|
updatedFraction = Double(updatedSize) / Double(deviceFreeSpace + updatedSize)
|
||||||
|
} else {
|
||||||
|
updatedFraction = 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
let updatedReportSize: Double?
|
||||||
|
if updatedFraction > fractionLimit {
|
||||||
|
updatedReportSize = Double(updatedSize)
|
||||||
|
} else {
|
||||||
|
updatedReportSize = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
subscriber.putNext(updatedReportSize)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return ActionDisposable {
|
||||||
|
disposable.dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return .single(initialReportSize)
|
||||||
|
|> then(
|
||||||
|
updatedReportSize
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
storageInfo = .single(nil)
|
||||||
|
}
|
||||||
|
|
||||||
let currentPeerId: EnginePeer.Id = context.account.peerId
|
let currentPeerId: EnginePeer.Id = context.account.peerId
|
||||||
|
|
||||||
let chatListNodeViewTransition = combineLatest(queue: viewProcessingQueue, hideArchivedFolderByDefault, displayArchiveIntro, savedMessagesPeer, chatListViewUpdate, self.statePromise.get())
|
let chatListNodeViewTransition = combineLatest(queue: viewProcessingQueue, hideArchivedFolderByDefault, displayArchiveIntro, storageInfo, savedMessagesPeer, chatListViewUpdate, self.statePromise.get())
|
||||||
|> mapToQueue { (hideArchivedFolderByDefault, displayArchiveIntro, savedMessagesPeer, updateAndFilter, state) -> Signal<ChatListNodeListViewTransition, NoError> in
|
|> mapToQueue { (hideArchivedFolderByDefault, displayArchiveIntro, storageInfo, savedMessagesPeer, updateAndFilter, state) -> Signal<ChatListNodeListViewTransition, NoError> in
|
||||||
let (update, filter) = updateAndFilter
|
let (update, filter) = updateAndFilter
|
||||||
|
|
||||||
let previousHideArchivedFolderByDefaultValue = previousHideArchivedFolderByDefault.swap(hideArchivedFolderByDefault)
|
let previousHideArchivedFolderByDefaultValue = previousHideArchivedFolderByDefault.swap(hideArchivedFolderByDefault)
|
||||||
|
|
||||||
let (rawEntries, isLoading) = chatListNodeEntriesForView(update.list, state: state, savedMessagesPeer: savedMessagesPeer, foundPeers: state.foundPeers, hideArchivedFolderByDefault: hideArchivedFolderByDefault, displayArchiveIntro: displayArchiveIntro, mode: mode, chatListLocation: location)
|
let (rawEntries, isLoading) = chatListNodeEntriesForView(update.list, state: state, savedMessagesPeer: savedMessagesPeer, foundPeers: state.foundPeers, hideArchivedFolderByDefault: hideArchivedFolderByDefault, displayArchiveIntro: displayArchiveIntro, storageInfo: storageInfo, mode: mode, chatListLocation: location)
|
||||||
let entries = rawEntries.filter { entry in
|
let entries = rawEntries.filter { entry in
|
||||||
switch entry {
|
switch entry {
|
||||||
case let .PeerEntry(peerEntry):
|
case let .PeerEntry(peerEntry):
|
||||||
@ -2361,7 +2457,7 @@ public final class ChatListNode: ListView {
|
|||||||
} else {
|
} else {
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
case .ArchiveIntro, .HeaderEntry, .AdditionalCategory:
|
case .ArchiveIntro, .StorageInfo, .HeaderEntry, .AdditionalCategory:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ enum ChatListNodeEntryId: Hashable {
|
|||||||
case ThreadId(Int64)
|
case ThreadId(Int64)
|
||||||
case GroupId(EngineChatList.Group)
|
case GroupId(EngineChatList.Group)
|
||||||
case ArchiveIntro
|
case ArchiveIntro
|
||||||
|
case StorageInfo
|
||||||
case additionalCategory(Int)
|
case additionalCategory(Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,6 +235,7 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
|||||||
case HoleEntry(EngineMessage.Index, theme: PresentationTheme)
|
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 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 ArchiveIntro(presentationData: ChatListPresentationData)
|
||||||
|
case StorageInfo(presentationData: ChatListPresentationData, sizeFraction: Double)
|
||||||
case AdditionalCategory(index: Int, id: Int, title: String, image: UIImage?, appearance: ChatListNodeAdditionalCategory.Appearance, selected: Bool, presentationData: ChatListPresentationData)
|
case AdditionalCategory(index: Int, id: Int, title: String, image: UIImage?, appearance: ChatListNodeAdditionalCategory.Appearance, selected: Bool, presentationData: ChatListPresentationData)
|
||||||
|
|
||||||
var sortIndex: ChatListNodeEntrySortIndex {
|
var sortIndex: ChatListNodeEntrySortIndex {
|
||||||
@ -248,6 +250,8 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
|||||||
return .index(index)
|
return .index(index)
|
||||||
case .ArchiveIntro:
|
case .ArchiveIntro:
|
||||||
return .index(.chatList(EngineChatList.Item.Index.ChatList.absoluteUpperBound.successor))
|
return .index(.chatList(EngineChatList.Item.Index.ChatList.absoluteUpperBound.successor))
|
||||||
|
case .StorageInfo:
|
||||||
|
return .index(.chatList(EngineChatList.Item.Index.ChatList.absoluteUpperBound.successor.successor))
|
||||||
case let .AdditionalCategory(index, _, _, _, _, _, _):
|
case let .AdditionalCategory(index, _, _, _, _, _, _):
|
||||||
return .additionalCategory(index)
|
return .additionalCategory(index)
|
||||||
}
|
}
|
||||||
@ -270,6 +274,8 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
|||||||
return .GroupId(groupId)
|
return .GroupId(groupId)
|
||||||
case .ArchiveIntro:
|
case .ArchiveIntro:
|
||||||
return .ArchiveIntro
|
return .ArchiveIntro
|
||||||
|
case .StorageInfo:
|
||||||
|
return .StorageInfo
|
||||||
case let .AdditionalCategory(_, id, _, _, _, _, _):
|
case let .AdditionalCategory(_, id, _, _, _, _, _):
|
||||||
return .additionalCategory(id)
|
return .additionalCategory(id)
|
||||||
}
|
}
|
||||||
@ -342,6 +348,18 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
case let .StorageInfo(lhsPresentationData, lhsInfo):
|
||||||
|
if case let .StorageInfo(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):
|
case let .AdditionalCategory(lhsIndex, lhsId, lhsTitle, lhsImage, lhsAppearance, lhsSelected, lhsPresentationData):
|
||||||
if case let .AdditionalCategory(rhsIndex, rhsId, rhsTitle, rhsImage, rhsAppearance, rhsSelected, rhsPresentationData) = rhs {
|
if case let .AdditionalCategory(rhsIndex, rhsId, rhsTitle, rhsImage, rhsAppearance, rhsSelected, rhsPresentationData) = rhs {
|
||||||
if lhsIndex != rhsIndex {
|
if lhsIndex != rhsIndex {
|
||||||
@ -381,7 +399,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, 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?, mode: ChatListNodeMode, chatListLocation: ChatListControllerLocation) -> (entries: [ChatListNodeEntry], loading: Bool) {
|
||||||
var result: [ChatListNodeEntry] = []
|
var result: [ChatListNodeEntry] = []
|
||||||
|
|
||||||
var pinnedIndexOffset: UInt16 = 0
|
var pinnedIndexOffset: UInt16 = 0
|
||||||
@ -643,6 +661,9 @@ func chatListNodeEntriesForView(_ view: EngineChatList, state: ChatListNodeState
|
|||||||
if displayArchiveIntro {
|
if displayArchiveIntro {
|
||||||
result.append(.ArchiveIntro(presentationData: state.presentationData))
|
result.append(.ArchiveIntro(presentationData: state.presentationData))
|
||||||
}
|
}
|
||||||
|
if let storageInfo {
|
||||||
|
result.append(.StorageInfo(presentationData: state.presentationData, sizeFraction: storageInfo))
|
||||||
|
}
|
||||||
|
|
||||||
result.append(.HeaderEntry)
|
result.append(.HeaderEntry)
|
||||||
}
|
}
|
||||||
|
164
submodules/ChatListUI/Sources/Node/ChatListStorageInfoItem.swift
Normal file
164
submodules/ChatListUI/Sources/Node/ChatListStorageInfoItem.swift
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
import AsyncDisplayKit
|
||||||
|
import Postbox
|
||||||
|
import Display
|
||||||
|
import SwiftSignalKit
|
||||||
|
import TelegramPresentationData
|
||||||
|
import ListSectionHeaderNode
|
||||||
|
import AppBundle
|
||||||
|
|
||||||
|
class ChatListStorageInfoItem: ListViewItem {
|
||||||
|
let theme: PresentationTheme
|
||||||
|
let strings: PresentationStrings
|
||||||
|
let sizeFraction: Double
|
||||||
|
let action: () -> Void
|
||||||
|
|
||||||
|
let selectable: Bool = true
|
||||||
|
|
||||||
|
init(theme: PresentationTheme, strings: PresentationStrings, sizeFraction: Double, action: @escaping () -> Void) {
|
||||||
|
self.theme = theme
|
||||||
|
self.strings = strings
|
||||||
|
self.sizeFraction = sizeFraction
|
||||||
|
self.action = action
|
||||||
|
}
|
||||||
|
|
||||||
|
func selected(listView: ListView) {
|
||||||
|
listView.clearHighlightAnimated(true)
|
||||||
|
|
||||||
|
self.action()
|
||||||
|
}
|
||||||
|
|
||||||
|
func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
|
||||||
|
async {
|
||||||
|
let node = ChatListStorageInfoItemNode()
|
||||||
|
|
||||||
|
let (nodeLayout, apply) = node.asyncLayout()(self, params, false)
|
||||||
|
|
||||||
|
node.insets = nodeLayout.insets
|
||||||
|
node.contentSize = nodeLayout.contentSize
|
||||||
|
|
||||||
|
Queue.mainQueue().async {
|
||||||
|
completion(node, {
|
||||||
|
return (nil, { _ in
|
||||||
|
apply()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) {
|
||||||
|
Queue.mainQueue().async {
|
||||||
|
assert(node() is ChatListStorageInfoItemNode)
|
||||||
|
if let nodeValue = node() as? ChatListStorageInfoItemNode {
|
||||||
|
|
||||||
|
let layout = nodeValue.asyncLayout()
|
||||||
|
async {
|
||||||
|
let (nodeLayout, apply) = layout(self, params, nextItem == nil)
|
||||||
|
Queue.mainQueue().async {
|
||||||
|
completion(nodeLayout, { _ in
|
||||||
|
apply()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private let separatorHeight = 1.0 / UIScreen.main.scale
|
||||||
|
|
||||||
|
private let titleFont = Font.semibold(15.0)
|
||||||
|
private let textFont = Font.regular(15.0)
|
||||||
|
|
||||||
|
class ChatListStorageInfoItemNode: ListViewItemNode {
|
||||||
|
private let titleNode: TextNode
|
||||||
|
private let textNode: TextNode
|
||||||
|
private let arrowNode: ASImageNode
|
||||||
|
private let separatorNode: ASDisplayNode
|
||||||
|
|
||||||
|
private var item: ChatListStorageInfoItem?
|
||||||
|
|
||||||
|
required init() {
|
||||||
|
self.titleNode = TextNode()
|
||||||
|
self.textNode = TextNode()
|
||||||
|
self.arrowNode = ASImageNode()
|
||||||
|
self.separatorNode = ASDisplayNode()
|
||||||
|
|
||||||
|
super.init(layerBacked: false, dynamicBounce: false)
|
||||||
|
|
||||||
|
self.addSubnode(self.separatorNode)
|
||||||
|
self.addSubnode(self.titleNode)
|
||||||
|
self.addSubnode(self.textNode)
|
||||||
|
self.addSubnode(self.arrowNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func didLoad() {
|
||||||
|
super.didLoad()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) {
|
||||||
|
let layout = self.asyncLayout()
|
||||||
|
let (_, apply) = layout(item as! ChatListStorageInfoItem, params, nextItem == nil)
|
||||||
|
apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
func asyncLayout() -> (_ item: ChatListStorageInfoItem, _ params: ListViewItemLayoutParams, _ isLast: Bool) -> (ListViewItemNodeLayout, () -> Void) {
|
||||||
|
let previousItem = self.item
|
||||||
|
|
||||||
|
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||||
|
let makeTextLayout = TextNode.asyncLayout(self.textNode)
|
||||||
|
|
||||||
|
return { item, params, last in
|
||||||
|
let baseWidth = params.width - params.leftInset - params.rightInset
|
||||||
|
let _ = baseWidth
|
||||||
|
|
||||||
|
let sideInset: CGFloat = params.leftInset + 16.0
|
||||||
|
let height: CGFloat = 54.0
|
||||||
|
let rightInset: CGFloat = sideInset + 24.0
|
||||||
|
|
||||||
|
let themeUpdated = item.theme !== previousItem?.theme
|
||||||
|
|
||||||
|
//TODO:localize
|
||||||
|
let titleString = NSMutableAttributedString()
|
||||||
|
titleString.append(NSAttributedString(string: "Free up to ", font: titleFont, textColor: item.theme.rootController.navigationBar.primaryTextColor))
|
||||||
|
let sizeString = dataSizeString(Int64(item.sizeFraction), formatting: DataSizeStringFormatting(strings: item.strings, decimalSeparator: "."))
|
||||||
|
titleString.append(NSAttributedString(string: sizeString, font: titleFont, textColor: item.theme.rootController.navigationBar.accentTextColor))
|
||||||
|
|
||||||
|
let titleLayout = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleString, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - sideInset - rightInset, height: 100.0)))
|
||||||
|
|
||||||
|
//TODO:localize
|
||||||
|
let textLayout = makeTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "Clear storage space on your iPhone", font: textFont, textColor: item.theme.rootController.navigationBar.secondaryTextColor), maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - sideInset - rightInset, height: 100.0)))
|
||||||
|
|
||||||
|
let layout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: height), insets: UIEdgeInsets())
|
||||||
|
|
||||||
|
return (layout, { [weak self] in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.item = item
|
||||||
|
|
||||||
|
if themeUpdated {
|
||||||
|
strongSelf.backgroundColor = item.theme.chatList.pinnedItemBackgroundColor
|
||||||
|
strongSelf.separatorNode.backgroundColor = item.theme.chatList.itemSeparatorColor
|
||||||
|
strongSelf.arrowNode.image = PresentationResourcesItemList.disclosureArrowImage(item.theme)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
let _ = textLayout.1()
|
||||||
|
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: sideInset, y: strongSelf.titleNode.frame.maxY - 0.0), 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
strongSelf.contentSize = layout.contentSize
|
||||||
|
strongSelf.insets = layout.insets
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -91,6 +91,7 @@ public final class HashtagSearchController: TelegramBaseController {
|
|||||||
gesture?.cancel()
|
gesture?.cancel()
|
||||||
}, present: { _ in
|
}, present: { _ in
|
||||||
}, openForumThread: { _, _ in
|
}, openForumThread: { _, _ in
|
||||||
|
}, openStorageManagement: {
|
||||||
})
|
})
|
||||||
|
|
||||||
let previousSearchItems = Atomic<[ChatListSearchEntry]?>(value: nil)
|
let previousSearchItems = Atomic<[ChatListSearchEntry]?>(value: nil)
|
||||||
|
@ -158,6 +158,9 @@ public final class StorageBox {
|
|||||||
let contentTypeStatsTable: ValueBoxTable
|
let contentTypeStatsTable: ValueBoxTable
|
||||||
let metadataTable: ValueBoxTable
|
let metadataTable: ValueBoxTable
|
||||||
|
|
||||||
|
let totalSizeSubscribers = Bag<(Int64) -> Void>()
|
||||||
|
private var totalSize: Int64 = 0
|
||||||
|
|
||||||
init(queue: Queue, logger: StorageBox.Logger, basePath: String) {
|
init(queue: Queue, logger: StorageBox.Logger, basePath: String) {
|
||||||
self.queue = queue
|
self.queue = queue
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
@ -183,6 +186,8 @@ public final class StorageBox {
|
|||||||
self.metadataTable = ValueBoxTable(id: 21, keyType: .binary, compactValuesOnCreation: true)
|
self.metadataTable = ValueBoxTable(id: 21, keyType: .binary, compactValuesOnCreation: true)
|
||||||
|
|
||||||
self.performUpdatesIfNeeded()
|
self.performUpdatesIfNeeded()
|
||||||
|
|
||||||
|
self.updateTotalSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func performUpdatesIfNeeded() {
|
private func performUpdatesIfNeeded() {
|
||||||
@ -230,6 +235,35 @@ public final class StorageBox {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateTotalSize() {
|
||||||
|
self.valueBox.begin()
|
||||||
|
|
||||||
|
var totalSize: Int64 = 0
|
||||||
|
self.valueBox.scan(self.contentTypeStatsTable, values: { key, value in
|
||||||
|
var size: Int64 = 0
|
||||||
|
value.read(&size, offset: 0, length: 8)
|
||||||
|
totalSize += size
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
self.valueBox.commit()
|
||||||
|
|
||||||
|
if self.totalSize != totalSize {
|
||||||
|
self.totalSize = totalSize
|
||||||
|
|
||||||
|
for f in self.totalSizeSubscribers.copyItems() {
|
||||||
|
f(totalSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func incrementalUpdateTotalSize() {
|
||||||
|
for f in self.totalSizeSubscribers.copyItems() {
|
||||||
|
f(totalSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func reset() {
|
func reset() {
|
||||||
self.valueBox.begin()
|
self.valueBox.begin()
|
||||||
|
|
||||||
@ -241,6 +275,8 @@ public final class StorageBox {
|
|||||||
self.valueBox.removeAllFromTable(self.metadataTable)
|
self.valueBox.removeAllFromTable(self.metadataTable)
|
||||||
|
|
||||||
self.valueBox.commit()
|
self.valueBox.commit()
|
||||||
|
|
||||||
|
self.updateTotalSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func internalAddSize(contentType: UInt8, delta: Int64) {
|
private func internalAddSize(contentType: UInt8, delta: Int64) {
|
||||||
@ -260,6 +296,8 @@ public final class StorageBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.valueBox.set(self.contentTypeStatsTable, key: key, value: MemoryBuffer(memory: ¤tSize, capacity: 8, length: 8, freeWhenDone: false))
|
self.valueBox.set(self.contentTypeStatsTable, key: key, value: MemoryBuffer(memory: ¤tSize, capacity: 8, length: 8, freeWhenDone: false))
|
||||||
|
|
||||||
|
self.totalSize += delta
|
||||||
}
|
}
|
||||||
|
|
||||||
private func internalAddSize(peerId: Int64, contentType: UInt8, delta: Int64) {
|
private func internalAddSize(peerId: Int64, contentType: UInt8, delta: Int64) {
|
||||||
@ -390,6 +428,8 @@ public final class StorageBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.valueBox.commit()
|
self.valueBox.commit()
|
||||||
|
|
||||||
|
self.incrementalUpdateTotalSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func peerIdsReferencing(hashId: HashId) -> Set<Int64> {
|
private func peerIdsReferencing(hashId: HashId) -> Set<Int64> {
|
||||||
@ -435,6 +475,8 @@ public final class StorageBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.valueBox.commit()
|
self.valueBox.commit()
|
||||||
|
|
||||||
|
self.incrementalUpdateTotalSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
func addEmptyReferencesIfNotReferenced(ids: [(id: Data, size: Int64)], contentType: UInt8) -> Int {
|
func addEmptyReferencesIfNotReferenced(ids: [(id: Data, size: Int64)], contentType: UInt8) -> Int {
|
||||||
@ -508,6 +550,8 @@ public final class StorageBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.valueBox.commit()
|
self.valueBox.commit()
|
||||||
|
|
||||||
|
self.incrementalUpdateTotalSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
func allPeerIds() -> [PeerId] {
|
func allPeerIds() -> [PeerId] {
|
||||||
@ -615,6 +659,22 @@ public final class StorageBox {
|
|||||||
return (ids, nextId)
|
return (ids, nextId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func subscribeTotalSize(next: @escaping (Int64) -> Void) -> Disposable {
|
||||||
|
let index = self.totalSizeSubscribers.add(next)
|
||||||
|
|
||||||
|
next(self.totalSize)
|
||||||
|
|
||||||
|
let queue = self.queue
|
||||||
|
return ActionDisposable { [weak self] in
|
||||||
|
queue.async {
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.totalSizeSubscribers.remove(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func all() -> [Entry] {
|
func all() -> [Entry] {
|
||||||
var result: [Entry] = []
|
var result: [Entry] = []
|
||||||
|
|
||||||
@ -825,6 +885,8 @@ public final class StorageBox {
|
|||||||
|
|
||||||
self.valueBox.commit()
|
self.valueBox.commit()
|
||||||
|
|
||||||
|
self.incrementalUpdateTotalSize()
|
||||||
|
|
||||||
return Array(resultIds)
|
return Array(resultIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -854,6 +916,8 @@ public final class StorageBox {
|
|||||||
|
|
||||||
self.valueBox.commit()
|
self.valueBox.commit()
|
||||||
|
|
||||||
|
self.incrementalUpdateTotalSize()
|
||||||
|
|
||||||
return Array(resultIds)
|
return Array(resultIds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -973,4 +1037,12 @@ public final class StorageBox {
|
|||||||
return EmptyDisposable
|
return EmptyDisposable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func totalSize() -> Signal<Int64, NoError> {
|
||||||
|
return self.impl.signalWith { impl, subscriber in
|
||||||
|
return impl.subscribeTotalSize(next: { value in
|
||||||
|
subscriber.putNext(value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -598,7 +598,6 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
|
|||||||
pushControllerImpl?(StorageUsageScreen(context: context, makeStorageUsageExceptionsScreen: { category in
|
pushControllerImpl?(StorageUsageScreen(context: context, makeStorageUsageExceptionsScreen: { category in
|
||||||
return storageUsageExceptionsScreen(context: context, category: category)
|
return storageUsageExceptionsScreen(context: context, category: category)
|
||||||
}))
|
}))
|
||||||
//pushControllerImpl?(storageUsageController(context: context, cacheUsagePromise: cacheUsagePromise))
|
|
||||||
}, openNetworkUsage: {
|
}, openNetworkUsage: {
|
||||||
pushControllerImpl?(networkUsageStatsController(context: context))
|
pushControllerImpl?(networkUsageStatsController(context: context))
|
||||||
}, openProxy: {
|
}, openProxy: {
|
||||||
|
@ -222,7 +222,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
|
|||||||
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in
|
}, messageSelected: { _, _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, setPeerThreadMuted: { _, _, _ in }, deletePeer: { _, _ in }, deletePeerThread: { _, _ in }, setPeerThreadStopped: { _, _, _ in }, setPeerThreadPinned: { _, _, _ in }, setPeerThreadHidden: { _, _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, toggleThreadsSelection: { _, _ in }, hidePsa: { _ in
|
||||||
}, activateChatPreview: { _, _, _, gesture, _ in
|
}, activateChatPreview: { _, _, _, gesture, _ in
|
||||||
gesture?.cancel()
|
gesture?.cancel()
|
||||||
}, present: { _ in }, openForumThread: { _, _ in })
|
}, present: { _ in }, openForumThread: { _, _ in }, openStorageManagement: {})
|
||||||
|
|
||||||
let chatListPresentationData = ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true)
|
let chatListPresentationData = ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true)
|
||||||
|
|
||||||
|
@ -843,7 +843,8 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
}, activateChatPreview: { _, _, _, gesture, _ in
|
}, activateChatPreview: { _, _, _, gesture, _ in
|
||||||
gesture?.cancel()
|
gesture?.cancel()
|
||||||
}, present: { _ in
|
}, present: { _ in
|
||||||
}, openForumThread: { _, _ in })
|
}, openForumThread: { _, _ in },
|
||||||
|
openStorageManagement: {})
|
||||||
let chatListPresentationData = ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true)
|
let chatListPresentationData = ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true)
|
||||||
|
|
||||||
func makeChatListItem(
|
func makeChatListItem(
|
||||||
|
@ -367,7 +367,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
}, activateChatPreview: { _, _, _, gesture, _ in
|
}, activateChatPreview: { _, _, _, gesture, _ in
|
||||||
gesture?.cancel()
|
gesture?.cancel()
|
||||||
}, present: { _ in
|
}, present: { _ in
|
||||||
}, openForumThread: { _, _ in })
|
}, openForumThread: { _, _ in }, openStorageManagement: {})
|
||||||
|
|
||||||
func makeChatListItem(
|
func makeChatListItem(
|
||||||
peer: EnginePeer,
|
peer: EnginePeer,
|
||||||
|
@ -351,6 +351,7 @@ swift_library(
|
|||||||
"//submodules/TelegramUI/Components/ChatListHeaderComponent",
|
"//submodules/TelegramUI/Components/ChatListHeaderComponent",
|
||||||
"//submodules/TelegramUI/Components/ChatInputNode",
|
"//submodules/TelegramUI/Components/ChatInputNode",
|
||||||
"//submodules/TelegramUI/Components/ChatEntityKeyboardInputNode",
|
"//submodules/TelegramUI/Components/ChatEntityKeyboardInputNode",
|
||||||
|
"//submodules/TelegramUI/Components/StorageUsageScreen",
|
||||||
"//submodules/MediaPasteboardUI:MediaPasteboardUI",
|
"//submodules/MediaPasteboardUI:MediaPasteboardUI",
|
||||||
"//submodules/DrawingUI:DrawingUI",
|
"//submodules/DrawingUI:DrawingUI",
|
||||||
"//submodules/FeaturedStickersScreen:FeaturedStickersScreen",
|
"//submodules/FeaturedStickersScreen:FeaturedStickersScreen",
|
||||||
|
@ -1163,11 +1163,11 @@ final class PieChartComponent: Component {
|
|||||||
let fractionValue: Double = floor(item.displayValue * 100.0 * 10.0) / 10.0
|
let fractionValue: Double = floor(item.displayValue * 100.0 * 10.0) / 10.0
|
||||||
let fractionString: String
|
let fractionString: String
|
||||||
if fractionValue < 0.1 {
|
if fractionValue < 0.1 {
|
||||||
fractionString = "<0.1"
|
fractionString = "<0.1%"
|
||||||
} else if abs(Double(Int(fractionValue)) - fractionValue) < 0.001 {
|
} else if abs(Double(Int(fractionValue)) - fractionValue) < 0.001 {
|
||||||
fractionString = "\(Int(fractionValue))"
|
fractionString = "\(Int(fractionValue))%"
|
||||||
} else {
|
} else {
|
||||||
fractionString = "\(fractionValue)"
|
fractionString = "\(fractionValue)%"
|
||||||
}
|
}
|
||||||
|
|
||||||
let tooltipSize = tooltip.update(
|
let tooltipSize = tooltip.update(
|
||||||
|
@ -262,6 +262,7 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDe
|
|||||||
}
|
}
|
||||||
}, present: { _ in
|
}, present: { _ in
|
||||||
}, openForumThread: { _, _ in
|
}, openForumThread: { _, _ in
|
||||||
|
}, openStorageManagement: {
|
||||||
})
|
})
|
||||||
interaction.searchTextHighightState = searchQuery
|
interaction.searchTextHighightState = searchQuery
|
||||||
self.interaction = interaction
|
self.interaction = interaction
|
||||||
|
@ -29,6 +29,7 @@ import PremiumUI
|
|||||||
import StickerPackPreviewUI
|
import StickerPackPreviewUI
|
||||||
import ChatControllerInteraction
|
import ChatControllerInteraction
|
||||||
import ChatPresentationInterfaceState
|
import ChatPresentationInterfaceState
|
||||||
|
import StorageUsageScreen
|
||||||
|
|
||||||
private final class AccountUserInterfaceInUseContext {
|
private final class AccountUserInterfaceInUseContext {
|
||||||
let subscribers = Bag<(Bool) -> Void>()
|
let subscribers = Bag<(Bool) -> Void>()
|
||||||
@ -1424,6 +1425,15 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
return SettingsUI.makePrivacyAndSecurityController(context: context)
|
return SettingsUI.makePrivacyAndSecurityController(context: context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func makeStorageManagementController(context: AccountContext) -> ViewController {
|
||||||
|
return StorageUsageScreen(context: context, makeStorageUsageExceptionsScreen: { [weak context] category in
|
||||||
|
guard let context else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return storageUsageExceptionsScreen(context: context, category: category)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
public func makePremiumIntroController(context: AccountContext, source: PremiumIntroSource) -> ViewController {
|
public func makePremiumIntroController(context: AccountContext, source: PremiumIntroSource) -> ViewController {
|
||||||
let mappedSource: PremiumSource
|
let mappedSource: PremiumSource
|
||||||
switch source {
|
switch source {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user