Various improvements

This commit is contained in:
Ilya Laktyushin 2025-03-18 20:12:41 +04:00
parent 730f03dcd8
commit d6eecb7844
18 changed files with 191 additions and 110 deletions

View File

@ -14059,3 +14059,33 @@ Sorry for the inconvenience.";
"ChatbotSetup.Rights.ManageStories" = "Manage Stories"; "ChatbotSetup.Rights.ManageStories" = "Manage Stories";
"Gift.Send.Upgrade.ForcedInfo" = "%1$@ accepts only unique gifts. [Learn More >]()"; "Gift.Send.Upgrade.ForcedInfo" = "%1$@ accepts only unique gifts. [Learn More >]()";
"Privacy.Gifts.ShowGiftButton" = "Show Gift Icon in Chats";
"Privacy.Gifts.ShowGiftButtonInfo" = "Display the #Gift icon in the message input field for both participants in all chats.";
"Privacy.Gifts.AcceptedTypes" = "ACCEPTED GIFT TYPES";
"Privacy.Gifts.AcceptedTypes.Unlimited" = "Unlimited";
"Privacy.Gifts.AcceptedTypes.Limited" = "Limited-Edition";
"Privacy.Gifts.AcceptedTypes.Unique" = "Unique";
"Privacy.Gifts.AcceptedTypes.Premium" = "Premium Subscriptions";
"Privacy.Gifts.AcceptedTypes.Info" = "Choose the types of gifts that you allow others to send you.";
"Chat.PanelFrozenAccount.Title" = "You account is frozen";
"Chat.PanelFrozenAccount.Text" = "Tap to view details";
"FrozenAccount.Title" = "Your Account is Frozen";
"FrozenAccount.Violation.Title" = "Violation of Terms";
"FrozenAccount.Violation.Text" = "Your account was frozen for breaking Telegram's Terms and Conditions.";
"FrozenAccount.ReadOnly.Title" = "Read-Only Mode";
"FrozenAccount.ReadOnly.Text" = "You can access your account but can't send messages or take actions.";
"FrozenAccount.Appeal.Title" = "Appeal Before Deactivation";
"FrozenAccount.Appeal.Text" = "Appeal via [@SpamBot]() before %@, or your account will be deleted.";
"FrozenAccount.SubmitAppeal" = "Submit an Appeal";
"FrozenAccount.Understood" = "Understood";
"AdsInfo.Search.Respect.Text" = "Ads like this do not use your personal information and are based on the search query you entered.";
"AdsInfo.Search.Ads.Text" = "You can turn off ads by subscribing to [Telegram Premium]().";
"AdsInfo.Search.Launch.Text" = "Anyone can create an ad to display in search results for any query. Check out the Telegram Ad Platform for details. [Learn More >]()";
"ChatList.FrozenAccount.Title" = "Your account is frozen";
"ChatList.FrozenAccount.Text" = "Tap to view details and submit an appeal.";

View File

