Transform to multi-account support
This commit is contained in:
@@ -1,87 +0,0 @@
|
||||
//
|
||||
// ContentView.swift
|
||||
// meterios-watch
|
||||
//
|
||||
// (c) 2025 Martin "maride" Dessauer
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
@EnvironmentObject var wcMgr: WCManager
|
||||
|
||||
@State private var favouriteDrinks: Array<Drink> = []
|
||||
@State private var availableDrinks: Array<Drink> = []
|
||||
|
||||
@State private var showUpdateError: Bool = false
|
||||
@State private var updateError: String = ""
|
||||
@State private var updateErrorCount: Int = 0
|
||||
|
||||
// update performs a full update from the paired device, covering connection info (user ID and backend address) and list of drinks
|
||||
func update() {
|
||||
if updateErrorCount >= 3 {
|
||||
showUpdateError = true
|
||||
updateErrorCount = 0
|
||||
return
|
||||
}
|
||||
|
||||
// Update drinks list from paired device
|
||||
wcMgr.requestDrinksList(
|
||||
replyHandler: { favDrinks, availDrinks in
|
||||
// Drinks received from backend
|
||||
self.favouriteDrinks = favDrinks
|
||||
self.availableDrinks = availDrinks
|
||||
showUpdateError = false
|
||||
}, errorHandler: { error in
|
||||
// Error receiving drinks
|
||||
print("Error receiving drinks: \(error)")
|
||||
updateError = error?.localizedDescription ?? "Unknown error"
|
||||
updateErrorCount += 1
|
||||
update()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
if favouriteDrinks.count + availableDrinks.count > 0 {
|
||||
NavigationView {
|
||||
List() {
|
||||
// Drinks
|
||||
Section(String(localized: "FAVOURITES")) {
|
||||
ForEach(favouriteDrinks) { drink in
|
||||
NavigationLink(drink.name) {
|
||||
DrinkDetailView(drink: drink)
|
||||
}
|
||||
}
|
||||
}
|
||||
Section(String(localized: "DRINKS")) {
|
||||
ForEach(availableDrinks) { drink in
|
||||
NavigationLink(drink.name) {
|
||||
DrinkDetailView(drink: drink)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Controls
|
||||
Section {
|
||||
Button(String(localized: "REFRESH")) {
|
||||
favouriteDrinks = []
|
||||
availableDrinks = []
|
||||
update()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ProgressView()
|
||||
}
|
||||
}
|
||||
.onAppear(perform: update)
|
||||
// Alert to communicate an error in communication with the paired device
|
||||
.alert(String(localized: "CONNECTION_ERROR"), isPresented: $showUpdateError) {
|
||||
Text(updateError).tint(.red).font(.footnote)
|
||||
Button(String(localized: "RETRY"), systemImage: "arrow.clockwise", action: update)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,15 +8,13 @@
|
||||
import SwiftUI
|
||||
|
||||
struct DrinkDetailView: View {
|
||||
@EnvironmentObject var wcMgr: WCManager
|
||||
|
||||
private var drink: Drink
|
||||
private var drink: MeteClientDrink
|
||||
|
||||
@State var shouldShowTransactionSheet = false
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
init(drink: Drink) {
|
||||
init(drink: MeteClientDrink) {
|
||||
self.drink = drink
|
||||
}
|
||||
|
||||
@@ -28,12 +26,20 @@ struct DrinkDetailView: View {
|
||||
// Basic info
|
||||
HStack {
|
||||
VStack {
|
||||
Text(String(format: "%img", drink.caffeine)).fontWeight(.bold)
|
||||
if drink.caffeine != nil {
|
||||
Text(String(format: "%img", drink.caffeine!)).fontWeight(.bold)
|
||||
} else {
|
||||
Text("? mg").fontWeight(.bold)
|
||||
}
|
||||
Text(String(localized: "CAFFEINE")).fontWeight(Font.Weight.thin)
|
||||
}
|
||||
Divider()
|
||||
VStack {
|
||||
Text(String(format: "%.2f€", drink.GetPrice())).fontWeight(.bold)
|
||||
if drink.price != nil {
|
||||
Text(drink.price!.formatted(.currency(code: "EUR"))).fontWeight(.bold)
|
||||
} else {
|
||||
Text("? €").fontWeight(.bold)
|
||||
}
|
||||
Text(String(localized: "PRICE")).fontWeight(Font.Weight.thin)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
//
|
||||
// ContentView.swift
|
||||
// meterios-watch
|
||||
//
|
||||
// (c) 2025 Martin "maride" Dessauer
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ContentView: View {
|
||||
@EnvironmentObject var wcMgr: WCManager
|
||||
|
||||
@State private var favouriteDrinks: Array<MeteClientDrink>?
|
||||
@State private var availableDrinks: Array<MeteClientDrink>?
|
||||
|
||||
@State private var userInfo: WCUser?
|
||||
|
||||
@State private var showUpdateError: Bool = false
|
||||
@State private var updateError: String = ""
|
||||
@State private var updateErrorCount: Int = 0
|
||||
|
||||
// update performs a full update from the paired device, covering connection info (user ID and backend address) and list of drinks
|
||||
func update() {
|
||||
if updateErrorCount >= 3 {
|
||||
showUpdateError = true
|
||||
updateErrorCount = 0
|
||||
return
|
||||
}
|
||||
|
||||
// Update user info
|
||||
wcMgr.requestUserInfo(replyHandler: { userInfo in
|
||||
self.userInfo = userInfo
|
||||
}, errorHandler: { error in
|
||||
// Error receiving user info
|
||||
print("Error receiving user info: \(error)")
|
||||
})
|
||||
|
||||
// Update drinks list from paired device
|
||||
wcMgr.requestDrinksList(
|
||||
replyHandler: { favDrinks, availDrinks in
|
||||
// Drinks received from backend
|
||||
self.favouriteDrinks = favDrinks
|
||||
self.availableDrinks = availDrinks
|
||||
showUpdateError = false
|
||||
}, errorHandler: { error in
|
||||
// Error receiving drinks
|
||||
print("Error receiving drinks: \(error)")
|
||||
updateError = error?.localizedDescription ?? "Unknown error"
|
||||
updateErrorCount += 1
|
||||
update()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
if favouriteDrinks != nil && availableDrinks != nil {
|
||||
NavigationView {
|
||||
List() {
|
||||
// Account
|
||||
if userInfo != nil {
|
||||
Button(action: {}, label: {
|
||||
HStack {
|
||||
// Profile Image
|
||||
AsyncImageWithPlaceholder(url: userInfo?.displayImageURL, width: 64, height: 64).clipShape(Circle()).fixedSize()
|
||||
Spacer(minLength: 16.0)
|
||||
|
||||
// Account, Address & Balance
|
||||
VStack(alignment: .leading) {
|
||||
Text(userInfo!.displayName)
|
||||
Text((userInfo!.balance!.formatted(.currency(code: "EUR")))).foregroundStyle((userInfo?.balance)! > 0 ? .green : .red)
|
||||
}.fixedSize()
|
||||
}.fixedSize()
|
||||
})
|
||||
}
|
||||
|
||||
// Drinks
|
||||
if !favouriteDrinks!.isEmpty {
|
||||
Section(String(localized: "FAVOURITES")) {
|
||||
ForEach(favouriteDrinks!) { drink in
|
||||
NavigationLink(destination: {
|
||||
DrinkDetailView(drink: drink)
|
||||
}, label: {
|
||||
AsyncImageWithPlaceholder(url: URL(string: "https://\(account.address)/\(drink.logoURL)"), width: 32, height: 32)
|
||||
Text(drink.name)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
if !availableDrinks!.isEmpty {
|
||||
Section(String(localized: "DRINKS")) {
|
||||
ForEach(availableDrinks!) { drink in
|
||||
NavigationLink(drink.name) {
|
||||
DrinkDetailView(drink: drink)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Section(content: {}, footer: {
|
||||
HStack(alignment: .center, content: {
|
||||
Spacer()
|
||||
VStack() {
|
||||
Image(systemName: "bolt.horizontal.circle.fill").font(.title).foregroundStyle(.gray)
|
||||
Spacer(minLength: 8)
|
||||
Text(String(localized: "NO_DRINKS")).font(.title).foregroundStyle(.gray)
|
||||
}
|
||||
Spacer()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Controls
|
||||
Section {
|
||||
Button(String(localized: "REFRESH")) {
|
||||
favouriteDrinks = []
|
||||
availableDrinks = []
|
||||
update()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ProgressView()
|
||||
}
|
||||
}
|
||||
.onAppear(perform: update)
|
||||
// Alert to communicate an error in communication with the paired device
|
||||
.alert(String(localized: "CONNECTION_ERROR"), isPresented: $showUpdateError) {
|
||||
Text(updateError).tint(.red).font(.footnote)
|
||||
Button(String(localized: "RETRY"), systemImage: "arrow.clockwise", action: update)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user