From a3e60ce9954ca4e2df6b7135271312989679b79a Mon Sep 17 00:00:00 2001 From: Atridad Lahiji Date: Sat, 13 Sep 2025 00:42:15 -0600 Subject: [PATCH] Import/export fixes, icon, and graphing --- .../UserInterfaceState.xcuserstate | Bin 35145 -> 39751 bytes .../AppIcon.appiconset/Contents.json | 41 +- .../AppIcon.appiconset/app_icon_1024.png | Bin 0 -> 22356 bytes .../MountainsIcon.imageset/Contents.json | 23 + .../mountains_icon_256.png | Bin 0 -> 5418 bytes ios/OpenClimb/Utils/ZipUtils.swift | 3 - .../Views/AddEdit/AddAttemptView.swift | 12 +- .../Views/AddEdit/AddEditGymView.swift | 2 +- .../Views/AddEdit/AddEditProblemView.swift | 17 +- ios/OpenClimb/Views/AnalyticsView.swift | 413 ++++++++++++------ ios/OpenClimb/Views/SettingsView.swift | 107 ++--- 11 files changed, 388 insertions(+), 230 deletions(-) create mode 100644 ios/OpenClimb/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png create mode 100644 ios/OpenClimb/Assets.xcassets/MountainsIcon.imageset/Contents.json create mode 100644 ios/OpenClimb/Assets.xcassets/MountainsIcon.imageset/mountains_icon_256.png diff --git a/ios/OpenClimb.xcodeproj/project.xcworkspace/xcuserdata/atridad.xcuserdatad/UserInterfaceState.xcuserstate b/ios/OpenClimb.xcodeproj/project.xcworkspace/xcuserdata/atridad.xcuserdatad/UserInterfaceState.xcuserstate index 9e7c81bcd8a9a00b981b953aafb9241e765a5976..d9d3b262109998ac0672b5d331ee7247e77f8ace 100644 GIT binary patch literal 39751 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 ZJ3LuV+VJ;fDR>`X$JX6j(sXT4{SOp&kyHQx literal 0 HcmV?d00001 diff --git a/ios/OpenClimb/Assets.xcassets/MountainsIcon.imageset/Contents.json b/ios/OpenClimb/Assets.xcassets/MountainsIcon.imageset/Contents.json new file mode 100644 index 0000000..75a2160 --- /dev/null +++ b/ios/OpenClimb/Assets.xcassets/MountainsIcon.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images": [ + { + "filename": "mountains_icon_256.png", + "idiom": "universal", + "scale": "1x" + }, + { + "filename": "mountains_icon_256.png", + "idiom": "universal", + "scale": "2x" + }, + { + "filename": "mountains_icon_256.png", + "idiom": "universal", + "scale": "3x" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/ios/OpenClimb/Assets.xcassets/MountainsIcon.imageset/mountains_icon_256.png b/ios/OpenClimb/Assets.xcassets/MountainsIcon.imageset/mountains_icon_256.png new file mode 100644 index 0000000000000000000000000000000000000000..209dd1c98b166cd568b4acc79b494ee1f1a2c0ae GIT binary patch literal 5418 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 some View { - if let gym = selectedGym { + if selectedGym != nil { Section("Climb Type") { ForEach(availableClimbTypes, id: \.self) { climbType in HStack { @@ -227,8 +227,13 @@ struct AddEditProblemView: View { .font(.headline) if selectedDifficultySystem == .custom || availableGrades.isEmpty { - TextField("Enter custom grade", text: $difficultyGrade) + TextField("Enter custom grade (numbers only)", text: $difficultyGrade) .textFieldStyle(.roundedBorder) + .keyboardType(.numberPad) + .onChange(of: difficultyGrade) { + // Filter out non-numeric characters + difficultyGrade = difficultyGrade.filter { $0.isNumber } + } } else { Menu { if !difficultyGrade.isEmpty { diff --git a/ios/OpenClimb/Views/AnalyticsView.swift b/ios/OpenClimb/Views/AnalyticsView.swift index 7a767b9..59e031e 100644 --- a/ios/OpenClimb/Views/AnalyticsView.swift +++ b/ios/OpenClimb/Views/AnalyticsView.swift @@ -20,9 +20,11 @@ struct AnalyticsView: View { ProgressChartSection() - FavoriteGymSection() + HStack(spacing: 16) { + FavoriteGymSection() - RecentActivitySection() + RecentActivitySection() + } } .padding() } @@ -34,9 +36,9 @@ struct AnalyticsView: View { struct HeaderSection: View { var body: some View { HStack { - Image(systemName: "mountain.2.fill") - .font(.title) - .foregroundColor(.blue) + Image("MountainsIcon") + .resizable() + .frame(width: 32, height: 32) Text("Analytics") .font(.title) @@ -133,7 +135,13 @@ struct ProgressChartSection: View { } private var usedSystems: [DifficultySystem] { - Set(progressData.map { $0.difficultySystem }).sorted { $0.rawValue < $1.rawValue } + let uniqueSystems = Set(progressData.map { $0.difficultySystem }) + return uniqueSystems.sorted { + let order: [DifficultySystem] = [.vScale, .font, .yds, .custom] + let firstIndex = order.firstIndex(of: $0) ?? order.count + let secondIndex = order.firstIndex(of: $1) ?? order.count + return firstIndex < secondIndex + } } var body: some View { @@ -148,20 +156,35 @@ struct ProgressChartSection: View { if usedSystems.count > 1 { Menu { ForEach(usedSystems, id: \.self) { system in - Button(system.displayName) { + Button(action: { selectedSystem = system + }) { + HStack { + Text(system.displayName) + if selectedSystem == system { + Spacer() + Image(systemName: "checkmark") + .foregroundColor(.blue) + } + } } } } label: { - Text(selectedSystem.displayName) - .font(.caption) - .padding(.horizontal, 8) - .padding(.vertical, 4) - .background( - RoundedRectangle(cornerRadius: 8) - .fill(.blue.opacity(0.1)) - ) - .foregroundColor(.blue) + HStack(spacing: 4) { + Text(selectedSystem.displayName) + .font(.subheadline) + .fontWeight(.medium) + Image(systemName: "chevron.down") + .font(.caption) + } + .padding(.horizontal, 12) + .padding(.vertical, 6) + .background( + RoundedRectangle(cornerRadius: 8) + .fill(.blue.opacity(0.1)) + .stroke(.blue.opacity(0.3), lineWidth: 1) + ) + .foregroundColor(.blue) } } } @@ -169,37 +192,11 @@ struct ProgressChartSection: View { let filteredData = progressData.filter { $0.difficultySystem == selectedSystem } if !filteredData.isEmpty { - VStack { - // Simple text-based chart placeholder - VStack(alignment: .leading, spacing: 8) { - ForEach(filteredData.indices.prefix(5), id: \.self) { index in - let point = filteredData[index] - HStack { - Text("Session \(index + 1)") - .font(.caption) - .frame(width: 80, alignment: .leading) - - Rectangle() - .fill(.blue) - .frame(width: CGFloat(point.maxGradeNumeric * 5), height: 20) - - Text(point.maxGrade) - .font(.caption) - .foregroundColor(.blue) - } - } - - if filteredData.count > 5 { - Text("... and \(filteredData.count - 5) more sessions") - .font(.caption) - .foregroundColor(.secondary) - } - } - } - .frame(height: 200) + LineChartView(data: filteredData, selectedSystem: selectedSystem) + .frame(height: 200) Text( - "X: session number, Y: max \(selectedSystem.displayName.lowercased()) grade achieved" + "Progress: max \(selectedSystem.displayName.lowercased()) grade achieved per session" ) .font(.caption) .foregroundColor(.secondary) @@ -239,22 +236,28 @@ struct ProgressChartSection: View { let attemptedProblemIds = sessionAttempts.map { $0.problemId } let attemptedProblems = problems.filter { attemptedProblemIds.contains($0.id) } - guard - let highestGradeProblem = attemptedProblems.max(by: { - $0.difficulty.numericValue < $1.difficulty.numericValue - }) - else { - return nil - } + // Group problems by difficulty system + let problemsBySystem = Dictionary(grouping: attemptedProblems) { $0.difficulty.system } - return ProgressDataPoint( - date: session.date, - maxGrade: highestGradeProblem.difficulty.grade, - maxGradeNumeric: highestGradeProblem.difficulty.numericValue, - climbType: highestGradeProblem.climbType, - difficultySystem: highestGradeProblem.difficulty.system - ) - } + // Create data points for each system used in this session + return problemsBySystem.compactMap { (system, systemProblems) -> ProgressDataPoint? in + guard + let highestGradeProblem = systemProblems.max(by: { + $0.difficulty.numericValue < $1.difficulty.numericValue + }) + else { + return nil + } + + return ProgressDataPoint( + date: session.date, + maxGrade: highestGradeProblem.difficulty.grade, + maxGradeNumeric: highestGradeProblem.difficulty.numericValue, + climbType: highestGradeProblem.climbType, + difficultySystem: system + ) + } + }.flatMap { $0 } } } @@ -275,27 +278,53 @@ struct FavoriteGymSection: View { } var body: some View { - VStack(alignment: .leading, spacing: 12) { - Text("Favorite Gym") - .font(.title2) - .fontWeight(.bold) + VStack(alignment: .leading, spacing: 16) { + HStack { + Image(systemName: "location.fill") + .font(.title2) + .foregroundColor(.purple) + + Text("Favorite Gym") + .font(.title2) + .fontWeight(.bold) + + Spacer() + } if let info = favoriteGymInfo { - VStack(alignment: .leading, spacing: 8) { + VStack(alignment: .leading, spacing: 12) { Text(info.gym.name) .font(.title3) .fontWeight(.semibold) + .foregroundColor(.primary) - Text("\(info.sessionCount) sessions") - .font(.subheadline) - .foregroundColor(.secondary) + HStack { + Image(systemName: "calendar") + .font(.subheadline) + .foregroundColor(.purple) + + Text("\(info.sessionCount) sessions") + .font(.subheadline) + .foregroundColor(.secondary) + } + + Spacer() } } else { - Text("No sessions yet") - .font(.subheadline) - .foregroundColor(.secondary) + VStack(alignment: .leading, spacing: 8) { + Text("No sessions yet") + .font(.subheadline) + .foregroundColor(.secondary) + + Text("Start climbing to see your favorite gym!") + .font(.caption) + .foregroundColor(.secondary) + + Spacer() + } } } + .frame(maxWidth: .infinity, minHeight: 120, alignment: .topLeading) .padding() .background( RoundedRectangle(cornerRadius: 16) @@ -311,21 +340,63 @@ struct RecentActivitySection: View { dataManager.sessions.count } + private var totalAttempts: Int { + dataManager.attempts.count + } + var body: some View { - VStack(alignment: .leading, spacing: 12) { - Text("Recent Activity") - .font(.title2) - .fontWeight(.bold) + VStack(alignment: .leading, spacing: 16) { + HStack { + Image(systemName: "clock.fill") + .font(.title2) + .foregroundColor(.blue) + + Text("Recent Activity") + .font(.title2) + .fontWeight(.bold) + + Spacer() + } if recentSessionsCount > 0 { - Text("You've had \(recentSessionsCount) sessions") - .font(.subheadline) + VStack(alignment: .leading, spacing: 12) { + HStack { + Image(systemName: "play.circle") + .font(.subheadline) + .foregroundColor(.blue) + + Text("\(recentSessionsCount) sessions") + .font(.subheadline) + .foregroundColor(.secondary) + } + + HStack { + Image(systemName: "hand.raised") + .font(.subheadline) + .foregroundColor(.green) + + Text("\(totalAttempts) attempts") + .font(.subheadline) + .foregroundColor(.secondary) + } + + Spacer() + } } else { - Text("No recent activity") - .font(.subheadline) - .foregroundColor(.secondary) + VStack(alignment: .leading, spacing: 8) { + Text("No recent activity") + .font(.subheadline) + .foregroundColor(.secondary) + + Text("Start your first session!") + .font(.caption) + .foregroundColor(.secondary) + + Spacer() + } } } + .frame(maxWidth: .infinity, minHeight: 120, alignment: .topLeading) .padding() .background( RoundedRectangle(cornerRadius: 16) @@ -334,6 +405,131 @@ struct RecentActivitySection: View { } } +struct LineChartView: View { + let data: [ProgressDataPoint] + let selectedSystem: DifficultySystem + + private var uniqueGrades: [String] { + if selectedSystem == .custom { + return Array(Set(data.map { $0.maxGrade })).sorted { grade1, grade2 in + return (Int(grade1) ?? 0) > (Int(grade2) ?? 0) + } + } else { + return Array(Set(data.map { $0.maxGrade })).sorted { grade1, grade2 in + let grade1Data = data.first(where: { $0.maxGrade == grade1 }) + let grade2Data = data.first(where: { $0.maxGrade == grade2 }) + return (grade1Data?.maxGradeNumeric ?? 0) + > (grade2Data?.maxGradeNumeric ?? 0) + } + } + } + + private var minGrade: Int { + data.map { $0.maxGradeNumeric }.min() ?? 0 + } + + private var maxGrade: Int { + data.map { $0.maxGradeNumeric }.max() ?? 1 + } + + private var gradeRange: Int { + max(maxGrade - minGrade, 1) + } + + var body: some View { + GeometryReader { geometry in + let chartWidth = geometry.size.width - 40 + let chartHeight = geometry.size.height - 40 + + if data.isEmpty { + Rectangle() + .fill(.clear) + .overlay( + Text("No data") + .foregroundColor(.secondary) + ) + } else { + + HStack { + // Y-axis labels + VStack { + ForEach(0.. 1 { + Path { path in + for (index, point) in data.enumerated() { + let x = CGFloat(index) * chartWidth / CGFloat(data.count - 1) + let normalizedY = + CGFloat(point.maxGradeNumeric - minGrade) + / CGFloat(gradeRange) + let y = chartHeight - (normalizedY * chartHeight) + + if index == 0 { + path.move(to: CGPoint(x: x, y: y)) + } else { + path.addLine(to: CGPoint(x: x, y: y)) + } + } + } + .stroke(.blue, lineWidth: 2) + } + + // Data points + ForEach(data.indices, id: \.self) { index in + let point = data[index] + let x = + data.count == 1 + ? chartWidth / 2 + : CGFloat(index) * chartWidth / CGFloat(data.count - 1) + let normalizedY = + CGFloat(point.maxGradeNumeric - minGrade) / CGFloat(gradeRange) + let y = chartHeight - (normalizedY * chartHeight) + + Circle() + .fill(.blue) + .frame(width: 8, height: 8) + .position(x: x, y: y) + .overlay( + Circle() + .stroke(.white, lineWidth: 2) + .frame(width: 8, height: 8) + .position(x: x, y: y) + ) + } + } + .frame(width: chartWidth, height: chartHeight) + } + } + } + .padding() + } +} + struct ProgressDataPoint { let date: Date let maxGrade: String @@ -344,63 +540,6 @@ struct ProgressDataPoint { // MARK: - Helper Functions -func gradeToNumeric(_ system: DifficultySystem, _ grade: String) -> Int { - switch system { - case .vScale: - if grade == "VB" { return 0 } - return Int(grade.replacingOccurrences(of: "V", with: "")) ?? 0 - case .font: - let fontMapping: [String: Int] = [ - "3": 3, "4A": 4, "4B": 5, "4C": 6, "5A": 7, "5B": 8, "5C": 9, - "6A": 10, "6A+": 11, "6B": 12, "6B+": 13, "6C": 14, "6C+": 15, - "7A": 16, "7A+": 17, "7B": 18, "7B+": 19, "7C": 20, "7C+": 21, - "8A": 22, "8A+": 23, "8B": 24, "8B+": 25, "8C": 26, "8C+": 27, - ] - return fontMapping[grade] ?? 0 - case .yds: - let ydsMapping: [String: Int] = [ - "5.0": 50, "5.1": 51, "5.2": 52, "5.3": 53, "5.4": 54, "5.5": 55, - "5.6": 56, "5.7": 57, "5.8": 58, "5.9": 59, "5.10a": 60, "5.10b": 61, - "5.10c": 62, "5.10d": 63, "5.11a": 64, "5.11b": 65, "5.11c": 66, - "5.11d": 67, "5.12a": 68, "5.12b": 69, "5.12c": 70, "5.12d": 71, - "5.13a": 72, "5.13b": 73, "5.13c": 74, "5.13d": 75, "5.14a": 76, - "5.14b": 77, "5.14c": 78, "5.14d": 79, "5.15a": 80, "5.15b": 81, - "5.15c": 82, "5.15d": 83, - ] - return ydsMapping[grade] ?? 0 - case .custom: - return Int(grade) ?? 0 - } -} - -func numericToGrade(_ system: DifficultySystem, _ numeric: Int) -> String { - switch system { - case .vScale: - return numeric == 0 ? "VB" : "V\(numeric)" - case .font: - let fontMapping: [Int: String] = [ - 3: "3", 4: "4A", 5: "4B", 6: "4C", 7: "5A", 8: "5B", 9: "5C", - 10: "6A", 11: "6A+", 12: "6B", 13: "6B+", 14: "6C", 15: "6C+", - 16: "7A", 17: "7A+", 18: "7B", 19: "7B+", 20: "7C", 21: "7C+", - 22: "8A", 23: "8A+", 24: "8B", 25: "8B+", 26: "8C", 27: "8C+", - ] - return fontMapping[numeric] ?? "\(numeric)" - case .yds: - let ydsMapping: [Int: String] = [ - 50: "5.0", 51: "5.1", 52: "5.2", 53: "5.3", 54: "5.4", 55: "5.5", - 56: "5.6", 57: "5.7", 58: "5.8", 59: "5.9", 60: "5.10a", 61: "5.10b", - 62: "5.10c", 63: "5.10d", 64: "5.11a", 65: "5.11b", 66: "5.11c", - 67: "5.11d", 68: "5.12a", 69: "5.12b", 70: "5.12c", 71: "5.12d", - 72: "5.13a", 73: "5.13b", 74: "5.13c", 75: "5.13d", 76: "5.14a", - 77: "5.14b", 78: "5.14c", 79: "5.14d", 80: "5.15a", 81: "5.15b", - 82: "5.15c", 83: "5.15d", - ] - return ydsMapping[numeric] ?? "\(numeric)" - case .custom: - return "\(numeric)" - } -} - #Preview { AnalyticsView() .environmentObject(ClimbingDataManager.preview) diff --git a/ios/OpenClimb/Views/SettingsView.swift b/ios/OpenClimb/Views/SettingsView.swift index 91866fe..018e9e3 100644 --- a/ios/OpenClimb/Views/SettingsView.swift +++ b/ios/OpenClimb/Views/SettingsView.swift @@ -8,31 +8,53 @@ import SwiftUI import UniformTypeIdentifiers +enum SheetType { + case export(Data) + case importData +} + struct SettingsView: View { @EnvironmentObject var dataManager: ClimbingDataManager - @State private var showingResetAlert = false - @State private var showingExportSheet = false - @State private var showingImportSheet = false - @State private var exportData: Data? + @State private var activeSheet: SheetType? var body: some View { - NavigationView { - List { - DataManagementSection() + List { + DataManagementSection( + activeSheet: $activeSheet + ) - AppInfoSection() + AppInfoSection() + } + .navigationTitle("Settings") + .sheet( + item: Binding( + get: { activeSheet }, + set: { activeSheet = $0 } + ) + ) { sheetType in + switch sheetType { + case .export(let data): + ExportDataView(data: data) + case .importData: + ImportDataView() } - .navigationTitle("Settings") + } + } +} + +extension SheetType: Identifiable { + var id: String { + switch self { + case .export: return "export" + case .importData: return "import" } } } struct DataManagementSection: View { @EnvironmentObject var dataManager: ClimbingDataManager + @Binding var activeSheet: SheetType? @State private var showingResetAlert = false - @State private var showingExportSheet = false - @State private var showingImportSheet = false - @State private var exportData: Data? @State private var isExporting = false var body: some View { @@ -60,7 +82,7 @@ struct DataManagementSection: View { // Import Data Button(action: { - showingImportSheet = true + activeSheet = .importData }) { HStack { Image(systemName: "square.and.arrow.down") @@ -94,38 +116,15 @@ struct DataManagementSection: View { "Are you sure you want to reset all data? This will permanently delete:\n\n• All gyms and their information\n• All problems and their images\n• All climbing sessions\n• All attempts and progress data\n\nThis action cannot be undone. Consider exporting your data first." ) } - .sheet(isPresented: $showingExportSheet) { - if let data = exportData { - ExportDataView(data: data) - } else { - Text("No export data available") - } - } - .sheet(isPresented: $showingImportSheet) { - ImportDataView() - } } private func exportDataAsync() { isExporting = true - Task { - let data = await withCheckedContinuation { continuation in - DispatchQueue.global(qos: .userInitiated).async { - let result = dataManager.exportData() - continuation.resume(returning: result) - } - } - - await MainActor.run { - isExporting = false - if let data = data { - exportData = data - showingExportSheet = true - } else { - // Error message should already be set by dataManager - exportData = nil - } + let data = await MainActor.run { dataManager.exportData() } + isExporting = false + if let data = data { + activeSheet = .export(data) } } } @@ -143,8 +142,9 @@ struct AppInfoSection: View { var body: some View { Section("App Information") { HStack { - Image(systemName: "mountain.2.fill") - .foregroundColor(.blue) + Image("MountainsIcon") + .resizable() + .frame(width: 24, height: 24) VStack(alignment: .leading) { Text("OpenClimb") .font(.headline) @@ -163,15 +163,6 @@ struct AppInfoSection: View { Text("\(appVersion) (\(buildNumber))") .foregroundColor(.secondary) } - - HStack { - Image(systemName: "person.fill") - .foregroundColor(.blue) - Text("Developer") - Spacer() - Text("OpenClimb Team") - .foregroundColor(.secondary) - } } } } @@ -203,7 +194,7 @@ struct ExportDataView: View { item: fileURL, preview: SharePreview( "OpenClimb Data Export", - image: Image(systemName: "mountain.2.fill")) + image: Image("MountainsIcon")) ) { Label("Share Data", systemImage: "square.and.arrow.up") .font(.headline) @@ -324,13 +315,6 @@ struct ImportDataView: View { Text("Import climbing data from a previously exported ZIP file.") .multilineTextAlignment(.center) - Text( - "Fully compatible with Android exports - identical ZIP format with images." - ) - .font(.subheadline) - .foregroundColor(.blue) - .multilineTextAlignment(.center) - Text("⚠️ Warning: This will replace all current data!") .font(.subheadline) .foregroundColor(.red) @@ -423,7 +407,10 @@ struct ImportDataView: View { await MainActor.run { isImporting = false - dismiss() + // Auto-close after successful import + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + dismiss() + } } } catch { await MainActor.run {