Skip to content

Commit e3241ea

Browse files
committed
Merge remote-tracking branch 'origin/master' into beta
2 parents df45cee + 685ce38 commit e3241ea

7 files changed

Lines changed: 98 additions & 16 deletions

File tree

‎submodules/GalleryData/Sources/GalleryData.swift‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ public func chatMessageGalleryControllerData(
112112
if message.id.peerId.namespace == Namespaces.Peer.CloudUser && message.id.namespace != Namespaces.Message.Cloud {
113113
standalone = true
114114
}
115+
var candidateMedia = message.effectiveMedia
116+
if case let .richTextMedia(mediaId) = mediaSubject {
117+
standalone = true
118+
candidateMedia = candidateMedia.filter { $0.id == mediaId }
119+
}
115120

116121
var galleryMedia: EngineRawMedia?
117122
var otherMedia: EngineRawMedia?
@@ -126,7 +131,7 @@ public func chatMessageGalleryControllerData(
126131
}
127132
}
128133
}
129-
for media in message.effectiveMedia {
134+
for media in candidateMedia {
130135
if let poll = media as? TelegramMediaPoll {
131136
standalone = true
132137
galleryMedia = poll
@@ -294,7 +299,7 @@ public func chatMessageGalleryControllerData(
294299

295300
var source = source
296301
if standalone {
297-
source = .standaloneMessage(message, nil)
302+
source = .standaloneMessage(message, mediaSubject)
298303
}
299304

300305
if internalDocumentItemSupportsMimeType(file.mimeType, fileName: file.fileName ?? "file") {

‎submodules/InstantPageUI/Sources/InstantPageV2Layout.swift‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2703,6 +2703,16 @@ private func layoutParagraph(
27032703
// silently resize existing inline images.
27042704
let attributedString = attributedStringForRichText(text, styleStack: styleStack, inlineButtonMaxWidth: boundingWidth - horizontalInset * 2.0, formatDate: context.formatDate, quoteSource: context.quoteSource(.text))
27052705

2706+
if attributedString.length == 0 {
2707+
let lineString = attributedStringForRichText(.plain("\u{200b}"), styleStack: styleStack, formatDate: context.formatDate)
2708+
let (_, _, lineSize) = layoutTextItem(
2709+
lineString,
2710+
boundingWidth: boundingWidth - horizontalInset * 2.0,
2711+
offset: CGPoint(x: horizontalInset, y: 0.0)
2712+
)
2713+
return [.anchor(InstantPageV2AnchorItem(frame: CGRect(x: horizontalInset, y: 0.0, width: 0.0, height: lineSize.height), name: ""))]
2714+
}
2715+
27062716
let (_, items, _) = layoutTextItem(
27072717
attributedString,
27082718
boundingWidth: boundingWidth - horizontalInset * 2.0,
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import Foundation
2+
3+
/// The track a profile's music strip shows: the first of the profile's saved-music list (`list`, nil where the screen
4+
/// has none). While that list has not answered (loading with nothing in it, before its cache or the server replies:
5+
/// a profile opened for the first time), the full user's track (`CachedUserData.savedMusic`), which the chat has usually
6+
/// fetched already, so the strip is in the profile's first layout and arrives with the transition instead of after it.
7+
/// A list that answered empty shows none, whatever the full user still says.
8+
public func peerInfoProfileMusic<File>(list: (files: [File], isLoading: Bool)?, fullUserMusic: File?) -> File? {
9+
guard let list else {
10+
return fullUserMusic
11+
}
12+
if let first = list.files.first {
13+
return first
14+
}
15+
return list.isLoading ? fullUserMusic : nil
16+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import XCTest
2+
@testable import PeerInfoPaneNode
3+
4+
final class PeerInfoProfileMusicTests: XCTestCase {
5+
// The list's first track once it has one, loading or not.
6+
func test_listTrack() {
7+
XCTAssertEqual(peerInfoProfileMusic(list: (files: [1, 2], isLoading: false), fullUserMusic: 3), 1)
8+
XCTAssertEqual(peerInfoProfileMusic(list: (files: [1, 2], isLoading: true), fullUserMusic: 3), 1)
9+
}
10+
11+
// A list that has not answered yet: the full user's track, so the strip is there from the first layout.
12+
func test_loadingListFallsBackToFullUser() {
13+
XCTAssertEqual(peerInfoProfileMusic(list: (files: [Int](), isLoading: true), fullUserMusic: 3), 3)
14+
XCTAssertNil(peerInfoProfileMusic(list: (files: [Int](), isLoading: true), fullUserMusic: nil))
15+
}
16+
17+
// A list that answered empty: none, even while the full user still carries a track.
18+
func test_answeredEmptyListShowsNone() {
19+
XCTAssertNil(peerInfoProfileMusic(list: (files: [Int](), isLoading: false), fullUserMusic: 3))
20+
}
21+
22+
// No list on the screen: the full user's track.
23+
func test_noList() {
24+
XCTAssertEqual(peerInfoProfileMusic(list: nil, fullUserMusic: 3), 3)
25+
XCTAssertNil(peerInfoProfileMusic(list: nil as (files: [Int], isLoading: Bool)?, fullUserMusic: nil))
26+
}
27+
}

‎submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift‎

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,18 @@ final class PeerInfoHeaderNode: ASDisplayNode {
196196
var hasBottomStrip: Bool {
197197
return self.music != nil
198198
}
199+
200+
/// The track the music strip shows for `peer` and `screenData` (`peerInfoProfileMusic`): none on Settings and on the
201+
/// account's own peer opened as a profile.
202+
func profileMusic(peer: EnginePeer?, screenData: PeerInfoScreenData?) -> TelegramMediaFile? {
203+
guard let peer, peer.id != self.context.account.peerId || self.isMyProfile, let screenData else {
204+
return nil
205+
}
206+
let list = screenData.savedMusicState.map { state -> (files: [TelegramMediaFile], isLoading: Bool) in
207+
return (state.files, state.dataState == .loading)
208+
}
209+
return peerInfoProfileMusic(list: list, fullUserMusic: (screenData.cachedData as? CachedUserData)?.savedMusic)
210+
}
199211

200212
var performButtonAction: ((PeerInfoHeaderButtonKey, PeerInfoHeaderButtonNode?, ContextGesture?) -> Void)?
201213
var requestAvatarExpansion: ((Bool, [AvatarGalleryEntry], AvatarGalleryEntry?, (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?) -> Void)?
@@ -622,14 +634,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
622634
backgroundCoverSubject = nil
623635
}
624636

625-
var currentSavedMusic: TelegramMediaFile?
626-
if let peer, peer.id != self.context.account.peerId || self.isMyProfile, let screenData {
627-
if let savedMusicState = screenData.savedMusicState {
628-
currentSavedMusic = savedMusicState.files.first
629-
} else if let cachedUserData = screenData.cachedData as? CachedUserData {
630-
currentSavedMusic = cachedUserData.savedMusic
631-
}
632-
}
637+
let currentSavedMusic = self.profileMusic(peer: peer, screenData: screenData)
633638
let currentWalletBalance: Int64?
634639
if !self.isSettings, let balance = (screenData?.cachedData as? CachedUserData)?.walletCard?.balance, balance >= 100_000_000 {
635640
currentWalletBalance = balance

‎submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift‎

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
273273
var resolvePeerByNameDisposable: MetaDisposable?
274274
let navigationActionDisposable = MetaDisposable()
275275
let enqueueMediaMessageDisposable = MetaDisposable()
276+
private let openSavedMusicDisposable = MetaDisposable()
276277

277278
private(set) var validLayout: (ContainerViewLayout, CGFloat)?
278279
/// While an expansion has the profile's views they are held still: layouts wait, and the last one is applied when
@@ -2701,6 +2702,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
27012702
self.resolvePeerByNameDisposable?.dispose()
27022703
self.navigationActionDisposable.dispose()
27032704
self.enqueueMediaMessageDisposable.dispose()
2705+
self.openSavedMusicDisposable.dispose()
27042706
self.supportPeerDisposable.dispose()
27052707
self.tipsPeerDisposable.dispose()
27062708
self.shareStatusDisposable?.dispose()
@@ -2920,6 +2922,10 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
29202922
if (previousBusinessLocation == nil) != (currentBusinessLocation != nil) {
29212923
infoUpdated = true
29222924
}
2925+
// The music strip arriving or leaving changes the header's height, and the page moves with it.
2926+
if self.hasProfileMusic(data: previousData) != self.hasProfileMusic(data: data) {
2927+
infoUpdated = true
2928+
}
29232929
}
29242930

29252931
self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: self.didSetReady && (membersUpdated || infoUpdated) ? .animated(duration: 0.3, curve: .spring) : .immediate)
@@ -3088,6 +3094,10 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
30883094
}
30893095
}
30903096

3097+
private func hasProfileMusic(data: PeerInfoScreenData?) -> Bool {
3098+
return self.headerNode.profileMusic(peer: data?.savedMessagesPeer ?? data?.peer, screenData: data) != nil
3099+
}
3100+
30913101
var previousSavedMusicTimestamp: Double?
30923102
private func displaySavedMusic() {
30933103
guard let savedMusicContext = self.data?.savedMusicContext else {
@@ -3100,15 +3110,21 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
31003110
}
31013111
self.previousSavedMusicTimestamp = currentTimestamp
31023112

3103-
let _ = (self.context.sharedContext.mediaManager.globalMediaPlayerState
3113+
// Until the list answers, the strip shows the full user's track (`peerInfoProfileMusic`); the player plays the
3114+
// list, so it waits for it.
3115+
let answeredList = savedMusicContext.state
3116+
|> filter { state in
3117+
return !state.files.isEmpty || state.dataState != .loading
3118+
}
31043119
|> take(1)
3105-
|> deliverOnMainQueue).start(next: { [weak self] accountStateAndType in
3120+
self.openSavedMusicDisposable.set((combineLatest(answeredList, self.context.sharedContext.mediaManager.globalMediaPlayerState |> take(1))
3121+
|> deliverOnMainQueue).start(next: { [weak self] listState, accountStateAndType in
31063122
guard let self else {
31073123
return
31083124
}
31093125
let peerId = self.peerId
31103126
var initialId: Int32
3111-
if let initialFileId = self.data?.savedMusicState?.files.first?.fileId {
3127+
if let initialFileId = listState.files.first?.fileId {
31123128
initialId = Int32(clamping: initialFileId.id % Int64(Int32.max))
31133129
} else {
31143130
initialId = 0
@@ -3139,7 +3155,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
31393155
musicController.navigationPresentation = .flatModal
31403156
self.controller?.push(musicController)
31413157
}
3142-
})
3158+
}))
31433159
}
31443160

31453161
func openAutoremove(currentValue: Int32?) {
@@ -5568,7 +5584,10 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
55685584
self.contentOffsetWhenLent = nil
55695585
if let held = self.layoutHeldDuringExpansion ?? self.validLayout.flatMap({ (layout: $0.0, navigationHeight: $0.1) }) {
55705586
self.layoutHeldDuringExpansion = nil
5571-
self.containerLayoutUpdated(layout: held.layout, navigationHeight: held.navigationHeight, transition: .immediate)
5587+
// The music strip arrived or left while the views were lent (the header still has what it had when they were
5588+
// lent): it moves in as it does outside an expansion, instead of appearing in one frame.
5589+
let stripChanged = self.headerNode.hasBottomStrip != self.hasProfileMusic(data: self.data)
5590+
self.containerLayoutUpdated(layout: held.layout, navigationHeight: held.navigationHeight, transition: stripChanged ? .animated(duration: 0.3, curve: .spring) : .immediate)
55725591
}
55735592
let actions = self.actionsAfterExpansion
55745593
self.actionsAfterExpansion = []

‎submodules/TelegramUI/Components/ShareScreen/Sources/ShareScreen.swift‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,7 @@ private final class ShareScreenComponent: Component {
946946
})),
947947
rightItem: rightItem,
948948
hasTopEdgeEffect: loadingNode == nil && nestedPeer != nil,
949-
hasBottomEdgeEffect: loadingNode == nil && (!model.isSearching || !selected.isEmpty),
949+
hasBottomEdgeEffect: loadingNode == nil && (!selected.isEmpty || (!model.isSearching && (copyTitle != nil || bottomAccessory != nil))),
950950
bottomEdgeEffectColor: isEmbedded && selected.isEmpty && copyTitle == nil ? .clear : nil,
951951
bottomItem: loadingNode == nil ? bottom : nil,
952952
bottomEdgeEffectExtension: loadingNode == nil && !model.isSearching && hostScreen?.startAtTitle != nil ? 60.0 : 0.0,

0 commit comments

Comments
 (0)