mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
680 lines
35 KiB
Swift
680 lines
35 KiB
Swift
import Foundation
|
|
import Display
|
|
import SwiftSignalKit
|
|
import Postbox
|
|
import TelegramCore
|
|
import LegacyComponents
|
|
|
|
private final class SettingsItemIcons {
|
|
static let proxy = UIImage(bundleImageName: "Settings/MenuIcons/Proxy")?.precomposed()
|
|
static let savedMessages = UIImage(bundleImageName: "Settings/MenuIcons/SavedMessages")?.precomposed()
|
|
static let recentCalls = UIImage(bundleImageName: "Settings/MenuIcons/RecentCalls")?.precomposed()
|
|
static let stickers = UIImage(bundleImageName: "Settings/MenuIcons/Stickers")?.precomposed()
|
|
|
|
static let notifications = UIImage(bundleImageName: "Settings/MenuIcons/Notifications")?.precomposed()
|
|
static let security = UIImage(bundleImageName: "Settings/MenuIcons/Security")?.precomposed()
|
|
static let dataAndStorage = UIImage(bundleImageName: "Settings/MenuIcons/DataAndStorage")?.precomposed()
|
|
static let appearance = UIImage(bundleImageName: "Settings/MenuIcons/Appearance")?.precomposed()
|
|
static let language = UIImage(bundleImageName: "Settings/MenuIcons/Language")?.precomposed()
|
|
|
|
static let secureId = UIImage(bundleImageName: "Settings/MenuIcons/Passport")?.precomposed()
|
|
|
|
static let support = UIImage(bundleImageName: "Settings/MenuIcons/Support")?.precomposed()
|
|
static let faq = UIImage(bundleImageName: "Settings/MenuIcons/Faq")?.precomposed()
|
|
}
|
|
|
|
private struct SettingsItemArguments {
|
|
let account: Account
|
|
let accountManager: AccountManager
|
|
let avatarAndNameInfoContext: ItemListAvatarAndNameInfoItemContext
|
|
|
|
let avatarTapAction: () -> Void
|
|
|
|
let changeProfilePhoto: () -> Void
|
|
let openUsername: () -> Void
|
|
let openProxy: () -> Void
|
|
let openSavedMessages: () -> Void
|
|
let openRecentCalls: () -> Void
|
|
let openPrivacyAndSecurity: () -> Void
|
|
let openDataAndStorage: () -> Void
|
|
let openThemes: () -> Void
|
|
let pushController: (ViewController) -> Void
|
|
let presentController: (ViewController) -> Void
|
|
let openLanguage: () -> Void
|
|
let openPassport: () -> Void
|
|
let openSupport: () -> Void
|
|
let openFaq: () -> Void
|
|
let openEditing: () -> Void
|
|
}
|
|
|
|
private enum SettingsSection: Int32 {
|
|
case info
|
|
case proxy
|
|
case media
|
|
case generalSettings
|
|
case passport
|
|
case help
|
|
}
|
|
|
|
private enum SettingsEntry: ItemListNodeEntry {
|
|
case userInfo(PresentationTheme, PresentationStrings, Peer?, CachedPeerData?, ItemListAvatarAndNameInfoItemState, ItemListAvatarAndNameInfoItemUpdatingAvatar?)
|
|
case setProfilePhoto(PresentationTheme, String)
|
|
case setUsername(PresentationTheme, String)
|
|
|
|
case proxy(PresentationTheme, UIImage?, String, String)
|
|
|
|
case savedMessages(PresentationTheme, UIImage?, String)
|
|
case recentCalls(PresentationTheme, UIImage?, String)
|
|
case stickers(PresentationTheme, UIImage?, String, String)
|
|
|
|
case notificationsAndSounds(PresentationTheme, UIImage?, String)
|
|
case privacyAndSecurity(PresentationTheme, UIImage?, String)
|
|
case dataAndStorage(PresentationTheme, UIImage?, String)
|
|
case themes(PresentationTheme, UIImage?, String)
|
|
case language(PresentationTheme, UIImage?, String, String)
|
|
case passport(PresentationTheme, UIImage?, String, String)
|
|
|
|
case askAQuestion(PresentationTheme, UIImage?, String)
|
|
case faq(PresentationTheme, UIImage?, String)
|
|
|
|
var section: ItemListSectionId {
|
|
switch self {
|
|
case .userInfo, .setProfilePhoto, .setUsername:
|
|
return SettingsSection.info.rawValue
|
|
case .proxy:
|
|
return SettingsSection.proxy.rawValue
|
|
case .savedMessages, .recentCalls, .stickers:
|
|
return SettingsSection.media.rawValue
|
|
case .notificationsAndSounds, .privacyAndSecurity, .dataAndStorage, .themes, .language:
|
|
return SettingsSection.generalSettings.rawValue
|
|
case .passport:
|
|
return SettingsSection.passport.rawValue
|
|
case .askAQuestion, .faq:
|
|
return SettingsSection.help.rawValue
|
|
}
|
|
}
|
|
|
|
var stableId: Int32 {
|
|
switch self {
|
|
case .userInfo:
|
|
return 0
|
|
case .setProfilePhoto:
|
|
return 1
|
|
case .setUsername:
|
|
return 2
|
|
case .proxy:
|
|
return 3
|
|
case .savedMessages:
|
|
return 4
|
|
case .recentCalls:
|
|
return 5
|
|
case .stickers:
|
|
return 6
|
|
case .notificationsAndSounds:
|
|
return 7
|
|
case .privacyAndSecurity:
|
|
return 8
|
|
case .dataAndStorage:
|
|
return 9
|
|
case .themes:
|
|
return 10
|
|
case .language:
|
|
return 11
|
|
case .passport:
|
|
return 12
|
|
case .askAQuestion:
|
|
return 13
|
|
case .faq:
|
|
return 14
|
|
}
|
|
}
|
|
|
|
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 .setUsername(lhsTheme, lhsText):
|
|
if case let .setUsername(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .proxy(lhsTheme, lhsImage, lhsText, lhsValue):
|
|
if case let .proxy(rhsTheme, rhsImage, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsImage === rhsImage, lhsText == rhsText, lhsValue == rhsValue {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .savedMessages(lhsTheme, lhsImage, lhsText):
|
|
if case let .savedMessages(rhsTheme, rhsImage, rhsText) = rhs, lhsTheme === rhsTheme, lhsImage === rhsImage, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .recentCalls(lhsTheme, lhsImage, lhsText):
|
|
if case let .recentCalls(rhsTheme, rhsImage, rhsText) = rhs, lhsTheme === rhsTheme, lhsImage === rhsImage, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .stickers(lhsTheme, lhsImage, lhsText, lhsValue):
|
|
if case let .stickers(rhsTheme, rhsImage, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsImage === rhsImage, lhsText == rhsText, lhsValue == rhsValue {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .notificationsAndSounds(lhsTheme, lhsImage, lhsText):
|
|
if case let .notificationsAndSounds(rhsTheme, rhsImage, rhsText) = rhs, lhsTheme === rhsTheme, lhsImage === rhsImage, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .privacyAndSecurity(lhsTheme, lhsImage, lhsText):
|
|
if case let .privacyAndSecurity(rhsTheme, rhsImage, rhsText) = rhs, lhsTheme === rhsTheme, lhsImage === rhsImage, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .dataAndStorage(lhsTheme, lhsImage, lhsText):
|
|
if case let .dataAndStorage(rhsTheme, rhsImage, rhsText) = rhs, lhsTheme === rhsTheme, lhsImage === rhsImage, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .themes(lhsTheme, lhsImage, lhsText):
|
|
if case let .themes(rhsTheme, rhsImage, rhsText) = rhs, lhsTheme === rhsTheme, lhsImage === rhsImage, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .language(lhsTheme, lhsImage, lhsText, lhsValue):
|
|
if case let .language(rhsTheme, rhsImage, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsImage === rhsImage, lhsText == rhsText, lhsValue == rhsValue {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .passport(lhsTheme, lhsImage, lhsText, lhsValue):
|
|
if case let .passport(rhsTheme, rhsImage, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsImage === rhsImage, lhsText == rhsText, lhsValue == rhsValue {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .askAQuestion(lhsTheme, lhsImage, lhsText):
|
|
if case let .askAQuestion(rhsTheme, rhsImage, rhsText) = rhs, lhsTheme === rhsTheme, lhsImage === rhsImage, lhsText == rhsText {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .faq(lhsTheme, lhsImage, lhsText):
|
|
if case let .faq(rhsTheme, rhsImage, rhsText) = rhs, lhsTheme === rhsTheme, lhsImage === rhsImage, 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, mode: .settings, peer: peer, presence: TelegramUserPresence(status: .present(until: Int32.max)), cachedData: cachedData, state: state, sectionId: ItemListSectionId(self.section), style: .blocks(withTopInset: false), editingNameUpdated: { _ in
|
|
}, avatarTapped: {
|
|
arguments.avatarTapAction()
|
|
}, context: arguments.avatarAndNameInfoContext, updatingImage: updatingImage, action: {
|
|
arguments.openEditing()
|
|
})
|
|
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 .setUsername(theme, text):
|
|
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.openUsername()
|
|
})
|
|
case let .proxy(theme, image, text, value):
|
|
return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: value, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.openProxy()
|
|
})
|
|
case let .savedMessages(theme, image, text):
|
|
return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.openSavedMessages()
|
|
})
|
|
case let .recentCalls(theme, image, text):
|
|
return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.openRecentCalls()
|
|
})
|
|
case let .stickers(theme, image, text, value):
|
|
return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: value, labelStyle: .badge, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.pushController(installedStickerPacksController(account: arguments.account, mode: .general))
|
|
})
|
|
case let .notificationsAndSounds(theme, image, text):
|
|
return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.pushController(notificationsAndSoundsController(account: arguments.account))
|
|
})
|
|
case let .privacyAndSecurity(theme, image, text):
|
|
return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.openPrivacyAndSecurity()
|
|
})
|
|
case let .dataAndStorage(theme, image, text):
|
|
return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.openDataAndStorage()
|
|
})
|
|
case let .themes(theme, image, text):
|
|
return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.openThemes()
|
|
})
|
|
case let .language(theme, image, text, value):
|
|
return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: value, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.openLanguage()
|
|
})
|
|
case let .passport(theme, image, text, value):
|
|
return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: value, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.openPassport()
|
|
})
|
|
case let .askAQuestion(theme, image, text):
|
|
return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.openSupport()
|
|
})
|
|
case let .faq(theme, image, text):
|
|
return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
|
arguments.openFaq()
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
private struct SettingsState: Equatable {
|
|
let updatingAvatar: ItemListAvatarAndNameInfoItemUpdatingAvatar?
|
|
|
|
init(updatingAvatar: ItemListAvatarAndNameInfoItemUpdatingAvatar? = nil) {
|
|
self.updatingAvatar = updatingAvatar
|
|
}
|
|
|
|
func withUpdatedUpdatingAvatar(_ updatingAvatar: ItemListAvatarAndNameInfoItemUpdatingAvatar?) -> SettingsState {
|
|
return SettingsState(updatingAvatar: updatingAvatar)
|
|
}
|
|
|
|
static func ==(lhs: SettingsState, rhs: SettingsState) -> Bool {
|
|
if lhs.updatingAvatar != rhs.updatingAvatar {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
}
|
|
|
|
private func settingsEntries(presentationData: PresentationData, state: SettingsState, view: PeerView, proxySettings: ProxySettings, unreadTrendingStickerPacks: Int) -> [SettingsEntry] {
|
|
var entries: [SettingsEntry] = []
|
|
|
|
if let peer = peerViewMainPeer(view) as? TelegramUser {
|
|
let userInfoState = ItemListAvatarAndNameInfoItemState(editingName: nil, updatingName: nil)
|
|
entries.append(.userInfo(presentationData.theme, presentationData.strings, peer, view.cachedData, userInfoState, state.updatingAvatar))
|
|
if peer.photo.isEmpty {
|
|
entries.append(.setProfilePhoto(presentationData.theme, presentationData.strings.Settings_SetProfilePhoto))
|
|
}
|
|
if peer.addressName == nil {
|
|
entries.append(.setUsername(presentationData.theme, presentationData.strings.Settings_SetUsername))
|
|
}
|
|
|
|
if !proxySettings.servers.isEmpty {
|
|
let valueString: String
|
|
if proxySettings.enabled, let activeServer = proxySettings.activeServer {
|
|
switch activeServer.connection {
|
|
case .mtp:
|
|
valueString = presentationData.strings.SocksProxySetup_ProxyTelegram
|
|
case .socks5:
|
|
valueString = presentationData.strings.SocksProxySetup_ProxySocks5
|
|
}
|
|
} else {
|
|
valueString = presentationData.strings.Settings_ProxyDisabled
|
|
}
|
|
entries.append(.proxy(presentationData.theme, SettingsItemIcons.proxy, presentationData.strings.Settings_Proxy, valueString))
|
|
}
|
|
|
|
entries.append(.savedMessages(presentationData.theme, SettingsItemIcons.savedMessages, presentationData.strings.Settings_SavedMessages))
|
|
entries.append(.recentCalls(presentationData.theme, SettingsItemIcons.recentCalls, presentationData.strings.CallSettings_RecentCalls))
|
|
entries.append(.stickers(presentationData.theme, SettingsItemIcons.stickers, presentationData.strings.ChatSettings_Stickers, unreadTrendingStickerPacks == 0 ? "" : "\(unreadTrendingStickerPacks)"))
|
|
|
|
entries.append(.notificationsAndSounds(presentationData.theme, SettingsItemIcons.notifications, presentationData.strings.Settings_NotificationsAndSounds))
|
|
entries.append(.privacyAndSecurity(presentationData.theme, SettingsItemIcons.security, presentationData.strings.Settings_PrivacySettings))
|
|
entries.append(.dataAndStorage(presentationData.theme, SettingsItemIcons.dataAndStorage, presentationData.strings.Settings_ChatSettings))
|
|
entries.append(.themes(presentationData.theme, SettingsItemIcons.appearance, presentationData.strings.ChatSettings_Appearance.lowercased().capitalized))
|
|
entries.append(.language(presentationData.theme, SettingsItemIcons.language, presentationData.strings.Settings_AppLanguage, presentationData.strings.Localization_LanguageName))
|
|
|
|
if GlobalExperimentalSettings.enablePassport {
|
|
entries.append(.passport(presentationData.theme, SettingsItemIcons.secureId, "Telegram Passport", ""))
|
|
}
|
|
|
|
entries.append(.askAQuestion(presentationData.theme, SettingsItemIcons.support, presentationData.strings.Settings_Support))
|
|
entries.append(.faq(presentationData.theme, SettingsItemIcons.faq, presentationData.strings.Settings_FAQ))
|
|
}
|
|
|
|
return entries
|
|
}
|
|
|
|
public func settingsController(account: Account, accountManager: AccountManager) -> ViewController {
|
|
let statePromise = ValuePromise(SettingsState(), ignoreRepeated: true)
|
|
let stateValue = Atomic(value: SettingsState())
|
|
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 cachedDataDisposable = MetaDisposable()
|
|
actionsDisposable.add(cachedDataDisposable)
|
|
|
|
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)?
|
|
var changeProfilePhotoImpl: (() -> Void)?
|
|
var openSavedMessagesImpl: (() -> Void)?
|
|
|
|
let openFaq: () -> Void = {
|
|
let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
|
|
var faqUrl = presentationData.strings.Settings_FAQ_URL
|
|
if faqUrl == "Settings.FAQ_URL" || faqUrl.isEmpty {
|
|
faqUrl = "https://telegram.org/faq#general"
|
|
}
|
|
|
|
if let applicationContext = account.applicationContext as? TelegramApplicationContext {
|
|
applicationContext.applicationBindings.openUrl(faqUrl)
|
|
}
|
|
}
|
|
|
|
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
|
|
if peer.smallProfileImage != nil {
|
|
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)
|
|
}))
|
|
} else {
|
|
changeProfilePhotoImpl?()
|
|
}
|
|
})
|
|
}, changeProfilePhoto: {
|
|
changeProfilePhotoImpl?()
|
|
}, openUsername: {
|
|
presentControllerImpl?(usernameSetupController(account: account), nil)
|
|
}, openProxy: {
|
|
pushControllerImpl?(proxySettingsController(account: account))
|
|
}, openSavedMessages: {
|
|
openSavedMessagesImpl?()
|
|
}, openRecentCalls: {
|
|
pushControllerImpl?(CallListController(account: account, mode: .navigation))
|
|
}, openPrivacyAndSecurity: {
|
|
pushControllerImpl?(privacyAndSecurityController(account: account, initialSettings: .single(nil) |> then(requestAccountPrivacySettings(account: account) |> map(Optional.init))))
|
|
}, openDataAndStorage: {
|
|
pushControllerImpl?(dataAndStorageController(account: account))
|
|
}, openThemes: {
|
|
pushControllerImpl?(themeSettingsController(account: account))
|
|
}, pushController: { controller in
|
|
pushControllerImpl?(controller)
|
|
}, presentController: { controller in
|
|
presentControllerImpl?(controller, nil)
|
|
}, openLanguage: {
|
|
let controller = LanguageSelectionController(account: account)
|
|
presentControllerImpl?(controller, nil)
|
|
}, openPassport: {
|
|
let controller = SecureIdAuthController(account: account, mode: .list)
|
|
presentControllerImpl?(controller, nil)
|
|
}, openSupport: {
|
|
let supportPeer = Promise<PeerId?>()
|
|
supportPeer.set(supportPeerId(account: account))
|
|
let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
|
|
presentControllerImpl?(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: nil, text: presentationData.strings.Settings_FAQ_Intro, actions: [
|
|
TextAlertAction(type: .genericAction, title: presentationData.strings.Settings_FAQ_Button, action: {
|
|
openFaq()
|
|
}),
|
|
TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {
|
|
supportPeerDisposable.set((supportPeer.get() |> take(1) |> deliverOnMainQueue).start(next: { peerId in
|
|
if let peerId = peerId {
|
|
pushControllerImpl?(ChatController(account: account, chatLocation: .peer(peerId)))
|
|
}
|
|
}))
|
|
})
|
|
]), nil)
|
|
}, openFaq: {
|
|
openFaq()
|
|
}, openEditing: {
|
|
let _ = (account.postbox.transaction { transaction -> (Peer?, CachedPeerData?) in
|
|
return (transaction.getPeer(account.peerId), transaction.getPeerCachedData(peerId: account.peerId))
|
|
} |> deliverOnMainQueue).start(next: { peer, cachedData in
|
|
if let peer = peer as? TelegramUser, let cachedData = cachedData as? CachedUserData {
|
|
pushControllerImpl?(editSettingsController(account: account, currentName: .personName(firstName: peer.firstName ?? "", lastName: peer.lastName ?? ""), currentBioText: cachedData.about ?? "", accountManager: accountManager))
|
|
}
|
|
})
|
|
})
|
|
|
|
changeProfilePhotoImpl = {
|
|
let _ = (account.postbox.transaction { transaction -> Peer? in
|
|
return transaction.getPeer(account.peerId)
|
|
} |> deliverOnMainQueue).start(next: { peer in
|
|
let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
|
|
|
|
let legacyController = LegacyController(presentation: .custom, theme: presentationData.theme)
|
|
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)
|
|
|
|
var hasPhotos = false
|
|
if let peer = peer, !peer.profileImageRepresentations.isEmpty {
|
|
hasPhotos = true
|
|
}
|
|
|
|
let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasDeleteButton: hasPhotos, 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(.image(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.didFinishWithDelete = {
|
|
let _ = currentAvatarMixin.swap(nil)
|
|
updateState {
|
|
if let profileImage = peer?.smallProfileImage {
|
|
return $0.withUpdatedUpdatingAvatar(.image(profileImage))
|
|
} else {
|
|
return $0.withUpdatedUpdatingAvatar(.none)
|
|
}
|
|
}
|
|
updateAvatarDisposable.set((updateAccountPhoto(account: account, resource: nil) |> 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()
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
let peerView = account.viewTracker.peerView(account.peerId)
|
|
|
|
let signal = combineLatest((account.applicationContext as! TelegramApplicationContext).presentationData, statePromise.get(), peerView, account.postbox.preferencesView(keys: [PreferencesKeys.proxySettings]), account.viewTracker.featuredStickerPacks())
|
|
|> map { presentationData, state, view, preferences, featuredStickerPacks -> (ItemListControllerState, (ItemListNodeState<SettingsEntry>, SettingsEntry.ItemGenerationArguments)) in
|
|
let proxySettings: ProxySettings
|
|
if let value = preferences.values[PreferencesKeys.proxySettings] as? ProxySettings {
|
|
proxySettings = value
|
|
} else {
|
|
proxySettings = ProxySettings.defaultSettings
|
|
}
|
|
|
|
let peer = peerViewMainPeer(view)
|
|
let rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Edit), style: .regular, enabled: true, action: {
|
|
if let _ = peer as? TelegramUser, let _ = view.cachedData as? CachedUserData {
|
|
arguments.openEditing()
|
|
}
|
|
})
|
|
|
|
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Settings_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
|
|
|
var unreadTrendingStickerPacks = 0
|
|
for item in featuredStickerPacks {
|
|
if item.unread {
|
|
unreadTrendingStickerPacks += 1
|
|
}
|
|
}
|
|
|
|
let listState = ItemListNodeState(entries: settingsEntries(presentationData: presentationData, state: state, view: view, proxySettings: proxySettings, unreadTrendingStickerPacks: unreadTrendingStickerPacks), 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, () -> UIView?), 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()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
openSavedMessagesImpl = { [weak controller] in
|
|
if let controller = controller, let navigationController = controller.navigationController as? NavigationController {
|
|
navigateToChatController(navigationController: navigationController, account: account, chatLocation: .peer(account.peerId))
|
|
}
|
|
}
|
|
controller.tabBarItemDebugTapAction = {
|
|
pushControllerImpl?(debugController(account: account, accountManager: accountManager))
|
|
}
|
|
return controller
|
|
}
|
|
|