Skip to content

Commit

Permalink
Better watchOS app
Browse files Browse the repository at this point in the history
  • Loading branch information
kabouzeid committed Feb 25, 2022
1 parent 37d3e7e commit 7893e11
Show file tree
Hide file tree
Showing 14 changed files with 306 additions and 323 deletions.
36 changes: 16 additions & 20 deletions Iron.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@
8A204B412367AEE200F40F79 /* URL+EnsureFileAccess.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A204B402367AEE200F40F79 /* URL+EnsureFileAccess.swift */; };
8A239AE8203580A1006BB38B /* WorkoutDataTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A239AE7203580A1006BB38B /* WorkoutDataTests.swift */; };
8A2F52A72316969B00194C54 /* WorkoutSetCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A2F52A62316969B00194C54 /* WorkoutSetCell.swift */; };
8A34FA072379B509009CF1DD /* EndHostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A34FA062379B509009CF1DD /* EndHostingController.swift */; };
8A34FA092379B59D009CF1DD /* EndContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A34FA082379B59D009CF1DD /* EndContentView.swift */; };
8A34FA092379B59D009CF1DD /* OptionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A34FA082379B59D009CF1DD /* OptionsView.swift */; };
8A362F2E23A2A2BC0071A167 /* PersonalRecordView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A362F2D23A2A2BC0071A167 /* PersonalRecordView.swift */; };
8A36F9E8231E932A0036E504 /* AddExercisesSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A36F9E7231E932A0036E504 /* AddExercisesSheet.swift */; };
8A36F9EA231EA62F0036E504 /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A36F9E9231EA62F0036E504 /* NotificationManager.swift */; };
Expand Down Expand Up @@ -140,8 +139,8 @@
8A861920236DAB6E00C1E96C /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8A86191E236DAB6E00C1E96C /* Interface.storyboard */; };
8A861922236DAB7000C1E96C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8A861921236DAB7000C1E96C /* Assets.xcassets */; };
8A861929236DAB7000C1E96C /* WatchIron Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 8A861928236DAB7000C1E96C /* WatchIron Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
8A86192E236DAB7000C1E96C /* MainContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A86192D236DAB7000C1E96C /* MainContentView.swift */; };
8A861930236DAB7000C1E96C /* MainHostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A86192F236DAB7000C1E96C /* MainHostingController.swift */; };
8A86192E236DAB7000C1E96C /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A86192D236DAB7000C1E96C /* ContentView.swift */; };
8A861930236DAB7000C1E96C /* WatchIronApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A86192F236DAB7000C1E96C /* WatchIronApp.swift */; };
8A861932236DAB7000C1E96C /* ExtensionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A861931236DAB7000C1E96C /* ExtensionDelegate.swift */; };
8A861934236DAB7100C1E96C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8A861933236DAB7100C1E96C /* Assets.xcassets */; };
8A861937236DAB7100C1E96C /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8A861936236DAB7100C1E96C /* Preview Assets.xcassets */; };
Expand Down Expand Up @@ -577,8 +576,7 @@
8A239AE7203580A1006BB38B /* WorkoutDataTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkoutDataTests.swift; sourceTree = "<group>"; };
8A2D21C023563FF60012A0A4 /* UserDefaults+HiddenExerciseUuids.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+HiddenExerciseUuids.swift"; sourceTree = "<group>"; };
8A2F52A62316969B00194C54 /* WorkoutSetCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkoutSetCell.swift; sourceTree = "<group>"; };
8A34FA062379B509009CF1DD /* EndHostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndHostingController.swift; sourceTree = "<group>"; };
8A34FA082379B59D009CF1DD /* EndContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndContentView.swift; sourceTree = "<group>"; };
8A34FA082379B59D009CF1DD /* OptionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptionsView.swift; sourceTree = "<group>"; };
8A362F2D23A2A2BC0071A167 /* PersonalRecordView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersonalRecordView.swift; sourceTree = "<group>"; };
8A36F9E7231E932A0036E504 /* AddExercisesSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddExercisesSheet.swift; sourceTree = "<group>"; };
8A36F9E9231EA62F0036E504 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -667,8 +665,8 @@
8A861921236DAB7000C1E96C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
8A861923236DAB7000C1E96C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8A861928236DAB7000C1E96C /* WatchIron Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "WatchIron Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
8A86192D236DAB7000C1E96C /* MainContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainContentView.swift; sourceTree = "<group>"; };
8A86192F236DAB7000C1E96C /* MainHostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainHostingController.swift; sourceTree = "<group>"; };
8A86192D236DAB7000C1E96C /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
8A86192F236DAB7000C1E96C /* WatchIronApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchIronApp.swift; sourceTree = "<group>"; };
8A861931236DAB7000C1E96C /* ExtensionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionDelegate.swift; sourceTree = "<group>"; };
8A861933236DAB7100C1E96C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
8A861936236DAB7100C1E96C /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1361,11 +1359,10 @@
8A86194C236DB65200C1E96C /* UI */ = {
isa = PBXGroup;
children = (
8A86192F236DAB7000C1E96C /* MainHostingController.swift */,
8A86192D236DAB7000C1E96C /* MainContentView.swift */,
8A86192F236DAB7000C1E96C /* WatchIronApp.swift */,
8A86192D236DAB7000C1E96C /* ContentView.swift */,
8A58807923776004007F31A1 /* WorkoutSessionView.swift */,
8A34FA062379B509009CF1DD /* EndHostingController.swift */,
8A34FA082379B59D009CF1DD /* EndContentView.swift */,
8A34FA082379B59D009CF1DD /* OptionsView.swift */,
);
path = UI;
sourceTree = "<group>";
Expand Down Expand Up @@ -2330,17 +2327,16 @@
8A58807A23776004007F31A1 /* WorkoutSessionView.swift in Sources */,
8A141CAF239C7DFF00993A61 /* Benchmark.swift in Sources */,
8ADC1B5E2371C9390019C01A /* WorkoutSessionManager.swift in Sources */,
8A861930236DAB7000C1E96C /* MainHostingController.swift in Sources */,
8A861930236DAB7000C1E96C /* WatchIronApp.swift in Sources */,
8AA68CFF242FB0D200418F36 /* IdentifiableHolder.swift in Sources */,
8A861948236DB17C00C1E96C /* PhoneConnectionManager.swift in Sources */,
8A4D3B7223858F6F007A3792 /* NotificationManager.swift in Sources */,
8AA68CFE242F84A200418F36 /* GenericError.swift in Sources */,
8AF07868239B0A3000CA95D6 /* PayloadKey.swift in Sources */,
8AA68CFB242F7CE400418F36 /* OSLog+trace.swift in Sources */,
8A58807823773432007F31A1 /* WorkoutSessionManagerStore.swift in Sources */,
8A34FA092379B59D009CF1DD /* EndContentView.swift in Sources */,
8A86192E236DAB7000C1E96C /* MainContentView.swift in Sources */,
8A34FA072379B509009CF1DD /* EndHostingController.swift in Sources */,
8A34FA092379B59D009CF1DD /* OptionsView.swift in Sources */,
8A86192E236DAB7000C1E96C /* ContentView.swift in Sources */,
8A861932236DAB7000C1E96C /* ExtensionDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -2825,7 +2821,7 @@
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 4;
WATCHOS_DEPLOYMENT_TARGET = 6.1;
WATCHOS_DEPLOYMENT_TARGET = 8.0;
};
name = Debug;
};
Expand All @@ -2849,7 +2845,7 @@
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 4;
WATCHOS_DEPLOYMENT_TARGET = 6.1;
WATCHOS_DEPLOYMENT_TARGET = 8.0;
};
name = Release;
};
Expand Down Expand Up @@ -2879,7 +2875,7 @@
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 4;
WATCHOS_DEPLOYMENT_TARGET = 6.1;
WATCHOS_DEPLOYMENT_TARGET = 8.0;
};
name = Debug;
};
Expand Down Expand Up @@ -2908,7 +2904,7 @@
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 4;
WATCHOS_DEPLOYMENT_TARGET = 6.1;
WATCHOS_DEPLOYMENT_TARGET = 8.0;
};
name = Release;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,48 +1,53 @@
{
"assets" : [
{
"idiom" : "watch",
"filename" : "Circular.imageset",
"idiom" : "watch",
"role" : "circular"
},
{
"idiom" : "watch",
"filename" : "Extra Large.imageset",
"idiom" : "watch",
"role" : "extra-large"
},
{
"idiom" : "watch",
"filename" : "Graphic Bezel.imageset",
"idiom" : "watch",
"role" : "graphic-bezel"
},
{
"idiom" : "watch",
"filename" : "Graphic Circular.imageset",
"idiom" : "watch",
"role" : "graphic-circular"
},
{
"idiom" : "watch",
"filename" : "Graphic Corner.imageset",
"idiom" : "watch",
"role" : "graphic-corner"
},
{
"filename" : "Graphic Extra Large.imageset",
"idiom" : "watch",
"role" : "graphic-extra-large"
},
{
"filename" : "Graphic Large Rectangular.imageset",
"idiom" : "watch",
"role" : "graphic-large-rectangular"
},
{
"idiom" : "watch",
"filename" : "Modular.imageset",
"idiom" : "watch",
"role" : "modular"
},
{
"idiom" : "watch",
"filename" : "Utilitarian.imageset",
"idiom" : "watch",
"role" : "utilitarian"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"images" : [
{
"idiom" : "watch",
"scale" : "2x"
},
{
"idiom" : "watch",
"scale" : "2x",
"screen-width" : "<=145"
},
{
"idiom" : "watch",
"scale" : "2x",
"screen-width" : ">183"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"auto-scaling" : "auto"
}
}
18 changes: 2 additions & 16 deletions WatchIron Extension/ExtensionDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,11 @@ import os.log
class ExtensionDelegate: NSObject, WKExtensionDelegate {
func applicationDidFinishLaunching() {
// Perform any final initialization of your application.
reloadRootPageControllers(workoutSessionManagerStore: WorkoutSessionManagerStore.shared)
cancellable = WorkoutSessionManagerStore.shared.objectWillChange.sink {
os_log("Reloading root page controllers", type: .info)
self.reloadRootPageControllers(workoutSessionManagerStore: WorkoutSessionManagerStore.shared)
}
os_log("Checking whether active workout session can be recovered")
handleActiveWorkoutRecovery() // somehow this isn't automatically called by the system?! last checked I think watchOS 6.0
handleActiveWorkoutRecovery() // somehow this isn't automatically called by the system?! last checked watchOS 8
PhoneConnectionManager.shared.activateSession()
NotificationManager.shared.awake()
}

private var cancellable: AnyCancellable?
private func reloadRootPageControllers(workoutSessionManagerStore: WorkoutSessionManagerStore) {
if workoutSessionManagerStore.workoutSessionManager == nil {
WKInterfaceController.reloadRootPageControllers(withNames: ["workout"], contexts: nil, orientation: .horizontal, pageIndex: 0)
} else {
WKInterfaceController.reloadRootPageControllers(withNames: ["options", "workout", "music"], contexts: nil, orientation: .horizontal, pageIndex: 1)
}
}

func applicationDidBecomeActive() {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
Expand Down Expand Up @@ -73,7 +59,7 @@ class ExtensionDelegate: NSObject, WKExtensionDelegate {
}
}
}

func handleActiveWorkoutRecovery() {
os_log("Recovering active workout session")
WorkoutSessionManager.healthStore.recoverActiveWorkoutSession { workoutSession, error in
Expand Down
4 changes: 2 additions & 2 deletions WatchIron Extension/NotificationManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ class NotificationManager: NSObject {
}

extension NotificationManager: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification) async -> UNNotificationPresentationOptions {
print(#function)
completionHandler([.alert, .sound])
return [.banner, .sound]
}
}
75 changes: 75 additions & 0 deletions WatchIron Extension/UI/ContentView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//
// MainContentView.swift
// WatchIron Extension
//
// Created by Karim Abou Zeid on 02.11.19.
// Copyright © 2019 Karim Abou Zeid Software. All rights reserved.
//

import SwiftUI
import WatchKit
import HealthKit

struct ContentView: View {
var body: some View {
_ContentView()
.environmentObject(WorkoutSessionManagerStore.shared)
}
}

private struct _ContentView: View {
@EnvironmentObject var workoutSessionManagerStore: WorkoutSessionManagerStore

@State private var selectedTab = "workout"

@ViewBuilder
var body: some View {
if workoutSessionManagerStore.workoutSessionManager != nil {
TabView(selection: $selectedTab) {
OptionsView()
.tag("options")

WorkoutSessionView(workoutSessionManager: workoutSessionManagerStore.workoutSessionManager!)
.tag("workout")

NowPlayingView()
.tag("now playing")
}
} else {
Group {
if let s = errorMessage {
Text(s).foregroundColor(.red)
} else {
Text("Start a workout on your iPhone.")
}
}.onAppear {
self.selectedTab = "workout"
}
}
}

private var errorMessage: String? {
guard HKHealthStore.isHealthDataAvailable() else {
return "HealthKit is not available on this device."
}

switch WorkoutSessionManager.healthStore.authorizationStatus(for: .workoutType()) {
case .notDetermined:
return nil
case .sharingAuthorized:
return nil
case .sharingDenied:
return "Not authorized for Apple Health. You can authorize Iron in the settings app."
@unknown default:
return nil
}
}
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
#endif
61 changes: 0 additions & 61 deletions WatchIron Extension/UI/EndContentView.swift

This file was deleted.

Loading

0 comments on commit 7893e11

Please sign in to comment.