mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-05 19:28:46 +02:00
Update tgwatch
This commit is contained in:
parent
55619c54f9
commit
3a62d3417f
3 changed files with 51 additions and 34 deletions
|
|
@ -1,17 +1,20 @@
|
|||
import SwiftUI
|
||||
import UIKit
|
||||
|
||||
/// A 36pt circular chat avatar. Renders (priority): Saved-Messages bookmark glyph;
|
||||
/// A circular chat avatar (default 36pt, customizable via `size`). Renders (priority):
|
||||
/// crisp downloaded photo; blurred minithumbnail placeholder; initials on a
|
||||
/// per-chat color. Drives viewport-based download of the small photo via
|
||||
/// `.onScrollVisibilityChange` (same as `PhotoBubbleView`) — only while the photo
|
||||
/// exists and hasn't downloaded yet.
|
||||
/// per-chat color. When embedded in a `ScrollView`, drives viewport-based download
|
||||
/// of the small photo via `.onScrollVisibilityChange` (same as `PhotoBubbleView`) —
|
||||
/// only while the photo exists and hasn't downloaded yet. Outside a scroll
|
||||
/// container (e.g. as a `ToolbarItem`), the visibility callback fires once on
|
||||
/// appear and once on disappear, so the download path is "request on chat open,
|
||||
/// cancel on chat close."
|
||||
struct AvatarView: View {
|
||||
let avatar: AvatarVisual
|
||||
var onRequestDownload: (Int) -> Void = { _ in }
|
||||
var onCancelDownload: (Int) -> Void = { _ in }
|
||||
|
||||
private let size: CGFloat = 36
|
||||
var size: CGFloat = 36
|
||||
|
||||
var body: some View {
|
||||
content
|
||||
|
|
|
|||
|
|
@ -13,39 +13,42 @@ struct ChatListView: View {
|
|||
@FocusState private var listFocused: Bool
|
||||
|
||||
var body: some View {
|
||||
ZStack(alignment: .top) {
|
||||
NavigationStack {
|
||||
ScrollViewReader { proxy in
|
||||
VStack(spacing: 0) {
|
||||
if case .failed(let message) = store.loadState(for: store.currentFolder) {
|
||||
banner(text: message, kind: .retry)
|
||||
}
|
||||
if let err = client.lastError, dismissedLastError != err {
|
||||
banner(text: err, kind: .dismiss)
|
||||
}
|
||||
content(proxy: proxy)
|
||||
NavigationStack {
|
||||
ScrollViewReader { proxy in
|
||||
VStack(spacing: 0) {
|
||||
if case .failed(let message) = store.loadState(for: store.currentFolder) {
|
||||
banner(text: message, kind: .retry)
|
||||
}
|
||||
.navigationDestination(for: ChatRow.self) { row in
|
||||
MessageListView(row: row)
|
||||
if let err = client.lastError, dismissedLastError != err {
|
||||
banner(text: err, kind: .dismiss)
|
||||
}
|
||||
.navigationTitle("")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
// Must live INSIDE the NavigationStack so the modifier's
|
||||
// .navigationDestination(isPresented:) attaches to it.
|
||||
.accountSwitcherSheet(presentation: .push, logoutAffordance: .allowed)
|
||||
content(proxy: proxy)
|
||||
}
|
||||
// Gradient is .overlay on the chat-list VStack — NOT a sibling
|
||||
// of NavigationStack. Earlier this lived in an outer ZStack and
|
||||
// rendered on top of every pushed destination (e.g. MessageListView's
|
||||
// back chevron + title), since ZStack draws siblings front-to-back
|
||||
// regardless of which destination is current. Scoping it to the
|
||||
// root view's overlay restricts it to the chat list itself.
|
||||
.overlay(alignment: .top) {
|
||||
LinearGradient(
|
||||
colors: [.black.opacity(0.8), .black.opacity(0)],
|
||||
startPoint: .top,
|
||||
endPoint: .bottom
|
||||
)
|
||||
.frame(height: 48)
|
||||
.allowsHitTesting(false)
|
||||
.ignoresSafeArea(edges: .top)
|
||||
}
|
||||
.navigationDestination(for: ChatRow.self) { row in
|
||||
MessageListView(row: row)
|
||||
}
|
||||
.navigationTitle("")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
// Must live INSIDE the NavigationStack so the modifier's
|
||||
// .navigationDestination(isPresented:) attaches to it.
|
||||
.accountSwitcherSheet(presentation: .push, logoutAffordance: .allowed)
|
||||
}
|
||||
// Gradient that fades chat content behind the system clock area,
|
||||
// so rows scrolling up under the clock don't visually collide
|
||||
// with the time readout.
|
||||
LinearGradient(
|
||||
colors: [.black.opacity(0.8), .black.opacity(0)],
|
||||
startPoint: .top,
|
||||
endPoint: .bottom
|
||||
)
|
||||
.frame(height: 48)
|
||||
.allowsHitTesting(false)
|
||||
.ignoresSafeArea(edges: .top)
|
||||
}
|
||||
.accessibilityIdentifier("chatListView")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,17 @@ struct MessageListView: View {
|
|||
}
|
||||
.navigationTitle(row.title)
|
||||
.accessibilityIdentifier("messageListView")
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
AvatarView(
|
||||
avatar: row.avatar,
|
||||
onRequestDownload: { fileId in store?.requestFileDownload(fileId: fileId) },
|
||||
onCancelDownload: { fileId in store?.cancelFileDownload(fileId: fileId) },
|
||||
size: 36
|
||||
)
|
||||
.glassEffect(in: Circle())
|
||||
}
|
||||
}
|
||||
.sheet(item: $presentedPhoto) { photo in
|
||||
PhotoViewerView(photo: photo)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue