Swiftgram/submodules/SettingsUI/Sources/ArchiveSettingsController.swift
2023-07-13 23:51:40 +04:00

217 lines
8.8 KiB
Swift

import Foundation
import UIKit
import Display
import SwiftSignalKit
import TelegramCore
import TelegramPresentationData
import TelegramUIPreferences
import ItemListUI
import PresentationDataUtils
import AccountContext
import UndoUI
private final class ArchiveSettingsControllerArguments {
let updateUnmuted: (Bool) -> Void
let updateFolders: (Bool) -> Void
let updateUnknown: (Bool?) -> Void
init(
updateUnmuted: @escaping (Bool) -> Void,
updateFolders: @escaping (Bool) -> Void,
updateUnknown: @escaping (Bool?) -> Void
) {
self.updateUnmuted = updateUnmuted
self.updateFolders = updateFolders
self.updateUnknown = updateUnknown
}
}
private enum ArchiveSettingsSection: Int32 {
case unmuted
case folders
case unknown
}
private enum ArchiveSettingsControllerEntry: ItemListNodeEntry {
case unmutedHeader
case unmutedValue(Bool)
case unmutedFooter
case foldersHeader
case foldersValue(Bool)
case foldersFooter
case unknownHeader
case unknownValue(isOn: Bool, isLocked: Bool)
case unknownFooter
var section: ItemListSectionId {
switch self {
case .unmutedHeader, .unmutedValue, .unmutedFooter:
return ArchiveSettingsSection.unmuted.rawValue
case .foldersHeader, .foldersValue, .foldersFooter:
return ArchiveSettingsSection.folders.rawValue
case .unknownHeader, .unknownValue, .unknownFooter:
return ArchiveSettingsSection.unknown.rawValue
}
}
var stableId: Int32 {
switch self {
case .unmutedHeader:
return 0
case .unmutedValue:
return 1
case .unmutedFooter:
return 2
case .foldersHeader:
return 3
case .foldersValue:
return 4
case .foldersFooter:
return 5
case .unknownHeader:
return 6
case .unknownValue:
return 7
case .unknownFooter:
return 8
}
}
static func <(lhs: ArchiveSettingsControllerEntry, rhs: ArchiveSettingsControllerEntry) -> Bool {
return lhs.stableId < rhs.stableId
}
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
let arguments = arguments as! ArchiveSettingsControllerArguments
//TODO:localize
switch self {
case .unmutedHeader:
return ItemListSectionHeaderItem(presentationData: presentationData, text: "UNMUTED CHATS", sectionId: self.section)
case let .unmutedValue(value):
return ItemListSwitchItem(presentationData: presentationData, title: "Always Keep Archived", value: value, sectionId: self.section, style: .blocks, updated: { value in
arguments.updateUnmuted(value)
})
case .unmutedFooter:
return ItemListTextItem(presentationData: presentationData, text: .markdown("Keep archived chats in the Archive even if they are unmuted and get a new message."), sectionId: self.section)
case .foldersHeader:
return ItemListSectionHeaderItem(presentationData: presentationData, text: "CHATS FROM FOLDERS", sectionId: self.section)
case let .foldersValue(value):
return ItemListSwitchItem(presentationData: presentationData, title: "Always Keep Archived", value: value, sectionId: self.section, style: .blocks, updated: { value in
arguments.updateFolders(value)
})
case .foldersFooter:
return ItemListTextItem(presentationData: presentationData, text: .markdown("Keep archived chats from folders in the Archive even if they are unmuted and get a new message."), sectionId: self.section)
case .unknownHeader:
return ItemListSectionHeaderItem(presentationData: presentationData, text: "NEW CHATS FROM UNKNOWN USERS", sectionId: self.section)
case let .unknownValue(isOn, isLocked):
return ItemListSwitchItem(presentationData: presentationData, title: "Always Keep Archived", value: isOn, enableInteractiveChanges: !isLocked, enabled: true, displayLocked: isLocked, sectionId: self.section, style: .blocks, updated: { value in
arguments.updateUnknown(value)
}, activatedWhileDisabled: {
arguments.updateUnknown(nil)
})
case .unknownFooter:
return ItemListTextItem(presentationData: presentationData, text: .markdown("Automatically archive and mute new private chats, groups and channels from non-contacts."), sectionId: self.section)
}
}
}
private func archiveSettingsControllerEntries(
presentationData: PresentationData,
settings: GlobalPrivacySettings,
isPremium: Bool,
isPremiumEnabled: Bool
) -> [ArchiveSettingsControllerEntry] {
var entries: [ArchiveSettingsControllerEntry] = []
entries.append(.unmutedHeader)
entries.append(.unmutedValue(settings.keepArchivedUnmuted))
entries.append(.unmutedFooter)
if !settings.keepArchivedUnmuted {
entries.append(.foldersHeader)
entries.append(.foldersValue(settings.keepArchivedFolders))
entries.append(.foldersFooter)
}
if isPremium || isPremiumEnabled {
entries.append(.unknownHeader)
entries.append(.unknownValue(isOn: isPremium && settings.automaticallyArchiveAndMuteNonContacts, isLocked: !isPremium))
entries.append(.unknownFooter)
}
return entries
}
public func archiveSettingsController(context: AccountContext) -> ViewController {
let updateDisposable = MetaDisposable()
updateDisposable.set(context.engine.privacy.requestAccountPrivacySettings().start())
var presentUndoImpl: ((UndoOverlayContent) -> Void)?
var presentPremiumImpl: (() -> Void)?
let arguments = ArchiveSettingsControllerArguments(
updateUnmuted: { value in
let _ = context.engine.privacy.updateAccountKeepArchivedUnmuted(value: value).start()
},
updateFolders: { value in
let _ = context.engine.privacy.updateAccountKeepArchivedFolders(value: value).start()
},
updateUnknown: { value in
if let value {
let _ = context.engine.privacy.updateAccountAutoArchiveChats(value: value).start()
} else {
presentUndoImpl?(.premiumPaywall(title: nil, text: "This setting is available only to the subscribers of [Telegram Premium]().", customUndoText: nil, timeout: nil, linkAction: { _ in
presentPremiumImpl?()
}))
}
}
)
let signal = combineLatest(queue: .mainQueue(),
context.sharedContext.presentationData,
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.GlobalPrivacy()),
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.App()),
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))
)
|> deliverOnMainQueue
|> map { presentationData, settings, appConfiguration, accountPeer -> (ItemListControllerState, (ItemListNodeState, Any)) in
let isPremium = accountPeer?.isPremium ?? false
let isPremiumDisabled = PremiumConfiguration.with(appConfiguration: appConfiguration).isPremiumDisabled
//TODO:localize
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text("Archive Settings"), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: archiveSettingsControllerEntries(
presentationData: presentationData,
settings: settings,
isPremium: isPremium,
isPremiumEnabled: !isPremiumDisabled
), style: .blocks, animateChanges: true)
return (controllerState, (listState, arguments))
}
let controller = ItemListController(context: context, state: signal)
presentUndoImpl = { [weak controller] content in
guard let controller else {
return
}
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
controller.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, action: { _ in
return false
}), in: .current)
}
presentPremiumImpl = { [weak controller] in
guard let controller else {
return
}
let premiumController = context.sharedContext.makePremiumIntroController(context: context, source: .settings)
controller.push(premiumController)
}
return controller
}