Skip to content

Commit ca3eacd

Browse files
committed
Various improvements
1 parent 8f8dca5 commit ca3eacd

8 files changed

Lines changed: 198 additions & 38 deletions

File tree

Telegram/Telegram-iOS/en.lproj/Localizable.strings

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16166,3 +16166,5 @@ Error: %8$@";
1616616166
"Attachment.PublicMusic" = "PUBLIC CHATS";
1616716167

1616816168
"PeerInfo.UnofficialSecurityRisk" = "%@ uses an unofficial Telegram client – messages to this user may be less secure.";
16169+
16170+
"Gallery.Live" = "LIVE";

submodules/GalleryUI/Sources/GalleryPagerNode.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,20 @@ public final class GalleryPagerNode: ASDisplayNode, ASScrollViewDelegate, ASGest
128128
private var pagingEnabledDisposable: Disposable?
129129

130130
private var edgeLongTapTimer: Foundation.Timer?
131+
132+
private func isInteractiveControlView(_ view: UIView?) -> Bool {
133+
var currentView = view
134+
while let view = currentView {
135+
if view is UIControl {
136+
return true
137+
}
138+
if let _ = view.asyncdisplaykit_node as? ASButtonNode {
139+
return true
140+
}
141+
currentView = view.superview
142+
}
143+
return false
144+
}
131145

132146
public init(pageGap: CGFloat, disableTapNavigation: Bool) {
133147
self.pageGap = pageGap
@@ -220,7 +234,7 @@ public final class GalleryPagerNode: ASDisplayNode, ASScrollViewDelegate, ASGest
220234
return .fail
221235
}
222236