@ -11,6 +11,7 @@ public final class BotCheckoutController: ViewController {
public final class InputData { public final class InputData {
public enum FetchError { public enum FetchError {
case generic case generic
case disallowedStarGifts
} }
public let form: BotPaymentForm public let form: BotPaymentForm
@ -53,8 +54,13 @@ public final class BotCheckoutController: ViewController {
} }
return context.engine.payments.fetchBotPaymentForm(source: source, themeParams: themeParams) return context.engine.payments.fetchBotPaymentForm(source: source, themeParams: themeParams)
|> mapError { _ -> FetchError in |> mapError { error -> FetchError in
return .generic switch error {
case .disallowedStarGift:
return .disallowedStarGifts
default:
return .generic
}
} }
|> mapToSignal { paymentForm -> Signal<InputData, FetchError> in |> mapToSignal { paymentForm -> Signal<InputData, FetchError> in
let botPeer: Signal<EnginePeer?, FetchError> let botPeer: Signal<EnginePeer?, FetchError>

View File

@ -6139,7 +6139,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
let context = self.context let context = self.context
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
//TODO:localize
var actions: [ContextMenuItem] = [] var actions: [ContextMenuItem] = []
if adPeer.sponsorInfo != nil || adPeer.additionalInfo != nil { if adPeer.sponsorInfo != nil || adPeer.additionalInfo != nil {
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_AdSponsorInfo, textColor: .primary, icon: { theme in actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_AdSponsorInfo, textColor: .primary, icon: { theme in
@ -6191,7 +6190,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
}))) })))
} }
actions.append(.action(ContextMenuActionItem(text: "About These Ads", textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_AboutAd, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.actionSheet.primaryTextColor)
}, iconSource: nil, action: { [weak self] _, f in }, iconSource: nil, action: { [weak self] _, f in
f(.default) f(.default)

View File

@ -855,6 +855,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: false), peer: .peer(peer: peer.peer, chatPeer: peer.peer), status: .addressName(suffixString), badge: nil, requiresPremiumForMessaging: false, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, searchQuery: nil, isAd: true, action: { _ in return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: false), peer: .peer(peer: peer.peer, chatPeer: peer.peer), status: .addressName(suffixString), badge: nil, requiresPremiumForMessaging: false, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, searchQuery: nil, isAd: true, action: { _ in
interaction.peerSelected(peer.peer, nil, nil, nil, false) interaction.peerSelected(peer.peer, nil, nil, nil, false)
context.engine.messages.markAdAction(opaqueId: peer.opaqueId, media: false, fullscreen: false)
}, disabledAction: { _ in }, disabledAction: { _ in
interaction.disabledPeerSelected(peer.peer, nil, .generic) interaction.disabledPeerSelected(peer.peer, nil, .generic)
}, contextAction: peerContextAction.flatMap { peerContextAction in }, contextAction: peerContextAction.flatMap { peerContextAction in

View File

@ -289,9 +289,8 @@ final class ChatListNoticeItemNode: ItemListRevealOptionsItemNode {
textString = NSAttributedString(string: item.strings.ChatList_AddPhoto_Text, font: smallTextFont, textColor: item.theme.rootController.navigationBar.secondaryTextColor) textString = NSAttributedString(string: item.strings.ChatList_AddPhoto_Text, font: smallTextFont, textColor: item.theme.rootController.navigationBar.secondaryTextColor)
avatarPeer = accountPeer avatarPeer = accountPeer
case .accountFreeze: case .accountFreeze:
//TODO:localize titleString = NSAttributedString(string: item.strings.ChatList_FrozenAccount_Title, font: titleFont, textColor: item.theme.list.itemDestructiveColor)
titleString = NSAttributedString(string: "Your account is frozen", 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: "Tap to view details and submit an appeal.", font: smallTextFont, textColor: item.theme.rootController.navigationBar.secondaryTextColor)
} }
var leftInset: CGFloat = sideInset var leftInset: CGFloat = sideInset

View File

@ -36,12 +36,13 @@ public class ItemListCheckboxItem: ListViewItem, ItemListItem {
let color: ItemListCheckboxItemColor let color: ItemListCheckboxItemColor
let textColor: TextColor let textColor: TextColor
let checked: Bool let checked: Bool
let enabled: Bool
let zeroSeparatorInsets: Bool let zeroSeparatorInsets: Bool
public let sectionId: ItemListSectionId public let sectionId: ItemListSectionId
let action: () -> Void let action: () -> Void
let deleteAction: (() -> Void)? let deleteAction: (() -> Void)?
public init(presentationData: ItemListPresentationData, icon: UIImage? = nil, iconSize: CGSize? = nil, iconPlacement: IconPlacement = .default, title: String, subtitle: String? = nil, style: ItemListCheckboxItemStyle, color: ItemListCheckboxItemColor = .accent, textColor: TextColor = .primary, checked: Bool, zeroSeparatorInsets: Bool, sectionId: ItemListSectionId, action: @escaping () -> Void, deleteAction: (() -> Void)? = nil) { public init(presentationData: ItemListPresentationData, icon: UIImage? = nil, iconSize: CGSize? = nil, iconPlacement: IconPlacement = .default, title: String, subtitle: String? = nil, style: ItemListCheckboxItemStyle, color: ItemListCheckboxItemColor = .accent, textColor: TextColor = .primary, checked: Bool, enabled: Bool = true, zeroSeparatorInsets: Bool, sectionId: ItemListSectionId, action: @escaping () -> Void, deleteAction: (() -> Void)? = nil) {
self.presentationData = presentationData self.presentationData = presentationData
self.icon = icon self.icon = icon
self.iconSize = iconSize self.iconSize = iconSize
@ -52,6 +53,7 @@ public class ItemListCheckboxItem: ListViewItem, ItemListItem {
self.color = color self.color = color
self.textColor = textColor self.textColor = textColor
self.checked = checked self.checked = checked
self.enabled = enabled
self.zeroSeparatorInsets = zeroSeparatorInsets self.zeroSeparatorInsets = zeroSeparatorInsets
self.sectionId = sectionId self.sectionId = sectionId
self.action = action self.action = action
@ -95,7 +97,9 @@ public class ItemListCheckboxItem: ListViewItem, ItemListItem {
public func selected(listView: ListView){ public func selected(listView: ListView){
listView.clearHighlightAnimated(true) listView.clearHighlightAnimated(true)
self.action() if self.enabled {
self.action()
}
} }
} }
@ -209,7 +213,7 @@ public class ItemListCheckboxItemNode: ItemListRevealOptionsItemNode {
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize) let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
let subtitleFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 15.0 / 17.0)) let subtitleFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 15.0 / 17.0))
let titleColor: UIColor var titleColor: UIColor
let subtitleColor: UIColor = item.presentationData.theme.list.itemSecondaryTextColor let subtitleColor: UIColor = item.presentationData.theme.list.itemSecondaryTextColor
switch item.textColor { switch item.textColor {
case .primary: case .primary:
@ -217,6 +221,9 @@ public class ItemListCheckboxItemNode: ItemListRevealOptionsItemNode {
case .accent: case .accent:
titleColor = item.presentationData.theme.list.itemAccentColor titleColor = item.presentationData.theme.list.itemAccentColor
} }
if !item.enabled {
titleColor = item.presentationData.theme.list.itemDisabledTextColor
}
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: titleColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 28.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: titleColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 28.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
@ -239,12 +246,16 @@ public class ItemListCheckboxItemNode: ItemListRevealOptionsItemNode {
updatedTheme = item.presentationData.theme updatedTheme = item.presentationData.theme
} }
if currentItem?.presentationData.theme !== item.presentationData.theme || currentItem?.color != item.color { if currentItem?.presentationData.theme !== item.presentationData.theme || currentItem?.color != item.color || currentItem?.enabled != item.enabled {
switch item.color { if !item.enabled {
case .accent: updateCheckImage = PresentationResourcesItemList.disabledCheckIconImage(item.presentationData.theme)
updateCheckImage = PresentationResourcesItemList.checkIconImage(item.presentationData.theme) } else {
case .secondary: switch item.color {
updateCheckImage = PresentationResourcesItemList.secondaryCheckIconImage(item.presentationData.theme) case .accent:
updateCheckImage = PresentationResourcesItemList.checkIconImage(item.presentationData.theme)
case .secondary:
updateCheckImage = PresentationResourcesItemList.secondaryCheckIconImage(item.presentationData.theme)
}
} }
} }
@ -261,6 +272,11 @@ public class ItemListCheckboxItemNode: ItemListRevealOptionsItemNode {
} else { } else {
strongSelf.activateArea.accessibilityValue = "" strongSelf.activateArea.accessibilityValue = ""
} }
if item.enabled {
strongSelf.activateArea.accessibilityTraits = []
} else {
strongSelf.activateArea.accessibilityTraits = [.notEnabled]
}
strongSelf.activateArea.frame = CGRect(origin: CGPoint(x: params.leftInset, y: 0.0), size: CGSize(width: params.width - params.leftInset - params.rightInset, height: layout.contentSize.height)) strongSelf.activateArea.frame = CGRect(origin: CGPoint(x: params.leftInset, y: 0.0), size: CGSize(width: params.width - params.leftInset - params.rightInset, height: layout.contentSize.height))
@ -368,7 +384,7 @@ public class ItemListCheckboxItemNode: ItemListRevealOptionsItemNode {
override public func setHighlighted(_ highlighted: Bool, at point: CGPoint, animated: Bool) { override public func setHighlighted(_ highlighted: Bool, at point: CGPoint, animated: Bool) {
super.setHighlighted(highlighted, at: point, animated: animated) super.setHighlighted(highlighted, at: point, animated: animated)
if highlighted { if highlighted && (self.item?.enabled ?? false) {
self.highlightedBackgroundNode.alpha = 1.0 self.highlightedBackgroundNode.alpha = 1.0
if self.highlightedBackgroundNode.supernode == nil { if self.highlightedBackgroundNode.supernode == nil {
var anchorNode: ASDisplayNode? var anchorNode: ASDisplayNode?

View File

@ -141,13 +141,13 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
case forwardsPreview(PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationChatBubbleCorners, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, String, Bool, String) case forwardsPreview(PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationChatBubbleCorners, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, String, Bool, String)
case birthdayHeader(PresentationTheme, String) case birthdayHeader(PresentationTheme, String)
case settingHeader(PresentationTheme, String) case settingHeader(PresentationTheme, String)
case everybody(PresentationTheme, String, Bool, Bool) case everybody(PresentationTheme, String, Bool, Bool, Bool)
case contacts(PresentationTheme, String, Bool, Bool) case contacts(PresentationTheme, String, Bool, Bool, Bool)
case nobody(PresentationTheme, String, Bool, Bool) case nobody(PresentationTheme, String, Bool, Bool, Bool)
case settingInfo(PresentationTheme, String, String) case settingInfo(PresentationTheme, String, String)
case exceptionsHeader(PresentationTheme, String) case exceptionsHeader(PresentationTheme, String)
case disableFor(PresentationTheme, String, String) case disableFor(PresentationTheme, String, String, Bool)
case enableFor(PresentationTheme, String, String) case enableFor(PresentationTheme, String, String, Bool)
case peersInfo(PresentationTheme, String) case peersInfo(PresentationTheme, String)
case callsP2PHeader(PresentationTheme, String) case callsP2PHeader(PresentationTheme, String)
case callsP2PAlways(PresentationTheme, String, Bool) case callsP2PAlways(PresentationTheme, String, Bool)
@ -323,20 +323,20 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
} else { } else {
return false return false
} }
case let .everybody(lhsTheme, lhsText, lhsValue, lhsIsLocked): case let .everybody(lhsTheme, lhsText, lhsValue, lhsIsLocked, lhsEnabled):
if case let .everybody(rhsTheme, rhsText, rhsValue, rhsIsLocked) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue, lhsIsLocked == rhsIsLocked { if case let .everybody(rhsTheme, rhsText, rhsValue, rhsIsLocked, rhsEnabled) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue, lhsIsLocked == rhsIsLocked, lhsEnabled == rhsEnabled {
return true return true
} else { } else {
return false return false
} }
case let .contacts(lhsTheme, lhsText, lhsValue, lhsIsLocked): case let .contacts(lhsTheme, lhsText, lhsValue, lhsIsLocked, lhsEnabled):
if case let .contacts(rhsTheme, rhsText, rhsValue, rhsIsLocked) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue, lhsIsLocked == rhsIsLocked { if case let .contacts(rhsTheme, rhsText, rhsValue, rhsIsLocked, rhsEnabled) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue, lhsIsLocked == rhsIsLocked, lhsEnabled == rhsEnabled {
return true return true
} else { } else {
return false return false
} }
case let .nobody(lhsTheme, lhsText, lhsValue, lhsIsLocked): case let .nobody(lhsTheme, lhsText, lhsValue, lhsIsLocked, lhsEnabled):
if case let .nobody(rhsTheme, rhsText, rhsValue, rhsIsLocked) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue, lhsIsLocked == rhsIsLocked { if case let .nobody(rhsTheme, rhsText, rhsValue, rhsIsLocked, rhsEnabled) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue, lhsIsLocked == rhsIsLocked, lhsEnabled == rhsEnabled {
return true return true
} else { } else {
return false return false
@ -353,14 +353,14 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
} else { } else {
return false return false
} }
case let .disableFor(lhsTheme, lhsText, lhsValue): case let .disableFor(lhsTheme, lhsText, lhsValue, lhsEnabled):
if case let .disableFor(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { if case let .disableFor(rhsTheme, rhsText, rhsValue, rhsEnabled) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue, lhsEnabled == rhsEnabled {
return true return true
} else { } else {
return false return false
} }
case let .enableFor(lhsTheme, lhsText, lhsValue): case let .enableFor(lhsTheme, lhsText, lhsValue, lhsEnabled):
if case let .enableFor(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { if case let .enableFor(rhsTheme, rhsText, rhsValue, rhsEnabled) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue, lhsEnabled == rhsEnabled {
return true return true
} else { } else {
return false return false
@ -565,23 +565,23 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
}) })
case let .settingHeader(_, text): case let .settingHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, multiline: true, sectionId: self.section) return ItemListSectionHeaderItem(presentationData: presentationData, text: text, multiline: true, sectionId: self.section)
case let .everybody(_, text, value, isLocked): case let .everybody(_, text, value, isLocked, isEnabled):
return ItemListCheckboxItem(presentationData: presentationData, icon: !isLocked ? nil : generateTintedImage(image: UIImage(bundleImageName: "Chat/Stickers/Lock"), color: presentationData.theme.list.itemSecondaryTextColor), iconPlacement: .check, title: text, style: .left, checked: value && !isLocked, zeroSeparatorInsets: false, sectionId: self.section, action: { return ItemListCheckboxItem(presentationData: presentationData, icon: !isLocked ? nil : generateTintedImage(image: UIImage(bundleImageName: "Chat/Stickers/Lock"), color: presentationData.theme.list.itemSecondaryTextColor), iconPlacement: .check, title: text, style: .left, checked: value && !isLocked, enabled: isEnabled, zeroSeparatorInsets: false, sectionId: self.section, action: {
if isLocked { if isLocked {
} else { } else {
arguments.updateType(.everybody) arguments.updateType(.everybody)
} }
}) })
case let .contacts(_, text, value, isLocked): case let .contacts(_, text, value, isLocked, isEnabled):
return ItemListCheckboxItem(presentationData: presentationData, icon: !isLocked ? nil : generateTintedImage(image: UIImage(bundleImageName: "Chat/Stickers/Lock"), color: presentationData.theme.list.itemSecondaryTextColor), iconPlacement: .check, title: text, style: .left, checked: value && !isLocked, zeroSeparatorInsets: false, sectionId: self.section, action: { return ItemListCheckboxItem(presentationData: presentationData, icon: !isLocked ? nil : generateTintedImage(image: UIImage(bundleImageName: "Chat/Stickers/Lock"), color: presentationData.theme.list.itemSecondaryTextColor), iconPlacement: .check, title: text, style: .left, checked: value && !isLocked, enabled: isEnabled, zeroSeparatorInsets: false, sectionId: self.section, action: {
if isLocked { if isLocked {
arguments.displayLockedInfo() arguments.displayLockedInfo()
} else { } else {
arguments.updateType(.contacts) arguments.updateType(.contacts)
} }
}) })
case let .nobody(_, text, value, isLocked): case let .nobody(_, text, value, isLocked, isEnabled):
return ItemListCheckboxItem(presentationData: presentationData, icon: !isLocked ? nil : generateTintedImage(image: UIImage(bundleImageName: "Chat/Stickers/Lock"), color: presentationData.theme.list.itemSecondaryTextColor), iconPlacement: .check, title: text, style: .left, checked: value && !isLocked, zeroSeparatorInsets: false, sectionId: self.section, action: { return ItemListCheckboxItem(presentationData: presentationData, icon: !isLocked ? nil : generateTintedImage(image: UIImage(bundleImageName: "Chat/Stickers/Lock"), color: presentationData.theme.list.itemSecondaryTextColor), iconPlacement: .check, title: text, style: .left, checked: value && !isLocked, enabled: isEnabled, zeroSeparatorInsets: false, sectionId: self.section, action: {
if isLocked { if isLocked {
arguments.displayLockedInfo() arguments.displayLockedInfo()
} else { } else {
@ -594,12 +594,12 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
}) })
case let .exceptionsHeader(_, text): case let .exceptionsHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .disableFor(_, title, value): case let .disableFor(_, title, value, isEnabled):
return ItemListDisclosureItem(presentationData: presentationData, title: title, label: value, sectionId: self.section, style: .blocks, action: { return ItemListDisclosureItem(presentationData: presentationData, title: title, enabled: isEnabled, label: value, sectionId: self.section, style: .blocks, action: {
arguments.openSelective(.main, false) arguments.openSelective(.main, false)
}) })
case let .enableFor(_, title, value): case let .enableFor(_, title, value, isEnabled):
return ItemListDisclosureItem(presentationData: presentationData, title: title, label: value, sectionId: self.section, style: .blocks, action: { return ItemListDisclosureItem(presentationData: presentationData, title: title, enabled: isEnabled, label: value, sectionId: self.section, style: .blocks, action: {
arguments.openSelective(.main, true) arguments.openSelective(.main, true)
}) })
case let .peersInfo(_, text): case let .peersInfo(_, text):
@ -1000,9 +1000,14 @@ private func selectivePrivacySettingsControllerEntries(presentationData: Present
enableForText = presentationData.strings.Privacy_GroupsAndChannels_AlwaysAllow enableForText = presentationData.strings.Privacy_GroupsAndChannels_AlwaysAllow
} }
var permisisonsEnabled = true
if case .giftsAutoSave = kind { if case .giftsAutoSave = kind {
entries.append(.showGiftButton(presentationData.theme, "Show Gift Icon in Chats", !isPremium, state.showGiftButton == true && state.disallowedGifts != TelegramDisallowedGifts.All, state.disallowedGifts != TelegramDisallowedGifts.All)) entries.append(.showGiftButton(presentationData.theme, presentationData.strings.Privacy_Gifts_ShowGiftButton, !isPremium, state.showGiftButton == true, true))
entries.append(.showGiftButtonInfo(presentationData.theme, "Display the # Gift icon in the message input field for both participants in all chats.")) entries.append(.showGiftButtonInfo(presentationData.theme, presentationData.strings.Privacy_Gifts_ShowGiftButtonInfo.replacingOccurrences(of: "#", with: " # ")))
if state.disallowedGifts == TelegramDisallowedGifts.All {
permisisonsEnabled = false
}
} }
if case .forwards = kind { if case .forwards = kind {
@ -1030,13 +1035,13 @@ private func selectivePrivacySettingsControllerEntries(presentationData: Present
entries.append(.settingHeader(presentationData.theme, settingTitle)) entries.append(.settingHeader(presentationData.theme, settingTitle))
if case .voiceMessages = kind { if case .voiceMessages = kind {
entries.append(.everybody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenEverybody, state.setting == .everybody || !isPremium, false)) entries.append(.everybody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenEverybody, state.setting == .everybody || !isPremium, false, permisisonsEnabled))
entries.append(.contacts(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenContacts, state.setting == .contacts && isPremium, !isPremium)) entries.append(.contacts(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenContacts, state.setting == .contacts && isPremium, !isPremium, permisisonsEnabled))
entries.append(.nobody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenNobody, state.setting == .nobody && isPremium, !isPremium)) entries.append(.nobody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenNobody, state.setting == .nobody && isPremium, !isPremium, permisisonsEnabled))
} else { } else {
entries.append(.everybody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenEverybody, state.setting == .everybody, false)) entries.append(.everybody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenEverybody, state.setting == .everybody, false, permisisonsEnabled))
entries.append(.contacts(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenContacts, state.setting == .contacts, false)) entries.append(.contacts(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenContacts, state.setting == .contacts, false, permisisonsEnabled))
entries.append(.nobody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenNobody, state.setting == .nobody, false)) entries.append(.nobody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenNobody, state.setting == .nobody, false, permisisonsEnabled))
} }
if let settingInfoText = settingInfoText { if let settingInfoText = settingInfoText {
@ -1059,12 +1064,12 @@ private func selectivePrivacySettingsControllerEntries(presentationData: Present
switch state.setting { switch state.setting {
case .everybody: case .everybody:
entries.append(.disableFor(presentationData.theme, disableForText, stringForUserCount(state.disableFor, enableForPremium: false, enableForBots: false, strings: presentationData.strings))) entries.append(.disableFor(presentationData.theme, disableForText, stringForUserCount(state.disableFor, enableForPremium: false, enableForBots: false, strings: presentationData.strings), permisisonsEnabled))
case .contacts: case .contacts:
entries.append(.disableFor(presentationData.theme, disableForText, stringForUserCount(state.disableFor, enableForPremium: false, enableForBots: false, strings: presentationData.strings))) entries.append(.disableFor(presentationData.theme, disableForText, stringForUserCount(state.disableFor, enableForPremium: false, enableForBots: false, strings: presentationData.strings), permisisonsEnabled))
entries.append(.enableFor(presentationData.theme, enableForText, stringForUserCount(state.enableFor, enableForPremium: state.enableForPremium, enableForBots: state.enableForBots, strings: presentationData.strings))) entries.append(.enableFor(presentationData.theme, enableForText, stringForUserCount(state.enableFor, enableForPremium: state.enableForPremium, enableForBots: state.enableForBots, strings: presentationData.strings), permisisonsEnabled))
case .nobody: case .nobody:
entries.append(.enableFor(presentationData.theme, enableForText, stringForUserCount(state.enableFor, enableForPremium: state.enableForPremium, enableForBots: state.enableForBots, strings: presentationData.strings))) entries.append(.enableFor(presentationData.theme, enableForText, stringForUserCount(state.enableFor, enableForPremium: state.enableForPremium, enableForBots: state.enableForBots, strings: presentationData.strings), permisisonsEnabled))
} }
let exceptionsInfo: String let exceptionsInfo: String
if case .profilePhoto = kind { if case .profilePhoto = kind {
@ -1146,13 +1151,12 @@ private func selectivePrivacySettingsControllerEntries(presentationData: Present
} }
if case .giftsAutoSave = kind { if case .giftsAutoSave = kind {
//TODO:localize entries.append(.disallowedGiftsHeader(presentationData.theme, presentationData.strings.Privacy_Gifts_AcceptedTypes.uppercased()))
entries.append(.disallowedGiftsHeader(presentationData.theme, "ACCEPTED GIFT TYPES")) entries.append(.disallowedGiftsUnlimited(presentationData.theme, presentationData.strings.Privacy_Gifts_AcceptedTypes_Unlimited, !isPremium, !(state.disallowedGifts?.contains(.unlimited) ?? false)))
entries.append(.disallowedGiftsUnlimited(presentationData.theme, "Unlimited", !isPremium, !(state.disallowedGifts?.contains(.unlimited) ?? false))) entries.append(.disallowedGiftsLimited(presentationData.theme, presentationData.strings.Privacy_Gifts_AcceptedTypes_Limited, !isPremium, !(state.disallowedGifts?.contains(.limited) ?? false)))
entries.append(.disallowedGiftsLimited(presentationData.theme, "Limited-Edition", !isPremium, !(state.disallowedGifts?.contains(.limited) ?? false))) entries.append(.disallowedGiftsUnique(presentationData.theme, presentationData.strings.Privacy_Gifts_AcceptedTypes_Unique, !isPremium, !(state.disallowedGifts?.contains(.unique) ?? false)))
entries.append(.disallowedGiftsUnique(presentationData.theme, "Unique", !isPremium, !(state.disallowedGifts?.contains(.unique) ?? false))) entries.append(.disallowedGiftsPremium(presentationData.theme, presentationData.strings.Privacy_Gifts_AcceptedTypes_Premium, !isPremium, !(state.disallowedGifts?.contains(.premium) ?? false)))
entries.append(.disallowedGiftsPremium(presentationData.theme, "Premium Subscriptions", !isPremium, !(state.disallowedGifts?.contains(.premium) ?? false))) entries.append(.disallowedGiftsInfo(presentationData.theme, presentationData.strings.Privacy_Gifts_AcceptedTypes_Info))
entries.append(.disallowedGiftsInfo(presentationData.theme, "Choose the types of gifts that you allow others to send you."))
} }
return entries return entries

View File

@ -1000,7 +1000,7 @@ public final class CachedUserData: CachedPeerData {
public let starRefProgram: TelegramStarRefProgram? public let starRefProgram: TelegramStarRefProgram?
public let verification: PeerVerification? public let verification: PeerVerification?
public let sendPaidMessageStars: StarsAmount? public let sendPaidMessageStars: StarsAmount?
public let disallowedGifts: TelegramDisallowedGifts public let disallowedGifts: TelegramDisallowedGifts?
public let peerIds: Set<PeerId> public let peerIds: Set<PeerId>
public let messageIds: Set<MessageId> public let messageIds: Set<MessageId>
@ -1042,10 +1042,10 @@ public final class CachedUserData: CachedPeerData {
self.starRefProgram = nil self.starRefProgram = nil
self.verification = nil self.verification = nil
self.sendPaidMessageStars = nil self.sendPaidMessageStars = nil
self.disallowedGifts = [] self.disallowedGifts = nil
} }
public init(about: String?, botInfo: BotInfo?, editableBotInfo: EditableBotInfo?, peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, isBlocked: Bool, commonGroupCount: Int32, voiceCallsAvailable: Bool, videoCallsAvailable: Bool, callsPrivate: Bool, canPinMessages: Bool, hasScheduledMessages: Bool, autoremoveTimeout: CachedPeerAutoremoveTimeout, themeEmoticon: String?, photo: CachedPeerProfilePhoto, personalPhoto: CachedPeerProfilePhoto, fallbackPhoto: CachedPeerProfilePhoto, voiceMessagesAvailable: Bool, wallpaper: TelegramWallpaper?, flags: CachedUserFlags, businessHours: TelegramBusinessHours?, businessLocation: TelegramBusinessLocation?, greetingMessage: TelegramBusinessGreetingMessage?, awayMessage: TelegramBusinessAwayMessage?, connectedBot: TelegramAccountConnectedBot?, businessIntro: CachedTelegramBusinessIntro, birthday: TelegramBirthday?, personalChannel: CachedTelegramPersonalChannel, botPreview: BotPreview?, starGiftsCount: Int32?, starRefProgram: TelegramStarRefProgram?, verification: PeerVerification?, sendPaidMessageStars: StarsAmount?, disallowedGifts: TelegramDisallowedGifts) { public init(about: String?, botInfo: BotInfo?, editableBotInfo: EditableBotInfo?, peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, isBlocked: Bool, commonGroupCount: Int32, voiceCallsAvailable: Bool, videoCallsAvailable: Bool, callsPrivate: Bool, canPinMessages: Bool, hasScheduledMessages: Bool, autoremoveTimeout: CachedPeerAutoremoveTimeout, themeEmoticon: String?, photo: CachedPeerProfilePhoto, personalPhoto: CachedPeerProfilePhoto, fallbackPhoto: CachedPeerProfilePhoto, voiceMessagesAvailable: Bool, wallpaper: TelegramWallpaper?, flags: CachedUserFlags, businessHours: TelegramBusinessHours?, businessLocation: TelegramBusinessLocation?, greetingMessage: TelegramBusinessGreetingMessage?, awayMessage: TelegramBusinessAwayMessage?, connectedBot: TelegramAccountConnectedBot?, businessIntro: CachedTelegramBusinessIntro, birthday: TelegramBirthday?, personalChannel: CachedTelegramPersonalChannel, botPreview: BotPreview?, starGiftsCount: Int32?, starRefProgram: TelegramStarRefProgram?, verification: PeerVerification?, sendPaidMessageStars: StarsAmount?, disallowedGifts: TelegramDisallowedGifts?) {
self.about = about self.about = about
self.botInfo = botInfo self.botInfo = botInfo
self.editableBotInfo = editableBotInfo self.editableBotInfo = editableBotInfo
@ -1153,7 +1153,7 @@ public final class CachedUserData: CachedPeerData {
self.sendPaidMessageStars = decoder.decodeCodable(StarsAmount.self, forKey: "sendPaidMessageStars") self.sendPaidMessageStars = decoder.decodeCodable(StarsAmount.self, forKey: "sendPaidMessageStars")
self.disallowedGifts = TelegramDisallowedGifts(rawValue: decoder.decodeInt32ForKey("disallowedGifts", orElse: 0)) self.disallowedGifts = decoder.decodeOptionalInt32ForKey("disallowedGifts").flatMap { TelegramDisallowedGifts(rawValue: $0) }
} }
public func encode(_ encoder: PostboxEncoder) { public func encode(_ encoder: PostboxEncoder) {
@ -1283,7 +1283,11 @@ public final class CachedUserData: CachedPeerData {
encoder.encodeNil(forKey: "sendPaidMessageStars") encoder.encodeNil(forKey: "sendPaidMessageStars")
} }
encoder.encodeInt32(self.disallowedGifts.rawValue, forKey: "disallowedGifts") if let disallowedGifts = self.disallowedGifts {
encoder.encodeInt32(disallowedGifts.rawValue, forKey: "disallowedGifts")
} else {
encoder.encodeNil(forKey: "disallowedGifts")
}
} }
public func isEqual(to: CachedPeerData) -> Bool { public func isEqual(to: CachedPeerData) -> Bool {

View File

@ -617,9 +617,6 @@ func _internal_markAdAction(account: Account, opaqueId: Data, media: Bool, fulls
let _ = signal.start() let _ = signal.start()
} }
func _internal_markAsSeen(account: Account, opaqueId: Data) -> Signal<Never, NoError> { func _internal_markAsSeen(account: Account, opaqueId: Data) -> Signal<Never, NoError> {
return account.network.request(Api.functions.messages.viewSponsoredMessage(randomId: Buffer(data: opaqueId))) return account.network.request(Api.functions.messages.viewSponsoredMessage(randomId: Buffer(data: opaqueId)))
|> `catch` { _ -> Signal<Api.Bool, NoError> in |> `catch` { _ -> Signal<Api.Bool, NoError> in

View File

@ -43,6 +43,7 @@ public enum PresentationResourceKey: Int32 {
case itemListDisclosureLocked case itemListDisclosureLocked
case itemListCheckIcon case itemListCheckIcon
case itemListSecondaryCheckIcon case itemListSecondaryCheckIcon
case itemListDisabledCheckIcon
case itemListPlusIcon case itemListPlusIcon
case itemListRoundPlusIcon case itemListRoundPlusIcon
case itemListAccentDeleteIcon case itemListAccentDeleteIcon

View File

@ -57,6 +57,12 @@ public struct PresentationResourcesItemList {
}) })
} }
public static func disabledCheckIconImage(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.itemListDisabledCheckIcon.rawValue, { theme in
return generateItemListCheckIcon(color: theme.list.itemDisabledTextColor)
})
}
public static func plusIconImage(_ theme: PresentationTheme) -> UIImage? { public static func plusIconImage(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.itemListPlusIcon.rawValue, { theme in return theme.image(PresentationResourceKey.itemListPlusIcon.rawValue, { theme in
return generateItemListPlusIcon(theme.list.itemAccentColor) return generateItemListPlusIcon(theme.list.itemAccentColor)

View File

@ -193,10 +193,9 @@ private final class ScrollContent: CombinedComponent {
adsText = strings.AdsInfo_Bot_Ads_Text adsText = strings.AdsInfo_Bot_Ads_Text
infoRawText = strings.AdsInfo_Bot_Launch_Text infoRawText = strings.AdsInfo_Bot_Launch_Text
case .search: case .search:
//TODO:localize respectText = strings.AdsInfo_Search_Respect_Text
respectText = "Ads like this do not use your personal information and are based on the search query you entered." adsText = strings.AdsInfo_Search_Ads_Text
adsText = strings.AdsInfo_Bot_Ads_Text infoRawText = strings.AdsInfo_Search_Launch_Text
infoRawText = "Anyone can create an ad to display in search results for any query. Check out the Telegram Ad Platform for details. [Learn More >]()"
} }
var items: [AnyComponentWithIdentity<Empty>] = [] var items: [AnyComponentWithIdentity<Empty>] = []

View File

@ -692,6 +692,10 @@ final class GiftOptionsScreenComponent: Component {
} }
self.component = component self.component = component
if let disallowedGifts = self.state?.disallowedGifts, disallowedGifts == .All {
controller()?.dismiss()
}
if (state.starGifts ?? []).isEmpty && !(state.transferStarGifts ?? []).isEmpty { if (state.starGifts ?? []).isEmpty && !(state.transferStarGifts ?? []).isEmpty {
self.starsFilter = .transfer self.starsFilter = .transfer
} }
@ -1344,19 +1348,26 @@ final class GiftOptionsScreenComponent: Component {
self.disposable = combineLatest( self.disposable = combineLatest(
queue: Queue.mainQueue(), queue: Queue.mainQueue(),
context.engine.data.get( context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.Peer.init(id: peerId), TelegramEngine.EngineData.Item.Peer.Peer.init(id: peerId)
),
context.engine.data.subscribe(
TelegramEngine.EngineData.Item.Peer.DisallowedGifts(id: peerId) TelegramEngine.EngineData.Item.Peer.DisallowedGifts(id: peerId)
), ),
availableProducts, availableProducts,
context.engine.payments.cachedStarGifts(), context.engine.payments.cachedStarGifts(),
self.starGiftsContext.state self.starGiftsContext.state
).start(next: { [weak self] data, availableProducts, starGifts, profileGiftsState in ).start(next: { [weak self] peer, disallowedGifts, availableProducts, starGifts, profileGiftsState in
guard let self else { guard let self else {
return return
} }
self.peer = data.0
self.disallowedGifts = data.1 ?? []
if disallowedGifts == nil && self.peer == nil, case .user = peer {
let _ = context.engine.peers.fetchAndUpdateCachedPeerData(peerId: peerId).startStandalone()
}
self.peer = peer
self.disallowedGifts = disallowedGifts ?? []
if peerId != context.account.peerId { if peerId != context.account.peerId {
if availableProducts.isEmpty { if availableProducts.isEmpty {
var premiumProducts: [PremiumGiftProduct] = [] var premiumProducts: [PremiumGiftProduct] = []

View File

@ -390,8 +390,13 @@ final class GiftSetupScreenComponent: Component {
let completion = component.completion let completion = component.completion
let signal = BotCheckoutController.InputData.fetch(context: component.context, source: source) let signal = BotCheckoutController.InputData.fetch(context: component.context, source: source)
|> `catch` { _ -> Signal<BotCheckoutController.InputData, SendBotPaymentFormError> in |> `catch` { error -> Signal<BotCheckoutController.InputData, SendBotPaymentFormError> in
return .fail(.generic) switch error {
case .disallowedStarGifts:
return .fail(.disallowedStarGift)
default:
return .fail(.generic)
}
} }
|> mapToSignal { inputData -> Signal<SendBotPaymentResult, SendBotPaymentFormError> in |> mapToSignal { inputData -> Signal<SendBotPaymentResult, SendBotPaymentFormError> in
return component.context.engine.payments.sendStarsPaymentForm(formId: inputData.form.id, source: source) return component.context.engine.payments.sendStarsPaymentForm(formId: inputData.form.id, source: source)

View File

@ -14363,7 +14363,7 @@ private final class AccountPeerContextItemNode: ASDisplayNode, ContextMenuCustom
action: nil action: nil
)), )),
environment: {}, environment: {},
containerSize: CGSize(width: 28.0, height: 28.0) containerSize: CGSize(width: 24.0, height: 24.0)
) )
if let view = self.emojiStatusView.view { if let view = self.emojiStatusView.view {
if view.superview == nil { if view.superview == nil {

View File

@ -111,7 +111,7 @@ private final class SheetContent: CombinedComponent {
let title = title.update( let title = title.update(
component: BalancedTextComponent( component: BalancedTextComponent(
text: .plain(NSAttributedString(string: "Your Account is Frozen", font: titleFont, textColor: textColor)), text: .plain(NSAttributedString(string: strings.FrozenAccount_Title, font: titleFont, textColor: textColor)),
horizontalAlignment: .center, horizontalAlignment: .center,
maximumNumberOfLines: 0, maximumNumberOfLines: 0,
lineSpacing: 0.1 lineSpacing: 0.1
@ -125,15 +125,14 @@ private final class SheetContent: CombinedComponent {
contentSize.height += title.size.height contentSize.height += title.size.height
contentSize.height += spacing - 2.0 contentSize.height += spacing - 2.0
//TODO:localize
var items: [AnyComponentWithIdentity<Empty>] = [] var items: [AnyComponentWithIdentity<Empty>] = []
items.append( items.append(
AnyComponentWithIdentity( AnyComponentWithIdentity(
id: "ads", id: "violation",
component: AnyComponent(ParagraphComponent( component: AnyComponent(ParagraphComponent(
title: "Violation of Terms", title: strings.FrozenAccount_Violation_Title,
titleColor: textColor, titleColor: textColor,
text: "Your account was frozen for breaking Telegram's Terms and Conditions.", text: strings.FrozenAccount_Violation_Text,
textColor: secondaryTextColor, textColor: secondaryTextColor,
iconName: "Account Freeze/Violation", iconName: "Account Freeze/Violation",
iconColor: linkColor iconColor: linkColor
@ -142,11 +141,11 @@ private final class SheetContent: CombinedComponent {
) )
items.append( items.append(
AnyComponentWithIdentity( AnyComponentWithIdentity(
id: "split", id: "readOnly",
component: AnyComponent(ParagraphComponent( component: AnyComponent(ParagraphComponent(
title: "Read-Only Mode", title: strings.FrozenAccount_ReadOnly_Title,
titleColor: textColor, titleColor: textColor,
text: "You can access your account but can't send messages or take actions.", text: strings.FrozenAccount_ReadOnly_Text,
textColor: secondaryTextColor, textColor: secondaryTextColor,
iconName: "Ads/Privacy", iconName: "Ads/Privacy",
iconColor: linkColor iconColor: linkColor
@ -156,19 +155,17 @@ private final class SheetContent: CombinedComponent {
let dateString = stringForFullDate(timestamp: component.configuration.freezeUntilDate ?? 0, strings: strings, dateTimeFormat: environment.dateTimeFormat) let dateString = stringForFullDate(timestamp: component.configuration.freezeUntilDate ?? 0, strings: strings, dateTimeFormat: environment.dateTimeFormat)
items.append( items.append(
AnyComponentWithIdentity( AnyComponentWithIdentity(
id: "withdrawal", id: "appeal",
component: AnyComponent(ParagraphComponent( component: AnyComponent(ParagraphComponent(
title: "Appeal Before Deactivation", title: strings.FrozenAccount_Appeal_Title,
titleColor: textColor, titleColor: textColor,
text: "Appeal via [@SpamBot]() before \(dateString), or your account will be deleted.", text: strings.FrozenAccount_Appeal_Text(dateString).string,
textColor: secondaryTextColor, textColor: secondaryTextColor,
iconName: "Account Freeze/Appeal", iconName: "Account Freeze/Appeal",
iconColor: linkColor, iconColor: linkColor,
action: { action: {
component.submitAppeal()
component.dismiss() component.dismiss()
Queue.mainQueue().after(0.5) {
component.submitAppeal()
}
} }
)) ))
) )
@ -185,7 +182,7 @@ private final class SheetContent: CombinedComponent {
contentSize.height += list.size.height contentSize.height += list.size.height
contentSize.height += spacing + 2.0 contentSize.height += spacing + 2.0
let buttonAttributedString = NSMutableAttributedString(string: "Submit an Appeal", font: Font.semibold(17.0), textColor: environment.theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center) let buttonAttributedString = NSMutableAttributedString(string: strings.FrozenAccount_SubmitAppeal, font: Font.semibold(17.0), textColor: environment.theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)
let actionButton = actionButton.update( let actionButton = actionButton.update(
component: ButtonComponent( component: ButtonComponent(
background: ButtonComponent.Background( background: ButtonComponent.Background(
@ -201,10 +198,8 @@ private final class SheetContent: CombinedComponent {
isEnabled: true, isEnabled: true,
displaysProgress: false, displaysProgress: false,
action: { action: {
component.submitAppeal()
component.dismiss() component.dismiss()
Queue.mainQueue().after(0.5) {
component.submitAppeal()
}
} }
), ),
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0), availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0),
@ -217,7 +212,7 @@ private final class SheetContent: CombinedComponent {
contentSize.height += actionButton.size.height contentSize.height += actionButton.size.height
contentSize.height += 8.0 contentSize.height += 8.0
let closeAttributedString = NSMutableAttributedString(string: "Understood", font: Font.regular(17.0), textColor: environment.theme.list.itemCheckColors.fillColor, paragraphAlignment: .center) let closeAttributedString = NSMutableAttributedString(string: strings.FrozenAccount_Understood, font: Font.regular(17.0), textColor: environment.theme.list.itemCheckColors.fillColor, paragraphAlignment: .center)
let closeButton = closeButton.update( let closeButton = closeButton.update(
component: ButtonComponent( component: ButtonComponent(
background: ButtonComponent.Background( background: ButtonComponent.Background(
@ -390,10 +385,12 @@ public final class AccountFreezeInfoScreen: ViewControllerComponentContainer {
self.navigationPresentation = .flatModal self.navigationPresentation = .flatModal
submitAppealImpl = { [weak self] in submitAppealImpl = { [weak self] in
guard let self, let url = configuration.freezeAppealUrl else { guard let self, let navigationController = self.navigationController as? NavigationController, let url = configuration.freezeAppealUrl else {
return return
} }
context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: url, forceExternal: false, presentationData: context.sharedContext.currentPresentationData.with { $0 }, navigationController: self.navigationController as? NavigationController, dismissInput: {}) Queue.mainQueue().after(0.4) {
context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: url, forceExternal: false, presentationData: context.sharedContext.currentPresentationData.with { $0 }, navigationController: navigationController, dismissInput: {})
}
} }
} }

View File

@ -1061,11 +1061,16 @@ final class ChatbotSetupScreenComponent: Component {
) )
if let subpermissions = permission.subpermissions { if let subpermissions = permission.subpermissions {
value = false value = true
var selectedCount = 0 var selectedCount = 0
for subpermission in subpermissions { for subpermission in subpermissions {
if subpermission.value == true { if let key = subpermission.key {
value = true if self.botRights.contains(key) {
selectedCount += 1
} else {
value = false
}
} else if subpermission.value == true {
selectedCount += 1 selectedCount += 1
} }
} }
@ -1138,8 +1143,10 @@ final class ChatbotSetupScreenComponent: Component {
if let subpermissions = permission.subpermissions, permission.expanded == true { if let subpermissions = permission.subpermissions, permission.expanded == true {
for subpermission in subpermissions { for subpermission in subpermissions {
var value = false var value = false
if let key = permission.key { if let key = subpermission.key {
value = self.botRights.contains(key) value = self.botRights.contains(key)
} else if subpermission.value == true {
value = true
} }
permissionsItems.append( permissionsItems.append(

View File

@ -89,10 +89,9 @@ final class ChatRestrictedInputPanelNode: ChatInputPanelNode {
if let context = self.context { if let context = self.context {
accountFreezeConfiguration = AccountFreezeConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }) accountFreezeConfiguration = AccountFreezeConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
} }
//TODO:localize
if let _ = accountFreezeConfiguration?.freezeUntilDate { if let _ = accountFreezeConfiguration?.freezeUntilDate {
self.textNode.attributedText = NSAttributedString(string: "You account is frozen", font: Font.semibold(15.0), textColor: interfaceState.theme.list.itemDestructiveColor) self.textNode.attributedText = NSAttributedString(string: interfaceState.strings.Chat_PanelFrozenAccount_Title, font: Font.semibold(15.0), textColor: interfaceState.theme.list.itemDestructiveColor)
self.subtitleNode.attributedText = NSAttributedString(string: "Tap to view details", font: Font.regular(13.0), textColor: interfaceState.theme.chat.inputPanel.secondaryTextColor) self.subtitleNode.attributedText = NSAttributedString(string: interfaceState.strings.Chat_PanelFrozenAccount_Text, font: Font.regular(13.0), textColor: interfaceState.theme.chat.inputPanel.secondaryTextColor)
isUserInteractionEnabled = true isUserInteractionEnabled = true
} else if case let .replyThread(message) = interfaceState.chatLocation, message.peerId == self.context?.account.peerId { } else if case let .replyThread(message) = interfaceState.chatLocation, message.peerId == self.context?.account.peerId {
self.textNode.attributedText = NSAttributedString(string: interfaceState.strings.Chat_PanelStatusAuthorHidden, font: Font.regular(13.0), textColor: interfaceState.theme.chat.inputPanel.secondaryTextColor) self.textNode.attributedText = NSAttributedString(string: interfaceState.strings.Chat_PanelStatusAuthorHidden, font: Font.regular(13.0), textColor: interfaceState.theme.chat.inputPanel.secondaryTextColor)