-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'feature/swiftformat' of github.com:DatepollSystems/wait…
…errobot-mobile_iOS into feature/swiftformat # Conflicts: # WaiterRobot/WaiterRobotApp.swift
- Loading branch information
Showing
8 changed files
with
233 additions
and
188 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import Foundation | ||
import shared | ||
import SwiftUI | ||
|
||
struct LaunchScreen: View { | ||
private let minimumOnScreenTimeSeconds = 3.0 | ||
private let device = UIDevice.current.userInterfaceIdiom | ||
|
||
@State private var startupFinished = false | ||
|
||
var body: some View { | ||
VStack { | ||
if case .phone = device { | ||
VStack { | ||
Spacer() | ||
|
||
Image(.launch) | ||
.resizable() | ||
.scaledToFit() | ||
} | ||
.padding(.horizontal, -2) | ||
.ignoresSafeArea() | ||
} else { | ||
ZStack { | ||
Image(.logoRounded) | ||
.resizable() | ||
.scaledToFit() | ||
.frame(width: 150) | ||
.padding() | ||
|
||
VStack { | ||
Spacer() | ||
|
||
ProgressView() | ||
.padding() | ||
.padding(.bottom) | ||
} | ||
} | ||
} | ||
} | ||
.onAppear { | ||
Task { | ||
async let setup: () = setupApp() | ||
async let delay: () = delay() | ||
|
||
_ = await [setup, delay] | ||
|
||
startupFinished = true | ||
} | ||
} | ||
.fullScreenCover(isPresented: $startupFinished) { | ||
MainView() | ||
} | ||
} | ||
|
||
/// Setup of frameworks and all the other related stuff which is needed everywhere in the app | ||
private func setupApp() { | ||
print("started app setup") | ||
var appVersion = readFromInfoPlist(withKey: "CFBundleShortVersionString") | ||
let versionSuffix = readFromInfoPlist(withKey: "VERSION_SUFFIX") | ||
if !versionSuffix.isEmpty { | ||
appVersion += "-\(versionSuffix)" | ||
} | ||
|
||
CommonApp.shared.doInit( | ||
appVersion: appVersion, | ||
appBuild: Int32(readFromInfoPlist(withKey: "CFBundleVersion"))!, | ||
phoneModel: UIDevice.current.deviceType, | ||
os: OS.Ios(version: UIDevice.current.systemVersion), | ||
apiBaseUrl: readFromInfoPlist(withKey: "API_BASE") | ||
) | ||
|
||
KoinKt.doInitKoinIos() | ||
let logger = koin.logger(tag: "AppDelegate") | ||
logger.d { "initialized Koin" } | ||
|
||
KMMResourcesLocalizationKt.localizationBundle = Bundle(for: shared.L.self) | ||
logger.d { "initialized localization bundle" } | ||
print("finished app setup") | ||
} | ||
|
||
private func delay() async { | ||
print("started delay") | ||
try? await Task.sleep(seconds: minimumOnScreenTimeSeconds) | ||
print("finished delay") | ||
} | ||
|
||
private func readFromInfoPlist(withKey key: String) -> String { | ||
guard let value = Bundle.main.infoDictionary?[key] as? String else { | ||
fatalError("Could not find key '\(key)' in info.plist file.") | ||
} | ||
|
||
return value | ||
} | ||
} | ||
|
||
#Preview { | ||
LaunchScreen() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
// | ||
// MainView.swift | ||
// WaiterRobot | ||
// | ||
// Created by Alexander Kauer on 29.12.23. | ||
// | ||
|
||
import shared | ||
import SwiftUI | ||
import UIPilot | ||
|
||
struct MainView: View { | ||
@State private var snackBarMessage: String? | ||
@State private var showUpdateAvailableAlert: Bool = false | ||
@StateObject private var navigator: UIPilot<Screen> = UIPilot(initial: Screen.RootScreen.shared, debug: true) | ||
@StateObject private var strongVM = ObservableViewModel(vm: koin.rootVM()) | ||
|
||
private var selectedScheme: ColorScheme? { | ||
switch strongVM.state.selectedTheme { | ||
case .dark: | ||
.dark | ||
case .light: | ||
.light | ||
default: | ||
nil | ||
} | ||
} | ||
|
||
var body: some View { | ||
unowned let vm = strongVM | ||
ZStack { | ||
UIPilotHost(navigator) { route in | ||
switch route { | ||
case is Screen.RootScreen: RootScreen(strongVM: vm) | ||
case is Screen.LoginScannerScreen: LoginScannerScreen() | ||
case is Screen.SwitchEventScreen: SwitchEventScreen() | ||
case is Screen.SettingsScreen: SettingsScreen() | ||
case is Screen.UpdateApp: UpdateAppScreen() | ||
case let screen as Screen.RegisterScreen: RegisterScreen(createToken: screen.createToken) | ||
case let screen as Screen.TableDetailScreen: TableDetailScreen(table: screen.table) | ||
case let screen as Screen.OrderScreen: OrderScreen(table: screen.table, initialItemId: screen.initialItemId) | ||
case let screen as Screen.BillingScreen: BillingScreen(table: screen.table) | ||
default: | ||
Text("No view defined for \(route.description)") // TODO: | ||
Button { | ||
navigator.pop() | ||
} label: { | ||
Text("Back") | ||
}.onAppear { | ||
koin.logger(tag: "WaiterRobotApp").e { "No view defined for \(route.description)" } | ||
} | ||
} | ||
} | ||
} | ||
.preferredColorScheme(selectedScheme) | ||
.overlay(alignment: .bottom) { | ||
if let message = snackBarMessage { | ||
ZStack { | ||
HStack { | ||
Text(message) | ||
.foregroundColor(.white) | ||
Spacer() | ||
Button { | ||
snackBarMessage = nil | ||
} label: { | ||
Image(systemName: "xmark.circle") | ||
} | ||
} | ||
.frame(maxWidth: .infinity) | ||
.padding() | ||
.background(.gray) | ||
.clipShape(RoundedRectangle(cornerRadius: 10)) | ||
} | ||
.padding() | ||
} | ||
} | ||
.handleSideEffects(of: vm, navigator) { effect in | ||
switch onEnum(of: effect) { | ||
case let .showSnackBar(snackBar): | ||
snackBarMessage = snackBar.message | ||
DispatchQueue.main.asyncAfter(deadline: .now() + 5) { | ||
snackBarMessage = nil | ||
} | ||
} | ||
return true | ||
} | ||
.onOpenURL { url in | ||
vm.actual.onDeepLink(url: url.absoluteString) | ||
} | ||
.alert( | ||
localize.app.updateAvailable.title(), | ||
isPresented: $showUpdateAvailableAlert | ||
) { | ||
Button(localize.dialog.cancel(), role: .cancel) { | ||
showUpdateAvailableAlert = false | ||
} | ||
|
||
Button(localize.app.forceUpdate.openStore(value0: "App Store")) { | ||
guard let storeUrl = VersionChecker.shared.storeUrl, | ||
let url = URL(string: storeUrl) | ||
else { | ||
return | ||
} | ||
|
||
DispatchQueue.main.async { | ||
UIApplication.shared.open(url, options: [:], completionHandler: nil) | ||
} | ||
} | ||
} message: { | ||
Text(localize.app.updateAvailable.message()) | ||
} | ||
.onAppear { | ||
VersionChecker.shared.checkVersion { | ||
showUpdateAvailableAlert = true | ||
} | ||
} | ||
.tint(.main) | ||
} | ||
} | ||
|
||
#Preview { | ||
MainView() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import Foundation | ||
|
||
extension Task where Success == Never, Failure == Never { | ||
static func sleep(seconds: Double) async throws { | ||
let duration = UInt64(seconds * 1_000_000_000) | ||
try await Task.sleep(nanoseconds: duration) | ||
} | ||
} |
Oops, something went wrong.