Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 58 additions & 5 deletions Gym Routine Tracker Plus.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,16 @@
objects = {

/* Begin PBXBuildFile section */
4001ED0D29732D4500F165ED /* ExportSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4001ED0C29732D4500F165ED /* ExportSettings.swift */; };
4001ED0F29732E1300F165ED /* ColorSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4001ED0E29732E1300F165ED /* ColorSettings.swift */; };
401064D92973374700BFB00E /* ZipDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = 401064D82973374700BFB00E /* ZipDocument.swift */; };
4011EECD2961C9B000A36D87 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 4011EECC2961C9B000A36D87 /* LICENSE */; };
40245EF6296BE7D4007B5DAB /* ExerciseRunList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40245EF5296BE7D4007B5DAB /* ExerciseRunList.swift */; };
402A5F2F296B7FE000A43DB3 /* HistoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 402A5F2E296B7F7B00A43DB3 /* HistoryView.swift */; };
402A5F32296B835B00A43DB3 /* Tabler in Frameworks */ = {isa = PBXBuildFile; productRef = 402A5F31296B835B00A43DB3 /* Tabler */; };
403CA2CE2971F6660084785B /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = 403CA2CD2971F6660084785B /* ZIPFoundation */; };
403CA2D0297220460084785B /* Export-Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 403CA2CF29721E750084785B /* Export-Utils.swift */; };
403CA2D22972829F0084785B /* PhoneSettingsForm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 403CA2D12972829F0084785B /* PhoneSettingsForm.swift */; };
408FACFE296CAC9300D02C9C /* RoutineRunList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 408FACFD296CABC400D02C9C /* RoutineRunList.swift */; };
40B51E45294549DF0047377A /* GroutUI in Frameworks */ = {isa = PBXBuildFile; productRef = 40B51E44294549DF0047377A /* GroutUI */; };
40CCF3F629454D2B007DDE69 /* GroutLib in Frameworks */ = {isa = PBXBuildFile; productRef = 40CCF3F529454D2B007DDE69 /* GroutLib */; };
Expand All @@ -23,10 +29,15 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
4001ED0C29732D4500F165ED /* ExportSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExportSettings.swift; sourceTree = "<group>"; };
4001ED0E29732E1300F165ED /* ColorSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorSettings.swift; sourceTree = "<group>"; };
401064D82973374700BFB00E /* ZipDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZipDocument.swift; sourceTree = "<group>"; };
4011EECC2961C9B000A36D87 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
4011EECE2961C9BC00A36D87 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
40245EF5296BE7D4007B5DAB /* ExerciseRunList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExerciseRunList.swift; sourceTree = "<group>"; };
402A5F2E296B7F7B00A43DB3 /* HistoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryView.swift; sourceTree = "<group>"; };
403CA2CF29721E750084785B /* Export-Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Export-Utils.swift"; sourceTree = "<group>"; };
403CA2D12972829F0084785B /* PhoneSettingsForm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhoneSettingsForm.swift; sourceTree = "<group>"; };
408FACFD296CABC400D02C9C /* RoutineRunList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoutineRunList.swift; sourceTree = "<group>"; };
40E347BA29452CF1003A19B9 /* Gym Routine Tracker Plus.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Gym Routine Tracker Plus.app"; sourceTree = BUILT_PRODUCTS_DIR; };
40E347BD29452CF1003A19B9 /* PlusApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlusApp.swift; sourceTree = "<group>"; };
Expand All @@ -47,12 +58,36 @@
40E347D329452E4B003A19B9 /* Compactor in Frameworks */,
40EBE1CC29635306004B9189 /* GroutUI in Frameworks */,
40CCF3F629454D2B007DDE69 /* GroutLib in Frameworks */,
403CA2CE2971F6660084785B /* ZIPFoundation in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
401064DA2973378500BFB00E /* Helper */ = {
isa = PBXGroup;
children = (
401064D82973374700BFB00E /* ZipDocument.swift */,
403CA2CF29721E750084785B /* Export-Utils.swift */,
);
path = Helper;
sourceTree = "<group>";
};
401064DB2973378C00BFB00E /* Views */ = {
isa = PBXGroup;
children = (
40E347BF29452CF1003A19B9 /* ContentView.swift */,
4001ED0E29732E1300F165ED /* ColorSettings.swift */,
40245EF5296BE7D4007B5DAB /* ExerciseRunList.swift */,
4001ED0C29732D4500F165ED /* ExportSettings.swift */,
402A5F2E296B7F7B00A43DB3 /* HistoryView.swift */,
403CA2D12972829F0084785B /* PhoneSettingsForm.swift */,
408FACFD296CABC400D02C9C /* RoutineRunList.swift */,
);
path = Views;
sourceTree = "<group>";
};
40B51E41294549D90047377A /* Frameworks */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -83,13 +118,11 @@
isa = PBXGroup;
children = (
40E347BD29452CF1003A19B9 /* PlusApp.swift */,
40E347BF29452CF1003A19B9 /* ContentView.swift */,
402A5F2E296B7F7B00A43DB3 /* HistoryView.swift */,
408FACFD296CABC400D02C9C /* RoutineRunList.swift */,
40245EF5296BE7D4007B5DAB /* ExerciseRunList.swift */,
401064DB2973378C00BFB00E /* Views */,
401064DA2973378500BFB00E /* Helper */,
40E347C329452CF1003A19B9 /* App.entitlements */,
40E347C129452CF1003A19B9 /* Assets.xcassets */,
40EBCFDE294BFB880082A172 /* Info.plist */,
40E347C329452CF1003A19B9 /* App.entitlements */,
40E347C429452CF1003A19B9 /* Preview Content */,
);
path = Sources;
Expand Down Expand Up @@ -125,6 +158,7 @@
40CCF3F529454D2B007DDE69 /* GroutLib */,
40EBE1CB29635306004B9189 /* GroutUI */,
402A5F31296B835B00A43DB3 /* Tabler */,
403CA2CD2971F6660084785B /* ZIPFoundation */,
);
productName = "Gym Routine Tracker Plus";
productReference = 40E347BA29452CF1003A19B9 /* Gym Routine Tracker Plus.app */;
Expand Down Expand Up @@ -158,6 +192,7 @@
40E347D129452E4B003A19B9 /* XCRemoteSwiftPackageReference "SwiftCompactor" */,
40EBE1CA29635306004B9189 /* XCRemoteSwiftPackageReference "GroutUI" */,
402A5F30296B835B00A43DB3 /* XCRemoteSwiftPackageReference "SwiftTabler" */,
403CA2CC2971F6660084785B /* XCRemoteSwiftPackageReference "ZIPFoundation" */,
);
productRefGroup = 40E347BB29452CF1003A19B9 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -187,6 +222,11 @@
buildActionMask = 2147483647;
files = (
40E347C029452CF1003A19B9 /* ContentView.swift in Sources */,
403CA2D22972829F0084785B /* PhoneSettingsForm.swift in Sources */,
4001ED0F29732E1300F165ED /* ColorSettings.swift in Sources */,
4001ED0D29732D4500F165ED /* ExportSettings.swift in Sources */,
401064D92973374700BFB00E /* ZipDocument.swift in Sources */,
403CA2D0297220460084785B /* Export-Utils.swift in Sources */,
408FACFE296CAC9300D02C9C /* RoutineRunList.swift in Sources */,
40245EF6296BE7D4007B5DAB /* ExerciseRunList.swift in Sources */,
402A5F2F296B7FE000A43DB3 /* HistoryView.swift in Sources */,
Expand Down Expand Up @@ -424,6 +464,14 @@
minimumVersion = 0.9.6;
};
};
403CA2CC2971F6660084785B /* XCRemoteSwiftPackageReference "ZIPFoundation" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/weichsel/ZIPFoundation.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 0.9.9;
};
};
40E347D129452E4B003A19B9 /* XCRemoteSwiftPackageReference "SwiftCompactor" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/openalloc/SwiftCompactor.git";
Expand All @@ -448,6 +496,11 @@
package = 402A5F30296B835B00A43DB3 /* XCRemoteSwiftPackageReference "SwiftTabler" */;
productName = Tabler;
};
403CA2CD2971F6660084785B /* ZIPFoundation */ = {
isa = XCSwiftPackageProductDependency;
package = 403CA2CC2971F6660084785B /* XCRemoteSwiftPackageReference "ZIPFoundation" */;
productName = ZIPFoundation;
};
40B51E44294549DF0047377A /* GroutUI */ = {
isa = XCSwiftPackageProductDependency;
productName = GroutUI;
Expand Down
54 changes: 54 additions & 0 deletions Sources/Helper/Export-Utils.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// Export-Utils.swift
//
// Copyright 2023 OpenAlloc LLC
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//

import CoreData
import ZIPFoundation

import GroutLib

public func createZipArchive(_ context: NSManagedObjectContext,
mainStore: NSPersistentStore,
archiveStore: NSPersistentStore,
format: ExportFormat = .CSV) throws -> Data?
{
guard let archive = Archive(accessMode: .create)
else { throw DataError.archiveCreationFailure }

func makeDelimFile<T: NSFetchRequestResult & Encodable & MAttributable>(_: T.Type,
inStore: NSPersistentStore?) throws
{
let request = makeRequest(T.self, inStore: inStore)
let results = try context.fetch(request)
let data = try exportData(results, format: format)
let fileName = "\(T.fileNamePrefix).\(format.defaultFileExtension)"
try archive.addEntry(with: fileName,
type: .file,
uncompressedSize: Int64(data.count),
provider: { position, size -> Data in
let range = Int(position) ..< Int(position) + size
return data.subdata(in: range)
})
}

try makeDelimFile(Routine.self, inStore: mainStore)
try makeDelimFile(Exercise.self, inStore: mainStore)

// NOT WORKING: Local function 'makeDelimFile(_:inStore:)' requires that 'NSManagedObject' conform to 'Encodable'
// [ZRoutine.self, ZRoutineRun.self, ZExercise.self, ZExerciseRun.self].forEach {
// try makeDelimFile($0, inStore: archiveStore)
// }

try makeDelimFile(ZRoutine.self, inStore: archiveStore)
try makeDelimFile(ZRoutineRun.self, inStore: archiveStore)
try makeDelimFile(ZExercise.self, inStore: archiveStore)
try makeDelimFile(ZExerciseRun.self, inStore: archiveStore)

return archive.data
}
32 changes: 32 additions & 0 deletions Sources/Helper/ZipDocument.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// ZipDocument.swift
//
// Copyright 2022, 2023 OpenAlloc LLC
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//

import SwiftUI
import UniformTypeIdentifiers

/// Simple wrapper for Zip Archive data
public struct ZipDocument: FileDocument {
public static var readableContentTypes = [UTType.zip]
public static var writableContentTypes = [UTType.zip]

private var data: Data

public init(data: Data) {
self.data = data
}

public init(configuration: ReadConfiguration) throws {
data = configuration.file.regularFileContents ?? Data()
}

public func fileWrapper(configuration _: WriteConfiguration) throws -> FileWrapper {
FileWrapper(regularFileWithContents: data)
}
}
44 changes: 44 additions & 0 deletions Sources/Views/ColorSettings.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// ColorSettings.swift
//
// Copyright 2023 OpenAlloc LLC
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//

import SwiftUI

import GroutLib
import GroutUI

struct ColorSettings: View {
// MARK: - Locals

@AppStorage(colorSchemeModeKey) var colorSchemeMode: ColorSchemeMode = .automatic

// MARK: - Views

var body: some View {
Section {
Picker("Color", selection: $colorSchemeMode) {
ForEach(ColorSchemeMode.allCases, id: \.self) { mode in
Text(mode.description).tag(mode)
}
}
.pickerStyle(SegmentedPickerStyle())
} header: {
Text("Color Scheme")
.foregroundStyle(.tint)
}
}
}

struct ColorSettings_Previews: PreviewProvider {
static var previews: some View {
Form {
ColorSettings()
}
}
}
7 changes: 5 additions & 2 deletions Sources/ContentView.swift → Sources/Views/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//

import CoreData
import os
import SwiftUI

import GroutLib
Expand All @@ -28,6 +28,9 @@ struct ContentView: View {
@SceneStorage("main-history-nav") private var historyNavData: Data?
@SceneStorage("main-settings-nav") private var settingsNavData: Data?

private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!,
category: String(describing: ContentView.self))

var body: some View {
TabView(selection: $selectedTab) {
NavStack(name: "routines",
Expand All @@ -51,7 +54,7 @@ struct ContentView: View {

NavStack(name: "settings",
navData: $settingsNavData) {
SettingsForm()
PhoneSettingsForm()
}
.tabItem {
Label("Settings", systemImage: "gear")
Expand Down
File renamed without changes.
Loading