mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
322 lines
13 KiB
Swift
322 lines
13 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import Display
|
|
import SwiftSignalKit
|
|
import Postbox
|
|
import TelegramCore
|
|
import SyncCore
|
|
import TelegramPresentationData
|
|
import ItemListUI
|
|
import PresentationDataUtils
|
|
import AccountContext
|
|
import ChatListFilterSettingsHeaderItem
|
|
|
|
private final class PeerAutoremoveSetupArguments {
|
|
let toggleGlobal: (Bool) -> Void
|
|
let updateValue: (Int32) -> Void
|
|
|
|
init(toggleGlobal: @escaping (Bool) -> Void, updateValue: @escaping (Int32) -> Void) {
|
|
self.toggleGlobal = toggleGlobal
|
|
self.updateValue = updateValue
|
|
}
|
|
}
|
|
|
|
private enum PeerAutoremoveSetupSection: Int32 {
|
|
case header
|
|
case time
|
|
case global
|
|
}
|
|
|
|
private enum PeerAutoremoveSetupEntry: ItemListNodeEntry {
|
|
case header
|
|
case timeHeader(String)
|
|
case timeValue(Int32, Int32)
|
|
case timeComment(String)
|
|
case globalSwitch(String, Bool)
|
|
|
|
var section: ItemListSectionId {
|
|
switch self {
|
|
case .header:
|
|
return PeerAutoremoveSetupSection.header.rawValue
|
|
case .timeHeader, .timeValue, .timeComment:
|
|
return PeerAutoremoveSetupSection.time.rawValue
|
|
case .globalSwitch:
|
|
return PeerAutoremoveSetupSection.global.rawValue
|
|
}
|
|
}
|
|
|
|
var stableId: Int32 {
|
|
switch self {
|
|
case .header:
|
|
return 0
|
|
case .timeHeader:
|
|
return 1
|
|
case .timeValue:
|
|
return 2
|
|
case .timeComment:
|
|
return 3
|
|
case .globalSwitch:
|
|
return 4
|
|
}
|
|
}
|
|
|
|
static func ==(lhs: PeerAutoremoveSetupEntry, rhs: PeerAutoremoveSetupEntry) -> Bool {
|
|
switch lhs {
|
|
case .header:
|
|
if case .header = rhs {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .timeHeader(lhsText):
|
|
if case let .timeHeader(rhsText) = rhs, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .timeValue(lhsValue, lhsMaxValue):
|
|
if case let .timeValue(rhsValue, rhsMaxValue) = rhs, lhsValue == rhsValue, lhsMaxValue == rhsMaxValue {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .timeComment(lhsText):
|
|
if case let .timeComment(rhsText) = rhs, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .globalSwitch(lhsText, lhsValue):
|
|
if case let .globalSwitch(rhsText, rhsValue) = rhs, lhsText == rhsText, lhsValue == rhsValue {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
static func <(lhs: PeerAutoremoveSetupEntry, rhs: PeerAutoremoveSetupEntry) -> Bool {
|
|
return lhs.stableId < rhs.stableId
|
|
}
|
|
|
|
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
|
let arguments = arguments as! PeerAutoremoveSetupArguments
|
|
switch self {
|
|
case .header:
|
|
return ChatListFilterSettingsHeaderItem(theme: presentationData.theme, text: "", animation: .autoRemove, sectionId: self.section)
|
|
case let .timeHeader(text):
|
|
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
|
case let .timeValue(value, maxValue):
|
|
return PeerRemoveTimeoutItem(theme: presentationData.theme, value: value, maxValue: maxValue, enabled: true, sectionId: self.section, updated: { value in
|
|
arguments.updateValue(value)
|
|
}, tag: nil)
|
|
case let .timeComment(text):
|
|
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
|
case let .globalSwitch(text, value):
|
|
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
|
arguments.toggleGlobal(value)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
private struct PeerAutoremoveSetupState: Equatable {
|
|
var changedValue: Int32?
|
|
var changedGlobalValue: Bool?
|
|
var applyingSetting: Bool = false
|
|
}
|
|
|
|
private func peerAutoremoveSetupEntries(peer: Peer?, presentationData: PresentationData, defaultMyValue: Int32, peerValue: Int32, defaultGlobalValue: Bool, state: PeerAutoremoveSetupState) -> [PeerAutoremoveSetupEntry] {
|
|
var entries: [PeerAutoremoveSetupEntry] = []
|
|
let globalValue = state.changedGlobalValue ?? defaultGlobalValue
|
|
|
|
let resolvedValue: Int32
|
|
let resolvedMaxValue: Int32
|
|
|
|
if peer is TelegramUser {
|
|
resolvedValue = state.changedValue ?? defaultMyValue
|
|
resolvedMaxValue = peerValue
|
|
} else {
|
|
resolvedValue = state.changedValue ?? peerValue
|
|
resolvedMaxValue = Int32.max
|
|
}
|
|
|
|
//TODO:localize
|
|
entries.append(.header)
|
|
entries.append(.timeHeader("AUTO-DELETE MESSAGES"))
|
|
entries.append(.timeValue(resolvedValue, resolvedMaxValue))
|
|
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
|
entries.append(.timeComment("Automatically delete messages sent in this channel after a certain period of time."))
|
|
} else {
|
|
if resolvedMaxValue != Int32.max {
|
|
entries.append(.timeComment("\(peer?.compactDisplayTitle ?? "") has set messages to auto-delete in \(timeIntervalString(strings: presentationData.strings, value: resolvedMaxValue)). You can't cancel it or make this interval longer."))
|
|
} else {
|
|
entries.append(.timeComment("Automatically delete messages sent in this chat after a certain period of time."))
|
|
}
|
|
}
|
|
if let user = peer as? TelegramUser {
|
|
entries.append(.globalSwitch("Also auto-delete for \(user.compactDisplayTitle)", globalValue))
|
|
}
|
|
|
|
return entries
|
|
}
|
|
|
|
public enum PeerAutoremoveSetupScreenResult {
|
|
public struct Updated {
|
|
public var myValue: Int32?
|
|
public var limitedByValue: Int32?
|
|
}
|
|
|
|
case unchanged
|
|
case updated(Updated)
|
|
}
|
|
|
|
public func peerAutoremoveSetupScreen(context: AccountContext, peerId: PeerId, completion: @escaping (PeerAutoremoveSetupScreenResult) -> Void = { _ in }) -> ViewController {
|
|
let statePromise = ValuePromise(PeerAutoremoveSetupState(), ignoreRepeated: true)
|
|
let stateValue = Atomic(value: PeerAutoremoveSetupState())
|
|
let updateState: ((PeerAutoremoveSetupState) -> PeerAutoremoveSetupState) -> Void = { f in
|
|
statePromise.set(stateValue.modify { f($0) })
|
|
}
|
|
|
|
var pushControllerImpl: ((ViewController) -> Void)?
|
|
var dismissImpl: (() -> Void)?
|
|
|
|
let actionsDisposable = DisposableSet()
|
|
|
|
let applyDisposable = MetaDisposable()
|
|
actionsDisposable.add(applyDisposable)
|
|
|
|
let arguments = PeerAutoremoveSetupArguments(toggleGlobal: { value in
|
|
updateState { state in
|
|
var state = state
|
|
state.changedGlobalValue = value
|
|
return state
|
|
}
|
|
}, updateValue: { value in
|
|
updateState { state in
|
|
var state = state
|
|
state.changedValue = value
|
|
return state
|
|
}
|
|
})
|
|
|
|
let signal = combineLatest(context.sharedContext.presentationData, statePromise.get(), context.account.viewTracker.peerView(peerId))
|
|
|> deliverOnMainQueue
|
|
|> map { presentationData, state, view -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
|
var defaultMyValue: Int32 = Int32.max
|
|
var peerValue: Int32 = Int32.max
|
|
var defaultGlobalValue = true
|
|
if let cachedData = view.cachedData as? CachedChannelData {
|
|
if case let .known(value) = cachedData.autoremoveTimeout {
|
|
defaultMyValue = value?.myValue ?? Int32.max
|
|
peerValue = value?.peerValue ?? Int32.max
|
|
defaultGlobalValue = value?.isGlobal ?? true
|
|
}
|
|
} else if let cachedData = view.cachedData as? CachedGroupData {
|
|
if case let .known(value) = cachedData.autoremoveTimeout {
|
|
defaultMyValue = value?.myValue ?? Int32.max
|
|
peerValue = value?.peerValue ?? Int32.max
|
|
defaultGlobalValue = value?.isGlobal ?? true
|
|
}
|
|
} else if let cachedData = view.cachedData as? CachedUserData {
|
|
if case let .known(value) = cachedData.autoremoveTimeout {
|
|
defaultMyValue = value?.myValue ?? Int32.max
|
|
peerValue = value?.peerValue ?? Int32.max
|
|
defaultGlobalValue = value?.isGlobal ?? true
|
|
}
|
|
}
|
|
|
|
let peer = view.peers[view.peerId]
|
|
|
|
let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
|
|
dismissImpl?()
|
|
})
|
|
var rightNavigationButton: ItemListNavigationButton?
|
|
if state.applyingSetting {
|
|
rightNavigationButton = ItemListNavigationButton(content: .none, style: .activity, enabled: true, action: {})
|
|
} else {
|
|
rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: true, action: {
|
|
var changedValue: Int32?
|
|
var globalValue: Bool?
|
|
updateState { state in
|
|
var state = state
|
|
state.applyingSetting = true
|
|
changedValue = state.changedValue
|
|
globalValue = state.changedGlobalValue
|
|
return state
|
|
}
|
|
|
|
let resolvedDefaultValue: Int32
|
|
if peer is TelegramUser {
|
|
resolvedDefaultValue = defaultMyValue
|
|
} else {
|
|
resolvedDefaultValue = peerValue
|
|
}
|
|
|
|
var updated = false
|
|
if let changedValue = changedValue, changedValue != resolvedDefaultValue {
|
|
updated = true
|
|
}
|
|
if let globalValue = globalValue, globalValue != defaultGlobalValue {
|
|
updated = true
|
|
}
|
|
if updated {
|
|
var resolvedValue: Int32? = changedValue ?? resolvedDefaultValue
|
|
if resolvedValue == Int32.max {
|
|
resolvedValue = nil
|
|
}
|
|
|
|
let resolvedMaxValue: Int32
|
|
if peer is TelegramUser {
|
|
resolvedMaxValue = peerValue
|
|
} else {
|
|
resolvedMaxValue = Int32.max
|
|
}
|
|
|
|
let resolvedGlobalValue = globalValue ?? defaultGlobalValue
|
|
|
|
let signal = setChatMessageAutoremoveTimeoutInteractively(account: context.account, peerId: peerId, timeout: resolvedValue, isGlobal: resolvedGlobalValue)
|
|
|> deliverOnMainQueue
|
|
|
|
applyDisposable.set((signal
|
|
|> deliverOnMainQueue).start(error: { _ in
|
|
}, completed: {
|
|
dismissImpl?()
|
|
if resolvedValue != resolvedDefaultValue {
|
|
completion(.updated(PeerAutoremoveSetupScreenResult.Updated(
|
|
myValue: resolvedValue,
|
|
limitedByValue: resolvedMaxValue == Int32.max ? nil : resolvedMaxValue
|
|
)))
|
|
} else {
|
|
completion(.unchanged)
|
|
}
|
|
}))
|
|
} else {
|
|
dismissImpl?()
|
|
completion(.unchanged)
|
|
}
|
|
})
|
|
}
|
|
|
|
//TODO:localize
|
|
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text("Auto-Deletion"), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
|
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: peerAutoremoveSetupEntries(peer: peer, presentationData: presentationData, defaultMyValue: defaultMyValue, peerValue: peerValue, defaultGlobalValue: defaultGlobalValue, state: state), style: .blocks)
|
|
|
|
return (controllerState, (listState, arguments))
|
|
}
|
|
|> afterDisposed {
|
|
actionsDisposable.dispose()
|
|
}
|
|
|
|
let controller = ItemListController(context: context, state: signal)
|
|
controller.navigationPresentation = .modal
|
|
dismissImpl = { [weak controller] in
|
|
controller?.view.endEditing(true)
|
|
controller?.dismiss()
|
|
}
|
|
pushControllerImpl = { [weak controller] c in
|
|
controller?.push(c)
|
|
}
|
|
return controller
|
|
}
|