mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
762c2d0e92
@ -496,8 +496,8 @@ private func channelAdminsControllerEntries(presentationData: PresentationData,
|
||||
|
||||
if !isGroup && peer.hasPermission(.sendSomething) {
|
||||
entries.append(.signMessages(presentationData.theme, presentationData.strings.Channel_SignMessages, signMessagesEnabled, showAuthorProfilesEnabled))
|
||||
entries.append(.showAuthorProfiles(presentationData.theme, presentationData.strings.Channel_ShowAuthors, showAuthorProfilesEnabled, signMessagesEnabled))
|
||||
if signMessagesEnabled {
|
||||
entries.append(.showAuthorProfiles(presentationData.theme, presentationData.strings.Channel_ShowAuthors, showAuthorProfilesEnabled, signMessagesEnabled))
|
||||
entries.append(.signMessagesInfo(presentationData.theme, presentationData.strings.Channel_ShowAuthorsFooter))
|
||||
}
|
||||
}
|
||||
|
@ -742,11 +742,16 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
|
||||
if messageNamespace != Namespaces.Message.ScheduledLocal && messageNamespace != Namespaces.Message.QuickReplyLocal {
|
||||
attributes.append(ViewCountMessageAttribute(count: 1))
|
||||
}
|
||||
if info.flags.contains(.messagesShouldHaveSignatures) {
|
||||
attributes.append(AuthorSignatureMessageAttribute(signature: accountPeer.debugDisplayTitle))
|
||||
}
|
||||
if info.flags.contains(.messagesShouldHaveProfiles) {
|
||||
authorId = account.peerId
|
||||
if sendAsPeer == nil {
|
||||
authorId = account.peerId
|
||||
}
|
||||
}
|
||||
if info.flags.contains(.messagesShouldHaveSignatures) {
|
||||
if let sendAsPeer, sendAsPeer.id == peerId {
|
||||
} else {
|
||||
attributes.append(AuthorSignatureMessageAttribute(signature: accountPeer.debugDisplayTitle))
|
||||
}
|
||||
}
|
||||
case .group:
|
||||
break
|
||||
|
@ -292,6 +292,11 @@ public final class AccountStateManager {
|
||||
return self.botPreviewUpdatesPipe.signal()
|
||||
}
|
||||
|
||||
fileprivate let forceSendPendingStarsReactionPipe = ValuePipe<MessageId>()
|
||||
public var forceSendPendingStarsReaction: Signal<MessageId, NoError> {
|
||||
return self.forceSendPendingStarsReactionPipe.signal()
|
||||
}
|
||||
|
||||
private var updatedWebpageContexts: [MediaId: UpdatedWebpageSubscriberContext] = [:]
|
||||
private var updatedPeersNearbyContext = UpdatedPeersNearbySubscriberContext()
|
||||
private var updatedRevenueBalancesContext = UpdatedRevenueBalancesSubscriberContext()
|
||||
@ -1873,11 +1878,25 @@ public final class AccountStateManager {
|
||||
}
|
||||
}
|
||||
|
||||
var forceSendPendingStarsReaction: Signal<MessageId, NoError> {
|
||||
return self.impl.signalWith { impl, subscriber in
|
||||
return impl.forceSendPendingStarsReaction.start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion)
|
||||
}
|
||||
}
|
||||
|
||||
func forceSendPendingStarsReaction(messageId: MessageId) {
|
||||
self.impl.with { impl in
|
||||
impl.forceSendPendingStarsReactionPipe.putNext(messageId)
|
||||
}
|
||||
}
|
||||
|
||||
var updateConfigRequested: (() -> Void)?
|
||||
var isPremiumUpdated: (() -> Void)?
|
||||
|
||||
let messagesRemovedContext = MessagesRemovedContext()
|
||||
|
||||
public weak var starsContext: StarsContext?
|
||||
|
||||
init(
|
||||
accountPeerId: PeerId,
|
||||
accountManager: AccountManager<TelegramAccountManagerTypes>,
|
||||
|
@ -220,6 +220,12 @@ func cancelPendingSendStarsReactionInteractively(account: Account, messageId: Me
|
||||
|> ignoreValues
|
||||
}
|
||||
|
||||
func _internal_forceSendPendingSendStarsReaction(account: Account, messageId: MessageId) -> Signal<Never, NoError> {
|
||||
account.stateManager.forceSendPendingStarsReaction(messageId: messageId)
|
||||
|
||||
return .complete()
|
||||
}
|
||||
|
||||
func _internal_updateStarsReactionIsAnonymous(account: Account, messageId: MessageId, isAnonymous: Bool) -> Signal<Never, NoError> {
|
||||
return account.postbox.transaction { transaction -> Api.InputPeer? in
|
||||
transaction.updateMessage(messageId, update: { currentMessage in
|
||||
@ -388,6 +394,9 @@ private func requestSendStarsReaction(postbox: Postbox, network: Network, stateM
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Never, RequestUpdateMessageReactionError> in
|
||||
stateManager.starsContext?.add(balance: Int64(-count), addTransaction: false)
|
||||
//stateManager.starsContext?.load(force: true)
|
||||
|
||||
return postbox.transaction { transaction -> Void in
|
||||
transaction.setPendingMessageAction(type: .sendStarsReaction, id: messageId, action: UpdateMessageReactionsAction())
|
||||
transaction.updateMessage(messageId, update: { currentMessage in
|
||||
@ -568,8 +577,20 @@ func managedApplyPendingMessageStarsReactionsActions(postbox: Postbox, network:
|
||||
let signal = withTakenStarsAction(postbox: postbox, type: .sendStarsReaction, id: entry.id, { transaction, entry -> Signal<Never, NoError> in
|
||||
if let entry = entry {
|
||||
if let _ = entry.action as? SendStarsReactionsAction {
|
||||
return synchronizeMessageStarsReactions(transaction: transaction, postbox: postbox, network: network, stateManager: stateManager, id: entry.id)
|
||||
|> delay(5.0, queue: .mainQueue())
|
||||
let triggerSignal: Signal<Void, NoError> = stateManager.forceSendPendingStarsReaction
|
||||
|> filter {
|
||||
$0 == entry.id
|
||||
}
|
||||
|> map { _ -> Void in
|
||||
return Void()
|
||||
}
|
||||
|> take(1)
|
||||
|> timeout(5.0, queue: .mainQueue(), alternate: .single(Void()))
|
||||
|
||||
return triggerSignal
|
||||
|> mapToSignal { _ -> Signal<Never, NoError> in
|
||||
return synchronizeMessageStarsReactions(transaction: transaction, postbox: postbox, network: network, stateManager: stateManager, id: entry.id)
|
||||
}
|
||||
} else {
|
||||
assertionFailure()
|
||||
}
|
||||
|
@ -342,6 +342,10 @@ public extension TelegramEngine {
|
||||
let _ = cancelPendingSendStarsReactionInteractively(account: self.account, messageId: id).startStandalone()
|
||||
}
|
||||
|
||||
public func forceSendPendingSendStarsReaction(id: EngineMessage.Id) {
|
||||
let _ = _internal_forceSendPendingSendStarsReaction(account: self.account, messageId: id).startStandalone()
|
||||
}
|
||||
|
||||
public func updateStarsReactionIsAnonymous(id: EngineMessage.Id, isAnonymous: Bool) -> Signal<Never, NoError> {
|
||||
return _internal_updateStarsReactionIsAnonymous(account: self.account, messageId: id, isAnonymous: isAnonymous)
|
||||
}
|
||||
|
@ -338,14 +338,16 @@ private final class StarsContextImpl {
|
||||
}))
|
||||
}
|
||||
|
||||
func add(balance: Int64) {
|
||||
func add(balance: Int64, addTransaction: Bool) {
|
||||
guard let state = self._state else {
|
||||
return
|
||||
}
|
||||
var transactions = state.transactions
|
||||
transactions.insert(.init(flags: [.isLocal], id: "\(arc4random())", count: balance, date: Int32(Date().timeIntervalSince1970), peer: .appStore, title: nil, description: nil, photo: nil, transactionDate: nil, transactionUrl: nil, paidMessageId: nil, media: [], subscriptionPeriod: nil), at: 0)
|
||||
if addTransaction {
|
||||
transactions.insert(.init(flags: [.isLocal], id: "\(arc4random())", count: balance, date: Int32(Date().timeIntervalSince1970), peer: .appStore, title: nil, description: nil, photo: nil, transactionDate: nil, transactionUrl: nil, paidMessageId: nil, media: [], subscriptionPeriod: nil), at: 0)
|
||||
}
|
||||
|
||||
self.updateState(StarsContext.State(flags: [.isPendingBalance], balance: state.balance + balance, subscriptions: state.subscriptions, canLoadMoreSubscriptions: state.canLoadMoreSubscriptions, transactions: transactions, canLoadMoreTransactions: state.canLoadMoreTransactions, isLoading: state.isLoading))
|
||||
self.updateState(StarsContext.State(flags: [.isPendingBalance], balance: max(0, state.balance + balance), subscriptions: state.subscriptions, canLoadMoreSubscriptions: state.canLoadMoreSubscriptions, transactions: transactions, canLoadMoreTransactions: state.canLoadMoreTransactions, isLoading: state.isLoading))
|
||||
}
|
||||
|
||||
fileprivate func updateBalance(_ balance: Int64, transactions: [StarsContext.State.Transaction]?) {
|
||||
@ -696,9 +698,9 @@ public final class StarsContext {
|
||||
return state
|
||||
}
|
||||
|
||||
public func add(balance: Int64) {
|
||||
public func add(balance: Int64, addTransaction: Bool = true) {
|
||||
self.impl.with {
|
||||
$0.add(balance: balance)
|
||||
$0.add(balance: balance, addTransaction: addTransaction)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,10 +344,8 @@ public extension Message {
|
||||
return false
|
||||
}
|
||||
} else if self.author?.id == accountPeerId {
|
||||
if let channel = self.peers[self.id.peerId] as? TelegramChannel, case let .broadcast(info) = channel.info {
|
||||
if !info.flags.contains(.messagesShouldHaveProfiles) {
|
||||
return true
|
||||
}
|
||||
if let channel = self.peers[self.id.peerId] as? TelegramChannel, case .broadcast = channel.info {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
} else if self.flags.contains(.Incoming) {
|
||||
|
@ -958,6 +958,7 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
|
||||
private var topOffsetDistance: CGFloat?
|
||||
|
||||
private var balance: Int64?
|
||||
private var amount: Int64 = 1
|
||||
private var isAnonymous: Bool = false
|
||||
private var cachedStarImage: (UIImage, PresentationTheme)?
|
||||
@ -965,6 +966,8 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
|
||||
private var isPastTopCutoff: Bool?
|
||||
|
||||
private var balanceDisposable: Disposable?
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.bottomOverscrollLimit = 200.0
|
||||
|
||||
@ -1019,6 +1022,10 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.balanceDisposable?.dispose()
|
||||
}
|
||||
|
||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
if !self.ignoreScrolling {
|
||||
self.updateScrolling(transition: .immediate)
|
||||
@ -1127,10 +1134,26 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
let sideInset: CGFloat = 16.0
|
||||
|
||||
if self.component == nil {
|
||||
self.balance = component.balance
|
||||
self.amount = 50
|
||||
if let myTopPeer = component.myTopPeer {
|
||||
self.isAnonymous = myTopPeer.isAnonymous
|
||||
}
|
||||
|
||||
if let starsContext = component.context.starsContext {
|
||||
self.balanceDisposable = (starsContext.state
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] state in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if let state {
|
||||
if self.balance != state.balance {
|
||||
self.balance = state.balance
|
||||
self.state?.updated(transition: .immediate)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
self.component = component
|
||||
@ -1335,7 +1358,7 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
context: component.context,
|
||||
theme: environment.theme,
|
||||
strings: environment.strings,
|
||||
balance: component.balance
|
||||
balance: self.balance
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 120.0, height: 100.0)
|
||||
@ -1751,7 +1774,7 @@ private final class ChatSendStarsScreenComponent: Component {
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
}
|
||||
guard let balance = component.balance else {
|
||||
guard let balance = self.balance else {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ swift_library(
|
||||
"//submodules/AsyncDisplayKit",
|
||||
"//submodules/ComponentFlow",
|
||||
"//submodules/TelegramUI/Components/SpaceWarpView/STCMeshView",
|
||||
"//submodules/UIKitRuntimeUtils",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -4,6 +4,7 @@ import Display
|
||||
import AsyncDisplayKit
|
||||
import ComponentFlow
|
||||
import STCMeshView
|
||||
import UIKitRuntimeUtils
|
||||
|
||||
private final class FPSView: UIView {
|
||||
private var lastTimestamp: Double?
|
||||
@ -327,6 +328,49 @@ private final class MaskGridLayer: SimpleLayer {
|
||||
}
|
||||
}
|
||||
|
||||
private final class PrivateContentLayerRestoreContext {
|
||||
final class Reference {
|
||||
weak var layer: CALayer?
|
||||
|
||||
init(layer: CALayer) {
|
||||
self.layer = layer
|
||||
}
|
||||
}
|
||||
|
||||
private static func collectPrivateContentLayers(layer: CALayer, into references: inout [Reference]) {
|
||||
if getLayerDisableScreenshots(layer) {
|
||||
references.append(Reference(layer: layer))
|
||||
}
|
||||
if let sublayers = layer.sublayers {
|
||||
for sublayer in sublayers {
|
||||
collectPrivateContentLayers(layer: sublayer, into: &references)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let references: [Reference]
|
||||
|
||||
init(rootLayer: CALayer) {
|
||||
var references: [Reference] = []
|
||||
PrivateContentLayerRestoreContext.collectPrivateContentLayers(layer: rootLayer, into: &references)
|
||||
self.references = references
|
||||
|
||||
for reference in self.references {
|
||||
if let layer = reference.layer {
|
||||
setLayerDisableScreenshots(layer, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func restore() {
|
||||
for reference in self.references {
|
||||
if let layer = reference.layer {
|
||||
setLayerDisableScreenshots(layer, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class SpaceWarpNodeImpl: ASDisplayNode, SpaceWarpNode {
|
||||
private final class Shockwave {
|
||||
let startPoint: CGPoint
|
||||
@ -346,6 +390,8 @@ open class SpaceWarpNodeImpl: ASDisplayNode, SpaceWarpNode {
|
||||
private var currentCloneView: UIView?
|
||||
private var meshView: STCMeshView?
|
||||
|
||||
private var privateContentRestoreContext: PrivateContentLayerRestoreContext?
|
||||
|
||||
private var gradientLayer: SimpleGradientLayer?
|
||||
private var gradientMaskLayer: MaskGridLayer?
|
||||
|
||||
@ -382,7 +428,25 @@ open class SpaceWarpNodeImpl: ASDisplayNode, SpaceWarpNode {
|
||||
#endif
|
||||
}
|
||||
|
||||
public static func supportsHierarchy(layer: CALayer) -> Bool {
|
||||
if getLayerDisableScreenshots(layer) {
|
||||
return false
|
||||
}
|
||||
if let sublayers = layer.sublayers {
|
||||
for sublayer in sublayers {
|
||||
if !supportsHierarchy(layer: sublayer) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
public func triggerRipple(at point: CGPoint) {
|
||||
if !SpaceWarpNodeImpl.supportsHierarchy(layer: self.contentNodeSource.view.layer) {
|
||||
return
|
||||
}
|
||||
|
||||
self.shockwaves.append(Shockwave(startPoint: point))
|
||||
if self.shockwaves.count > 8 {
|
||||
self.shockwaves.removeFirst()
|
||||
@ -480,9 +544,18 @@ open class SpaceWarpNodeImpl: ASDisplayNode, SpaceWarpNode {
|
||||
gradientMaskLayer.removeFromSuperlayer()
|
||||
}
|
||||
|
||||
if let privateContentRestoreContext = self.privateContentRestoreContext {
|
||||
self.privateContentRestoreContext = nil
|
||||
privateContentRestoreContext.restore()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if self.privateContentRestoreContext == nil {
|
||||
self.privateContentRestoreContext = PrivateContentLayerRestoreContext(rootLayer: self.contentNodeSource.view.layer)
|
||||
}
|
||||
|
||||
self.backgroundView.isHidden = false
|
||||
self.contentNodeSource.clipsToBounds = true
|
||||
self.contentNodeSource.layer.cornerRadius = cornerRadius
|
||||
|
@ -304,6 +304,8 @@ public final class AccountContextImpl: AccountContext {
|
||||
self.starsContext = nil
|
||||
}
|
||||
|
||||
self.account.stateManager.starsContext = self.starsContext
|
||||
|
||||
if let locationManager = self.sharedContextImpl.locationManager, sharedContext.applicationBindings.isMainApp && !temp {
|
||||
self.peersNearbyManager = PeersNearbyManagerImpl(account: account, engine: self.engine, locationManager: locationManager, inForeground: sharedContext.applicationBindings.applicationInForeground)
|
||||
} else {
|
||||
|
@ -294,6 +294,24 @@ extension ChatControllerImpl {
|
||||
if !hasAnonymousPeer {
|
||||
allPeers?.insert(SendAsPeer(peer: channel, subscribers: 0, isPremiumRequired: false), at: 0)
|
||||
}
|
||||
} else if let channel = peerViewMainPeer(peerView) as? TelegramChannel, case let .broadcast(info) = channel.info, info.flags.contains(.messagesShouldHaveProfiles) {
|
||||
allPeers = peers
|
||||
|
||||
var hasAnonymousPeer = false
|
||||
var hasSelfPeer = false
|
||||
for peer in peers {
|
||||
if peer.peer.id == channel.id {
|
||||
hasAnonymousPeer = true
|
||||
} else if peer.peer.id == strongSelf.context.account.peerId {
|
||||
hasSelfPeer = true
|
||||
}
|
||||
}
|
||||
if !hasSelfPeer {
|
||||
allPeers?.insert(currentAccountPeer, at: 0)
|
||||
}
|
||||
if !hasAnonymousPeer {
|
||||
allPeers?.insert(SendAsPeer(peer: channel, subscribers: 0, isPremiumRequired: false), at: 0)
|
||||
}
|
||||
} else {
|
||||
allPeers = peers.filter { $0.peer.id != peerViewMainPeer(peerView)?.id }
|
||||
allPeers?.insert(currentAccountPeer, at: 0)
|
||||
@ -3978,6 +3996,8 @@ extension ChatControllerImpl {
|
||||
let defaultMyPeerId: PeerId
|
||||
if let channel = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramChannel, case .group = channel.info, channel.hasPermission(.canBeAnonymous) {
|
||||
defaultMyPeerId = channel.id
|
||||
} else if let channel = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramChannel, case let .broadcast(info) = channel.info, info.flags.contains(.messagesShouldHaveProfiles) {
|
||||
defaultMyPeerId = channel.id
|
||||
} else {
|
||||
defaultMyPeerId = strongSelf.context.account.peerId
|
||||
}
|
||||
|
@ -369,6 +369,12 @@ extension ChatControllerImpl {
|
||||
}
|
||||
|
||||
func openMessageSendStarsScreen(message: Message) {
|
||||
if let current = self.currentSendStarsUndoController {
|
||||
self.currentSendStarsUndoController = nil
|
||||
current.dismiss()
|
||||
}
|
||||
self.context.engine.messages.forceSendPendingSendStarsReaction(id: message.id)
|
||||
|
||||
let reactionsAttribute = mergedMessageReactions(attributes: message.attributes, isTags: false)
|
||||
let _ = (ChatSendStarsScreen.initialData(context: self.context, peerId: message.id.peerId, messageId: message.id, topPeers: reactionsAttribute?.topPeers ?? [])
|
||||
|> deliverOnMainQueue).start(next: { [weak self] initialData in
|
||||
|
@ -32,4 +32,6 @@ NSObject * _Nullable makeLuminanceToAlphaFilter();
|
||||
NSObject * _Nullable makeMonochromeFilter();
|
||||
|
||||
void setLayerDisableScreenshots(CALayer * _Nonnull layer, bool disableScreenshots);
|
||||
bool getLayerDisableScreenshots(CALayer * _Nonnull layer);
|
||||
|
||||
void setLayerContentsMaskMode(CALayer * _Nonnull layer, bool maskMode);
|
||||
|
@ -1,5 +1,7 @@
|
||||
#import "UIKitUtils.h"
|
||||
|
||||
#import <ObjCRuntimeUtils/RuntimeUtils.h>
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
@ -236,6 +238,7 @@ NSObject * _Nullable makeMonochromeFilter() {
|
||||
return [(id<GraphicsFilterProtocol>)NSClassFromString(@"CAFilter") filterWithName:@"colorMonochrome"];
|
||||
}
|
||||
|
||||
static const void *layerDisableScreenshotsKey = &layerDisableScreenshotsKey;
|
||||
|
||||
void setLayerDisableScreenshots(CALayer * _Nonnull layer, bool disableScreenshots) {
|
||||
static UITextField *textField = nil;
|
||||
@ -264,6 +267,17 @@ void setLayerDisableScreenshots(CALayer * _Nonnull layer, bool disableScreenshot
|
||||
textField.secureTextEntry = false;
|
||||
}
|
||||
[secureView setValue:previousLayer forKey:@"layer"];
|
||||
|
||||
[layer setAssociatedObject:@(disableScreenshots) forKey:layerDisableScreenshotsKey associationPolicy:NSObjectAssociationPolicyRetain];
|
||||
}
|
||||
|
||||
bool getLayerDisableScreenshots(CALayer * _Nonnull layer) {
|
||||
id result = [layer associatedObjectForKey:layerDisableScreenshotsKey];
|
||||
if ([result respondsToSelector:@selector(boolValue)]) {
|
||||
return [(NSNumber *)result boolValue];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void setLayerContentsMaskMode(CALayer * _Nonnull layer, bool maskMode) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user