mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-15 18:59:54 +00:00
Move contacts sync settings back to individual accounts
This commit is contained in:
parent
5b04bba7b2
commit
55aa20c2a5
@ -134,10 +134,10 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
}).start()
|
||||
}
|
||||
})
|
||||
controller.loginWithNumber = { [weak self, weak controller] number in
|
||||
controller.loginWithNumber = { [weak self, weak controller] number, syncContacts in
|
||||
if let strongSelf = self {
|
||||
controller?.inProgress = true
|
||||
strongSelf.actionDisposable.set((sendAuthorizationCode(accountManager: strongSelf.sharedContext.accountManager, account: strongSelf.account, phoneNumber: number, apiId: strongSelf.apiId, apiHash: strongSelf.apiHash) |> deliverOnMainQueue).start(next: { [weak self] account in
|
||||
strongSelf.actionDisposable.set((sendAuthorizationCode(accountManager: strongSelf.sharedContext.accountManager, account: strongSelf.account, phoneNumber: number, apiId: strongSelf.apiId, apiHash: strongSelf.apiHash, syncContacts: syncContacts) |> deliverOnMainQueue).start(next: { [weak self] account in
|
||||
if let strongSelf = self {
|
||||
controller?.inProgress = false
|
||||
strongSelf.account = account
|
||||
@ -399,7 +399,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
return controller
|
||||
}
|
||||
|
||||
private func passwordEntryController(hint: String, suggestReset: Bool) -> AuthorizationSequencePasswordEntryController {
|
||||
private func passwordEntryController(hint: String, suggestReset: Bool, syncContacts: Bool) -> AuthorizationSequencePasswordEntryController {
|
||||
var currentController: AuthorizationSequencePasswordEntryController?
|
||||
for c in self.viewControllers {
|
||||
if let c = c as? AuthorizationSequencePasswordEntryController {
|
||||
@ -425,7 +425,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
if let strongSelf = self {
|
||||
controller?.inProgress = true
|
||||
|
||||
strongSelf.actionDisposable.set((authorizeWithPassword(accountManager: strongSelf.sharedContext.accountManager, account: strongSelf.account, password: password) |> deliverOnMainQueue).start(error: { error in
|
||||
strongSelf.actionDisposable.set((authorizeWithPassword(accountManager: strongSelf.sharedContext.accountManager, account: strongSelf.account, password: password, syncContacts: syncContacts) |> deliverOnMainQueue).start(error: { error in
|
||||
Queue.mainQueue().async {
|
||||
if let strongSelf = self, let controller = controller {
|
||||
controller.inProgress = false
|
||||
@ -458,8 +458,8 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
switch option {
|
||||
case let .email(pattern):
|
||||
let _ = (strongSelf.account.postbox.transaction { transaction -> Void in
|
||||
if let state = transaction.getState() as? UnauthorizedAccountState, case let .passwordEntry(hint, number, code, _) = state.contents {
|
||||
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .passwordRecovery(hint: hint, number: number, code: code, emailPattern: pattern)))
|
||||
if let state = transaction.getState() as? UnauthorizedAccountState, case let .passwordEntry(hint, number, code, _, syncContacts) = state.contents {
|
||||
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: strongSelf.account.testingEnvironment, masterDatacenterId: strongSelf.account.masterDatacenterId, contents: .passwordRecovery(hint: hint, number: number, code: code, emailPattern: pattern, syncContacts: syncContacts)))
|
||||
}
|
||||
}).start()
|
||||
case .none:
|
||||
@ -507,7 +507,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
return controller
|
||||
}
|
||||
|
||||
private func passwordRecoveryController(emailPattern: String) -> AuthorizationSequencePasswordRecoveryController {
|
||||
private func passwordRecoveryController(emailPattern: String, syncContacts: Bool) -> AuthorizationSequencePasswordRecoveryController {
|
||||
var currentController: AuthorizationSequencePasswordRecoveryController?
|
||||
for c in self.viewControllers {
|
||||
if let c = c as? AuthorizationSequencePasswordRecoveryController {
|
||||
@ -533,7 +533,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
if let strongSelf = self {
|
||||
controller?.inProgress = true
|
||||
|
||||
strongSelf.actionDisposable.set((performPasswordRecovery(accountManager: strongSelf.sharedContext.accountManager, account: strongSelf.account, code: code) |> deliverOnMainQueue).start(error: { error in
|
||||
strongSelf.actionDisposable.set((performPasswordRecovery(accountManager: strongSelf.sharedContext.accountManager, account: strongSelf.account, code: code, syncContacts: syncContacts) |> deliverOnMainQueue).start(error: { error in
|
||||
Queue.mainQueue().async {
|
||||
if let strongSelf = self, let controller = controller {
|
||||
controller.inProgress = false
|
||||
@ -559,8 +559,8 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
controller.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.theme), title: nil, text: strongSelf.strings.TwoStepAuth_RecoveryFailed, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
let account = strongSelf.account
|
||||
let _ = (strongSelf.account.postbox.transaction { transaction -> Void in
|
||||
if let state = transaction.getState() as? UnauthorizedAccountState, case let .passwordRecovery(hint, number, code, _) = state.contents {
|
||||
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .passwordEntry(hint: hint, number: number, code: code, suggestReset: true)))
|
||||
if let state = transaction.getState() as? UnauthorizedAccountState, case let .passwordRecovery(hint, number, code, _, syncContacts) = state.contents {
|
||||
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .passwordEntry(hint: hint, number: number, code: code, suggestReset: true, syncContacts: syncContacts)))
|
||||
}
|
||||
}).start()
|
||||
}
|
||||
@ -715,7 +715,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
}
|
||||
controllers.append(self.phoneEntryController(countryCode: countryCode, number: number))
|
||||
self.setViewControllers(controllers, animated: !self.viewControllers.isEmpty)
|
||||
case let .confirmationCodeEntry(number, type, _, timeout, nextType, termsOfService):
|
||||
case let .confirmationCodeEntry(number, type, _, timeout, nextType, termsOfService, syncContacts):
|
||||
var controllers: [ViewController] = []
|
||||
if !self.otherAccountPhoneNumbers.1.isEmpty {
|
||||
controllers.append(self.splashController())
|
||||
@ -723,28 +723,28 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
||||
controllers.append(self.phoneEntryController(countryCode: defaultCountryCode(), number: ""))
|
||||
controllers.append(self.codeEntryController(number: number, type: type, nextType: nextType, timeout: timeout, termsOfService: termsOfService))
|
||||
self.setViewControllers(controllers, animated: !self.viewControllers.isEmpty)
|
||||
case let .passwordEntry(hint, _, _, suggestReset):
|
||||
case let .passwordEntry(hint, _, _, suggestReset, syncContacts):
|
||||
var controllers: [ViewController] = []
|
||||
if !self.otherAccountPhoneNumbers.1.isEmpty {
|
||||
controllers.append(self.splashController())
|
||||
}
|
||||
controllers.append(self.passwordEntryController(hint: hint, suggestReset: suggestReset))
|
||||
controllers.append(self.passwordEntryController(hint: hint, suggestReset: suggestReset, syncContacts: syncContacts))
|
||||
self.setViewControllers(controllers, animated: !self.viewControllers.isEmpty)
|
||||
case let .passwordRecovery(_, _, _, emailPattern):
|
||||
case let .passwordRecovery(_, _, _, emailPattern, syncContacts):
|
||||
var controllers: [ViewController] = []
|
||||
if !self.otherAccountPhoneNumbers.1.isEmpty {
|
||||
controllers.append(self.splashController())
|
||||
}
|
||||
controllers.append(self.passwordRecoveryController(emailPattern: emailPattern))
|
||||
controllers.append(self.passwordRecoveryController(emailPattern: emailPattern, syncContacts: syncContacts))
|
||||
self.setViewControllers(controllers, animated: !self.viewControllers.isEmpty)
|
||||
case let .awaitingAccountReset(protectedUntil, number):
|
||||
case let .awaitingAccountReset(protectedUntil, number, _):
|
||||
var controllers: [ViewController] = []
|
||||
if !self.otherAccountPhoneNumbers.1.isEmpty {
|
||||
controllers.append(self.splashController())
|
||||
}
|
||||
controllers.append(self.awaitingAccountResetController(protectedUntil: protectedUntil, number: number))
|
||||
self.setViewControllers(controllers, animated: !self.viewControllers.isEmpty)
|
||||
case let .signUp(_, _, _, firstName, lastName, termsOfService):
|
||||
case let .signUp(_, _, _, firstName, lastName, termsOfService, syncContacts):
|
||||
var controllers: [ViewController] = []
|
||||
if !self.otherAccountPhoneNumbers.1.isEmpty {
|
||||
controllers.append(self.splashController())
|
||||
|
||||
@ -33,7 +33,7 @@ final class AuthorizationSequencePhoneEntryController: ViewController {
|
||||
self.controllerNode.inProgress = self.inProgress
|
||||
}
|
||||
}
|
||||
var loginWithNumber: ((String) -> Void)?
|
||||
var loginWithNumber: ((String, Bool) -> Void)?
|
||||
|
||||
private let termsDisposable = MetaDisposable()
|
||||
|
||||
@ -94,7 +94,7 @@ final class AuthorizationSequencePhoneEntryController: ViewController {
|
||||
return
|
||||
}
|
||||
self?.present(debugController(sharedContext: strongSelf.sharedContext, context: nil, modal: true), in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
})
|
||||
}, hasOtherAccounts: self.otherAccountPhoneNumbers.0 != nil)
|
||||
if let (code, name, number) = self.currentData {
|
||||
self.controllerNode.codeAndNumber = (code, name, number)
|
||||
}
|
||||
@ -160,7 +160,7 @@ final class AuthorizationSequencePhoneEntryController: ViewController {
|
||||
actions.append(TextAlertAction(type: .defaultAction, title: self.strings.Common_OK, action: {}))
|
||||
self.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: self.theme), title: nil, text: self.strings.Login_PhoneNumberAlreadyAuthorized, actions: actions), in: .window(.root))
|
||||
} else {
|
||||
self.loginWithNumber?(self.controllerNode.currentNumber)
|
||||
self.loginWithNumber?(self.controllerNode.currentNumber, self.controllerNode.syncContacts)
|
||||
}
|
||||
} else {
|
||||
hapticFeedback.error()
|
||||
|
||||
@ -162,14 +162,42 @@ private final class PhoneAndCountryNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
private final class ContactSyncNode: ASDisplayNode {
|
||||
private let titleNode: ImmediateTextNode
|
||||
let switchNode: SwitchNode
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings) {
|
||||
self.titleNode = ImmediateTextNode()
|
||||
self.titleNode.maximumNumberOfLines = 1
|
||||
self.titleNode.attributedText = NSAttributedString(string: strings.Privacy_ContactsSync, font: Font.regular(17.0), textColor: theme.list.itemPrimaryTextColor)
|
||||
self.switchNode = SwitchNode()
|
||||
self.switchNode.isOn = true
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.titleNode)
|
||||
self.addSubnode(self.switchNode)
|
||||
}
|
||||
|
||||
func updateLayout(width: CGFloat) -> CGSize {
|
||||
let switchSize = CGSize(width: 51.0, height: 31.0)
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: width - switchSize.width - 16.0 * 2.0 - 8.0, height: .greatestFiniteMagnitude))
|
||||
let height: CGFloat = 40.0
|
||||
self.titleNode.frame = CGRect(origin: CGPoint(x: 16.0, y: floor((height - titleSize.height) / 2.0)), size: titleSize)
|
||||
self.switchNode.frame = CGRect(origin: CGPoint(x: width - 16.0 - switchSize.width, y: floor((height - switchSize.height) / 2.0)), size: switchSize)
|
||||
return CGSize(width: width, height: height)
|
||||
}
|
||||
}
|
||||
|
||||
final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
private let strings: PresentationStrings
|
||||
private let theme: PresentationTheme
|
||||
private let hasOtherAccounts: Bool
|
||||
|
||||
private let titleNode: ASTextNode
|
||||
private let noticeNode: ASTextNode
|
||||
private let phoneAndCountryNode: PhoneAndCountryNode
|
||||
private let termsOfServiceNode: ImmediateTextNode
|
||||
private let contactSyncNode: ContactSyncNode
|
||||
|
||||
private let debugAction: () -> Void
|
||||
|
||||
@ -185,6 +213,16 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
var syncContacts: Bool {
|
||||
get {
|
||||
if self.hasOtherAccounts {
|
||||
return self.contactSyncNode.switchNode.isOn
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var selectCountryCode: (() -> Void)?
|
||||
var checkPhone: (() -> Void)?
|
||||
|
||||
@ -196,10 +234,11 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
init(strings: PresentationStrings, theme: PresentationTheme, debugAction: @escaping () -> Void) {
|
||||
init(strings: PresentationStrings, theme: PresentationTheme, debugAction: @escaping () -> Void, hasOtherAccounts: Bool) {
|
||||
self.strings = strings
|
||||
self.theme = theme
|
||||
self.debugAction = debugAction
|
||||
self.hasOtherAccounts = hasOtherAccounts
|
||||
|
||||
self.titleNode = ASTextNode()
|
||||
self.titleNode.isUserInteractionEnabled = true
|
||||
@ -211,18 +250,7 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
self.noticeNode.displaysAsynchronously = false
|
||||
self.noticeNode.attributedText = NSAttributedString(string: strings.Login_PhoneAndCountryHelp, font: Font.regular(16.0), textColor: theme.list.itemPrimaryTextColor, paragraphAlignment: .center)
|
||||
|
||||
self.termsOfServiceNode = ImmediateTextNode()
|
||||
self.termsOfServiceNode.maximumNumberOfLines = 0
|
||||
self.termsOfServiceNode.textAlignment = .center
|
||||
self.termsOfServiceNode.displaysAsynchronously = false
|
||||
|
||||
let termsOfServiceAttributes = MarkdownAttributeSet(font: Font.regular(16.0), textColor: self.theme.list.itemPrimaryTextColor)
|
||||
let termsOfServiceLinkAttributes = MarkdownAttributeSet(font: Font.regular(16.0), textColor: self.theme.list.itemAccentColor, additionalAttributes: [NSAttributedStringKey.underlineStyle.rawValue: NSUnderlineStyle.styleSingle.rawValue as NSNumber, TelegramTextAttributes.URL: ""])
|
||||
|
||||
let termsString = parseMarkdownIntoAttributedString(self.strings.Login_TermsOfServiceLabel.replacingOccurrences(of: "]", with: "]()"), attributes: MarkdownAttributes(body: termsOfServiceAttributes, bold: termsOfServiceAttributes, link: termsOfServiceLinkAttributes, linkAttribute: { _ in
|
||||
return nil
|
||||
}), textAlignment: .center)
|
||||
self.termsOfServiceNode.attributedText = termsString
|
||||
self.contactSyncNode = ContactSyncNode(theme: theme, strings: strings)
|
||||
|
||||
self.phoneAndCountryNode = PhoneAndCountryNode(strings: strings, theme: theme)
|
||||
|
||||
@ -235,9 +263,10 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
self.backgroundColor = theme.list.plainBackgroundColor
|
||||
|
||||
self.addSubnode(self.titleNode)
|
||||
//self.addSubnode(self.termsOfServiceNode)
|
||||
self.addSubnode(self.noticeNode)
|
||||
self.addSubnode(self.phoneAndCountryNode)
|
||||
self.addSubnode(self.contactSyncNode)
|
||||
self.contactSyncNode.isHidden = true
|
||||
|
||||
self.phoneAndCountryNode.selectCountryCode = { [weak self] in
|
||||
self?.selectCountryCode?()
|
||||
@ -245,19 +274,6 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
self.phoneAndCountryNode.checkPhone = { [weak self] in
|
||||
self?.checkPhone?()
|
||||
}
|
||||
|
||||
self.termsOfServiceNode.highlightAttributeAction = { attributes in
|
||||
if let _ = attributes[NSAttributedStringKey(rawValue: TelegramTextAttributes.URL)] {
|
||||
return NSAttributedStringKey(rawValue: TelegramTextAttributes.URL)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
self.termsOfServiceNode.tapAttributeAction = { attributes in
|
||||
if let _ = attributes[NSAttributedStringKey(rawValue: TelegramTextAttributes.URL)] as? String {
|
||||
}
|
||||
}
|
||||
self.termsOfServiceNode.linkHighlightColor = theme.list.itemAccentColor.withAlphaComponent(0.5)
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
@ -292,14 +308,15 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
AuthorizationLayoutItem(node: self.noticeNode, size: noticeSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 18.0, maxValue: 18.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)),
|
||||
AuthorizationLayoutItem(node: self.phoneAndCountryNode, size: CGSize(width: layout.size.width, height: 115.0), spacingBefore: AuthorizationLayoutItemSpacing(weight: 44.0, maxValue: 44.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))
|
||||
]
|
||||
|
||||
if layoutAuthorizationItems(bounds: CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: layout.size.width, height: layout.size.height - insets.top - insets.bottom - 10.0)), items: items, transition: transition, failIfDoesNotFit: true) {
|
||||
self.termsOfServiceNode.isHidden = false
|
||||
let contactSyncSize = self.contactSyncNode.updateLayout(width: layout.size.width)
|
||||
if self.hasOtherAccounts {
|
||||
self.contactSyncNode.isHidden = false
|
||||
items.append(AuthorizationLayoutItem(node: self.contactSyncNode, size: contactSyncSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 16.0, maxValue: 16.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))
|
||||
} else {
|
||||
items.removeLast()
|
||||
let _ = layoutAuthorizationItems(bounds: CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: layout.size.width, height: layout.size.height - insets.top - insets.bottom - 10.0)), items: items, transition: transition, failIfDoesNotFit: false)
|
||||
self.termsOfServiceNode.isHidden = true
|
||||
self.contactSyncNode.isHidden = true
|
||||
}
|
||||
|
||||
let _ = layoutAuthorizationItems(bounds: CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: layout.size.width, height: layout.size.height - insets.top - insets.bottom - 10.0)), items: items, transition: transition, failIfDoesNotFit: false)
|
||||
}
|
||||
|
||||
func activateInput() {
|
||||
|
||||
@ -209,6 +209,7 @@ public final class ChatController: TelegramController, KeyShortcutResponder, Gal
|
||||
private weak var silentPostTooltipController: TooltipController?
|
||||
private weak var mediaRecordingModeTooltipController: TooltipController?
|
||||
private weak var mediaRestrictedTooltipController: TooltipController?
|
||||
private var forwardDisabledNoticeTooltipController: TooltipController?
|
||||
private var mediaRestrictedTooltipControllerMode = true
|
||||
|
||||
private var screenCaptureEventsDisposable: Disposable?
|
||||
@ -1158,6 +1159,24 @@ public final class ChatController: TelegramController, KeyShortcutResponder, Gal
|
||||
}, cancelInteractiveKeyboardGestures: { [weak self] in
|
||||
(self?.view.window as? WindowHost)?.cancelInteractiveKeyboardGestures()
|
||||
self?.chatDisplayNode.cancelInteractiveKeyboardGestures()
|
||||
}, displayForwardDisabledNotice: { [weak self] sourceNode, sourceRect, name in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.forwardDisabledNoticeTooltipController?.dismiss()
|
||||
let tooltipController = TooltipController(content: .text(strongSelf.presentationInterfaceState.strings.Chat_ForwardHiddenAccount(name).0), timeout: 2.0, dismissByTapOutside: true)
|
||||
strongSelf.forwardDisabledNoticeTooltipController = tooltipController
|
||||
tooltipController.dismissed = { [weak tooltipController] in
|
||||
if let strongSelf = self, let tooltipController = tooltipController, strongSelf.forwardDisabledNoticeTooltipController === tooltipController {
|
||||
strongSelf.forwardDisabledNoticeTooltipController = nil
|
||||
}
|
||||
}
|
||||
strongSelf.present(tooltipController, in: .window(.root), with: TooltipControllerPresentationArguments(sourceNodeAndRect: {
|
||||
if let strongSelf = self {
|
||||
return (sourceNode, sourceRect)
|
||||
}
|
||||
return nil
|
||||
}))
|
||||
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings,
|
||||
pollActionState: ChatInterfacePollActionState())
|
||||
|
||||
|
||||
@ -90,6 +90,8 @@ public final class ChatControllerInteraction {
|
||||
let requestMessageUpdate: (MessageId) -> Void
|
||||
let cancelInteractiveKeyboardGestures: () -> Void
|
||||
|
||||
let displayForwardDisabledNotice: (ASDisplayNode, CGRect, String) -> Void
|
||||
|
||||
var hiddenMedia: [MessageId: [Media]] = [:]
|
||||
var selectionState: ChatInterfaceSelectionState?
|
||||
var highlightedState: ChatInterfaceHighlightedState?
|
||||
@ -98,7 +100,7 @@ public final class ChatControllerInteraction {
|
||||
var pollActionState: ChatInterfacePollActionState
|
||||
var searchTextHighightState: String?
|
||||
|
||||
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool) -> Void, sendGif: @escaping (FileMediaReference) -> Void, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOption: @escaping (MessageId, Data) -> Void, openAppStorePage: @escaping () -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState) {
|
||||
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool) -> Void, sendGif: @escaping (FileMediaReference) -> Void, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOption: @escaping (MessageId, Data) -> Void, openAppStorePage: @escaping () -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, displayForwardDisabledNotice: @escaping (ASDisplayNode, CGRect, String) -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState) {
|
||||
self.openMessage = openMessage
|
||||
self.openPeer = openPeer
|
||||
self.openPeerMention = openPeerMention
|
||||
@ -139,6 +141,7 @@ public final class ChatControllerInteraction {
|
||||
|
||||
self.requestMessageUpdate = requestMessageUpdate
|
||||
self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures
|
||||
self.displayForwardDisabledNotice = displayForwardDisabledNotice
|
||||
|
||||
self.automaticMediaDownloadSettings = automaticMediaDownloadSettings
|
||||
|
||||
@ -161,7 +164,7 @@ public final class ChatControllerInteraction {
|
||||
}, openAppStorePage: {
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||
}, displayForwardDisabledNotice: { _, _, _ in }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||
pollActionState: ChatInterfacePollActionState())
|
||||
}
|
||||
}
|
||||
|
||||
@ -1597,6 +1597,8 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
|
||||
item.controllerInteraction.navigateToMessage(item.message.id, sourceMessageId)
|
||||
} else if let id = forwardInfo.source?.id ?? forwardInfo.author?.id {
|
||||
item.controllerInteraction.openPeer(id, .info, nil)
|
||||
} else if let authorSignature = forwardInfo.authorSignature {
|
||||
item.controllerInteraction.displayForwardDisabledNotice(forwardInfoNode, forwardInfoNode.bounds, authorSignature)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -364,7 +364,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
||||
}
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings,
|
||||
}, displayForwardDisabledNotice: { _, _, _ in }, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings,
|
||||
pollActionState: ChatInterfacePollActionState())
|
||||
self.controllerInteraction = controllerInteraction
|
||||
|
||||
|
||||
@ -819,9 +819,10 @@ final class ContactListNode: ASDisplayNode {
|
||||
let contactsWarningSuppressed = Promise<(Bool, Bool)>()
|
||||
contactsWarningSuppressed.set(.single((false, false))
|
||||
|> then(
|
||||
combineLatest(context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.contactsPermissionWarningKey()), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.contactSynchronizationSettings]))
|
||||
|> map { noticeView, sharedData -> (Bool, Bool) in
|
||||
let synchronizeDeviceContacts: Bool = (sharedData.entries[ApplicationSpecificSharedDataKeys.contactSynchronizationSettings] as? ContactSynchronizationSettings)?.synchronizeDeviceContacts ?? true
|
||||
combineLatest(context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.contactsPermissionWarningKey()), context.account.postbox.preferencesView(keys: [PreferencesKeys.contactsSettings]))
|
||||
|> map { noticeView, preferences -> (Bool, Bool) in
|
||||
let settings: ContactsSettings = preferences.values[PreferencesKeys.contactsSettings] as? ContactsSettings ?? ContactsSettings.defaultSettings
|
||||
let synchronizeDeviceContacts: Bool = settings.synchronizeContacts
|
||||
let suppressed: Bool
|
||||
let timestamp = noticeView.value.flatMap({ ApplicationSpecificNotice.getTimestampValue($0) })
|
||||
if let timestamp = timestamp, timestamp > 0 {
|
||||
|
||||
@ -8,28 +8,28 @@ public enum ContactsSortOrder: Int32 {
|
||||
}
|
||||
|
||||
public struct ContactSynchronizationSettings: Equatable, PreferencesEntry {
|
||||
public var synchronizeDeviceContacts: Bool
|
||||
public var _legacySynchronizeDeviceContacts: Bool
|
||||
public var nameDisplayOrder: PresentationPersonNameOrder
|
||||
public var sortOrder: ContactsSortOrder
|
||||
|
||||
public static var defaultSettings: ContactSynchronizationSettings {
|
||||
return ContactSynchronizationSettings(synchronizeDeviceContacts: true, nameDisplayOrder: .firstLast, sortOrder: .presence)
|
||||
return ContactSynchronizationSettings(_legacySynchronizeDeviceContacts: true, nameDisplayOrder: .firstLast, sortOrder: .presence)
|
||||
}
|
||||
|
||||
public init(synchronizeDeviceContacts: Bool, nameDisplayOrder: PresentationPersonNameOrder, sortOrder: ContactsSortOrder) {
|
||||
self.synchronizeDeviceContacts = synchronizeDeviceContacts
|
||||
public init(_legacySynchronizeDeviceContacts: Bool, nameDisplayOrder: PresentationPersonNameOrder, sortOrder: ContactsSortOrder) {
|
||||
self._legacySynchronizeDeviceContacts = _legacySynchronizeDeviceContacts
|
||||
self.nameDisplayOrder = nameDisplayOrder
|
||||
self.sortOrder = sortOrder
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.synchronizeDeviceContacts = decoder.decodeInt32ForKey("synchronizeDeviceContacts", orElse: 0) != 0
|
||||
self._legacySynchronizeDeviceContacts = decoder.decodeInt32ForKey("synchronizeDeviceContacts", orElse: 0) != 0
|
||||
self.nameDisplayOrder = PresentationPersonNameOrder(rawValue: decoder.decodeInt32ForKey("nameDisplayOrder", orElse: 0)) ?? .firstLast
|
||||
self.sortOrder = ContactsSortOrder(rawValue: decoder.decodeInt32ForKey("sortOrder", orElse: 0)) ?? .presence
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeInt32(self.synchronizeDeviceContacts ? 1 : 0, forKey: "synchronizeDeviceContacts")
|
||||
encoder.encodeInt32(self._legacySynchronizeDeviceContacts ? 1 : 0, forKey: "synchronizeDeviceContacts")
|
||||
encoder.encodeInt32(self.nameDisplayOrder.rawValue, forKey: "nameDisplayOrder")
|
||||
encoder.encodeInt32(self.sortOrder.rawValue, forKey: "sortOrder")
|
||||
}
|
||||
|
||||
@ -119,11 +119,14 @@ public class ContactsController: ViewController {
|
||||
})
|
||||
|
||||
if #available(iOSApplicationExtension 10.0, *) {
|
||||
self.authorizationDisposable = (combineLatest(DeviceAccess.authorizationStatus(context: context, subject: .contacts), combineLatest(context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.contactsPermissionWarningKey()), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.contactSynchronizationSettings]))
|
||||
|> map { noticeView, sharedData -> (Bool, ContactsSortOrder) in
|
||||
let settings = sharedData.entries[ApplicationSpecificSharedDataKeys.contactSynchronizationSettings] as? ContactSynchronizationSettings
|
||||
let synchronizeDeviceContacts: Bool = settings?.synchronizeDeviceContacts ?? true
|
||||
let sortOrder: ContactsSortOrder = settings?.sortOrder ?? .presence
|
||||
self.authorizationDisposable = (combineLatest(DeviceAccess.authorizationStatus(context: context, subject: .contacts), combineLatest(context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.contactsPermissionWarningKey()), context.account.postbox.preferencesView(keys: [PreferencesKeys.contactsSettings]), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.contactSynchronizationSettings]))
|
||||
|> map { noticeView, preferences, sharedData -> (Bool, ContactsSortOrder) in
|
||||
let settings: ContactsSettings = preferences.values[PreferencesKeys.contactsSettings] as? ContactsSettings ?? ContactsSettings.defaultSettings
|
||||
let synchronizeDeviceContacts: Bool = settings.synchronizeContacts
|
||||
|
||||
let contactsSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.contactSynchronizationSettings] as? ContactSynchronizationSettings
|
||||
|
||||
let sortOrder: ContactsSortOrder = contactsSettings?.sortOrder ?? .presence
|
||||
if !synchronizeDeviceContacts {
|
||||
return (true, sortOrder)
|
||||
}
|
||||
|
||||
@ -394,11 +394,13 @@ public func dataPrivacyController(context: AccountContext) -> ViewController {
|
||||
return
|
||||
}
|
||||
|
||||
let _ = updateContactSettingsInteractively(accountManager: context.sharedContext.accountManager, { settings in
|
||||
var settings = settings
|
||||
settings.synchronizeDeviceContacts = false
|
||||
return settings
|
||||
})
|
||||
let _ = context.account.postbox.transaction({ transaction in
|
||||
transaction.updatePreferencesEntry(key: PreferencesKeys.contactsSettings, { current in
|
||||
var settings = current as? ContactsSettings ?? ContactsSettings.defaultSettings
|
||||
settings.synchronizeContacts = false
|
||||
return settings
|
||||
})
|
||||
}).start()
|
||||
|
||||
actionsDisposable.add(((deleteAllContacts(postbox: context.account.postbox, network: context.account.network) |> then(resetSavedContacts(network: context.account.network)))
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
@ -413,10 +415,12 @@ public func dataPrivacyController(context: AccountContext) -> ViewController {
|
||||
}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {})]))
|
||||
}
|
||||
}, updateSyncContacts: { value in
|
||||
let _ = updateContactSettingsInteractively(accountManager: context.sharedContext.accountManager, { settings in
|
||||
var settings = settings
|
||||
settings.synchronizeDeviceContacts = value
|
||||
return settings
|
||||
let _ = context.account.postbox.transaction({ transaction in
|
||||
transaction.updatePreferencesEntry(key: PreferencesKeys.contactsSettings, { current in
|
||||
var settings = current as? ContactsSettings ?? ContactsSettings.defaultSettings
|
||||
settings.synchronizeContacts = value
|
||||
return settings
|
||||
})
|
||||
}).start()
|
||||
}, updateSuggestFrequentContacts: { value in
|
||||
let apply: () -> Void = {
|
||||
@ -477,11 +481,13 @@ public func dataPrivacyController(context: AccountContext) -> ViewController {
|
||||
|
||||
actionsDisposable.add(managedUpdatedRecentPeers(accountPeerId: context.account.peerId, postbox: context.account.postbox, network: context.account.network).start())
|
||||
|
||||
let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, statePromise.get(), context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.secretChatLinkPreviewsKey()), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.contactSynchronizationSettings]), recentPeers(account: context.account))
|
||||
|> map { presentationData, state, noticeView, sharedData, recentPeers -> (ItemListControllerState, (ItemListNodeState<PrivacyAndSecurityEntry>, PrivacyAndSecurityEntry.ItemGenerationArguments)) in
|
||||
let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, statePromise.get(), context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.secretChatLinkPreviewsKey()), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.contactSynchronizationSettings]), context.account.postbox.preferencesView(keys: [PreferencesKeys.contactsSettings]), recentPeers(account: context.account))
|
||||
|> map { presentationData, state, noticeView, sharedData, preferences, recentPeers -> (ItemListControllerState, (ItemListNodeState<PrivacyAndSecurityEntry>, PrivacyAndSecurityEntry.ItemGenerationArguments)) in
|
||||
let secretChatLinkPreviews = noticeView.value.flatMap({ ApplicationSpecificNotice.getSecretChatLinkPreviews($0) })
|
||||
|
||||
let synchronizeDeviceContacts: Bool = (sharedData.entries[ApplicationSpecificSharedDataKeys.contactSynchronizationSettings] as? ContactSynchronizationSettings)?.synchronizeDeviceContacts ?? true
|
||||
let settings: ContactsSettings = preferences.values[PreferencesKeys.contactsSettings] as? ContactsSettings ?? ContactsSettings.defaultSettings
|
||||
|
||||
let synchronizeDeviceContacts: Bool = settings.synchronizeContacts
|
||||
|
||||
let suggestRecentPeers: Bool
|
||||
if let updatedSuggestFrequentContacts = state.updatedSuggestFrequentContacts {
|
||||
|
||||
@ -73,7 +73,7 @@ final class OverlayPlayerControllerNode: ViewControllerTracingNode, UIGestureRec
|
||||
}, openAppStorePage: {
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||
}, displayForwardDisabledNotice: { _, _, _ in }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||
pollActionState: ChatInterfacePollActionState())
|
||||
|
||||
self.dimNode = ASDisplayNode()
|
||||
|
||||
@ -255,7 +255,7 @@ public class PeerMediaCollectionController: TelegramController {
|
||||
}, openAppStorePage: {
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||
}, displayForwardDisabledNotice: { _, _, _ in }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||
pollActionState: ChatInterfacePollActionState())
|
||||
|
||||
self.controllerInteraction = controllerInteraction
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -241,6 +241,37 @@ public func upgradedAccounts(accountManager: AccountManager, rootPath: String) -
|
||||
signal = signal |> then(upgradeAccessChallengeData)
|
||||
}
|
||||
}
|
||||
if version < 4 {
|
||||
let updatedContactSynchronizationSettings = accountManager.transaction { transaction -> (ContactSynchronizationSettings, [AccountRecordId]) in
|
||||
return (transaction.getSharedData(ApplicationSpecificSharedDataKeys.contactSynchronizationSettings) as? ContactSynchronizationSettings ?? ContactSynchronizationSettings.defaultSettings, transaction.getRecords().map({ $0.id }))
|
||||
}
|
||||
|> mapToSignal { globalSettings, ids -> Signal<Never, NoError> in
|
||||
var importSignal: Signal<Never, NoError> = .complete()
|
||||
for id in ids {
|
||||
let importInfoAccounttSignal = accountTransaction(rootPath: rootPath, id: id, transaction: { transaction -> Void in
|
||||
transaction.updatePreferencesEntry(key: PreferencesKeys.contactsSettings, { current in
|
||||
var settings = current as? ContactsSettings ?? ContactsSettings.defaultSettings
|
||||
settings.synchronizeContacts = globalSettings._legacySynchronizeDeviceContacts
|
||||
return settings
|
||||
})
|
||||
})
|
||||
|> ignoreValues
|
||||
importSignal = importSignal |> then(importInfoAccounttSignal)
|
||||
}
|
||||
return importSignal
|
||||
}
|
||||
|
||||
let applyVersion = accountManager.transaction { transaction -> Void in
|
||||
transaction.setVersion(4)
|
||||
}
|
||||
|> ignoreValues
|
||||
signal = signal |> then(
|
||||
updatedContactSynchronizationSettings
|
||||
|> then(
|
||||
applyVersion
|
||||
)
|
||||
)
|
||||
}
|
||||
return signal
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user