mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various improvements
This commit is contained in:
parent
c92ce1c1dc
commit
83c7fdd228
@ -9197,6 +9197,8 @@ Sorry for the inconvenience.";
|
|||||||
|
|
||||||
"WebApp.LaunchMoreInfo" = "More about this bot";
|
"WebApp.LaunchMoreInfo" = "More about this bot";
|
||||||
"WebApp.LaunchConfirmation" = "To launch this web app, you will connect to its website.";
|
"WebApp.LaunchConfirmation" = "To launch this web app, you will connect to its website.";
|
||||||
|
"WebApp.LaunchTermsConfirmation" = "By launching this mini app, you agree to the [Terms of Service for Mini Apps]().";
|
||||||
|
"WebApp.LaunchTermsConfirmation_URL" = "https://telegram.org/tos/mini-apps";
|
||||||
"WebApp.LaunchOpenApp" = "Open App";
|
"WebApp.LaunchOpenApp" = "Open App";
|
||||||
|
|
||||||
"WallpaperPreview.PreviewInNightMode" = "Preview this wallpaper in night mode.";
|
"WallpaperPreview.PreviewInNightMode" = "Preview this wallpaper in night mode.";
|
||||||
@ -12517,6 +12519,7 @@ Sorry for the inconvenience.";
|
|||||||
"Notification.StarsGift.Title_any" = "%@ Stars";
|
"Notification.StarsGift.Title_any" = "%@ Stars";
|
||||||
"Notification.StarsGift.Subtitle" = "Use Stars to unlock content and services on Telegram.";
|
"Notification.StarsGift.Subtitle" = "Use Stars to unlock content and services on Telegram.";
|
||||||
"Notification.StarsGift.SubtitleYou" = "With Stars, %@ will be able to unlock content and services on Telegram.";
|
"Notification.StarsGift.SubtitleYou" = "With Stars, %@ will be able to unlock content and services on Telegram.";
|
||||||
|
"Notification.StarsGift.UnknownUser" = "Unknown user";
|
||||||
|
|
||||||
"Bot.Settings" = "Bot Settings";
|
"Bot.Settings" = "Bot Settings";
|
||||||
|
|
||||||
@ -12736,3 +12739,32 @@ Sorry for the inconvenience.";
|
|||||||
"Stars.Transfer.Subscribe.Successful.Text" = "%1$@ transferred to %2$@.";
|
"Stars.Transfer.Subscribe.Successful.Text" = "%1$@ transferred to %2$@.";
|
||||||
|
|
||||||
"Gallery.Ad" = "Ad";
|
"Gallery.Ad" = "Ad";
|
||||||
|
|
||||||
|
"Chat.SensitiveContent" = "18+ Content";
|
||||||
|
|
||||||
|
"Settings.SensitiveContent" = "Show 18+ Content";
|
||||||
|
"Settings.SensitiveContentInfo" = "Do not hide media that contain content suitable only for adults.";
|
||||||
|
|
||||||
|
"SensitiveContent.Title" = "18+ Content";
|
||||||
|
"SensitiveContent.Text" = "This media may contain sensitive content suitable only for adults.\nDo you still want to view it?";
|
||||||
|
"SensitiveContent.ShowAlways" = "Always show 18+ media";
|
||||||
|
"SensitiveContent.ViewAnyway" = "View Anyway";
|
||||||
|
"SensitiveContent.SettingsInfo" = "You can update the visibility of sensitive media in [Data and Storage > Show 18+ Content]().";
|
||||||
|
|
||||||
|
"Notification.Refund" = "You received a refund of {amount} from {name}";
|
||||||
|
|
||||||
|
"InviteLink.SubscriptionFee.Title" = "SUBSCRIPTION FEE";
|
||||||
|
"InviteLink.SubscriptionFee.PerMonth" = "%@ / month";
|
||||||
|
"InviteLink.SubscriptionFee.NoOneJoined" = "No one joined yet";
|
||||||
|
"InviteLink.SubscriptionFee.ApproximateIncome" = "You get approximately %@ monthly";
|
||||||
|
|
||||||
|
"InviteLink.PerMonth" = "per month";
|
||||||
|
|
||||||
|
"InviteLink.Create.Fee" = "Require Monthly Fee";
|
||||||
|
"InviteLink.Create.FeePerMonth" = "%@ / month";
|
||||||
|
"InviteLink.Create.FeePlaceholder" = "Stars amount per month";
|
||||||
|
"InviteLink.Create.FeeInfo" = "Charge a subscription fee from people joining your channel via this link. [Learn More >]()";
|
||||||
|
"InviteLink.Create.FeeEditInfo" = "If you need to change the subscription fee, create a new invite link with a different price.";
|
||||||
|
"InviteLink.Create.RequestApprovalFeeUnavailable" = "You can't enable admin approval for links that require a monthly fee.";
|
||||||
|
|
||||||
|
"WebApp.PrivacyPolicy_URL" = "https://telegram.org/privacy-tpa";
|
||||||
|
@ -996,6 +996,8 @@ public protocol SharedAccountContext: AnyObject {
|
|||||||
|
|
||||||
func makeProxySettingsController(sharedContext: SharedAccountContext, account: UnauthorizedAccount) -> ViewController
|
func makeProxySettingsController(sharedContext: SharedAccountContext, account: UnauthorizedAccount) -> ViewController
|
||||||
|
|
||||||
|
func makeDataAndStorageController(context: AccountContext, sensitiveContent: Bool) -> ViewController
|
||||||
|
|
||||||
func makeInstalledStickerPacksController(context: AccountContext, mode: InstalledStickerPacksControllerMode, forceTheme: PresentationTheme?) -> ViewController
|
func makeInstalledStickerPacksController(context: AccountContext, mode: InstalledStickerPacksControllerMode, forceTheme: PresentationTheme?) -> ViewController
|
||||||
|
|
||||||
func makeChannelStatsController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peerId: EnginePeer.Id, boosts: Bool, boostStatus: ChannelBoostStatus?) -> ViewController
|
func makeChannelStatsController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peerId: EnginePeer.Id, boosts: Bool, boostStatus: ChannelBoostStatus?) -> ViewController
|
||||||
|
@ -62,6 +62,7 @@ public final class ChatMessageItemAssociatedData: Equatable {
|
|||||||
public let deviceContactsNumbers: Set<String>
|
public let deviceContactsNumbers: Set<String>
|
||||||
public let isStandalone: Bool
|
public let isStandalone: Bool
|
||||||
public let isInline: Bool
|
public let isInline: Bool
|
||||||
|
public let showSensitiveContent: Bool
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
automaticDownloadPeerType: MediaAutoDownloadPeerType,
|
automaticDownloadPeerType: MediaAutoDownloadPeerType,
|
||||||
@ -94,7 +95,8 @@ public final class ChatMessageItemAssociatedData: Equatable {
|
|||||||
chatThemes: [TelegramTheme] = [],
|
chatThemes: [TelegramTheme] = [],
|
||||||
deviceContactsNumbers: Set<String> = Set(),
|
deviceContactsNumbers: Set<String> = Set(),
|
||||||
isStandalone: Bool = false,
|
isStandalone: Bool = false,
|
||||||
isInline: Bool = false
|
isInline: Bool = false,
|
||||||
|
showSensitiveContent: Bool = false
|
||||||
) {
|
) {
|
||||||
self.automaticDownloadPeerType = automaticDownloadPeerType
|
self.automaticDownloadPeerType = automaticDownloadPeerType
|
||||||
self.automaticDownloadPeerId = automaticDownloadPeerId
|
self.automaticDownloadPeerId = automaticDownloadPeerId
|
||||||
@ -127,6 +129,7 @@ public final class ChatMessageItemAssociatedData: Equatable {
|
|||||||
self.deviceContactsNumbers = deviceContactsNumbers
|
self.deviceContactsNumbers = deviceContactsNumbers
|
||||||
self.isStandalone = isStandalone
|
self.isStandalone = isStandalone
|
||||||
self.isInline = isInline
|
self.isInline = isInline
|
||||||
|
self.showSensitiveContent = showSensitiveContent
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func == (lhs: ChatMessageItemAssociatedData, rhs: ChatMessageItemAssociatedData) -> Bool {
|
public static func == (lhs: ChatMessageItemAssociatedData, rhs: ChatMessageItemAssociatedData) -> Bool {
|
||||||
@ -217,6 +220,9 @@ public final class ChatMessageItemAssociatedData: Equatable {
|
|||||||
if lhs.isInline != rhs.isInline {
|
if lhs.isInline != rhs.isInline {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.showSensitiveContent != rhs.showSensitiveContent {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,6 +105,7 @@ public class MediaDustNode: ASDisplayNode {
|
|||||||
private var staticNode: ASImageNode?
|
private var staticNode: ASImageNode?
|
||||||
private var staticParams: CGSize?
|
private var staticParams: CGSize?
|
||||||
|
|
||||||
|
public var revealOnTap = true
|
||||||
public var isRevealed = false
|
public var isRevealed = false
|
||||||
private var isExploding = false
|
private var isExploding = false
|
||||||
|
|
||||||
@ -218,6 +219,10 @@ public class MediaDustNode: ASDisplayNode {
|
|||||||
|
|
||||||
self.tapped()
|
self.tapped()
|
||||||
|
|
||||||
|
guard self.revealOnTap else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
self.isRevealed = true
|
self.isRevealed = true
|
||||||
|
|
||||||
if self.enableAnimations {
|
if self.enableAnimations {
|
||||||
|
@ -489,20 +489,19 @@ private func inviteLinkEditControllerEntries(invite: ExportedInvitation?, state:
|
|||||||
let isEditingEnabled = invite?.pricing == nil
|
let isEditingEnabled = invite?.pricing == nil
|
||||||
let isSubscription = state.subscriptionEnabled
|
let isSubscription = state.subscriptionEnabled
|
||||||
if !isGroup {
|
if !isGroup {
|
||||||
//TODO:localize
|
entries.append(.subscriptionFeeToggle(presentationData.theme, presentationData.strings.InviteLink_Create_Fee, state.subscriptionEnabled, isEditingEnabled))
|
||||||
entries.append(.subscriptionFeeToggle(presentationData.theme, "Require Monthly Fee", state.subscriptionEnabled, isEditingEnabled))
|
|
||||||
if state.subscriptionEnabled {
|
if state.subscriptionEnabled {
|
||||||
var label: String = ""
|
var label: String = ""
|
||||||
if let subscriptionFee = state.subscriptionFee, subscriptionFee > 0, let starsState {
|
if let subscriptionFee = state.subscriptionFee, subscriptionFee > 0, let starsState {
|
||||||
label = "≈\(formatTonUsdValue(subscriptionFee, divide: false, rate: starsState.usdRate, dateTimeFormat: presentationData.dateTimeFormat)) / month"
|
label = presentationData.strings.InviteLink_Create_FeePerMonth("≈\(formatTonUsdValue(subscriptionFee, divide: false, rate: starsState.usdRate, dateTimeFormat: presentationData.dateTimeFormat))").string
|
||||||
}
|
}
|
||||||
entries.append(.subscriptionFee(presentationData.theme, "Stars amount per month", isEditingEnabled, state.subscriptionFee, label, configuration.maxFee))
|
entries.append(.subscriptionFee(presentationData.theme, presentationData.strings.InviteLink_Create_FeePlaceholder, isEditingEnabled, state.subscriptionFee, label, configuration.maxFee))
|
||||||
}
|
}
|
||||||
let infoText: String
|
let infoText: String
|
||||||
if let _ = invite, state.subscriptionEnabled {
|
if let _ = invite, state.subscriptionEnabled {
|
||||||
infoText = "If you need to change the subscription fee, create a new invite link with a different price."
|
infoText = presentationData.strings.InviteLink_Create_FeeEditInfo
|
||||||
} else {
|
} else {
|
||||||
infoText = "Charge a subscription fee from people joining your channel via this link. [Learn More >]()"
|
infoText = presentationData.strings.InviteLink_Create_FeeInfo
|
||||||
}
|
}
|
||||||
entries.append(.subscriptionFeeInfo(presentationData.theme, infoText))
|
entries.append(.subscriptionFeeInfo(presentationData.theme, infoText))
|
||||||
}
|
}
|
||||||
@ -511,7 +510,7 @@ private func inviteLinkEditControllerEntries(invite: ExportedInvitation?, state:
|
|||||||
entries.append(.requestApproval(presentationData.theme, presentationData.strings.InviteLink_Create_RequestApproval, state.requestApproval, isEditingEnabled && !isSubscription))
|
entries.append(.requestApproval(presentationData.theme, presentationData.strings.InviteLink_Create_RequestApproval, state.requestApproval, isEditingEnabled && !isSubscription))
|
||||||
var requestApprovalInfoText = presentationData.strings.InviteLink_Create_RequestApprovalOffInfoChannel
|
var requestApprovalInfoText = presentationData.strings.InviteLink_Create_RequestApprovalOffInfoChannel
|
||||||
if isSubscription {
|
if isSubscription {
|
||||||
requestApprovalInfoText = "You can't enable admin approval for links that require a monthly fee."
|
requestApprovalInfoText = presentationData.strings.InviteLink_Create_RequestApprovalFeeUnavailable
|
||||||
} else {
|
} else {
|
||||||
if state.requestApproval {
|
if state.requestApproval {
|
||||||
requestApprovalInfoText = isGroup ? presentationData.strings.InviteLink_Create_RequestApprovalOnInfoGroup : presentationData.strings.InviteLink_Create_RequestApprovalOnInfoChannel
|
requestApprovalInfoText = isGroup ? presentationData.strings.InviteLink_Create_RequestApprovalOnInfoGroup : presentationData.strings.InviteLink_Create_RequestApprovalOnInfoChannel
|
||||||
|
@ -310,10 +310,9 @@ private enum InviteLinkViewEntry: Comparable, Identifiable {
|
|||||||
|
|
||||||
let label: ItemListPeerItemLabel
|
let label: ItemListPeerItemLabel
|
||||||
if let pricing {
|
if let pricing {
|
||||||
//TODO:localize
|
|
||||||
let text = NSMutableAttributedString()
|
let text = NSMutableAttributedString()
|
||||||
text.append(NSAttributedString(string: "⭐️\(pricing.amount)\n", font: Font.semibold(17.0), textColor: presentationData.theme.list.itemPrimaryTextColor))
|
text.append(NSAttributedString(string: "⭐️\(pricing.amount)\n", font: Font.semibold(17.0), textColor: presentationData.theme.list.itemPrimaryTextColor))
|
||||||
text.append(NSAttributedString(string: "per month", font: Font.regular(13.0), textColor: presentationData.theme.list.itemSecondaryTextColor))
|
text.append(NSAttributedString(string: presentationData.strings.InviteLink_PerMonth, font: Font.regular(13.0), textColor: presentationData.theme.list.itemSecondaryTextColor))
|
||||||
if let range = text.string.range(of: "⭐️") {
|
if let range = text.string.range(of: "⭐️") {
|
||||||
text.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .stars(tinted: false)), range: NSRange(range, in: text.string))
|
text.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .stars(tinted: false)), range: NSRange(range, in: text.string))
|
||||||
text.addAttribute(NSAttributedString.Key.font, value: Font.semibold(15.0), range: NSRange(range, in: text.string))
|
text.addAttribute(NSAttributedString.Key.font, value: Font.semibold(15.0), range: NSRange(range, in: text.string))
|
||||||
@ -841,15 +840,14 @@ public final class InviteLinkViewController: ViewController {
|
|||||||
entries.append(.link(presentationData.theme, invite))
|
entries.append(.link(presentationData.theme, invite))
|
||||||
|
|
||||||
if let pricing = invite.pricing {
|
if let pricing = invite.pricing {
|
||||||
//TODO:localize
|
entries.append(.subscriptionHeader(presentationData.theme, presentationData.strings.InviteLink_SubscriptionFee_Title.uppercased()))
|
||||||
entries.append(.subscriptionHeader(presentationData.theme, "SUBSCRIPTION FEE"))
|
var title = presentationData.strings.InviteLink_SubscriptionFee_PerMonth("\(pricing.amount)").string
|
||||||
var title = "⭐️\(pricing.amount) / month"
|
var subtitle = presentationData.strings.InviteLink_SubscriptionFee_NoOneJoined
|
||||||
var subtitle = "No one joined yet"
|
|
||||||
if state.count > 0 {
|
if state.count > 0 {
|
||||||
title += " x \(state.count)"
|
title += " x \(state.count)"
|
||||||
if let usdRate {
|
if let usdRate {
|
||||||
let usdValue = formatTonUsdValue(pricing.amount * Int64(state.count), divide: false, rate: usdRate, dateTimeFormat: presentationData.dateTimeFormat)
|
let usdValue = formatTonUsdValue(pricing.amount * Int64(state.count), divide: false, rate: usdRate, dateTimeFormat: presentationData.dateTimeFormat)
|
||||||
subtitle = "You get approximately \(usdValue) monthly"
|
subtitle = presentationData.strings.InviteLink_SubscriptionFee_ApproximateIncome(usdValue).string
|
||||||
} else {
|
} else {
|
||||||
subtitle = ""
|
subtitle = ""
|
||||||
}
|
}
|
||||||
|
@ -404,10 +404,9 @@ public class ItemListInviteLinkItemNode: ListViewItemNode, ItemListItemNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let subscriptionPricing {
|
if let subscriptionPricing {
|
||||||
//TODO:localize
|
|
||||||
let text = NSMutableAttributedString()
|
let text = NSMutableAttributedString()
|
||||||
text.append(NSAttributedString(string: "⭐️\(subscriptionPricing.amount)\n", font: Font.semibold(17.0), textColor: item.presentationData.theme.list.itemPrimaryTextColor))
|
text.append(NSAttributedString(string: "⭐️\(subscriptionPricing.amount)\n", font: Font.semibold(17.0), textColor: item.presentationData.theme.list.itemPrimaryTextColor))
|
||||||
text.append(NSAttributedString(string: "per month", font: Font.regular(13.0), textColor: item.presentationData.theme.list.itemSecondaryTextColor))
|
text.append(NSAttributedString(string: item.presentationData.strings.InviteLink_PerMonth, font: Font.regular(13.0), textColor: item.presentationData.theme.list.itemSecondaryTextColor))
|
||||||
if let range = text.string.range(of: "⭐️") {
|
if let range = text.string.range(of: "⭐️") {
|
||||||
text.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .stars(tinted: false)), range: NSRange(range, in: text.string))
|
text.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .stars(tinted: false)), range: NSRange(range, in: text.string))
|
||||||
text.addAttribute(NSAttributedString.Key.font, value: Font.semibold(15.0), range: NSRange(range, in: text.string))
|
text.addAttribute(NSAttributedString.Key.font, value: Font.semibold(15.0), range: NSRange(range, in: text.string))
|
||||||
|
@ -20,6 +20,9 @@ public extension Message {
|
|||||||
public extension RestrictedContentMessageAttribute {
|
public extension RestrictedContentMessageAttribute {
|
||||||
func platformText(platform: String, contentSettings: ContentSettings) -> String? {
|
func platformText(platform: String, contentSettings: ContentSettings) -> String? {
|
||||||
for rule in self.rules {
|
for rule in self.rules {
|
||||||
|
if rule.isSensitive {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if rule.platform == "all" || rule.platform == "ios" || contentSettings.addContentRestrictionReasons.contains(rule.platform) {
|
if rule.platform == "all" || rule.platform == "ios" || contentSettings.addContentRestrictionReasons.contains(rule.platform) {
|
||||||
if !contentSettings.ignoreContentRestrictionReasons.contains(rule.reason) {
|
if !contentSettings.ignoreContentRestrictionReasons.contains(rule.reason) {
|
||||||
return rule.text
|
return rule.text
|
||||||
|
@ -232,6 +232,12 @@ public func combineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13
|
|||||||
}, initialValues: [:], queue: queue)
|
}, initialValues: [:], queue: queue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func combineLatest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, E>(queue: Queue? = nil, _ s1: Signal<T1, E>, _ s2: Signal<T2, E>, _ s3: Signal<T3, E>, _ s4: Signal<T4, E>, _ s5: Signal<T5, E>, _ s6: Signal<T6, E>, _ s7: Signal<T7, E>, _ s8: Signal<T8, E>, _ s9: Signal<T9, E>, _ s10: Signal<T10, E>, _ s11: Signal<T11, E>, _ s12: Signal<T12, E>, _ s13: Signal<T13, E>, _ s14: Signal<T14, E>, _ s15: Signal<T15, E>, _ s16: Signal<T16, E>, _ s17: Signal<T17, E>, _ s18: Signal<T18, E>, _ s19: Signal<T19, E>, _ s20: Signal<T20, E>, _ s21: Signal<T21, E>, _ s22: Signal<T22, E>, _ s23: Signal<T23, E>, _ s24: Signal<T24, E>, _ s25: Signal<T25, E>) -> Signal<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25), E> {
|
||||||
|
return combineLatestAny([signalOfAny(s1), signalOfAny(s2), signalOfAny(s3), signalOfAny(s4), signalOfAny(s5), signalOfAny(s6), signalOfAny(s7), signalOfAny(s8), signalOfAny(s9), signalOfAny(s10), signalOfAny(s11), signalOfAny(s12), signalOfAny(s13), signalOfAny(s14), signalOfAny(s15), signalOfAny(s16), signalOfAny(s17), signalOfAny(s18), signalOfAny(s19), signalOfAny(s20), signalOfAny(s21), signalOfAny(s22), signalOfAny(s23), signalOfAny(s24), signalOfAny(s25)], combine: { values in
|
||||||
|
return (values[0] as! T1, values[1] as! T2, values[2] as! T3, values[3] as! T4, values[4] as! T5, values[5] as! T6, values[6] as! T7, values[7] as! T8, values[8] as! T9, values[9] as! T10, values[10] as! T11, values[11] as! T12, values[12] as! T13, values[13] as! T14, values[14] as! T15, values[15] as! T16, values[16] as! T17, values[17] as! T18, values[18] as! T19, values[19] as! T20, values[20] as! T21, values[21] as! T22, values[22] as! T23, values[23] as! T24, values[24] as! T25)
|
||||||
|
}, initialValues: [:], queue: queue)
|
||||||
|
}
|
||||||
|
|
||||||
public func combineLatest<T, E>(queue: Queue? = nil, _ signals: [Signal<T, E>]) -> Signal<[T], E> {
|
public func combineLatest<T, E>(queue: Queue? = nil, _ signals: [Signal<T, E>]) -> Signal<[T], E> {
|
||||||
if signals.count == 0 {
|
if signals.count == 0 {
|
||||||
return single([T](), E.self)
|
return single([T](), E.self)
|
||||||
|
@ -34,9 +34,26 @@ private final class DataAndStorageControllerArguments {
|
|||||||
let toggleDownloadInBackground: (Bool) -> Void
|
let toggleDownloadInBackground: (Bool) -> Void
|
||||||
let openBrowserSelection: () -> Void
|
let openBrowserSelection: () -> Void
|
||||||
let openIntents: () -> Void
|
let openIntents: () -> Void
|
||||||
let toggleEnableSensitiveContent: (Bool) -> Void
|
let toggleSensitiveContent: (Bool) -> Void
|
||||||
|
let toggleOtherSensitiveContent: (Bool) -> Void
|
||||||
|
|
||||||
init(openStorageUsage: @escaping () -> Void, openNetworkUsage: @escaping () -> Void, openProxy: @escaping () -> Void, openAutomaticDownloadConnectionType: @escaping (AutomaticDownloadConnectionType) -> Void, resetAutomaticDownload: @escaping () -> Void, toggleVoiceUseLessData: @escaping (Bool) -> Void, openSaveIncoming: @escaping (AutomaticSaveIncomingPeerType) -> Void, toggleSaveEditedPhotos: @escaping (Bool) -> Void, togglePauseMusicOnRecording: @escaping (Bool) -> Void, toggleRaiseToListen: @escaping (Bool) -> Void, toggleDownloadInBackground: @escaping (Bool) -> Void, openBrowserSelection: @escaping () -> Void, openIntents: @escaping () -> Void, toggleEnableSensitiveContent: @escaping (Bool) -> Void) {
|
init(
|
||||||
|
openStorageUsage: @escaping () -> Void,
|
||||||
|
openNetworkUsage: @escaping () -> Void,
|
||||||
|
openProxy: @escaping () -> Void,
|
||||||
|
openAutomaticDownloadConnectionType: @escaping (AutomaticDownloadConnectionType) -> Void,
|
||||||
|
resetAutomaticDownload: @escaping () -> Void,
|
||||||
|
toggleVoiceUseLessData: @escaping (Bool) -> Void,
|
||||||
|
openSaveIncoming: @escaping (AutomaticSaveIncomingPeerType) -> Void,
|
||||||
|
toggleSaveEditedPhotos: @escaping (Bool) -> Void,
|
||||||
|
togglePauseMusicOnRecording: @escaping (Bool) -> Void,
|
||||||
|
toggleRaiseToListen: @escaping (Bool) -> Void,
|
||||||
|
toggleDownloadInBackground: @escaping (Bool) -> Void,
|
||||||
|
openBrowserSelection: @escaping () -> Void,
|
||||||
|
openIntents: @escaping () -> Void,
|
||||||
|
toggleSensitiveContent: @escaping (Bool) -> Void,
|
||||||
|
toggleOtherSensitiveContent: @escaping (Bool) -> Void
|
||||||
|
) {
|
||||||
self.openStorageUsage = openStorageUsage
|
self.openStorageUsage = openStorageUsage
|
||||||
self.openNetworkUsage = openNetworkUsage
|
self.openNetworkUsage = openNetworkUsage
|
||||||
self.openProxy = openProxy
|
self.openProxy = openProxy
|
||||||
@ -50,7 +67,8 @@ private final class DataAndStorageControllerArguments {
|
|||||||
self.toggleDownloadInBackground = toggleDownloadInBackground
|
self.toggleDownloadInBackground = toggleDownloadInBackground
|
||||||
self.openBrowserSelection = openBrowserSelection
|
self.openBrowserSelection = openBrowserSelection
|
||||||
self.openIntents = openIntents
|
self.openIntents = openIntents
|
||||||
self.toggleEnableSensitiveContent = toggleEnableSensitiveContent
|
self.toggleSensitiveContent = toggleSensitiveContent
|
||||||
|
self.toggleOtherSensitiveContent = toggleOtherSensitiveContent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +80,8 @@ private enum DataAndStorageSection: Int32 {
|
|||||||
case voiceCalls
|
case voiceCalls
|
||||||
case other
|
case other
|
||||||
case connection
|
case connection
|
||||||
case enableSensitiveContent
|
case sensitiveContent
|
||||||
|
case otherSensitiveContent
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DataAndStorageEntryTag: ItemListItemTag, Equatable {
|
public enum DataAndStorageEntryTag: ItemListItemTag, Equatable {
|
||||||
@ -72,6 +91,7 @@ public enum DataAndStorageEntryTag: ItemListItemTag, Equatable {
|
|||||||
case pauseMusicOnRecording
|
case pauseMusicOnRecording
|
||||||
case raiseToListen
|
case raiseToListen
|
||||||
case autoSave(AutomaticSaveIncomingPeerType)
|
case autoSave(AutomaticSaveIncomingPeerType)
|
||||||
|
case sensitiveContent
|
||||||
|
|
||||||
public func isEqual(to other: ItemListItemTag) -> Bool {
|
public func isEqual(to other: ItemListItemTag) -> Bool {
|
||||||
if let other = other as? DataAndStorageEntryTag, self == other {
|
if let other = other as? DataAndStorageEntryTag, self == other {
|
||||||
@ -107,9 +127,12 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
|
|||||||
case raiseToListen(PresentationTheme, String, Bool)
|
case raiseToListen(PresentationTheme, String, Bool)
|
||||||
case raiseToListenInfo(PresentationTheme, String)
|
case raiseToListenInfo(PresentationTheme, String)
|
||||||
|
|
||||||
|
case sensitiveContent(String, Bool)
|
||||||
|
case sensitiveContentInfo(String)
|
||||||
|
|
||||||
case connectionHeader(PresentationTheme, String)
|
case connectionHeader(PresentationTheme, String)
|
||||||
case connectionProxy(PresentationTheme, String, String)
|
case connectionProxy(PresentationTheme, String, String)
|
||||||
case enableSensitiveContent(String, Bool)
|
case otherSensitiveContent(String, Bool)
|
||||||
|
|
||||||
var section: ItemListSectionId {
|
var section: ItemListSectionId {
|
||||||
switch self {
|
switch self {
|
||||||
@ -125,10 +148,12 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
|
|||||||
return DataAndStorageSection.voiceCalls.rawValue
|
return DataAndStorageSection.voiceCalls.rawValue
|
||||||
case .otherHeader, .openLinksIn, .shareSheet, .saveEditedPhotos, .pauseMusicOnRecording, .raiseToListen, .raiseToListenInfo:
|
case .otherHeader, .openLinksIn, .shareSheet, .saveEditedPhotos, .pauseMusicOnRecording, .raiseToListen, .raiseToListenInfo:
|
||||||
return DataAndStorageSection.other.rawValue
|
return DataAndStorageSection.other.rawValue
|
||||||
|
case .sensitiveContent, .sensitiveContentInfo:
|
||||||
|
return DataAndStorageSection.sensitiveContent.rawValue
|
||||||
case .connectionHeader, .connectionProxy:
|
case .connectionHeader, .connectionProxy:
|
||||||
return DataAndStorageSection.connection.rawValue
|
return DataAndStorageSection.connection.rawValue
|
||||||
case .enableSensitiveContent:
|
case .otherSensitiveContent:
|
||||||
return DataAndStorageSection.enableSensitiveContent.rawValue
|
return DataAndStorageSection.otherSensitiveContent.rawValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,12 +199,16 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
|
|||||||
return 34
|
return 34
|
||||||
case .raiseToListenInfo:
|
case .raiseToListenInfo:
|
||||||
return 35
|
return 35
|
||||||
case .connectionHeader:
|
case .sensitiveContent:
|
||||||
return 36
|
return 36
|
||||||
case .connectionProxy:
|
case .sensitiveContentInfo:
|
||||||
return 37
|
return 37
|
||||||
case .enableSensitiveContent:
|
case .connectionHeader:
|
||||||
return 38
|
return 38
|
||||||
|
case .connectionProxy:
|
||||||
|
return 39
|
||||||
|
case .otherSensitiveContent:
|
||||||
|
return 40
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,6 +322,18 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
case let .sensitiveContent(text, value):
|
||||||
|
if case .sensitiveContent(text, value) = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case let .sensitiveContentInfo(text):
|
||||||
|
if case .sensitiveContentInfo(text) = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
case let .downloadInBackground(lhsTheme, lhsText, lhsValue):
|
case let .downloadInBackground(lhsTheme, lhsText, lhsValue):
|
||||||
if case let .downloadInBackground(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
|
if case let .downloadInBackground(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
|
||||||
return true
|
return true
|
||||||
@ -317,8 +358,8 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case let .enableSensitiveContent(text, value):
|
case let .otherSensitiveContent(text, value):
|
||||||
if case .enableSensitiveContent(text, value) = rhs {
|
if case .otherSensitiveContent(text, value) = rhs {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
@ -408,6 +449,12 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
|
|||||||
}, tag: DataAndStorageEntryTag.raiseToListen)
|
}, tag: DataAndStorageEntryTag.raiseToListen)
|
||||||
case let .raiseToListenInfo(_, text):
|
case let .raiseToListenInfo(_, text):
|
||||||
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section)
|
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section)
|
||||||
|
case let .sensitiveContent(text, value):
|
||||||
|
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||||
|
arguments.toggleSensitiveContent(value)
|
||||||
|
}, tag: DataAndStorageEntryTag.sensitiveContent)
|
||||||
|
case let .sensitiveContentInfo(text):
|
||||||
|
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section)
|
||||||
case let .downloadInBackground(_, text, value):
|
case let .downloadInBackground(_, text, value):
|
||||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||||
arguments.toggleDownloadInBackground(value)
|
arguments.toggleDownloadInBackground(value)
|
||||||
@ -420,9 +467,9 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
|
|||||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
||||||
arguments.openProxy()
|
arguments.openProxy()
|
||||||
})
|
})
|
||||||
case let .enableSensitiveContent(text, value):
|
case let .otherSensitiveContent(text, value):
|
||||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||||
arguments.toggleEnableSensitiveContent(value)
|
arguments.toggleOtherSensitiveContent(value)
|
||||||
}, tag: nil)
|
}, tag: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -588,7 +635,7 @@ private func autosaveLabelAndValue(presentationData: PresentationData, settings:
|
|||||||
return (label, value)
|
return (label, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func dataAndStorageControllerEntries(state: DataAndStorageControllerState, data: DataAndStorageData, presentationData: PresentationData, defaultWebBrowser: String, contentSettingsConfiguration: ContentSettingsConfiguration?, networkUsage: Int64, storageUsage: Int64, mediaAutoSaveSettings: MediaAutoSaveSettings, autosaveExceptionPeers: [EnginePeer.Id: EnginePeer?]) -> [DataAndStorageEntry] {
|
private func dataAndStorageControllerEntries(state: DataAndStorageControllerState, data: DataAndStorageData, presentationData: PresentationData, defaultWebBrowser: String, contentSettingsConfiguration: ContentSettingsConfiguration?, networkUsage: Int64, storageUsage: Int64, mediaAutoSaveSettings: MediaAutoSaveSettings, autosaveExceptionPeers: [EnginePeer.Id: EnginePeer?], mediaSettings: MediaDisplaySettings) -> [DataAndStorageEntry] {
|
||||||
var entries: [DataAndStorageEntry] = []
|
var entries: [DataAndStorageEntry] = []
|
||||||
|
|
||||||
entries.append(.storageUsage(presentationData.theme, presentationData.strings.ChatSettings_Cache, dataSizeString(storageUsage, formatting: DataSizeStringFormatting(presentationData: presentationData))))
|
entries.append(.storageUsage(presentationData.theme, presentationData.strings.ChatSettings_Cache, dataSizeString(storageUsage, formatting: DataSizeStringFormatting(presentationData: presentationData))))
|
||||||
@ -627,6 +674,9 @@ private func dataAndStorageControllerEntries(state: DataAndStorageControllerStat
|
|||||||
entries.append(.raiseToListen(presentationData.theme, presentationData.strings.Settings_RaiseToListen, data.mediaInputSettings.enableRaiseToSpeak))
|
entries.append(.raiseToListen(presentationData.theme, presentationData.strings.Settings_RaiseToListen, data.mediaInputSettings.enableRaiseToSpeak))
|
||||||
entries.append(.raiseToListenInfo(presentationData.theme, presentationData.strings.Settings_RaiseToListenInfo))
|
entries.append(.raiseToListenInfo(presentationData.theme, presentationData.strings.Settings_RaiseToListenInfo))
|
||||||
|
|
||||||
|
entries.append(.sensitiveContent(presentationData.strings.Settings_SensitiveContent, mediaSettings.showSensitiveContent))
|
||||||
|
entries.append(.sensitiveContentInfo(presentationData.strings.Settings_SensitiveContentInfo))
|
||||||
|
|
||||||
let proxyValue: String
|
let proxyValue: String
|
||||||
if let proxySettings = data.proxySettings, let activeServer = proxySettings.activeServer, proxySettings.enabled {
|
if let proxySettings = data.proxySettings, let activeServer = proxySettings.activeServer, proxySettings.enabled {
|
||||||
switch activeServer.connection {
|
switch activeServer.connection {
|
||||||
@ -643,7 +693,7 @@ private func dataAndStorageControllerEntries(state: DataAndStorageControllerStat
|
|||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if let contentSettingsConfiguration = contentSettingsConfiguration, contentSettingsConfiguration.canAdjustSensitiveContent {
|
if let contentSettingsConfiguration = contentSettingsConfiguration, contentSettingsConfiguration.canAdjustSensitiveContent {
|
||||||
entries.append(.enableSensitiveContent("Display Sensitive Content", contentSettingsConfiguration.sensitiveContentEnabled))
|
entries.append(.otherSensitiveContent("Display Sensitive Content", contentSettingsConfiguration.sensitiveContentEnabled))
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -872,7 +922,11 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
|
|||||||
}, openIntents: {
|
}, openIntents: {
|
||||||
let controller = intentsSettingsController(context: context)
|
let controller = intentsSettingsController(context: context)
|
||||||
pushControllerImpl?(controller)
|
pushControllerImpl?(controller)
|
||||||
}, toggleEnableSensitiveContent: { value in
|
}, toggleSensitiveContent: { value in
|
||||||
|
let _ = updateMediaDisplaySettingsInteractively(accountManager: context.sharedContext.accountManager, {
|
||||||
|
$0.withUpdatedShowSensitiveContent(value)
|
||||||
|
}).startStandalone()
|
||||||
|
}, toggleOtherSensitiveContent: { value in
|
||||||
let _ = (contentSettingsConfiguration.get()
|
let _ = (contentSettingsConfiguration.get()
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> deliverOnMainQueue).start(next: { [weak contentSettingsConfiguration] settings in
|
|> deliverOnMainQueue).start(next: { [weak contentSettingsConfiguration] settings in
|
||||||
@ -905,7 +959,7 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
|
|||||||
context.sharedContext.presentationData,
|
context.sharedContext.presentationData,
|
||||||
statePromise.get(),
|
statePromise.get(),
|
||||||
dataAndStorageDataPromise.get(),
|
dataAndStorageDataPromise.get(),
|
||||||
context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.webBrowserSettings]),
|
context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.webBrowserSettings, ApplicationSpecificSharedDataKeys.mediaDisplaySettings]),
|
||||||
contentSettingsConfiguration.get(),
|
contentSettingsConfiguration.get(),
|
||||||
preferences,
|
preferences,
|
||||||
usageSignal,
|
usageSignal,
|
||||||
@ -913,6 +967,8 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
|
|||||||
)
|
)
|
||||||
|> map { presentationData, state, dataAndStorageData, sharedData, contentSettingsConfiguration, mediaAutoSaveSettings, usageSignal, autosaveExceptionPeers -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
|> map { presentationData, state, dataAndStorageData, sharedData, contentSettingsConfiguration, mediaAutoSaveSettings, usageSignal, autosaveExceptionPeers -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||||
let webBrowserSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.webBrowserSettings]?.get(WebBrowserSettings.self) ?? WebBrowserSettings.defaultSettings
|
let webBrowserSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.webBrowserSettings]?.get(WebBrowserSettings.self) ?? WebBrowserSettings.defaultSettings
|
||||||
|
let mediaSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.mediaDisplaySettings]?.get(MediaDisplaySettings.self) ?? MediaDisplaySettings.defaultSettings
|
||||||
|
|
||||||
let options = availableOpenInOptions(context: context, item: .url(url: "https://telegram.org"))
|
let options = availableOpenInOptions(context: context, item: .url(url: "https://telegram.org"))
|
||||||
let defaultWebBrowser: String
|
let defaultWebBrowser: String
|
||||||
if let option = options.first(where: { $0.identifier == webBrowserSettings.defaultWebBrowser }) {
|
if let option = options.first(where: { $0.identifier == webBrowserSettings.defaultWebBrowser }) {
|
||||||
@ -924,7 +980,7 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
|
|||||||
}
|
}
|
||||||
|
|
||||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.ChatSettings_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.ChatSettings_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: dataAndStorageControllerEntries(state: state, data: dataAndStorageData, presentationData: presentationData, defaultWebBrowser: defaultWebBrowser, contentSettingsConfiguration: contentSettingsConfiguration, networkUsage: usageSignal.network, storageUsage: usageSignal.storage, mediaAutoSaveSettings: mediaAutoSaveSettings, autosaveExceptionPeers: autosaveExceptionPeers), style: .blocks, ensureVisibleItemTag: focusOnItemTag, emptyStateItem: nil, animateChanges: false)
|
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: dataAndStorageControllerEntries(state: state, data: dataAndStorageData, presentationData: presentationData, defaultWebBrowser: defaultWebBrowser, contentSettingsConfiguration: contentSettingsConfiguration, networkUsage: usageSignal.network, storageUsage: usageSignal.storage, mediaAutoSaveSettings: mediaAutoSaveSettings, autosaveExceptionPeers: autosaveExceptionPeers, mediaSettings: mediaSettings), style: .blocks, ensureVisibleItemTag: focusOnItemTag, emptyStateItem: nil, animateChanges: false)
|
||||||
|
|
||||||
return (controllerState, (listState, arguments))
|
return (controllerState, (listState, arguments))
|
||||||
} |> afterDisposed {
|
} |> afterDisposed {
|
||||||
|
@ -275,7 +275,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1038136962] = { return Api.EncryptedFile.parse_encryptedFileEmpty($0) }
|
dict[-1038136962] = { return Api.EncryptedFile.parse_encryptedFileEmpty($0) }
|
||||||
dict[-317144808] = { return Api.EncryptedMessage.parse_encryptedMessage($0) }
|
dict[-317144808] = { return Api.EncryptedMessage.parse_encryptedMessage($0) }
|
||||||
dict[594758406] = { return Api.EncryptedMessage.parse_encryptedMessageService($0) }
|
dict[594758406] = { return Api.EncryptedMessage.parse_encryptedMessageService($0) }
|
||||||
dict[-1812799720] = { return Api.ExportedChatInvite.parse_chatInviteExported($0) }
|
dict[-1574126186] = { return Api.ExportedChatInvite.parse_chatInviteExported($0) }
|
||||||
dict[-317687113] = { return Api.ExportedChatInvite.parse_chatInvitePublicJoinRequests($0) }
|
dict[-317687113] = { return Api.ExportedChatInvite.parse_chatInvitePublicJoinRequests($0) }
|
||||||
dict[206668204] = { return Api.ExportedChatlistInvite.parse_exportedChatlistInvite($0) }
|
dict[206668204] = { return Api.ExportedChatlistInvite.parse_exportedChatlistInvite($0) }
|
||||||
dict[1103040667] = { return Api.ExportedContactToken.parse_exportedContactToken($0) }
|
dict[1103040667] = { return Api.ExportedContactToken.parse_exportedContactToken($0) }
|
||||||
@ -803,6 +803,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1929860175] = { return Api.RequestedPeer.parse_requestedPeerChat($0) }
|
dict[1929860175] = { return Api.RequestedPeer.parse_requestedPeerChat($0) }
|
||||||
dict[-701500310] = { return Api.RequestedPeer.parse_requestedPeerUser($0) }
|
dict[-701500310] = { return Api.RequestedPeer.parse_requestedPeerUser($0) }
|
||||||
dict[-797791052] = { return Api.RestrictionReason.parse_restrictionReason($0) }
|
dict[-797791052] = { return Api.RestrictionReason.parse_restrictionReason($0) }
|
||||||
|
dict[2007669447] = { return Api.RestrictionReason.parse_restrictionReasonSensitive($0) }
|
||||||
dict[894777186] = { return Api.RichText.parse_textAnchor($0) }
|
dict[894777186] = { return Api.RichText.parse_textAnchor($0) }
|
||||||
dict[1730456516] = { return Api.RichText.parse_textBold($0) }
|
dict[1730456516] = { return Api.RichText.parse_textBold($0) }
|
||||||
dict[2120376535] = { return Api.RichText.parse_textConcat($0) }
|
dict[2120376535] = { return Api.RichText.parse_textConcat($0) }
|
||||||
|
@ -397,6 +397,7 @@ public extension Api {
|
|||||||
public extension Api {
|
public extension Api {
|
||||||
enum RestrictionReason: TypeConstructorDescription {
|
enum RestrictionReason: TypeConstructorDescription {
|
||||||
case restrictionReason(platform: String, reason: String, text: String)
|
case restrictionReason(platform: String, reason: String, text: String)
|
||||||
|
case restrictionReasonSensitive(platform: String)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
@ -408,6 +409,12 @@ public extension Api {
|
|||||||
serializeString(reason, buffer: buffer, boxed: false)
|
serializeString(reason, buffer: buffer, boxed: false)
|
||||||
serializeString(text, buffer: buffer, boxed: false)
|
serializeString(text, buffer: buffer, boxed: false)
|
||||||
break
|
break
|
||||||
|
case .restrictionReasonSensitive(let platform):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(2007669447)
|
||||||
|
}
|
||||||
|
serializeString(platform, buffer: buffer, boxed: false)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,6 +422,8 @@ public extension Api {
|
|||||||
switch self {
|
switch self {
|
||||||
case .restrictionReason(let platform, let reason, let text):
|
case .restrictionReason(let platform, let reason, let text):
|
||||||
return ("restrictionReason", [("platform", platform as Any), ("reason", reason as Any), ("text", text as Any)])
|
return ("restrictionReason", [("platform", platform as Any), ("reason", reason as Any), ("text", text as Any)])
|
||||||
|
case .restrictionReasonSensitive(let platform):
|
||||||
|
return ("restrictionReasonSensitive", [("platform", platform as Any)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,6 +444,17 @@ public extension Api {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static func parse_restrictionReasonSensitive(_ reader: BufferReader) -> RestrictionReason? {
|
||||||
|
var _1: String?
|
||||||
|
_1 = parseString(reader)
|
||||||
|
let _c1 = _1 != nil
|
||||||
|
if _c1 {
|
||||||
|
return Api.RestrictionReason.restrictionReasonSensitive(platform: _1!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7935,14 +7935,15 @@ public extension Api.functions.messages {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public extension Api.functions.messages {
|
public extension Api.functions.messages {
|
||||||
static func sendPaidReaction(peer: Api.InputPeer, msgId: Int32, count: Int32, randomId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
static func sendPaidReaction(flags: Int32, peer: Api.InputPeer, msgId: Int32, count: Int32, randomId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(508941107)
|
buffer.appendInt32(633929278)
|
||||||
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
peer.serialize(buffer, true)
|
peer.serialize(buffer, true)
|
||||||
serializeInt32(msgId, buffer: buffer, boxed: false)
|
serializeInt32(msgId, buffer: buffer, boxed: false)
|
||||||
serializeInt32(count, buffer: buffer, boxed: false)
|
serializeInt32(count, buffer: buffer, boxed: false)
|
||||||
serializeInt64(randomId, buffer: buffer, boxed: false)
|
serializeInt64(randomId, buffer: buffer, boxed: false)
|
||||||
return (FunctionDescription(name: "messages.sendPaidReaction", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("count", String(describing: count)), ("randomId", String(describing: randomId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
return (FunctionDescription(name: "messages.sendPaidReaction", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("count", String(describing: count)), ("randomId", String(describing: randomId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||||
let reader = BufferReader(buffer)
|
let reader = BufferReader(buffer)
|
||||||
var result: Api.Updates?
|
var result: Api.Updates?
|
||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
|
@ -1012,14 +1012,14 @@ public extension Api {
|
|||||||
}
|
}
|
||||||
public extension Api {
|
public extension Api {
|
||||||
enum ExportedChatInvite: TypeConstructorDescription {
|
enum ExportedChatInvite: TypeConstructorDescription {
|
||||||
case chatInviteExported(flags: Int32, link: String, adminId: Int64, date: Int32, startDate: Int32?, expireDate: Int32?, usageLimit: Int32?, usage: Int32?, requested: Int32?, title: String?, subscriptionPricing: Api.StarsSubscriptionPricing?)
|
case chatInviteExported(flags: Int32, link: String, adminId: Int64, date: Int32, startDate: Int32?, expireDate: Int32?, usageLimit: Int32?, usage: Int32?, requested: Int32?, subscriptionExpired: Int32?, title: String?, subscriptionPricing: Api.StarsSubscriptionPricing?)
|
||||||
case chatInvitePublicJoinRequests
|
case chatInvitePublicJoinRequests
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage, let requested, let title, let subscriptionPricing):
|
case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage, let requested, let subscriptionExpired, let title, let subscriptionPricing):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(-1812799720)
|
buffer.appendInt32(-1574126186)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
serializeString(link, buffer: buffer, boxed: false)
|
serializeString(link, buffer: buffer, boxed: false)
|
||||||
@ -1030,6 +1030,7 @@ public extension Api {
|
|||||||
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(usageLimit!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(usageLimit!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(usage!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(usage!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 7) != 0 {serializeInt32(requested!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 7) != 0 {serializeInt32(requested!, buffer: buffer, boxed: false)}
|
||||||
|
if Int(flags) & Int(1 << 10) != 0 {serializeInt32(subscriptionExpired!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 8) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 8) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 9) != 0 {subscriptionPricing!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 9) != 0 {subscriptionPricing!.serialize(buffer, true)}
|
||||||
break
|
break
|
||||||
@ -1044,8 +1045,8 @@ public extension Api {
|
|||||||
|
|
||||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||||
switch self {
|
switch self {
|
||||||
case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage, let requested, let title, let subscriptionPricing):
|
case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage, let requested, let subscriptionExpired, let title, let subscriptionPricing):
|
||||||
return ("chatInviteExported", [("flags", flags as Any), ("link", link as Any), ("adminId", adminId as Any), ("date", date as Any), ("startDate", startDate as Any), ("expireDate", expireDate as Any), ("usageLimit", usageLimit as Any), ("usage", usage as Any), ("requested", requested as Any), ("title", title as Any), ("subscriptionPricing", subscriptionPricing as Any)])
|
return ("chatInviteExported", [("flags", flags as Any), ("link", link as Any), ("adminId", adminId as Any), ("date", date as Any), ("startDate", startDate as Any), ("expireDate", expireDate as Any), ("usageLimit", usageLimit as Any), ("usage", usage as Any), ("requested", requested as Any), ("subscriptionExpired", subscriptionExpired as Any), ("title", title as Any), ("subscriptionPricing", subscriptionPricing as Any)])
|
||||||
case .chatInvitePublicJoinRequests:
|
case .chatInvitePublicJoinRequests:
|
||||||
return ("chatInvitePublicJoinRequests", [])
|
return ("chatInvitePublicJoinRequests", [])
|
||||||
}
|
}
|
||||||
@ -1070,11 +1071,13 @@ public extension Api {
|
|||||||
if Int(_1!) & Int(1 << 3) != 0 {_8 = reader.readInt32() }
|
if Int(_1!) & Int(1 << 3) != 0 {_8 = reader.readInt32() }
|
||||||
var _9: Int32?
|
var _9: Int32?
|
||||||
if Int(_1!) & Int(1 << 7) != 0 {_9 = reader.readInt32() }
|
if Int(_1!) & Int(1 << 7) != 0 {_9 = reader.readInt32() }
|
||||||
var _10: String?
|
var _10: Int32?
|
||||||
if Int(_1!) & Int(1 << 8) != 0 {_10 = parseString(reader) }
|
if Int(_1!) & Int(1 << 10) != 0 {_10 = reader.readInt32() }
|
||||||
var _11: Api.StarsSubscriptionPricing?
|
var _11: String?
|
||||||
|
if Int(_1!) & Int(1 << 8) != 0 {_11 = parseString(reader) }
|
||||||
|
var _12: Api.StarsSubscriptionPricing?
|
||||||
if Int(_1!) & Int(1 << 9) != 0 {if let signature = reader.readInt32() {
|
if Int(_1!) & Int(1 << 9) != 0 {if let signature = reader.readInt32() {
|
||||||
_11 = Api.parse(reader, signature: signature) as? Api.StarsSubscriptionPricing
|
_12 = Api.parse(reader, signature: signature) as? Api.StarsSubscriptionPricing
|
||||||
} }
|
} }
|
||||||
let _c1 = _1 != nil
|
let _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
@ -1085,10 +1088,11 @@ public extension Api {
|
|||||||
let _c7 = (Int(_1!) & Int(1 << 2) == 0) || _7 != nil
|
let _c7 = (Int(_1!) & Int(1 << 2) == 0) || _7 != nil
|
||||||
let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil
|
let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil
|
||||||
let _c9 = (Int(_1!) & Int(1 << 7) == 0) || _9 != nil
|
let _c9 = (Int(_1!) & Int(1 << 7) == 0) || _9 != nil
|
||||||
let _c10 = (Int(_1!) & Int(1 << 8) == 0) || _10 != nil
|
let _c10 = (Int(_1!) & Int(1 << 10) == 0) || _10 != nil
|
||||||
let _c11 = (Int(_1!) & Int(1 << 9) == 0) || _11 != nil
|
let _c11 = (Int(_1!) & Int(1 << 8) == 0) || _11 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 {
|
let _c12 = (Int(_1!) & Int(1 << 9) == 0) || _12 != nil
|
||||||
return Api.ExportedChatInvite.chatInviteExported(flags: _1!, link: _2!, adminId: _3!, date: _4!, startDate: _5, expireDate: _6, usageLimit: _7, usage: _8, requested: _9, title: _10, subscriptionPricing: _11)
|
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 {
|
||||||
|
return Api.ExportedChatInvite.chatInviteExported(flags: _1!, link: _2!, adminId: _3!, date: _4!, startDate: _5, expireDate: _6, usageLimit: _7, usage: _8, requested: _9, subscriptionExpired: _10, title: _11, subscriptionPricing: _12)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
@ -6,7 +6,8 @@ import TelegramApi
|
|||||||
extension ExportedInvitation {
|
extension ExportedInvitation {
|
||||||
init(apiExportedInvite: Api.ExportedChatInvite) {
|
init(apiExportedInvite: Api.ExportedChatInvite) {
|
||||||
switch apiExportedInvite {
|
switch apiExportedInvite {
|
||||||
case let .chatInviteExported(flags, link, adminId, date, startDate, expireDate, usageLimit, usage, requested, title, pricing):
|
case let .chatInviteExported(flags, link, adminId, date, startDate, expireDate, usageLimit, usage, requested, subscriptionExpired, title, pricing):
|
||||||
|
let _ = subscriptionExpired
|
||||||
self = .link(link: link, title: title, isPermanent: (flags & (1 << 5)) != 0, requestApproval: (flags & (1 << 6)) != 0, isRevoked: (flags & (1 << 0)) != 0, adminId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(adminId)), date: date, startDate: startDate, expireDate: expireDate, usageLimit: usageLimit, count: usage, requestedCount: requested, pricing: pricing.flatMap { StarsSubscriptionPricing(apiStarsSubscriptionPricing: $0) })
|
self = .link(link: link, title: title, isPermanent: (flags & (1 << 5)) != 0, requestApproval: (flags & (1 << 6)) != 0, isRevoked: (flags & (1 << 0)) != 0, adminId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(adminId)), date: date, startDate: startDate, expireDate: expireDate, usageLimit: usageLimit, count: usage, requestedCount: requested, pricing: pricing.flatMap { StarsSubscriptionPricing(apiStarsSubscriptionPricing: $0) })
|
||||||
case .chatInvitePublicJoinRequests:
|
case .chatInvitePublicJoinRequests:
|
||||||
self = .publicJoinRequest
|
self = .publicJoinRequest
|
||||||
|
@ -8,6 +8,8 @@ extension RestrictionRule {
|
|||||||
switch apiReason {
|
switch apiReason {
|
||||||
case let .restrictionReason(platform, reason, text):
|
case let .restrictionReason(platform, reason, text):
|
||||||
self.init(platform: platform, reason: reason, text: text)
|
self.init(platform: platform, reason: reason, text: text)
|
||||||
|
case let .restrictionReasonSensitive(platform):
|
||||||
|
self.init(platform: platform)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -341,7 +341,7 @@ private func requestSendStarsReaction(postbox: Postbox, network: Network, stateM
|
|||||||
let timestampPart = UInt64(UInt32(bitPattern: Int32(Date().timeIntervalSince1970)))
|
let timestampPart = UInt64(UInt32(bitPattern: Int32(Date().timeIntervalSince1970)))
|
||||||
let randomId = (timestampPart << 32) | randomPartId
|
let randomId = (timestampPart << 32) | randomPartId
|
||||||
|
|
||||||
let signal: Signal<Never, RequestUpdateMessageReactionError> = network.request(Api.functions.messages.sendPaidReaction(peer: inputPeer, msgId: messageId.id, count: count, randomId: Int64(bitPattern: randomId)))
|
let signal: Signal<Never, RequestUpdateMessageReactionError> = network.request(Api.functions.messages.sendPaidReaction(flags: 0, peer: inputPeer, msgId: messageId.id, count: count, randomId: Int64(bitPattern: randomId)))
|
||||||
|> mapError { _ -> RequestUpdateMessageReactionError in
|
|> mapError { _ -> RequestUpdateMessageReactionError in
|
||||||
return .generic
|
return .generic
|
||||||
}
|
}
|
||||||
|
@ -4,23 +4,34 @@ public final class RestrictionRule: PostboxCoding, Equatable {
|
|||||||
public let platform: String
|
public let platform: String
|
||||||
public let reason: String
|
public let reason: String
|
||||||
public let text: String
|
public let text: String
|
||||||
|
public let isSensitive: Bool
|
||||||
|
|
||||||
public init(platform: String, reason: String, text: String) {
|
public init(platform: String, reason: String, text: String) {
|
||||||
self.platform = platform
|
self.platform = platform
|
||||||
self.reason = reason
|
self.reason = reason
|
||||||
self.text = text
|
self.text = text
|
||||||
|
self.isSensitive = false
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(platform: String) {
|
||||||
|
self.platform = platform
|
||||||
|
self.reason = ""
|
||||||
|
self.text = ""
|
||||||
|
self.isSensitive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(decoder: PostboxDecoder) {
|
public init(decoder: PostboxDecoder) {
|
||||||
self.platform = decoder.decodeStringForKey("p", orElse: "all")
|
self.platform = decoder.decodeStringForKey("p", orElse: "all")
|
||||||
self.reason = decoder.decodeStringForKey("r", orElse: "")
|
self.reason = decoder.decodeStringForKey("r", orElse: "")
|
||||||
self.text = decoder.decodeStringForKey("t", orElse: "")
|
self.text = decoder.decodeStringForKey("t", orElse: "")
|
||||||
|
self.isSensitive = decoder.decodeBoolForKey("s", orElse: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(_ encoder: PostboxEncoder) {
|
public func encode(_ encoder: PostboxEncoder) {
|
||||||
encoder.encodeString(self.platform, forKey: "p")
|
encoder.encodeString(self.platform, forKey: "p")
|
||||||
encoder.encodeString(self.reason, forKey: "r")
|
encoder.encodeString(self.reason, forKey: "r")
|
||||||
encoder.encodeString(self.text, forKey: "t")
|
encoder.encodeString(self.text, forKey: "t")
|
||||||
|
encoder.encodeBool(self.isSensitive, forKey: "s")
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs: RestrictionRule, rhs: RestrictionRule) -> Bool {
|
public static func ==(lhs: RestrictionRule, rhs: RestrictionRule) -> Bool {
|
||||||
@ -33,6 +44,9 @@ public final class RestrictionRule: PostboxCoding, Equatable {
|
|||||||
if lhs.text != rhs.text {
|
if lhs.text != rhs.text {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.isSensitive != rhs.isSensitive {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -381,7 +381,15 @@ public extension Message {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isAgeRestricted() -> Bool {
|
func isSensitiveContent(platform: String) -> Bool {
|
||||||
|
if let rule = self.restrictedContentAttribute?.rules.first(where: { $0.isSensitive }) {
|
||||||
|
if rule.platform == "all" || rule.platform == platform {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let peer = self.peers[self.id.peerId], peer.hasSensitiveContent(platform: platform) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,9 @@ public extension Peer {
|
|||||||
|
|
||||||
if let restrictionInfo = restrictionInfo {
|
if let restrictionInfo = restrictionInfo {
|
||||||
for rule in restrictionInfo.rules {
|
for rule in restrictionInfo.rules {
|
||||||
|
if rule.isSensitive {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if rule.platform == "all" || rule.platform == platform || contentSettings.addContentRestrictionReasons.contains(rule.platform) {
|
if rule.platform == "all" || rule.platform == platform || contentSettings.addContentRestrictionReasons.contains(rule.platform) {
|
||||||
if !contentSettings.ignoreContentRestrictionReasons.contains(rule.reason) {
|
if !contentSettings.ignoreContentRestrictionReasons.contains(rule.reason) {
|
||||||
return rule.text
|
return rule.text
|
||||||
@ -220,6 +223,25 @@ public extension Peer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hasSensitiveContent(platform: String) -> Bool {
|
||||||
|
var restrictionInfo: PeerAccessRestrictionInfo?
|
||||||
|
switch self {
|
||||||
|
case let user as TelegramUser:
|
||||||
|
restrictionInfo = user.restrictionInfo
|
||||||
|
case let channel as TelegramChannel:
|
||||||
|
restrictionInfo = channel.restrictionInfo
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if let restrictionInfo, let rule = restrictionInfo.rules.first(where: { $0.isSensitive }) {
|
||||||
|
if rule.platform == "all" || rule.platform == platform {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
var isForum: Bool {
|
var isForum: Bool {
|
||||||
if let channel = self as? TelegramChannel {
|
if let channel = self as? TelegramChannel {
|
||||||
return channel.flags.contains(.isForum)
|
return channel.flags.contains(.isForum)
|
||||||
|
@ -751,11 +751,10 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
|||||||
if message.author?.id == accountPeerId {
|
if message.author?.id == accountPeerId {
|
||||||
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_SentYou(price)._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes])
|
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_SentYou(price)._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes])
|
||||||
} else {
|
} else {
|
||||||
//TODO:localize
|
|
||||||
var authorName = compactAuthorName
|
var authorName = compactAuthorName
|
||||||
var peerIds: [(Int, EnginePeer.Id?)] = [(0, message.author?.id)]
|
var peerIds: [(Int, EnginePeer.Id?)] = [(0, message.author?.id)]
|
||||||
if message.id.peerId.namespace == Namespaces.Peer.CloudUser && message.id.peerId.id._internalGetInt64Value() == 777000 {
|
if message.id.peerId.namespace == Namespaces.Peer.CloudUser && message.id.peerId.id._internalGetInt64Value() == 777000 {
|
||||||
authorName = "Unknown user"
|
authorName = strings.Notification_StarsGift_UnknownUser
|
||||||
peerIds = []
|
peerIds = []
|
||||||
}
|
}
|
||||||
var attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
|
var attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
|
||||||
@ -1010,13 +1009,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case let .paymentRefunded(peerId, currency, totalAmount, _, _):
|
case let .paymentRefunded(peerId, currency, totalAmount, _, _):
|
||||||
//TODO:localize
|
let patternString = strings.Notification_Refund
|
||||||
let patternString: String
|
|
||||||
if peerId == message.id.peerId {
|
|
||||||
patternString = "You received a refund of {amount}"
|
|
||||||
} else {
|
|
||||||
patternString = "You received a refund of {amount} from {name}"
|
|
||||||
}
|
|
||||||
|
|
||||||
let mutableString = NSMutableAttributedString()
|
let mutableString = NSMutableAttributedString()
|
||||||
mutableString.append(NSAttributedString(string: patternString, font: titleFont, textColor: primaryTextColor))
|
mutableString.append(NSAttributedString(string: patternString, font: titleFont, textColor: primaryTextColor))
|
||||||
|
@ -217,7 +217,7 @@ private class ExtendedMediaOverlayNode: ASDisplayNode {
|
|||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
|
|
||||||
private let blurredImageNode: TransformImageNode
|
private let blurredImageNode: TransformImageNode
|
||||||
private let dustNode: MediaDustNode
|
fileprivate let dustNode: MediaDustNode
|
||||||
fileprivate let buttonNode: HighlightTrackingButtonNode
|
fileprivate let buttonNode: HighlightTrackingButtonNode
|
||||||
private let highlightedBackgroundNode: ASDisplayNode
|
private let highlightedBackgroundNode: ASDisplayNode
|
||||||
private let iconNode: ASImageNode
|
private let iconNode: ASImageNode
|
||||||
@ -452,6 +452,7 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||||||
private var automaticDownload: InteractiveMediaNodeAutodownloadMode?
|
private var automaticDownload: InteractiveMediaNodeAutodownloadMode?
|
||||||
public var automaticPlayback: Bool?
|
public var automaticPlayback: Bool?
|
||||||
private var preferredStoryHighQuality: Bool = false
|
private var preferredStoryHighQuality: Bool = false
|
||||||
|
private var showSensitiveContent: Bool = false
|
||||||
|
|
||||||
private let statusDisposable = MetaDisposable()
|
private let statusDisposable = MetaDisposable()
|
||||||
private let fetchControls = Atomic<FetchControls?>(value: nil)
|
private let fetchControls = Atomic<FetchControls?>(value: nil)
|
||||||
@ -1570,6 +1571,7 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||||||
strongSelf.automaticPlayback = automaticPlayback
|
strongSelf.automaticPlayback = automaticPlayback
|
||||||
strongSelf.automaticDownload = automaticDownload
|
strongSelf.automaticDownload = automaticDownload
|
||||||
strongSelf.preferredStoryHighQuality = associatedData.preferredStoryHighQuality
|
strongSelf.preferredStoryHighQuality = associatedData.preferredStoryHighQuality
|
||||||
|
strongSelf.showSensitiveContent = associatedData.showSensitiveContent
|
||||||
|
|
||||||
if let previousArguments = strongSelf.currentImageArguments {
|
if let previousArguments = strongSelf.currentImageArguments {
|
||||||
if previousArguments.imageSize == arguments.imageSize {
|
if previousArguments.imageSize == arguments.imageSize {
|
||||||
@ -2399,20 +2401,25 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||||||
displaySpoiler = true
|
displaySpoiler = true
|
||||||
} else if isSecretMedia {
|
} else if isSecretMedia {
|
||||||
displaySpoiler = true
|
displaySpoiler = true
|
||||||
} else if message.isAgeRestricted() {
|
} else if message.isSensitiveContent(platform: "ios") {
|
||||||
|
if !self.showSensitiveContent {
|
||||||
displaySpoiler = true
|
displaySpoiler = true
|
||||||
icon = .eye
|
icon = .eye
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if displaySpoiler {
|
if displaySpoiler, let context = self.context {
|
||||||
if self.extendedMediaOverlayNode == nil, let context = self.context {
|
let extendedMediaOverlayNode: ExtendedMediaOverlayNode
|
||||||
|
if let current = self.extendedMediaOverlayNode {
|
||||||
|
extendedMediaOverlayNode = current
|
||||||
|
} else {
|
||||||
let enableAnimations = context.sharedContext.energyUsageSettings.fullTranslucency && !isPreview
|
let enableAnimations = context.sharedContext.energyUsageSettings.fullTranslucency && !isPreview
|
||||||
let extendedMediaOverlayNode = ExtendedMediaOverlayNode(context: context, hasImageOverlay: !isSecretMedia, icon: icon, enableAnimations: enableAnimations)
|
extendedMediaOverlayNode = ExtendedMediaOverlayNode(context: context, hasImageOverlay: !isSecretMedia, icon: icon, enableAnimations: enableAnimations)
|
||||||
extendedMediaOverlayNode.tapped = { [weak self] in
|
extendedMediaOverlayNode.tapped = { [weak self] in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if message.isAgeRestricted() {
|
if message.isSensitiveContent(platform: "ios") {
|
||||||
self.activateAgeRestrictedMedia?()
|
self.activateAgeRestrictedMedia?()
|
||||||
} else {
|
} else {
|
||||||
self.internallyVisible = true
|
self.internallyVisible = true
|
||||||
@ -2423,7 +2430,7 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||||||
self.extendedMediaOverlayNode = extendedMediaOverlayNode
|
self.extendedMediaOverlayNode = extendedMediaOverlayNode
|
||||||
self.pinchContainerNode.contentNode.insertSubnode(extendedMediaOverlayNode, aboveSubnode: self.imageNode)
|
self.pinchContainerNode.contentNode.insertSubnode(extendedMediaOverlayNode, aboveSubnode: self.imageNode)
|
||||||
}
|
}
|
||||||
self.extendedMediaOverlayNode?.frame = self.imageNode.frame
|
extendedMediaOverlayNode.frame = self.imageNode.frame
|
||||||
|
|
||||||
var tappable = false
|
var tappable = false
|
||||||
if !isSecretMedia {
|
if !isSecretMedia {
|
||||||
@ -2434,13 +2441,12 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
extendedMediaOverlayNode.isUserInteractionEnabled = tappable
|
||||||
self.extendedMediaOverlayNode?.isUserInteractionEnabled = tappable
|
|
||||||
|
|
||||||
var viewText: String = ""
|
var viewText: String = ""
|
||||||
if message.isAgeRestricted() {
|
if case .eye = icon {
|
||||||
//TODO:localize
|
viewText = strings.Chat_SensitiveContent
|
||||||
viewText = "18+ Content"
|
extendedMediaOverlayNode.dustNode.revealOnTap = false
|
||||||
} else {
|
} else {
|
||||||
outer: for attribute in message.attributes {
|
outer: for attribute in message.attributes {
|
||||||
if let attribute = attribute as? ReplyMarkupMessageAttribute {
|
if let attribute = attribute as? ReplyMarkupMessageAttribute {
|
||||||
@ -2455,8 +2461,9 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
extendedMediaOverlayNode.dustNode.revealOnTap = true
|
||||||
}
|
}
|
||||||
self.extendedMediaOverlayNode?.update(size: self.imageNode.frame.size, text: viewText, imageSignal: self.currentBlurredImageSignal, imageFrame: self.imageNode.view.convert(self.imageNode.bounds, to: self.extendedMediaOverlayNode?.view), corners: self.currentImageArguments?.corners)
|
extendedMediaOverlayNode.update(size: self.imageNode.frame.size, text: viewText, imageSignal: self.currentBlurredImageSignal, imageFrame: self.imageNode.view.convert(self.imageNode.bounds, to: extendedMediaOverlayNode.view), corners: self.currentImageArguments?.corners)
|
||||||
} else if let extendedMediaOverlayNode = self.extendedMediaOverlayNode {
|
} else if let extendedMediaOverlayNode = self.extendedMediaOverlayNode {
|
||||||
self.extendedMediaOverlayNode = nil
|
self.extendedMediaOverlayNode = nil
|
||||||
extendedMediaOverlayNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak extendedMediaOverlayNode] _ in
|
extendedMediaOverlayNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak extendedMediaOverlayNode] _ in
|
||||||
@ -2664,12 +2671,12 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func ignoreTapActionAtPoint(_ point: CGPoint) -> Bool {
|
public func ignoreTapActionAtPoint(_ point: CGPoint) -> Bool {
|
||||||
// if let extendedMediaOverlayNode = self.extendedMediaOverlayNode {
|
if let extendedMediaOverlayNode = self.extendedMediaOverlayNode {
|
||||||
// let convertedPoint = self.view.convert(point, to: extendedMediaOverlayNode.view)
|
let convertedPoint = self.view.convert(point, to: extendedMediaOverlayNode.view)
|
||||||
// if extendedMediaOverlayNode.buttonNode.frame.contains(convertedPoint) {
|
if extendedMediaOverlayNode.buttonNode.frame.contains(convertedPoint) {
|
||||||
// return true
|
return true
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1135,7 +1135,7 @@ public class StarsTransactionScreen: ViewControllerComponentContainer {
|
|||||||
theme: forceDark ? .dark : .default
|
theme: forceDark ? .dark : .default
|
||||||
)
|
)
|
||||||
|
|
||||||
self.navigationPresentation = .flatModal
|
self.navigationPresentation = .standaloneModal
|
||||||
self.automaticallyControlPresentationContextLayout = false
|
self.automaticallyControlPresentationContextLayout = false
|
||||||
|
|
||||||
openPeerImpl = { [weak self] peer in
|
openPeerImpl = { [weak self] peer in
|
||||||
|
@ -626,7 +626,6 @@ final class StarsTransactionsScreenComponent: Component {
|
|||||||
maximumNumberOfLines: 1
|
maximumNumberOfLines: 1
|
||||||
)))
|
)))
|
||||||
)
|
)
|
||||||
//TODO:localize
|
|
||||||
let dateText: String
|
let dateText: String
|
||||||
let dateValue = stringForDateWithoutYear(date: Date(timeIntervalSince1970: Double(subscription.untilDate)), strings: environment.strings)
|
let dateValue = stringForDateWithoutYear(date: Date(timeIntervalSince1970: Double(subscription.untilDate)), strings: environment.strings)
|
||||||
if subscription.flags.contains(.isCancelled) {
|
if subscription.flags.contains(.isCancelled) {
|
||||||
|
@ -77,6 +77,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
|
|
||||||
private(set) var botPeer: EnginePeer?
|
private(set) var botPeer: EnginePeer?
|
||||||
private(set) var chatPeer: EnginePeer?
|
private(set) var chatPeer: EnginePeer?
|
||||||
|
private(set) var authorPeer: EnginePeer?
|
||||||
private var peerDisposable: Disposable?
|
private var peerDisposable: Disposable?
|
||||||
private(set) var balance: Int64?
|
private(set) var balance: Int64?
|
||||||
private(set) var form: BotPaymentForm?
|
private(set) var form: BotPaymentForm?
|
||||||
@ -799,7 +800,7 @@ public final class StarsTransferScreen: ViewControllerComponentContainer {
|
|||||||
theme: .default
|
theme: .default
|
||||||
)
|
)
|
||||||
|
|
||||||
self.navigationPresentation = .flatModal
|
self.navigationPresentation = .standaloneModal
|
||||||
|
|
||||||
starsContext.load(force: false)
|
starsContext.load(force: false)
|
||||||
}
|
}
|
||||||
|
@ -524,7 +524,7 @@ public final class StarsWithdrawScreen: ViewControllerComponentContainer {
|
|||||||
theme: .default
|
theme: .default
|
||||||
)
|
)
|
||||||
|
|
||||||
self.navigationPresentation = .flatModal
|
self.navigationPresentation = .standaloneModal
|
||||||
}
|
}
|
||||||
|
|
||||||
required public init(coder aDecoder: NSCoder) {
|
required public init(coder aDecoder: NSCoder) {
|
||||||
|
@ -294,7 +294,9 @@ func openWebAppImpl(context: AccountContext, parentController: ViewController, u
|
|||||||
let controller = webAppLaunchConfirmationController(context: context, updatedPresentationData: updatedPresentationData, peer: botPeer, completion: { _ in
|
let controller = webAppLaunchConfirmationController(context: context, updatedPresentationData: updatedPresentationData, peer: botPeer, completion: { _ in
|
||||||
let _ = ApplicationSpecificNotice.setBotGameNotice(accountManager: context.sharedContext.accountManager, peerId: botPeer.id).startStandalone()
|
let _ = ApplicationSpecificNotice.setBotGameNotice(accountManager: context.sharedContext.accountManager, peerId: botPeer.id).startStandalone()
|
||||||
openWebView()
|
openWebView()
|
||||||
}, showMore: nil)
|
}, showMore: nil, openTerms: {
|
||||||
|
|
||||||
|
})
|
||||||
parentController.present(controller, in: .window(.root))
|
parentController.present(controller, in: .window(.root))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -312,7 +314,7 @@ public extension ChatControllerImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static func botRequestSwitchInline(context: AccountContext, controller: ChatControllerImpl?, peerId: EnginePeer.Id, botAddress: String, query: String, chatTypes: [ReplyMarkupButtonRequestPeerType]?, completion: @escaping () -> Void) -> Void {
|
static func botRequestSwitchInline(context: AccountContext, controller: ChatControllerImpl?, peerId: EnginePeer.Id, botAddress: String, query: String, chatTypes: [ReplyMarkupButtonRequestPeerType]?, completion: @escaping () -> Void) -> Void {
|
||||||
let activateSwitchInline = {
|
let activateSwitchInline: (EnginePeer?) -> Void = { selectedPeer in
|
||||||
var chatController: ChatControllerImpl?
|
var chatController: ChatControllerImpl?
|
||||||
if let current = controller {
|
if let current = controller {
|
||||||
chatController = current
|
chatController = current
|
||||||
@ -325,7 +327,7 @@ public extension ChatControllerImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let chatController {
|
if let chatController {
|
||||||
chatController.controllerInteraction?.activateSwitchInline(peerId, "@\(botAddress) \(query)", nil)
|
chatController.controllerInteraction?.activateSwitchInline(selectedPeer?.id ?? peerId, "@\(botAddress) \(query)", nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,7 +336,7 @@ public extension ChatControllerImpl {
|
|||||||
peerController.peerSelected = { [weak peerController] peer, _ in
|
peerController.peerSelected = { [weak peerController] peer, _ in
|
||||||
completion()
|
completion()
|
||||||
peerController?.dismiss()
|
peerController?.dismiss()
|
||||||
activateSwitchInline()
|
activateSwitchInline(peer)
|
||||||
}
|
}
|
||||||
if let controller {
|
if let controller {
|
||||||
controller.push(peerController)
|
controller.push(peerController)
|
||||||
@ -342,7 +344,7 @@ public extension ChatControllerImpl {
|
|||||||
((context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface)?.viewControllers.last as? ViewController)?.push(peerController)
|
((context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface)?.viewControllers.last as? ViewController)?.push(peerController)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
activateSwitchInline()
|
activateSwitchInline(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,6 +549,10 @@ public extension ChatControllerImpl {
|
|||||||
if let self {
|
if let self {
|
||||||
self.openResolved(result: .peer(botPeer._asPeer(), .info(nil)), sourceMessageId: nil)
|
self.openResolved(result: .peer(botPeer._asPeer(), .info(nil)), sourceMessageId: nil)
|
||||||
}
|
}
|
||||||
|
}, openTerms: { [weak self] in
|
||||||
|
if let self {
|
||||||
|
self.context.sharedContext.openExternalUrl(context: self.context, urlContext: .generic, url: self.presentationData.strings.WebApp_LaunchTermsConfirmation_URL, forceExternal: false, presentationData: self.presentationData, navigationController: self.effectiveNavigationController, dismissInput: {})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
self.present(controller, in: .window(.root))
|
self.present(controller, in: .window(.root))
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ private final class ChatAgeRestrictionAlertContentNode: AlertContentNode {
|
|||||||
self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.semibold(17.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.semibold(17.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||||
self.textNode.attributedText = NSAttributedString(string: self.text, font: Font.regular(13.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
self.textNode.attributedText = NSAttributedString(string: self.text, font: Font.regular(13.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||||
|
|
||||||
self.alwaysLabelNode.attributedText = formattedText("Always show 18+ media", color: theme.primaryColor)
|
self.alwaysLabelNode.attributedText = formattedText(self.strings.SensitiveContent_ShowAlways, color: theme.primaryColor)
|
||||||
|
|
||||||
self.actionNodesSeparator.backgroundColor = theme.separatorColor
|
self.actionNodesSeparator.backgroundColor = theme.separatorColor
|
||||||
for actionNode in self.actionNodes {
|
for actionNode in self.actionNodes {
|
||||||
@ -269,10 +269,9 @@ public func chatAgeRestrictionAlertController(context: AccountContext, updatedPr
|
|||||||
}
|
}
|
||||||
let strings = presentationData.strings
|
let strings = presentationData.strings
|
||||||
|
|
||||||
//TODO:localize
|
|
||||||
var dismissImpl: ((Bool) -> Void)?
|
var dismissImpl: ((Bool) -> Void)?
|
||||||
var getContentNodeImpl: (() -> ChatAgeRestrictionAlertContentNode?)?
|
var getContentNodeImpl: (() -> ChatAgeRestrictionAlertContentNode?)?
|
||||||
let actions: [TextAlertAction] = [TextAlertAction(type: .defaultAction, title: "View Anyway", action: {
|
let actions: [TextAlertAction] = [TextAlertAction(type: .defaultAction, title: strings.SensitiveContent_ViewAnyway, action: {
|
||||||
if let alwaysShow = getContentNodeImpl?()?.alwaysShow {
|
if let alwaysShow = getContentNodeImpl?()?.alwaysShow {
|
||||||
completion(alwaysShow)
|
completion(alwaysShow)
|
||||||
} else {
|
} else {
|
||||||
@ -283,8 +282,8 @@ public func chatAgeRestrictionAlertController(context: AccountContext, updatedPr
|
|||||||
dismissImpl?(true)
|
dismissImpl?(true)
|
||||||
})]
|
})]
|
||||||
|
|
||||||
let title = "18+ Content"
|
let title = strings.SensitiveContent_Title
|
||||||
let text = "This media may contain sensitive content suitable only for adults.\nDo you still want to view it?"
|
let text = strings.SensitiveContent_Text
|
||||||
|
|
||||||
let contentNode = ChatAgeRestrictionAlertContentNode(context: context, theme: AlertControllerTheme(presentationData: presentationData), ptheme: theme, strings: strings, title: title, text: text, actions: actions)
|
let contentNode = ChatAgeRestrictionAlertContentNode(context: context, theme: AlertControllerTheme(presentationData: presentationData), ptheme: theme, strings: strings, title: title, text: text, actions: actions)
|
||||||
getContentNodeImpl = { [weak contentNode] in
|
getContentNodeImpl = { [weak contentNode] in
|
||||||
|
@ -4423,7 +4423,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if alwaysShow {
|
if alwaysShow {
|
||||||
self.present(UndoOverlayController(presentationData: self.presentationData, content: .info(title: nil, text: "You can update the visibility of sensitive media in [Data and Storage > Show 18+ Content]().", timeout: nil, customUndoText: nil), elevatedLayout: false, position: .top, action: { _ in return false }), in: .current)
|
let _ = updateMediaDisplaySettingsInteractively(accountManager: context.sharedContext.accountManager, {
|
||||||
|
$0.withUpdatedShowSensitiveContent(true)
|
||||||
|
}).startStandalone()
|
||||||
|
|
||||||
|
self.present(UndoOverlayController(presentationData: self.presentationData, content: .info(title: nil, text: self.presentationData.strings.SensitiveContent_SettingsInfo, timeout: nil, customUndoText: nil), elevatedLayout: false, position: .top, action: { [weak self] action in
|
||||||
|
if case .info = action, let self {
|
||||||
|
let controller = self.context.sharedContext.makeDataAndStorageController(context: self.context, sensitiveContent: true)
|
||||||
|
self.push(controller)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}), in: .current)
|
||||||
}
|
}
|
||||||
reveal()
|
reveal()
|
||||||
})
|
})
|
||||||
|
@ -350,7 +350,8 @@ private func extractAssociatedData(
|
|||||||
audioTranscriptionTrial: AudioTranscription.TrialState,
|
audioTranscriptionTrial: AudioTranscription.TrialState,
|
||||||
chatThemes: [TelegramTheme],
|
chatThemes: [TelegramTheme],
|
||||||
deviceContactsNumbers: Set<String>,
|
deviceContactsNumbers: Set<String>,
|
||||||
isInline: Bool
|
isInline: Bool,
|
||||||
|
showSensitiveContent: Bool
|
||||||
) -> ChatMessageItemAssociatedData {
|
) -> ChatMessageItemAssociatedData {
|
||||||
var automaticDownloadPeerId: EnginePeer.Id?
|
var automaticDownloadPeerId: EnginePeer.Id?
|
||||||
var automaticMediaDownloadPeerType: MediaAutoDownloadPeerType = .channel
|
var automaticMediaDownloadPeerType: MediaAutoDownloadPeerType = .channel
|
||||||
@ -405,7 +406,7 @@ private func extractAssociatedData(
|
|||||||
automaticDownloadPeerId = message.peerId
|
automaticDownloadPeerId = message.peerId
|
||||||
}
|
}
|
||||||
|
|
||||||
return ChatMessageItemAssociatedData(automaticDownloadPeerType: automaticMediaDownloadPeerType, automaticDownloadPeerId: automaticDownloadPeerId, automaticDownloadNetworkType: automaticDownloadNetworkType, preferredStoryHighQuality: preferredStoryHighQuality, isRecentActions: false, subject: subject, contactsPeerIds: contactsPeerIds, channelDiscussionGroup: channelDiscussionGroup, animatedEmojiStickers: animatedEmojiStickers, additionalAnimatedEmojiStickers: additionalAnimatedEmojiStickers, currentlyPlayingMessageId: currentlyPlayingMessageId, isCopyProtectionEnabled: isCopyProtectionEnabled, availableReactions: availableReactions, availableMessageEffects: availableMessageEffects, savedMessageTags: savedMessageTags, defaultReaction: defaultReaction, isPremium: isPremium, accountPeer: accountPeer, alwaysDisplayTranscribeButton: alwaysDisplayTranscribeButton, topicAuthorId: topicAuthorId, hasBots: hasBots, translateToLanguage: translateToLanguage, maxReadStoryId: maxReadStoryId, recommendedChannels: recommendedChannels, audioTranscriptionTrial: audioTranscriptionTrial, chatThemes: chatThemes, deviceContactsNumbers: deviceContactsNumbers, isInline: isInline)
|
return ChatMessageItemAssociatedData(automaticDownloadPeerType: automaticMediaDownloadPeerType, automaticDownloadPeerId: automaticDownloadPeerId, automaticDownloadNetworkType: automaticDownloadNetworkType, preferredStoryHighQuality: preferredStoryHighQuality, isRecentActions: false, subject: subject, contactsPeerIds: contactsPeerIds, channelDiscussionGroup: channelDiscussionGroup, animatedEmojiStickers: animatedEmojiStickers, additionalAnimatedEmojiStickers: additionalAnimatedEmojiStickers, currentlyPlayingMessageId: currentlyPlayingMessageId, isCopyProtectionEnabled: isCopyProtectionEnabled, availableReactions: availableReactions, availableMessageEffects: availableMessageEffects, savedMessageTags: savedMessageTags, defaultReaction: defaultReaction, isPremium: isPremium, accountPeer: accountPeer, alwaysDisplayTranscribeButton: alwaysDisplayTranscribeButton, topicAuthorId: topicAuthorId, hasBots: hasBots, translateToLanguage: translateToLanguage, maxReadStoryId: maxReadStoryId, recommendedChannels: recommendedChannels, audioTranscriptionTrial: audioTranscriptionTrial, chatThemes: chatThemes, deviceContactsNumbers: deviceContactsNumbers, isInline: isInline, showSensitiveContent: showSensitiveContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension ChatHistoryLocationInput {
|
private extension ChatHistoryLocationInput {
|
||||||
@ -1557,6 +1558,8 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||||||
self.allAdMessagesPromise.get()
|
self.allAdMessagesPromise.get()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
let sharedData = self.context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.mediaDisplaySettings])
|
||||||
|
|
||||||
let maxReadStoryId: Signal<Int32?, NoError>
|
let maxReadStoryId: Signal<Int32?, NoError>
|
||||||
if let peerId = self.chatLocation.peerId, peerId.namespace == Namespaces.Peer.CloudUser {
|
if let peerId = self.chatLocation.peerId, peerId.namespace == Namespaces.Peer.CloudUser {
|
||||||
maxReadStoryId = self.context.account.postbox.combinedView(keys: [PostboxViewKey.storiesState(key: .peer(peerId))])
|
maxReadStoryId = self.context.account.postbox.combinedView(keys: [PostboxViewKey.storiesState(key: .peer(peerId))])
|
||||||
@ -1632,9 +1635,11 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||||||
recommendedChannels,
|
recommendedChannels,
|
||||||
audioTranscriptionTrial,
|
audioTranscriptionTrial,
|
||||||
chatThemes,
|
chatThemes,
|
||||||
deviceContactsNumbers
|
deviceContactsNumbers,
|
||||||
).startStrict(next: { [weak self] update, chatPresentationData, selectedMessages, updatingMedia, networkType, preferredStoryHighQuality, animatedEmojiStickers, additionalAnimatedEmojiStickers, customChannelDiscussionReadState, customThreadOutgoingReadState, availableReactions, availableMessageEffects, savedMessageTags, defaultReaction, accountPeer, suggestAudioTranscription, promises, topicAuthorId, translationState, maxReadStoryId, recommendedChannels, audioTranscriptionTrial, chatThemes, deviceContactsNumbers in
|
sharedData
|
||||||
|
).startStrict(next: { [weak self] update, chatPresentationData, selectedMessages, updatingMedia, networkType, preferredStoryHighQuality, animatedEmojiStickers, additionalAnimatedEmojiStickers, customChannelDiscussionReadState, customThreadOutgoingReadState, availableReactions, availableMessageEffects, savedMessageTags, defaultReaction, accountPeer, suggestAudioTranscription, promises, topicAuthorId, translationState, maxReadStoryId, recommendedChannels, audioTranscriptionTrial, chatThemes, deviceContactsNumbers, sharedData in
|
||||||
let (historyAppearsCleared, pendingUnpinnedAllMessages, pendingRemovedMessages, currentlyPlayingMessageIdAndType, scrollToMessageId, chatHasBots, allAdMessages) = promises
|
let (historyAppearsCleared, pendingUnpinnedAllMessages, pendingRemovedMessages, currentlyPlayingMessageIdAndType, scrollToMessageId, chatHasBots, allAdMessages) = promises
|
||||||
|
let mediaSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.mediaDisplaySettings]?.get(MediaDisplaySettings.self) ?? MediaDisplaySettings.defaultSettings
|
||||||
|
|
||||||
func applyHole() {
|
func applyHole() {
|
||||||
Queue.mainQueue().async {
|
Queue.mainQueue().async {
|
||||||
@ -1852,7 +1857,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||||||
translateToLanguage = languageCode
|
translateToLanguage = languageCode
|
||||||
}
|
}
|
||||||
|
|
||||||
let associatedData = extractAssociatedData(chatLocation: chatLocation, view: view, automaticDownloadNetworkType: networkType, preferredStoryHighQuality: preferredStoryHighQuality, animatedEmojiStickers: animatedEmojiStickers, additionalAnimatedEmojiStickers: additionalAnimatedEmojiStickers, subject: subject, currentlyPlayingMessageId: currentlyPlayingMessageIdAndType?.0, isCopyProtectionEnabled: isCopyProtectionEnabled, availableReactions: availableReactions, availableMessageEffects: availableMessageEffects, savedMessageTags: savedMessageTags, defaultReaction: defaultReaction, isPremium: isPremium, alwaysDisplayTranscribeButton: alwaysDisplayTranscribeButton, accountPeer: accountPeer, topicAuthorId: topicAuthorId, hasBots: chatHasBots, translateToLanguage: translateToLanguage, maxReadStoryId: maxReadStoryId, recommendedChannels: recommendedChannels, audioTranscriptionTrial: audioTranscriptionTrial, chatThemes: chatThemes, deviceContactsNumbers: deviceContactsNumbers, isInline: !rotated)
|
let associatedData = extractAssociatedData(chatLocation: chatLocation, view: view, automaticDownloadNetworkType: networkType, preferredStoryHighQuality: preferredStoryHighQuality, animatedEmojiStickers: animatedEmojiStickers, additionalAnimatedEmojiStickers: additionalAnimatedEmojiStickers, subject: subject, currentlyPlayingMessageId: currentlyPlayingMessageIdAndType?.0, isCopyProtectionEnabled: isCopyProtectionEnabled, availableReactions: availableReactions, availableMessageEffects: availableMessageEffects, savedMessageTags: savedMessageTags, defaultReaction: defaultReaction, isPremium: isPremium, alwaysDisplayTranscribeButton: alwaysDisplayTranscribeButton, accountPeer: accountPeer, topicAuthorId: topicAuthorId, hasBots: chatHasBots, translateToLanguage: translateToLanguage, maxReadStoryId: maxReadStoryId, recommendedChannels: recommendedChannels, audioTranscriptionTrial: audioTranscriptionTrial, chatThemes: chatThemes, deviceContactsNumbers: deviceContactsNumbers, isInline: !rotated, showSensitiveContent: mediaSettings.showSensitiveContent)
|
||||||
|
|
||||||
var includeEmbeddedSavedChatInfo = false
|
var includeEmbeddedSavedChatInfo = false
|
||||||
if case let .replyThread(message) = chatLocation, message.peerId == context.account.peerId, !rotated {
|
if case let .replyThread(message) = chatLocation, message.peerId == context.account.peerId, !rotated {
|
||||||
|
@ -1739,26 +1739,6 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
|||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if message.id.peerId.isGroupOrChannel {
|
|
||||||
// //TODO:localize
|
|
||||||
// if message.isAgeRestricted() {
|
|
||||||
// actions.append(.action(ContextMenuActionItem(text: "Unmark as 18+", icon: { theme in
|
|
||||||
// return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/AgeUnmark"), color: theme.actionSheet.primaryTextColor)
|
|
||||||
// }, action: { c, _ in
|
|
||||||
// c?.dismiss(completion: {
|
|
||||||
// controllerInteraction.openMessageStats(messages[0].id)
|
|
||||||
// })
|
|
||||||
// })))
|
|
||||||
// } else {
|
|
||||||
// actions.append(.action(ContextMenuActionItem(text: "Mark as 18+", icon: { theme in
|
|
||||||
// return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/AgeMark"), color: theme.actionSheet.primaryTextColor)
|
|
||||||
// }, action: { c, _ in
|
|
||||||
// c?.dismiss(completion: {
|
|
||||||
// controllerInteraction.openMessageStats(messages[0].id)
|
|
||||||
// })
|
|
||||||
// })))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
if isReplyThreadHead {
|
if isReplyThreadHead {
|
||||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ViewInChannel, icon: { theme in
|
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ViewInChannel, icon: { theme in
|
||||||
|
@ -2715,6 +2715,10 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
return proxySettingsController(accountManager: sharedContext.accountManager, sharedContext: sharedContext, postbox: account.postbox, network: account.network, mode: .modal, presentationData: sharedContext.currentPresentationData.with { $0 }, updatedPresentationData: sharedContext.presentationData)
|
return proxySettingsController(accountManager: sharedContext.accountManager, sharedContext: sharedContext, postbox: account.postbox, network: account.network, mode: .modal, presentationData: sharedContext.currentPresentationData.with { $0 }, updatedPresentationData: sharedContext.presentationData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func makeDataAndStorageController(context: AccountContext, sensitiveContent: Bool) -> ViewController {
|
||||||
|
return dataAndStorageController(context: context, focusOnItemTag: sensitiveContent ? DataAndStorageEntryTag.sensitiveContent : nil)
|
||||||
|
}
|
||||||
|
|
||||||
public func makeInstalledStickerPacksController(context: AccountContext, mode: InstalledStickerPacksControllerMode, forceTheme: PresentationTheme?) -> ViewController {
|
public func makeInstalledStickerPacksController(context: AccountContext, mode: InstalledStickerPacksControllerMode, forceTheme: PresentationTheme?) -> ViewController {
|
||||||
return installedStickerPacksController(context: context, mode: mode, forceTheme: forceTheme)
|
return installedStickerPacksController(context: context, mode: mode, forceTheme: forceTheme)
|
||||||
}
|
}
|
||||||
|
@ -4,33 +4,41 @@ import SwiftSignalKit
|
|||||||
|
|
||||||
public struct MediaDisplaySettings: Codable, Equatable {
|
public struct MediaDisplaySettings: Codable, Equatable {
|
||||||
public let showNextMediaOnTap: Bool
|
public let showNextMediaOnTap: Bool
|
||||||
|
public let showSensitiveContent: Bool
|
||||||
|
|
||||||
public static var defaultSettings: MediaDisplaySettings {
|
public static var defaultSettings: MediaDisplaySettings {
|
||||||
return MediaDisplaySettings(showNextMediaOnTap: true)
|
return MediaDisplaySettings(showNextMediaOnTap: true, showSensitiveContent: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(showNextMediaOnTap: Bool) {
|
public init(showNextMediaOnTap: Bool, showSensitiveContent: Bool) {
|
||||||
self.showNextMediaOnTap = showNextMediaOnTap
|
self.showNextMediaOnTap = showNextMediaOnTap
|
||||||
|
self.showSensitiveContent = showSensitiveContent
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(from decoder: Decoder) throws {
|
public init(from decoder: Decoder) throws {
|
||||||
let container = try decoder.container(keyedBy: StringCodingKey.self)
|
let container = try decoder.container(keyedBy: StringCodingKey.self)
|
||||||
|
|
||||||
self.showNextMediaOnTap = (try container.decode(Int32.self, forKey: "showNextMediaOnTap")) != 0
|
self.showNextMediaOnTap = (try container.decode(Int32.self, forKey: "showNextMediaOnTap")) != 0
|
||||||
|
self.showSensitiveContent = (try container.decode(Int32.self, forKey: "showSensitiveContent")) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
public func encode(to encoder: Encoder) throws {
|
public func encode(to encoder: Encoder) throws {
|
||||||
var container = encoder.container(keyedBy: StringCodingKey.self)
|
var container = encoder.container(keyedBy: StringCodingKey.self)
|
||||||
|
|
||||||
try container.encode((self.showNextMediaOnTap ? 1 : 0) as Int32, forKey: "showNextMediaOnTap")
|
try container.encode((self.showNextMediaOnTap ? 1 : 0) as Int32, forKey: "showNextMediaOnTap")
|
||||||
|
try container.encode((self.showSensitiveContent ? 1 : 0) as Int32, forKey: "showSensitiveContent")
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs: MediaDisplaySettings, rhs: MediaDisplaySettings) -> Bool {
|
public static func ==(lhs: MediaDisplaySettings, rhs: MediaDisplaySettings) -> Bool {
|
||||||
return lhs.showNextMediaOnTap == rhs.showNextMediaOnTap
|
return lhs.showNextMediaOnTap == rhs.showNextMediaOnTap && lhs.showSensitiveContent == rhs.showSensitiveContent
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedShowNextMediaOnTap(_ showNextMediaOnTap: Bool) -> MediaDisplaySettings {
|
public func withUpdatedShowNextMediaOnTap(_ showNextMediaOnTap: Bool) -> MediaDisplaySettings {
|
||||||
return MediaDisplaySettings(showNextMediaOnTap: showNextMediaOnTap)
|
return MediaDisplaySettings(showNextMediaOnTap: showNextMediaOnTap, showSensitiveContent: self.showSensitiveContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func withUpdatedShowSensitiveContent(_ showSensitiveContent: Bool) -> MediaDisplaySettings {
|
||||||
|
return MediaDisplaySettings(showNextMediaOnTap: self.showNextMediaOnTap, showSensitiveContent: showSensitiveContent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +231,7 @@ public func parseInternalUrl(sharedContext: SharedAccountContext, query: String)
|
|||||||
if let phone = phone, let hash = hash {
|
if let phone = phone, let hash = hash {
|
||||||
return .cancelAccountReset(phone: phone, hash: hash)
|
return .cancelAccountReset(phone: phone, hash: hash)
|
||||||
}
|
}
|
||||||
} else if peerName == "msg" {
|
} else if peerName == "msg" || peerName == "share" {
|
||||||
var url: String?
|
var url: String?
|
||||||
var text: String?
|
var text: String?
|
||||||
var to: String?
|
var to: String?
|
||||||
@ -241,7 +241,7 @@ public func parseInternalUrl(sharedContext: SharedAccountContext, query: String)
|
|||||||
url = value
|
url = value
|
||||||
} else if queryItem.name == "text" {
|
} else if queryItem.name == "text" {
|
||||||
text = value
|
text = value
|
||||||
} else if queryItem.name == "to" {
|
} else if queryItem.name == "to" && peerName != "share" {
|
||||||
to = value
|
to = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2072,9 +2072,6 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
})
|
})
|
||||||
})))
|
})))
|
||||||
|
|
||||||
if let botCommands {
|
|
||||||
for command in botCommands {
|
|
||||||
if command.text == "privacy" {
|
|
||||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.WebApp_PrivacyPolicy, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: presentationData.strings.WebApp_PrivacyPolicy, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Privacy"), color: theme.contextMenu.primaryColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Privacy"), color: theme.contextMenu.primaryColor)
|
||||||
}, action: { [weak self] c, _ in
|
}, action: { [weak self] c, _ in
|
||||||
@ -2083,13 +2080,23 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(self.parentController() as? AttachmentController)?.minimizeIfNeeded()
|
||||||
|
if let botCommands, botCommands.contains(where: { $0.text == "privacy" }) {
|
||||||
let _ = enqueueMessages(account: self.context.account, peerId: self.botId, messages: [.message(text: "/privacy", attributes: [], inlineStickers: [:], mediaReference: nil, threadId: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).startStandalone()
|
let _ = enqueueMessages(account: self.context.account, peerId: self.botId, messages: [.message(text: "/privacy", attributes: [], inlineStickers: [:], mediaReference: nil, threadId: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).startStandalone()
|
||||||
|
|
||||||
if let botPeer, let navigationController = self.getNavigationController() {
|
if let botPeer, let navigationController = self.getNavigationController() {
|
||||||
(self.parentController() as? AttachmentController)?.minimizeIfNeeded()
|
|
||||||
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(botPeer)))
|
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(botPeer)))
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
self.context.sharedContext.openExternalUrl(context: self.context, urlContext: .generic, url: self.presentationData.strings.WebApp_PrivacyPolicy_URL, forceExternal: false, presentationData: self.presentationData, navigationController: self.getNavigationController(), dismissInput: {})
|
||||||
|
}
|
||||||
})))
|
})))
|
||||||
|
|
||||||
|
if let botCommands, botCommands.contains(where: { $0.text == "privacy" }) {
|
||||||
|
for command in botCommands {
|
||||||
|
if command.text == "privacy" {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,8 @@ import Markdown
|
|||||||
private let textFont = Font.regular(13.0)
|
private let textFont = Font.regular(13.0)
|
||||||
private let boldTextFont = Font.semibold(13.0)
|
private let boldTextFont = Font.semibold(13.0)
|
||||||
|
|
||||||
private func formattedText(_ text: String, color: UIColor, textAlignment: NSTextAlignment = .natural) -> NSAttributedString {
|
private func formattedText(_ text: String, color: UIColor, linkColor: UIColor, textAlignment: NSTextAlignment = .natural) -> NSAttributedString {
|
||||||
return parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: textFont, textColor: color), bold: MarkdownAttributeSet(font: boldTextFont, textColor: color), link: MarkdownAttributeSet(font: textFont, textColor: color), linkAttribute: { _ in return nil}), textAlignment: textAlignment)
|
return parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: textFont, textColor: color), bold: MarkdownAttributeSet(font: boldTextFont, textColor: color), link: MarkdownAttributeSet(font: textFont, textColor: linkColor), linkAttribute: { _ in return nil}), textAlignment: textAlignment)
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class WebAppLaunchConfirmationAlertContentNode: AlertContentNode {
|
private final class WebAppLaunchConfirmationAlertContentNode: AlertContentNode {
|
||||||
@ -44,6 +44,7 @@ private final class WebAppLaunchConfirmationAlertContentNode: AlertContentNode {
|
|||||||
private var validLayout: CGSize?
|
private var validLayout: CGSize?
|
||||||
|
|
||||||
private let morePressed: () -> Void
|
private let morePressed: () -> Void
|
||||||
|
private let termsPressed: () -> Void
|
||||||
|
|
||||||
override var dismissOnOutsideTap: Bool {
|
override var dismissOnOutsideTap: Bool {
|
||||||
return self.isUserInteractionEnabled
|
return self.isUserInteractionEnabled
|
||||||
@ -55,13 +56,14 @@ private final class WebAppLaunchConfirmationAlertContentNode: AlertContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(context: AccountContext, theme: AlertControllerTheme, ptheme: PresentationTheme, strings: PresentationStrings, peer: EnginePeer, title: String, text: String, showMore: Bool, requestWriteAccess: Bool, actions: [TextAlertAction], morePressed: @escaping () -> Void) {
|
init(context: AccountContext, theme: AlertControllerTheme, ptheme: PresentationTheme, strings: PresentationStrings, peer: EnginePeer, title: String, text: String, showMore: Bool, requestWriteAccess: Bool, actions: [TextAlertAction], morePressed: @escaping () -> Void, termsPressed: @escaping () -> Void) {
|
||||||
self.strings = strings
|
self.strings = strings
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.title = title
|
self.title = title
|
||||||
self.text = text
|
self.text = text
|
||||||
self.showMore = showMore
|
self.showMore = showMore
|
||||||
self.morePressed = morePressed
|
self.morePressed = morePressed
|
||||||
|
self.termsPressed = termsPressed
|
||||||
|
|
||||||
self.titleNode = ImmediateTextNode()
|
self.titleNode = ImmediateTextNode()
|
||||||
self.titleNode.displaysAsynchronously = false
|
self.titleNode.displaysAsynchronously = false
|
||||||
@ -145,6 +147,8 @@ private final class WebAppLaunchConfirmationAlertContentNode: AlertContentNode {
|
|||||||
super.didLoad()
|
super.didLoad()
|
||||||
|
|
||||||
self.allowWriteLabelNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.allowWriteTap(_:))))
|
self.allowWriteLabelNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.allowWriteTap(_:))))
|
||||||
|
|
||||||
|
self.textNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.termsTap(_:))))
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func allowWriteTap(_ gestureRecognizer: UITapGestureRecognizer) {
|
@objc private func allowWriteTap(_ gestureRecognizer: UITapGestureRecognizer) {
|
||||||
@ -153,18 +157,22 @@ private final class WebAppLaunchConfirmationAlertContentNode: AlertContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc private func termsTap(_ gestureRecognizer: UITapGestureRecognizer) {
|
||||||
|
self.termsPressed()
|
||||||
|
}
|
||||||
|
|
||||||
@objc private func moreButtonPressed() {
|
@objc private func moreButtonPressed() {
|
||||||
self.morePressed()
|
self.morePressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func updateTheme(_ theme: AlertControllerTheme) {
|
override func updateTheme(_ theme: AlertControllerTheme) {
|
||||||
self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.semibold(17.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.semibold(17.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||||
self.textNode.attributedText = NSAttributedString(string: self.text, font: Font.regular(13.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
self.textNode.attributedText = formattedText(self.text, color: theme.primaryColor, linkColor: theme.accentColor, textAlignment: .center)
|
||||||
|
|
||||||
self.moreButton.setAttributedTitle(NSAttributedString(string: self.strings.WebApp_LaunchMoreInfo, font: Font.regular(13.0), textColor: theme.accentColor), for: .normal)
|
self.moreButton.setAttributedTitle(NSAttributedString(string: self.strings.WebApp_LaunchMoreInfo, font: Font.regular(13.0), textColor: theme.accentColor), for: .normal)
|
||||||
self.arrowNode.image = generateTintedImage(image: UIImage(bundleImageName: "Peer Info/AlertArrow"), color: theme.accentColor)
|
self.arrowNode.image = generateTintedImage(image: UIImage(bundleImageName: "Peer Info/AlertArrow"), color: theme.accentColor)
|
||||||
|
|
||||||
self.allowWriteLabelNode.attributedText = formattedText(strings.WebApp_AddToAttachmentAllowMessages(self.peer.compactDisplayTitle).string, color: theme.primaryColor)
|
self.allowWriteLabelNode.attributedText = formattedText(strings.WebApp_AddToAttachmentAllowMessages(self.peer.compactDisplayTitle).string, color: theme.primaryColor, linkColor: theme.primaryColor)
|
||||||
|
|
||||||
self.actionNodesSeparator.backgroundColor = theme.separatorColor
|
self.actionNodesSeparator.backgroundColor = theme.separatorColor
|
||||||
for actionNode in self.actionNodes {
|
for actionNode in self.actionNodes {
|
||||||
@ -313,7 +321,15 @@ private final class WebAppLaunchConfirmationAlertContentNode: AlertContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func webAppLaunchConfirmationController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peer: EnginePeer, requestWriteAccess: Bool = false, completion: @escaping (Bool) -> Void, showMore: (() -> Void)?) -> AlertController {
|
public func webAppLaunchConfirmationController(
|
||||||
|
context: AccountContext,
|
||||||
|
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?,
|
||||||
|
peer: EnginePeer,
|
||||||
|
requestWriteAccess: Bool = false,
|
||||||
|
completion: @escaping (Bool) -> Void,
|
||||||
|
showMore: (() -> Void)?,
|
||||||
|
openTerms: @escaping () -> Void
|
||||||
|
) -> AlertController {
|
||||||
let theme = defaultDarkColorPresentationTheme
|
let theme = defaultDarkColorPresentationTheme
|
||||||
let presentationData: PresentationData
|
let presentationData: PresentationData
|
||||||
if let updatedPresentationData {
|
if let updatedPresentationData {
|
||||||
@ -337,11 +353,14 @@ public func webAppLaunchConfirmationController(context: AccountContext, updatedP
|
|||||||
})]
|
})]
|
||||||
|
|
||||||
let title = peer.compactDisplayTitle
|
let title = peer.compactDisplayTitle
|
||||||
let text = presentationData.strings.WebApp_LaunchConfirmation
|
let text = presentationData.strings.WebApp_LaunchTermsConfirmation
|
||||||
|
|
||||||
let contentNode = WebAppLaunchConfirmationAlertContentNode(context: context, theme: AlertControllerTheme(presentationData: presentationData), ptheme: theme, strings: strings, peer: peer, title: title, text: text, showMore: showMore != nil, requestWriteAccess: requestWriteAccess, actions: actions, morePressed: {
|
let contentNode = WebAppLaunchConfirmationAlertContentNode(context: context, theme: AlertControllerTheme(presentationData: presentationData), ptheme: theme, strings: strings, peer: peer, title: title, text: text, showMore: showMore != nil, requestWriteAccess: requestWriteAccess, actions: actions, morePressed: {
|
||||||
dismissImpl?(true)
|
dismissImpl?(true)
|
||||||
showMore?()
|
showMore?()
|
||||||
|
}, termsPressed: {
|
||||||
|
dismissImpl?(true)
|
||||||
|
openTerms()
|
||||||
})
|
})
|
||||||
getContentNodeImpl = { [weak contentNode] in
|
getContentNodeImpl = { [weak contentNode] in
|
||||||
return contentNode
|
return contentNode
|
||||||
|
Loading…
x
Reference in New Issue
Block a user