Some checks failed
Apple Platform CI / smoke-and-tests (push) Has been cancelled
Deep audit (issues 2-14): - Add missing WCSession handlers for applicationContext and userInfo - Fix BoundedFIFOQueue race condition with serial dispatch queue - Fix timer race condition with main thread guarantee - Fix watch pause state divergence — phone is now source of truth - Fix wrong notification posted on logout (createdNewWorkout → userLoggedOut) - Fix POST status check to accept any 2xx (was exact match) - Fix @StateObject → @ObservedObject for injected viewModel - Add pull-to-refresh to CompletedWorkoutsView - Fix typos: RefreshUserInfoFetcable, defualtPackageModle - Replace string concatenation with interpolation - Replace 6 @StateObject with @ObservedObject for BridgeModule.shared - Replace 7 hardcoded AVPlayer URLs with BaseURLs.currentBaseURL UI audit (issues 1-15): - Fix GeometryReader eating VStack space — replaced with .overlay - Fix refreshable continuation resuming before fetch completes - Remove duplicate @State workouts — derive from DataStore - Decouple leaf views from BridgeModule (pass discrete values) - Convert selectedIds from Array to Set for O(1) lookups - Extract .sorted() from var body into computed properties - Move search filter out of ForEach render loop - Replace import SwiftUI with import Combine in non-UI classes - Mark all @State properties private - Extract L/R exercise auto-add logic to WorkoutViewModel - Use enumerated() instead of .indices in ForEach - Make AddSupersetView frame flexible instead of fixed 300pt - Hoist Set construction out of per-exercise filter loop - Move ViewModel network fetch from init to load() Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
113 lines
3.9 KiB
Swift
113 lines
3.9 KiB
Swift
//
|
|
// Werkout_iosApp.swift
|
|
// Werkout_ios
|
|
//
|
|
// Created by Trey Tartt on 6/13/23.
|
|
//
|
|
|
|
import SwiftUI
|
|
import Combine
|
|
import AVKit
|
|
import SharedCore
|
|
|
|
|
|
struct Constants {
|
|
static let phoneThotStyle = "phoneThotStyle"
|
|
static let extThotStyle = "extThotStyle"
|
|
static let extShowNextVideo = "extShowNextVideo"
|
|
static let thotGenderOption = "thotGenderOption"
|
|
|
|
static let buttonRadius: CGFloat = 12
|
|
}
|
|
|
|
@main
|
|
struct Werkout_iosApp: App {
|
|
let persistenceController = PersistenceController.shared
|
|
@State var additionalWindows: [UIWindow] = []
|
|
@State private var tabSelection = 1
|
|
@Environment(\.scenePhase) private var scenePhase
|
|
|
|
let pub = NotificationCenter.default.publisher(for: AppNotifications.createdNewWorkout)
|
|
let logoutPub = NotificationCenter.default.publisher(for: AppNotifications.userLoggedOut)
|
|
|
|
private var screenDidConnectPublisher: AnyPublisher<UIWindowScene, Never> {
|
|
NotificationCenter.default
|
|
.publisher(for: UIScene.willConnectNotification)
|
|
.compactMap { $0.object as? UIWindowScene }
|
|
.filter { $0.screen != UIApplication.shared.connectedScenes.compactMap { ($0 as? UIWindowScene)?.screen }.first }
|
|
.receive(on: RunLoop.main)
|
|
.eraseToAnyPublisher()
|
|
}
|
|
|
|
private var screenDidDisconnectPublisher: AnyPublisher<UIWindowScene, Never> {
|
|
NotificationCenter.default
|
|
.publisher(for: UIScene.didDisconnectNotification)
|
|
.compactMap { $0.object as? UIWindowScene }
|
|
.receive(on: RunLoop.main)
|
|
.eraseToAnyPublisher()
|
|
}
|
|
|
|
var body: some Scene {
|
|
WindowGroup {
|
|
TabView(selection: $tabSelection) {
|
|
AllWorkoutsView()
|
|
.onReceive(screenDidConnectPublisher) { scene in
|
|
screenDidConnect(scene)
|
|
}
|
|
.onReceive(screenDidDisconnectPublisher) { scene in
|
|
screenDidDisconnect(scene)
|
|
}
|
|
.tabItem {
|
|
Label("All Workouts", systemImage: "figure.strengthtraining.traditional")
|
|
}
|
|
.tag(1)
|
|
|
|
CreateWorkoutMainView()
|
|
.tabItem {
|
|
Label("Create Workout", systemImage: "plus.app.fill")
|
|
}
|
|
.tag(2)
|
|
|
|
AccountView()
|
|
.tabItem {
|
|
Label("Accounts", systemImage: "person.fill.turn.down")
|
|
}
|
|
.tag(3)
|
|
}
|
|
.tint(WerkoutTheme.accent)
|
|
.tabBarMinimizeBehavior(.onScrollDown)
|
|
.preferredColorScheme(.dark)
|
|
.onAppear{
|
|
UIApplication.shared.isIdleTimerDisabled = scenePhase == .active
|
|
_ = try? AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback, mode: .default, options: .mixWithOthers)
|
|
}
|
|
.onChange(of: scenePhase) { _, phase in
|
|
UIApplication.shared.isIdleTimerDisabled = phase == .active
|
|
}
|
|
.onReceive(pub) { _ in
|
|
self.tabSelection = 1
|
|
}
|
|
.onReceive(logoutPub) { _ in
|
|
self.tabSelection = 1
|
|
}
|
|
}
|
|
}
|
|
|
|
private func screenDidDisconnect(_ scene: UIWindowScene) {
|
|
additionalWindows.removeAll { $0.windowScene == scene }
|
|
BridgeModule.shared.isShowingOnExternalDisplay = false
|
|
}
|
|
|
|
private func screenDidConnect(_ scene: UIWindowScene) {
|
|
let window = UIWindow(windowScene: scene)
|
|
|
|
let view = ExternalWorkoutDetailView()
|
|
.preferredColorScheme(.dark)
|
|
let controller = UIHostingController(rootView: view)
|
|
window.rootViewController = controller
|
|
window.isHidden = false
|
|
additionalWindows.append(window)
|
|
BridgeModule.shared.isShowingOnExternalDisplay = true
|
|
}
|
|
}
|