diff --git a/submodules/DebugSettingsUI/Sources/DebugController.swift b/submodules/DebugSettingsUI/Sources/DebugController.swift index 76f2848d8f..56398e6f7c 100644 --- a/submodules/DebugSettingsUI/Sources/DebugController.swift +++ b/submodules/DebugSettingsUI/Sources/DebugController.swift @@ -100,7 +100,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { case enableReactionOverrides(Bool) case storiesExperiment(Bool) case storiesJpegExperiment(Bool) - case playlistPlayback(Bool) + case conferenceDebug(Bool) case enableQuickReactionSwitch(Bool) case disableReloginTokens(Bool) case liveStreamV2(Bool) @@ -133,7 +133,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { return DebugControllerSection.web.rawValue case .keepChatNavigationStack, .skipReadHistory, .dustEffect, .crashOnSlowQueries, .crashOnMemoryPressure: return DebugControllerSection.experiments.rawValue - case .clearTips, .resetNotifications, .crash, .fillLocalSavedMessageCache, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .resetTagHoles, .reindexUnread, .resetCacheIndex, .reindexCache, .resetBiometricsData, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .storiesExperiment, .storiesJpegExperiment, .playlistPlayback, .enableQuickReactionSwitch, .experimentalCompatibility, .enableDebugDataDisplay, .rippleEffect, .browserExperiment, .localTranscription, .enableReactionOverrides, .restorePurchases, .disableReloginTokens, .liveStreamV2, .experimentalCallMute, .playerV2, .devRequests, .fakeAds, .enableLocalTranslation: + case .clearTips, .resetNotifications, .crash, .fillLocalSavedMessageCache, .resetDatabase, .resetDatabaseAndCache, .resetHoles, .resetTagHoles, .reindexUnread, .resetCacheIndex, .reindexCache, .resetBiometricsData, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .storiesExperiment, .storiesJpegExperiment, .conferenceDebug, .enableQuickReactionSwitch, .experimentalCompatibility, .enableDebugDataDisplay, .rippleEffect, .browserExperiment, .localTranscription, .enableReactionOverrides, .restorePurchases, .disableReloginTokens, .liveStreamV2, .experimentalCallMute, .playerV2, .devRequests, .fakeAds, .enableLocalTranslation: return DebugControllerSection.experiments.rawValue case .logTranslationRecognition, .resetTranslationStates: return DebugControllerSection.translation.rawValue @@ -242,7 +242,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { return 47 case .disableReloginTokens: return 48 - case .playlistPlayback: + case .conferenceDebug: return 49 case .enableQuickReactionSwitch: return 50 @@ -1308,12 +1308,12 @@ private enum DebugControllerEntry: ItemListNodeEntry { }) }).start() }) - case let .playlistPlayback(value): - return ItemListSwitchItem(presentationData: presentationData, title: "Playlist Playback", value: value, sectionId: self.section, style: .blocks, updated: { value in + case let .conferenceDebug(value): + return ItemListSwitchItem(presentationData: presentationData, title: "Conference Debug", value: value, sectionId: self.section, style: .blocks, updated: { value in let _ = arguments.sharedContext.accountManager.transaction ({ transaction in transaction.updateSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings, { settings in var settings = settings?.get(ExperimentalUISettings.self) ?? ExperimentalUISettings.defaultSettings - settings.playlistPlayback = value + settings.conferenceDebug = value return PreferencesEntry(settings) }) }).start() @@ -1540,7 +1540,7 @@ private func debugControllerEntries(sharedContext: SharedAccountContext, present entries.append(.storiesJpegExperiment(experimentalSettings.storiesJpegExperiment)) entries.append(.disableReloginTokens(experimentalSettings.disableReloginTokens)) } - entries.append(.playlistPlayback(experimentalSettings.playlistPlayback)) + entries.append(.conferenceDebug(experimentalSettings.conferenceDebug)) entries.append(.enableQuickReactionSwitch(!experimentalSettings.disableQuickReaction)) entries.append(.liveStreamV2(experimentalSettings.liveStreamV2)) entries.append(.experimentalCallMute(experimentalSettings.experimentalCallMute)) diff --git a/submodules/SemanticStatusNode/BUILD b/submodules/SemanticStatusNode/BUILD index e4a4b8d840..97e68da2c4 100644 --- a/submodules/SemanticStatusNode/BUILD +++ b/submodules/SemanticStatusNode/BUILD @@ -16,7 +16,8 @@ swift_library( "//submodules/GZip:GZip", "//submodules/rlottie:RLottieBinding", "//submodules/AppBundle:AppBundle", - "//submodules/ManagedAnimationNode:ManagedAnimationNode" + "//submodules/ManagedAnimationNode:ManagedAnimationNode", + "//submodules/Components/HierarchyTrackingLayer", ], visibility = [ "//visibility:public", diff --git a/submodules/SemanticStatusNode/Sources/SemanticStatusNode.swift b/submodules/SemanticStatusNode/Sources/SemanticStatusNode.swift index 7cb36a0453..d6864b7632 100644 --- a/submodules/SemanticStatusNode/Sources/SemanticStatusNode.swift +++ b/submodules/SemanticStatusNode/Sources/SemanticStatusNode.swift @@ -6,6 +6,7 @@ import SwiftSignalKit import RLottieBinding import GZip import AppBundle +import HierarchyTrackingLayer public enum SemanticStatusNodeState: Equatable { public struct ProgressAppearance: Equatable { @@ -90,7 +91,7 @@ private func svgPath(_ path: StaticString, scale: CGPoint = CGPoint(x: 1.0, y: 1 } private extension SemanticStatusNodeState { - func context(current: SemanticStatusNodeStateContext?) -> SemanticStatusNodeStateContext { + func context(current: SemanticStatusNodeStateContext?, animated: Bool) -> SemanticStatusNodeStateContext { switch self { case .none, .download, .play, .pause, .customIcon: let icon: SemanticStatusNodeIcon @@ -114,7 +115,7 @@ private extension SemanticStatusNodeState { if current.icon == icon { return current } else if (current.icon == .play && icon == .pause) || (current.icon == .pause && icon == .play) { - current.icon = icon + current.setIcon(icon: icon, animated: animated) return current } else { return SemanticStatusNodeIconContext(icon: icon) @@ -376,6 +377,8 @@ public final class SemanticStatusNode: ASControlNode { private var stateContext: SemanticStatusNodeStateContext private var appearanceContext: SemanticStatusNodeAppearanceContext + private let hierarchyTrackingLayer: HierarchyTrackingLayer + private var disposable: Disposable? private var backgroundNodeImage: UIImage? @@ -391,13 +394,16 @@ public final class SemanticStatusNode: ASControlNode { public init(backgroundNodeColor: UIColor, foregroundNodeColor: UIColor, image: Signal<(TransformImageArguments) -> DrawingContext?, NoError>? = nil, overlayForegroundNodeColor: UIColor? = nil, cutout: CGRect? = nil) { self.state = .none - self.stateContext = self.state.context(current: nil) + self.stateContext = self.state.context(current: nil, animated: false) self.appearanceContext = SemanticStatusNodeAppearanceContext(background: backgroundNodeColor, foreground: foregroundNodeColor, backgroundImage: nil, overlayForeground: overlayForegroundNodeColor, cutout: cutout) + self.hierarchyTrackingLayer = HierarchyTrackingLayer() super.init() + self.layer.addSublayer(self.hierarchyTrackingLayer) + self.isOpaque = false - self.displaysAsynchronously = true + self.displaysAsynchronously = false if let image { self.setBackgroundImage(image, size: CGSize(width: 44.0, height: 44.0)) @@ -420,7 +426,6 @@ public final class SemanticStatusNode: ASControlNode { animate = true } } - if self.stateContext.isAnimating { animate = true } @@ -449,12 +454,15 @@ public final class SemanticStatusNode: ASControlNode { self.hasState = true animated = false } + if !self.hierarchyTrackingLayer.isInHierarchy { + animated = false + } if self.state != state || self.appearanceContext.cutout != cutout { self.state = state let previousStateContext = self.stateContext let previousAppearanceContext = updateCutout ? self.appearanceContext : nil - self.stateContext = self.state.context(current: self.stateContext) + self.stateContext = self.state.context(current: self.stateContext, animated: animated) self.stateContext.requestUpdate = { [weak self] in self?.setNeedsDisplay() } diff --git a/submodules/SemanticStatusNode/Sources/SemanticStatusNodeIconContext.swift b/submodules/SemanticStatusNode/Sources/SemanticStatusNodeIconContext.swift index f47b643bf7..bd9586b2d1 100644 --- a/submodules/SemanticStatusNode/Sources/SemanticStatusNodeIconContext.swift +++ b/submodules/SemanticStatusNode/Sources/SemanticStatusNodeIconContext.swift @@ -131,11 +131,7 @@ final class SemanticStatusNodeIconContext: SemanticStatusNodeStateContext { } } - var icon: SemanticStatusNodeIcon { - didSet { - self.animationNode?.enqueueState(self.icon == .play ? .play : .pause, animated: self.iconImage != nil) - } - } + private(set) var icon: SemanticStatusNodeIcon private var animationNode: PlayPauseIconNode? private var iconImage: UIImage? @@ -171,6 +167,11 @@ final class SemanticStatusNodeIconContext: SemanticStatusNodeStateContext { var requestUpdate: () -> Void = {} + func setIcon(icon: SemanticStatusNodeIcon, animated: Bool) { + self.icon = icon + self.animationNode?.enqueueState(self.icon == .play ? .play : .pause, animated: animated) + } + func drawingState(transitionFraction: CGFloat) -> SemanticStatusNodeStateDrawingState { return DrawingState(transitionFraction: transitionFraction, icon: self.icon, iconImage: self.iconImage, iconOffset: self.iconOffset) } diff --git a/submodules/TelegramCallsUI/Sources/CallControllerNodeV2.swift b/submodules/TelegramCallsUI/Sources/CallControllerNodeV2.swift index 7ccc395be3..7e25b16b0b 100644 --- a/submodules/TelegramCallsUI/Sources/CallControllerNodeV2.swift +++ b/submodules/TelegramCallsUI/Sources/CallControllerNodeV2.swift @@ -167,6 +167,14 @@ final class CallControllerNodeV2: ViewControllerTracingNode, CallControllerNodeP self.conferenceAddParticipant?() } + var isConferencePossible = false + if self.call.context.sharedContext.immediateExperimentalUISettings.conferenceDebug { + isConferencePossible = true + } + if let data = self.call.context.currentAppConfiguration.with({ $0 }).data, let value = data["ios_enable_conference"] as? Double { + isConferencePossible = value != 0.0 + } + self.callScreenState = PrivateCallScreen.State( strings: presentationData.strings, lifecycleState: .connecting, @@ -180,7 +188,7 @@ final class CallControllerNodeV2: ViewControllerTracingNode, CallControllerNodeP remoteVideo: nil, isRemoteBatteryLow: false, isEnergySavingEnabled: !self.sharedContext.energyUsageSettings.fullTranslucency, - isConferencePossible: true + isConferencePossible: isConferencePossible ) self.isMicrophoneMutedDisposable = (call.isMuted diff --git a/submodules/TelegramUI/Components/BatchVideoRendering/Sources/BatchVideoRenderingContext.swift b/submodules/TelegramUI/Components/BatchVideoRendering/Sources/BatchVideoRenderingContext.swift index ea3af6fad2..3455b29612 100644 --- a/submodules/TelegramUI/Components/BatchVideoRendering/Sources/BatchVideoRenderingContext.swift +++ b/submodules/TelegramUI/Components/BatchVideoRendering/Sources/BatchVideoRenderingContext.swift @@ -153,7 +153,6 @@ public final class BatchVideoRenderingContext { for (id, targetContext) in self.targetContexts { if targetContext.target != nil { if targetContext.fetchDisposable == nil { - //TODO:release pass resource reference targetContext.fetchDisposable = fetchedMediaResource( mediaBox: self.context.account.postbox.mediaBox, userLocation: targetContext.userLocation, diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode/BUILD b/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode/BUILD index ff525a9ace..cf18fe2633 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode/BUILD +++ b/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode/BUILD @@ -43,6 +43,7 @@ swift_library( "//submodules/TelegramUI/Components/Chat/ChatMessageItemCommon", "//submodules/AnimatedCountLabelNode", "//submodules/AudioWaveform", + "//submodules/DeviceProximity", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode/Sources/ChatMessageInteractiveFileNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode/Sources/ChatMessageInteractiveFileNode.swift index 7d9888408e..5357300699 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode/Sources/ChatMessageInteractiveFileNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveFileNode/Sources/ChatMessageInteractiveFileNode.swift @@ -34,6 +34,7 @@ import ChatMessageItemCommon import TelegramStringFormatting import AnimatedCountLabelNode import AudioWaveform +import DeviceProximity private struct FetchControls { let fetch: (Bool) -> Void @@ -1561,6 +1562,12 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode { guard let arguments = self.arguments else { return } + + var animated = animated + if DeviceProximityManager.shared().currentValue() { + animated = false + } + let incoming = message.effectivelyIncoming(context.account.peerId) let messageTheme = incoming ? presentationData.theme.theme.chat.message.incoming : presentationData.theme.theme.chat.message.outgoing diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNavigationButtonContainerNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNavigationButtonContainerNode.swift index 77d110f53e..09ee654713 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNavigationButtonContainerNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNavigationButtonContainerNode.swift @@ -54,7 +54,10 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode { } var accumulatedRightButtonOffset: CGFloat = canBeExpanded ? 16.0 : 0.0 - for (_, button) in self.rightButtonNodes { + for spec in self.currentRightButtons.reversed() { + guard let button = self.rightButtonNodes[spec.key] else { + continue + } button.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, canBeExpanded: canBeExpanded, transition: transition) transition.updateSublayerTransformOffset(layer: button.layer, offset: CGPoint(x: accumulatedRightButtonOffset, y: 0.0)) if self.backgroundContentColor.alpha != 0.0 { @@ -174,6 +177,7 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode { } } + var accumulatedRightButtonOffset: CGFloat = self.canBeExpanded ? 16.0 : 0.0 if self.currentRightButtons != rightButtons || presentationData.strings !== self.presentationData?.strings { self.currentRightButtons = rightButtons @@ -225,7 +229,10 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode { buttonNode.alpha = 0.0 transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor) - transition.updateSublayerTransformOffset(layer: buttonNode.layer, offset: CGPoint(x: canBeExpanded ? 16.0 : 0.0, y: 0.0)) + transition.updateSublayerTransformOffset(layer: buttonNode.layer, offset: CGPoint(x: accumulatedRightButtonOffset, y: 0.0)) + if self.backgroundContentColor.alpha != 0.0 { + accumulatedRightButtonOffset -= 6.0 + } } else { transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame) transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor) diff --git a/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift b/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift index 586ed5b192..3a2400cd6d 100644 --- a/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift +++ b/submodules/TelegramUIPreferences/Sources/ExperimentalUISettings.swift @@ -32,7 +32,6 @@ public struct ExperimentalUISettings: Codable, Equatable { public var knockoutWallpaper: Bool public var foldersTabAtBottom: Bool public var playerEmbedding: Bool - public var playlistPlayback: Bool public var preferredVideoCodec: String? public var disableVideoAspectScaling: Bool public var enableVoipTcp: Bool @@ -65,6 +64,7 @@ public struct ExperimentalUISettings: Codable, Equatable { public var playerV2: Bool public var devRequests: Bool public var fakeAds: Bool + public var conferenceDebug: Bool public static var defaultSettings: ExperimentalUISettings { return ExperimentalUISettings( @@ -75,7 +75,6 @@ public struct ExperimentalUISettings: Codable, Equatable { knockoutWallpaper: false, foldersTabAtBottom: false, playerEmbedding: false, - playlistPlayback: false, preferredVideoCodec: nil, disableVideoAspectScaling: false, enableVoipTcp: false, @@ -107,7 +106,8 @@ public struct ExperimentalUISettings: Codable, Equatable { autoBenchmarkReflectors: nil, playerV2: false, devRequests: false, - fakeAds: false + fakeAds: false, + conferenceDebug: false ) } @@ -119,7 +119,6 @@ public struct ExperimentalUISettings: Codable, Equatable { knockoutWallpaper: Bool, foldersTabAtBottom: Bool, playerEmbedding: Bool, - playlistPlayback: Bool, preferredVideoCodec: String?, disableVideoAspectScaling: Bool, enableVoipTcp: Bool, @@ -151,7 +150,8 @@ public struct ExperimentalUISettings: Codable, Equatable { autoBenchmarkReflectors: Bool?, playerV2: Bool, devRequests: Bool, - fakeAds: Bool + fakeAds: Bool, + conferenceDebug: Bool ) { self.keepChatNavigationStack = keepChatNavigationStack self.skipReadHistory = skipReadHistory @@ -160,7 +160,6 @@ public struct ExperimentalUISettings: Codable, Equatable { self.knockoutWallpaper = knockoutWallpaper self.foldersTabAtBottom = foldersTabAtBottom self.playerEmbedding = playerEmbedding - self.playlistPlayback = playlistPlayback self.preferredVideoCodec = preferredVideoCodec self.disableVideoAspectScaling = disableVideoAspectScaling self.enableVoipTcp = enableVoipTcp @@ -193,6 +192,7 @@ public struct ExperimentalUISettings: Codable, Equatable { self.playerV2 = playerV2 self.devRequests = devRequests self.fakeAds = fakeAds + self.conferenceDebug = conferenceDebug } public init(from decoder: Decoder) throws { @@ -205,7 +205,6 @@ public struct ExperimentalUISettings: Codable, Equatable { self.knockoutWallpaper = (try container.decodeIfPresent(Int32.self, forKey: "knockoutWallpaper") ?? 0) != 0 self.foldersTabAtBottom = (try container.decodeIfPresent(Int32.self, forKey: "foldersTabAtBottom") ?? 0) != 0 self.playerEmbedding = (try container.decodeIfPresent(Int32.self, forKey: "playerEmbedding") ?? 0) != 0 - self.playlistPlayback = (try container.decodeIfPresent(Int32.self, forKey: "playlistPlayback") ?? 0) != 0 self.preferredVideoCodec = try container.decodeIfPresent(String.self.self, forKey: "preferredVideoCodec") self.disableVideoAspectScaling = (try container.decodeIfPresent(Int32.self, forKey: "disableVideoAspectScaling") ?? 0) != 0 self.enableVoipTcp = (try container.decodeIfPresent(Int32.self, forKey: "enableVoipTcp") ?? 0) != 0 @@ -238,6 +237,7 @@ public struct ExperimentalUISettings: Codable, Equatable { self.playerV2 = try container.decodeIfPresent(Bool.self, forKey: "playerV2") ?? false self.devRequests = try container.decodeIfPresent(Bool.self, forKey: "devRequests") ?? false self.fakeAds = try container.decodeIfPresent(Bool.self, forKey: "fakeAds") ?? false + self.conferenceDebug = try container.decodeIfPresent(Bool.self, forKey: "conferenceDebug") ?? false } public func encode(to encoder: Encoder) throws { @@ -250,7 +250,6 @@ public struct ExperimentalUISettings: Codable, Equatable { try container.encode((self.knockoutWallpaper ? 1 : 0) as Int32, forKey: "knockoutWallpaper") try container.encode((self.foldersTabAtBottom ? 1 : 0) as Int32, forKey: "foldersTabAtBottom") try container.encode((self.playerEmbedding ? 1 : 0) as Int32, forKey: "playerEmbedding") - try container.encode((self.playlistPlayback ? 1 : 0) as Int32, forKey: "playlistPlayback") try container.encodeIfPresent(self.preferredVideoCodec, forKey: "preferredVideoCodec") try container.encode((self.disableVideoAspectScaling ? 1 : 0) as Int32, forKey: "disableVideoAspectScaling") try container.encode((self.enableVoipTcp ? 1 : 0) as Int32, forKey: "enableVoipTcp") @@ -283,6 +282,7 @@ public struct ExperimentalUISettings: Codable, Equatable { try container.encodeIfPresent(self.playerV2, forKey: "playerV2") try container.encodeIfPresent(self.devRequests, forKey: "devRequests") try container.encodeIfPresent(self.fakeAds, forKey: "fakeAds") + try container.encodeIfPresent(self.conferenceDebug, forKey: "conferenceDebug") } }