commit 39767097234f31ced92e17e07f468cde0bb859a2
parent 3b59e23a40bd629f3da4eaf8e2c77f8f392152c5
Author: Marc Stibane <marc@taler.net>
Date: Sun, 3 Nov 2024 08:35:55 +0100
Onboarding
Diffstat:
4 files changed, 90 insertions(+), 40 deletions(-)
diff --git a/TalerWallet1/Controllers/PublicConstants.swift b/TalerWallet1/Controllers/PublicConstants.swift
@@ -7,12 +7,21 @@
*/
import Foundation
-public let MAXRECENT = 4
+public let CHF_4217 = "CHF" // ISO-4217 Swiss Francs
+public let EUR_4217 = "EUR" // ISO-4217 Euro
+public let HUF_4217 = "HUF" // ISO-4217 Hungarian Forint
+
+public let TAPPED = 4 // how often you need to tap on the Actions button before it loses its label
+public let DRAGGED = 2 // #times to drag to stop the auto-dragging
+public let DRAGDELAY = 0.5
+public let DRAGDURATION = 0.25
+public let DRAGSPEED = 0.1
+public let MAXRECENT = 4 // # of rows in Recent Transactions
+
public let ICONLEADING = CGFloat(-8)
public let HSPACING = CGFloat(10) // space between items in HStack
public let LAUNCHDURATION: Double = 1.60
-public let SLIDEDURATION: Double = 0.45
public let ONEDAY: UInt = 1 // 1..3
public let SEVENDAYS: UInt = 7 // 3..9
diff --git a/TalerWallet1/Views/HelperViews/TabBarView.swift b/TalerWallet1/Views/HelperViews/TabBarView.swift
@@ -9,6 +9,7 @@ import SwiftUI
struct TabBarView: View {
@Binding var selection: Tab
+ @Binding var userAction: Int
@Binding var hidden: Int
let onActionTab: () -> Void
let onActionDrag: () -> Void
@@ -16,15 +17,20 @@ struct TabBarView: View {
@Environment(\.keyboardShowing) var keyboardShowing
@AppStorage("minimalistic") var minimalistic: Bool = false
+ @AppStorage("tapped") var tapped: Int = 0
+ @AppStorage("dragged") var dragged: Int = 0
@State private var offset = CGSize.zero
@State private var didDrag = false
private func tabBarItem(for tab: Tab) -> some View {
VStack(spacing: 0) {
- if tab == .actions {
- let width = 72.0
- let height = 57.6
+ let isActions = (tab == .actions)
+ let withText = isActions ? tapped < TAPPED
+ : tapped < TAPPED || !minimalistic
+ if isActions {
+ let width = withText ? 48 : 72.0
+ let height = withText ? 36 : 57.6
tab.image
.resizable()
.scaledToFill()
@@ -32,7 +38,7 @@ struct TabBarView: View {
.clipped() // Crop the image to the frame size
.padding(.bottom, 4)
.offset(offset)
- .opacity(1 - Double(abs(offset.height / 35)))
+// .opacity(1 - Double(abs(offset.height / 35)))
.gesture(
DragGesture()
.onChanged { gesture in
@@ -42,6 +48,9 @@ struct TabBarView: View {
offset = .zero
didDrag = true
onActionDrag() // switch to camera
+ if tapped >= TAPPED {
+ dragged += 1
+ }
} else {
offset = trans
}
@@ -55,50 +64,62 @@ struct TabBarView: View {
offset = .zero
}
)
-
} else {
- let size = minimalistic ? 36.0 : 24.0
+ let size = withText ? 24.0 : 36.0
tab.image
.resizable()
.renderingMode(.template)
.tint(.black)
.aspectRatio(contentMode: .fit)
.frame(width: size, height: size)
- if !minimalistic {
- Text(tab.title)
- .lineLimit(1)
- .talerFont(.body)
- }
}
- }
+ if withText {
+ Text(tab.title)
+ .lineLimit(1)
+ .talerFont(.body)
+ }
+ }.id(tab)
.foregroundColor(selection == tab ? .accentColor : .secondary)
.padding(.vertical, 8)
.accessibilityElement(children: .combine)
.accessibility(label: Text(tab.title))
.accessibility(addTraits: [.isButton])
.accessibility(removeTraits: [.isImage])
+ .frame(maxWidth: .infinity)
+ .contentShape(Rectangle())
}
+ private func userAction(_ newValue: Int) {
+ if tapped >= TAPPED && dragged < DRAGGED {
+ withAnimation(Animation.easeOut(duration: DRAGDURATION).delay(DRAGDELAY)) {
+ offset.height = -50
+ }
+ withAnimation(Animation.easeOut(duration: DRAGSPEED).delay(DRAGDELAY + DRAGDURATION + DRAGSPEED)) {
+ offset.height = 0
+ }
+ }
+ }
var body: some View {
Group {
if keyboardShowing || hidden > 0 {
EmptyView()
} else {
+ let actionTab = tabBarItem(for: Tab.actions)
+ let balanceTab = tabBarItem(for: Tab.balances)
+ let settingsTab = tabBarItem(for: Tab.settings)
HStack(alignment: .bottom) {
- ForEach(Tab.allCases, id: \.self) { tab in
- tabBarItem(for: tab)
- .frame(maxWidth: .infinity)
- .contentShape(Rectangle())
- .onTapGesture {
- if tab == .actions {
- onActionTab()
- } else {
- selection = tab
- }
- }
+ balanceTab.onTapGesture { selection = .balances; userAction += 1 }
+ actionTab.onTapGesture {
+ onActionTab()
+ tapped += 1
+// dragged = 0
}
+ settingsTab.onTapGesture { selection = .settings; userAction += 1 }
}
.background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.bottom))
+ .onChange(of: userAction) { newValue in
+ userAction(newValue)
+ }
}
}
}
diff --git a/TalerWallet1/Views/Main/MainView.swift b/TalerWallet1/Views/Main/MainView.swift
@@ -46,6 +46,7 @@ struct MainView: View {
// @State private var showCameraAlert: Bool = false
@State private var qrButtonTapped = false
@State private var innerHeight: CGFloat = .zero
+ @State private var userAction = 0
func sheetDismissed() -> Void {
logger.info("sheet dismiss")
@@ -65,12 +66,13 @@ struct MainView: View {
#endif
Group {
if controller.backendState == .ready {
- Content(logger: logger, stack: stack.push("Content"),
- selectedBalance: $selectedBalance,
- talerFontIndex: $talerFontIndex,
- showActionSheet: $showActionSheet,
- showScanner: $showScanner)
- .onAppear() {
+ MainContent(logger: logger, stack: stack.push("Content"),
+ selectedBalance: $selectedBalance,
+ talerFontIndex: $talerFontIndex,
+ showActionSheet: $showActionSheet,
+ showScanner: $showScanner,
+ userAction: $userAction)
+ .onAppear() {
#if DEBUG
if playSoundsI != 0 && playSoundsB && !soundPlayed {
controller.playSound(1008) // Startup chime
@@ -211,13 +213,14 @@ extension MainView {
}
}
- struct Content: View {
+ struct MainContent: View {
let logger: Logger
let stack: CallStack
@Binding var selectedBalance: Balance?
@Binding var talerFontIndex: Int
@Binding var showActionSheet: Bool
@Binding var showScanner: Bool
+ @Binding var userAction: Int
#if DEBUG
@AppStorage("developerMode") var developerMode: Bool = true
@@ -304,12 +307,7 @@ extension MainView {
let balancesTitle = Tab.balances.title
// let actionTitle = Tab.actions.title
let settingsTitle = Tab.settings.title
- let tabBarView = TabBarView(selection: tabSelection(), hidden: $navModel.tabBarHidden) {
- if selectedTab != .balances {
- selectedTab = .balances
- }
- // TODO: check NavigationStack, pop only if necessary
-// ViewState.shared.popToRootView(nil) either do this after any of the buttons was operated, or don't do it at all
+ let tabBarView = TabBarView(selection: tabSelection(), userAction: $userAction, hidden: $navModel.tabBarHidden) {
showActionSheet = true
} onActionDrag: {
showScanner = true
diff --git a/TalerWallet1/Views/Settings/AboutView.swift b/TalerWallet1/Views/Settings/AboutView.swift
@@ -22,10 +22,13 @@ struct AboutView: View {
#endif
@AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
@AppStorage("minimalistic") var minimalistic: Bool = false
+ @AppStorage("tapped") var tapped: Int = 0
+ @AppStorage("dragged") var dragged: Int = 0
@State private var rotationEnabled = false
@State private var showGitHash = false
@State private var listID = UUID()
+ @State private var onboarding = false
var body: some View {
#if PRINT_CHANGES
@@ -63,11 +66,27 @@ struct AboutView: View {
}
}
} else {
- SettingsItem(name: String(localized: "WalletCore Version"), id1: "wallet-coreV") {
+ SettingsItem(name: String(localized: "Wallet-Core Version"), id1: "wallet-coreV") {
Text(verbatim: "\(walletCore.versionInfo?.implementationSemver ?? "unknown")")
}
}
}.onTapGesture(count: 1) { showGitHash.toggle() }
+ SettingsToggle(name: String(localized: "Onboarding"),
+ value: $onboarding.onChange({ shouldOnboard in
+ if shouldOnboard {
+ tapped = 0
+ dragged = 0
+ } else {
+ tapped = TAPPED
+ dragged = DRAGGED
+ }
+ }),
+ id1: "onboarding",
+ description: minimalistic ? nil : String(localized: "Explain the Actions button"))
+#if DEBUG
+ Text("Tapped: \(tapped), dragged: \(dragged)")
+#endif
+
// SettingsItem(name: "Supported Exchange Versions", id1: "exchange") {
// Text(verbatim: "\(walletCore.versionInfo?.exchange ?? "unknown")")
// }
@@ -82,6 +101,9 @@ struct AboutView: View {
.listStyle(myListStyle.style).anyView
}
.navigationTitle(navTitle)
+ .task {
+ onboarding = (tapped < TAPPED || dragged < DRAGGED)
+ }
.onAppear() {
DebugViewC.shared.setViewID(VIEW_ABOUT, stack: stack.push())
}
@@ -110,7 +132,7 @@ extension Bundle {
}
var releaseVersionNumberPretty: String {
let release = releaseVersionNumber ?? "1.0.0"
- return "v\(release) (\(buildVersionNumber))"
+ return release // "v\(release) (\(buildVersionNumber))"
}
}
// MARK: -