mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Chat list notices
This commit is contained in:
parent
b92293efe9
commit
46d9465841
@ -2501,13 +2501,13 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
strongSelf.dismissAutoarchiveDisposable.set(strongSelf.context.engine.notices.dismissServerProvidedSuggestion(suggestion: .autoarchivePopular).startStrict())
|
strongSelf.dismissAutoarchiveDisposable.set(strongSelf.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.autoarchivePopular.id).startStrict())
|
||||||
}),
|
}),
|
||||||
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.ChatList_AutoarchiveSuggestion_OpenSettings, action: {
|
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.ChatList_AutoarchiveSuggestion_OpenSettings, action: {
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
strongSelf.dismissAutoarchiveDisposable.set(strongSelf.context.engine.notices.dismissServerProvidedSuggestion(suggestion: .autoarchivePopular).startStrict())
|
strongSelf.dismissAutoarchiveDisposable.set(strongSelf.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.autoarchivePopular.id).startStrict())
|
||||||
strongSelf.push(strongSelf.context.sharedContext.makePrivacyAndSecurityController(context: strongSelf.context))
|
strongSelf.push(strongSelf.context.sharedContext.makePrivacyAndSecurityController(context: strongSelf.context))
|
||||||
})
|
})
|
||||||
], actionLayout: .vertical, parseMarkdown: true), in: .window(.root))
|
], actionLayout: .vertical, parseMarkdown: true), in: .window(.root))
|
||||||
@ -6114,7 +6114,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
|
|
||||||
func openBirthdaySetup() {
|
func openBirthdaySetup() {
|
||||||
let context = self.context
|
let context = self.context
|
||||||
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: .setupBirthday).startStandalone()
|
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupBirthday.id).startStandalone()
|
||||||
|
|
||||||
let settingsPromise: Promise<AccountPrivacySettings?>
|
let settingsPromise: Promise<AccountPrivacySettings?>
|
||||||
if let rootController = self.context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface, let current = rootController.getPrivacySettings() {
|
if let rootController = self.context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface, let current = rootController.getPrivacySettings() {
|
||||||
|
@ -778,7 +778,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
nodeInteraction?.openPhotoSetup()
|
nodeInteraction?.openPhotoSetup()
|
||||||
case .accountFreeze:
|
case .accountFreeze:
|
||||||
nodeInteraction?.openAccountFreezeInfo()
|
nodeInteraction?.openAccountFreezeInfo()
|
||||||
case let .link(url, _, _):
|
case let .link(_, url, _, _):
|
||||||
nodeInteraction?.openUrl(url)
|
nodeInteraction?.openUrl(url)
|
||||||
}
|
}
|
||||||
case .hide:
|
case .hide:
|
||||||
@ -1128,7 +1128,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
nodeInteraction?.openPhotoSetup()
|
nodeInteraction?.openPhotoSetup()
|
||||||
case .accountFreeze:
|
case .accountFreeze:
|
||||||
nodeInteraction?.openAccountFreezeInfo()
|
nodeInteraction?.openAccountFreezeInfo()
|
||||||
case let .link(url, _, _):
|
case let .link(_, url, _, _):
|
||||||
nodeInteraction?.openUrl(url)
|
nodeInteraction?.openUrl(url)
|
||||||
}
|
}
|
||||||
case .hide:
|
case .hide:
|
||||||
@ -1731,7 +1731,7 @@ public final class ChatListNode: ListView {
|
|||||||
}
|
}
|
||||||
Queue.mainQueue().after(0.6) { [weak self] in
|
Queue.mainQueue().after(0.6) { [weak self] in
|
||||||
if let self {
|
if let self {
|
||||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: .setupPassword).startStandalone()
|
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupPassword.id).startStandalone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let controller = self.context.sharedContext.makeSetupTwoFactorAuthController(context: self.context)
|
let controller = self.context.sharedContext.makeSetupTwoFactorAuthController(context: self.context)
|
||||||
@ -1742,9 +1742,9 @@ public final class ChatListNode: ListView {
|
|||||||
}
|
}
|
||||||
Queue.mainQueue().after(0.6) { [weak self] in
|
Queue.mainQueue().after(0.6) { [weak self] in
|
||||||
if let self {
|
if let self {
|
||||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: .annualPremium).startStandalone()
|
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.annualPremium.id).startStandalone()
|
||||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: .upgradePremium).startStandalone()
|
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.upgradePremium.id).startStandalone()
|
||||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: .restorePremium).startStandalone()
|
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.restorePremium.id).startStandalone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let controller = self.context.sharedContext.makePremiumIntroController(context: self.context, source: .ads, forceDark: false, dismissed: nil)
|
let controller = self.context.sharedContext.makePremiumIntroController(context: self.context, source: .ads, forceDark: false, dismissed: nil)
|
||||||
@ -1875,26 +1875,28 @@ public final class ChatListNode: ListView {
|
|||||||
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
switch notice {
|
switch notice {
|
||||||
case .xmasPremiumGift:
|
case .xmasPremiumGift:
|
||||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: .xmasPremiumGift).startStandalone()
|
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.xmasPremiumGift.id).startStandalone()
|
||||||
self.present?(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.ChatList_PremiumGiftInSettingsInfo, timeout: 5.0, customUndoText: nil), elevatedLayout: false, action: { _ in
|
self.present?(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.ChatList_PremiumGiftInSettingsInfo, timeout: 5.0, customUndoText: nil), elevatedLayout: false, action: { _ in
|
||||||
return true
|
return true
|
||||||
}))
|
}))
|
||||||
case .setupBirthday:
|
case .setupBirthday:
|
||||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: .setupBirthday).startStandalone()
|
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupBirthday.id).startStandalone()
|
||||||
self.present?(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.ChatList_BirthdayInSettingsInfo, timeout: 5.0, customUndoText: nil), elevatedLayout: false, action: { _ in
|
self.present?(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.ChatList_BirthdayInSettingsInfo, timeout: 5.0, customUndoText: nil), elevatedLayout: false, action: { _ in
|
||||||
return true
|
return true
|
||||||
}))
|
}))
|
||||||
case .birthdayPremiumGift:
|
case .birthdayPremiumGift:
|
||||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: .todayBirthdays).startStandalone()
|
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.todayBirthdays.id).startStandalone()
|
||||||
self.present?(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.ChatList_PremiumGiftInSettingsInfo, timeout: 5.0, customUndoText: nil), elevatedLayout: false, action: { _ in
|
self.present?(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.ChatList_PremiumGiftInSettingsInfo, timeout: 5.0, customUndoText: nil), elevatedLayout: false, action: { _ in
|
||||||
return true
|
return true
|
||||||
}))
|
}))
|
||||||
case .premiumGrace:
|
case .premiumGrace:
|
||||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: .gracePremium).startStandalone()
|
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.gracePremium.id).startStandalone()
|
||||||
case .setupPhoto:
|
case .setupPhoto:
|
||||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: .setupPhoto).startStandalone()
|
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupPhoto.id).startStandalone()
|
||||||
case .starsSubscriptionLowBalance:
|
case .starsSubscriptionLowBalance:
|
||||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: .starsSubscriptionLowBalance).startStandalone()
|
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.starsSubscriptionLowBalance.id).startStandalone()
|
||||||
|
case let .link(id, _, _, _):
|
||||||
|
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: id).startStandalone()
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -2063,7 +2065,7 @@ public final class ChatListNode: ListView {
|
|||||||
return lhs < rhs
|
return lhs < rhs
|
||||||
}
|
}
|
||||||
|
|
||||||
if dismissedSuggestions.contains(.todayBirthdays) {
|
if dismissedSuggestions.contains(ServerProvidedSuggestion.todayBirthdays.id) {
|
||||||
todayBirthdayPeerIds = []
|
todayBirthdayPeerIds = []
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2147,8 +2149,8 @@ public final class ChatListNode: ListView {
|
|||||||
}
|
}
|
||||||
return .birthdayPremiumGift(peers: todayBirthdayPeers, birthdays: birthdays)
|
return .birthdayPremiumGift(peers: todayBirthdayPeers, birthdays: birthdays)
|
||||||
}
|
}
|
||||||
} else if case let .link(url, title, subtitle) = suggestions.first(where: { if case .link = $0 { return true } else { return false} }) {
|
} else if case let .link(id, url, title, subtitle) = suggestions.first(where: { if case .link = $0 { return true } else { return false} }) {
|
||||||
return .single(.link(url: url, title: title, subtitle: subtitle))
|
return .single(.link(id: id, url: url, title: title, subtitle: subtitle))
|
||||||
} else {
|
} else {
|
||||||
return .single(nil)
|
return .single(nil)
|
||||||
}
|
}
|
||||||
@ -2156,11 +2158,6 @@ public final class ChatListNode: ListView {
|
|||||||
|> distinctUntilChanged
|
|> distinctUntilChanged
|
||||||
|
|
||||||
self.suggestedChatListNotice.set(suggestedChatListNoticeSignal)
|
self.suggestedChatListNotice.set(suggestedChatListNoticeSignal)
|
||||||
|
|
||||||
/*#if DEBUG
|
|
||||||
let testNotice: Signal<ChatListNotice?, NoError> = Signal<ChatListNotice?, NoError>.single(.setupPassword) |> then(Signal<ChatListNotice?, NoError>.complete() |> delay(1.0, queue: .mainQueue())) |> then(Signal<ChatListNotice?, NoError>.single(.xmasPremiumGift)) |> then(Signal<ChatListNotice?, NoError>.complete() |> delay(1.0, queue: .mainQueue())) |> restart
|
|
||||||
self.suggestedChatListNotice.set(testNotice)
|
|
||||||
#endif*/
|
|
||||||
}).strict()
|
}).strict()
|
||||||
|
|
||||||
let storageInfo: Signal<Double?, NoError>
|
let storageInfo: Signal<Double?, NoError>
|
||||||
|
@ -93,7 +93,7 @@ public enum ChatListNotice: Equatable {
|
|||||||
case starsSubscriptionLowBalance(amount: StarsAmount, peers: [EnginePeer])
|
case starsSubscriptionLowBalance(amount: StarsAmount, peers: [EnginePeer])
|
||||||
case setupPhoto(EnginePeer)
|
case setupPhoto(EnginePeer)
|
||||||
case accountFreeze
|
case accountFreeze
|
||||||
case link(url: String, title: String, subtitle: String)
|
case link(id: String, url: String, title: ServerSuggestionInfo.Item.Text, subtitle: ServerSuggestionInfo.Item.Text)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ChatListNodeEntry: Comparable, Identifiable {
|
enum ChatListNodeEntry: Comparable, Identifiable {
|
||||||
|
@ -85,13 +85,21 @@ class ChatListNoticeItem: ListViewItem {
|
|||||||
private let separatorHeight = 1.0 / UIScreen.main.scale
|
private let separatorHeight = 1.0 / UIScreen.main.scale
|
||||||
|
|
||||||
private let titleFont = Font.semibold(15.0)
|
private let titleFont = Font.semibold(15.0)
|
||||||
|
private let titleBoldFont = Font.bold(15.0)
|
||||||
|
private let titleItalicFont = Font.semiboldItalic(15.0)
|
||||||
|
private let titleBoldItalicFont = Font.semiboldItalic(15.0)
|
||||||
|
|
||||||
private let textFont = Font.regular(15.0)
|
private let textFont = Font.regular(15.0)
|
||||||
|
private let textBoldFont = Font.semibold(15.0)
|
||||||
|
private let textItalicFont = Font.italic(15.0)
|
||||||
|
private let textBoldItalicFont = Font.semiboldItalic(15.0)
|
||||||
|
|
||||||
private let smallTextFont = Font.regular(14.0)
|
private let smallTextFont = Font.regular(14.0)
|
||||||
|
|
||||||
final class ChatListNoticeItemNode: ItemListRevealOptionsItemNode {
|
final class ChatListNoticeItemNode: ItemListRevealOptionsItemNode {
|
||||||
private let contentContainer: ASDisplayNode
|
private let contentContainer: ASDisplayNode
|
||||||
private let titleNode: TextNodeWithEntities
|
private let titleNode: TextNodeWithEntities
|
||||||
private let textNode: TextNode
|
private let textNode: TextNodeWithEntities
|
||||||
private let arrowNode: ASImageNode
|
private let arrowNode: ASImageNode
|
||||||
private let separatorNode: ASDisplayNode
|
private let separatorNode: ASDisplayNode
|
||||||
|
|
||||||
@ -118,7 +126,7 @@ final class ChatListNoticeItemNode: ItemListRevealOptionsItemNode {
|
|||||||
self.contentContainer = ASDisplayNode()
|
self.contentContainer = ASDisplayNode()
|
||||||
|
|
||||||
self.titleNode = TextNodeWithEntities()
|
self.titleNode = TextNodeWithEntities()
|
||||||
self.textNode = TextNode()
|
self.textNode = TextNodeWithEntities()
|
||||||
self.arrowNode = ASImageNode()
|
self.arrowNode = ASImageNode()
|
||||||
self.separatorNode = ASDisplayNode()
|
self.separatorNode = ASDisplayNode()
|
||||||
|
|
||||||
@ -128,7 +136,7 @@ final class ChatListNoticeItemNode: ItemListRevealOptionsItemNode {
|
|||||||
self.clipsToBounds = true
|
self.clipsToBounds = true
|
||||||
|
|
||||||
self.contentContainer.addSubnode(self.titleNode.textNode)
|
self.contentContainer.addSubnode(self.titleNode.textNode)
|
||||||
self.contentContainer.addSubnode(self.textNode)
|
self.contentContainer.addSubnode(self.textNode.textNode)
|
||||||
self.contentContainer.addSubnode(self.arrowNode)
|
self.contentContainer.addSubnode(self.arrowNode)
|
||||||
|
|
||||||
self.addSubnode(self.contentContainer)
|
self.addSubnode(self.contentContainer)
|
||||||
@ -154,7 +162,7 @@ final class ChatListNoticeItemNode: ItemListRevealOptionsItemNode {
|
|||||||
let previousItem = self.item
|
let previousItem = self.item
|
||||||
|
|
||||||
let makeTitleLayout = TextNodeWithEntities.asyncLayout(self.titleNode)
|
let makeTitleLayout = TextNodeWithEntities.asyncLayout(self.titleNode)
|
||||||
let makeTextLayout = TextNode.asyncLayout(self.textNode)
|
let makeTextLayout = TextNodeWithEntities.asyncLayout(self.textNode)
|
||||||
|
|
||||||
let makeOkButtonTextLayout = TextNode.asyncLayout(self.okButtonText)
|
let makeOkButtonTextLayout = TextNode.asyncLayout(self.okButtonText)
|
||||||
let makeCancelButtonTextLayout = TextNode.asyncLayout(self.cancelButtonText)
|
let makeCancelButtonTextLayout = TextNode.asyncLayout(self.cancelButtonText)
|
||||||
@ -291,9 +299,9 @@ final class ChatListNoticeItemNode: ItemListRevealOptionsItemNode {
|
|||||||
case .accountFreeze:
|
case .accountFreeze:
|
||||||
titleString = NSAttributedString(string: item.strings.ChatList_FrozenAccount_Title, font: titleFont, textColor: item.theme.list.itemDestructiveColor)
|
titleString = NSAttributedString(string: item.strings.ChatList_FrozenAccount_Title, font: titleFont, textColor: item.theme.list.itemDestructiveColor)
|
||||||
textString = NSAttributedString(string: item.strings.ChatList_FrozenAccount_Text, font: smallTextFont, textColor: item.theme.rootController.navigationBar.secondaryTextColor)
|
textString = NSAttributedString(string: item.strings.ChatList_FrozenAccount_Text, font: smallTextFont, textColor: item.theme.rootController.navigationBar.secondaryTextColor)
|
||||||
case let .link(_, title, subtitle):
|
case let .link(_, _, title, subtitle):
|
||||||
titleString = NSAttributedString(string: title, font: titleFont, textColor: item.theme.list.itemPrimaryTextColor)
|
titleString = stringWithAppliedEntities(title.string, entities: title.entities, baseColor: item.theme.list.itemPrimaryTextColor, linkColor: item.theme.list.itemAccentColor, baseFont: titleFont, linkFont: titleFont, boldFont: titleBoldFont, italicFont: titleItalicFont, boldItalicFont: titleBoldItalicFont, fixedFont: titleFont, blockQuoteFont: titleFont, message: nil)
|
||||||
textString = NSAttributedString(string: subtitle, font: smallTextFont, textColor: item.theme.rootController.navigationBar.secondaryTextColor)
|
textString = stringWithAppliedEntities(subtitle.string, entities: subtitle.entities, baseColor: item.theme.list.itemPrimaryTextColor, linkColor: item.theme.list.itemAccentColor, baseFont: textFont, linkFont: textFont, boldFont: textBoldFont, italicFont: textItalicFont, boldItalicFont: textBoldItalicFont, fixedFont: textFont, blockQuoteFont: textFont, message: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
var leftInset: CGFloat = sideInset
|
var leftInset: CGFloat = sideInset
|
||||||
@ -333,12 +341,15 @@ final class ChatListNoticeItemNode: ItemListRevealOptionsItemNode {
|
|||||||
strongSelf.titleNode.textNode.frame = CGRect(origin: CGPoint(x: leftInset, y: verticalInset), size: titleLayout.0.size)
|
strongSelf.titleNode.textNode.frame = CGRect(origin: CGPoint(x: leftInset, y: verticalInset), size: titleLayout.0.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = textLayout.1()
|
let _ = textLayout.1(TextNodeWithEntities.Arguments(context: item.context, cache: item.context.animationCache, renderer: item.context.animationRenderer, placeholderColor: .white, attemptSynchronous: true))
|
||||||
|
|
||||||
|
strongSelf.titleNode.visibilityRect = CGRect(origin: CGPoint(), size: CGSize(width: 1000000.0, height: 1000000.0))
|
||||||
|
strongSelf.textNode.visibilityRect = CGRect(origin: CGPoint(), size: CGSize(width: 1000000.0, height: 1000000.0))
|
||||||
|
|
||||||
if case .center = alignment {
|
if case .center = alignment {
|
||||||
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: floor((params.width - textLayout.0.size.width) * 0.5), y: strongSelf.titleNode.textNode.frame.maxY + spacing), size: textLayout.0.size)
|
strongSelf.textNode.textNode.frame = CGRect(origin: CGPoint(x: floor((params.width - textLayout.0.size.width) * 0.5), y: strongSelf.titleNode.textNode.frame.maxY + spacing), size: textLayout.0.size)
|
||||||
} else {
|
} else {
|
||||||
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: leftInset, y: strongSelf.titleNode.textNode.frame.maxY + spacing), size: textLayout.0.size)
|
strongSelf.textNode.textNode.frame = CGRect(origin: CGPoint(x: leftInset, y: strongSelf.titleNode.textNode.frame.maxY + spacing), size: textLayout.0.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !avatarPeers.isEmpty {
|
if !avatarPeers.isEmpty {
|
||||||
@ -434,8 +445,8 @@ final class ChatListNoticeItemNode: ItemListRevealOptionsItemNode {
|
|||||||
let buttonWidth: CGFloat = floor(buttonsWidth * 0.5)
|
let buttonWidth: CGFloat = floor(buttonsWidth * 0.5)
|
||||||
let buttonHeight: CGFloat = 32.0
|
let buttonHeight: CGFloat = 32.0
|
||||||
|
|
||||||
let okButtonFrame = CGRect(origin: CGPoint(x: floor((params.width - buttonsWidth) * 0.5), y: strongSelf.textNode.frame.maxY + 6.0), size: CGSize(width: buttonWidth, height: buttonHeight))
|
let okButtonFrame = CGRect(origin: CGPoint(x: floor((params.width - buttonsWidth) * 0.5), y: strongSelf.textNode.textNode.frame.maxY + 6.0), size: CGSize(width: buttonWidth, height: buttonHeight))
|
||||||
let cancelButtonFrame = CGRect(origin: CGPoint(x: okButtonFrame.maxX, y: strongSelf.textNode.frame.maxY + 6.0), size: CGSize(width: buttonWidth, height: buttonHeight))
|
let cancelButtonFrame = CGRect(origin: CGPoint(x: okButtonFrame.maxX, y: strongSelf.textNode.textNode.frame.maxY + 6.0), size: CGSize(width: buttonWidth, height: buttonHeight))
|
||||||
|
|
||||||
okButton.frame = okButtonFrame
|
okButton.frame = okButtonFrame
|
||||||
cancelButton.frame = cancelButtonFrame
|
cancelButton.frame = cancelButtonFrame
|
||||||
|
@ -285,7 +285,7 @@ func changePhoneNumberCodeController(context: AccountContext, phoneNumber: Strin
|
|||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
presentControllerImpl?(OverlayStatusController(theme: presentationData.theme, type: .success), nil)
|
presentControllerImpl?(OverlayStatusController(theme: presentationData.theme, type: .success), nil)
|
||||||
|
|
||||||
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: .validatePhoneNumber).start()
|
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.validatePhoneNumber.id).start()
|
||||||
|
|
||||||
dismissImpl?()
|
dismissImpl?()
|
||||||
}))
|
}))
|
||||||
|
@ -84,7 +84,7 @@ public func ChangePhoneNumberController(context: AccountContext) -> ViewControll
|
|||||||
}, completed: { [weak codeController] in
|
}, completed: { [weak codeController] in
|
||||||
codeController?.present(OverlayStatusController(theme: presentationData.theme, type: .success), in: .window(.root))
|
codeController?.present(OverlayStatusController(theme: presentationData.theme, type: .success), in: .window(.root))
|
||||||
|
|
||||||
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: .validatePhoneNumber).start()
|
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.validatePhoneNumber.id).start()
|
||||||
|
|
||||||
if let navigationController = codeController?.navigationController as? NavigationController {
|
if let navigationController = codeController?.navigationController as? NavigationController {
|
||||||
var viewControllers = navigationController.viewControllers
|
var viewControllers = navigationController.viewControllers
|
||||||
|
@ -106,6 +106,14 @@ public final class ServerSuggestionInfo: Codable, Equatable {
|
|||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
self = .link(url: try container.decode(String.self, forKey: .link))
|
self = .link(url: try container.decode(String.self, forKey: .link))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: any Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
switch self {
|
||||||
|
case let .link(url):
|
||||||
|
try container.encode(url, forKey: .link)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public let id: String
|
public let id: String
|
||||||
|
@ -3,7 +3,7 @@ import Postbox
|
|||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
import TelegramApi
|
import TelegramApi
|
||||||
|
|
||||||
public enum ServerProvidedSuggestion: Hashable {
|
public enum ServerProvidedSuggestion: Equatable {
|
||||||
case autoarchivePopular
|
case autoarchivePopular
|
||||||
case newcomerTicks
|
case newcomerTicks
|
||||||
case validatePhoneNumber
|
case validatePhoneNumber
|
||||||
@ -18,9 +18,9 @@ public enum ServerProvidedSuggestion: Hashable {
|
|||||||
case gracePremium
|
case gracePremium
|
||||||
case starsSubscriptionLowBalance
|
case starsSubscriptionLowBalance
|
||||||
case setupPhoto
|
case setupPhoto
|
||||||
case link(url: String, title: String, subtitle: String)
|
case link(id: String, url: String, title: ServerSuggestionInfo.Item.Text, subtitle: ServerSuggestionInfo.Item.Text)
|
||||||
|
|
||||||
public init?(string: String) {
|
init?(string: String) {
|
||||||
switch string {
|
switch string {
|
||||||
case "AUTOARCHIVE_POPULAR":
|
case "AUTOARCHIVE_POPULAR":
|
||||||
self = .autoarchivePopular
|
self = .autoarchivePopular
|
||||||
@ -51,33 +51,11 @@ public enum ServerProvidedSuggestion: Hashable {
|
|||||||
case "USERPIC_SETUP":
|
case "USERPIC_SETUP":
|
||||||
self = .setupPhoto
|
self = .setupPhoto
|
||||||
default:
|
default:
|
||||||
if string.hasPrefix("LINK_") {
|
|
||||||
let rawString = string.dropFirst(Int("LINK_".count))
|
|
||||||
if let dict = try? JSONSerialization.jsonObject(with: rawString.data(using: .utf8) ?? Data()) as? [String: Any] {
|
|
||||||
var url: String?
|
|
||||||
var title: String?
|
|
||||||
var subtitle: String?
|
|
||||||
|
|
||||||
if let urlValue = dict["url"] as? String {
|
|
||||||
url = urlValue
|
|
||||||
}
|
|
||||||
if let titleValue = dict["title"] as? String {
|
|
||||||
title = titleValue
|
|
||||||
}
|
|
||||||
if let subtitleValue = dict["subtitle"] as? String {
|
|
||||||
subtitle = subtitleValue
|
|
||||||
}
|
|
||||||
if let url = url, let title = title, let subtitle = subtitle {
|
|
||||||
self = .link(url: url, title: title, subtitle: subtitle)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var stringValue: String {
|
public var id: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .autoarchivePopular:
|
case .autoarchivePopular:
|
||||||
return "AUTOARCHIVE_POPULAR"
|
return "AUTOARCHIVE_POPULAR"
|
||||||
@ -107,90 +85,79 @@ public enum ServerProvidedSuggestion: Hashable {
|
|||||||
return "STARS_SUBSCRIPTION_LOW_BALANCE"
|
return "STARS_SUBSCRIPTION_LOW_BALANCE"
|
||||||
case .setupPhoto:
|
case .setupPhoto:
|
||||||
return "USERPIC_SETUP"
|
return "USERPIC_SETUP"
|
||||||
case let .link(url, title, subtitle):
|
case let .link(id, _, _, _):
|
||||||
let dict: [String: String] = [
|
return id
|
||||||
"url": url,
|
|
||||||
"title": title,
|
|
||||||
"subtitle": subtitle
|
|
||||||
]
|
|
||||||
if let data = try? JSONSerialization.data(withJSONObject: dict, options: []), let string = String(data: data, encoding: .utf8) {
|
|
||||||
return "LINK_\(string)"
|
|
||||||
} else {
|
|
||||||
// Fallback or error handling, though unlikely to fail with basic strings
|
|
||||||
return "LINK_{}"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var dismissedSuggestionsPromise = ValuePromise<[AccountRecordId: Set<ServerProvidedSuggestion>]>([:])
|
private var dismissedSuggestionsPromise = ValuePromise<[AccountRecordId: Set<String>]>([:])
|
||||||
private var dismissedSuggestions: [AccountRecordId: Set<ServerProvidedSuggestion>] = [:] {
|
private var dismissedSuggestions: [AccountRecordId: Set<String>] = [:] {
|
||||||
didSet {
|
didSet {
|
||||||
dismissedSuggestionsPromise.set(dismissedSuggestions)
|
dismissedSuggestionsPromise.set(dismissedSuggestions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func _internal_getServerProvidedSuggestions(account: Account) -> Signal<[ServerProvidedSuggestion], NoError> {
|
func _internal_getServerProvidedSuggestions(account: Account) -> Signal<[ServerProvidedSuggestion], NoError> {
|
||||||
let key: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.appConfiguration]))
|
let key: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.serverSuggestionInfo()]))
|
||||||
return combineLatest(account.postbox.combinedView(keys: [key]), dismissedSuggestionsPromise.get())
|
return combineLatest(account.postbox.combinedView(keys: [key]), dismissedSuggestionsPromise.get())
|
||||||
|> map { views, dismissedSuggestionsValue -> [ServerProvidedSuggestion] in
|
|> map { views, dismissedSuggestionsValue -> [ServerProvidedSuggestion] in
|
||||||
let dismissedSuggestions = dismissedSuggestionsValue[account.id] ?? Set()
|
let dismissedSuggestions = dismissedSuggestionsValue[account.id] ?? Set()
|
||||||
guard let view = views.views[key] as? PreferencesView else {
|
guard let view = views.views[key] as? PreferencesView else {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
guard let appConfiguration = view.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self) else {
|
guard let serverSuggestionInfo = view.values[PreferencesKeys.serverSuggestionInfo()]?.get(ServerSuggestionInfo.self) else {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
var items: [ServerProvidedSuggestion] = []
|
||||||
guard let data = appConfiguration.data, var listItems = data["pending_suggestions"] as? [String] else {
|
for item in serverSuggestionInfo.legacyItems {
|
||||||
return []
|
if let value = ServerProvidedSuggestion(string: item) {
|
||||||
|
items.append(value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
listItems.insert("LINK_{\"url\": \"https://t.me/durov\", \"title\": \"📣 Stay updated!\", \"subtitle\": \"Subscribe to the channel of Telegram's founder.\"}", at: 0)
|
for item in serverSuggestionInfo.items {
|
||||||
#else
|
switch item.action {
|
||||||
guard let data = appConfiguration.data, let listItems = data["pending_suggestions"] as? [String] else {
|
case let .link(url):
|
||||||
return []
|
items.append(.link(
|
||||||
|
id: item.id,
|
||||||
|
url: url,
|
||||||
|
title: item.title,
|
||||||
|
subtitle: item.text
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
return items.filter({ !dismissedSuggestions.contains($0.id) })
|
||||||
return listItems.compactMap { item -> ServerProvidedSuggestion? in
|
|
||||||
return ServerProvidedSuggestion(string: item)
|
|
||||||
}.filter { !dismissedSuggestions.contains($0) }
|
|
||||||
}
|
}
|
||||||
|> distinctUntilChanged
|
|> distinctUntilChanged
|
||||||
}
|
}
|
||||||
|
|
||||||
func _internal_getServerDismissedSuggestions(account: Account) -> Signal<[ServerProvidedSuggestion], NoError> {
|
func _internal_getServerDismissedSuggestions(account: Account) -> Signal<[String], NoError> {
|
||||||
let key: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.appConfiguration]))
|
let key: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.serverSuggestionInfo()]))
|
||||||
return combineLatest(account.postbox.combinedView(keys: [key]), dismissedSuggestionsPromise.get())
|
return combineLatest(account.postbox.combinedView(keys: [key]), dismissedSuggestionsPromise.get())
|
||||||
|> map { views, dismissedSuggestionsValue -> [ServerProvidedSuggestion] in
|
|> map { views, dismissedSuggestionsValue -> [String] in
|
||||||
let dismissedSuggestions = dismissedSuggestionsValue[account.id] ?? Set()
|
let dismissedSuggestions = dismissedSuggestionsValue[account.id] ?? Set()
|
||||||
guard let view = views.views[key] as? PreferencesView else {
|
guard let view = views.views[key] as? PreferencesView else {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
guard let appConfiguration = view.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self) else {
|
guard let serverSuggestionInfo = view.values[PreferencesKeys.serverSuggestionInfo()]?.get(ServerSuggestionInfo.self) else {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
var listItems: [String] = []
|
var items: [String] = serverSuggestionInfo.dismissedIds
|
||||||
if let data = appConfiguration.data, let listItemsValues = data["dismissed_suggestions"] as? [String] {
|
|
||||||
listItems.append(contentsOf: listItemsValues)
|
|
||||||
}
|
|
||||||
var items = listItems.compactMap { item -> ServerProvidedSuggestion? in
|
|
||||||
return ServerProvidedSuggestion(string: item)
|
|
||||||
}
|
|
||||||
items.append(contentsOf: dismissedSuggestions)
|
items.append(contentsOf: dismissedSuggestions)
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|> distinctUntilChanged
|
|> distinctUntilChanged
|
||||||
}
|
}
|
||||||
|
|
||||||
func _internal_dismissServerProvidedSuggestion(account: Account, suggestion: ServerProvidedSuggestion) -> Signal<Never, NoError> {
|
func _internal_dismissServerProvidedSuggestion(account: Account, suggestion: String) -> Signal<Never, NoError> {
|
||||||
if let _ = dismissedSuggestions[account.id] {
|
if let _ = dismissedSuggestions[account.id] {
|
||||||
dismissedSuggestions[account.id]?.insert(suggestion)
|
dismissedSuggestions[account.id]?.insert(suggestion)
|
||||||
} else {
|
} else {
|
||||||
dismissedSuggestions[account.id] = Set([suggestion])
|
dismissedSuggestions[account.id] = Set([suggestion])
|
||||||
}
|
}
|
||||||
return account.network.request(Api.functions.help.dismissSuggestion(peer: .inputPeerEmpty, suggestion: suggestion.stringValue))
|
return account.network.request(Api.functions.help.dismissSuggestion(peer: .inputPeerEmpty, suggestion: suggestion))
|
||||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||||
return .single(.boolFalse)
|
return .single(.boolFalse)
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,11 @@ public extension TelegramEngine {
|
|||||||
return _internal_getServerProvidedSuggestions(account: self.account)
|
return _internal_getServerProvidedSuggestions(account: self.account)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func getServerDismissedSuggestions() -> Signal<[ServerProvidedSuggestion], NoError> {
|
public func getServerDismissedSuggestions() -> Signal<[String], NoError> {
|
||||||
return _internal_getServerDismissedSuggestions(account: self.account)
|
return _internal_getServerDismissedSuggestions(account: self.account)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion) -> Signal<Never, NoError> {
|
public func dismissServerProvidedSuggestion(suggestion: String) -> Signal<Never, NoError> {
|
||||||
return _internal_dismissServerProvidedSuggestion(account: self.account, suggestion: suggestion)
|
return _internal_dismissServerProvidedSuggestion(account: self.account, suggestion: suggestion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -849,7 +849,7 @@ private func settingsItems(data: PeerInfoScreenData?, context: AccountContext, p
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
items[.phone]!.append(PeerInfoScreenActionItem(id: 1, text: presentationData.strings.Settings_KeepPhoneNumber(phoneNumber).string, action: {
|
items[.phone]!.append(PeerInfoScreenActionItem(id: 1, text: presentationData.strings.Settings_KeepPhoneNumber(phoneNumber).string, action: {
|
||||||
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: .validatePhoneNumber).startStandalone()
|
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.validatePhoneNumber.id).startStandalone()
|
||||||
}))
|
}))
|
||||||
items[.phone]!.append(PeerInfoScreenActionItem(id: 2, text: presentationData.strings.Settings_ChangePhoneNumber, action: {
|
items[.phone]!.append(PeerInfoScreenActionItem(id: 2, text: presentationData.strings.Settings_ChangePhoneNumber, action: {
|
||||||
interaction.openSettings(.phoneNumber)
|
interaction.openSettings(.phoneNumber)
|
||||||
@ -858,7 +858,7 @@ private func settingsItems(data: PeerInfoScreenData?, context: AccountContext, p
|
|||||||
items[.phone]!.append(PeerInfoScreenInfoItem(id: 0, title: presentationData.strings.Settings_CheckPasswordTitle, text: .markdown(presentationData.strings.Settings_CheckPasswordText), linkAction: { _ in
|
items[.phone]!.append(PeerInfoScreenInfoItem(id: 0, title: presentationData.strings.Settings_CheckPasswordTitle, text: .markdown(presentationData.strings.Settings_CheckPasswordText), linkAction: { _ in
|
||||||
}))
|
}))
|
||||||
items[.phone]!.append(PeerInfoScreenActionItem(id: 1, text: presentationData.strings.Settings_KeepPassword, action: {
|
items[.phone]!.append(PeerInfoScreenActionItem(id: 1, text: presentationData.strings.Settings_KeepPassword, action: {
|
||||||
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: .validatePassword).startStandalone()
|
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.validatePassword.id).startStandalone()
|
||||||
}))
|
}))
|
||||||
items[.phone]!.append(PeerInfoScreenActionItem(id: 2, text: presentationData.strings.Settings_TryEnterPassword, action: {
|
items[.phone]!.append(PeerInfoScreenActionItem(id: 2, text: presentationData.strings.Settings_TryEnterPassword, action: {
|
||||||
interaction.openSettings(.rememberPassword)
|
interaction.openSettings(.rememberPassword)
|
||||||
@ -10370,7 +10370,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: .setupPassword).startStandalone()
|
let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupPassword.id).startStandalone()
|
||||||
})
|
})
|
||||||
|
|
||||||
let controller = self.context.sharedContext.makeSetupTwoFactorAuthController(context: self.context)
|
let controller = self.context.sharedContext.makeSetupTwoFactorAuthController(context: self.context)
|
||||||
@ -10498,7 +10498,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
return twoStepVerificationUnlockSettingsController(context: context, mode: .access(intro: false, data: .single(TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: configuration, password: nil)))))
|
return twoStepVerificationUnlockSettingsController(context: context, mode: .access(intro: false, data: .single(TwoStepVerificationUnlockSettingsControllerData.access(configuration: TwoStepVerificationAccessConfiguration(configuration: configuration, password: nil)))))
|
||||||
}
|
}
|
||||||
controller.passwordRemembered = {
|
controller.passwordRemembered = {
|
||||||
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: .validatePassword).startStandalone()
|
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.validatePassword.id).startStandalone()
|
||||||
}
|
}
|
||||||
push(controller)
|
push(controller)
|
||||||
case .emojiStatus:
|
case .emojiStatus:
|
||||||
|
@ -4815,7 +4815,7 @@ extension ChatControllerImpl {
|
|||||||
self?.displayChecksTooltip()
|
self?.displayChecksTooltip()
|
||||||
}
|
}
|
||||||
self.shouldDisplayChecksTooltip = false
|
self.shouldDisplayChecksTooltip = false
|
||||||
self.checksTooltipDisposable.set(self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: .newcomerTicks).startStrict())
|
self.checksTooltipDisposable.set(self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.newcomerTicks.id).startStrict())
|
||||||
}
|
}
|
||||||
|
|
||||||
if let shouldDisplayProcessingVideoTooltip = self.shouldDisplayProcessingVideoTooltip {
|
if let shouldDisplayProcessingVideoTooltip = self.shouldDisplayProcessingVideoTooltip {
|
||||||
|
@ -2856,7 +2856,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
guard let controller else {
|
guard let controller else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: .setupBirthday).startStandalone()
|
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupBirthday.id).startStandalone()
|
||||||
|
|
||||||
let settingsPromise: Promise<AccountPrivacySettings?>
|
let settingsPromise: Promise<AccountPrivacySettings?>
|
||||||
if let rootController = context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface, let current = rootController.getPrivacySettings() {
|
if let rootController = context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface, let current = rootController.getPrivacySettings() {
|
||||||
@ -3047,7 +3047,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
guard let controller else {
|
guard let controller else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: .setupBirthday).startStandalone()
|
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupBirthday.id).startStandalone()
|
||||||
|
|
||||||
let settingsPromise: Promise<AccountPrivacySettings?>
|
let settingsPromise: Promise<AccountPrivacySettings?>
|
||||||
if let rootController = context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface, let current = rootController.getPrivacySettings() {
|
if let rootController = context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface, let current = rootController.getPrivacySettings() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user