Skip to content

Commit 55b5dda

Browse files
authored
Merge pull request #360 from bwees-forks/refactor/user-page
2 parents 9b59273 + e594a59 commit 55b5dda

7 files changed

Lines changed: 148 additions & 110 deletions

File tree

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import SwiftUI
2+
3+
extension View {
4+
/// Leaves the navigation bar title empty while the header is on screen, then fades
5+
/// in `title` (the entity name) once the user scrolls past `revealAfter` points.
6+
/// Pass the header's measured height (see `scrollRevealHeaderHeight`) so the reveal
7+
/// tracks the real header size and adapts to Dynamic Type.
8+
/// Pairs with `.navigationBarTitleDisplayMode(.inline)`.
9+
func scrollRevealNavigationTitle(_ title: String, revealAfter: CGFloat = 150) -> some View {
10+
modifier(ScrollRevealNavigationTitle(title: title, revealAfter: revealAfter))
11+
}
12+
13+
/// Reports the measured height of the scroll-reveal header into `height`, so the
14+
/// title reveals based on the header's real (Dynamic Type-aware) size rather than a
15+
/// fixed threshold. Attach to the header content, then feed `height` to
16+
/// `scrollRevealNavigationTitle(_:revealAfter:)`.
17+
func scrollRevealHeaderHeight(into height: Binding<CGFloat>) -> some View {
18+
onGeometryChange(for: CGFloat.self) { $0.size.height } action: { height.wrappedValue = $0 }
19+
}
20+
}
21+
22+
private struct ScrollRevealNavigationTitle: ViewModifier {
23+
let title: String
24+
let revealAfter: CGFloat
25+
26+
@State private var isRevealed = false
27+
28+
func body(content: Content) -> some View {
29+
content
30+
.onScrollGeometryChange(for: Bool.self) { geometry in
31+
geometry.contentOffset.y > revealAfter
32+
} action: { _, revealed in
33+
guard revealed != isRevealed else { return }
34+
withAnimation(.easeInOut(duration: 0.2)) { isRevealed = revealed }
35+
}
36+
.toolbar {
37+
ToolbarItem(placement: .principal) {
38+
Text(title)
39+
.font(.headline)
40+
.opacity(isRevealed ? 1 : 0)
41+
}
42+
}
43+
}
44+
}

