Privacy settings

This commit is contained in:
Isaac 2024-01-12 22:42:18 +04:00
parent 5b7d4984ac
commit eeba8a7db1
70 changed files with 2586 additions and 521 deletions

View file

@ -20,6 +20,8 @@ import TelegramIntents
import AnimationCache
import MultiAnimationRenderer
import ObjectiveC
import PremiumUI
import UndoUI
private var ObjCKey_DeinitWatcher: Int?
@ -356,6 +358,7 @@ public protocol ShareControllerAccountContext: AnyObject {
var accountId: AccountRecordId { get }
var accountPeerId: EnginePeer.Id { get }
var stateManager: AccountStateManager { get }
var engineData: TelegramEngine.EngineData { get }
var animationCache: AnimationCache { get }
var animationRenderer: MultiAnimationRenderer { get }
var contentSettings: ContentSettings { get }
@ -376,6 +379,9 @@ public final class ShareControllerAppAccountContext: ShareControllerAccountConte
public var stateManager: AccountStateManager {
return self.context.account.stateManager
}
public var engineData: TelegramEngine.EngineData {
return self.context.engine.data
}
public var animationCache: AnimationCache {
return self.context.animationCache
}
@ -446,7 +452,7 @@ public final class ShareController: ViewController {
private let segmentedValues: [ShareControllerSegmentedValue]?
private let fromForeignApp: Bool
private let peers = Promise<([(EngineRenderedPeer, EnginePeer.Presence?)], EnginePeer)>()
private let peers = Promise<([(peer: EngineRenderedPeer, presence: EnginePeer.Presence?, requiresPremiumForMessaging: Bool)], EnginePeer)>()
private let peersDisposable = MetaDisposable()
private let readyDisposable = MetaDisposable()
private let accountActiveDisposable = MetaDisposable()
@ -470,6 +476,8 @@ public final class ShareController: ViewController {
public var debugAction: (() -> Void)?
public var parentNavigationController: NavigationController?
public convenience init(context: AccountContext, subject: ShareControllerSubject, presetText: String? = nil, preferredAction: ShareControllerPreferredAction = .default, showInChat: ((Message) -> Void)? = nil, fromForeignApp: Bool = false, segmentedValues: [ShareControllerSegmentedValue]? = nil, externalShare: Bool = true, immediateExternalShare: Bool = false, switchableAccounts: [AccountWithInfo] = [], immediatePeerId: PeerId? = nil, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, forceTheme: PresentationTheme? = nil, forcedActionTitle: String? = nil, shareAsLink: Bool = false) {
self.init(
environment: ShareControllerAppEnvironment(sharedContext: context.sharedContext),
@ -515,6 +523,7 @@ public final class ShareController: ViewController {
super.init(navigationBarPresentationData: nil)
self.statusBar.statusBarStyle = .Ignore
self.automaticallyControlPresentationContextLayout = false
switch subject {
case let .url(text):
@ -695,7 +704,7 @@ public final class ShareController: ViewController {
fromPublicChannel = true
}
self.displayNode = ShareControllerNode(environment: self.environment, presentationData: self.presentationData, presetText: self.presetText, defaultAction: self.defaultAction, requestLayout: { [weak self] transition in
self.displayNode = ShareControllerNode(controller: self, environment: self.environment, presentationData: self.presentationData, presetText: self.presetText, defaultAction: self.defaultAction, requestLayout: { [weak self] transition in
self?.requestLayout(transition: transition)
}, presentError: { [weak self] title, text in
guard let strongSelf = self else {
@ -1197,6 +1206,31 @@ public final class ShareController: ViewController {
strongSelf.view.endEditing(true)
strongSelf.present(controller, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}
self.controllerNode.disabledPeerSelected = { [weak self] peer in
guard let self else {
return
}
self.forEachController { c in
if let c = c as? UndoOverlayController {
c.dismiss()
}
return true
}
//TODO:localize
self.present(UndoOverlayController(presentationData: presentationData, content: .premiumPaywall(title: nil, text: "**\(peer.compactDisplayTitle)** only accepts messages from contacts and **Premium** users.", customUndoText: (self.environment is ShareControllerAppEnvironment) ? "View" : nil, timeout: nil, linkAction: { _ in
}), elevatedLayout: false, animateInAsReplacement: false, action: { [weak self] action in
guard let self, let parentNavigationController = self.parentNavigationController, let context = self.currentContext as? ShareControllerAppAccountContext else {
return false
}
if case .undo = action {
self.controllerNode.cancel?()
let premiumController = PremiumIntroScreen(context: context.context, source: .settings)
parentNavigationController.pushViewController(premiumController)
}
return false
}), in: .current)
}
self.controllerNode.debugAction = { [weak self] in
self?.debugAction?()
}
@ -2416,36 +2450,56 @@ public final class ShareController: ViewController {
peer,
tailChatList |> take(1)
)
|> mapToSignal { maybeAccountPeer, view -> Signal<([(EngineRenderedPeer, EnginePeer.Presence?)], EnginePeer), NoError> in
|> mapToSignal { maybeAccountPeer, view -> Signal<([(peer: EngineRenderedPeer, presence: EnginePeer.Presence?, requiresPremiumForMessaging: Bool)], EnginePeer), NoError> in
let accountPeer = maybeAccountPeer!
var peers: [EngineRenderedPeer] = []
var possiblePremiumRequiredPeers = Set<EnginePeer.Id>()
for entry in view.0.entries.reversed() {
switch entry {
case let .MessageEntry(entryData):
if let peer = entryData.renderedPeer.peers[entryData.renderedPeer.peerId], peer.id != accountPeer.id, canSendMessagesToPeer(peer) {
peers.append(EngineRenderedPeer(entryData.renderedPeer))
case let .MessageEntry(entryData):
if let peer = entryData.renderedPeer.peers[entryData.renderedPeer.peerId], peer.id != accountPeer.id, canSendMessagesToPeer(peer) {
peers.append(EngineRenderedPeer(entryData.renderedPeer))
if let user = peer as? TelegramUser, user.flags.contains(.requirePremium) {
possiblePremiumRequiredPeers.insert(user.id)
}
default:
break
}
default:
break
}
}
let key = PostboxViewKey.peerPresences(peerIds: Set(peers.map(\.peerId)))
return account.stateManager.postbox.combinedView(keys: [key])
|> map { views -> [EnginePeer.Id: EnginePeer.Presence?] in
let peerPresencesKey = PostboxViewKey.peerPresences(peerIds: Set(peers.map(\.peerId)))
var keys: [PostboxViewKey] = []
keys.append(peerPresencesKey)
for id in possiblePremiumRequiredPeers {
keys.append(.cachedPeerData(peerId: id))
}
return account.stateManager.postbox.combinedView(keys: keys)
|> map { views -> ([EnginePeer.Id: EnginePeer.Presence?], [EnginePeer.Id: Bool]) in
var result: [EnginePeer.Id: EnginePeer.Presence?] = [:]
if let view = views.views[key] as? PeerPresencesView {
if let view = views.views[peerPresencesKey] as? PeerPresencesView {
result = view.presences.mapValues { value -> EnginePeer.Presence? in
return EnginePeer.Presence(value)
}
}
return result
var requiresPremiumForMessaging: [EnginePeer.Id: Bool] = [:]
for id in possiblePremiumRequiredPeers {
if let view = views.views[.cachedPeerData(peerId: id)] as? CachedPeerDataView, let data = view.cachedPeerData as? CachedUserData {
requiresPremiumForMessaging[id] = data.flags.contains(.premiumRequired)
} else {
requiresPremiumForMessaging[id] = false
}
}
return (result, requiresPremiumForMessaging)
}
|> map { presenceMap -> ([(EngineRenderedPeer, EnginePeer.Presence?)], EnginePeer) in
var resultPeers: [(EngineRenderedPeer, EnginePeer.Presence?)] = []
|> map { presenceMap, requiresPremiumForMessaging -> ([(peer: EngineRenderedPeer, presence: EnginePeer.Presence?, requiresPremiumForMessaging: Bool)], EnginePeer) in
var resultPeers: [(peer: EngineRenderedPeer, presence: EnginePeer.Presence?, requiresPremiumForMessaging: Bool)] = []
for peer in peers {
resultPeers.append((peer, presenceMap[peer.peerId].flatMap { $0 }))
resultPeers.append((peer, presenceMap[peer.peerId].flatMap { $0 }, requiresPremiumForMessaging[peer.peerId] ?? false))
}
return (resultPeers, accountPeer)
}