From ba24d706bc876183da9f329523187997d9f8a745 Mon Sep 17 00:00:00 2001 From: Dallas Groot Date: Wed, 8 Apr 2026 17:27:44 -0700 Subject: [PATCH] Initial project setup --- .DS_Store | Bin 0 -> 6148 bytes Info.plist | 28 ++ Sources/App/TagMasterApp.swift | 10 + Sources/Models/Track.swift | 25 ++ Sources/ViewModels/EditorViewModel.swift | 58 +++ Sources/Views/EditorView.swift | 101 +++++ Sources/Views/MainImportView.swift | 33 ++ TagMaster.xcodeproj/project.pbxproj | 364 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/swiftpm/Package.resolved | 15 + .../UserInterfaceState.xcuserstate | Bin 0 -> 13640 bytes .../xcschemes/xcschememanagement.plist | 14 + generate.sh | 0 project.yml | 22 ++ 14 files changed, 677 insertions(+) create mode 100644 .DS_Store create mode 100644 Info.plist create mode 100644 Sources/App/TagMasterApp.swift create mode 100644 Sources/Models/Track.swift create mode 100644 Sources/ViewModels/EditorViewModel.swift create mode 100644 Sources/Views/EditorView.swift create mode 100644 Sources/Views/MainImportView.swift create mode 100644 TagMaster.xcodeproj/project.pbxproj create mode 100644 TagMaster.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 TagMaster.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 TagMaster.xcodeproj/project.xcworkspace/xcuserdata/dallasgroot.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 TagMaster.xcodeproj/xcuserdata/dallasgroot.xcuserdatad/xcschemes/xcschememanagement.plist mode change 100644 => 100755 generate.sh create mode 100644 project.yml diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..1e11b1807e4fd4a7eebccd8545770e0b4d85028e GIT binary patch literal 6148 zcmeHKOG*Pl5Phv#3y#-*!x0F#VF!h{*3LY8v~58@eg;aR+eue!?5 z;4BnDM600dRexSj_k-!~0uUxQ4_H)$sGobzKzms-BaPZIAAsZXX_x zzrrrR!EP?!uli0G@7@(~1zZ7F;6E$CJ6kN9r^uvJV)2VF`5 zi1Lh1##nL*;Y7pSuvKIaEhv?!)L + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSSupportsOpeningDocumentsInPlace + + UIFileSharingEnabled + + UILaunchScreen + + + diff --git a/Sources/App/TagMasterApp.swift b/Sources/App/TagMasterApp.swift new file mode 100644 index 0000000..fd6105e --- /dev/null +++ b/Sources/App/TagMasterApp.swift @@ -0,0 +1,10 @@ +import SwiftUI + +@main +struct TagMasterApp: App { + var body: some Scene { + WindowGroup { + MainImportView() + } + } +} diff --git a/Sources/Models/Track.swift b/Sources/Models/Track.swift new file mode 100644 index 0000000..788e844 --- /dev/null +++ b/Sources/Models/Track.swift @@ -0,0 +1,25 @@ +import Foundation +import SwiftUI + +struct Track: Identifiable, Hashable { + let id = UUID() + var originalURL: URL? + var songName: String = "" + var trackNumber: String = "" + var discNumber: String = "" +} + +struct BatchMetadata { + var artist: String = "" + var album: String = "" + var albumArtist: String = "" + var composer: String = "" + var grouping: String = "" + var genre: String = "Speech" + var year: String = "" + var compilation: Bool = false + var rating: Int = 0 + var bpm: String = "" + var comments: String = "" + var coverArt: UIImage? = nil +} diff --git a/Sources/ViewModels/EditorViewModel.swift b/Sources/ViewModels/EditorViewModel.swift new file mode 100644 index 0000000..97b6ff2 --- /dev/null +++ b/Sources/ViewModels/EditorViewModel.swift @@ -0,0 +1,58 @@ +import SwiftUI +import UniformTypeIdentifiers + +@MainActor +class EditorViewModel: ObservableObject { + @Published var batchData = BatchMetadata() + @Published var tracks: [Track] = [] + @Published var isProcessing = false + @Published var shareZipURL: URL? + + // Simulating the import process + func importFiles() { + // In reality, you'd use a UIDocumentPickerViewController or ZIPFoundation to extract + tracks = [ + Track(songName: "Preface", trackNumber: "1", discNumber: "1"), + Track(songName: "Chapter 1", trackNumber: "2", discNumber: "1") + ] + } + + func exportAndZip() async { + isProcessing = true + + // 1. Create staging directory + let fm = FileManager.default + let tempDir = fm.temporaryDirectory.appendingPathComponent(UUID().uuidString) + try? fm.createDirectory(at: tempDir, withIntermediateDirectories: true) + + // 2. Save Cover Art + if let cover = batchData.coverArt, let data = cover.jpegData(compressionQuality: 0.8) { + let coverURL = tempDir.appendingPathComponent("cover.jpg") + try? data.write(to: coverURL) + } + + // 3. Process, Rename, and Move Files + // Format: [Disc]-[Track]-[Songname].[ext] + for track in tracks { + let safeSong = track.songName.replacingOccurrences(of: "/", with: "-") + let dNum = track.discNumber.isEmpty ? "01" : String(format: "%02d", Int(track.discNumber) ?? 1) + let tNum = track.trackNumber.isEmpty ? "01" : String(format: "%02d", Int(track.trackNumber) ?? 1) + + let filename = "\(dNum)-\(tNum)-\(safeSong).flac" // Defaulting to flac for demo + let destinationURL = tempDir.appendingPathComponent(filename) + + // Here you would write the ID3 metadata to the file using AVAssetExportSession or ID3TagEditor + // and copy it to the destinationURL. + try? "Simulated Audio Data".write(to: destinationURL, atomically: true, encoding: .utf8) + } + + // 4. Zip the folder + let zipURL = fm.temporaryDirectory.appendingPathComponent("\(batchData.album.isEmpty ? "Export" : batchData.album).zip") + // NOTE: Use ZIPFoundation here to zip `tempDir` to `zipURL` + // try? fm.zipItem(at: tempDir, to: zipURL) + + // 5. Present Share Sheet + self.shareZipURL = zipURL + self.isProcessing = false + } +} diff --git a/Sources/Views/EditorView.swift b/Sources/Views/EditorView.swift new file mode 100644 index 0000000..5259606 --- /dev/null +++ b/Sources/Views/EditorView.swift @@ -0,0 +1,101 @@ +import SwiftUI + +struct EditorView: View { + @ObservedObject var viewModel: EditorViewModel + @State private var showingImagePicker = false + + var body: some View { + Form { + Section(header: Text("Album Artwork")) { + HStack { + Spacer() + Button(action: { showingImagePicker = true }) { + if let img = viewModel.batchData.coverArt { + Image(uiImage: img) + .resizable() + .scaledToFit() + .frame(width: 150, height: 150) + .cornerRadius(8) + } else { + ZStack { + RoundedRectangle(cornerRadius: 8) + .fill(Color(uiColor: .systemGray5)) + .frame(width: 150, height: 150) + Image(systemName: "photo") + .font(.largeTitle) + .foregroundColor(.gray) + } + } + } + Spacer() + } + } + + Section(header: Text("Batch Metadata (Applies to all)")) { + TextField("Artist", text: $viewModel.batchData.artist) + TextField("Album", text: $viewModel.batchData.album) + TextField("Album Artist", text: $viewModel.batchData.albumArtist) + TextField("Composer", text: $viewModel.batchData.composer) + TextField("Grouping", text: $viewModel.batchData.grouping) + TextField("Genre", text: $viewModel.batchData.genre) + TextField("Year", text: $viewModel.batchData.year) + .keyboardType(.numberPad) + Toggle("Compilation (Various Artists)", isOn: $viewModel.batchData.compilation) + TextField("BPM", text: $viewModel.batchData.bpm) + .keyboardType(.numberPad) + TextField("Comments", text: $viewModel.batchData.comments) + } + + Section(header: Text("Individual Track Data")) { + ForEach($viewModel.tracks) { $track in + VStack(alignment: .leading) { + TextField("Song Name", text: $track.songName) + .font(.headline) + HStack { + TextField("Disc", text: $track.discNumber) + .keyboardType(.numberPad) + .frame(width: 50) + Text("-") + TextField("Track", text: $track.trackNumber) + .keyboardType(.numberPad) + .frame(width: 50) + } + } + .padding(.vertical, 4) + } + } + } + .navigationTitle("Edit Tags") + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .navigationBarTrailing) { + Button("Export ZIP") { + Task { + await viewModel.exportAndZip() + } + } + .disabled(viewModel.isProcessing) + } + } + .sheet(item: Binding( + get: { viewModel.shareZipURL.map { ShareURL(url: $0) } }, + set: { if $0 == nil { viewModel.shareZipURL = nil } } + )) { shareItem in + ShareSheet(activityItems: [shareItem.url]) + } + } +} + +// Helpers for ShareSheet mapping +struct ShareURL: Identifiable { + let id = UUID() + let url: URL +} + +struct ShareSheet: UIViewControllerRepresentable { + var activityItems: [Any] + func makeUIViewController(context: Context) -> UIActivityViewController { + UIActivityViewController(activityItems: activityItems, applicationActivities: nil) + } + func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {} +} diff --git a/Sources/Views/MainImportView.swift b/Sources/Views/MainImportView.swift new file mode 100644 index 0000000..c189593 --- /dev/null +++ b/Sources/Views/MainImportView.swift @@ -0,0 +1,33 @@ +import SwiftUI + +struct MainImportView: View { + @StateObject private var viewModel = EditorViewModel() + @State private var showEditor = false + + var body: some View { + NavigationStack { + VStack { + Button(action: { + viewModel.importFiles() + showEditor = true + }) { + VStack(spacing: 20) { + Image(systemName: "plus.circle.fill") + .font(.system(size: 80)) + Text("Import Zip or Audio Files") + .font(.title2.bold()) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(Color(uiColor: .secondarySystemBackground)) + .cornerRadius(20) + .padding() + } + .buttonStyle(PlainButtonStyle()) + } + .navigationTitle("TagMaster") + .navigationDestination(isPresented: $showEditor) { + EditorView(viewModel: viewModel) + } + } + } +} diff --git a/TagMaster.xcodeproj/project.pbxproj b/TagMaster.xcodeproj/project.pbxproj new file mode 100644 index 0000000..8e493a3 --- /dev/null +++ b/TagMaster.xcodeproj/project.pbxproj @@ -0,0 +1,364 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXBuildFile section */ + 24699FE22C1CA273526A7F00 /* EditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A4967029EB9623BF8EBFB96 /* EditorView.swift */; }; + 532F02E8FD3A3DDB7638F3AC /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = 81BAF38189EA665DB7F0ADAB /* ZIPFoundation */; }; + 64F9CE5F7F9E849ABC2F28F4 /* EditorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B7584CD1B4714CC0B3623E9 /* EditorViewModel.swift */; }; + A671247AA2BF3958E48DF509 /* MainImportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF4E016D299B195D23A439A6 /* MainImportView.swift */; }; + D48515953E1ECE08E1B7A2C5 /* Track.swift in Sources */ = {isa = PBXBuildFile; fileRef = 705426259912E57439983143 /* Track.swift */; }; + E35AC07D26043CDE632C77DF /* TagMasterApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33185AC1D011C5790AAEABB0 /* TagMasterApp.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 07ADE7E4792A98BE9F5320D7 /* TagMaster.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = TagMaster.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 1B7584CD1B4714CC0B3623E9 /* EditorViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorViewModel.swift; sourceTree = ""; }; + 33185AC1D011C5790AAEABB0 /* TagMasterApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagMasterApp.swift; sourceTree = ""; }; + 5A4967029EB9623BF8EBFB96 /* EditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditorView.swift; sourceTree = ""; }; + 705426259912E57439983143 /* Track.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Track.swift; sourceTree = ""; }; + AF4E016D299B195D23A439A6 /* MainImportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainImportView.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + B3ED9C41320B3AD23AF5D522 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 532F02E8FD3A3DDB7638F3AC /* ZIPFoundation in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0786FC0C08BCC999BB96B678 /* Sources */ = { + isa = PBXGroup; + children = ( + F33C92270C13063431683668 /* App */, + 0F968F602B9E056E487855D5 /* Models */, + CD8A4F908E22769095D6D1C1 /* ViewModels */, + 3F8F1037C6A6B2A66BA14992 /* Views */, + ); + path = Sources; + sourceTree = ""; + }; + 0A7DD76DBB4B7EAA5B1B4AC9 = { + isa = PBXGroup; + children = ( + 0786FC0C08BCC999BB96B678 /* Sources */, + 25A98F3E183C554DE4B67719 /* Products */, + ); + sourceTree = ""; + }; + 0F968F602B9E056E487855D5 /* Models */ = { + isa = PBXGroup; + children = ( + 705426259912E57439983143 /* Track.swift */, + ); + path = Models; + sourceTree = ""; + }; + 25A98F3E183C554DE4B67719 /* Products */ = { + isa = PBXGroup; + children = ( + 07ADE7E4792A98BE9F5320D7 /* TagMaster.app */, + ); + name = Products; + sourceTree = ""; + }; + 3F8F1037C6A6B2A66BA14992 /* Views */ = { + isa = PBXGroup; + children = ( + 5A4967029EB9623BF8EBFB96 /* EditorView.swift */, + AF4E016D299B195D23A439A6 /* MainImportView.swift */, + ); + path = Views; + sourceTree = ""; + }; + CD8A4F908E22769095D6D1C1 /* ViewModels */ = { + isa = PBXGroup; + children = ( + 1B7584CD1B4714CC0B3623E9 /* EditorViewModel.swift */, + ); + path = ViewModels; + sourceTree = ""; + }; + F33C92270C13063431683668 /* App */ = { + isa = PBXGroup; + children = ( + 33185AC1D011C5790AAEABB0 /* TagMasterApp.swift */, + ); + path = App; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 18ACF1B0C27495AAC68C7CAA /* TagMaster */ = { + isa = PBXNativeTarget; + buildConfigurationList = 00F5581FF005FF871219AA58 /* Build configuration list for PBXNativeTarget "TagMaster" */; + buildPhases = ( + 7661FCEF871A1C63D84D5E3B /* Sources */, + B3ED9C41320B3AD23AF5D522 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = TagMaster; + packageProductDependencies = ( + 81BAF38189EA665DB7F0ADAB /* ZIPFoundation */, + ); + productName = TagMaster; + productReference = 07ADE7E4792A98BE9F5320D7 /* TagMaster.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 9AAB891F0987F221E77E4124 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1430; + TargetAttributes = { + }; + }; + buildConfigurationList = C1F95098F10215ED6A4E23FC /* Build configuration list for PBXProject "TagMaster" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ); + mainGroup = 0A7DD76DBB4B7EAA5B1B4AC9; + minimizedProjectReferenceProxies = 1; + packageReferences = ( + 9880C46838452B5EDADB700D /* XCRemoteSwiftPackageReference "ZIPFoundation" */, + ); + preferredProjectObjectVersion = 77; + productRefGroup = 25A98F3E183C554DE4B67719 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 18ACF1B0C27495AAC68C7CAA /* TagMaster */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 7661FCEF871A1C63D84D5E3B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 24699FE22C1CA273526A7F00 /* EditorView.swift in Sources */, + 64F9CE5F7F9E849ABC2F28F4 /* EditorViewModel.swift in Sources */, + A671247AA2BF3958E48DF509 /* MainImportView.swift in Sources */, + E35AC07D26043CDE632C77DF /* TagMasterApp.swift in Sources */, + D48515953E1ECE08E1B7A2C5 /* Track.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 52C32149D75AB7B208D76A21 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DEBUG=1", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 78B34E92D87A643D256811CF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.tagmaster.TagMaster; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 79A8CED0E92065580A7A6599 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.tagmaster.TagMaster; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + E0AF33C424E9B8F35E9A248E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 00F5581FF005FF871219AA58 /* Build configuration list for PBXNativeTarget "TagMaster" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 79A8CED0E92065580A7A6599 /* Debug */, + 78B34E92D87A643D256811CF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + C1F95098F10215ED6A4E23FC /* Build configuration list for PBXProject "TagMaster" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 52C32149D75AB7B208D76A21 /* Debug */, + E0AF33C424E9B8F35E9A248E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 9880C46838452B5EDADB700D /* XCRemoteSwiftPackageReference "ZIPFoundation" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/weichsel/ZIPFoundation.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.9.19; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 81BAF38189EA665DB7F0ADAB /* ZIPFoundation */ = { + isa = XCSwiftPackageProductDependency; + package = 9880C46838452B5EDADB700D /* XCRemoteSwiftPackageReference "ZIPFoundation" */; + productName = ZIPFoundation; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 9AAB891F0987F221E77E4124 /* Project object */; +} diff --git a/TagMaster.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/TagMaster.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/TagMaster.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/TagMaster.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/TagMaster.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..e314e45 --- /dev/null +++ b/TagMaster.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,15 @@ +{ + "originHash" : "b26c070fd1f0b029780331f3cefa3909a6d58ea6b3ae242bffe49d6011fe06fe", + "pins" : [ + { + "identity" : "zipfoundation", + "kind" : "remoteSourceControl", + "location" : "https://github.com/weichsel/ZIPFoundation.git", + "state" : { + "revision" : "22787ffb59de99e5dc1fbfe80b19c97a904ad48d", + "version" : "0.9.20" + } + } + ], + "version" : 3 +} diff --git a/TagMaster.xcodeproj/project.xcworkspace/xcuserdata/dallasgroot.xcuserdatad/UserInterfaceState.xcuserstate b/TagMaster.xcodeproj/project.xcworkspace/xcuserdata/dallasgroot.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..1745ff3adb312c44e9d5bd59350f01db4f74cbdc GIT binary patch literal 13640 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 literal 0 HcmV?d00001 diff --git a/TagMaster.xcodeproj/xcuserdata/dallasgroot.xcuserdatad/xcschemes/xcschememanagement.plist b/TagMaster.xcodeproj/xcuserdata/dallasgroot.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..594910e --- /dev/null +++ b/TagMaster.xcodeproj/xcuserdata/dallasgroot.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + TagMaster.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/generate.sh b/generate.sh old mode 100644 new mode 100755 diff --git a/project.yml b/project.yml new file mode 100644 index 0000000..b6f3645 --- /dev/null +++ b/project.yml @@ -0,0 +1,22 @@ +name: TagMaster +options: + bundleIdPrefix: com.tagmaster + deploymentTarget: + iOS: "17.0" +targets: + TagMaster: + type: application + platform: iOS + sources: [Sources] + info: + path: Info.plist + properties: + UILaunchScreen: {} + UIFileSharingEnabled: true + LSSupportsOpeningDocumentsInPlace: true + dependencies: + - package: ZIPFoundation +packages: + ZIPFoundation: + url: https://github.com/weichsel/ZIPFoundation.git + from: 0.9.19