mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
622 lines
30 KiB
Swift
622 lines
30 KiB
Swift
import Foundation
|
|
import Display
|
|
import SwiftSignalKit
|
|
import Postbox
|
|
import TelegramCore
|
|
import LegacyComponents
|
|
|
|
private struct SettingsItemArguments {
|
|
let account: Account
|
|
let accountManager: AccountManager
|
|
let avatarAndNameInfoContext: ItemListAvatarAndNameInfoItemContext
|
|
|
|
let avatarTapAction: () -> Void
|
|
|
|
let changeProfilePhoto: () -> Void
|
|
let openPrivacyAndSecurity: () -> Void
|
|
let openDataAndStorage: () -> Void
|
|
let openThemes: () -> Void
|
|
let openTheme: (TelegramWallpaper) -> Void
|
|
let pushController: (ViewController) -> Void
|
|
let presentController: (ViewController) -> Void
|
|
let updateEditingName: (ItemListAvatarAndNameInfoItemName) -> Void
|
|
let saveEditingState: () -> Void
|
|
let openLanguage: () -> Void
|
|
let openSupport: () -> Void
|
|
let openFaq: () -> Void
|
|
let logout: () -> Void
|
|
}
|
|
|
|
private enum SettingsSection: Int32 {
|
|
case info
|
|
case generalSettings
|
|
case accountSettings
|
|
case help
|
|
case logOut
|
|
}
|
|
|
|
private enum SettingsEntry: ItemListNodeEntry {
|
|
case userInfo(PresentationTheme, PresentationStrings, Peer?, CachedPeerData?, ItemListAvatarAndNameInfoItemState, TelegramMediaImageRepresentation?)
|
|
case setProfilePhoto(PresentationTheme, String)
|
|
|
|
case notificationsAndSounds(PresentationTheme, String)
|
|
case privacyAndSecurity(PresentationTheme, String)
|
|
case dataAndStorage(PresentationTheme, String)
|
|
case stickers(PresentationTheme, String)
|
|
case themes(PresentationTheme, String, [TelegramWallpaper])
|
|
case phoneNumber(PresentationTheme, String, String)
|
|
case username(PresentationTheme, String, String)
|
|
case language(PresentationTheme, String, String)
|
|
case askAQuestion(PresentationTheme, String, Bool)
|
|
case faq(PresentationTheme, String)
|
|
case debug(PresentationTheme, String)
|
|
case logOut(PresentationTheme, String)
|
|
|
|
var section: ItemListSectionId {
|
|
switch self {
|
|
case .userInfo, .setProfilePhoto:
|
|
return SettingsSection.info.rawValue
|
|
case .notificationsAndSounds, .privacyAndSecurity, .dataAndStorage, .stickers, .themes:
|
|
return SettingsSection.generalSettings.rawValue
|
|
case .phoneNumber, .username:
|
|
return SettingsSection.accountSettings.rawValue
|
|
case .language, .askAQuestion, .faq, .debug:
|
|
return SettingsSection.help.rawValue
|
|
case .logOut:
|
|
return SettingsSection.logOut.rawValue
|
|
}
|
|
}
|
|
|
|
var stableId: Int32 {
|
|
switch self {
|
|
case .userInfo:
|
|
return 0
|
|
case .setProfilePhoto:
|
|
return 1
|
|
case .notificationsAndSounds:
|
|
return 2
|
|
case .privacyAndSecurity:
|
|
return 3
|
|
case .dataAndStorage:
|
|
return 4
|
|
case .stickers:
|
|
return 5
|
|
case .themes:
|
|
return 6
|
|
case .phoneNumber:
|
|
return 7
|
|
case .username:
|
|
return 8
|
|
case .askAQuestion:
|
|
return 9
|
|
case .language:
|
|
return 10
|
|
case .faq:
|
|
return 11
|
|
case .debug:
|
|
return 12
|
|
case .logOut:
|
|
return 13
|
|
}
|
|
}
|
|
|
|
static func ==(lhs: SettingsEntry, rhs: SettingsEntry) -> Bool {
|
|
switch lhs {
|
|
case let .userInfo(lhsTheme, lhsStrings, lhsPeer, lhsCachedData, lhsEditingState, lhsUpdatingImage):
|
|
if case let .userInfo(rhsTheme, rhsStrings, rhsPeer, rhsCachedData, rhsEditingState, rhsUpdatingImage) = rhs {
|
|
if lhsTheme !== rhsTheme {
|
|
return false
|
|
}
|
|
if lhsStrings !== rhsStrings {
|
|
return false
|
|
}
|
|
if let lhsPeer = lhsPeer, let rhsPeer = rhsPeer {
|
|
if !lhsPeer.isEqual(rhsPeer) {
|
|
return false
|
|
}
|
|
} else if (lhsPeer != nil) != (rhsPeer != nil) {
|
|
return false
|
|
}
|
|
if let lhsCachedData = lhsCachedData, let rhsCachedData = rhsCachedData {
|
|
if !lhsCachedData.isEqual(to: rhsCachedData) {
|
|
return false
|
|
}
|
|
} else if (lhsCachedData != nil) != (rhsCachedData != nil) {
|
|
return false
|
|
}
|
|
if lhsEditingState != rhsEditingState {
|
|
return false
|
|
}
|
|
if lhsUpdatingImage != rhsUpdatingImage {
|
|
return false
|
|
}
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .setProfilePhoto(lhsTheme, lhsText):
|
|
if case let .setProfilePhoto(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .notificationsAndSounds(lhsTheme, lhsText):
|
|
if case let .notificationsAndSounds(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .privacyAndSecurity(lhsTheme, lhsText):
|
|
if case let .privacyAndSecurity(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .dataAndStorage(lhsTheme, lhsText):
|
|
if case let .dataAndStorage(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .stickers(lhsTheme, lhsText):
|
|
if case let .stickers(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .themes(lhsTheme, lhsText, lhsWallpapers):
|
|
if case let .themes(rhsTheme, rhsText, rhsWallpapers) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsWallpapers == rhsWallpapers {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .phoneNumber(lhsTheme, lhsText, lhsNumber):
|
|
if case let .phoneNumber(rhsTheme, rhsText, rhsNumber) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsNumber == rhsNumber {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .username(lhsTheme, lhsText, lhsAddress):
|
|
if case let .username(rhsTheme, rhsText, rhsAddress) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsAddress == rhsAddress {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .language(lhsTheme, lhsText, lhsValue):
|
|
if case let .language(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .askAQuestion(lhsTheme, lhsText, lhsLoading):
|
|
if case let .askAQuestion(rhsTheme, rhsText, rhsLoading) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsLoading == rhsLoading {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .faq(lhsTheme, lhsText):
|
|
if case let .faq(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .debug(lhsTheme, lhsText):
|
|
if case let .debug(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .logOut(lhsTheme, lhsText):
|
|
if case let .logOut(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
static func <(lhs: SettingsEntry, rhs: SettingsEntry) -> Bool {
|
|
return lhs.stableId < rhs.stableId
|
|
}
|
|
|
|
func item(_ arguments: SettingsItemArguments) -> ListViewItem {
|
|
switch self {
|
|
case let .userInfo(theme, strings, peer, cachedData, state, updatingImage):
|
|
return ItemListAvatarAndNameInfoItem(account: arguments.account, theme: theme, strings: strings, peer: peer, presence: TelegramUserPresence(status: .present(until: Int32.max)), cachedData: cachedData, state: state, sectionId: ItemListSectionId(self.section), style: .blocks(withTopInset: false), editingNameUpdated: { editingName in
|
|
arguments.updateEditingName(editingName)
|
|
}, avatarTapped: {
|
|
arguments.avatarTapAction()
|
|
}, context: arguments.avatarAndNameInfoContext, updatingImage: updatingImage)
|
|
case let .setProfilePhoto(theme, text):
|
|
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.changeProfilePhoto()
|
|
})
|
|
case let .notificationsAndSounds(theme, text):
|
|
return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.pushController(notificationsAndSoundsController(account: arguments.account))
|
|
})
|
|
case let .privacyAndSecurity(theme, text):
|
|
return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.openPrivacyAndSecurity()
|
|
})
|
|
case let .dataAndStorage(theme, text):
|
|
return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.openDataAndStorage()
|
|
})
|
|
case let .stickers(theme, text):
|
|
return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.pushController(installedStickerPacksController(account: arguments.account, mode: .general))
|
|
})
|
|
case let .themes(theme, text, wallpapers):
|
|
return SettingsThemesItem(account: arguments.account, theme: theme, title: text, sectionId: self.section, action: {
|
|
arguments.openThemes()
|
|
}, openWallpaper: { wallpaper in
|
|
arguments.openTheme(wallpaper)
|
|
}, wallpapers: wallpapers)
|
|
case let .phoneNumber(theme, text, number):
|
|
return ItemListDisclosureItem(theme: theme, title: text, label: number, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.pushController(ChangePhoneNumberIntroController(account: arguments.account, phoneNumber: number))
|
|
})
|
|
case let .username(theme, text, address):
|
|
return ItemListDisclosureItem(theme: theme, title: text, label: address, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.presentController(usernameSetupController(account: arguments.account))
|
|
})
|
|
case let .language(theme, text, value):
|
|
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.openLanguage()
|
|
})
|
|
case let .askAQuestion(theme, text, loading):
|
|
return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.openSupport()
|
|
})
|
|
case let .faq(theme, text):
|
|
return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.openFaq()
|
|
})
|
|
case let .debug(theme, text):
|
|
return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.pushController(debugController(account: arguments.account, accountManager: arguments.accountManager))
|
|
})
|
|
case let .logOut(theme, text):
|
|
return ItemListActionItem(theme: theme, title: text, kind: .destructive, alignment: .center, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.logout()
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
private struct SettingsEditingState: Equatable {
|
|
let editingName: ItemListAvatarAndNameInfoItemName
|
|
|
|
static func ==(lhs: SettingsEditingState, rhs: SettingsEditingState) -> Bool {
|
|
if lhs.editingName != rhs.editingName {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
}
|
|
|
|
private struct SettingsState: Equatable {
|
|
let updatingAvatar: TelegramMediaImageRepresentation?
|
|
let editingState: SettingsEditingState?
|
|
let updatingName: ItemListAvatarAndNameInfoItemName?
|
|
let loadingSupportPeer: Bool
|
|
|
|
func withUpdatedUpdatingAvatar(_ updatingAvatar: TelegramMediaImageRepresentation?) -> SettingsState {
|
|
return SettingsState(updatingAvatar: updatingAvatar, editingState: editingState, updatingName: self.updatingName, loadingSupportPeer: self.loadingSupportPeer)
|
|
}
|
|
|
|
func withUpdatedEditingState(_ editingState: SettingsEditingState?) -> SettingsState {
|
|
return SettingsState(updatingAvatar: self.updatingAvatar, editingState: editingState, updatingName: self.updatingName, loadingSupportPeer: self.loadingSupportPeer)
|
|
}
|
|
|
|
func withUpdatedUpdatingName(_ updatingName: ItemListAvatarAndNameInfoItemName?) -> SettingsState {
|
|
return SettingsState(updatingAvatar: self.updatingAvatar, editingState: self.editingState, updatingName: updatingName, loadingSupportPeer: self.loadingSupportPeer)
|
|
}
|
|
|
|
func withUpdatedLoadingSupportPeer(_ loadingSupportPeer: Bool) -> SettingsState {
|
|
return SettingsState(updatingAvatar: self.updatingAvatar, editingState: self.editingState, updatingName: self.updatingName, loadingSupportPeer: loadingSupportPeer)
|
|
}
|
|
|
|
static func ==(lhs: SettingsState, rhs: SettingsState) -> Bool {
|
|
if lhs.updatingAvatar != rhs.updatingAvatar {
|
|
return false
|
|
}
|
|
if lhs.editingState != rhs.editingState {
|
|
return false
|
|
}
|
|
if lhs.updatingName != rhs.updatingName {
|
|
return false
|
|
}
|
|
if lhs.loadingSupportPeer != rhs.loadingSupportPeer {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
}
|
|
|
|
private func settingsEntries(presentationData: PresentationData, state: SettingsState, view: PeerView, wallpapers: [TelegramWallpaper]) -> [SettingsEntry] {
|
|
var entries: [SettingsEntry] = []
|
|
|
|
if let peer = peerViewMainPeer(view) as? TelegramUser {
|
|
let userInfoState = ItemListAvatarAndNameInfoItemState(editingName: state.editingState?.editingName, updatingName: state.updatingName)
|
|
entries.append(.userInfo(presentationData.theme, presentationData.strings, peer, view.cachedData, userInfoState, state.updatingAvatar))
|
|
entries.append(.setProfilePhoto(presentationData.theme, presentationData.strings.Settings_SetProfilePhoto))
|
|
|
|
entries.append(.notificationsAndSounds(presentationData.theme, presentationData.strings.Settings_NotificationsAndSounds))
|
|
entries.append(.privacyAndSecurity(presentationData.theme, presentationData.strings.Settings_PrivacySettings))
|
|
entries.append(.dataAndStorage(presentationData.theme, presentationData.strings.Settings_ChatSettings))
|
|
entries.append(.stickers(presentationData.theme, presentationData.strings.ChatSettings_Stickers))
|
|
entries.append(.themes(presentationData.theme, presentationData.strings.Settings_ChatBackground, wallpapers))
|
|
|
|
if let phone = peer.phone {
|
|
entries.append(.phoneNumber(presentationData.theme, presentationData.strings.Settings_PhoneNumber, formatPhoneNumber(phone)))
|
|
}
|
|
entries.append(.username(presentationData.theme, presentationData.strings.Settings_Username, peer.addressName == nil ? "" : ("@" + peer.addressName!)))
|
|
|
|
entries.append(.askAQuestion(presentationData.theme, presentationData.strings.Settings_Support, state.loadingSupportPeer))
|
|
entries.append(.language(presentationData.theme, presentationData.strings.Settings_AppLanguage, presentationData.strings.Localization_LanguageName))
|
|
entries.append(.faq(presentationData.theme, presentationData.strings.Settings_FAQ))
|
|
entries.append(.debug(presentationData.theme, "Debug"))
|
|
|
|
if let _ = state.editingState {
|
|
entries.append(.logOut(presentationData.theme, presentationData.strings.Settings_Logout))
|
|
}
|
|
}
|
|
|
|
return entries
|
|
}
|
|
|
|
public func settingsController(account: Account, accountManager: AccountManager) -> ViewController {
|
|
let statePromise = ValuePromise(SettingsState(updatingAvatar: nil, editingState: nil, updatingName: nil, loadingSupportPeer: false), ignoreRepeated: true)
|
|
let stateValue = Atomic(value: SettingsState(updatingAvatar: nil, editingState: nil, updatingName: nil, loadingSupportPeer: false))
|
|
let updateState: ((SettingsState) -> SettingsState) -> Void = { f in
|
|
statePromise.set(stateValue.modify { f($0) })
|
|
}
|
|
|
|
var pushControllerImpl: ((ViewController) -> Void)?
|
|
var presentControllerImpl: ((ViewController, Any?) -> Void)?
|
|
|
|
let actionsDisposable = DisposableSet()
|
|
|
|
let updateAvatarDisposable = MetaDisposable()
|
|
actionsDisposable.add(updateAvatarDisposable)
|
|
|
|
let updatePeerNameDisposable = MetaDisposable()
|
|
actionsDisposable.add(updatePeerNameDisposable)
|
|
|
|
let supportPeerDisposable = MetaDisposable()
|
|
actionsDisposable.add(supportPeerDisposable)
|
|
|
|
let hiddenAvatarRepresentationDisposable = MetaDisposable()
|
|
actionsDisposable.add(hiddenAvatarRepresentationDisposable)
|
|
|
|
let currentAvatarMixin = Atomic<TGMediaAvatarMenuMixin?>(value: nil)
|
|
|
|
var avatarGalleryTransitionArguments: ((AvatarGalleryEntry) -> GalleryTransitionArguments?)?
|
|
let avatarAndNameInfoContext = ItemListAvatarAndNameInfoItemContext()
|
|
var updateHiddenAvatarImpl: (() -> Void)?
|
|
|
|
let wallpapersPromise = Promise<[TelegramWallpaper]>()
|
|
wallpapersPromise.set(telegramWallpapers(account: account))
|
|
|
|
let arguments = SettingsItemArguments(account: account, accountManager: accountManager, avatarAndNameInfoContext: avatarAndNameInfoContext, avatarTapAction: {
|
|
var updating = false
|
|
updateState {
|
|
updating = $0.updatingAvatar != nil
|
|
return $0
|
|
}
|
|
|
|
if updating {
|
|
return
|
|
}
|
|
|
|
let _ = (account.postbox.loadedPeerWithId(account.peerId) |> take(1) |> deliverOnMainQueue).start(next: { peer in
|
|
let galleryController = AvatarGalleryController(account: account, peer: peer, replaceRootController: { controller, ready in
|
|
|
|
})
|
|
hiddenAvatarRepresentationDisposable.set((galleryController.hiddenMedia |> deliverOnMainQueue).start(next: { entry in
|
|
avatarAndNameInfoContext.hiddenAvatarRepresentation = entry?.representations.first
|
|
updateHiddenAvatarImpl?()
|
|
}))
|
|
presentControllerImpl?(galleryController, AvatarGalleryControllerPresentationArguments(transitionArguments: { entry in
|
|
return avatarGalleryTransitionArguments?(entry)
|
|
}))
|
|
})
|
|
}, changeProfilePhoto: {
|
|
let legacyController = LegacyController(presentation: .custom)
|
|
legacyController.statusBar.statusBarStyle = .Ignore
|
|
|
|
let emptyController = LegacyEmptyController(context: legacyController.context)!
|
|
let navigationController = makeLegacyNavigationController(rootController: emptyController)
|
|
navigationController.setNavigationBarHidden(true, animated: false)
|
|
navigationController.navigationBar.transform = CGAffineTransform(translationX: -1000.0, y: 0.0)
|
|
|
|
legacyController.bind(controller: navigationController)
|
|
|
|
presentControllerImpl?(legacyController, nil)
|
|
|
|
let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasDeleteButton: false, personalPhoto: true, saveEditedPhotos: false, saveCapturedMedia: false)!
|
|
let _ = currentAvatarMixin.swap(mixin)
|
|
mixin.didFinishWithImage = { image in
|
|
if let image = image {
|
|
if let data = UIImageJPEGRepresentation(image, 0.6) {
|
|
let resource = LocalFileMediaResource(fileId: arc4random64())
|
|
account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
|
let representation = TelegramMediaImageRepresentation(dimensions: CGSize(width: 640.0, height: 640.0), resource: resource)
|
|
updateState {
|
|
$0.withUpdatedUpdatingAvatar(representation)
|
|
}
|
|
updateAvatarDisposable.set((updateAccountPhoto(account: account, resource: resource) |> deliverOnMainQueue).start(next: { result in
|
|
switch result {
|
|
case .complete:
|
|
updateState {
|
|
$0.withUpdatedUpdatingAvatar(nil)
|
|
}
|
|
case .progress:
|
|
break
|
|
}
|
|
}))
|
|
}
|
|
}
|
|
}
|
|
mixin.didDismiss = { [weak legacyController] in
|
|
let _ = currentAvatarMixin.swap(nil)
|
|
legacyController?.dismiss()
|
|
}
|
|
let menuController = mixin.present()
|
|
if let menuController = menuController {
|
|
menuController.customRemoveFromParentViewController = { [weak legacyController] in
|
|
legacyController?.dismiss()
|
|
}
|
|
}
|
|
}, openPrivacyAndSecurity: {
|
|
pushControllerImpl?(privacyAndSecurityController(account: account, initialSettings: .single(nil) |> then(requestAccountPrivacySettings(account: account) |> map { Optional($0) })))
|
|
}, openDataAndStorage: {
|
|
pushControllerImpl?(dataAndStorageController(account: account))
|
|
}, openThemes: {
|
|
pushControllerImpl?(ThemeGridController(account: account))
|
|
}, openTheme: { wallpaper in
|
|
let _ = (wallpapersPromise.get() |> take(1) |> deliverOnMainQueue).start(next: { wallpapers in
|
|
let controller = ThemeGalleryController(account: account, wallpapers: wallpapers, at: wallpaper)
|
|
presentControllerImpl?(controller, ThemePreviewControllerPresentationArguments(transitionArguments: { entry -> GalleryTransitionArguments? in
|
|
return nil
|
|
}))
|
|
})
|
|
}, pushController: { controller in
|
|
pushControllerImpl?(controller)
|
|
}, presentController: { controller in
|
|
presentControllerImpl?(controller, nil)
|
|
}, updateEditingName: { editingName in
|
|
updateState { state in
|
|
if let _ = state.editingState {
|
|
return state.withUpdatedEditingState(SettingsEditingState(editingName: editingName))
|
|
} else {
|
|
return state
|
|
}
|
|
}
|
|
}, saveEditingState: {
|
|
var updateName: ItemListAvatarAndNameInfoItemName?
|
|
updateState { state in
|
|
if let editingState = state.editingState {
|
|
updateName = editingState.editingName
|
|
return state.withUpdatedEditingState(nil).withUpdatedUpdatingName(editingState.editingName)
|
|
} else {
|
|
return state
|
|
}
|
|
}
|
|
if let updateName = updateName, case let .personName(firstName, lastName) = updateName {
|
|
updatePeerNameDisposable.set((updateAccountPeerName(account: account, firstName: firstName, lastName: lastName) |> afterDisposed {
|
|
Queue.mainQueue().async {
|
|
updateState { state in
|
|
return state.withUpdatedUpdatingName(nil)
|
|
}
|
|
}
|
|
}).start())
|
|
}
|
|
}, openLanguage: {
|
|
let controller = LanguageSelectionController(account: account)
|
|
presentControllerImpl?(controller, nil)
|
|
}, openSupport: {
|
|
var load = false
|
|
updateState { state in
|
|
if !state.loadingSupportPeer {
|
|
load = true
|
|
}
|
|
return state.withUpdatedLoadingSupportPeer(true)
|
|
}
|
|
if load {
|
|
supportPeerDisposable.set((supportPeerId(account: account) |> deliverOnMainQueue).start(next: { peerId in
|
|
updateState { state in
|
|
return state.withUpdatedLoadingSupportPeer(false)
|
|
}
|
|
if let peerId = peerId {
|
|
pushControllerImpl?(ChatController(account: account, peerId: peerId))
|
|
}
|
|
}))
|
|
}
|
|
}, openFaq: {
|
|
var faqUrl = NSLocalizedString("Settings.FAQ_URL", comment: "")
|
|
if faqUrl == "Settings.FAQ_URL" {
|
|
faqUrl = "http://telegram.org/faq#general"
|
|
}
|
|
|
|
if let applicationContext = account.applicationContext as? TelegramApplicationContext {
|
|
applicationContext.applicationBindings.openUrl(faqUrl)
|
|
}
|
|
}, logout: {
|
|
let alertController = standardTextAlertController(title: NSLocalizedString("Settings.LogoutConfirmationTitle", comment: ""), text: NSLocalizedString("Settings.LogoutConfirmationText", comment: ""), actions: [
|
|
TextAlertAction(type: .genericAction, title: "Cancel", action: {
|
|
}),
|
|
TextAlertAction(type: .defaultAction, title: "OK", action: {
|
|
let _ = logoutFromAccount(id: account.id, accountManager: accountManager).start()
|
|
})
|
|
])
|
|
presentControllerImpl?(alertController, nil)
|
|
})
|
|
|
|
let peerView = account.viewTracker.peerView(account.peerId)
|
|
|
|
let signal = combineLatest((account.applicationContext as! TelegramApplicationContext).presentationData, statePromise.get(), peerView, wallpapersPromise.get())
|
|
|> map { presentationData, state, view, wallpapers -> (ItemListControllerState, (ItemListNodeState<SettingsEntry>, SettingsEntry.ItemGenerationArguments)) in
|
|
let peer = peerViewMainPeer(view)
|
|
let rightNavigationButton: ItemListNavigationButton
|
|
if let _ = state.editingState {
|
|
rightNavigationButton = ItemListNavigationButton(title: presentationData.strings.Common_Done, style: .bold, enabled: true, action: {
|
|
arguments.saveEditingState()
|
|
})
|
|
} else {
|
|
rightNavigationButton = ItemListNavigationButton(title: presentationData.strings.Common_Edit, style: .regular, enabled: true, action: {
|
|
if let peer = peer as? TelegramUser {
|
|
updateState { state in
|
|
return state.withUpdatedEditingState(SettingsEditingState(editingName: ItemListAvatarAndNameInfoItemName(peer.indexName)))
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Settings_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
|
let listState = ItemListNodeState(entries: settingsEntries(presentationData: presentationData, state: state, view: view, wallpapers: wallpapers), style: .blocks)
|
|
|
|
return (controllerState, (listState, arguments))
|
|
} |> afterDisposed {
|
|
actionsDisposable.dispose()
|
|
}
|
|
|
|
let controller = ItemListController(account: account, state: signal, tabBarItem: (account.applicationContext as! TelegramApplicationContext).presentationData |> map { presentationData in
|
|
return ItemListControllerTabBarItem(title: presentationData.strings.Settings_Title, image: PresentationResourcesRootController.tabSettingsIcon(presentationData.theme), selectedImage: PresentationResourcesRootController.tabSettingsSelectedIcon(presentationData.theme))
|
|
})
|
|
pushControllerImpl = { [weak controller] value in
|
|
(controller?.navigationController as? NavigationController)?.pushViewController(value)
|
|
}
|
|
presentControllerImpl = { [weak controller] value, arguments in
|
|
controller?.present(value, in: .window(.root), with: arguments ?? ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
|
}
|
|
avatarGalleryTransitionArguments = { [weak controller] entry in
|
|
if let controller = controller {
|
|
var result: (ASDisplayNode, CGRect)?
|
|
controller.forEachItemNode { itemNode in
|
|
if let itemNode = itemNode as? ItemListAvatarAndNameInfoItemNode {
|
|
result = itemNode.avatarTransitionNode()
|
|
}
|
|
}
|
|
if let (node, _) = result {
|
|
return GalleryTransitionArguments(transitionNode: node, addToTransitionSurface: { _ in
|
|
})
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
updateHiddenAvatarImpl = { [weak controller] in
|
|
if let controller = controller {
|
|
controller.forEachItemNode { itemNode in
|
|
if let itemNode = itemNode as? ItemListAvatarAndNameInfoItemNode {
|
|
itemNode.updateAvatarHidden()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return controller
|
|
}
|