223-
if let result = strongSelf.hitTest(point, with: nil), let _ = result.asyncdisplaykit_node as? ASButtonNode {
237+
if strongSelf.isInteractiveControlView(strongSelf.hitTest(point, with: nil)) {
224238
return .fail
225239
}
226240

submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift

Lines changed: 156 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import MultilineTextComponent
3838
import BundleIconComponent
3939
import VideoPlaybackControlsComponent
4040
import PhotoResources
41+
import GlassBackgroundComponent
4142

4243
public enum UniversalVideoGalleryItemContentInfo {
4344
case message(Message, GalleryMediaSubject?)
@@ -893,7 +894,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
893894
private let statusButtonNode: HighlightableButtonNode
894895
private let statusNode: RadialStatusNode
895896
private var statusNodeShouldBeHidden = true
896-
private var livePhotoIconNode: ASImageNode?
897+
private var livePhotoButton: LivePhotoButton?
897898

898899
private let playbackControls = ComponentView<Empty>()
899900

@@ -963,9 +964,11 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
963964
private var activeEdgeRateIndicator: ComponentView<Empty>?
964965

965966
private var isAnimatingOut: Bool = false
967+
966968
private var isLivePhoto = false
967969
private var didAutoplayLivePhotoOnce = false
968-
private var isPlayingLivePhotoByHolding = false
970+
private var isLivePhotoPlaybackActive = false
971+
private var isLivePhotoGestureActive = false
969972

970973
init(context: AccountContext, presentationData: PresentationData, performAction: @escaping (GalleryControllerInteractionTapAction) -> Void, openActionOptions: @escaping (GalleryControllerInteractionTapAction, Message) -> Void, present: @escaping (ViewController, Any?) -> Void) {
971974
self.context = context
@@ -1275,6 +1278,14 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
12751278
let transition = ComponentTransition(transition)
12761279
transition.setFrame(view: playbackControlsView, frame: playbackControlsFrame)
12771280
}
1281+
1282+
if let livePhotoButton = self.livePhotoButton {
1283+
let livePhotoButtonSize = livePhotoButton.update(isPlaying: self.isLivePhotoPlaybackActive)
1284+
if livePhotoButton.superview == nil {
1285+
self.view.addSubview(livePhotoButton)
1286+
}
1287+
transition.updateFrame(view: livePhotoButton, frame: CGRect(origin: CGPoint(x: 16.0, y: max(navigationBarHeight, layout.statusBarHeight ?? 0.0) + 10.0), size: livePhotoButtonSize))
1288+
}
12781289

12791290
if let pictureInPictureNode = self.pictureInPictureNode {
12801291
if let item = self.item {
@@ -1374,10 +1385,11 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
13741385
self.statusButtonNode.isHidden = true
13751386
}
13761387

1388+
self.resetLivePhotoPlayback()
13771389
self.dismissOnOrientationChange = item.landscape
13781390
self.isLivePhoto = false
13791391
self.didAutoplayLivePhotoOnce = false
1380-
self.isPlayingLivePhotoByHolding = false
1392+
self.isLivePhotoPlaybackActive = false
13811393

13821394
var hasLinkedStickers = false
13831395
if let content = item.content as? NativeVideoContent {
@@ -1716,7 +1728,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
17161728
initialBuffering = true
17171729
}
17181730
isPaused = !whilePlaying
1719-
if strongSelf.isPlayingLivePhotoByHolding {
1731+
if strongSelf.isLivePhotoPlaybackActive {
17201732
isPaused = false
17211733
}
17221734
var isStreaming = false
@@ -1961,7 +1973,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
19611973
}
19621974

19631975
if strongSelf.isLivePhoto {
1964-
if !strongSelf.isPlayingLivePhotoByHolding {
1976+
if !strongSelf.isLivePhotoPlaybackActive {
19651977
strongSelf.setLivePhotoVideoVisible(false, animated: true)
19661978
}
19671979
} else if let snapshotView = videoNode?.view.snapshotView(afterScreenUpdates: false) {
@@ -1973,7 +1985,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
19731985

19741986
if !strongSelf.isLivePhoto {
19751987
videoNode?.seek(0.0)
1976-
} else if strongSelf.isPlayingLivePhotoByHolding {
1988+
} else if strongSelf.isLivePhotoPlaybackActive {
19771989
videoNode?.playOnceWithSound(playAndRecord: false, actionAtEnd: .loop)
19781990
}
19791991

@@ -2059,22 +2071,29 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
20592071
}
20602072

20612073
if self.isLivePhoto {
2062-
let livePhotoIconNode: ASImageNode
2063-
if let current = self.livePhotoIconNode {
2064-
livePhotoIconNode = current
2074+
let livePhotoButton: LivePhotoButton
2075+
if let current = self.livePhotoButton {
2076+
livePhotoButton = current
20652077
} else {
2066-
livePhotoIconNode = ASImageNode()
2067-
livePhotoIconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Media Editor/LiveOn"), color: .white)
2068-
//self.addSubnode(livePhotoIconNode)
2069-
self.livePhotoIconNode = livePhotoIconNode
2070-
}
2071-
2072-
if let icon = livePhotoIconNode.image {
2073-
livePhotoIconNode.frame = CGRect(origin: CGPoint(x: 8.0, y: 8.0), size: icon.size)
2074-
}
2075-
} else if let livePhotoIconNode = self.livePhotoIconNode {
2076-
self.livePhotoIconNode = nil
2077-
livePhotoIconNode.removeFromSupernode()
2078+
livePhotoButton = LivePhotoButton(context: self.context)
2079+
livePhotoButton.pressed = { [weak self] in
2080+
guard let self else {
2081+
return
2082+
}
2083+
self.updateLivePhotoPlayback(isActive: !self.isLivePhotoPlaybackActive, animated: true)
2084+
}
2085+
self.livePhotoButton = livePhotoButton
2086+
self.view.addSubview(livePhotoButton)
2087+
}
2088+
// if livePhotoButton.superview == nil {
2089+
//
2090+
// }
2091+
// if let validLayout = self.validLayout {
2092+
// self.containerLayoutUpdated(validLayout.layout, navigationBarHeight: validLayout.navigationBarHeight, transition: .immediate)
2093+
// }
2094+
} else if let livePhotoButton = self.livePhotoButton {
2095+
self.livePhotoButton = nil
2096+
livePhotoButton.removeFromSuperview()
20782097
}
20792098
}
20802099

@@ -2169,24 +2188,29 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
21692188
}
21702189
}
21712190

2172-
private func updateLivePhotoHoldPlayback(isActive: Bool, animated: Bool) {
2173-
guard self.isLivePhoto, let videoNode = self.videoNode else {
2174-
return
2175-
}
2176-
guard self.isPlayingLivePhotoByHolding != isActive else {
2191+
private func updateLivePhotoPlayback(isActive: Bool, animated: Bool) {
2192+
guard self.isLivePhoto, self.isLivePhotoPlaybackActive != isActive, let videoNode = self.videoNode else {
21772193
return
21782194
}
2179-
2180-
self.isPlayingLivePhotoByHolding = isActive
2195+
2196+
self.isLivePhotoPlaybackActive = isActive
21812197
if isActive {
21822198
self.setLivePhotoVideoVisible(true, animated: animated)
21832199
videoNode.seek(0.0)
2184-
videoNode.playOnceWithSound(playAndRecord: false)
2200+
videoNode.playOnceWithSound(playAndRecord: false, actionAtEnd: .loop)
21852201
} else {
21862202
videoNode.pause()
21872203
videoNode.seek(0.0)
21882204
self.setLivePhotoVideoVisible(false, animated: animated)
21892205
}
2206+
2207+
if let validLayout = self.validLayout {
2208+
self.containerLayoutUpdated(validLayout.layout, navigationBarHeight: validLayout.navigationBarHeight, transition: animated ? .animated(duration: 0.2, curve: .easeInOut) : .immediate)
2209+
}
2210+
}
2211+
2212+
private func resetLivePhotoPlayback() {
2213+
self.updateLivePhotoPlayback(isActive: false, animated: false)
21902214
}
21912215

21922216
override func centralityUpdated(isCentral: Bool) {
@@ -2228,7 +2252,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
22282252
}
22292253
}
22302254
} else {
2231-
self.updateLivePhotoHoldPlayback(isActive: false, animated: false)
2255+
self.resetLivePhotoPlayback()
22322256
self.isPlayingPromise.set(false)
22332257
self.isPlaying = false
22342258

@@ -2265,17 +2289,19 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
22652289
if self.skipInitialPause {
22662290
self.skipInitialPause = false
22672291
} else {
2268-
self.updateLivePhotoHoldPlayback(isActive: false, animated: false)
2292+
self.resetLivePhotoPlayback()
22692293
self.ignorePauseStatus = true
22702294
videoNode.pause()
22712295
videoNode.seek(0.0)
22722296
}
22732297
} else {
2274-
self.updateLivePhotoHoldPlayback(isActive: false, animated: false)
2298+
self.resetLivePhotoPlayback()
22752299
if let status = self.playerStatusValue {
22762300
self.maybeStorePlaybackStatus(status: status)
22772301
}
2278-
videoNode.continuePlayingWithoutSound()
2302+
if !self.isLivePhoto {
2303+
videoNode.continuePlayingWithoutSound()
2304+
}
22792305
}
22802306
self.updateDisplayPlaceholder()
22812307
} else if !item.fromPlayingVideo {
@@ -2382,7 +2408,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
23822408

23832409
private var actionAtEnd: MediaPlayerPlayOnceWithSoundActionAtEnd {
23842410
if self.isLivePhoto {
2385-
return self.isPlayingLivePhotoByHolding ? .loop : .stop
2411+
return self.isLivePhotoPlaybackActive ? .loop : .stop
23862412
}
23872413
if let item = self.item {
23882414
if !item.isSecret, let content = item.content as? NativeVideoContent, content.duration <= 30 {
@@ -4082,7 +4108,13 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
40824108
return
40834109
}
40844110
if let edge, case .middle = edge {
4085-
self.updateLivePhotoHoldPlayback(isActive: true, animated: true)
4111+
guard self.isLivePhoto else {
4112+
return
4113+
}
4114+
if !self.isLivePhotoPlaybackActive {
4115+
self.updateLivePhotoPlayback(isActive: true, animated: true)
4116+
}
4117+
self.isLivePhotoGestureActive = true
40864118
} else if let edge, case .right = edge {
40874119
let effectiveRate: Double
40884120
if let current = self.activeEdgeRateState {
@@ -4097,7 +4129,11 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
40974129
}
40984130
videoNode.setBaseRate(effectiveRate)
40994131
} else {
4100-
self.updateLivePhotoHoldPlayback(isActive: false, animated: true)
4132+
if self.isLivePhotoGestureActive {
4133+
self.updateLivePhotoPlayback(isActive: false, animated: true)
4134+
}
4135+
self.isLivePhotoGestureActive = false
4136+
41014137
if let (initialRate, _) = self.activeEdgeRateState {
41024138
self.activeEdgeRateState = nil
41034139
videoNode.setBaseRate(initialRate)
@@ -4154,3 +4190,87 @@ final class HeaderContextReferenceContentSource: ContextReferenceContentSource {
41544190
private func normalizeValue(_ value: CGFloat) -> CGFloat {
41554191
return round(value * 10.0) / 10.0
41564192
}
4193+
4194+
private final class LivePhotoButton: UIView {
4195+
private let context: AccountContext
4196+
4197+
private let backgroundView: GlassBackgroundView
4198+
private let icon = ComponentView<Empty>()
4199+
private let label = ComponentView<Empty>()
4200+
private let button = HighlightTrackingButton()
4201+
4202+
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
4203+
return self.bounds.insetBy(dx: -16.0, dy: -16.0).contains(point)
4204+
}
4205+
4206+
var pressed: () -> Void = {}
4207+
4208+
init(context: AccountContext) {
4209+
self.context = context
4210+
4211+
self.backgroundView = GlassBackgroundView()
4212+
4213+
super.init(frame: .zero)
4214+
4215+
self.addSubview(self.backgroundView)
4216+
self.backgroundView.contentView.addSubview(self.button)
4217+
4218+
self.button.addTarget(self, action: #selector(self.buttonPressed), for: .touchUpInside)
4219+
}
4220+
4221+
required init?(coder: NSCoder) {
4222+
preconditionFailure()
4223+
}
4224+
4225+
@objc private func buttonPressed() {
4226+
self.pressed()
4227+
}
4228+
4229+
func update(isPlaying: Bool = false) -> CGSize {
4230+
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
4231+
4232+
let iconName: String = isPlaying ? "Media Gallery/LivePhotoPlaying" : "Media Gallery/LivePhotoPlay"
4233+
let labelText: String = presentationData.strings.Gallery_Live
4234+
4235+
let iconSize = self.icon.update(
4236+
transition: .immediate,
4237+
component: AnyComponent(
4238+
BundleIconComponent(name: iconName, tintColor: .white)
4239+
),
4240+
environment: {},
4241+
containerSize: CGSize(width: 18.0, height: 18.0)
4242+
)
4243+
let iconFrame = CGRect(origin: CGPoint(x: 8.0, y: floorToScreenPixels((30.0 - iconSize.height) / 2.0)), size: iconSize)
4244+
if let iconView = self.icon.view {
4245+
if iconView.superview == nil {
4246+
iconView.isUserInteractionEnabled = false
4247+
self.backgroundView.contentView.addSubview(iconView)
4248+
}
4249+
iconView.frame = iconFrame
4250+
}
4251+
4252+
let labelSize = self.label.update(
4253+
transition: .immediate,
4254+
component: AnyComponent(
4255+
Text(text: labelText.uppercased(), font: Font.regular(12.0), color: .white)
4256+
),
4257+
environment: {},
4258+
containerSize: CGSize(width: 200.0, height: 18.0)
4259+
)
4260+
let labelFrame = CGRect(origin: CGPoint(x: 28.0, y: floorToScreenPixels((30.0 - labelSize.height) / 2.0)), size: labelSize)
4261+
if let labelView = self.label.view {
4262+
if labelView.superview == nil {
4263+
labelView.isUserInteractionEnabled = false
4264+
self.backgroundView.contentView.addSubview(labelView)
4265+
}
4266+
labelView.frame = labelFrame
4267+
}
4268+
4269+
let size = CGSize(width: 21.0 + labelSize.width + 18.0, height: 30.0)
4270+
self.backgroundView.update(size: size, cornerRadius: size.height * 0.5, isDark: true, tintColor: .init(kind: .panel), isInteractive: true, transition: .immediate)
4271+
self.backgroundView.frame = CGRect(origin: .zero, size: size)
4272+
self.button.frame = CGRect(origin: .zero, size: size).insetBy(dx: -16.0, dy: -16.0)
4273+
4274+
return size
4275+
}
4276+
}

submodules/MediaPickerUI/Sources/LivePhotoButton.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ final class LivePhotoButton: UIView, TGLivePhotoButton {
217217
let size = CGSize(width: 19.0 + labelSize.width + 16.0, height: 18.0)
218218
self.backgroundView.update(size: size, cornerRadius: size.height * 0.5, isDark: true, tintColor: .init(kind: .panel), isInteractive: true, transition: .immediate)
219219
self.backgroundView.frame = CGRect(origin: .zero, size: size)
220-
self.button.frame = CGRect(origin: .zero, size: size)
220+
self.button.frame = CGRect(origin: .zero, size: size).insetBy(dx: -16.0, dy: -16.0)
221221
}
222222
}
223223

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"images" : [
3+
{
4+
"filename" : "play1.pdf",
5+
"idiom" : "universal"
6+
}
7+
],
8+
"info" : {
9+
"author" : "xcode",
10+
"version" : 1
11+
}
12+
}
Binary file not shown.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"images" : [
3+
{
4+
"filename" : "play2.pdf",
5+
"idiom" : "universal"
6+
}
7+
],
8+
"info" : {
9+
"author" : "xcode",
10+
"version" : 1
11+
}
12+
}
Binary file not shown.

0 commit comments

Comments
 (0)