From e5a011573ee47ae7cd0d268f25652659a94e9ab1 Mon Sep 17 00:00:00 2001 From: Philipp Walter Date: Tue, 5 May 2026 10:14:42 +0200 Subject: [PATCH] refactor(ui): InsetHeaderScrollView, shared tab swipes --- .../Contents.json | 2 +- .../lightbulb-figure.png | Bin 0 -> 9619 bytes .../lightning.imageset/lightning.png | Bin 56245 -> 0 bytes .../lightbulb.imageset}/Contents.json | 0 .../lightbulb.imageset/lightbulb.png | Bin Bitkit/Components/Activity/ActivityList.swift | 2 - Bitkit/Components/Home/SuggestionsCard.swift | 57 ------ Bitkit/Components/InsetHeaderScrollView.swift | 64 ++++++ Bitkit/Components/SuggestionCard.swift | 89 +++++++++ .../{Home => Widgets}/Suggestions.swift | 16 +- Bitkit/Extensions/View+AllowSwipeBack.swift | 21 -- Bitkit/Extensions/View+SwipeGestures.swift | 55 +++++ .../Views/Settings/MainSettingsScreen.swift | 38 ++-- Bitkit/Views/Settings/SupportScreen.swift | 169 ++++++++-------- Bitkit/Views/Shop/ShopDiscover.swift | 189 +++++++----------- .../Wallets/Activity/AllActivityView.swift | 142 ++++++------- changelog.d/next/535.changed.md | 1 + 17 files changed, 469 insertions(+), 376 deletions(-) rename Bitkit/Assets.xcassets/Illustrations/{lightbulb.imageset => lightbulb-figure.imageset}/Contents.json (86%) create mode 100644 Bitkit/Assets.xcassets/Illustrations/lightbulb-figure.imageset/lightbulb-figure.png delete mode 100644 Bitkit/Assets.xcassets/Illustrations/lightning.imageset/lightning.png rename Bitkit/Assets.xcassets/{Illustrations/lightning.imageset => icons/lightbulb.imageset}/Contents.json (100%) rename Bitkit/Assets.xcassets/{Illustrations => icons}/lightbulb.imageset/lightbulb.png (100%) delete mode 100644 Bitkit/Components/Home/SuggestionsCard.swift create mode 100644 Bitkit/Components/InsetHeaderScrollView.swift create mode 100644 Bitkit/Components/SuggestionCard.swift rename Bitkit/Components/{Home => Widgets}/Suggestions.swift (94%) delete mode 100644 Bitkit/Extensions/View+AllowSwipeBack.swift create mode 100644 Bitkit/Extensions/View+SwipeGestures.swift create mode 100644 changelog.d/next/535.changed.md diff --git a/Bitkit/Assets.xcassets/Illustrations/lightbulb.imageset/Contents.json b/Bitkit/Assets.xcassets/Illustrations/lightbulb-figure.imageset/Contents.json similarity index 86% rename from Bitkit/Assets.xcassets/Illustrations/lightbulb.imageset/Contents.json rename to Bitkit/Assets.xcassets/Illustrations/lightbulb-figure.imageset/Contents.json index 2a4514b86..5ba053448 100644 --- a/Bitkit/Assets.xcassets/Illustrations/lightbulb.imageset/Contents.json +++ b/Bitkit/Assets.xcassets/Illustrations/lightbulb-figure.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "lightbulb.png", + "filename" : "lightbulb-figure.png", "idiom" : "universal", "scale" : "1x" }, diff --git a/Bitkit/Assets.xcassets/Illustrations/lightbulb-figure.imageset/lightbulb-figure.png b/Bitkit/Assets.xcassets/Illustrations/lightbulb-figure.imageset/lightbulb-figure.png new file mode 100644 index 0000000000000000000000000000000000000000..6f5838659f0299fd1ae30826f4090f40d883effd GIT binary patch literal 9619 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 literal 0 HcmV?d00001 diff --git a/Bitkit/Assets.xcassets/Illustrations/lightning.imageset/lightning.png b/Bitkit/Assets.xcassets/Illustrations/lightning.imageset/lightning.png deleted file mode 100644 index 80d8a7684b7dd51bf10ec2aeeebb77d571fbd841..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56245 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 Void = {} - - var body: some View { - ZStack(alignment: .topTrailing) { - VStack(alignment: .leading, spacing: 0) { - Spacer() - - Image(data.imageName) - .resizable() - .interpolation(.high) - .scaledToFit() - .frame(height: 80) - - Text(data.title) - .font(.custom(Fonts.black, size: 20)) - .lineLimit(1) - .kerning(-0.5) - .textCase(.uppercase) - .padding(.top, 4) - - CaptionBText(data.description) - } - .padding() - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) - .background( - RoundedRectangle(cornerRadius: 16) - .fill( - LinearGradient( - gradient: Gradient(stops: [ - .init(color: data.color, location: 0.0), - .init(color: Color.black.opacity(0.1), location: 0.9), - .init(color: Color.black, location: 1.0), - ]), - startPoint: .top, - endPoint: .bottom - ) - ) - ) - - Button(action: onDismiss) { - Image("x-mark") - .resizable() - .aspectRatio(contentMode: .fit) - .foregroundColor(.textSecondary) - .frame(width: 16, height: 16) - .padding(8) - } - .padding(8) - .accessibilityIdentifier("SuggestionDismiss") - .accessibility(label: Text("Dismiss \(data.title)")) - } - } -} diff --git a/Bitkit/Components/InsetHeaderScrollView.swift b/Bitkit/Components/InsetHeaderScrollView.swift new file mode 100644 index 000000000..d7b8ec9bd --- /dev/null +++ b/Bitkit/Components/InsetHeaderScrollView.swift @@ -0,0 +1,64 @@ +import SwiftUI + +// MARK: - InsetHeaderScrollView + +// Measured top header (`safeAreaInset`) and scroll content with `minHeight` to fill the viewport below it. +// Optional `scrollModifier` for refresh, margins, etc. + +private enum HeaderHeightPreferenceKey: PreferenceKey { + static var defaultValue: CGFloat = 0 + + static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { + let next = nextValue() + guard next > 0 else { return } + value = next + } +} + +private struct HeaderHeightMeasure: View { + var body: some View { + GeometryReader { proxy in + Color.clear.preference(key: HeaderHeightPreferenceKey.self, value: proxy.size.height) + } + } +} + +struct InsetHeaderScrollView: View { + let header: () -> Header + let content: () -> Content + let scrollModifier: ScrollModifier + + @State private var headerHeight: CGFloat = 0 + + init( + header: @escaping () -> Header, + content: @escaping () -> Content, + scrollModifier: ScrollModifier = EmptyModifier() + ) { + self.header = header + self.content = content + self.scrollModifier = scrollModifier + } + + var body: some View { + GeometryReader { geo in + ScrollView(showsIndicators: false) { + content() + .frame(minHeight: contentMinHeight(in: geo), alignment: .top) + } + .safeAreaInset(edge: .top, spacing: 0) { + header().background(HeaderHeightMeasure()) + } + .modifier(scrollModifier) + .onPreferenceChange(HeaderHeightPreferenceKey.self) { newValue in + if newValue > 0 { headerHeight = newValue } + } + } + } + + /// Before the first header measurement, use full height so `minHeight` is non-negative. + private func contentMinHeight(in geo: GeometryProxy) -> CGFloat { + let insetTop = headerHeight > 0 ? headerHeight : 0 + return max(0, geo.size.height - insetTop) + } +} diff --git a/Bitkit/Components/SuggestionCard.swift b/Bitkit/Components/SuggestionCard.swift new file mode 100644 index 000000000..49918181a --- /dev/null +++ b/Bitkit/Components/SuggestionCard.swift @@ -0,0 +1,89 @@ +import SwiftUI + +/// Shared gradient tile used by suggestions widget and shop discover +struct SuggestionCard: View { + let title: String + let description: String + let imageName: String + let accentColor: Color + let onTap: () -> Void + let onDismiss: (() -> Void)? + + init( + title: String, + description: String, + imageName: String, + accentColor: Color, + onTap: @escaping () -> Void, + onDismiss: (() -> Void)? = nil + ) { + self.title = title + self.description = description + self.imageName = imageName + self.accentColor = accentColor + self.onTap = onTap + self.onDismiss = onDismiss + } + + var body: some View { + ZStack(alignment: .topTrailing) { + Button(action: onTap) { + VStack(alignment: .leading, spacing: 0) { + Spacer() + + Image(imageName) + .resizable() + .scaledToFit() + .frame(width: 96, height: 96) + .frame(maxWidth: .infinity, alignment: .center) + + Text(title) + .font(.custom(Fonts.black, size: 20)) + .lineLimit(1) + .kerning(-0.5) + .textCase(.uppercase) + .padding(.top, 4) + + CaptionBText(description) + } + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) + .padding(.vertical, 12) + .padding(.horizontal, 16) + .background( + RoundedRectangle(cornerRadius: 16) + .fill( + LinearGradient( + gradient: Gradient(stops: [ + .init(color: accentColor, location: 0.0), + .init(color: Color.black.opacity(0.1), location: 0.9), + .init(color: Color.black, location: 1.0), + ]), + startPoint: .top, + endPoint: .bottom + ) + ) + ) + } + .buttonStyle(.plain) + .zIndex(0) + + if let onDismiss { + Button(action: onDismiss) { + Image("x-mark") + .resizable() + .aspectRatio(contentMode: .fit) + .foregroundColor(.textSecondary) + .frame(width: 16, height: 16) + .padding(8) + .contentShape(Rectangle()) + } + .padding(8) + .contentShape(Rectangle()) + .accessibilityIdentifier("SuggestionDismiss") + .accessibility(label: Text("Dismiss \(title)")) + .buttonStyle(.plain) + .zIndex(1) + } + } + } +} diff --git a/Bitkit/Components/Home/Suggestions.swift b/Bitkit/Components/Widgets/Suggestions.swift similarity index 94% rename from Bitkit/Components/Home/Suggestions.swift rename to Bitkit/Components/Widgets/Suggestions.swift index 676bdff8c..7b38f3b2c 100644 --- a/Bitkit/Components/Home/Suggestions.swift +++ b/Bitkit/Components/Widgets/Suggestions.swift @@ -75,7 +75,7 @@ let cards: [SuggestionCardData] = [ id: "support", title: t("cards__support__title"), description: t("cards__support__description"), - imageName: "lightbulb", + imageName: "lightbulb-figure", color: .yellow24, action: .support ), @@ -245,10 +245,16 @@ struct Suggestions: View { spacing: 16 ) { ForEach(visibleCards) { card in - SuggestionCard(data: card, onDismiss: { dismissCard(card) }) - .onTapGesture { if !isPreview { onItemTap(card) } } - .accessibilityElement(children: .contain) - .accessibilityIdentifier("Suggestion-\(card.accessibilityId)") + SuggestionCard( + title: card.title, + description: card.description, + imageName: card.imageName, + accentColor: card.color, + onTap: { if !isPreview { onItemTap(card) } }, + onDismiss: { dismissCard(card) } + ) + .accessibilityElement(children: .contain) + .accessibilityIdentifier("Suggestion-\(card.accessibilityId)") } } .allowsHitTesting(!isPreview) diff --git a/Bitkit/Extensions/View+AllowSwipeBack.swift b/Bitkit/Extensions/View+AllowSwipeBack.swift deleted file mode 100644 index 81949857a..000000000 --- a/Bitkit/Extensions/View+AllowSwipeBack.swift +++ /dev/null @@ -1,21 +0,0 @@ -import SwiftUI - -extension View { - /// Controls whether the interactive swipe-back gesture is enabled on this screen. - /// Use `.allowSwipeBack(false)` on screens that use a custom header without a back button - /// (e.g. `SheetHeader` with default `showBackButton: false`) so users can't swipe to dismiss. - /// Default is `true`; only apply this modifier when you want to disable the gesture. - func allowSwipeBack(_ allowed: Bool) -> some View { - modifier(AllowSwipeBackModifier(allowed: allowed)) - } -} - -private struct AllowSwipeBackModifier: ViewModifier { - let allowed: Bool - - func body(content: Content) -> some View { - content - .onAppear { SwipeBackState.allowSwipeBack = allowed } - .onDisappear { SwipeBackState.allowSwipeBack = true } - } -} diff --git a/Bitkit/Extensions/View+SwipeGestures.swift b/Bitkit/Extensions/View+SwipeGestures.swift new file mode 100644 index 000000000..b713e9118 --- /dev/null +++ b/Bitkit/Extensions/View+SwipeGestures.swift @@ -0,0 +1,55 @@ +import SwiftUI + +// Swipe-to-go-back (nav stack) and horizontal swipes between `SegmentedControl` tabs. + +extension View { + /// Controls whether the interactive swipe-back gesture is enabled on this screen. + /// Use `.allowSwipeBack(false)` on screens that use a custom header without a back button + /// (e.g. `SheetHeader` with default `showBackButton: false`) so users can't swipe to dismiss. + /// Default is `true`; only apply this modifier when you want to disable the gesture. + func allowSwipeBack(_ allowed: Bool) -> some View { + modifier(AllowSwipeBackModifier(allowed: allowed)) + } + + // MARK: Segmented tab swipes + + /// Swipe left/right to move between adjacent tabs (same order as `T.allCases` / `SegmentedControl`). + func swipeSegmentedTabs( + selection: Binding, + minimumDragDistance: CGFloat = 20, + swipeThreshold: CGFloat = 50, + animation: Animation = .easeInOut(duration: 0.2) + ) -> some View { + highPriorityGesture( + DragGesture(minimumDistance: minimumDragDistance, coordinateSpace: .local) + .onEnded { value in + let horizontalAmount = value.translation.width + let verticalAmount = value.translation.height + guard abs(horizontalAmount) > abs(verticalAmount) else { return } + + let tabs = Array(T.allCases) + guard let currentIndex = tabs.firstIndex(of: selection.wrappedValue) else { return } + + if horizontalAmount < -swipeThreshold, currentIndex < tabs.count - 1 { + withAnimation(animation) { + selection.wrappedValue = tabs[currentIndex + 1] + } + } else if horizontalAmount > swipeThreshold, currentIndex > 0 { + withAnimation(animation) { + selection.wrappedValue = tabs[currentIndex - 1] + } + } + } + ) + } +} + +private struct AllowSwipeBackModifier: ViewModifier { + let allowed: Bool + + func body(content: Content) -> some View { + content + .onAppear { SwipeBackState.allowSwipeBack = allowed } + .onDisappear { SwipeBackState.allowSwipeBack = true } + } +} diff --git a/Bitkit/Views/Settings/MainSettingsScreen.swift b/Bitkit/Views/Settings/MainSettingsScreen.swift index 93088c337..00506a780 100644 --- a/Bitkit/Views/Settings/MainSettingsScreen.swift +++ b/Bitkit/Views/Settings/MainSettingsScreen.swift @@ -22,22 +22,34 @@ struct MainSettingsScreen: View { } var body: some View { - VStack(alignment: .leading, spacing: 0) { - NavigationBar(title: t("settings__settings")) - .padding(.horizontal, 16) + InsetHeaderScrollView( + header: { + VStack(spacing: 0) { + NavigationBar(title: t("settings__settings")) + .padding(.horizontal, 16) - SegmentedControl(selectedTab: $selectedTab, tabItems: settingsTabItems) - .padding(.horizontal, 16) - - Group { - switch selectedTab { - case .general: GeneralSettingsView() - case .security: SecuritySettingsView() - case .advanced: AdvancedSettingsView() + SegmentedControl(selectedTab: $selectedTab, tabItems: settingsTabItems) + .padding(.horizontal, 16) + } + .background( + BlurView() + .ignoresSafeArea(edges: .top) + ) + .compositingGroup() + .shadow(color: Color.black.opacity(0.5), radius: 8, x: 0, y: 20) + }, + content: { + Group { + switch selectedTab { + case .general: GeneralSettingsView() + case .security: SecuritySettingsView() + case .advanced: AdvancedSettingsView() + } } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .swipeSegmentedTabs(selection: $selectedTab) } - .frame(maxWidth: .infinity, maxHeight: .infinity) - } + ) .navigationBarHidden(true) } } diff --git a/Bitkit/Views/Settings/SupportScreen.swift b/Bitkit/Views/Settings/SupportScreen.swift index 2feb70bf6..7e8ce0d58 100644 --- a/Bitkit/Views/Settings/SupportScreen.swift +++ b/Bitkit/Views/Settings/SupportScreen.swift @@ -61,103 +61,102 @@ struct SupportScreen: View { } var body: some View { - VStack(alignment: .leading, spacing: 0) { - NavigationBar(title: t("settings__support__title")) - .padding(.horizontal, 16) - .padding(.bottom, 16) - - GeometryReader { geometry in - ScrollView(showsIndicators: false) { - ZStack { - // Orange diagonal background (scrolls with content) - Color.brandAccent - .clipShape(DiagonalCut()) - .ignoresSafeArea() - - VStack(alignment: .leading, spacing: 0) { - BodyMText(t("settings__support__text")) - .padding(.bottom, 16) - - VStack(spacing: 0) { - NavigationLink(value: Route.reportIssue) { - SettingsRow(title: t("settings__support__report"), iconName: "warning") - } - - Button(action: { - openURL(URL(string: Env.helpUrl)!) - }) { - SettingsRow(title: t("settings__support__help"), iconName: "question") - } - - NavigationLink(value: Route.appStatus) { - SettingsRow(title: t("settings__support__status"), iconName: "power") - } - .accessibilityIdentifier("AppStatus") - - Button(action: { - openURL(URL(string: Env.termsOfServiceUrl)!) - }) { - SettingsRow(title: t("settings__about__legal"), iconName: "file-text") - } - - ShareLink(item: shareText, message: Text(shareText)) { - SettingsRow(title: t("settings__about__share"), iconName: "share") - } - - Button(action: { - onVersionTap() - }) { - SettingsRow( - title: t("settings__about__version"), - iconName: "stack", - rightText: appVersion, - rightIcon: nil - ) - } - .accessibilityIdentifier("DevOptions") - } + InsetHeaderScrollView( + header: { + NavigationBar(title: t("settings__support__title")) + .padding(.horizontal, 16) + .padding(.bottom, 16) + }, + content: { + ZStack { + // Orange diagonal background (scrolls with content) + Color.brandAccent + .clipShape(DiagonalCut()) + .ignoresSafeArea() + + VStack(alignment: .leading, spacing: 0) { + BodyMText(t("settings__support__text")) + .padding(.bottom, 16) - Spacer(minLength: 32) + VStack(spacing: 0) { + NavigationLink(value: Route.reportIssue) { + SettingsRow(title: t("settings__support__report"), iconName: "warning") + } - VStack(alignment: .center, spacing: 0) { - Image("logo") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(maxHeight: 100) - .accessibilityIdentifier("AboutLogo") + Button(action: { + openURL(URL(string: Env.helpUrl)!) + }) { + SettingsRow(title: t("settings__support__help"), iconName: "question") } - .frame(maxWidth: .infinity) - .padding(.bottom, 16) - Social() - .padding(.bottom, 16) + NavigationLink(value: Route.appStatus) { + SettingsRow(title: t("settings__support__status"), iconName: "power") + } + .accessibilityIdentifier("AppStatus") - BodyMText("Bitkit was crafted by Synonym Software, S.A. DE C.V. ©2025. All rights reserved.") - .padding(.bottom, 16) + Button(action: { + openURL(URL(string: Env.termsOfServiceUrl)!) + }) { + SettingsRow(title: t("settings__about__legal"), iconName: "file-text") + } - HStack(alignment: .center, spacing: 10) { - Image("synonym-logo") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(height: 24) + ShareLink(item: shareText, message: Text(shareText)) { + SettingsRow(title: t("settings__about__share"), iconName: "share") + } - Image("tether-logo") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(height: 16) + Button(action: { + onVersionTap() + }) { + SettingsRow( + title: t("settings__about__version"), + iconName: "stack", + rightText: appVersion, + rightIcon: nil + ) } - .frame(maxWidth: .infinity, alignment: .center) - .frame(height: 24) - .padding(.bottom, 32) + .accessibilityIdentifier("DevOptions") + } + + Spacer(minLength: 32) + + VStack(alignment: .center, spacing: 0) { + Image("logo") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(maxHeight: 100) + .accessibilityIdentifier("AboutLogo") } - .frame(minHeight: geometry.size.height) - .padding(.horizontal, 16) - .bottomSafeAreaPadding() + .frame(maxWidth: .infinity) + .padding(.bottom, 16) + + Social() + .padding(.bottom, 16) + + BodyMText("Bitkit was crafted by Synonym Software, S.A. DE C.V. ©2025. All rights reserved.") + .padding(.bottom, 16) + + HStack(alignment: .center, spacing: 10) { + Image("synonym-logo") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(height: 24) + + Image("tether-logo") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(height: 16) + } + .frame(maxWidth: .infinity, alignment: .center) + .frame(height: 24) + .padding(.bottom, 32) } + .padding(.horizontal, 16) + .bottomSafeAreaPadding() } + .frame(maxWidth: .infinity, maxHeight: .infinity) } - .ignoresSafeArea() - } + ) + .ignoresSafeArea(edges: .bottom) .navigationBarHidden(true) } diff --git a/Bitkit/Views/Shop/ShopDiscover.swift b/Bitkit/Views/Shop/ShopDiscover.swift index 8855af60d..a237a69d0 100644 --- a/Bitkit/Views/Shop/ShopDiscover.swift +++ b/Bitkit/Views/Shop/ShopDiscover.swift @@ -24,16 +24,15 @@ enum ShopTab: String, CaseIterable, CustomStringConvertible { var description: String { switch self { - case .shop: - return t("other__shop__discover__tabs__shop") - case .map: - return t("other__shop__discover__tabs__map") + case .shop: t("other__shop__discover__tabs__shop") + case .map: t("other__shop__discover__tabs__map") } } } struct ShopDiscover: View { @EnvironmentObject var navigation: NavigationViewModel + @State private var selectedTab: ShopTab = .shop /// Categories data @@ -95,129 +94,95 @@ struct ShopDiscover: View { ] var body: some View { - VStack(spacing: 0) { - NavigationBar(title: t("other__shop__discover__nav_title")) - .padding(.horizontal, 16) - - SegmentedControl(selectedTab: $selectedTab, tabs: ShopTab.allCases) - .padding(.horizontal, 16) + InsetHeaderScrollView( + header: { + VStack(spacing: 0) { + NavigationBar(title: t("other__shop__discover__nav_title")) + .padding(.horizontal, 16) - Group { - switch selectedTab { - case .shop: - shopContent - case .map: - ShopWebView(url: Env.btcMapUrl) - .padding(.top, 16) + SegmentedControl(selectedTab: $selectedTab, tabs: ShopTab.allCases) .padding(.horizontal, 16) } + .background( + ZStack { + BlurView() + LinearGradient( + gradient: Gradient(stops: [ + .init(color: Color.black, location: 0.0), + .init(color: Color.black, location: 0.4), + .init(color: Color.black.opacity(0), location: 1.0), + ]), + startPoint: .top, + endPoint: .bottom + ) + } + .ignoresSafeArea(edges: .top) + ) + .compositingGroup() + .shadow(color: Color.black.opacity(0.5), radius: 8, x: 0, y: 20) + }, + content: { + Group { + switch selectedTab { + case .shop: + shopContent + case .map: + ShopWebView(url: Env.btcMapUrl) + .padding(.top, 16) + .padding(.horizontal, 16) + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .swipeSegmentedTabs(selection: $selectedTab) } - .frame(maxWidth: .infinity, maxHeight: .infinity) - } + ) .navigationBarHidden(true) } private var shopContent: some View { - GeometryReader { geometry in - let cardSize = (geometry.size.width - 32 - 16) / 2 - - ScrollView(showsIndicators: false) { - VStack(alignment: .leading, spacing: 0) { - LazyVGrid( - columns: [ - GridItem(.flexible(), spacing: 16), - GridItem(.flexible(), spacing: 16), - ], - spacing: 16 - ) { - ForEach(cards) { card in - ShopDiscoverCard( - title: card.title, - description: card.description, - imageName: card.imageName, - color: card.color, - size: cardSize - ) { - navigation.navigate(.shopMain(page: card.route)) - } + VStack(alignment: .leading, spacing: 0) { + LazyVGrid( + columns: [ + GridItem(.flexible(), spacing: 16), + GridItem(.flexible(), spacing: 16), + ], + spacing: 16 + ) { + ForEach(cards) { card in + SuggestionCard( + title: card.title, + description: card.description, + imageName: card.imageName, + accentColor: card.color, + onTap: { + navigation.navigate(.shopMain(page: card.route)) } - } - .padding(.bottom, 16) + ) + } + } + .padding(.bottom, 16) - VStack { - CaptionMText(t("other__shop__discover__label")) - .frame(maxWidth: .infinity, alignment: .leading) - } - .frame(height: 50) + VStack { + CaptionMText(t("other__shop__discover__label")) .frame(maxWidth: .infinity, alignment: .leading) - .padding(.bottom, 8) - - LazyVStack(spacing: 0) { - ForEach(categories) { category in - ShopCategoryRow( - title: category.title, - iconName: category.iconName - ) { - navigation.navigate(.shopMain(page: category.route)) - } - } + } + .frame(height: 50) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.bottom, 8) + + LazyVStack(spacing: 0) { + ForEach(categories) { category in + ShopCategoryRow( + title: category.title, + iconName: category.iconName + ) { + navigation.navigate(.shopMain(page: category.route)) } } - .padding(.top, 16) - .padding(.horizontal, 16) } } - } -} - -// MARK: - Shop Discover Card Component - -struct ShopDiscoverCard: View { - let title: String - let description: String - let imageName: String - let color: Color - let size: CGFloat - let onTap: () -> Void - - var body: some View { - Button(action: onTap) { - VStack(alignment: .leading, spacing: 0) { - Spacer() - - Image(imageName) - .resizable() - .scaledToFit() - .frame(width: 96, height: 96) - .frame(maxWidth: .infinity, alignment: .center) - - Text(title) - .font(.custom(Fonts.black, size: 20)) - .lineLimit(1) - .kerning(-0.5) - .textCase(.uppercase) - .padding(.top, 4) - - CaptionBText(description) - } - .padding() - .frame(width: size, height: size, alignment: .topLeading) - .background( - RoundedRectangle(cornerRadius: 16) - .fill( - LinearGradient( - gradient: Gradient(stops: [ - .init(color: color, location: 0.0), - .init(color: Color.black.opacity(0.1), location: 0.9), - .init(color: Color.black, location: 1.0), - ]), - startPoint: .top, - endPoint: .bottom - ) - ) - ) - } - .buttonStyle(PlainButtonStyle()) + .padding(.top, 16) + .padding(.horizontal, 16) } } diff --git a/Bitkit/Views/Wallets/Activity/AllActivityView.swift b/Bitkit/Views/Wallets/Activity/AllActivityView.swift index 0939b097d..041a703a7 100644 --- a/Bitkit/Views/Wallets/Activity/AllActivityView.swift +++ b/Bitkit/Views/Wallets/Activity/AllActivityView.swift @@ -5,92 +5,51 @@ struct AllActivityView: View { @EnvironmentObject private var app: AppViewModel @EnvironmentObject private var wallet: WalletViewModel - private var headerTopPadding: CGFloat { - // NavBar + Filter + SegmentedControl + spacing - return ScreenLayout.topPaddingWithoutSafeArea + 116 - } - var body: some View { ZStack(alignment: .top) { - // ScrollView - base layer, full height, content scrolls behind header - ScrollView(showsIndicators: false) { - ActivityList(viewType: .all) - // .padding(.top, headerTopPadding) - .scrollDismissesKeyboard(.interactively) - .highPriorityGesture( - // TODO: rewrite using TabView - DragGesture(minimumDistance: 20, coordinateSpace: .local) - .onEnded { value in - let horizontalAmount = value.translation.width - let verticalAmount = value.translation.height - - if abs(horizontalAmount) > abs(verticalAmount) { - if horizontalAmount < -50 { - // Swipe left - move to next tab - if let currentIndex = ActivityTab.allCases.firstIndex(of: activity.selectedTab), - currentIndex < ActivityTab.allCases.count - 1 - { - withAnimation(.easeInOut(duration: 0.2)) { - activity.selectedTab = ActivityTab.allCases[currentIndex + 1] - } - } - } else if horizontalAmount > 50 { - // Swipe right - move to previous tab - if let currentIndex = ActivityTab.allCases.firstIndex(of: activity.selectedTab), - currentIndex > 0 - { - withAnimation(.easeInOut(duration: 0.2)) { - activity.selectedTab = ActivityTab.allCases[currentIndex - 1] - } - } - } - } - } - ) - } - .contentMargins(.top, headerTopPadding) - .contentMargins(.bottom, ScreenLayout.bottomPaddingWithSafeArea) - .padding(.horizontal, 16) - .scrollDismissesKeyboard(.interactively) - .refreshable { - do { - try await wallet.sync() - try await activity.syncLdkNodePayments() - } catch { - app.toast(error) - } - } - .transition(.move(edge: .leading).combined(with: .opacity)) + InsetHeaderScrollView( + header: { + VStack(spacing: 0) { + NavigationBar(title: t("wallet__activity")) + .padding(.bottom, 16) - // Header - overlay on top, scroll content goes behind it - VStack(spacing: 0) { - NavigationBar(title: t("wallet__activity")) - .padding(.bottom, 16) + ActivityListFilter(viewModel: activity) + .padding(.bottom, 16) - ActivityListFilter(viewModel: activity) - .padding(.bottom, 16) - - SegmentedControl(selectedTab: $activity.selectedTab, tabs: ActivityTab.allCases) - } - .frame(maxWidth: .infinity, alignment: .top) - .padding(.horizontal, 16) - .background( - ZStack { - BlurView() - LinearGradient( - gradient: Gradient(stops: [ - .init(color: Color.black, location: 0.0), - .init(color: Color.black, location: 0.4), - .init(color: Color.black.opacity(0), location: 1.0), - ]), - startPoint: .top, - endPoint: .bottom + SegmentedControl(selectedTab: $activity.selectedTab, tabs: ActivityTab.allCases) + } + .frame(maxWidth: .infinity, alignment: .top) + .padding(.horizontal, 16) + .background( + ZStack { + BlurView() + LinearGradient( + gradient: Gradient(stops: [ + .init(color: Color.black, location: 0.0), + .init(color: Color.black, location: 0.4), + .init(color: Color.black.opacity(0), location: 1.0), + ]), + startPoint: .top, + endPoint: .bottom + ) + } + .ignoresSafeArea(edges: .top) ) - } - .ignoresSafeArea(edges: .top) + .compositingGroup() + .shadow(color: Color.black.opacity(0.5), radius: 8, x: 0, y: 20) + }, + content: { + ActivityList(viewType: .all) + .padding(.horizontal, 16) + .swipeSegmentedTabs(selection: $activity.selectedTab) + }, + scrollModifier: ActivityScrollModifier( + activity: activity, + app: app, + wallet: wallet + ) ) - .compositingGroup() - .shadow(color: Color.black.opacity(0.5), radius: 8, x: 0, y: 20) + .transition(.move(edge: .leading).combined(with: .opacity)) // Bottom gradient overlay VStack { @@ -112,10 +71,33 @@ struct AllActivityView: View { } } +private struct ActivityScrollModifier: ViewModifier { + let activity: ActivityListViewModel + let app: AppViewModel + let wallet: WalletViewModel + + func body(content: Content) -> some View { + content + .contentMargins(.top, 16) + .contentMargins(.bottom, ScreenLayout.bottomPaddingWithSafeArea) + .scrollDismissesKeyboard(.interactively) + .refreshable { + do { + try await wallet.sync() + try await activity.syncLdkNodePayments() + } catch { + app.toast(error) + } + } + } +} + #Preview { NavigationStack { AllActivityView() .environmentObject(ActivityListViewModel()) + .environmentObject(AppViewModel()) + .environmentObject(WalletViewModel()) .preferredColorScheme(.dark) } } diff --git a/changelog.d/next/535.changed.md b/changelog.d/next/535.changed.md new file mode 100644 index 000000000..2a446847f --- /dev/null +++ b/changelog.d/next/535.changed.md @@ -0,0 +1 @@ +Added swipe gestures on the tabs in settings and shop and polished the header areas on those screens