UI optimizations

This commit is contained in:
Ali 2023-02-18 00:05:50 +04:00
parent 1acde55d24
commit 8735edc6fb
15 changed files with 263 additions and 68 deletions

View File

@ -383,8 +383,41 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
private let waitingForNodesDisposable = MetaDisposable() private let waitingForNodesDisposable = MetaDisposable()
private var auxiliaryDisplayLink: CADisplayLink? private var auxiliaryDisplayLink: CADisplayLink?
private var auxiliaryDisplayLinkHandle: SharedDisplayLinkDriver.Link?
private var debugView: UIView?
private var isAuxiliaryDisplayLinkEnabled: Bool = false { private var isAuxiliaryDisplayLinkEnabled: Bool = false {
didSet { didSet {
if self.isAuxiliaryDisplayLinkEnabled {
if self.auxiliaryDisplayLinkHandle == nil {
self.auxiliaryDisplayLinkHandle = SharedDisplayLinkDriver.shared.add(needsHighestFramerate: true, { [weak self] in
guard let self else {
return
}
if self.debugView == nil {
let debugView = UIView(frame: CGRect(origin: CGPoint(), size: CGSize(width: 1.0, height: 1.0)))
debugView.backgroundColor = .black
debugView.alpha = 0.0001
self.debugView = debugView
self.view.addSubview(debugView)
}
if let debugView = self.debugView {
if debugView.frame.origin.x == 0.0 {
debugView.frame = CGRect(origin: CGPoint(x: 1.0, y: 0.0), size: CGSize(width: 1.0, height: 1.0))
} else {
debugView.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: 1.0, height: 1.0))
}
}
})
}
} else if let auxiliaryDisplayLinkHandle = self.auxiliaryDisplayLinkHandle {
self.auxiliaryDisplayLinkHandle = nil
auxiliaryDisplayLinkHandle.invalidate()
if let debugView = self.debugView {
self.debugView = nil
debugView.removeFromSuperview()
}
}
/*if self.isAuxiliaryDisplayLinkEnabled != oldValue { /*if self.isAuxiliaryDisplayLinkEnabled != oldValue {
if self.isAuxiliaryDisplayLinkEnabled { if self.isAuxiliaryDisplayLinkEnabled {
if self.auxiliaryDisplayLink == nil { if self.auxiliaryDisplayLink == nil {

View File

@ -1513,6 +1513,8 @@ open class TextNode: ASDisplayNode {
var fixDoubleEmoji = false var fixDoubleEmoji = false
if glyphCount == 2, let font = attributes["NSFont"] as? UIFont, font.fontName.contains("ColorEmoji"), let string = layout.attributedString { if glyphCount == 2, let font = attributes["NSFont"] as? UIFont, font.fontName.contains("ColorEmoji"), let string = layout.attributedString {
let range = CTRunGetStringRange(run) let range = CTRunGetStringRange(run)
if range.location < string.length && (range.location + range.length) < string.length {
let substring = string.attributedSubstring(from: NSMakeRange(range.location, range.length)).string let substring = string.attributedSubstring(from: NSMakeRange(range.location, range.length)).string
let heart = Unicode.Scalar(0x2764)! let heart = Unicode.Scalar(0x2764)!
@ -1527,6 +1529,7 @@ open class TextNode: ASDisplayNode {
fixDoubleEmoji = true fixDoubleEmoji = true
} }
} }
}
if fixDoubleEmoji { if fixDoubleEmoji {
context.setBlendMode(.normal) context.setBlendMode(.normal)

View File

@ -265,16 +265,15 @@ final class ChatListTable: Table {
} }
} }
func getUnreadChatListPeerIds(postbox: PostboxImpl, currentTransaction: Transaction, groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?) -> [PeerId] { func getUnreadChatListPeerIds(postbox: PostboxImpl, currentTransaction: Transaction, groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?, additionalFilter: ((Peer) -> Bool)?, stopOnFirstMatch: Bool) -> [PeerId] {
let globalNotificationSettings = postbox.getGlobalNotificationSettings(transaction: currentTransaction) let globalNotificationSettings = postbox.getGlobalNotificationSettings(transaction: currentTransaction)
var result: [PeerId] = [] var result: [PeerId] = []
self.valueBox.range(self.table, start: self.upperBound(groupId: groupId), end: self.lowerBound(groupId: groupId), keys: { key in self.valueBox.range(self.table, start: self.upperBound(groupId: groupId), end: self.lowerBound(groupId: groupId), keys: { key in
let (_, _, messageIndex, _) = extractKey(key) let (_, _, messageIndex, _) = extractKey(key)
if let state = postbox.readStateTable.getCombinedState(messageIndex.id.peerId), state.isUnread { if let state = postbox.readStateTable.getCombinedState(messageIndex.id.peerId), state.isUnread, let peer = postbox.peerTable.get(messageIndex.id.peerId) {
let passFilter: Bool var passFilter: Bool
if let filterPredicate = filterPredicate { if let filterPredicate = filterPredicate {
if let peer = postbox.peerTable.get(messageIndex.id.peerId) {
let isUnread = postbox.readStateTable.getCombinedState(messageIndex.id.peerId)?.isUnread ?? false let isUnread = postbox.readStateTable.getCombinedState(messageIndex.id.peerId)?.isUnread ?? false
let isContact = postbox.contactsTable.isContact(peerId: messageIndex.id.peerId) let isContact = postbox.contactsTable.isContact(peerId: messageIndex.id.peerId)
@ -290,14 +289,20 @@ final class ChatListTable: Table {
passFilter = false passFilter = false
} }
} else { } else {
passFilter = true
}
if passFilter, let additionalFilter = additionalFilter {
if !additionalFilter(peer) {
passFilter = false passFilter = false
} }
} else {
passFilter = true
} }
if passFilter { if passFilter {
result.append(messageIndex.id.peerId) result.append(messageIndex.id.peerId)
if stopOnFirstMatch {
return false
}
} }
} }
return true return true

View File

@ -389,10 +389,10 @@ public final class Transaction {
return self.postbox?.chatListTable.getPeerChatListIndex(peerId: peerId) return self.postbox?.chatListTable.getPeerChatListIndex(peerId: peerId)
} }
public func getUnreadChatListPeerIds(groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?) -> [PeerId] { public func getUnreadChatListPeerIds(groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?, additionalFilter: ((Peer) -> Bool)?, stopOnFirstMatch: Bool) -> [PeerId] {
assert(!self.disposed) assert(!self.disposed)
if let postbox = self.postbox { if let postbox = self.postbox {
return postbox.chatListTable.getUnreadChatListPeerIds(postbox: postbox, currentTransaction: self, groupId: groupId, filterPredicate: filterPredicate) return postbox.chatListTable.getUnreadChatListPeerIds(postbox: postbox, currentTransaction: self, groupId: groupId, filterPredicate: filterPredicate, additionalFilter: additionalFilter, stopOnFirstMatch: stopOnFirstMatch)
} else { } else {
return [] return []
} }
@ -1564,7 +1564,7 @@ final class PostboxImpl {
var installedMessageActionsByPeerId: [PeerId: Bag<([StoreMessage], Transaction) -> Void>] = [:] var installedMessageActionsByPeerId: [PeerId: Bag<([StoreMessage], Transaction) -> Void>] = [:]
var installedStoreOrUpdateMessageActionsByPeerId: [PeerId: Bag<StoreOrUpdateMessageAction>] = [:] var installedStoreOrUpdateMessageActionsByPeerId: [PeerId: Bag<StoreOrUpdateMessageAction>] = [:]
init(queue: Queue, basePath: String, seedConfiguration: SeedConfiguration, valueBox: SqliteValueBox, timestampForAbsoluteTimeBasedOperations: Int32, isTemporary: Bool, tempDir: TempBoxDirectory?, useCaches: Bool) { init(queue: Queue, basePath: String, seedConfiguration: SeedConfiguration, valueBox: SqliteValueBox, timestampForAbsoluteTimeBasedOperations: Int32, isTemporary: Bool, tempDir: TempBoxDirectory?, useCaches: Bool, isInTransaction: Atomic<Bool>) {
assert(queue.isCurrent()) assert(queue.isCurrent())
let startTime = CFAbsoluteTimeGetCurrent() let startTime = CFAbsoluteTimeGetCurrent()
@ -1576,6 +1576,8 @@ final class PostboxImpl {
self.valueBox = valueBox self.valueBox = valueBox
self.isInTransaction = isInTransaction
self.metadataTable = MetadataTable(valueBox: self.valueBox, table: MetadataTable.tableSpec(0), useCaches: useCaches) self.metadataTable = MetadataTable(valueBox: self.valueBox, table: MetadataTable.tableSpec(0), useCaches: useCaches)
self.keychainTable = KeychainTable(valueBox: self.valueBox, table: KeychainTable.tableSpec(1), useCaches: useCaches) self.keychainTable = KeychainTable(valueBox: self.valueBox, table: KeychainTable.tableSpec(1), useCaches: useCaches)
@ -2597,7 +2599,7 @@ final class PostboxImpl {
return result return result
} }
private let canBeginTransactionsValue = Atomic<Bool>(value: true) let canBeginTransactionsValue = Atomic<Bool>(value: true)
public func setCanBeginTransactions(_ value: Bool) { public func setCanBeginTransactions(_ value: Bool) {
self.queue.async { self.queue.async {
let previous = self.canBeginTransactionsValue.swap(value) let previous = self.canBeginTransactionsValue.swap(value)
@ -2625,7 +2627,11 @@ final class PostboxImpl {
} }
} }
let isInTransaction: Atomic<Bool>
private func internalTransaction<T>(_ f: (Transaction) -> T) -> (result: T, updatedTransactionStateVersion: Int64?, updatedMasterClientId: Int64?) { private func internalTransaction<T>(_ f: (Transaction) -> T) -> (result: T, updatedTransactionStateVersion: Int64?, updatedMasterClientId: Int64?) {
let _ = self.isInTransaction.swap(true)
self.valueBox.begin() self.valueBox.begin()
let transaction = Transaction(queue: self.queue, postbox: self) let transaction = Transaction(queue: self.queue, postbox: self)
self.afterBegin(transaction: transaction) self.afterBegin(transaction: transaction)
@ -2634,6 +2640,8 @@ final class PostboxImpl {
transaction.disposed = true transaction.disposed = true
self.valueBox.commit() self.valueBox.commit()
let _ = self.isInTransaction.swap(false)
if let currentUpdatedState = self.currentUpdatedState { if let currentUpdatedState = self.currentUpdatedState {
self.statePipe.putNext(currentUpdatedState) self.statePipe.putNext(currentUpdatedState)
} }
@ -3849,6 +3857,8 @@ public class Postbox {
public let seedConfiguration: SeedConfiguration public let seedConfiguration: SeedConfiguration
public let mediaBox: MediaBox public let mediaBox: MediaBox
private let isInTransaction = Atomic<Bool>(value: false)
init( init(
queue: Queue, queue: Queue,
basePath: String, basePath: String,
@ -3866,8 +3876,10 @@ public class Postbox {
postboxLog("MediaBox path: \(basePath + "/media")") postboxLog("MediaBox path: \(basePath + "/media")")
self.mediaBox = MediaBox(basePath: basePath + "/media") self.mediaBox = MediaBox(basePath: basePath + "/media")
let isInTransaction = self.isInTransaction
self.impl = QueueLocalObject(queue: queue, generate: { self.impl = QueueLocalObject(queue: queue, generate: {
return PostboxImpl( let impl = PostboxImpl(
queue: queue, queue: queue,
basePath: basePath, basePath: basePath,
seedConfiguration: seedConfiguration, seedConfiguration: seedConfiguration,
@ -3875,8 +3887,10 @@ public class Postbox {
timestampForAbsoluteTimeBasedOperations: timestampForAbsoluteTimeBasedOperations, timestampForAbsoluteTimeBasedOperations: timestampForAbsoluteTimeBasedOperations,
isTemporary: isTemporary, isTemporary: isTemporary,
tempDir: tempDir, tempDir: tempDir,
useCaches: useCaches useCaches: useCaches,
isInTransaction: isInTransaction
) )
return impl
}) })
} }
@ -3898,6 +3912,12 @@ public class Postbox {
} }
public func setCanBeginTransactions(_ value: Bool) { public func setCanBeginTransactions(_ value: Bool) {
#if DEBUG
if !value {
assert(!self.isInTransaction.with({ $0 }))
}
#endif
self.impl.with { impl in self.impl.with { impl in
impl.setCanBeginTransactions(value) impl.setCanBeginTransactions(value)
} }

View File

@ -235,7 +235,7 @@ public func clearPeerUnseenReactionsInteractively(account: Account, peerId: Peer
} }
func _internal_markAllChatsAsReadInteractively(transaction: Transaction, network: Network, viewTracker: AccountViewTracker, groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?) { func _internal_markAllChatsAsReadInteractively(transaction: Transaction, network: Network, viewTracker: AccountViewTracker, groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?) {
for peerId in transaction.getUnreadChatListPeerIds(groupId: groupId, filterPredicate: filterPredicate) { for peerId in transaction.getUnreadChatListPeerIds(groupId: groupId, filterPredicate: filterPredicate, additionalFilter: nil, stopOnFirstMatch: false) {
_internal_togglePeerUnreadMarkInteractively(transaction: transaction, network: network, viewTracker: viewTracker, peerId: peerId, setToValue: false) _internal_togglePeerUnreadMarkInteractively(transaction: transaction, network: network, viewTracker: viewTracker, peerId: peerId, setToValue: false)
} }
} }

View File

@ -441,7 +441,7 @@ public extension TelegramEngine {
public func unreadChatListPeerIds(groupId: EngineChatList.Group, filterPredicate: ChatListFilterPredicate?) -> Signal<[EnginePeer.Id], NoError> { public func unreadChatListPeerIds(groupId: EngineChatList.Group, filterPredicate: ChatListFilterPredicate?) -> Signal<[EnginePeer.Id], NoError> {
return self.account.postbox.transaction { transaction -> [EnginePeer.Id] in return self.account.postbox.transaction { transaction -> [EnginePeer.Id] in
return transaction.getUnreadChatListPeerIds(groupId: groupId._asGroup(), filterPredicate: filterPredicate) return transaction.getUnreadChatListPeerIds(groupId: groupId._asGroup(), filterPredicate: filterPredicate, additionalFilter: nil, stopOnFirstMatch: false)
} }
} }

View File

@ -632,15 +632,23 @@ public extension TelegramEngine {
public func getNextUnreadChannel(peerId: PeerId, chatListFilterId: Int32?, getFilterPredicate: @escaping (ChatListFilterData) -> ChatListFilterPredicate) -> Signal<(peer: EnginePeer, unreadCount: Int, location: NextUnreadChannelLocation)?, NoError> { public func getNextUnreadChannel(peerId: PeerId, chatListFilterId: Int32?, getFilterPredicate: @escaping (ChatListFilterData) -> ChatListFilterPredicate) -> Signal<(peer: EnginePeer, unreadCount: Int, location: NextUnreadChannelLocation)?, NoError> {
return self.account.postbox.transaction { transaction -> (peer: EnginePeer, unreadCount: Int, location: NextUnreadChannelLocation)? in return self.account.postbox.transaction { transaction -> (peer: EnginePeer, unreadCount: Int, location: NextUnreadChannelLocation)? in
func getForFilter(predicate: ChatListFilterPredicate?, isArchived: Bool) -> (peer: EnginePeer, unreadCount: Int)? { func getForFilter(predicate: ChatListFilterPredicate?, isArchived: Bool) -> (peer: EnginePeer, unreadCount: Int)? {
let additionalFilter: (Peer) -> Bool = { peer in
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
return true
} else {
return false
}
}
var peerIds: [PeerId] = [] var peerIds: [PeerId] = []
if predicate != nil { if predicate != nil {
peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: .root, filterPredicate: predicate)) peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: .root, filterPredicate: predicate, additionalFilter: additionalFilter, stopOnFirstMatch: true))
peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: Namespaces.PeerGroup.archive, filterPredicate: predicate)) peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: Namespaces.PeerGroup.archive, filterPredicate: predicate, additionalFilter: additionalFilter, stopOnFirstMatch: true))
} else { } else {
if isArchived { if isArchived {
peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: Namespaces.PeerGroup.archive, filterPredicate: nil)) peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: Namespaces.PeerGroup.archive, filterPredicate: nil, additionalFilter: additionalFilter, stopOnFirstMatch: true))
} else { } else {
peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: .root, filterPredicate: nil)) peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: .root, filterPredicate: nil, additionalFilter: additionalFilter, stopOnFirstMatch: true))
} }
} }

View File

@ -30,7 +30,7 @@ public func selectReactionFillStaticColor(theme: PresentationTheme, wallpaper: T
public func dateFillNeedsBlur(theme: PresentationTheme, wallpaper: TelegramWallpaper) -> Bool { public func dateFillNeedsBlur(theme: PresentationTheme, wallpaper: TelegramWallpaper) -> Bool {
if !DeviceMetrics.performance.isGraphicallyCapable { if !DeviceMetrics.performance.isGraphicallyCapable {
return false //return false
} }
if case .builtin = wallpaper { if case .builtin = wallpaper {

View File

@ -938,9 +938,11 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
let wakeupManager = SharedWakeupManager(beginBackgroundTask: { name, expiration in let wakeupManager = SharedWakeupManager(beginBackgroundTask: { name, expiration in
let id = application.beginBackgroundTask(withName: name, expirationHandler: expiration) let id = application.beginBackgroundTask(withName: name, expirationHandler: expiration)
Logger.shared.log("App \(self.episodeId)", "Begin background task \(name): \(id)") Logger.shared.log("App \(self.episodeId)", "Begin background task \(name): \(id)")
print("App \(self.episodeId)", "Begin background task \(name): \(id)")
return id return id
}, endBackgroundTask: { id in }, endBackgroundTask: { id in
print("App \(self.episodeId)", "End background task \(id)") print("App \(self.episodeId)", "End background task \(id)")
Logger.shared.log("App \(self.episodeId)", "End background task \(id)")
application.endBackgroundTask(id) application.endBackgroundTask(id)
}, backgroundTimeRemaining: { application.backgroundTimeRemaining }, acquireIdleExtension: { }, backgroundTimeRemaining: { application.backgroundTimeRemaining }, acquireIdleExtension: {
return applicationBindings.pushIdleTimerExtension() return applicationBindings.pushIdleTimerExtension()

View File

@ -4973,6 +4973,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
isRegularChat = true isRegularChat = true
} }
if isRegularChat, strongSelf.nextChannelToReadDisposable == nil { if isRegularChat, strongSelf.nextChannelToReadDisposable == nil {
//TODO:loc optimize
strongSelf.nextChannelToReadDisposable = (combineLatest(queue: .mainQueue(), strongSelf.nextChannelToReadDisposable = (combineLatest(queue: .mainQueue(),
strongSelf.context.engine.peers.getNextUnreadChannel(peerId: channel.id, chatListFilterId: strongSelf.currentChatListFilter, getFilterPredicate: chatListFilterPredicate), strongSelf.context.engine.peers.getNextUnreadChannel(peerId: channel.id, chatListFilterId: strongSelf.currentChatListFilter, getFilterPredicate: chatListFilterPredicate),
ApplicationSpecificNotice.getNextChatSuggestionTip(accountManager: strongSelf.context.sharedContext.accountManager) ApplicationSpecificNotice.getNextChatSuggestionTip(accountManager: strongSelf.context.sharedContext.accountManager)

View File

@ -11,7 +11,8 @@ import WallpaperBackgroundNode
private let titleFont = Font.medium(16.0) private let titleFont = Font.medium(16.0)
private final class ChatMessageActionButtonNode: ASDisplayNode { private final class ChatMessageActionButtonNode: ASDisplayNode {
private let backgroundBlurNode: NavigationBackgroundNode //private let backgroundBlurNode: NavigationBackgroundNode
private var backgroundBlurView: PortalView?
private var titleNode: TextNode? private var titleNode: TextNode?
private var iconNode: ASImageNode? private var iconNode: ASImageNode?
@ -32,15 +33,15 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
private let accessibilityArea: AccessibilityAreaNode private let accessibilityArea: AccessibilityAreaNode
override init() { override init() {
self.backgroundBlurNode = NavigationBackgroundNode(color: .clear) //self.backgroundBlurNode = NavigationBackgroundNode(color: .clear)
self.backgroundBlurNode.isUserInteractionEnabled = false //self.backgroundBlurNode.isUserInteractionEnabled = false
self.accessibilityArea = AccessibilityAreaNode() self.accessibilityArea = AccessibilityAreaNode()
self.accessibilityArea.accessibilityTraits = .button self.accessibilityArea.accessibilityTraits = .button
super.init() super.init()
self.addSubnode(self.backgroundBlurNode) //self.addSubnode(self.backgroundBlurNode)
self.addSubnode(self.accessibilityArea) self.addSubnode(self.accessibilityArea)
self.accessibilityArea.activate = { [weak self] in self.accessibilityArea.activate = { [weak self] in
@ -60,14 +61,24 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
buttonView.highligthedChanged = { [weak self] highlighted in buttonView.highligthedChanged = { [weak self] highlighted in
if let strongSelf = self { if let strongSelf = self {
if highlighted { if highlighted {
strongSelf.backgroundBlurNode.layer.removeAnimation(forKey: "opacity") //strongSelf.backgroundBlurNode.layer.removeAnimation(forKey: "opacity")
strongSelf.backgroundBlurNode.alpha = 0.55 //strongSelf.backgroundBlurNode.alpha = 0.55
if let backgroundBlurView = strongSelf.backgroundBlurView {
backgroundBlurView.view.layer.removeAnimation(forKey: "opacity")
backgroundBlurView.view.alpha = 0.55
}
strongSelf.backgroundContent?.layer.removeAnimation(forKey: "opacity") strongSelf.backgroundContent?.layer.removeAnimation(forKey: "opacity")
strongSelf.backgroundContent?.alpha = 0.55 strongSelf.backgroundContent?.alpha = 0.55
} else { } else {
strongSelf.backgroundBlurNode.alpha = 1.0 //strongSelf.backgroundBlurNode.alpha = 1.0
strongSelf.backgroundBlurNode.layer.animateAlpha(from: 0.55, to: 1.0, duration: 0.2) //strongSelf.backgroundBlurNode.layer.animateAlpha(from: 0.55, to: 1.0, duration: 0.2)
if let backgroundBlurView = strongSelf.backgroundBlurView {
backgroundBlurView.view.alpha = 1.0
backgroundBlurView.view.layer.animateAlpha(from: 0.55, to: 1.0, duration: 0.2)
}
strongSelf.backgroundContent?.alpha = 1.0 strongSelf.backgroundContent?.alpha = 1.0
strongSelf.backgroundContent?.layer.animateAlpha(from: 0.55, to: 1.0, duration: 0.2) strongSelf.backgroundContent?.layer.animateAlpha(from: 0.55, to: 1.0, duration: 0.2)
@ -179,9 +190,20 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
node.longTapRecognizer?.isEnabled = false node.longTapRecognizer?.isEnabled = false
} }
animation.animator.updateFrame(layer: node.backgroundBlurNode.layer, frame: CGRect(origin: CGPoint(), size: CGSize(width: max(0.0, width), height: 42.0)), completion: nil) //animation.animator.updateFrame(layer: node.backgroundBlurNode.layer, frame: CGRect(origin: CGPoint(), size: CGSize(width: max(0.0, width), height: 42.0)), completion: nil)
node.backgroundBlurNode.update(size: node.backgroundBlurNode.bounds.size, cornerRadius: 0.0, animator: animation.animator)
node.backgroundBlurNode.updateColor(color: selectDateFillStaticColor(theme: theme.theme, wallpaper: theme.wallpaper), enableBlur: context.sharedContext.energyUsageSettings.fullTranslucency && dateFillNeedsBlur(theme: theme.theme, wallpaper: theme.wallpaper), transition: .immediate) if node.backgroundBlurView == nil {
if let backgroundBlurView = backgroundNode?.makeFreeBackground() {
node.backgroundBlurView = backgroundBlurView
node.view.insertSubview(backgroundBlurView.view, at: 0)
}
}
if let backgroundBlurView = node.backgroundBlurView {
animation.animator.updateFrame(layer: backgroundBlurView.view.layer, frame: CGRect(origin: CGPoint(), size: CGSize(width: max(0.0, width), height: 42.0)), completion: nil)
}
/*node.backgroundBlurNode.update(size: node.backgroundBlurNode.bounds.size, cornerRadius: 0.0, animator: animation.animator)
node.backgroundBlurNode.updateColor(color: selectDateFillStaticColor(theme: theme.theme, wallpaper: theme.wallpaper), enableBlur: context.sharedContext.energyUsageSettings.fullTranslucency && dateFillNeedsBlur(theme: theme.theme, wallpaper: theme.wallpaper), transition: .immediate)*/
if backgroundNode?.hasExtraBubbleBackground() == true { if backgroundNode?.hasExtraBubbleBackground() == true {
if node.backgroundContent == nil, let backgroundContent = backgroundNode?.makeBubbleBackground(for: .free) { if node.backgroundContent == nil, let backgroundContent = backgroundNode?.makeBubbleBackground(for: .free) {
@ -208,8 +230,9 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
node.clipsToBounds = true node.clipsToBounds = true
if let backgroundContent = node.backgroundContent { if let backgroundContent = node.backgroundContent {
node.backgroundBlurNode.isHidden = true //node.backgroundBlurNode.isHidden = true
backgroundContent.frame = node.backgroundBlurNode.frame node.backgroundBlurView?.view.isHidden = true
backgroundContent.frame = CGRect(origin: CGPoint(), size: CGSize(width: max(0.0, width), height: 42.0))
node.backgroundColorNode?.frame = backgroundContent.bounds node.backgroundColorNode?.frame = backgroundContent.bounds
@ -220,11 +243,11 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate) backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate)
} }
} else { } else {
node.backgroundBlurNode.isHidden = false node.backgroundBlurView?.view.isHidden = false
} }
let rect = node.backgroundBlurNode.bounds let rect = CGRect(origin: CGPoint(), size: CGSize(width: max(0.0, width), height: 42.0))
let maskPath: CGPath? let maskPath: CGPath?
switch position { switch position {
case .bottomSingle: case .bottomSingle:

View File

@ -59,7 +59,8 @@ extension SlotMachineAnimationNode: GenericAnimatedStickerNode {
class ChatMessageShareButton: HighlightableButtonNode { class ChatMessageShareButton: HighlightableButtonNode {
private var backgroundContent: WallpaperBubbleBackgroundNode? private var backgroundContent: WallpaperBubbleBackgroundNode?
private let backgroundNode: NavigationBackgroundNode //private let backgroundNode: NavigationBackgroundNode
private var backgroundBlurView: PortalView?
private let iconNode: ASImageNode private let iconNode: ASImageNode
private var iconOffset = CGPoint() private var iconOffset = CGPoint()
@ -72,14 +73,14 @@ class ChatMessageShareButton: HighlightableButtonNode {
private var absolutePosition: (CGRect, CGSize)? private var absolutePosition: (CGRect, CGSize)?
init() { init() {
self.backgroundNode = NavigationBackgroundNode(color: .clear) //self.backgroundNode = NavigationBackgroundNode(color: .clear)
self.iconNode = ASImageNode() self.iconNode = ASImageNode()
super.init(pointerStyle: nil) super.init(pointerStyle: nil)
self.allowsGroupOpacity = true self.allowsGroupOpacity = true
self.addSubnode(self.backgroundNode) //self.addSubnode(self.backgroundNode)
self.addSubnode(self.iconNode) self.addSubnode(self.iconNode)
} }
@ -125,7 +126,7 @@ class ChatMessageShareButton: HighlightableButtonNode {
} else { } else {
updatedIconImage = PresentationResourcesChat.chatFreeShareButtonIcon(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper) updatedIconImage = PresentationResourcesChat.chatFreeShareButtonIcon(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper)
} }
self.backgroundNode.updateColor(color: selectDateFillStaticColor(theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper), enableBlur: controllerInteraction.enableFullTranslucency && dateFillNeedsBlur(theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper), transition: .immediate) //self.backgroundNode.updateColor(color: selectDateFillStaticColor(theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper), enableBlur: controllerInteraction.enableFullTranslucency && dateFillNeedsBlur(theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper), transition: .immediate)
self.iconNode.image = updatedIconImage self.iconNode.image = updatedIconImage
self.iconOffset = updatedIconOffset self.iconOffset = updatedIconOffset
} }
@ -162,8 +163,22 @@ class ChatMessageShareButton: HighlightableButtonNode {
self.textNode = nil self.textNode = nil
textNode.removeFromSupernode() textNode.removeFromSupernode()
} }
self.backgroundNode.frame = CGRect(origin: CGPoint(), size: size)
self.backgroundNode.update(size: self.backgroundNode.bounds.size, cornerRadius: min(self.backgroundNode.bounds.width, self.backgroundNode.bounds.height) / 2.0, transition: .immediate) if self.backgroundBlurView == nil {
if let backgroundBlurView = controllerInteraction.presentationContext.backgroundNode?.makeFreeBackground() {
self.backgroundBlurView = backgroundBlurView
self.view.insertSubview(backgroundBlurView.view, at: 0)
backgroundBlurView.view.clipsToBounds = true
}
}
if let backgroundBlurView = self.backgroundBlurView {
backgroundBlurView.view.frame = CGRect(origin: CGPoint(), size: size)
backgroundBlurView.view.layer.cornerRadius = min(size.width, size.height) / 2.0
}
//self.backgroundNode.frame = CGRect(origin: CGPoint(), size: size)
//self.backgroundNode.update(size: self.backgroundNode.bounds.size, cornerRadius: min(self.backgroundNode.bounds.width, self.backgroundNode.bounds.height) / 2.0, transition: .immediate)
if let image = self.iconNode.image { if let image = self.iconNode.image {
self.iconNode.frame = CGRect(origin: CGPoint(x: floor((size.width - image.size.width) / 2.0) + self.iconOffset.x, y: floor((size.width - image.size.width) / 2.0) - (offsetIcon ? 1.0 : 0.0) + self.iconOffset.y), size: image.size) self.iconNode.frame = CGRect(origin: CGPoint(x: floor((size.width - image.size.width) / 2.0) + self.iconOffset.x, y: floor((size.width - image.size.width) / 2.0) - (offsetIcon ? 1.0 : 0.0) + self.iconOffset.y), size: image.size)
} }
@ -181,9 +196,10 @@ class ChatMessageShareButton: HighlightableButtonNode {
} }
if let backgroundContent = self.backgroundContent { if let backgroundContent = self.backgroundContent {
self.backgroundNode.isHidden = true //self.backgroundNode.isHidden = true
backgroundContent.cornerRadius = min(self.backgroundNode.bounds.width, self.backgroundNode.bounds.height) / 2.0 self.backgroundBlurView?.view.isHidden = true
backgroundContent.frame = self.backgroundNode.frame backgroundContent.cornerRadius = min(size.width, size.height) / 2.0
backgroundContent.frame = CGRect(origin: CGPoint(), size: size)
if let (rect, containerSize) = self.absolutePosition { if let (rect, containerSize) = self.absolutePosition {
var backgroundFrame = backgroundContent.frame var backgroundFrame = backgroundContent.frame
backgroundFrame.origin.x += rect.minX backgroundFrame.origin.x += rect.minX
@ -191,7 +207,8 @@ class ChatMessageShareButton: HighlightableButtonNode {
backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate) backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate)
} }
} else { } else {
self.backgroundNode.isHidden = false //self.backgroundNode.isHidden = false
self.backgroundBlurView?.view.isHidden = false
} }
return size return size

View File

@ -914,6 +914,7 @@ private struct UrlHandlingConfiguration {
return UrlHandlingConfiguration(token: token, domains: domains, urlAuthDomains: urlAuthDomains) return UrlHandlingConfiguration(token: token, domains: domains, urlAuthDomains: urlAuthDomains)
} }
} }
//TODO:loc move to getConfig
return .defaultValue return .defaultValue
} }
} }