MC1/Views/Chats/Room/RoomInfoSheet.swift

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ struct RoomInfoSheet: View {
1616
@State private var favoriteTask: Task<Void, Never>?
1717
@State private var showTelemetry = false
1818
@State private var showSettings = false
19+
@State private var headerHeight: CGFloat = 150
1920

2021
init(session: RemoteNodeSessionDTO) {
2122
self.session = session
@@ -27,17 +28,27 @@ struct RoomInfoSheet: View {
2728
NavigationStack {
2829
List {
2930
Section {
30-
HStack {
31-
Spacer()
32-
NodeAvatar(publicKey: session.publicKey, role: .roomServer, size: 80)
33-
Spacer()
31+
VStack(spacing: 12) {
32+
NodeAvatar(publicKey: session.publicKey, role: .roomServer, size: 150)
33+
34+
VStack(spacing: 4) {
35+
Text(session.name)
36+
.font(.title2)
37+
.bold()
38+
39+
Text(L10n.RemoteNodes.RemoteNodes.Auth.typeRoom)
40+
.font(.subheadline)
41+
.foregroundStyle(.secondary)
42+
}
3443
}
44+
.frame(maxWidth: .infinity)
45+
.scrollRevealHeaderHeight(into: $headerHeight)
3546
.listRowBackground(Color.clear)
3647
}
3748

3849
ConversationQuickActionsSection(
39-
notificationLevel: $notificationLevel,
4050
isFavorite: $isFavorite,
51+
notificationLevel: $notificationLevel,
4152
availableLevels: NotificationLevel.roomLevels
4253
)
4354
.onChange(of: notificationLevel) { _, newValue in
@@ -102,10 +113,11 @@ struct RoomInfoSheet: View {
102113
.themedRowBackground(theme)
103114
}
104115
.themedCanvas(theme)
105-
.navigationTitle(Strings.infoTitle)
106116
.navigationBarTitleDisplayMode(.inline)
117+
.scrollRevealNavigationTitle(session.name, revealAfter: headerHeight)
118+
.contentMargins(.top, 0, for: .scrollContent)
107119
.toolbar {
108-
ToolbarItem(placement: .cancellationAction) {
120+
ToolbarItem(placement: .confirmationAction) {
109121
Button(L10n.Localizable.Common.done) { dismiss() }
110122
}
111123
}

MC1/Views/Chats/Sheets/ChannelInfoSheet.swift

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ struct ChannelInfoSheet: View {
3333
@State private var discoveredNewRegions: [String] = []
3434
@State private var showingDiscoveryResults = false
3535
@State private var selectedFloodScope: ChannelFloodScope
36+
@State private var headerHeight: CGFloat = 150
3637

3738
init(channel: ChannelDTO, onClearMessages: @escaping () -> Void, onDelete: @escaping () -> Void) {
3839
self.channel = channel
@@ -47,12 +48,12 @@ struct ChannelInfoSheet: View {
4748
NavigationStack {
4849
Form {
4950
// Channel Header Section
50-
ChannelInfoHeaderSection(channel: channel)
51+
ChannelInfoHeaderSection(channel: channel, measuredHeight: $headerHeight)
5152

5253
// Quick Actions Section
5354
ConversationQuickActionsSection(
54-
notificationLevel: $notificationLevel,
5555
isFavorite: $isFavorite,
56+
notificationLevel: $notificationLevel,
5657
availableLevels: NotificationLevel.channelLevels
5758
)
5859
.onChange(of: notificationLevel) { _, newValue in
@@ -122,10 +123,11 @@ struct ChannelInfoSheet: View {
122123
)
123124
}
124125
.themedCanvas(theme)
125-
.navigationTitle(L10n.Chats.Chats.ChannelInfo.title)
126126
.navigationBarTitleDisplayMode(.inline)
127+
.scrollRevealNavigationTitle(channel.displayName, revealAfter: headerHeight)
128+
.contentMargins(.top, 0, for: .scrollContent)
127129
.toolbar {
128-
ToolbarItem(placement: .cancellationAction) {
130+
ToolbarItem(placement: .confirmationAction) {
129131
Button(L10n.Chats.Chats.Common.done) {
130132
dismiss()
131133
}
@@ -353,6 +355,7 @@ struct ChannelInfoSheet: View {
353355

354356
private struct ChannelInfoHeaderSection: View {
355357
let channel: ChannelDTO
358+
@Binding var measuredHeight: CGFloat
356359

357360
private var channelTypeLabel: String {
358361
if channel.isPublicChannel {
@@ -366,11 +369,10 @@ private struct ChannelInfoHeaderSection: View {
366369

367370
var body: some View {
368371
Section {
369-
HStack {
370-
Spacer()
371-
VStack(spacing: 12) {
372-
ChannelAvatar(channel: channel, size: 80)
372+
VStack(spacing: 12) {
373+
ChannelAvatar(channel: channel, size: 150)
373374

375+
VStack(spacing: 4) {
374376
Text(channel.displayName)
375377
.font(.title2)
376378
.bold()
@@ -379,8 +381,9 @@ private struct ChannelInfoHeaderSection: View {
379381
.font(.subheadline)
380382
.foregroundStyle(.secondary)
381383
}
382-
Spacer()
383384
}
385+
.frame(maxWidth: .infinity)
386+
.scrollRevealHeaderHeight(into: $measuredHeight)
384387
.listRowBackground(Color.clear)
385388
}
386389
}
@@ -474,33 +477,28 @@ private struct ChannelInfoActionsSection: View {
474477

475478
var body: some View {
476479
Section {
477-
Button {
480+
Button(role: .destructive) {
478481
showingClearMessagesConfirmation = true
479482
} label: {
480483
HStack {
481-
Spacer()
484+
Label(L10n.Chats.Chats.ChannelInfo.clearMessagesButton, systemImage: "xmark.circle")
482485
if isClearingMessages {
486+
Spacer()
483487
ProgressView()
484-
} else {
485-
Label(L10n.Chats.Chats.ChannelInfo.clearMessagesButton, systemImage: "xmark.circle")
486488
}
487-
Spacer()
488489
}
489490
}
490491
.disabled(isActionInProgress)
491-
.alignmentGuide(.listRowSeparatorLeading) { _ in 0 }
492492

493493
Button(role: .destructive) {
494494
showingDeleteConfirmation = true
495495
} label: {
496496
HStack {
497-
Spacer()
497+
Label(L10n.Chats.Chats.ChannelInfo.deleteButton, systemImage: "trash")
498498
if isDeleting {
499+
Spacer()
499500
ProgressView()
500-
} else {
501-
Label(L10n.Chats.Chats.ChannelInfo.deleteButton, systemImage: "trash")
502501
}
503-
Spacer()
504502
}
505503
}
506504
.disabled(isActionInProgress)

MC1/Views/Components/ConversationQuickActionsSection.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,28 @@ import SwiftUI
33

44
struct ConversationQuickActionsSection: View {
55
@Environment(\.appTheme) private var theme
6-
@Binding var notificationLevel: NotificationLevel
76
@Binding var isFavorite: Bool
7+
@Binding var notificationLevel: NotificationLevel
88
let availableLevels: [NotificationLevel]
99

1010
init(
11-
notificationLevel: Binding<NotificationLevel>,
1211
isFavorite: Binding<Bool>,
12+
notificationLevel: Binding<NotificationLevel>,
1313
availableLevels: [NotificationLevel] = NotificationLevel.allCases
1414
) {
15-
_notificationLevel = notificationLevel
1615
_isFavorite = isFavorite
16+
_notificationLevel = notificationLevel
1717
self.availableLevels = availableLevels
1818
}
1919

2020
var body: some View {
2121
Section {
22-
VStack(spacing: 16) {
23-
NotificationLevelPicker(selection: $notificationLevel, availableLevels: availableLevels)
22+
NotificationLevelPicker(selection: $notificationLevel, availableLevels: availableLevels)
23+
.listRowInsets(EdgeInsets(top: 12, leading: 16, bottom: 12, trailing: 16))
2424

25-
FavoriteToggleRow(isFavorite: $isFavorite)
25+
Toggle(isOn: $isFavorite) {
26+
Label(L10n.Chats.Chats.Action.favorite, systemImage: "star")
2627
}
27-
.listRowInsets(EdgeInsets(top: 12, leading: 16, bottom: 12, trailing: 16))
2828
}
2929
.themedRowBackground(theme)
3030
}

MC1/Views/Components/FavoriteToggleRow.swift

Lines changed: 0 additions & 22 deletions
This file was deleted.

0 commit comments

Comments
 (0)