Various settings UI improvements

This commit is contained in:
Ilya Laktyushin
2021-10-26 14:57:50 +04:00
parent 8fdc7a8e1e
commit 6b0fb9097b
61 changed files with 3066 additions and 267 deletions

View File

@@ -12,6 +12,7 @@ import TextFormat
import AccountContext
import StickerPackPreviewUI
import ItemListStickerPackItem
import ItemListPeerActionItem
import UndoUI
import ShareController
@@ -28,8 +29,10 @@ private final class InstalledStickerPacksControllerArguments {
let openSuggestOptions: () -> Void
let toggleAnimatedStickers: (Bool) -> Void
let togglePackSelected: (ItemCollectionId) -> Void
let expandTrendingPacks: () -> Void
let addPack: (StickerPackCollectionInfo) -> Void
init(account: Account, openStickerPack: @escaping (StickerPackCollectionInfo) -> Void, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, removePack: @escaping (ArchivedStickerPackItem) -> Void, openStickersBot: @escaping () -> Void, openMasks: @escaping () -> Void, openFeatured: @escaping () -> Void, openArchived: @escaping ([ArchivedStickerPackItem]?) -> Void, openSuggestOptions: @escaping () -> Void, toggleAnimatedStickers: @escaping (Bool) -> Void, togglePackSelected: @escaping (ItemCollectionId) -> Void) {
init(account: Account, openStickerPack: @escaping (StickerPackCollectionInfo) -> Void, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, removePack: @escaping (ArchivedStickerPackItem) -> Void, openStickersBot: @escaping () -> Void, openMasks: @escaping () -> Void, openFeatured: @escaping () -> Void, openArchived: @escaping ([ArchivedStickerPackItem]?) -> Void, openSuggestOptions: @escaping () -> Void, toggleAnimatedStickers: @escaping (Bool) -> Void, togglePackSelected: @escaping (ItemCollectionId) -> Void, expandTrendingPacks: @escaping () -> Void, addPack: @escaping (StickerPackCollectionInfo) -> Void) {
self.account = account
self.openStickerPack = openStickerPack
self.setPackIdWithRevealedOptions = setPackIdWithRevealedOptions
@@ -41,11 +44,14 @@ private final class InstalledStickerPacksControllerArguments {
self.openSuggestOptions = openSuggestOptions
self.toggleAnimatedStickers = toggleAnimatedStickers
self.togglePackSelected = togglePackSelected
self.expandTrendingPacks = expandTrendingPacks
self.addPack = addPack
}
}
private enum InstalledStickerPacksSection: Int32 {
case service
case trending
case stickers
}
@@ -64,6 +70,7 @@ public enum InstalledStickerPacksEntryTag: ItemListItemTag {
private enum InstalledStickerPacksEntryId: Hashable {
case index(Int32)
case trendingPack(ItemCollectionId)
case pack(ItemCollectionId)
}
@@ -74,6 +81,9 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry {
case masks(PresentationTheme, String)
case animatedStickers(PresentationTheme, String, Bool)
case animatedStickersInfo(PresentationTheme, String)
case trendingPacksTitle(PresentationTheme, String)
case trendingPack(Int32, PresentationTheme, PresentationStrings, StickerPackCollectionInfo, StickerPackItem?, String, Bool, Bool, Bool)
case trendingExpand(PresentationTheme, String)
case packsTitle(PresentationTheme, String)
case pack(Int32, PresentationTheme, PresentationStrings, StickerPackCollectionInfo, StickerPackItem?, String, Bool, Bool, ItemListStickerPackItemEditing, Bool?)
case packsInfo(PresentationTheme, String)
@@ -82,6 +92,8 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry {
switch self {
case .suggestOptions, .trending, .masks, .archived, .animatedStickers, .animatedStickersInfo:
return InstalledStickerPacksSection.service.rawValue
case .trendingPacksTitle, .trendingPack, .trendingExpand:
return InstalledStickerPacksSection.trending.rawValue
case .packsTitle, .pack, .packsInfo:
return InstalledStickerPacksSection.stickers.rawValue
}
@@ -101,12 +113,18 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry {
return .index(4)
case .animatedStickersInfo:
return .index(5)
case .packsTitle:
case .trendingPacksTitle:
return .index(6)
case let .trendingPack(_, _, _, info, _, _, _, _, _):
return .trendingPack(info.id)
case .trendingExpand:
return .index(7)
case .packsTitle:
return .index(8)
case let .pack(_, _, _, info, _, _, _, _, _, _):
return .pack(info.id)
case .packsInfo:
return .index(7)
return .index(9)
}
}
@@ -148,12 +166,57 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry {
} else {
return false
}
case let .trendingPacksTitle(lhsTheme, lhsText):
if case let .trendingPacksTitle(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .packsTitle(lhsTheme, lhsText):
if case let .packsTitle(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .trendingPack(lhsIndex, lhsTheme, lhsStrings, lhsInfo, lhsTopItem, lhsCount, lhsAnimatedStickers, lhsUnread, lhsInstalled):
if case let .trendingPack(rhsIndex, rhsTheme, rhsStrings, rhsInfo, rhsTopItem, rhsCount, rhsAnimatedStickers, rhsUnread, rhsInstalled) = rhs {
if lhsIndex != rhsIndex {
return false
}
if lhsTheme !== rhsTheme {
return false
}
if lhsStrings !== rhsStrings {
return false
}
if lhsInfo != rhsInfo {
return false
}
if lhsTopItem != rhsTopItem {
return false
}
if lhsCount != rhsCount {
return false
}
if lhsAnimatedStickers != rhsAnimatedStickers {
return false
}
if lhsUnread != rhsUnread {
return false
}
if lhsInstalled != rhsInstalled {
return false
}
return true
} else {
return false
}
case let .trendingExpand(lhsTheme, lhsText):
if case let .trendingExpand(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .pack(lhsIndex, lhsTheme, lhsStrings, lhsInfo, lhsTopItem, lhsCount, lhsAnimatedStickers, lhsEnabled, lhsEditing, lhsSelected):
if case let .pack(rhsIndex, rhsTheme, rhsStrings, rhsInfo, rhsTopItem, rhsCount, rhsAnimatedStickers, rhsEnabled, rhsEditing, rhsSelected) = rhs {
if lhsIndex != rhsIndex {
@@ -243,9 +306,32 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry {
default:
return true
}
case .trendingPacksTitle:
switch rhs {
case .suggestOptions, .trending, .masks, .archived, .animatedStickers, .animatedStickersInfo, .trendingPacksTitle:
return false
default:
return true
}
case let .trendingPack(lhsIndex, _, _, _, _, _, _, _, _):
switch rhs {
case let .trendingPack(rhsIndex, _, _, _, _, _, _, _, _):
return lhsIndex < rhsIndex
case .trendingExpand, .packsTitle, .pack, .packsInfo:
return true
default:
return false
}
case .trendingExpand:
switch rhs {
case .suggestOptions, .trending, .masks, .archived, .animatedStickers, .animatedStickersInfo, .trendingPacksTitle, .trendingPack, .trendingExpand:
return false
default:
return true
}
case .packsTitle:
switch rhs {
case .suggestOptions, .trending, .masks, .archived, .animatedStickers, .animatedStickersInfo, .packsTitle:
case .suggestOptions, .trending, .masks, .archived, .animatedStickers, .animatedStickersInfo, .trendingPacksTitle, .trendingPack, .trendingExpand, .packsTitle:
return false
default:
return true
@@ -294,6 +380,21 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry {
})
case let .animatedStickersInfo(_, text):
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
case let .trendingPacksTitle(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .trendingPack(_, _, _, info, topItem, count, animatedStickers, unread, installed):
return ItemListStickerPackItem(presentationData: presentationData, account: arguments.account, packInfo: info, itemCount: count, topItem: topItem, unread: unread, control: .installation(installed: installed), editing: ItemListStickerPackItemEditing(editable: false, editing: false, revealed: false, reorderable: false, selectable: false), enabled: true, playAnimatedStickers: animatedStickers, sectionId: self.section, action: {
arguments.openStickerPack(info)
}, setPackIdWithRevealedOptions: { _, _ in
}, addPack: {
arguments.addPack(info)
}, removePack: {
}, toggleSelected: {
})
case let .trendingExpand(theme, text):
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.downArrowImage(theme), title: text, sectionId: self.section, editing: false, action: {
arguments.expandTrendingPacks()
})
case let .packsTitle(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .pack(_, _, _, info, topItem, count, animatedStickers, enabled, editing, selected):
@@ -319,17 +420,20 @@ private struct InstalledStickerPacksControllerState: Equatable {
let editing: Bool
let selectedPackIds: Set<ItemCollectionId>?
let packIdWithRevealedOptions: ItemCollectionId?
let trendingPacksExpanded: Bool
init() {
self.editing = false
self.selectedPackIds = nil
self.packIdWithRevealedOptions = nil
self.trendingPacksExpanded = false
}
init(editing: Bool, selectedPackIds: Set<ItemCollectionId>?, packIdWithRevealedOptions: ItemCollectionId?) {
init(editing: Bool, selectedPackIds: Set<ItemCollectionId>?, packIdWithRevealedOptions: ItemCollectionId?, trendingPacksExpanded: Bool) {
self.editing = editing
self.selectedPackIds = selectedPackIds
self.packIdWithRevealedOptions = packIdWithRevealedOptions
self.trendingPacksExpanded = trendingPacksExpanded
}
static func ==(lhs: InstalledStickerPacksControllerState, rhs: InstalledStickerPacksControllerState) -> Bool {
@@ -342,20 +446,26 @@ private struct InstalledStickerPacksControllerState: Equatable {
if lhs.packIdWithRevealedOptions != rhs.packIdWithRevealedOptions {
return false
}
if lhs.trendingPacksExpanded != rhs.trendingPacksExpanded {
return false
}
return true
}
func withUpdatedEditing(_ editing: Bool) -> InstalledStickerPacksControllerState {
return InstalledStickerPacksControllerState(editing: editing, selectedPackIds: self.selectedPackIds, packIdWithRevealedOptions: self.packIdWithRevealedOptions)
return InstalledStickerPacksControllerState(editing: editing, selectedPackIds: self.selectedPackIds, packIdWithRevealedOptions: self.packIdWithRevealedOptions, trendingPacksExpanded: self.trendingPacksExpanded)
}
func withUpdatedSelectedPackIds(_ selectedPackIds: Set<ItemCollectionId>?) -> InstalledStickerPacksControllerState {
return InstalledStickerPacksControllerState(editing: editing, selectedPackIds: selectedPackIds, packIdWithRevealedOptions: self.packIdWithRevealedOptions)
return InstalledStickerPacksControllerState(editing: editing, selectedPackIds: selectedPackIds, packIdWithRevealedOptions: self.packIdWithRevealedOptions, trendingPacksExpanded: self.trendingPacksExpanded)
}
func withUpdatedPackIdWithRevealedOptions(_ packIdWithRevealedOptions: ItemCollectionId?) -> InstalledStickerPacksControllerState {
return InstalledStickerPacksControllerState(editing: self.editing, selectedPackIds: self.selectedPackIds, packIdWithRevealedOptions: packIdWithRevealedOptions)
return InstalledStickerPacksControllerState(editing: self.editing, selectedPackIds: self.selectedPackIds, packIdWithRevealedOptions: packIdWithRevealedOptions, trendingPacksExpanded: self.trendingPacksExpanded)
}
func withUpdatedTrendingPacksExpanded(_ trendingPacksExpanded: Bool) -> InstalledStickerPacksControllerState {
return InstalledStickerPacksControllerState(editing: self.editing, selectedPackIds: self.selectedPackIds, packIdWithRevealedOptions: self.packIdWithRevealedOptions, trendingPacksExpanded: trendingPacksExpanded)
}
}
@@ -368,9 +478,24 @@ private func namespaceForMode(_ mode: InstalledStickerPacksControllerMode) -> It
}
}
private let maxTrendingPacksDisplayedLimit: Int32 = 3
private func installedStickerPacksControllerEntries(presentationData: PresentationData, state: InstalledStickerPacksControllerState, mode: InstalledStickerPacksControllerMode, view: CombinedView, temporaryPackOrder: [ItemCollectionId]?, featured: [FeaturedStickerPackItem], archived: [ArchivedStickerPackItem]?, stickerSettings: StickerSettings) -> [InstalledStickerPacksEntry] {
var entries: [InstalledStickerPacksEntry] = []
var installedPacks = Set<ItemCollectionId>()
if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [namespaceForMode(mode)])] as? ItemCollectionInfosView {
if let packsEntries = stickerPacksView.entriesByNamespace[namespaceForMode(mode)] {
var sortedPacks: [ItemCollectionInfoEntry] = []
for entry in packsEntries {
if let _ = entry.info as? StickerPackCollectionInfo {
installedPacks.insert(entry.id)
sortedPacks.append(entry)
}
}
}
}
switch mode {
case .general, .modal:
let suggestString: String
@@ -384,15 +509,6 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati
}
entries.append(.suggestOptions(presentationData.theme, presentationData.strings.Stickers_SuggestStickers, suggestString))
if featured.count != 0 {
var unreadCount: Int32 = 0
for item in featured {
if item.unread {
unreadCount += 1
}
}
entries.append(.trending(presentationData.theme, presentationData.strings.StickerPacksSettings_FeaturedPacks, unreadCount))
}
if let archived = archived, !archived.isEmpty {
entries.append(.archived(presentationData.theme, presentationData.strings.StickerPacksSettings_ArchivedPacks, Int32(archived.count), archived))
}
@@ -401,6 +517,28 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati
entries.append(.animatedStickers(presentationData.theme, presentationData.strings.StickerPacksSettings_AnimatedStickers, stickerSettings.loopAnimatedStickers))
entries.append(.animatedStickersInfo(presentationData.theme, presentationData.strings.StickerPacksSettings_AnimatedStickersInfo))
if featured.count > 0 {
entries.append(.trendingPacksTitle(presentationData.theme, presentationData.strings.StickerPacksSettings_FeaturedPacks.uppercased()))
var index: Int32 = 0
var featuredPacks = featured
var effectiveExpanded = state.trendingPacksExpanded
if featuredPacks.count > maxTrendingPacksDisplayedLimit && !effectiveExpanded {
featuredPacks = Array(featuredPacks.prefix(Int(maxTrendingPacksDisplayedLimit)))
} else {
effectiveExpanded = true
}
for featuredPack in featuredPacks {
entries.append(.trendingPack(index, presentationData.theme, presentationData.strings, featuredPack.info, featuredPack.topItems.first, presentationData.strings.StickerPack_StickerCount(featuredPack.info.count), stickerSettings.loopAnimatedStickers, featuredPack.unread, installedPacks.contains(featuredPack.info.id)))
index += 1
}
if !effectiveExpanded {
entries.append(.trendingExpand(presentationData.theme, presentationData.strings.Stickers_ShowMore))
}
}
entries.append(.packsTitle(presentationData.theme, presentationData.strings.StickerPacksSettings_StickerPacksSection))
case .masks:
if let archived = archived, !archived.isEmpty {
@@ -618,6 +756,27 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
return state
}
}
}, expandTrendingPacks: {
updateState { state in
return state.withUpdatedTrendingPacksExpanded(true)
}
}, addPack: { info in
let _ = (context.engine.stickers.loadedStickerPack(reference: .id(id: info.id.id, accessHash: info.accessHash), forceActualized: false)
|> mapToSignal { result -> Signal<Void, NoError> in
switch result {
case let .result(info, items, installed):
if installed {
return .complete()
} else {
return context.engine.stickers.addStickerPackInteractively(info: info, items: items)
}
case .fetching:
break
case .none:
break
}
return .complete()
} |> deliverOnMainQueue).start()
})
let stickerPacks = Promise<CombinedView>()
stickerPacks.set(context.account.postbox.combinedView(keys: [.itemCollectionInfos(namespaces: [namespaceForMode(mode)])]))