View File

@ -303,6 +303,10 @@ final class MetalWallpaperBackgroundNode: ASDisplayNode, WallpaperBackgroundNode
return nil return nil
} }
func makeFreeBackground() -> PortalView? {
return nil
}
func makeDimmedNode() -> ASDisplayNode? { func makeDimmedNode() -> ASDisplayNode? {
return nil return nil
} }

View File

@ -66,6 +66,7 @@ public protocol WallpaperBackgroundNode: ASDisplayNode {
func updateBubbleTheme(bubbleTheme: PresentationTheme, bubbleCorners: PresentationChatBubbleCorners) func updateBubbleTheme(bubbleTheme: PresentationTheme, bubbleCorners: PresentationChatBubbleCorners)
func hasBubbleBackground(for type: WallpaperBubbleType) -> Bool func hasBubbleBackground(for type: WallpaperBubbleType) -> Bool
func makeBubbleBackground(for type: WallpaperBubbleType) -> WallpaperBubbleBackgroundNode? func makeBubbleBackground(for type: WallpaperBubbleType) -> WallpaperBubbleBackgroundNode?
func makeFreeBackground() -> PortalView?
func hasExtraBubbleBackground() -> Bool func hasExtraBubbleBackground() -> Bool
@ -586,6 +587,10 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
private let contentNode: ASDisplayNode private let contentNode: ASDisplayNode
private var blurredBackgroundContents: UIImage? private var blurredBackgroundContents: UIImage?
private var blurredBackgroundPortalSourceView: PortalSourceView?
private var blurredBackgroundDimmedNode: GradientBackgroundNode.CloneNode?
private var blurredBackgroundDimmedOverlayView: UIView?
private var blurredBackgroundContentView: UIImageView?
private var gradientBackgroundNode: GradientBackgroundNode? private var gradientBackgroundNode: GradientBackgroundNode?
private var outgoingBubbleGradientBackgroundNode: GradientBackgroundNode? private var outgoingBubbleGradientBackgroundNode: GradientBackgroundNode?
@ -715,6 +720,17 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
super.init() super.init()
if #available(iOS 12.0, *) {
let blurredBackgroundPortalSourceView = PortalSourceView()
self.blurredBackgroundPortalSourceView = blurredBackgroundPortalSourceView
blurredBackgroundPortalSourceView.alpha = 0.0001
self.view.addSubview(blurredBackgroundPortalSourceView)
let blurredBackgroundContentView = UIImageView()
self.blurredBackgroundContentView = blurredBackgroundContentView
blurredBackgroundPortalSourceView.addSubview(blurredBackgroundContentView)
}
self.clipsToBounds = true self.clipsToBounds = true
self.contentNode.frame = self.bounds self.contentNode.frame = self.bounds
self.addSubnode(self.contentNode) self.addSubnode(self.contentNode)
@ -763,11 +779,28 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
scheduleLoopingEvent = true scheduleLoopingEvent = true
} }
} }
if let gradientBackgroundNode = self.gradientBackgroundNode {
if self.blurredBackgroundDimmedNode == nil {
let blurredBackgroundDimmedNode = GradientBackgroundNode.CloneNode(parentNode: gradientBackgroundNode)
self.blurredBackgroundDimmedNode = blurredBackgroundDimmedNode
self.blurredBackgroundPortalSourceView?.addSubnode(blurredBackgroundDimmedNode)
}
if self.blurredBackgroundDimmedOverlayView == nil {
let blurredBackgroundDimmedOverlayView = UIView()
self.blurredBackgroundDimmedOverlayView = blurredBackgroundDimmedOverlayView
self.blurredBackgroundPortalSourceView?.addSubview(blurredBackgroundDimmedOverlayView)
}
}
self.gradientBackgroundNode?.updateColors(colors: mappedColors) self.gradientBackgroundNode?.updateColors(colors: mappedColors)
if let bubbleTheme = self.bubbleTheme {
self.blurredBackgroundDimmedOverlayView?.backgroundColor = selectDateFillStaticColor(theme: bubbleTheme, wallpaper: wallpaper)
}
self.contentNode.backgroundColor = nil self.contentNode.backgroundColor = nil
self.contentNode.contents = nil self.contentNode.contents = nil
self.blurredBackgroundContents = nil self.blurredBackgroundContents = nil
self.blurredBackgroundContentView?.image = self.blurredBackgroundContents
self.motionEnabled = false self.motionEnabled = false
self.wallpaperDisposable.set(nil) self.wallpaperDisposable.set(nil)
} else { } else {
@ -777,6 +810,14 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
gradientBackgroundNode.setPatternOverlay(layer: nil) gradientBackgroundNode.setPatternOverlay(layer: nil)
self.layer.insertSublayer(self.patternImageLayer, above: self.contentNode.layer) self.layer.insertSublayer(self.patternImageLayer, above: self.contentNode.layer)
} }
if let blurredBackgroundDimmedNode = self.blurredBackgroundDimmedNode {
self.blurredBackgroundDimmedNode = nil
blurredBackgroundDimmedNode.removeFromSupernode()
}
if let blurredBackgroundDimmedOverlayView = self.blurredBackgroundDimmedOverlayView {
self.blurredBackgroundDimmedOverlayView = nil
blurredBackgroundDimmedOverlayView.removeFromSuperview()
}
self.motionEnabled = wallpaper.settings?.motion ?? false self.motionEnabled = wallpaper.settings?.motion ?? false
@ -797,17 +838,20 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
}) })
self.contentNode.contents = image?.cgImage self.contentNode.contents = image?.cgImage
self.blurredBackgroundContents = image self.blurredBackgroundContents = image
self.blurredBackgroundContentView?.image = self.blurredBackgroundContents
self.wallpaperDisposable.set(nil) self.wallpaperDisposable.set(nil)
} else if gradientColors.count >= 1 { } else if gradientColors.count >= 1 {
self.contentNode.backgroundColor = UIColor(rgb: gradientColors[0]) self.contentNode.backgroundColor = UIColor(rgb: gradientColors[0])
self.contentNode.contents = nil self.contentNode.contents = nil
self.blurredBackgroundContents = nil self.blurredBackgroundContents = nil
self.blurredBackgroundContentView?.image = self.blurredBackgroundContents
self.wallpaperDisposable.set(nil) self.wallpaperDisposable.set(nil)
} else { } else {
self.contentNode.backgroundColor = .white self.contentNode.backgroundColor = .white
if let image = chatControllerBackgroundImage(theme: nil, wallpaper: wallpaper, mediaBox: self.context.sharedContext.accountManager.mediaBox, knockoutMode: false) { if let image = chatControllerBackgroundImage(theme: nil, wallpaper: wallpaper, mediaBox: self.context.sharedContext.accountManager.mediaBox, knockoutMode: false) {
self.contentNode.contents = image.cgImage self.contentNode.contents = image.cgImage
self.blurredBackgroundContents = generateBlurredContents(image: image) self.blurredBackgroundContents = generateBlurredContents(image: image)
self.blurredBackgroundContentView?.image = self.blurredBackgroundContents
self.wallpaperDisposable.set(nil) self.wallpaperDisposable.set(nil)
Queue.mainQueue().justDispatch { Queue.mainQueue().justDispatch {
self._isReady.set(true) self._isReady.set(true)
@ -815,6 +859,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
} else if let image = chatControllerBackgroundImage(theme: nil, wallpaper: wallpaper, mediaBox: self.context.account.postbox.mediaBox, knockoutMode: false) { } else if let image = chatControllerBackgroundImage(theme: nil, wallpaper: wallpaper, mediaBox: self.context.account.postbox.mediaBox, knockoutMode: false) {
self.contentNode.contents = image.cgImage self.contentNode.contents = image.cgImage
self.blurredBackgroundContents = generateBlurredContents(image: image) self.blurredBackgroundContents = generateBlurredContents(image: image)
self.blurredBackgroundContentView?.image = self.blurredBackgroundContents
self.wallpaperDisposable.set(nil) self.wallpaperDisposable.set(nil)
Queue.mainQueue().justDispatch { Queue.mainQueue().justDispatch {
self._isReady.set(true) self._isReady.set(true)
@ -831,6 +876,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
} else { } else {
strongSelf.blurredBackgroundContents = nil strongSelf.blurredBackgroundContents = nil
} }
strongSelf.blurredBackgroundContentView?.image = strongSelf.blurredBackgroundContents
strongSelf._isReady.set(true) strongSelf._isReady.set(true)
})) }))
} }
@ -1079,6 +1125,19 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
let isFirstLayout = self.validLayout == nil let isFirstLayout = self.validLayout == nil
self.validLayout = size self.validLayout = size
if let blurredBackgroundPortalSourceView = self.blurredBackgroundPortalSourceView {
transition.updateFrame(view: blurredBackgroundPortalSourceView, frame: CGRect(origin: CGPoint(), size: size))
}
if let blurredBackgroundContentView = self.blurredBackgroundContentView {
transition.updateFrame(view: blurredBackgroundContentView, frame: CGRect(origin: CGPoint(), size: size))
}
if let blurredBackgroundDimmedNode = self.blurredBackgroundDimmedNode {
transition.updateFrame(view: blurredBackgroundDimmedNode.view, frame: CGRect(origin: CGPoint(), size: size))
}
if let blurredBackgroundDimmedOverlayView = self.blurredBackgroundDimmedOverlayView {
transition.updateFrame(view: blurredBackgroundDimmedOverlayView, frame: CGRect(origin: CGPoint(), size: size))
}
transition.updatePosition(node: self.contentNode, position: CGPoint(x: size.width / 2.0, y: size.height / 2.0)) transition.updatePosition(node: self.contentNode, position: CGPoint(x: size.width / 2.0, y: size.height / 2.0))
transition.updateBounds(node: self.contentNode, bounds: CGRect(origin: CGPoint(), size: size)) transition.updateBounds(node: self.contentNode, bounds: CGRect(origin: CGPoint(), size: size))
@ -1153,6 +1212,10 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
self.outgoingBubbleGradientBackgroundNode = nil self.outgoingBubbleGradientBackgroundNode = nil
} }
if let wallpaper = self.wallpaper {
self.blurredBackgroundDimmedOverlayView?.backgroundColor = selectDateFillStaticColor(theme: bubbleTheme, wallpaper: wallpaper)
}
self.updateBubbles() self.updateBubbles()
} }
} }
@ -1217,6 +1280,17 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
return node return node
} }
func makeFreeBackground() -> PortalView? {
guard let blurredBackgroundPortalSourceView = self.blurredBackgroundPortalSourceView else {
return nil
}
guard let portalView = PortalView(matchPosition: true) else {
return nil
}
blurredBackgroundPortalSourceView.addPortal(view: portalView)
return portalView
}
func hasExtraBubbleBackground() -> Bool { func hasExtraBubbleBackground() -> Bool {
var isInvertedGradient = false var isInvertedGradient = false
switch self.wallpaper { switch self.wallpaper {
@ -2076,6 +2150,10 @@ final class WallpaperBackgroundNodeMergedImpl: ASDisplayNode, WallpaperBackgroun
return node return node
} }
func makeFreeBackground() -> PortalView? {
return nil
}
func hasExtraBubbleBackground() -> Bool { func hasExtraBubbleBackground() -> Bool {
return false return false
} }