diff --git a/submodules/AccountContext/Sources/ContactMultiselectionController.swift b/submodules/AccountContext/Sources/ContactMultiselectionController.swift index 0d9f444f23..880014fbf6 100644 --- a/submodules/AccountContext/Sources/ContactMultiselectionController.swift +++ b/submodules/AccountContext/Sources/ContactMultiselectionController.swift @@ -46,6 +46,7 @@ public enum ContactMultiselectionControllerMode { public var displayAutoremoveTimeout: Bool public var displayPresence: Bool public var onlyUsers: Bool + public var disableChannels: Bool public init( title: String, @@ -55,7 +56,8 @@ public enum ContactMultiselectionControllerMode { chatListFilters: [ChatListFilter]?, displayAutoremoveTimeout: Bool = false, displayPresence: Bool = false, - onlyUsers: Bool = false + onlyUsers: Bool = false, + disableChannels: Bool = false ) { self.title = title self.searchPlaceholder = searchPlaceholder @@ -65,6 +67,7 @@ public enum ContactMultiselectionControllerMode { self.displayAutoremoveTimeout = displayAutoremoveTimeout self.displayPresence = displayPresence self.onlyUsers = onlyUsers + self.disableChannels = disableChannels } } diff --git a/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift b/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift index 739937f0f7..bc606e7a54 100644 --- a/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift +++ b/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift @@ -445,6 +445,7 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem { let threadInfo: EngineMessageHistoryThread.Info? let height: ItemListPeerItemHeight let aliasHandling: ItemListPeerItemAliasHandling + let customAvatarIcon: UIImage? let nameColor: ItemListPeerItemNameColor let nameStyle: ItemListPeerItemNameStyle let presence: EnginePeer.Presence? @@ -486,6 +487,7 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem { threadInfo: EngineMessageHistoryThread.Info? = nil, height: ItemListPeerItemHeight = .peerList, aliasHandling: ItemListPeerItemAliasHandling = .standard, + customAvatarIcon: UIImage? = nil, nameColor: ItemListPeerItemNameColor = .primary, nameStyle: ItemListPeerItemNameStyle = .distinctBold, presence: EnginePeer.Presence?, @@ -526,6 +528,7 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem { self.threadInfo = threadInfo self.height = height self.aliasHandling = aliasHandling + self.customAvatarIcon = customAvatarIcon self.nameColor = nameColor self.nameStyle = nameStyle self.presence = presence @@ -568,6 +571,7 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem { threadInfo: EngineMessageHistoryThread.Info? = nil, height: ItemListPeerItemHeight = .peerList, aliasHandling: ItemListPeerItemAliasHandling = .standard, + customAvatarIcon: UIImage? = nil, nameColor: ItemListPeerItemNameColor = .primary, nameStyle: ItemListPeerItemNameStyle = .distinctBold, presence: EnginePeer.Presence?, @@ -608,6 +612,7 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem { self.threadInfo = threadInfo self.height = height self.aliasHandling = aliasHandling + self.customAvatarIcon = customAvatarIcon self.nameColor = nameColor self.nameStyle = nameStyle self.presence = presence @@ -717,6 +722,8 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo private var avatarIconComponent: EmojiStatusComponent? private var avatarIconView: ComponentView? + private var customAvatarIconView: UIImageView? + private var avatarButton: HighlightTrackingButton? private let titleNode: TextNode @@ -1701,6 +1708,24 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo shimmerNode.removeFromSupernode() } + if let customAvatarIcon = item.customAvatarIcon { + strongSelf.avatarNode.isHidden = true + + let customAvatarIconView: UIImageView + if let current = strongSelf.customAvatarIconView { + customAvatarIconView = current + } else { + customAvatarIconView = UIImageView() + strongSelf.customAvatarIconView = customAvatarIconView + strongSelf.containerNode.view.addSubview(customAvatarIconView) + } + customAvatarIconView.image = customAvatarIcon + customAvatarIconView.frame = strongSelf.avatarNode.frame + } else if let customAvatarIconView = strongSelf.customAvatarIconView { + strongSelf.customAvatarIconView = nil + customAvatarIconView.removeFromSuperview() + } + strongSelf.backgroundNode.isHidden = !item.displayDecorations strongSelf.highlightedBackgroundNode.isHidden = !item.displayDecorations || !item.highlightable diff --git a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift index 9b1a27d4bc..3ab98d4d93 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift @@ -475,11 +475,24 @@ private func countForSelectivePeers(_ peers: [PeerId: SelectivePrivacyPeer]) -> private func stringForSelectiveSettings(strings: PresentationStrings, settings: SelectivePrivacySettings) -> String { switch settings { - case let .disableEveryone(enableFor, enableForCloseFriends): - if enableFor.isEmpty && !enableForCloseFriends { + case let .disableEveryone(enableFor, enableForCloseFriends, enableForPremium): + if enableFor.isEmpty && !enableForCloseFriends && !enableForPremium { return strings.PrivacySettings_LastSeenNobody } else { - if enableForCloseFriends { + if enableForCloseFriends && enableForPremium { + //TODO:localize + if enableFor.isEmpty { + return "Close Friends, Premium" + } else { + return "Close Friends, Premium +\(countForSelectivePeers(enableFor))" + } + } else if enableForPremium { + if enableFor.isEmpty { + return "Premium Users" + } else { + return "Premium Users +\(countForSelectivePeers(enableFor))" + } + } else if enableForCloseFriends { if enableFor.isEmpty { return strings.PrivacySettings_LastSeenCloseFriendsPlus("\(countForSelectivePeers(enableFor))").string } else { @@ -499,15 +512,27 @@ private func stringForSelectiveSettings(strings: PresentationStrings, settings: } else { return strings.PrivacySettings_LastSeenEverybodyMinus("\(countForSelectivePeers(disableFor))").string } - case let .enableContacts(enableFor, disableFor): - if !enableFor.isEmpty && !disableFor.isEmpty { - return strings.PrivacySettings_LastSeenContactsMinusPlus("\(countForSelectivePeers(disableFor))", "\(countForSelectivePeers(enableFor))").string - } else if !enableFor.isEmpty { - return strings.PrivacySettings_LastSeenContactsPlus("\(countForSelectivePeers(enableFor))").string - } else if !disableFor.isEmpty { - return strings.PrivacySettings_LastSeenContactsMinus("\(countForSelectivePeers(disableFor))").string + case let .enableContacts(enableFor, disableFor, enableForPremium): + if enableForPremium { + if !enableFor.isEmpty && !disableFor.isEmpty { + return "Premium, " + strings.PrivacySettings_LastSeenContactsMinusPlus("\(countForSelectivePeers(disableFor))", "\(countForSelectivePeers(enableFor))").string + } else if !enableFor.isEmpty { + return "Premium, " + strings.PrivacySettings_LastSeenContactsPlus("\(countForSelectivePeers(enableFor))").string + } else if !disableFor.isEmpty { + return "Premium, " + strings.PrivacySettings_LastSeenContactsMinus("\(countForSelectivePeers(disableFor))").string + } else { + return "Premium, " + strings.PrivacySettings_LastSeenContacts + } } else { - return strings.PrivacySettings_LastSeenContacts + if !enableFor.isEmpty && !disableFor.isEmpty { + return strings.PrivacySettings_LastSeenContactsMinusPlus("\(countForSelectivePeers(disableFor))", "\(countForSelectivePeers(enableFor))").string + } else if !enableFor.isEmpty { + return strings.PrivacySettings_LastSeenContactsPlus("\(countForSelectivePeers(enableFor))").string + } else if !disableFor.isEmpty { + return strings.PrivacySettings_LastSeenContactsMinus("\(countForSelectivePeers(disableFor))").string + } else { + return strings.PrivacySettings_LastSeenContacts + } } } } diff --git a/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsController.swift b/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsController.swift index e83455cce8..a0ea26298c 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsController.swift @@ -103,15 +103,25 @@ private enum SelectivePrivacySettingsSection: Int32 { case premium } -private func stringForUserCount(_ peers: [EnginePeer.Id: SelectivePrivacyPeer], strings: PresentationStrings) -> String { - if peers.isEmpty { +private func stringForUserCount(_ peers: [EnginePeer.Id: SelectivePrivacyPeer], enableForPremium: Bool, strings: PresentationStrings) -> String { + if peers.isEmpty && !enableForPremium { return strings.PrivacyLastSeenSettings_EmpryUsersPlaceholder } else { var result = 0 for (_, peer) in peers { result += peer.userCount } - return strings.UserCount(Int32(result)) + + if enableForPremium { + //TODO:localize + if result == 0 { + return "Premium Users" + } else { + return "Premium Users +\(result)" + } + } else { + return strings.UserCount(Int32(result)) + } } } @@ -568,6 +578,7 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry { private struct SelectivePrivacySettingsControllerState: Equatable { let setting: SelectivePrivacySettingType let enableFor: [EnginePeer.Id: SelectivePrivacyPeer] + let enableForPremium: Bool let disableFor: [EnginePeer.Id: SelectivePrivacyPeer] let enableForCloseFriends: Bool @@ -585,9 +596,10 @@ private struct SelectivePrivacySettingsControllerState: Equatable { let uploadedPhoto: UIImage? - init(setting: SelectivePrivacySettingType, enableFor: [EnginePeer.Id: SelectivePrivacyPeer], disableFor: [EnginePeer.Id: SelectivePrivacyPeer], enableForCloseFriends: Bool, saving: Bool, callDataSaving: VoiceCallDataSaving?, callP2PMode: SelectivePrivacySettingType?, callP2PEnableFor: [EnginePeer.Id: SelectivePrivacyPeer]?, callP2PDisableFor: [EnginePeer.Id: SelectivePrivacyPeer]?, callP2PEnableForCloseFriends: Bool?, callIntegrationAvailable: Bool?, callIntegrationEnabled: Bool?, phoneDiscoveryEnabled: Bool?, hideReadTimeEnabled: Bool?, uploadedPhoto: UIImage?) { + init(setting: SelectivePrivacySettingType, enableFor: [EnginePeer.Id: SelectivePrivacyPeer], enableForPremium: Bool, disableFor: [EnginePeer.Id: SelectivePrivacyPeer], enableForCloseFriends: Bool, saving: Bool, callDataSaving: VoiceCallDataSaving?, callP2PMode: SelectivePrivacySettingType?, callP2PEnableFor: [EnginePeer.Id: SelectivePrivacyPeer]?, callP2PDisableFor: [EnginePeer.Id: SelectivePrivacyPeer]?, callP2PEnableForCloseFriends: Bool?, callIntegrationAvailable: Bool?, callIntegrationEnabled: Bool?, phoneDiscoveryEnabled: Bool?, hideReadTimeEnabled: Bool?, uploadedPhoto: UIImage?) { self.setting = setting self.enableFor = enableFor + self.enableForPremium = enableForPremium self.disableFor = disableFor self.enableForCloseFriends = enableForCloseFriends self.saving = saving @@ -610,6 +622,9 @@ private struct SelectivePrivacySettingsControllerState: Equatable { if lhs.enableFor != rhs.enableFor { return false } + if lhs.enableForPremium != rhs.enableForPremium { + return false + } if lhs.disableFor != rhs.disableFor { return false } @@ -654,55 +669,59 @@ private struct SelectivePrivacySettingsControllerState: Equatable { } func withUpdatedSetting(_ setting: SelectivePrivacySettingType) -> SelectivePrivacySettingsControllerState { - return SelectivePrivacySettingsControllerState(setting: setting, enableFor: self.enableFor, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) + return SelectivePrivacySettingsControllerState(setting: setting, enableFor: self.enableFor, enableForPremium: self.enableForPremium, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) } func withUpdatedEnableFor(_ enableFor: [EnginePeer.Id: SelectivePrivacyPeer]) -> SelectivePrivacySettingsControllerState { - return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: enableFor, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) + return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: enableFor, enableForPremium: self.enableForPremium, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) + } + + func withUpdatedEnableForPremium(_ value: Bool) -> SelectivePrivacySettingsControllerState { + return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, enableForPremium: value, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) } func withUpdatedDisableFor(_ disableFor: [EnginePeer.Id: SelectivePrivacyPeer]) -> SelectivePrivacySettingsControllerState { - return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) + return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, enableForPremium: self.enableForPremium, disableFor: disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) } func withUpdatedEnableForCloseFriends(_ enableForCloseFriends: Bool) -> SelectivePrivacySettingsControllerState { - return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, enableForCloseFriends: enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) + return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, enableForPremium: self.enableForPremium, disableFor: self.disableFor, enableForCloseFriends: enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) } func withUpdatedSaving(_ saving: Bool) -> SelectivePrivacySettingsControllerState { - return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) + return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, enableForPremium: self.enableForPremium, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) } func withUpdatedCallP2PMode(_ mode: SelectivePrivacySettingType) -> SelectivePrivacySettingsControllerState { - return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: mode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) + return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, enableForPremium: self.enableForPremium, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: mode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) } func withUpdatedCallP2PEnableFor(_ enableFor: [EnginePeer.Id: SelectivePrivacyPeer]) -> SelectivePrivacySettingsControllerState { - return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: enableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) + return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, enableForPremium: self.enableForPremium, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: enableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) } func withUpdatedCallP2PDisableFor(_ disableFor: [EnginePeer.Id: SelectivePrivacyPeer]) -> SelectivePrivacySettingsControllerState { - return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: disableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) + return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, enableForPremium: self.enableForPremium, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: disableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) } func withUpdatedCallP2PEnableForCloseFriends(_ callP2PEnableForCloseFriends: Bool) -> SelectivePrivacySettingsControllerState { - return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) + return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, enableForPremium: self.enableForPremium, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) } func withUpdatedCallsIntegrationEnabled(_ enabled: Bool) -> SelectivePrivacySettingsControllerState { - return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: enabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) + return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, enableForPremium: self.enableForPremium, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: enabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) } func withUpdatedPhoneDiscoveryEnabled(_ phoneDiscoveryEnabled: Bool) -> SelectivePrivacySettingsControllerState { - return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) + return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, enableForPremium: self.enableForPremium, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) } func withUpdatedUploadedPhoto(_ uploadedPhoto: UIImage?) -> SelectivePrivacySettingsControllerState { - return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: uploadedPhoto) + return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, enableForPremium: self.enableForPremium, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: self.hideReadTimeEnabled, uploadedPhoto: uploadedPhoto) } func withUpdatedHideReadTimeEnabled(_ hideReadTimeEnabled: Bool) -> SelectivePrivacySettingsControllerState { - return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) + return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, enableForPremium: self.enableForPremium, disableFor: self.disableFor, enableForCloseFriends: self.enableForCloseFriends, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callP2PEnableForCloseFriends: self.callP2PEnableForCloseFriends, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, hideReadTimeEnabled: hideReadTimeEnabled, uploadedPhoto: self.uploadedPhoto) } } @@ -820,12 +839,12 @@ private func selectivePrivacySettingsControllerEntries(presentationData: Present switch state.setting { case .everybody: - entries.append(.disableFor(presentationData.theme, disableForText, stringForUserCount(state.disableFor, strings: presentationData.strings))) + entries.append(.disableFor(presentationData.theme, disableForText, stringForUserCount(state.disableFor, enableForPremium: false, strings: presentationData.strings))) case .contacts: - entries.append(.disableFor(presentationData.theme, disableForText, stringForUserCount(state.disableFor, strings: presentationData.strings))) - entries.append(.enableFor(presentationData.theme, enableForText, stringForUserCount(state.enableFor, strings: presentationData.strings))) + entries.append(.disableFor(presentationData.theme, disableForText, stringForUserCount(state.disableFor, enableForPremium: false, strings: presentationData.strings))) + entries.append(.enableFor(presentationData.theme, enableForText, stringForUserCount(state.enableFor, enableForPremium: state.enableForPremium, strings: presentationData.strings))) case .nobody: - entries.append(.enableFor(presentationData.theme, enableForText, stringForUserCount(state.enableFor, strings: presentationData.strings))) + entries.append(.enableFor(presentationData.theme, enableForText, stringForUserCount(state.enableFor, enableForPremium: state.enableForPremium, strings: presentationData.strings))) } let exceptionsInfo: String if case .profilePhoto = kind { @@ -854,12 +873,12 @@ private func selectivePrivacySettingsControllerEntries(presentationData: Present if let callP2PMode = state.callP2PMode, let disableFor = state.callP2PDisableFor, let enableFor = state.callP2PEnableFor { switch callP2PMode { case .everybody: - entries.append(.callsP2PDisableFor(presentationData.theme, disableForText, stringForUserCount(disableFor, strings: presentationData.strings))) + entries.append(.callsP2PDisableFor(presentationData.theme, disableForText, stringForUserCount(disableFor, enableForPremium: false, strings: presentationData.strings))) case .contacts: - entries.append(.callsP2PDisableFor(presentationData.theme, disableForText, stringForUserCount(disableFor, strings: presentationData.strings))) - entries.append(.callsP2PEnableFor(presentationData.theme, enableForText, stringForUserCount(enableFor, strings: presentationData.strings))) + entries.append(.callsP2PDisableFor(presentationData.theme, disableForText, stringForUserCount(disableFor, enableForPremium: false, strings: presentationData.strings))) + entries.append(.callsP2PEnableFor(presentationData.theme, enableForText, stringForUserCount(enableFor, enableForPremium: false, strings: presentationData.strings))) case .nobody: - entries.append(.callsP2PEnableFor(presentationData.theme, enableForText, stringForUserCount(enableFor, strings: presentationData.strings))) + entries.append(.callsP2PEnableFor(presentationData.theme, enableForText, stringForUserCount(enableFor, enableForPremium: false, strings: presentationData.strings))) } } entries.append(.callsP2PPeersInfo(presentationData.theme, presentationData.strings.PrivacyLastSeenSettings_CustomShareSettingsHelp)) @@ -918,17 +937,9 @@ func generatePremiumCategoryIcon(size: CGSize, cornerRadius: CGFloat) -> UIImage context.addPath(path.cgPath) context.clip() - let colorsArray: [CGColor] = [ - UIColor(rgb: 0xF161DD).cgColor, - UIColor(rgb: 0xF161DD).cgColor, - UIColor(rgb: 0x8d77ff).cgColor, - UIColor(rgb: 0xb56eec).cgColor, - UIColor(rgb: 0xb56eec).cgColor - ] - var locations: [CGFloat] = [0.0, 0.15, 0.5, 0.85, 1.0] - let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colorsArray as CFArray, locations: &locations)! - - context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: size.width, y: size.height), options: CGGradientDrawingOptions()) + if let gradientImage = UIImage(bundleImageName: "Premium/PremiumIconBackground"), let cgImage = gradientImage.cgImage { + context.draw(cgImage, in: CGRect(origin: CGPoint(), size: size)) + } if let image = generateTintedImage(image: UIImage(bundleImageName: "Premium/ButtonIcon"), color: UIColor(rgb: 0xffffff)), let cgImage = image.cgImage { let imageSize = image.size.aspectFitted(CGSize(width: floor(size.width * 0.6), height: floor(size.height * 0.6))) @@ -953,15 +964,18 @@ func selectivePrivacySettingsController( let strings = context.sharedContext.currentPresentationData.with { $0 }.strings var initialEnableFor: [EnginePeer.Id: SelectivePrivacyPeer] = [:] + var initialEnableForPremium = false var initialDisableFor: [EnginePeer.Id: SelectivePrivacyPeer] = [:] var initialEnableForCloseFriends = false switch current { - case let .disableEveryone(enableFor, enableForCloseFriends): + case let .disableEveryone(enableFor, enableForCloseFriends, enableForPremiumValue): initialEnableFor = enableFor initialEnableForCloseFriends = enableForCloseFriends - case let .enableContacts(enableFor, disableFor): + initialEnableForPremium = enableForPremiumValue + case let .enableContacts(enableFor, disableFor, enableForPremiumValue): initialEnableFor = enableFor initialDisableFor = disableFor + initialEnableForPremium = enableForPremiumValue case let .enableEveryone(disableFor): initialDisableFor = disableFor } @@ -970,11 +984,11 @@ func selectivePrivacySettingsController( var initialCallEnableForCloseFriends = false if let callCurrent = callSettings?.0 { switch callCurrent { - case let .disableEveryone(enableFor, enableForCloseFriends): + case let .disableEveryone(enableFor, enableForCloseFriends, _): initialCallP2PEnableFor = enableFor initialCallP2PDisableFor = [:] initialCallEnableForCloseFriends = enableForCloseFriends - case let .enableContacts(enableFor, disableFor): + case let .enableContacts(enableFor, disableFor, _): initialCallP2PEnableFor = enableFor initialCallP2PDisableFor = disableFor case let .enableEveryone(disableFor): @@ -984,7 +998,7 @@ func selectivePrivacySettingsController( } //TODO:replace hideReadTimeEnabled with actual value - let initialState = SelectivePrivacySettingsControllerState(setting: SelectivePrivacySettingType(current), enableFor: initialEnableFor, disableFor: initialDisableFor, enableForCloseFriends: initialEnableForCloseFriends, saving: false, callDataSaving: callSettings?.1.dataSaving, callP2PMode: callSettings != nil ? SelectivePrivacySettingType(callSettings!.0) : nil, callP2PEnableFor: initialCallP2PEnableFor, callP2PDisableFor: initialCallP2PDisableFor, callP2PEnableForCloseFriends: initialCallEnableForCloseFriends, callIntegrationAvailable: callIntegrationAvailable, callIntegrationEnabled: callSettings?.1.enableSystemIntegration, phoneDiscoveryEnabled: phoneDiscoveryEnabled, hideReadTimeEnabled: globalSettings?.hideReadTime, uploadedPhoto: nil) + let initialState = SelectivePrivacySettingsControllerState(setting: SelectivePrivacySettingType(current), enableFor: initialEnableFor, enableForPremium: initialEnableForPremium, disableFor: initialDisableFor, enableForCloseFriends: initialEnableForCloseFriends, saving: false, callDataSaving: callSettings?.1.dataSaving, callP2PMode: callSettings != nil ? SelectivePrivacySettingType(callSettings!.0) : nil, callP2PEnableFor: initialCallP2PEnableFor, callP2PDisableFor: initialCallP2PDisableFor, callP2PEnableForCloseFriends: initialCallEnableForCloseFriends, callIntegrationAvailable: callIntegrationAvailable, callIntegrationEnabled: callSettings?.1.enableSystemIntegration, phoneDiscoveryEnabled: phoneDiscoveryEnabled, hideReadTimeEnabled: globalSettings?.hideReadTime, uploadedPhoto: nil) let statePromise = ValuePromise(initialState, ignoreRepeated: true) let stateValue = Atomic(value: initialState) @@ -1068,7 +1082,7 @@ func selectivePrivacySettingsController( } return state } - if peerIds.isEmpty { + if peerIds.isEmpty && !stateValue.with({ $0 }).enableForPremium { enum AdditionalCategoryId: Int { case premiumUsers } @@ -1084,13 +1098,14 @@ func selectivePrivacySettingsController( //TODO:localize var additionalCategories: [ChatListNodeAdditionalCategory] = [] - if displayPremiumCategory { + if displayPremiumCategory && enable { additionalCategories = [ ChatListNodeAdditionalCategory( id: AdditionalCategoryId.premiumUsers.rawValue, icon: generatePremiumCategoryIcon(size: CGSize(width: 40.0, height: 40.0), cornerRadius: 12.0), smallIcon: generatePremiumCategoryIcon(size: CGSize(width: 22.0, height: 22.0), cornerRadius: 6.0), - title: "Premium Users" + title: "Premium Users", + appearance: .option(sectionTitle: "USER TYPES") ) ] } @@ -1102,17 +1117,20 @@ func selectivePrivacySettingsController( selectedChats: Set(), additionalCategories: ContactMultiselectionControllerAdditionalCategories(categories: additionalCategories, selectedCategories: selectedCategories), chatListFilters: nil, - onlyUsers: false - )), options: [])) + onlyUsers: false, + disableChannels: true + )), options: [], filters: [.excludeSelf])) addPeerDisposable.set((controller.result |> take(1) |> deliverOnMainQueue).start(next: { [weak controller] result in var peerIds: [ContactListPeerId] = [] - if case let .result(peerIdsValue, _) = result { + var premiumSelected = false + if case let .result(peerIdsValue, additionalOptionIds) = result { peerIds = peerIdsValue + premiumSelected = additionalOptionIds.contains(AdditionalCategoryId.premiumUsers.rawValue) } - if peerIds.isEmpty { + if peerIds.isEmpty && !premiumSelected { controller?.dismiss() return } @@ -1162,6 +1180,7 @@ func selectivePrivacySettingsController( disableFor.removeValue(forKey: key) } return state.withUpdatedEnableFor(updatedPeerIds).withUpdatedDisableFor(disableFor) + .withUpdatedEnableForPremium(premiumSelected ? true : state.enableForPremium) case .callP2P: var callP2PDisableFor = state.callP2PDisableFor ?? [:] for (key, _) in updatedPeerIds { @@ -1193,12 +1212,14 @@ func selectivePrivacySettingsController( var displayPremiumCategory = false switch kind { case .groupInvitations: - displayPremiumCategory = true + if enable { + displayPremiumCategory = true + } default: break } - let controller = selectivePrivacyPeersController(context: context, title: title, initialPeers: peerIds, displayPremiumCategory: displayPremiumCategory, updated: { updatedPeerIds in + let controller = selectivePrivacyPeersController(context: context, title: title, initialPeers: peerIds, initialEnableForPremium: stateValue.with({ $0 }).enableForPremium, displayPremiumCategory: displayPremiumCategory, updated: { updatedPeerIds, enableForPremium in updateState { state in if enable { switch target { @@ -1207,7 +1228,7 @@ func selectivePrivacySettingsController( for (key, _) in updatedPeerIds { disableFor.removeValue(forKey: key) } - return state.withUpdatedEnableFor(updatedPeerIds).withUpdatedDisableFor(disableFor) + return state.withUpdatedEnableFor(updatedPeerIds).withUpdatedDisableFor(disableFor).withUpdatedEnableForPremium(enableForPremium) case .callP2P: var callP2PDisableFor = state.callP2PDisableFor ?? [:] for (key, _) in updatedPeerIds { @@ -1382,9 +1403,9 @@ func selectivePrivacySettingsController( case .everybody: settings = SelectivePrivacySettings.enableEveryone(disableFor: state.disableFor) case .contacts: - settings = SelectivePrivacySettings.enableContacts(enableFor: state.enableFor, disableFor: state.disableFor) + settings = SelectivePrivacySettings.enableContacts(enableFor: state.enableFor, disableFor: state.disableFor, enableForPremium: state.enableForPremium) case .nobody: - settings = SelectivePrivacySettings.disableEveryone(enableFor: state.enableFor, enableForCloseFriends: state.enableForCloseFriends) + settings = SelectivePrivacySettings.disableEveryone(enableFor: state.enableFor, enableForCloseFriends: state.enableForCloseFriends, enableForPremium: state.enableForPremium) } if case .phoneNumber = kind, let value = state.phoneDiscoveryEnabled { @@ -1400,9 +1421,9 @@ func selectivePrivacySettingsController( case .everybody: callP2PSettings = SelectivePrivacySettings.enableEveryone(disableFor: disableFor) case .contacts: - callP2PSettings = SelectivePrivacySettings.enableContacts(enableFor: enableFor, disableFor: disableFor) + callP2PSettings = SelectivePrivacySettings.enableContacts(enableFor: enableFor, disableFor: disableFor, enableForPremium: false) case .nobody: - callP2PSettings = SelectivePrivacySettings.disableEveryone(enableFor: enableFor, enableForCloseFriends: enableForCloseFriends) + callP2PSettings = SelectivePrivacySettings.disableEveryone(enableFor: enableFor, enableForCloseFriends: enableForCloseFriends, enableForPremium: false) } } diff --git a/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsPeersController.swift b/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsPeersController.swift index b2aad40413..e67e6300de 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsPeersController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsPeersController.swift @@ -19,14 +19,16 @@ private final class SelectivePrivacyPeersControllerArguments { let addPeer: () -> Void let openPeer: (EnginePeer) -> Void let deleteAll: () -> Void + let removePremiumUsers: () -> Void - init(context: AccountContext, setPeerIdWithRevealedOptions: @escaping (EnginePeer.Id?, EnginePeer.Id?) -> Void, removePeer: @escaping (EnginePeer.Id) -> Void, addPeer: @escaping () -> Void, openPeer: @escaping (EnginePeer) -> Void, deleteAll: @escaping () -> Void) { + init(context: AccountContext, setPeerIdWithRevealedOptions: @escaping (EnginePeer.Id?, EnginePeer.Id?) -> Void, removePeer: @escaping (EnginePeer.Id) -> Void, addPeer: @escaping () -> Void, openPeer: @escaping (EnginePeer) -> Void, deleteAll: @escaping () -> Void, removePremiumUsers: @escaping () -> Void) { self.context = context self.setPeerIdWithRevealedOptions = setPeerIdWithRevealedOptions self.removePeer = removePeer self.addPeer = addPeer self.openPeer = openPeer self.deleteAll = deleteAll + self.removePremiumUsers = removePremiumUsers } } @@ -38,19 +40,25 @@ private enum SelectivePrivacyPeersSection: Int32 { private enum SelectivePrivacyPeersEntryStableId: Hashable { case header case add + case premiumUsers case peer(EnginePeer.Id) case delete } +private let premiumAvatarIcon: UIImage? = { + return generatePremiumCategoryIcon(size: CGSize(width: 31.0, height: 31.0), cornerRadius: 8.0) +}() + private enum SelectivePrivacyPeersEntry: ItemListNodeEntry { - case peerItem(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, SelectivePrivacyPeer, ItemListPeerItemEditing, Bool) - case addItem(PresentationTheme, String, Bool) - case headerItem(PresentationTheme, String) - case deleteItem(PresentationTheme, String) + case premiumUsersItem(ItemListPeerItemEditing, Bool) + case peerItem(Int32, PresentationDateTimeFormat, PresentationPersonNameOrder, SelectivePrivacyPeer, ItemListPeerItemEditing, Bool) + case addItem(String, Bool) + case headerItem(String) + case deleteItem(String) var section: ItemListSectionId { switch self { - case .addItem, .peerItem, .headerItem: + case .addItem, .premiumUsersItem, .peerItem, .headerItem: return SelectivePrivacyPeersSection.peers.rawValue case .deleteItem: return SelectivePrivacyPeersSection.delete.rawValue @@ -59,7 +67,9 @@ private enum SelectivePrivacyPeersEntry: ItemListNodeEntry { var stableId: SelectivePrivacyPeersEntryStableId { switch self { - case let .peerItem(_, _, _, _, _, peer, _, _): + case .premiumUsersItem: + return .premiumUsers + case let .peerItem(_, _, _, peer, _, _): return .peer(peer.peer.id) case .addItem: return .add @@ -72,20 +82,20 @@ private enum SelectivePrivacyPeersEntry: ItemListNodeEntry { static func ==(lhs: SelectivePrivacyPeersEntry, rhs: SelectivePrivacyPeersEntry) -> Bool { switch lhs { - case let .peerItem(lhsIndex, lhsTheme, lhsStrings, lhsDateTimeFormat, lhsNameOrder, lhsPeer, lhsEditing, lhsEnabled): - if case let .peerItem(rhsIndex, rhsTheme, rhsStrings, rhsDateTimeFormat, rhsNameOrder, rhsPeer, rhsEditing, rhsEnabled) = rhs { + case let .premiumUsersItem(editing, isEnabled): + if case .premiumUsersItem(editing, isEnabled) = rhs { + return true + } else { + return false + } + case let .peerItem(lhsIndex, lhsDateTimeFormat, lhsNameOrder, lhsPeer, lhsEditing, lhsEnabled): + if case let .peerItem(rhsIndex, rhsDateTimeFormat, rhsNameOrder, rhsPeer, rhsEditing, rhsEnabled) = rhs { if lhsIndex != rhsIndex { return false } if lhsPeer != rhsPeer { return false } - if lhsTheme !== rhsTheme { - return false - } - if lhsStrings !== rhsStrings { - return false - } if lhsDateTimeFormat != rhsDateTimeFormat { return false } @@ -102,20 +112,20 @@ private enum SelectivePrivacyPeersEntry: ItemListNodeEntry { } else { return false } - case let .addItem(lhsTheme, lhsText, lhsEditing): - if case let .addItem(rhsTheme, rhsText, rhsEditing) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsEditing == rhsEditing { + case let .addItem(lhsText, lhsEditing): + if case let .addItem(rhsText, rhsEditing) = rhs, lhsText == rhsText, lhsEditing == rhsEditing { return true } else { return false } - case let .headerItem(lhsTheme, lhsText): - if case let .headerItem(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + case let .headerItem(lhsText): + if case let .headerItem(rhsText) = rhs, lhsText == rhsText { return true } else { return false } - case let .deleteItem(lhsTheme, lhsText): - if case let .deleteItem(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + case let .deleteItem(lhsText): + if case let .deleteItem(rhsText) = rhs, lhsText == rhsText { return true } else { return false @@ -125,47 +135,67 @@ private enum SelectivePrivacyPeersEntry: ItemListNodeEntry { static func <(lhs: SelectivePrivacyPeersEntry, rhs: SelectivePrivacyPeersEntry) -> Bool { switch lhs { + case .deleteItem: + return false + case let .peerItem(index, _, _, _, _, _): + switch rhs { case .deleteItem: - return false - case let .peerItem(index, _, _, _, _, _, _, _): - switch rhs { - case .deleteItem: - return true - case let .peerItem(rhsIndex, _, _, _, _, _, _, _): - return index < rhsIndex - case .addItem, .headerItem: - return false - } - case .addItem: - switch rhs { - case .peerItem, .deleteItem: - return true - case .headerItem: - return false - default: - return false - } - case .headerItem: return true + case let .peerItem(rhsIndex, _, _, _, _, _): + return index < rhsIndex + case .addItem, .headerItem, .premiumUsersItem: + return false + } + case .premiumUsersItem: + switch rhs { + case .peerItem, .deleteItem: + return true + case .premiumUsersItem, .addItem, .headerItem: + return false + } + case .addItem: + switch rhs { + case .peerItem, .deleteItem, .premiumUsersItem: + return true + case .addItem, .headerItem: + return false + } + case .headerItem: + switch rhs { + case .peerItem, .deleteItem, .premiumUsersItem, .addItem: + return true + case .headerItem: + return false + } } } func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem { let arguments = arguments as! SelectivePrivacyPeersControllerArguments switch self { - case let .peerItem(_, _, strings, dateTimeFormat, nameDisplayOrder, peer, editing, enabled): + case let .premiumUsersItem(editing, enabled): + //TODO:localize + let peer: EnginePeer = .user(TelegramUser( + id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(1)), accessHash: nil, firstName: "Premium Users", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: PresentationDateTimeFormat(), nameDisplayOrder: .firstLast, context: arguments.context, peer: peer, customAvatarIcon: premiumAvatarIcon, presence: nil, text: .none, label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: { + }, setPeerIdWithRevealedOptions: { previousId, id in + arguments.setPeerIdWithRevealedOptions(previousId, id) + }, removePeer: { peerId in + arguments.removePremiumUsers() + }) + case let .peerItem(_, dateTimeFormat, nameDisplayOrder, peer, editing, enabled): var text: ItemListPeerItemText = .none if let group = peer.peer as? TelegramGroup { - text = .text(strings.Conversation_StatusMembers(Int32(group.participantCount)), .secondary) + text = .text(presentationData.strings.Conversation_StatusMembers(Int32(group.participantCount)), .secondary) } else if let channel = peer.peer as? TelegramChannel { if let participantCount = peer.participantCount { - text = .text(strings.Conversation_StatusMembers(Int32(participantCount)), .secondary) + text = .text(presentationData.strings.Conversation_StatusMembers(Int32(participantCount)), .secondary) } else { switch channel.info { case .group: - text = .text(strings.Group_Status, .secondary) + text = .text(presentationData.strings.Group_Status, .secondary) case .broadcast: - text = .text(strings.Channel_Status, .secondary) + text = .text(presentationData.strings.Channel_Status, .secondary) } } } @@ -176,13 +206,13 @@ private enum SelectivePrivacyPeersEntry: ItemListNodeEntry { }, removePeer: { peerId in arguments.removePeer(peerId) }) - case let .addItem(theme, text, editing): - return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.plusIconImage(theme), title: text, sectionId: self.section, height: .compactPeerList, editing: editing, action: { + case let .addItem(text, editing): + return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.plusIconImage(presentationData.theme), title: text, sectionId: self.section, height: .compactPeerList, editing: editing, action: { arguments.addPeer() }) - case let .headerItem(_, text): + case let .headerItem(text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) - case let .deleteItem(_, text): + case let .deleteItem(text): return ItemListActionItem(presentationData: presentationData, title: text, kind: .destructive, alignment: .center, sectionId: self.section, style: .blocks, action: { arguments.deleteAll() }) @@ -191,36 +221,15 @@ private enum SelectivePrivacyPeersEntry: ItemListNodeEntry { } private struct SelectivePrivacyPeersControllerState: Equatable { - let editing: Bool - let peerIdWithRevealedOptions: EnginePeer.Id? + var enableForPremium: Bool + var editing: Bool + var peerIdWithRevealedOptions: EnginePeer.Id? - init() { - self.editing = false - self.peerIdWithRevealedOptions = nil - } - - init(editing: Bool, peerIdWithRevealedOptions: EnginePeer.Id?) { + init(enableForPremium: Bool, editing: Bool, peerIdWithRevealedOptions: EnginePeer.Id?) { + self.enableForPremium = enableForPremium self.editing = editing self.peerIdWithRevealedOptions = peerIdWithRevealedOptions } - - static func ==(lhs: SelectivePrivacyPeersControllerState, rhs: SelectivePrivacyPeersControllerState) -> Bool { - if lhs.editing != rhs.editing { - return false - } - if lhs.peerIdWithRevealedOptions != rhs.peerIdWithRevealedOptions { - return false - } - return true - } - - func withUpdatedEditing(_ editing: Bool) -> SelectivePrivacyPeersControllerState { - return SelectivePrivacyPeersControllerState(editing: editing, peerIdWithRevealedOptions: self.peerIdWithRevealedOptions) - } - - func withUpdatedPeerIdWithRevealedOptions(_ peerIdWithRevealedOptions: EnginePeer.Id?) -> SelectivePrivacyPeersControllerState { - return SelectivePrivacyPeersControllerState(editing: self.editing, peerIdWithRevealedOptions: peerIdWithRevealedOptions) - } } private func selectivePrivacyPeersControllerEntries(presentationData: PresentationData, state: SelectivePrivacyPeersControllerState, peers: [SelectivePrivacyPeer]) -> [SelectivePrivacyPeersEntry] { @@ -232,25 +241,30 @@ private func selectivePrivacyPeersControllerEntries(presentationData: Presentati } else { title = presentationData.strings.Privacy_ExceptionsCount(Int32(peers.count)) } - entries.append(.headerItem(presentationData.theme, title)) - entries.append(.addItem(presentationData.theme, presentationData.strings.Privacy_AddNewPeer, state.editing)) + entries.append(.headerItem(title)) + entries.append(.addItem(presentationData.strings.Privacy_AddNewPeer, state.editing)) + + if state.enableForPremium { + entries.append(.premiumUsersItem(ItemListPeerItemEditing(editable: true, editing: state.editing, revealed: state.peerIdWithRevealedOptions?.id._internalGetInt64Value() == 1), true)) + } var index: Int32 = 0 for peer in peers { - entries.append(.peerItem(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, peer, ItemListPeerItemEditing(editable: true, editing: state.editing, revealed: peer.peer.id == state.peerIdWithRevealedOptions), true)) + entries.append(.peerItem(index, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, peer, ItemListPeerItemEditing(editable: true, editing: state.editing, revealed: peer.peer.id == state.peerIdWithRevealedOptions), true)) index += 1 } if !peers.isEmpty { - entries.append(.deleteItem(presentationData.theme, presentationData.strings.Privacy_Exceptions_DeleteAllExceptions)) + entries.append(.deleteItem(presentationData.strings.Privacy_Exceptions_DeleteAllExceptions)) } return entries } -public func selectivePrivacyPeersController(context: AccountContext, title: String, initialPeers: [EnginePeer.Id: SelectivePrivacyPeer], displayPremiumCategory: Bool, updated: @escaping ([EnginePeer.Id: SelectivePrivacyPeer]) -> Void) -> ViewController { - let statePromise = ValuePromise(SelectivePrivacyPeersControllerState(), ignoreRepeated: true) - let stateValue = Atomic(value: SelectivePrivacyPeersControllerState()) +public func selectivePrivacyPeersController(context: AccountContext, title: String, initialPeers: [EnginePeer.Id: SelectivePrivacyPeer], initialEnableForPremium: Bool, displayPremiumCategory: Bool, updated: @escaping ([EnginePeer.Id: SelectivePrivacyPeer], Bool) -> Void) -> ViewController { + let initialState = SelectivePrivacyPeersControllerState(enableForPremium: initialEnableForPremium, editing: false, peerIdWithRevealedOptions: nil) + let statePromise = ValuePromise(initialState, ignoreRepeated: true) + let stateValue = Atomic(value: initialState) let updateState: ((SelectivePrivacyPeersControllerState) -> SelectivePrivacyPeersControllerState) -> Void = { f in statePromise.set(stateValue.modify { f($0) }) } @@ -273,7 +287,9 @@ public func selectivePrivacyPeersController(context: AccountContext, title: Stri let arguments = SelectivePrivacyPeersControllerArguments(context: context, setPeerIdWithRevealedOptions: { peerId, fromPeerId in updateState { state in if (peerId == nil && fromPeerId == state.peerIdWithRevealedOptions) || (peerId != nil && fromPeerId == nil) { - return state.withUpdatedPeerIdWithRevealedOptions(peerId) + var state = state + state.peerIdWithRevealedOptions = peerId + return state } else { return state } @@ -296,7 +312,7 @@ public func selectivePrivacyPeersController(context: AccountContext, title: Stri for peer in updatedPeers { updatedPeerDict[peer.peer.id] = peer } - updated(updatedPeerDict) + updated(updatedPeerDict, stateValue.with({ $0 }).enableForPremium) if updatedPeerDict.isEmpty { dismissImpl?() @@ -320,11 +336,15 @@ public func selectivePrivacyPeersController(context: AccountContext, title: Stri id: AdditionalCategoryId.premiumUsers.rawValue, icon: generatePremiumCategoryIcon(size: CGSize(width: 40.0, height: 40.0), cornerRadius: 12.0), smallIcon: generatePremiumCategoryIcon(size: CGSize(width: 22.0, height: 22.0), cornerRadius: 6.0), - title: "Premium Users" + title: "Premium Users", + appearance: .option(sectionTitle: "USER TYPES") ) ] } - let selectedCategories = Set() + var selectedCategories = Set() + if stateValue.with({ $0 }).enableForPremium { + selectedCategories.insert(AdditionalCategoryId.premiumUsers.rawValue) + } let controller = context.sharedContext.makeContactMultiselectionController(ContactMultiselectionControllerParams(context: context, mode: .chatSelection(ContactMultiselectionControllerMode.ChatSelection( title: "Add Users", @@ -332,14 +352,19 @@ public func selectivePrivacyPeersController(context: AccountContext, title: Stri selectedChats: Set(), additionalCategories: ContactMultiselectionControllerAdditionalCategories(categories: additionalCategories, selectedCategories: selectedCategories), chatListFilters: nil, - onlyUsers: false + onlyUsers: false, + disableChannels: true )), options: [])) addPeerDisposable.set((controller.result |> take(1) |> deliverOnMainQueue).start(next: { [weak controller] result in var peerIds: [ContactListPeerId] = [] - if case let .result(peerIdsValue, _) = result { + var premiumSelected = false + if case let .result(peerIdsValue, additionalOptionIds) = result { peerIds = peerIdsValue + premiumSelected = additionalOptionIds.contains(AdditionalCategoryId.premiumUsers.rawValue) + } else { + return } let applyPeers: Signal = peersPromise.get() @@ -386,7 +411,13 @@ public func selectivePrivacyPeersController(context: AccountContext, title: Stri for peer in updatedPeers { updatedPeerDict[peer.peer.id] = peer } - updated(updatedPeerDict) + updated(updatedPeerDict, premiumSelected) + + updateState { state in + var state = state + state.enableForPremium = premiumSelected + return state + } return .complete() } @@ -412,8 +443,14 @@ public func selectivePrivacyPeersController(context: AccountContext, title: Stri |> take(1) |> deliverOnMainQueue |> mapToSignal { _ -> Signal in + updateState { state in + var state = state + state.enableForPremium = false + return state + } + peersPromise.set(.single([])) - updated([:]) + updated([:], false) dismissImpl?() @@ -428,6 +465,33 @@ public func selectivePrivacyPeersController(context: AccountContext, title: Stri }) ])]) presentControllerImpl?(actionSheet, nil) + }, removePremiumUsers: { + updateState { state in + var state = state + state.enableForPremium = false + return state + } + let applyPeers: Signal = peersPromise.get() + |> take(1) + |> deliverOnMainQueue + |> mapToSignal { peers -> Signal in + let updatedPeers = peers + peersPromise.set(.single(updatedPeers)) + + var updatedPeerDict: [EnginePeer.Id: SelectivePrivacyPeer] = [:] + for peer in updatedPeers { + updatedPeerDict[peer.peer.id] = peer + } + updated(updatedPeerDict, false) + + if updatedPeerDict.isEmpty && !stateValue.with({ $0 }).enableForPremium { + dismissImpl?() + } + + return .complete() + } + + removePeerDisposable.set(applyPeers.start()) }) var previousPeers: [SelectivePrivacyPeer]? @@ -440,13 +504,17 @@ public func selectivePrivacyPeersController(context: AccountContext, title: Stri if state.editing { rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: true, action: { updateState { state in - return state.withUpdatedEditing(false) + var state = state + state.editing = false + return state } }) } else { rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Edit), style: .regular, enabled: true, action: { updateState { state in - return state.withUpdatedEditing(true) + var state = state + state.editing = true + return state } }) } diff --git a/submodules/TelegramCore/Sources/Settings/PrivacySettings.swift b/submodules/TelegramCore/Sources/Settings/PrivacySettings.swift index bd375d0806..06ca47960a 100644 --- a/submodules/TelegramCore/Sources/Settings/PrivacySettings.swift +++ b/submodules/TelegramCore/Sources/Settings/PrivacySettings.swift @@ -35,8 +35,8 @@ public final class SelectivePrivacyPeer: Equatable { public enum SelectivePrivacySettings: Equatable { case enableEveryone(disableFor: [PeerId: SelectivePrivacyPeer]) - case enableContacts(enableFor: [PeerId: SelectivePrivacyPeer], disableFor: [PeerId: SelectivePrivacyPeer]) - case disableEveryone(enableFor: [PeerId: SelectivePrivacyPeer], enableForCloseFriends: Bool) + case enableContacts(enableFor: [PeerId: SelectivePrivacyPeer], disableFor: [PeerId: SelectivePrivacyPeer], enableForPremium: Bool) + case disableEveryone(enableFor: [PeerId: SelectivePrivacyPeer], enableForCloseFriends: Bool, enableForPremium: Bool) public static func ==(lhs: SelectivePrivacySettings, rhs: SelectivePrivacySettings) -> Bool { switch lhs { @@ -46,14 +46,14 @@ public enum SelectivePrivacySettings: Equatable { } else { return false } - case let .enableContacts(enableFor, disableFor): - if case .enableContacts(enableFor, disableFor) = rhs { + case let .enableContacts(enableFor, disableFor, enableForPremium): + if case .enableContacts(enableFor, disableFor, enableForPremium) = rhs { return true } else { return false } - case let .disableEveryone(enableFor, enableForCloseFriends): - if case .disableEveryone(enableFor, enableForCloseFriends) = rhs { + case let .disableEveryone(enableFor, enableForCloseFriends, enableForPremium): + if case .disableEveryone(enableFor, enableForCloseFriends, enableForPremium) = rhs { return true } else { return false @@ -63,10 +63,10 @@ public enum SelectivePrivacySettings: Equatable { func withEnabledPeers(_ peers: [PeerId: SelectivePrivacyPeer]) -> SelectivePrivacySettings { switch self { - case let .disableEveryone(enableFor, enableForCloseFriends): - return .disableEveryone(enableFor: enableFor.merging(peers, uniquingKeysWith: { lhs, rhs in lhs }), enableForCloseFriends: enableForCloseFriends) - case let .enableContacts(enableFor, disableFor): - return .enableContacts(enableFor: enableFor.merging(peers, uniquingKeysWith: { lhs, rhs in lhs }), disableFor: disableFor) + case let .disableEveryone(enableFor, enableForCloseFriends, enableForPremium): + return .disableEveryone(enableFor: enableFor.merging(peers, uniquingKeysWith: { lhs, rhs in lhs }), enableForCloseFriends: enableForCloseFriends, enableForPremium: enableForPremium) + case let .enableContacts(enableFor, disableFor, enableForPremium): + return .enableContacts(enableFor: enableFor.merging(peers, uniquingKeysWith: { lhs, rhs in lhs }), disableFor: disableFor, enableForPremium: enableForPremium) case .enableEveryone: return self } @@ -76,17 +76,28 @@ public enum SelectivePrivacySettings: Equatable { switch self { case .disableEveryone: return self - case let .enableContacts(enableFor, disableFor): - return .enableContacts(enableFor: enableFor, disableFor: disableFor.merging(peers, uniquingKeysWith: { lhs, rhs in lhs })) + case let .enableContacts(enableFor, disableFor, enableForPremium): + return .enableContacts(enableFor: enableFor, disableFor: disableFor.merging(peers, uniquingKeysWith: { lhs, rhs in lhs }), enableForPremium: enableForPremium) case let .enableEveryone(disableFor): return .enableEveryone(disableFor: disableFor.merging(peers, uniquingKeysWith: { lhs, rhs in lhs })) } } + func withEnableForPremium(_ enableForPremium: Bool) -> SelectivePrivacySettings { + switch self { + case let .disableEveryone(enableFor, enableForCloseFriends, _): + return .disableEveryone(enableFor: enableFor, enableForCloseFriends: enableForCloseFriends, enableForPremium: enableForPremium) + case let .enableContacts(enableFor, disableFor, _): + return .enableContacts(enableFor: enableFor, disableFor: disableFor, enableForPremium: enableForPremium) + case .enableEveryone: + return self + } + } + func withEnableForCloseFriends(_ enableForCloseFriends: Bool) -> SelectivePrivacySettings { switch self { - case let .disableEveryone(enableFor, _): - return .disableEveryone(enableFor: enableFor, enableForCloseFriends: enableForCloseFriends) + case let .disableEveryone(enableFor, _, enableForPremium): + return .disableEveryone(enableFor: enableFor, enableForCloseFriends: enableForCloseFriends, enableForPremium: enableForPremium) case .enableContacts: return self case .enableEveryone: @@ -174,18 +185,19 @@ public struct AccountPrivacySettings: Equatable { extension SelectivePrivacySettings { init(apiRules: [Api.PrivacyRule], peers: [PeerId: SelectivePrivacyPeer]) { - var current: SelectivePrivacySettings = .disableEveryone(enableFor: [:], enableForCloseFriends: false) + var current: SelectivePrivacySettings = .disableEveryone(enableFor: [:], enableForCloseFriends: false, enableForPremium: false) var disableFor: [PeerId: SelectivePrivacyPeer] = [:] var enableFor: [PeerId: SelectivePrivacyPeer] = [:] var enableForCloseFriends: Bool = false + let enableForPremium: Bool = false for rule in apiRules { switch rule { case .privacyValueAllowAll: current = .enableEveryone(disableFor: [:]) case .privacyValueAllowContacts: - current = .enableContacts(enableFor: [:], disableFor: [:]) + current = .enableContacts(enableFor: [:], disableFor: [:], enableForPremium: false) case let .privacyValueAllowUsers(users): for id in users { if let peer = peers[PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id))] { @@ -223,7 +235,7 @@ extension SelectivePrivacySettings { } } - self = current.withEnabledPeers(enableFor).withDisabledPeers(disableFor).withEnableForCloseFriends(enableForCloseFriends) + self = current.withEnabledPeers(enableFor).withDisabledPeers(disableFor).withEnableForCloseFriends(enableForCloseFriends).withEnableForPremium(enableForPremium) } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Privacy/UpdatedAccountPrivacySettings.swift b/submodules/TelegramCore/Sources/TelegramEngine/Privacy/UpdatedAccountPrivacySettings.swift index 87e3c6d59b..deb32f81a4 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Privacy/UpdatedAccountPrivacySettings.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Privacy/UpdatedAccountPrivacySettings.swift @@ -412,7 +412,7 @@ func _internal_updateSelectiveAccountPrivacySettings(account: Account, type: Upd return account.postbox.transaction { transaction -> Signal in var rules: [Api.InputPrivacyRule] = [] switch settings { - case let .disableEveryone(enableFor, enableForCloseFriends): + case let .disableEveryone(enableFor, enableForCloseFriends, enableForPremium): let enablePeers = apiUserAndGroupIds(peerIds: enableFor) if !enablePeers.users.isEmpty { @@ -426,7 +426,8 @@ func _internal_updateSelectiveAccountPrivacySettings(account: Account, type: Upd if enableForCloseFriends { rules.append(.inputPrivacyValueAllowCloseFriends) } - case let .enableContacts(enableFor, disableFor): + let _ = enableForPremium + case let .enableContacts(enableFor, disableFor, enableForPremium): let enablePeers = apiUserAndGroupIds(peerIds: enableFor) let disablePeers = apiUserAndGroupIds(peerIds: disableFor) @@ -445,6 +446,7 @@ func _internal_updateSelectiveAccountPrivacySettings(account: Account, type: Upd } rules.append(Api.InputPrivacyRule.inputPrivacyValueAllowContacts) + let _ = enableForPremium case let .enableEveryone(disableFor): let disablePeers = apiUserAndGroupIds(peerIds: disableFor) diff --git a/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift b/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift index 2294553396..76e1ad28b7 100644 --- a/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift +++ b/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift @@ -311,7 +311,7 @@ final class BusinessIntroSetupScreenComponent: Component { placeholder: "Enter Title", autocapitalizationType: .none, autocorrectionType: .no, - characterLimit: 256, + characterLimit: 32, allowEmptyLines: false, updated: { _ in }, @@ -331,7 +331,7 @@ final class BusinessIntroSetupScreenComponent: Component { placeholder: "Enter Message", autocapitalizationType: .none, autocorrectionType: .no, - characterLimit: 256, + characterLimit: 70, allowEmptyLines: false, updated: { _ in }, diff --git a/submodules/TelegramUI/Images.xcassets/Premium/PremiumIconBackground.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Premium/PremiumIconBackground.imageset/Contents.json new file mode 100644 index 0000000000..5d2b29a449 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/PremiumIconBackground.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Icon.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Premium/PremiumIconBackground.imageset/Icon.png b/submodules/TelegramUI/Images.xcassets/Premium/PremiumIconBackground.imageset/Icon.png new file mode 100644 index 0000000000..3c1a635d77 Binary files /dev/null and b/submodules/TelegramUI/Images.xcassets/Premium/PremiumIconBackground.imageset/Icon.png differ diff --git a/submodules/TelegramUI/Sources/ContactMultiselectionController.swift b/submodules/TelegramUI/Sources/ContactMultiselectionController.swift index 0a086cedf0..ba05f5d38c 100644 --- a/submodules/TelegramUI/Sources/ContactMultiselectionController.swift +++ b/submodules/TelegramUI/Sources/ContactMultiselectionController.swift @@ -190,6 +190,20 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection } private func updateTitle() { + var updatedCount: Int = 0 + switch self.contactsNode.contentNode { + case let .contacts(contactsNode): + if let selectionState = contactsNode.selectionState { + updatedCount = selectionState.selectedPeerIndices.count + } + case let .chats(chatsNode): + chatsNode.updateState { state in + updatedCount = state.selectedPeerIds.count + return state + } + break + } + switch self.mode { case .groupCreation: let maxCount: Int32 = self.limitsConfiguration?.maxSupergroupMemberCount ?? 5000 @@ -204,7 +218,7 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection let rightNavigationButton = UIBarButtonItem(title: self.presentationData.strings.Common_Next, style: .done, target: self, action: #selector(self.rightNavigationButtonPressed)) self.rightNavigationButton = rightNavigationButton self.navigationItem.rightBarButtonItem = self.rightNavigationButton - rightNavigationButton.isEnabled = true //count != 0 || self.params.alwaysEnabled + rightNavigationButton.isEnabled = true case .premiumGifting: let maxCount: Int32 = self.limit ?? 10 var count = 0 @@ -240,6 +254,13 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection self.navigationItem.rightBarButtonItem = self.rightNavigationButton rightNavigationButton.isEnabled = self.params.alwaysEnabled } + + switch self.mode { + case .groupCreation, .peerSelection, .chatSelection: + self.rightNavigationButton?.isEnabled = updatedCount != 0 || !self.contactsNode.editableTokens.isEmpty || self.params.alwaysEnabled + case .channelCreation, .premiumGifting, .requestedUsersSelection: + break + } } override func loadDisplayNode() { @@ -340,31 +361,12 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection } } - if let updatedCount = updatedCount { - switch strongSelf.mode { - case .groupCreation, .peerSelection, .chatSelection: - strongSelf.rightNavigationButton?.isEnabled = updatedCount != 0 || !strongSelf.contactsNode.editableTokens.isEmpty || strongSelf.params.alwaysEnabled - case .channelCreation, .premiumGifting, .requestedUsersSelection: - break - } - - switch strongSelf.mode { - case .groupCreation: - let maxCount: Int32 = strongSelf.limitsConfiguration?.maxSupergroupMemberCount ?? 5000 - strongSelf.titleView.title = CounterContollerTitle(title: strongSelf.presentationData.strings.Compose_NewGroupTitle, counter: "\(updatedCount)/\(maxCount)") - case .premiumGifting: - let maxCount: Int32 = strongSelf.limit ?? 10 - strongSelf.titleView.title = CounterContollerTitle(title: strongSelf.presentationData.strings.Premium_Gift_ContactSelection_Title, counter: "\(updatedCount)/\(maxCount)") - case .requestedUsersSelection: - let maxCount: Int32 = strongSelf.limit ?? 10 - strongSelf.titleView.title = CounterContollerTitle(title: strongSelf.presentationData.strings.RequestPeer_SelectUsers, counter: "\(updatedCount)/\(maxCount)") - case .peerSelection, .channelCreation, .chatSelection: - break - } - } + let _ = updatedCount strongSelf.requestLayout(transition: ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring)) + strongSelf.updateTitle() + if displayCountAlert { strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.CreateGroup_SoftUserLimitAlert, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) } @@ -481,6 +483,8 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection } } strongSelf.requestLayout(transition: ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring)) + + strongSelf.updateTitle() } } @@ -508,6 +512,8 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection } strongSelf.requestLayout(transition: ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring)) } + + strongSelf.updateTitle() } self.contactsNode.additionalCategorySelected = { [weak self] id in @@ -571,6 +577,8 @@ class ContactMultiselectionControllerImpl: ViewController, ContactMultiselection } } strongSelf.requestLayout(transition: ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring)) + + strongSelf.updateTitle() } } self.contactsNode.complete = { [weak self] in diff --git a/submodules/TelegramUI/Sources/ContactMultiselectionControllerNode.swift b/submodules/TelegramUI/Sources/ContactMultiselectionControllerNode.swift index 798de3e5d8..ed094a4bb9 100644 --- a/submodules/TelegramUI/Sources/ContactMultiselectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/ContactMultiselectionControllerNode.swift @@ -140,6 +140,18 @@ final class ContactMultiselectionControllerNode: ASDisplayNode { excludePeers: [], color: nil )) + } else if chatSelection.disableChannels { + chatListFilter = .filter(id: Int32.max, title: "", emoticon: nil, data: ChatListFilterData( + isShared: false, + hasSharedLinks: false, + categories: [.contacts, .nonContacts, .groups, .bots], + excludeMuted: false, + excludeRead: false, + excludeArchived: false, + includePeers: ChatListFilterIncludePeers(), + excludePeers: [], + color: nil + )) } placeholder = placeholderValue @@ -278,7 +290,7 @@ final class ContactMultiselectionControllerNode: ASDisplayNode { } else { searchChatList = true searchGroups = true - searchChannels = true + searchChannels = !chatSelection.disableChannels } globalSearch = false case .premiumGifting, .requestedUsersSelection: diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 8b8ffa67ec..a7d9ac3d04 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -2232,7 +2232,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { let presence = current.presence var disabledFor: [PeerId: SelectivePrivacyPeer] = [:] switch presence { - case let .enableEveryone(disabledForValue), let .enableContacts(_, disabledForValue): + case let .enableEveryone(disabledForValue), let .enableContacts(_, disabledForValue, _): disabledFor = disabledForValue default: break