Skip to content

Commit

Permalink
History Log Feature #6 (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
reedes authored Jan 11, 2023
1 parent fc47ff6 commit c3cd786
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 41 deletions.
34 changes: 17 additions & 17 deletions Gym Routine Tracker Watch.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
40A70CAB293BA22D008688F8 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 40A70CA9293BA22D008688F8 /* LICENSE */; };
40A70CAC293BA22D008688F8 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 40A70CAA293BA22D008688F8 /* README.md */; };
40BD218F293FDD0500B17BEA /* GroutLib in Frameworks */ = {isa = PBXBuildFile; productRef = 40BD218E293FDD0500B17BEA /* GroutLib */; };
40CE1404293B0DBB00462D62 /* Gym Routine Tracker Watch App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 40CE1403293B0DBB00462D62 /* Gym Routine Tracker Watch App.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
40CE1404293B0DBB00462D62 /* Gym Routine Tracker.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 40CE1403293B0DBB00462D62 /* Gym Routine Tracker.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
40CE1409293B0DBB00462D62 /* WatchApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40CE1408293B0DBB00462D62 /* WatchApp.swift */; };
40CE140D293B0DBC00462D62 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 40CE140C293B0DBC00462D62 /* Assets.xcassets */; };
40CE1458293B100800462D62 /* GroutLib in Frameworks */ = {isa = PBXBuildFile; productRef = 40CE1457293B100800462D62 /* GroutLib */; };
Expand All @@ -38,7 +38,7 @@
dstPath = "$(CONTENTS_FOLDER_PATH)/Watch";
dstSubfolderSpec = 16;
files = (
40CE1404293B0DBB00462D62 /* Gym Routine Tracker Watch App.app in Embed Watch Content */,
40CE1404293B0DBB00462D62 /* Gym Routine Tracker.app in Embed Watch Content */,
);
name = "Embed Watch Content";
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -49,7 +49,7 @@
40A70CA9293BA22D008688F8 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
40A70CAA293BA22D008688F8 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
40CE13FD293B0DBB00462D62 /* Gym Routine Tracker Watch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Gym Routine Tracker Watch.app"; sourceTree = BUILT_PRODUCTS_DIR; };
40CE1403293B0DBB00462D62 /* Gym Routine Tracker Watch App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Gym Routine Tracker Watch App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
40CE1403293B0DBB00462D62 /* Gym Routine Tracker.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Gym Routine Tracker.app"; sourceTree = BUILT_PRODUCTS_DIR; };
40CE1408293B0DBB00462D62 /* WatchApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchApp.swift; sourceTree = "<group>"; };
40CE140C293B0DBC00462D62 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
40CE1459293B105800462D62 /* App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = "<group>"; };
Expand Down Expand Up @@ -89,7 +89,7 @@
isa = PBXGroup;
children = (
40CE13FD293B0DBB00462D62 /* Gym Routine Tracker Watch.app */,
40CE1403293B0DBB00462D62 /* Gym Routine Tracker Watch App.app */,
40CE1403293B0DBB00462D62 /* Gym Routine Tracker.app */,
);
name = Products;
sourceTree = "<group>";
Expand Down Expand Up @@ -143,9 +143,9 @@
productReference = 40CE13FD293B0DBB00462D62 /* Gym Routine Tracker Watch.app */;
productType = "com.apple.product-type.application.watchapp2-container";
};
40CE1402293B0DBB00462D62 /* Gym Routine Tracker Watch App */ = {
40CE1402293B0DBB00462D62 /* Gym Routine Tracker */ = {
isa = PBXNativeTarget;
buildConfigurationList = 40CE1413293B0DBC00462D62 /* Build configuration list for PBXNativeTarget "Gym Routine Tracker Watch App" */;
buildConfigurationList = 40CE1413293B0DBC00462D62 /* Build configuration list for PBXNativeTarget "Gym Routine Tracker" */;
buildPhases = (
40CE13FF293B0DBB00462D62 /* Sources */,
40CE1400293B0DBB00462D62 /* Frameworks */,
Expand All @@ -155,7 +155,7 @@
);
dependencies = (
);
name = "Gym Routine Tracker Watch App";
name = "Gym Routine Tracker";
packageProductDependencies = (
40CE1457293B100800462D62 /* GroutLib */,
40CE145C293B113600462D62 /* Compactor */,
Expand All @@ -164,7 +164,7 @@
40EBE1C829634FEA004B9189 /* GroutUI */,
);
productName = "Gym Routine Tracker Watch App";
productReference = 40CE1403293B0DBB00462D62 /* Gym Routine Tracker Watch App.app */;
productReference = 40CE1403293B0DBB00462D62 /* Gym Routine Tracker.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
Expand Down Expand Up @@ -204,7 +204,7 @@
projectRoot = "";
targets = (
40CE13FC293B0DBB00462D62 /* Gym Routine Tracker Watch */,
40CE1402293B0DBB00462D62 /* Gym Routine Tracker Watch App */,
40CE1402293B0DBB00462D62 /* Gym Routine Tracker */,
);
};
/* End PBXProject section */
Expand Down Expand Up @@ -245,7 +245,7 @@
/* Begin PBXTargetDependency section */
40CE1406293B0DBB00462D62 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 40CE1402293B0DBB00462D62 /* Gym Routine Tracker Watch App */;
target = 40CE1402293B0DBB00462D62 /* Gym Routine Tracker */;
targetProxy = 40CE1405293B0DBB00462D62 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
Expand Down Expand Up @@ -372,7 +372,7 @@
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CODE_SIGN_ENTITLEMENTS = Sources/App.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 5;
CURRENT_PROJECT_VERSION = 6;
DEVELOPMENT_ASSET_PATHS = "\"Sources/Preview Content\"";
DEVELOPMENT_TEAM = J735QC5U38;
ENABLE_PREVIEWS = YES;
Expand All @@ -385,7 +385,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.4;
MARKETING_VERSION = 1.5;
PRODUCT_BUNDLE_IDENTIFIER = org.openalloc.grout.watch;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = watchos;
Expand All @@ -405,7 +405,7 @@
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CODE_SIGN_ENTITLEMENTS = Sources/App.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 5;
CURRENT_PROJECT_VERSION = 6;
DEVELOPMENT_ASSET_PATHS = "\"Sources/Preview Content\"";
DEVELOPMENT_TEAM = J735QC5U38;
ENABLE_PREVIEWS = YES;
Expand All @@ -418,7 +418,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.4;
MARKETING_VERSION = 1.5;
PRODUCT_BUNDLE_IDENTIFIER = org.openalloc.grout.watch;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = watchos;
Expand All @@ -440,7 +440,7 @@
DEVELOPMENT_TEAM = J735QC5U38;
INFOPLIST_FILE = Sources/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Gym Routine Tracker";
MARKETING_VERSION = 1.4;
MARKETING_VERSION = 1.5;
PRODUCT_BUNDLE_IDENTIFIER = org.openalloc.grout;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
Expand All @@ -457,7 +457,7 @@
DEVELOPMENT_TEAM = J735QC5U38;
INFOPLIST_FILE = Sources/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Gym Routine Tracker";
MARKETING_VERSION = 1.4;
MARKETING_VERSION = 1.5;
PRODUCT_BUNDLE_IDENTIFIER = org.openalloc.grout;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
Expand All @@ -478,7 +478,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
40CE1413293B0DBC00462D62 /* Build configuration list for PBXNativeTarget "Gym Routine Tracker Watch App" */ = {
40CE1413293B0DBC00462D62 /* Build configuration list for PBXNativeTarget "Gym Routine Tracker" */ = {
isa = XCConfigurationList;
buildConfigurations = (
40CE1414293B0DBC00462D62 /* Debug */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "40CE1402293B0DBB00462D62"
BuildableName = "Gym Routine Tracker Watch App.app"
BlueprintName = "Gym Routine Tracker Watch App"
BuildableName = "Gym Routine Tracker.app"
BlueprintName = "Gym Routine Tracker"
ReferencedContainer = "container:Gym Routine Tracker Watch.xcodeproj">
</BuildableReference>
</BuildActionEntry>
Expand Down Expand Up @@ -59,8 +59,8 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "40CE1402293B0DBB00462D62"
BuildableName = "Gym Routine Tracker Watch App.app"
BlueprintName = "Gym Routine Tracker Watch App"
BuildableName = "Gym Routine Tracker.app"
BlueprintName = "Gym Routine Tracker"
ReferencedContainer = "container:Gym Routine Tracker Watch.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
Expand Down Expand Up @@ -90,8 +90,8 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "40CE1402293B0DBB00462D62"
BuildableName = "Gym Routine Tracker Watch App.app"
BlueprintName = "Gym Routine Tracker Watch App"
BuildableName = "Gym Routine Tracker.app"
BlueprintName = "Gym Routine Tracker"
ReferencedContainer = "container:Gym Routine Tracker Watch.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
Expand Down
50 changes: 35 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
# Gym Routine Tracker Watch App
# Gym Routine Tracker

_A minimalist wrist-based gym workout tracker_

## Download

Available as a free download in the App Store [HERE](https://apps.apple.com/us/app/gym-routine-tracker/id6444747204).
Available as a FREE download in the App Store [GRT for Apple Watch](https://apps.apple.com/us/app/gym-routine-tracker/id6444747204)

## Features

- Independent WatchOS app, not requiring companion iOS app. Leave your iPhone at home!
- LARGE text in RUN mode, for those with presbyopia. Leave your cheaters in your locker!
- Prioritizes convenience, quick interactions, and the basic needs of the recreational fitness user.
- _NEW in 1.5_ Logs routine/exercise completions, where history can be reviewed on your iPhone/iPad.

- Independent watchOS app, not requiring companion iOS app. Leave your iPhone at home!
- LARGE text in RUN mode, for the farsighted. Leave your glasses in your locker!
- Simple data model of user-defined routines and their exercises.
- Your data syncs with your private iCloud account when a network connection is available.
- Fully open source where code is licensed with Mozilla Public License 2.0.
- Available separately as an app for iPhone/iPad.

GRT prioritizes convenience, quick interactions, and the basic needs of the recreational fitness user.

### Quick and easy setup

Expand All @@ -25,33 +32,46 @@ Available as a free download in the App Store [HERE](https://apps.apple.com/us/a
- Convenient skip to the next incomplete exercise, in case a machine isn’t immediately available.
- Control screen showing the time elapsed since starting the routine.

### App features
### History features (NEW)

- Simple data model of user-defined routines and their exercises.
- Your data syncs with CloudKit when a network connection is available.
- Fully open source where code is licensed with Mozilla Public License 2.0.
- App available as a free download in the WatchOS App Store.
- Completion of routine/exercise is automatically logged to your private iCloud account.
- Logging can be disabled in settings.
- For the watchOS app, recent history will be stored locally for up to 1 year. Periodically run iOS app for long-term storage and review.
- History can be reviewed on the iOS app for the iPhone/iPad.

### iCloud Sync

- Your data automatically syncs with your private iCloud account when a network connection is available.
- That synced data available to the _Gym Routine Tracker_ app running on your other devices.

## Requirements

Requires WatchOS 9.1 or later
Requires watchOS 9.1 or later

## Caveats

- GRT remembers only your most recent workout for each routine. It does not (yet) maintain a historical record of progress.
- Future enhancements will largely rely on contributors.
- Future enhancements may largely rely on contributors.
- GRT prioritizes convenience, quick interactions, and the basic needs of the recreational user. More sophisticated trackers are available on the App Store.

To any Apple product managers who like this app, please consider Sherlocking it!

## See Also

* [GRT Website](https://gym-routine-tracker.github.io) - Website for GRT (both watchOS and iOS implementations)
* [GRT on the App Store](https://apps.apple.com/us/app/gym-routine-tracker/id6444747204) - App Store link for free download of GRT
### App Download Links

* [GRT for Apple Watch](https://apps.apple.com/us/app/gym-routine-tracker/id6444747204) - App Store link for FREE download
* [GRT+ for iPhone/iPad](https://apps.apple.com/us/app/gym-routine-tracker/id1662243916) - App Store link for FREE download

### Source Code

* [GRT Website](https://gym-routine-tracker.github.io) - Website for GRT
* [GRT for Apple Watch Source](https://github.com/gym-routine-tracker/Gym-Routine-Tracker-Watch-App) - watchOS implementation
* [GRT+ for iPhone/iPad Source](https://github.com/gym-routine-tracker/Gym-Routine-Tracker-Plus-App) - iOS implementation
* [GroutUI](https://github.com/gym-routine-tracker/GroutUI) - shared UI layer for GRT (watchOS and iOS)
* [GroutLib](https://github.com/gym-routine-tracker/GroutLib) - shared business logic and data layer for GRT

Apps by the same author:
### macOS Apps by the same author

* [FlowAllocator](https://openalloc.github.io/FlowAllocator/index.html) - portfolio rebalancing tool for macOS
* [FlowWorth](https://openalloc.github.io/FlowWorth/index.html) - portfolio valuation and tracking tool for macOS
Expand Down
1 change: 1 addition & 0 deletions Sources/App.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
<string>iCloud.org.openalloc.grout</string>
<string>iCloud.org.openalloc.grout.archive</string>
</array>
<key>com.apple.developer.icloud-services</key>
<array>
Expand Down
3 changes: 1 addition & 2 deletions Sources/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@ struct ContentView: View {
}
}

// TODO: four copies of each routine showing up; should be one!
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
let ctx = PersistenceManager.preview.container.viewContext
let ctx = PersistenceManager.getPreviewContainer().viewContext
let routine = Routine.create(ctx, userOrder: 0)
routine.name = "Back & Bicep"
let e1 = Exercise.create(ctx, userOrder: 0)
Expand Down
11 changes: 10 additions & 1 deletion Sources/WatchApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ struct Gym_Routine_Tracker_Watch_App: App {

@Environment(\.scenePhase) var scenePhase

private let logger = Logger(
subsystem: Bundle.main.bundleIdentifier!,
category: "App"
)

var body: some Scene {
WindowGroup {
ContentView()
Expand All @@ -27,7 +32,11 @@ struct Gym_Routine_Tracker_Watch_App: App {
}
.onChange(of: scenePhase) { _ in
// save if: (1) app moved to background, and (2) changes are pending
persistenceManager.save()
do {
try persistenceManager.container.viewContext.save()
} catch {
logger.error("\(#function): \(error.localizedDescription)")
}
}
}
}

0 comments on commit c3cd786

Please sign in to comment.