From 6e490d15986887babf70aabacb94bd6fef993be3 Mon Sep 17 00:00:00 2001 From: Atridad Lahiji Date: Sun, 28 Sep 2025 23:12:46 -0600 Subject: [PATCH 1/4] Sync Server DONE! --- ...otlin-compiler-12230421336915548227.salive | 0 android/app/build.gradle.kts | 2 + android/app/build.gradle.kts.backup | 98 ++ android/app/build_new.gradle.kts | 98 ++ android/app/src/main/AndroidManifest.xml | 3 + .../openclimb/data/format/BackupFormat.kt | 9 +- .../data/migration/ImageMigrationService.kt | 205 ++++ .../atridad/openclimb/data/model/Attempt.kt | 96 +- .../openclimb/data/model/ClimbSession.kt | 101 +- .../openclimb/data/model/DifficultySystem.kt | 244 +++-- .../com/atridad/openclimb/data/model/Gym.kt | 53 +- .../atridad/openclimb/data/model/Problem.kt | 4 +- .../data/repository/ClimbRepository.kt | 137 ++- .../openclimb/data/state/DataStateManager.kt | 81 ++ .../openclimb/data/sync/SyncService.kt | 998 ++++++++++++++++++ .../com/atridad/openclimb/ui/OpenClimbApp.kt | 9 +- .../openclimb/ui/screens/SettingsScreen.kt | 961 ++++++++++++----- .../openclimb/ui/viewmodel/ClimbViewModel.kt | 25 +- .../ui/viewmodel/ClimbViewModelFactory.kt | 8 +- .../openclimb/utils/DateFormatUtils.kt | 68 ++ .../openclimb/utils/ImageNamingUtils.kt | 147 +++ .../com/atridad/openclimb/utils/ImageUtils.kt | 254 ++++- .../atridad/openclimb/SyncMergeLogicTest.kt | 451 ++++++++ android/gradle/libs.versions.toml | 4 + android/gradle/wrapper/gradle-wrapper.jar | 16 + .../UserInterfaceState.xcuserstate | Bin 117982 -> 124304 bytes .../xcshareddata/xcschemes/OpenClimb.xcscheme | 78 ++ ios/OpenClimb/ContentView.swift | 4 + ios/OpenClimb/Models/BackupFormat.swift | 5 - ios/OpenClimb/Services/SyncService.swift | 978 +++++++++++++++++ ios/OpenClimb/Utils/DataStateManager.swift | 85 ++ ios/OpenClimb/Utils/ImageNamingUtils.swift | 176 +++ .../ViewModels/ClimbingDataManager.swift | 29 + ios/OpenClimb/Views/SettingsView.swift | 358 +++++++ sync-server/.env.example | 14 + sync-server/.gitignore | 16 + sync-server/Dockerfile | 14 + sync-server/docker-compose.yml | 14 + sync-server/go.mod | 3 + sync-server/main.go | 358 +++++++ sync-server/run.sh | 31 + 41 files changed, 5684 insertions(+), 551 deletions(-) delete mode 100644 android/.kotlin/sessions/kotlin-compiler-12230421336915548227.salive create mode 100644 android/app/build.gradle.kts.backup create mode 100644 android/app/build_new.gradle.kts create mode 100644 android/app/src/main/java/com/atridad/openclimb/data/migration/ImageMigrationService.kt create mode 100644 android/app/src/main/java/com/atridad/openclimb/data/state/DataStateManager.kt create mode 100644 android/app/src/main/java/com/atridad/openclimb/data/sync/SyncService.kt create mode 100644 android/app/src/main/java/com/atridad/openclimb/utils/DateFormatUtils.kt create mode 100644 android/app/src/main/java/com/atridad/openclimb/utils/ImageNamingUtils.kt create mode 100644 android/app/src/test/java/com/atridad/openclimb/SyncMergeLogicTest.kt create mode 100644 android/gradle/wrapper/gradle-wrapper.jar create mode 100644 ios/OpenClimb/Services/SyncService.swift create mode 100644 ios/OpenClimb/Utils/DataStateManager.swift create mode 100644 ios/OpenClimb/Utils/ImageNamingUtils.swift create mode 100644 sync-server/.env.example create mode 100644 sync-server/.gitignore create mode 100644 sync-server/Dockerfile create mode 100644 sync-server/docker-compose.yml create mode 100644 sync-server/go.mod create mode 100644 sync-server/main.go create mode 100755 sync-server/run.sh diff --git a/android/.kotlin/sessions/kotlin-compiler-12230421336915548227.salive b/android/.kotlin/sessions/kotlin-compiler-12230421336915548227.salive deleted file mode 100644 index e69de29..0000000 diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index dc0c78f..2349fa4 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -92,4 +92,6 @@ dependencies { androidTestImplementation(libs.androidx.ui.test.junit4) debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.test.manifest) + debugImplementation(libs.androidx.ui.tooling) + debugImplementation(libs.androidx.ui.test.manifest) } diff --git a/android/app/build.gradle.kts.backup b/android/app/build.gradle.kts.backup new file mode 100644 index 0000000..3d33435 --- /dev/null +++ b/android/app/build.gradle.kts.backup @@ -0,0 +1,98 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.kotlin.compose) + alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.ksp) +} + +android { + namespace = "com.atridad.openclimb" + compileSdk = 36 + + defaultConfig { + applicationId = "com.atridad.openclimb" + minSdk = 31 + targetSdk = 36 + versionCode = 27 + versionName = "1.6.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + java { toolchain { languageVersion.set(JavaLanguageVersion.of(17)) } } + + buildFeatures { compose = true } +} + +kotlin { compilerOptions { jvmTarget.set(JvmTarget.JVM_17) } } + +dependencies { + // Core Android libraries + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.activity.compose) + + // Compose BOM and UI + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.ui) + implementation(libs.androidx.ui.graphics) + implementation(libs.androidx.ui.tooling.preview) + implementation(libs.androidx.material3) + implementation(libs.androidx.material.icons.extended) + + // Room Database + implementation(libs.androidx.room.runtime) + implementation(libs.androidx.room.ktx) + + ksp(libs.androidx.room.compiler) + + // Navigation + implementation(libs.androidx.navigation.compose) + + // ViewModel + implementation(libs.androidx.lifecycle.viewmodel.compose) + + // Serialization + implementation(libs.kotlinx.serialization.json) + + // Coroutines + implementation(libs.kotlinx.coroutines.android) + + // Image Loading + implementation(libs.coil.compose) + + // Testing + testImplementation(libs.junit) + testImplementation(libs.mockk) + testImplementation(libs.kotlinx.coroutines.test) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(libs.androidx.test.core) + androidTestImplementation(libs.androidx.test.ext) + androidTestImplementation(libs.androidx.test.runner) + androidTestImplementation(libs.androidx.test.rules) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.ui.test.junit4) + debugImplementation(libs.androidx.ui.tooling) + debugImplementation(libs.androidx.ui.test.manifest) +} + debugImplementation(libs.androidx.ui.tooling) + debugImplementation(libs.androidx.ui.test.manifest) +} diff --git a/android/app/build_new.gradle.kts b/android/app/build_new.gradle.kts new file mode 100644 index 0000000..5fec1e4 --- /dev/null +++ b/android/app/build_new.gradle.kts @@ -0,0 +1,98 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.kotlin.compose) + alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.ksp) +} + +android { + namespace = "com.atridad.openclimb" + compileSdk = 36 + + defaultConfig { + applicationId = "com.atridad.openclimb" + minSdk = 31 + targetSdk = 36 + versionCode = 27 + versionName = "1.6.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + java { toolchain { languageVersion.set(JavaLanguageVersion.of(17)) } } + + buildFeatures { compose = true } +} + +kotlin { compilerOptions { jvmTarget.set(JvmTarget.JVM_17) } } + +dependencies { + // Core Android libraries + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.activity.compose) + + // Compose BOM and UI + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.ui) + implementation(libs.androidx.ui.graphics) + implementation(libs.androidx.ui.tooling.preview) + implementation(libs.androidx.material3) + implementation(libs.androidx.material.icons.extended) + + // Room Database + implementation(libs.androidx.room.runtime) + implementation(libs.androidx.room.ktx) + + ksp(libs.androidx.room.compiler) + + // Navigation + implementation(libs.androidx.navigation.compose) + + // ViewModel + implementation(libs.androidx.lifecycle.viewmodel.compose) + + // Serialization + implementation(libs.kotlinx.serialization.json) + + // Coroutines + implementation(libs.kotlinx.coroutines.android) + + // Image Loading + implementation(libs.coil.compose) + + // HTTP Client + implementation(libs.okhttp) + + // Testing + testImplementation(libs.junit) + testImplementation(libs.mockk) + testImplementation(libs.kotlinx.coroutines.test) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(libs.androidx.test.core) + androidTestImplementation(libs.androidx.test.ext) + androidTestImplementation(libs.androidx.test.runner) + androidTestImplementation(libs.androidx.test.rules) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.ui.test.junit4) + debugImplementation(libs.androidx.ui.tooling) + debugImplementation(libs.androidx.ui.test.manifest) +} diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 5af5fc4..c187fce 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -8,6 +8,9 @@ android:maxSdkVersion="28" /> + + + diff --git a/android/app/src/main/java/com/atridad/openclimb/data/format/BackupFormat.kt b/android/app/src/main/java/com/atridad/openclimb/data/format/BackupFormat.kt index e1658a7..f8fae25 100644 --- a/android/app/src/main/java/com/atridad/openclimb/data/format/BackupFormat.kt +++ b/android/app/src/main/java/com/atridad/openclimb/data/format/BackupFormat.kt @@ -23,6 +23,7 @@ data class BackupGym( val location: String? = null, val supportedClimbTypes: List, val difficultySystems: List, + @kotlinx.serialization.SerialName("customDifficultyGrades") val customDifficultyGrades: List = emptyList(), val notes: String? = null, val createdAt: String, // ISO 8601 format @@ -91,7 +92,13 @@ data class BackupProblem( difficulty = problem.difficulty, tags = problem.tags, location = problem.location, - imagePaths = problem.imagePaths.ifEmpty { null }, + imagePaths = + if (problem.imagePaths.isEmpty()) null + else + problem.imagePaths.map { path -> + // Store just the filename to match iOS format + path.substringAfterLast('/') + }, isActive = problem.isActive, dateSet = problem.dateSet, notes = problem.notes, diff --git a/android/app/src/main/java/com/atridad/openclimb/data/migration/ImageMigrationService.kt b/android/app/src/main/java/com/atridad/openclimb/data/migration/ImageMigrationService.kt new file mode 100644 index 0000000..0ec8afc --- /dev/null +++ b/android/app/src/main/java/com/atridad/openclimb/data/migration/ImageMigrationService.kt @@ -0,0 +1,205 @@ +package com.atridad.openclimb.data.migration + +import android.content.Context +import android.util.Log +import com.atridad.openclimb.data.repository.ClimbRepository +import com.atridad.openclimb.utils.ImageNamingUtils +import com.atridad.openclimb.utils.ImageUtils +import kotlinx.coroutines.flow.first + +/** + * Service responsible for migrating images to use consistent naming convention across platforms. + * This ensures that iOS and Android use the same image filenames for sync compatibility. + */ +class ImageMigrationService(private val context: Context, private val repository: ClimbRepository) { + companion object { + private const val TAG = "ImageMigrationService" + private const val MIGRATION_PREF_KEY = "image_naming_migration_completed" + } + + /** + * Performs a complete migration of all images in the system to use consistent naming. This + * should be called once during app startup after the naming convention is implemented. + */ + suspend fun performFullMigration(): ImageMigrationResult { + Log.i(TAG, "Starting full image naming migration") + + val prefs = context.getSharedPreferences("openclimb_migration", Context.MODE_PRIVATE) + if (prefs.getBoolean(MIGRATION_PREF_KEY, false)) { + Log.i(TAG, "Image migration already completed, skipping") + return ImageMigrationResult.AlreadyCompleted + } + + try { + val allProblems = repository.getAllProblems().first() + val migrationResults = mutableMapOf() + var migratedCount = 0 + var errorCount = 0 + + Log.i(TAG, "Found ${allProblems.size} problems to check for image migration") + + for (problem in allProblems) { + if (problem.imagePaths.isNotEmpty()) { + Log.d( + TAG, + "Migrating images for problem '${problem.name}': ${problem.imagePaths}" + ) + + try { + val problemMigrations = + ImageUtils.migrateImageNaming( + context = context, + problemId = problem.id, + currentImagePaths = problem.imagePaths + ) + + if (problemMigrations.isNotEmpty()) { + migrationResults.putAll(problemMigrations) + migratedCount += problemMigrations.size + + // Update problem with new image paths + val newImagePaths = + problem.imagePaths.map { oldPath -> + problemMigrations[oldPath] ?: oldPath + } + + val updatedProblem = problem.copy(imagePaths = newImagePaths) + repository.insertProblem(updatedProblem) + + Log.d( + TAG, + "Updated problem '${problem.name}' with ${problemMigrations.size} migrated images" + ) + } + } catch (e: Exception) { + Log.e( + TAG, + "Failed to migrate images for problem '${problem.name}': ${e.message}", + e + ) + errorCount++ + } + } + } + + // Mark migration as completed + prefs.edit().putBoolean(MIGRATION_PREF_KEY, true).apply() + + Log.i( + TAG, + "Image migration completed: $migratedCount images migrated, $errorCount errors" + ) + + return ImageMigrationResult.Success( + totalMigrated = migratedCount, + errors = errorCount, + migrations = migrationResults + ) + } catch (e: Exception) { + Log.e(TAG, "Image migration failed: ${e.message}", e) + return ImageMigrationResult.Failed(e.message ?: "Unknown error") + } + } + + /** Validates that all images in the system follow the consistent naming convention. */ + suspend fun validateImageNaming(): ValidationResult { + try { + val allProblems = repository.getAllProblems().first() + val validImages = mutableListOf() + val invalidImages = mutableListOf() + val missingImages = mutableListOf() + + for (problem in allProblems) { + for (imagePath in problem.imagePaths) { + val filename = imagePath.substringAfterLast('/') + + // Check if file exists + val imageFile = ImageUtils.getImageFile(context, imagePath) + if (!imageFile.exists()) { + missingImages.add(imagePath) + continue + } + + // Check if filename follows our convention + if (ImageNamingUtils.isValidImageFilename(filename)) { + validImages.add(imagePath) + } else { + invalidImages.add(imagePath) + } + } + } + + return ValidationResult( + totalImages = validImages.size + invalidImages.size + missingImages.size, + validImages = validImages, + invalidImages = invalidImages, + missingImages = missingImages + ) + } catch (e: Exception) { + Log.e(TAG, "Image validation failed: ${e.message}", e) + return ValidationResult( + totalImages = 0, + validImages = emptyList(), + invalidImages = emptyList(), + missingImages = emptyList() + ) + } + } + + /** Migrates images for a specific problem during sync operations. */ + suspend fun migrateProblemImages( + problemId: String, + currentImagePaths: List + ): Map { + return try { + ImageUtils.migrateImageNaming(context, problemId, currentImagePaths) + } catch (e: Exception) { + Log.e(TAG, "Failed to migrate images for problem $problemId: ${e.message}", e) + emptyMap() + } + } + + /** + * Cleans up any orphaned image files that don't follow our naming convention and aren't + * referenced by any problems. + */ + suspend fun cleanupOrphanedImages() { + try { + val allProblems = repository.getAllProblems().first() + val referencedPaths = allProblems.flatMap { it.imagePaths }.toSet() + + ImageUtils.cleanupOrphanedImages(context, referencedPaths) + + Log.i(TAG, "Orphaned image cleanup completed") + } catch (e: Exception) { + Log.e(TAG, "Failed to cleanup orphaned images: ${e.message}", e) + } + } +} + +/** Result of an image migration operation */ +sealed class ImageMigrationResult { + object AlreadyCompleted : ImageMigrationResult() + + data class Success( + val totalMigrated: Int, + val errors: Int, + val migrations: Map + ) : ImageMigrationResult() + + data class Failed(val error: String) : ImageMigrationResult() +} + +/** Result of image naming validation */ +data class ValidationResult( + val totalImages: Int, + val validImages: List, + val invalidImages: List, + val missingImages: List +) { + val isAllValid: Boolean + get() = invalidImages.isEmpty() && missingImages.isEmpty() + + val validPercentage: Double + get() = if (totalImages == 0) 100.0 else (validImages.size.toDouble() / totalImages) * 100 +} diff --git a/android/app/src/main/java/com/atridad/openclimb/data/model/Attempt.kt b/android/app/src/main/java/com/atridad/openclimb/data/model/Attempt.kt index 1f93a1c..794cf7d 100644 --- a/android/app/src/main/java/com/atridad/openclimb/data/model/Attempt.kt +++ b/android/app/src/main/java/com/atridad/openclimb/data/model/Attempt.kt @@ -4,8 +4,8 @@ import androidx.room.Entity import androidx.room.ForeignKey import androidx.room.Index import androidx.room.PrimaryKey +import com.atridad.openclimb.utils.DateFormatUtils import kotlinx.serialization.Serializable -import java.time.LocalDateTime @Serializable enum class AttemptResult { @@ -16,63 +16,59 @@ enum class AttemptResult { } @Entity( - tableName = "attempts", - foreignKeys = [ - ForeignKey( - entity = ClimbSession::class, - parentColumns = ["id"], - childColumns = ["sessionId"], - onDelete = ForeignKey.CASCADE - ), - ForeignKey( - entity = Problem::class, - parentColumns = ["id"], - childColumns = ["problemId"], - onDelete = ForeignKey.CASCADE - ) - ], - indices = [ - Index(value = ["sessionId"]), - Index(value = ["problemId"]) - ] + tableName = "attempts", + foreignKeys = + [ + ForeignKey( + entity = ClimbSession::class, + parentColumns = ["id"], + childColumns = ["sessionId"], + onDelete = ForeignKey.CASCADE + ), + ForeignKey( + entity = Problem::class, + parentColumns = ["id"], + childColumns = ["problemId"], + onDelete = ForeignKey.CASCADE + )], + indices = [Index(value = ["sessionId"]), Index(value = ["problemId"])] ) @Serializable data class Attempt( - @PrimaryKey - val id: String, - val sessionId: String, - val problemId: String, - val result: AttemptResult, - val highestHold: String? = null, // Description of the highest hold reached - val notes: String? = null, - val duration: Long? = null, // Attempt duration in seconds - val restTime: Long? = null, // Rest time before this attempt in seconds - val timestamp: String, // When this attempt was made - val createdAt: String + @PrimaryKey val id: String, + val sessionId: String, + val problemId: String, + val result: AttemptResult, + val highestHold: String? = null, // Description of the highest hold reached + val notes: String? = null, + val duration: Long? = null, // Attempt duration in seconds + val restTime: Long? = null, // Rest time before this attempt in seconds + val timestamp: String, // When this attempt was made + val createdAt: String ) { companion object { fun create( - sessionId: String, - problemId: String, - result: AttemptResult, - highestHold: String? = null, - notes: String? = null, - duration: Long? = null, - restTime: Long? = null, - timestamp: String = LocalDateTime.now().toString() + sessionId: String, + problemId: String, + result: AttemptResult, + highestHold: String? = null, + notes: String? = null, + duration: Long? = null, + restTime: Long? = null, + timestamp: String = DateFormatUtils.nowISO8601() ): Attempt { - val now = LocalDateTime.now().toString() + val now = DateFormatUtils.nowISO8601() return Attempt( - id = java.util.UUID.randomUUID().toString(), - sessionId = sessionId, - problemId = problemId, - result = result, - highestHold = highestHold, - notes = notes, - duration = duration, - restTime = restTime, - timestamp = timestamp, - createdAt = now + id = java.util.UUID.randomUUID().toString(), + sessionId = sessionId, + problemId = problemId, + result = result, + highestHold = highestHold, + notes = notes, + duration = duration, + restTime = restTime, + timestamp = timestamp, + createdAt = now ) } } diff --git a/android/app/src/main/java/com/atridad/openclimb/data/model/ClimbSession.kt b/android/app/src/main/java/com/atridad/openclimb/data/model/ClimbSession.kt index f3b9c7d..0c4b5c9 100644 --- a/android/app/src/main/java/com/atridad/openclimb/data/model/ClimbSession.kt +++ b/android/app/src/main/java/com/atridad/openclimb/data/model/ClimbSession.kt @@ -4,8 +4,8 @@ import androidx.room.Entity import androidx.room.ForeignKey import androidx.room.Index import androidx.room.PrimaryKey +import com.atridad.openclimb.utils.DateFormatUtils import kotlinx.serialization.Serializable -import java.time.LocalDateTime @Serializable enum class SessionStatus { @@ -15,66 +15,65 @@ enum class SessionStatus { } @Entity( - tableName = "climb_sessions", - foreignKeys = [ - ForeignKey( - entity = Gym::class, - parentColumns = ["id"], - childColumns = ["gymId"], - onDelete = ForeignKey.CASCADE - ) - ], - indices = [Index(value = ["gymId"])] + tableName = "climb_sessions", + foreignKeys = + [ + ForeignKey( + entity = Gym::class, + parentColumns = ["id"], + childColumns = ["gymId"], + onDelete = ForeignKey.CASCADE + )], + indices = [Index(value = ["gymId"])] ) @Serializable data class ClimbSession( - @PrimaryKey - val id: String, - val gymId: String, - val date: String, - val startTime: String? = null, - val endTime: String? = null, - val duration: Long? = null, - val status: SessionStatus = SessionStatus.ACTIVE, - val notes: String? = null, - val createdAt: String, - val updatedAt: String + @PrimaryKey val id: String, + val gymId: String, + val date: String, + val startTime: String? = null, + val endTime: String? = null, + val duration: Long? = null, + val status: SessionStatus = SessionStatus.ACTIVE, + val notes: String? = null, + val createdAt: String, + val updatedAt: String ) { companion object { - fun create( - gymId: String, - notes: String? = null - ): ClimbSession { - val now = LocalDateTime.now().toString() + fun create(gymId: String, notes: String? = null): ClimbSession { + val now = DateFormatUtils.nowISO8601() return ClimbSession( - id = java.util.UUID.randomUUID().toString(), - gymId = gymId, - date = now, - startTime = now, - status = SessionStatus.ACTIVE, - notes = notes, - createdAt = now, - updatedAt = now + id = java.util.UUID.randomUUID().toString(), + gymId = gymId, + date = now, + startTime = now, + status = SessionStatus.ACTIVE, + notes = notes, + createdAt = now, + updatedAt = now ) } - + fun ClimbSession.complete(): ClimbSession { - val endTime = LocalDateTime.now().toString() - val durationMinutes = if (startTime != null) { - try { - val start = LocalDateTime.parse(startTime) - val end = LocalDateTime.parse(endTime) - java.time.Duration.between(start, end).toMinutes() - } catch (_: Exception) { - null - } - } else null - + val endTime = DateFormatUtils.nowISO8601() + val durationMinutes = + if (startTime != null) { + try { + val start = DateFormatUtils.parseISO8601(startTime) + val end = DateFormatUtils.parseISO8601(endTime) + if (start != null && end != null) { + java.time.Duration.between(start, end).toMinutes() + } else null + } catch (_: Exception) { + null + } + } else null + return this.copy( - endTime = endTime, - duration = durationMinutes, - status = SessionStatus.COMPLETED, - updatedAt = LocalDateTime.now().toString() + endTime = endTime, + duration = durationMinutes, + status = SessionStatus.COMPLETED, + updatedAt = DateFormatUtils.nowISO8601() ) } } diff --git a/android/app/src/main/java/com/atridad/openclimb/data/model/DifficultySystem.kt b/android/app/src/main/java/com/atridad/openclimb/data/model/DifficultySystem.kt index 835e600..fd58bb9 100644 --- a/android/app/src/main/java/com/atridad/openclimb/data/model/DifficultySystem.kt +++ b/android/app/src/main/java/com/atridad/openclimb/data/model/DifficultySystem.kt @@ -7,75 +7,199 @@ enum class DifficultySystem { // Bouldering V_SCALE, // V-Scale (VB - V17) FONT, // Fontainebleau (3 - 8C+) - + // Rope YDS, // Yosemite Decimal System (5.0 - 5.15d) - + // Custom difficulty systems CUSTOM; - - /** - * Get the display name for the UI - */ - fun getDisplayName(): String = when (this) { - V_SCALE -> "V Scale" - FONT -> "Font Scale" - YDS -> "YDS (Yosemite)" - CUSTOM -> "Custom" - } - - /** - * Check if this system is for bouldering - */ - fun isBoulderingSystem(): Boolean = when (this) { - V_SCALE, FONT -> true - YDS -> false - CUSTOM -> true // Custom is available for all - } - - /** - * Check if this system is for rope climbing - */ - fun isRopeSystem(): Boolean = when (this) { - YDS -> true - V_SCALE, FONT -> false - CUSTOM -> true - } - - /** - * Get available grades for this system - */ - fun getAvailableGrades(): List = when (this) { - V_SCALE -> listOf("VB", "V0", "V1", "V2", "V3", "V4", "V5", "V6", "V7", "V8", "V9", "V10", "V11", "V12", "V13", "V14", "V15", "V16", "V17") - FONT -> listOf("3", "4A", "4B", "4C", "5A", "5B", "5C", "6A", "6A+", "6B", "6B+", "6C", "6C+", "7A", "7A+", "7B", "7B+", "7C", "7C+", "8A", "8A+", "8B", "8B+", "8C", "8C+") - YDS -> listOf("5.0", "5.1", "5.2", "5.3", "5.4", "5.5", "5.6", "5.7", "5.8", "5.9", "5.10a", "5.10b", "5.10c", "5.10d", "5.11a", "5.11b", "5.11c", "5.11d", "5.12a", "5.12b", "5.12c", "5.12d", "5.13a", "5.13b", "5.13c", "5.13d", "5.14a", "5.14b", "5.14c", "5.14d", "5.15a", "5.15b", "5.15c", "5.15d") - CUSTOM -> emptyList() - } - + + /** Get the display name for the UI */ + fun getDisplayName(): String = + when (this) { + V_SCALE -> "V Scale" + FONT -> "Font Scale" + YDS -> "YDS (Yosemite)" + CUSTOM -> "Custom" + } + + /** Check if this system is for bouldering */ + fun isBoulderingSystem(): Boolean = + when (this) { + V_SCALE, FONT -> true + YDS -> false + CUSTOM -> true // Custom is available for all + } + + /** Check if this system is for rope climbing */ + fun isRopeSystem(): Boolean = + when (this) { + YDS -> true + V_SCALE, FONT -> false + CUSTOM -> true + } + + /** Get available grades for this system */ + fun getAvailableGrades(): List = + when (this) { + V_SCALE -> + listOf( + "VB", + "V0", + "V1", + "V2", + "V3", + "V4", + "V5", + "V6", + "V7", + "V8", + "V9", + "V10", + "V11", + "V12", + "V13", + "V14", + "V15", + "V16", + "V17" + ) + FONT -> + listOf( + "3", + "4A", + "4B", + "4C", + "5A", + "5B", + "5C", + "6A", + "6A+", + "6B", + "6B+", + "6C", + "6C+", + "7A", + "7A+", + "7B", + "7B+", + "7C", + "7C+", + "8A", + "8A+", + "8B", + "8B+", + "8C", + "8C+" + ) + YDS -> + listOf( + "5.0", + "5.1", + "5.2", + "5.3", + "5.4", + "5.5", + "5.6", + "5.7", + "5.8", + "5.9", + "5.10a", + "5.10b", + "5.10c", + "5.10d", + "5.11a", + "5.11b", + "5.11c", + "5.11d", + "5.12a", + "5.12b", + "5.12c", + "5.12d", + "5.13a", + "5.13b", + "5.13c", + "5.13d", + "5.14a", + "5.14b", + "5.14c", + "5.14d", + "5.15a", + "5.15b", + "5.15c", + "5.15d" + ) + CUSTOM -> emptyList() + } + companion object { - /** - * Get all difficulty systems based on type - */ - fun getSystemsForClimbType(climbType: ClimbType): List = when (climbType) { - ClimbType.BOULDER -> entries.filter { it.isBoulderingSystem() } - ClimbType.ROPE -> entries.filter { it.isRopeSystem() } - } + /** Get all difficulty systems based on type */ + fun getSystemsForClimbType(climbType: ClimbType): List = + when (climbType) { + ClimbType.BOULDER -> entries.filter { it.isBoulderingSystem() } + ClimbType.ROPE -> entries.filter { it.isRopeSystem() } + } } } @Serializable -data class DifficultyGrade( - val system: DifficultySystem, - val grade: String, - val numericValue: Int -) { +data class DifficultyGrade(val system: DifficultySystem, val grade: String, val numericValue: Int) { + + constructor( + system: DifficultySystem, + grade: String + ) : this(system = system, grade = grade, numericValue = calculateNumericValue(system, grade)) + + companion object { + private fun calculateNumericValue(system: DifficultySystem, grade: String): Int { + return when (system) { + DifficultySystem.V_SCALE -> { + if (grade == "VB") 0 else grade.removePrefix("V").toIntOrNull() ?: 0 + } + DifficultySystem.YDS -> { + // Simplified numeric mapping for YDS grades + when { + grade.startsWith("5.10") -> + 10 + (grade.getOrNull(4)?.toString()?.hashCode()?.rem(4) ?: 0) + grade.startsWith("5.11") -> + 14 + (grade.getOrNull(4)?.toString()?.hashCode()?.rem(4) ?: 0) + grade.startsWith("5.12") -> + 18 + (grade.getOrNull(4)?.toString()?.hashCode()?.rem(4) ?: 0) + grade.startsWith("5.13") -> + 22 + (grade.getOrNull(4)?.toString()?.hashCode()?.rem(4) ?: 0) + grade.startsWith("5.14") -> + 26 + (grade.getOrNull(4)?.toString()?.hashCode()?.rem(4) ?: 0) + grade.startsWith("5.15") -> + 30 + (grade.getOrNull(4)?.toString()?.hashCode()?.rem(4) ?: 0) + else -> grade.removePrefix("5.").toIntOrNull() ?: 0 + } + } + DifficultySystem.FONT -> { + // Simplified Font grade mapping + when { + grade.startsWith("6A") -> 6 + grade.startsWith("6B") -> 7 + grade.startsWith("6C") -> 8 + grade.startsWith("7A") -> 9 + grade.startsWith("7B") -> 10 + grade.startsWith("7C") -> 11 + grade.startsWith("8A") -> 12 + grade.startsWith("8B") -> 13 + grade.startsWith("8C") -> 14 + else -> grade.toIntOrNull() ?: 0 + } + } + DifficultySystem.CUSTOM -> grade.hashCode().rem(100) + } + } + } /** - * Compare this grade with another grade of the same system - * Returns negative if this grade is easier, positive if harder, 0 if equal + * Compare this grade with another grade of the same system Returns negative if this grade is + * easier, positive if harder, 0 if equal */ fun compareTo(other: DifficultyGrade): Int { if (system != other.system) return 0 - + return when (system) { DifficultySystem.V_SCALE -> compareVScaleGrades(grade, other.grade) DifficultySystem.FONT -> compareFontGrades(grade, other.grade) @@ -83,24 +207,24 @@ data class DifficultyGrade( DifficultySystem.CUSTOM -> grade.compareTo(other.grade) } } - + private fun compareVScaleGrades(grade1: String, grade2: String): Int { // Handle VB (easiest) specially if (grade1 == "VB" && grade2 != "VB") return -1 if (grade2 == "VB" && grade1 != "VB") return 1 if (grade1 == "VB" && grade2 == "VB") return 0 - + // Extract numeric values for V grades val num1 = grade1.removePrefix("V").toIntOrNull() ?: 0 val num2 = grade2.removePrefix("V").toIntOrNull() ?: 0 return num1.compareTo(num2) } - + private fun compareFontGrades(grade1: String, grade2: String): Int { // Simple string comparison for Font grades return grade1.compareTo(grade2) } - + private fun compareYDSGrades(grade1: String, grade2: String): Int { // Simple string comparison for YDS grades return grade1.compareTo(grade2) diff --git a/android/app/src/main/java/com/atridad/openclimb/data/model/Gym.kt b/android/app/src/main/java/com/atridad/openclimb/data/model/Gym.kt index de81001..1876cd9 100644 --- a/android/app/src/main/java/com/atridad/openclimb/data/model/Gym.kt +++ b/android/app/src/main/java/com/atridad/openclimb/data/model/Gym.kt @@ -2,43 +2,42 @@ package com.atridad.openclimb.data.model import androidx.room.Entity import androidx.room.PrimaryKey +import com.atridad.openclimb.utils.DateFormatUtils import kotlinx.serialization.Serializable -import java.time.LocalDateTime @Entity(tableName = "gyms") @Serializable data class Gym( - @PrimaryKey - val id: String, - val name: String, - val location: String? = null, - val supportedClimbTypes: List, - val difficultySystems: List, - val customDifficultyGrades: List = emptyList(), - val notes: String? = null, - val createdAt: String, - val updatedAt: String + @PrimaryKey val id: String, + val name: String, + val location: String? = null, + val supportedClimbTypes: List, + val difficultySystems: List, + val customDifficultyGrades: List = emptyList(), + val notes: String? = null, + val createdAt: String, + val updatedAt: String ) { companion object { fun create( - name: String, - location: String? = null, - supportedClimbTypes: List, - difficultySystems: List, - customDifficultyGrades: List = emptyList(), - notes: String? = null + name: String, + location: String? = null, + supportedClimbTypes: List, + difficultySystems: List, + customDifficultyGrades: List = emptyList(), + notes: String? = null ): Gym { - val now = LocalDateTime.now().toString() + val now = DateFormatUtils.nowISO8601() return Gym( - id = java.util.UUID.randomUUID().toString(), - name = name, - location = location, - supportedClimbTypes = supportedClimbTypes, - difficultySystems = difficultySystems, - customDifficultyGrades = customDifficultyGrades, - notes = notes, - createdAt = now, - updatedAt = now + id = java.util.UUID.randomUUID().toString(), + name = name, + location = location, + supportedClimbTypes = supportedClimbTypes, + difficultySystems = difficultySystems, + customDifficultyGrades = customDifficultyGrades, + notes = notes, + createdAt = now, + updatedAt = now ) } } diff --git a/android/app/src/main/java/com/atridad/openclimb/data/model/Problem.kt b/android/app/src/main/java/com/atridad/openclimb/data/model/Problem.kt index 1116f7f..b983d22 100644 --- a/android/app/src/main/java/com/atridad/openclimb/data/model/Problem.kt +++ b/android/app/src/main/java/com/atridad/openclimb/data/model/Problem.kt @@ -4,7 +4,7 @@ import androidx.room.Entity import androidx.room.ForeignKey import androidx.room.Index import androidx.room.PrimaryKey -import java.time.LocalDateTime +import com.atridad.openclimb.utils.DateFormatUtils import kotlinx.serialization.Serializable @Entity( @@ -49,7 +49,7 @@ data class Problem( dateSet: String? = null, notes: String? = null ): Problem { - val now = LocalDateTime.now().toString() + val now = DateFormatUtils.nowISO8601() return Problem( id = java.util.UUID.randomUUID().toString(), gymId = gymId, diff --git a/android/app/src/main/java/com/atridad/openclimb/data/repository/ClimbRepository.kt b/android/app/src/main/java/com/atridad/openclimb/data/repository/ClimbRepository.kt index 37acff7..01aced1 100644 --- a/android/app/src/main/java/com/atridad/openclimb/data/repository/ClimbRepository.kt +++ b/android/app/src/main/java/com/atridad/openclimb/data/repository/ClimbRepository.kt @@ -8,9 +8,10 @@ import com.atridad.openclimb.data.format.BackupGym import com.atridad.openclimb.data.format.BackupProblem import com.atridad.openclimb.data.format.ClimbDataBackup import com.atridad.openclimb.data.model.* +import com.atridad.openclimb.data.state.DataStateManager +import com.atridad.openclimb.utils.DateFormatUtils import com.atridad.openclimb.utils.ZipExportImportUtils import java.io.File -import java.time.LocalDateTime import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first import kotlinx.serialization.json.Json @@ -20,6 +21,10 @@ class ClimbRepository(database: OpenClimbDatabase, private val context: Context) private val problemDao = database.problemDao() private val sessionDao = database.climbSessionDao() private val attemptDao = database.attemptDao() + private val dataStateManager = DataStateManager(context) + + // Callback interface for auto-sync functionality + private var autoSyncCallback: (() -> Unit)? = null private val json = Json { prettyPrint = true @@ -29,17 +34,41 @@ class ClimbRepository(database: OpenClimbDatabase, private val context: Context) // Gym operations fun getAllGyms(): Flow> = gymDao.getAllGyms() suspend fun getGymById(id: String): Gym? = gymDao.getGymById(id) - suspend fun insertGym(gym: Gym) = gymDao.insertGym(gym) - suspend fun updateGym(gym: Gym) = gymDao.updateGym(gym) - suspend fun deleteGym(gym: Gym) = gymDao.deleteGym(gym) + suspend fun insertGym(gym: Gym) { + gymDao.insertGym(gym) + dataStateManager.updateDataState() + triggerAutoSync() + } + suspend fun updateGym(gym: Gym) { + gymDao.updateGym(gym) + dataStateManager.updateDataState() + triggerAutoSync() + } + suspend fun deleteGym(gym: Gym) { + gymDao.deleteGym(gym) + dataStateManager.updateDataState() + triggerAutoSync() + } // Problem operations fun getAllProblems(): Flow> = problemDao.getAllProblems() suspend fun getProblemById(id: String): Problem? = problemDao.getProblemById(id) fun getProblemsByGym(gymId: String): Flow> = problemDao.getProblemsByGym(gymId) - suspend fun insertProblem(problem: Problem) = problemDao.insertProblem(problem) - suspend fun updateProblem(problem: Problem) = problemDao.updateProblem(problem) - suspend fun deleteProblem(problem: Problem) = problemDao.deleteProblem(problem) + suspend fun insertProblem(problem: Problem) { + problemDao.insertProblem(problem) + dataStateManager.updateDataState() + triggerAutoSync() + } + suspend fun updateProblem(problem: Problem) { + problemDao.updateProblem(problem) + dataStateManager.updateDataState() + triggerAutoSync() + } + suspend fun deleteProblem(problem: Problem) { + problemDao.deleteProblem(problem) + dataStateManager.updateDataState() + triggerAutoSync() + } // Session operations fun getAllSessions(): Flow> = sessionDao.getAllSessions() @@ -48,9 +77,21 @@ class ClimbRepository(database: OpenClimbDatabase, private val context: Context) sessionDao.getSessionsByGym(gymId) suspend fun getActiveSession(): ClimbSession? = sessionDao.getActiveSession() fun getActiveSessionFlow(): Flow = sessionDao.getActiveSessionFlow() - suspend fun insertSession(session: ClimbSession) = sessionDao.insertSession(session) - suspend fun updateSession(session: ClimbSession) = sessionDao.updateSession(session) - suspend fun deleteSession(session: ClimbSession) = sessionDao.deleteSession(session) + suspend fun insertSession(session: ClimbSession) { + sessionDao.insertSession(session) + dataStateManager.updateDataState() + triggerAutoSync() + } + suspend fun updateSession(session: ClimbSession) { + sessionDao.updateSession(session) + dataStateManager.updateDataState() + triggerAutoSync() + } + suspend fun deleteSession(session: ClimbSession) { + sessionDao.deleteSession(session) + dataStateManager.updateDataState() + triggerAutoSync() + } suspend fun getLastUsedGym(): Gym? { val recentSessions = sessionDao.getRecentSessions(1).first() return if (recentSessions.isNotEmpty()) { @@ -66,9 +107,21 @@ class ClimbRepository(database: OpenClimbDatabase, private val context: Context) attemptDao.getAttemptsBySession(sessionId) fun getAttemptsByProblem(problemId: String): Flow> = attemptDao.getAttemptsByProblem(problemId) - suspend fun insertAttempt(attempt: Attempt) = attemptDao.insertAttempt(attempt) - suspend fun updateAttempt(attempt: Attempt) = attemptDao.updateAttempt(attempt) - suspend fun deleteAttempt(attempt: Attempt) = attemptDao.deleteAttempt(attempt) + suspend fun insertAttempt(attempt: Attempt) { + attemptDao.insertAttempt(attempt) + dataStateManager.updateDataState() + triggerAutoSync() + } + suspend fun updateAttempt(attempt: Attempt) { + attemptDao.updateAttempt(attempt) + dataStateManager.updateDataState() + triggerAutoSync() + } + suspend fun deleteAttempt(attempt: Attempt) { + attemptDao.deleteAttempt(attempt) + dataStateManager.updateDataState() + triggerAutoSync() + } suspend fun exportAllDataToZipUri(context: Context, uri: android.net.Uri) { try { @@ -84,7 +137,7 @@ class ClimbRepository(database: OpenClimbDatabase, private val context: Context) // Create backup data using platform-neutral format val backupData = ClimbDataBackup( - exportedAt = LocalDateTime.now().toString(), + exportedAt = DateFormatUtils.nowISO8601(), version = "2.0", formatVersion = "2.0", gyms = allGyms.map { BackupGym.fromGym(it) }, @@ -154,7 +207,8 @@ class ClimbRepository(database: OpenClimbDatabase, private val context: Context) problemDao.deleteAllProblems() gymDao.deleteAllGyms() - // Import gyms first (problems depend on gyms) + // Import gyms first (problems depend on gyms) - use DAO directly to avoid multiple data + // state updates importData.gyms.forEach { backupGym -> try { gymDao.insertGym(backupGym.toGym()) @@ -170,7 +224,7 @@ class ClimbRepository(database: OpenClimbDatabase, private val context: Context) importResult.importedImagePaths ) - // Import problems (depends on gyms) + // Import problems (depends on gyms) - use DAO directly updatedBackupProblems.forEach { backupProblem -> try { problemDao.insertProblem(backupProblem.toProblem()) @@ -181,7 +235,7 @@ class ClimbRepository(database: OpenClimbDatabase, private val context: Context) } } - // Import sessions + // Import sessions - use DAO directly importData.sessions.forEach { backupSession -> try { sessionDao.insertSession(backupSession.toClimbSession()) @@ -190,7 +244,7 @@ class ClimbRepository(database: OpenClimbDatabase, private val context: Context) } } - // Import attempts last (depends on problems and sessions) + // Import attempts last (depends on problems and sessions) - use DAO directly importData.attempts.forEach { backupAttempt -> try { attemptDao.insertAttempt(backupAttempt.toAttempt()) @@ -198,11 +252,30 @@ class ClimbRepository(database: OpenClimbDatabase, private val context: Context) throw Exception("Failed to import attempt '${backupAttempt.id}': ${e.message}") } } + + // Update data state once at the end to current time since we just imported new data + dataStateManager.updateDataState() } catch (e: Exception) { throw Exception("Import failed: ${e.message}") } } + /** + * Sets the callback for auto-sync functionality. This should be called by the SyncService to + * register itself for auto-sync triggers. + */ + fun setAutoSyncCallback(callback: (() -> Unit)?) { + autoSyncCallback = callback + } + + /** + * Triggers auto-sync if enabled. This is called after any data modification to keep data + * synchronized across devices automatically. + */ + private fun triggerAutoSync() { + autoSyncCallback?.invoke() + } + private fun validateDataIntegrity( gyms: List, problems: List, @@ -260,6 +333,10 @@ class ClimbRepository(database: OpenClimbDatabase, private val context: Context) suspend fun resetAllData() { try { + // Temporarily disable auto-sync during reset + val originalCallback = autoSyncCallback + autoSyncCallback = null + // Clear all data from database attemptDao.deleteAllAttempts() sessionDao.deleteAllSessions() @@ -268,11 +345,35 @@ class ClimbRepository(database: OpenClimbDatabase, private val context: Context) // Clear all images from storage clearAllImages() + + // Restore auto-sync callback + autoSyncCallback = originalCallback } catch (e: Exception) { throw Exception("Reset failed: ${e.message}") } } + // Import methods that bypass auto-sync to avoid triggering sync during data restoration + suspend fun insertGymWithoutSync(gym: Gym) { + gymDao.insertGym(gym) + dataStateManager.updateDataState() + } + + suspend fun insertProblemWithoutSync(problem: Problem) { + problemDao.insertProblem(problem) + dataStateManager.updateDataState() + } + + suspend fun insertSessionWithoutSync(session: ClimbSession) { + sessionDao.insertSession(session) + dataStateManager.updateDataState() + } + + suspend fun insertAttemptWithoutSync(attempt: Attempt) { + attemptDao.insertAttempt(attempt) + dataStateManager.updateDataState() + } + private fun clearAllImages() { try { // Get the images directory diff --git a/android/app/src/main/java/com/atridad/openclimb/data/state/DataStateManager.kt b/android/app/src/main/java/com/atridad/openclimb/data/state/DataStateManager.kt new file mode 100644 index 0000000..7fedf7f --- /dev/null +++ b/android/app/src/main/java/com/atridad/openclimb/data/state/DataStateManager.kt @@ -0,0 +1,81 @@ +package com.atridad.openclimb.data.state + +import android.content.Context +import android.content.SharedPreferences +import android.util.Log +import com.atridad.openclimb.utils.DateFormatUtils + +/** + * Manages the overall data state timestamp for sync purposes. This tracks when any data in the + * local database was last modified, independent of individual entity timestamps. + */ +class DataStateManager(context: Context) { + + companion object { + private const val TAG = "DataStateManager" + private const val PREFS_NAME = "openclimb_data_state" + private const val KEY_LAST_MODIFIED = "last_modified_timestamp" + private const val KEY_INITIALIZED = "state_initialized" + } + + private val prefs: SharedPreferences = + context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + + init { + // Initialize with current timestamp if this is the first time + if (!isInitialized()) { + updateDataState() + markAsInitialized() + Log.d(TAG, "DataStateManager initialized with timestamp: ${getLastModified()}") + } + } + + /** + * Updates the data state timestamp to the current time. Call this whenever any data is modified + * (create, update, delete). + */ + fun updateDataState() { + val now = DateFormatUtils.nowISO8601() + prefs.edit().putString(KEY_LAST_MODIFIED, now).apply() + Log.d(TAG, "Data state updated to: $now") + } + + /** + * Gets the current data state timestamp. This represents when any data was last modified + * locally. + */ + fun getLastModified(): String { + return prefs.getString(KEY_LAST_MODIFIED, DateFormatUtils.nowISO8601()) + ?: DateFormatUtils.nowISO8601() + } + + /** + * Sets the data state timestamp to a specific value. Used when importing data from server to + * sync the state. + */ + fun setLastModified(timestamp: String) { + prefs.edit().putString(KEY_LAST_MODIFIED, timestamp).apply() + Log.d(TAG, "Data state set to: $timestamp") + } + + /** Resets the data state (for testing or complete data wipe). */ + fun reset() { + prefs.edit().clear().apply() + Log.d(TAG, "Data state reset") + } + + /** Checks if the data state has been initialized. */ + private fun isInitialized(): Boolean { + return prefs.getBoolean(KEY_INITIALIZED, false) + } + + /** Marks the data state as initialized. */ + private fun markAsInitialized() { + prefs.edit().putBoolean(KEY_INITIALIZED, true).apply() + } + + /** Gets debug information about the current state. */ + fun getDebugInfo(): String { + return "DataState(lastModified=${getLastModified()}, initialized=${isInitialized()})" + } +} diff --git a/android/app/src/main/java/com/atridad/openclimb/data/sync/SyncService.kt b/android/app/src/main/java/com/atridad/openclimb/data/sync/SyncService.kt new file mode 100644 index 0000000..9d193e6 --- /dev/null +++ b/android/app/src/main/java/com/atridad/openclimb/data/sync/SyncService.kt @@ -0,0 +1,998 @@ +package com.atridad.openclimb.data.sync + +import android.content.Context +import android.content.SharedPreferences +import android.util.Log +import com.atridad.openclimb.data.format.BackupAttempt +import com.atridad.openclimb.data.format.BackupClimbSession +import com.atridad.openclimb.data.format.BackupGym +import com.atridad.openclimb.data.format.BackupProblem +import com.atridad.openclimb.data.format.ClimbDataBackup +import com.atridad.openclimb.data.migration.ImageMigrationService +import com.atridad.openclimb.data.repository.ClimbRepository +import com.atridad.openclimb.data.state.DataStateManager +import com.atridad.openclimb.utils.DateFormatUtils +import com.atridad.openclimb.utils.ImageNamingUtils +import com.atridad.openclimb.utils.ImageUtils +import java.io.IOException +import java.time.Instant +import java.util.concurrent.TimeUnit +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import kotlinx.coroutines.withContext +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody + +class SyncService(private val context: Context, private val repository: ClimbRepository) { + + private val migrationService = ImageMigrationService(context, repository) + private val dataStateManager = DataStateManager(context) + private val syncMutex = Mutex() + + companion object { + private const val TAG = "SyncService" + } + + private val sharedPreferences: SharedPreferences = + context.getSharedPreferences("sync_preferences", Context.MODE_PRIVATE) + + private val httpClient = + OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS) + .readTimeout(60, TimeUnit.SECONDS) + .writeTimeout(60, TimeUnit.SECONDS) + .build() + + private val json = Json { + prettyPrint = true + ignoreUnknownKeys = true + explicitNulls = false + encodeDefaults = true + coerceInputValues = true + } + + // State flows + private val _isSyncing = MutableStateFlow(false) + val isSyncing: StateFlow = _isSyncing.asStateFlow() + + private val _lastSyncTime = MutableStateFlow(null) + val lastSyncTime: StateFlow = _lastSyncTime.asStateFlow() + + private val _syncError = MutableStateFlow(null) + val syncError: StateFlow = _syncError.asStateFlow() + + private val _isConnected = MutableStateFlow(false) + val isConnected: StateFlow = _isConnected.asStateFlow() + + private val _isTesting = MutableStateFlow(false) + val isTesting: StateFlow = _isTesting.asStateFlow() + + // Configuration keys + private object Keys { + const val SERVER_URL = "sync_server_url" + const val AUTH_TOKEN = "sync_auth_token" + const val LAST_SYNC_TIME = "last_sync_time" + const val IS_CONNECTED = "sync_is_connected" + const val AUTO_SYNC_ENABLED = "auto_sync_enabled" + } + + // Configuration properties + var serverURL: String + get() = sharedPreferences.getString(Keys.SERVER_URL, "") ?: "" + set(value) { + sharedPreferences.edit().putString(Keys.SERVER_URL, value).apply() + } + + var authToken: String + get() = sharedPreferences.getString(Keys.AUTH_TOKEN, "") ?: "" + set(value) { + sharedPreferences.edit().putString(Keys.AUTH_TOKEN, value).apply() + } + + val isConfigured: Boolean + get() = serverURL.isNotEmpty() && authToken.isNotEmpty() + + var isAutoSyncEnabled: Boolean + get() = sharedPreferences.getBoolean(Keys.AUTO_SYNC_ENABLED, true) + set(value) { + sharedPreferences.edit().putBoolean(Keys.AUTO_SYNC_ENABLED, value).apply() + } + + init { + // Initialize state from preferences + _isConnected.value = sharedPreferences.getBoolean(Keys.IS_CONNECTED, false) + _lastSyncTime.value = sharedPreferences.getString(Keys.LAST_SYNC_TIME, null) + + // Register auto-sync callback with repository + repository.setAutoSyncCallback { + kotlinx.coroutines.CoroutineScope(kotlinx.coroutines.Dispatchers.IO).launch { + triggerAutoSync() + } + } + } + + suspend fun downloadData(): ClimbDataBackup = + withContext(Dispatchers.IO) { + if (!isConfigured) { + throw SyncException.NotConfigured + } + + val request = + Request.Builder() + .url("$serverURL/sync") + .get() + .addHeader("Authorization", "Bearer $authToken") + .addHeader("Accept", "application/json") + .build() + + try { + val response = httpClient.newCall(request).execute() + + when (response.code) { + 200 -> { + val responseBody = + response.body?.string() + ?: throw SyncException.InvalidResponse( + "Empty response body" + ) + Log.d(TAG, "Downloaded data from server: ${responseBody.take(500)}...") + try { + val backup = json.decodeFromString(responseBody) + Log.d( + TAG, + "Server backup contains: gyms=${backup.gyms.size}, problems=${backup.problems.size}, sessions=${backup.sessions.size}, attempts=${backup.attempts.size}" + ) + + // Log problems with images + backup.problems.forEach { problem -> + val imageCount = problem.imagePaths?.size ?: 0 + if (imageCount > 0) { + Log.d( + TAG, + "Server problem '${problem.name}' has images: ${problem.imagePaths}" + ) + } + } + + backup + } catch (e: Exception) { + Log.e(TAG, "Failed to decode download response: ${e.message}") + throw SyncException.DecodingError( + e.message ?: "Failed to decode response" + ) + } + } + 401 -> throw SyncException.Unauthorized + else -> throw SyncException.ServerError(response.code) + } + } catch (e: IOException) { + throw SyncException.NetworkError(e.message ?: "Network error") + } + } + + suspend fun uploadData(backup: ClimbDataBackup): ClimbDataBackup = + withContext(Dispatchers.IO) { + if (!isConfigured) { + throw SyncException.NotConfigured + } + + val jsonBody = json.encodeToString(backup) + Log.d(TAG, "Uploading JSON to server: $jsonBody") + val requestBody = jsonBody.toRequestBody("application/json".toMediaType()) + + val request = + Request.Builder() + .url("$serverURL/sync") + .put(requestBody) + .addHeader("Authorization", "Bearer $authToken") + .addHeader("Content-Type", "application/json") + .build() + + try { + val response = httpClient.newCall(request).execute() + Log.d(TAG, "Upload response code: ${response.code}") + + when (response.code) { + 200 -> { + val responseBody = + response.body?.string() + ?: throw SyncException.InvalidResponse( + "Empty response body" + ) + try { + json.decodeFromString(responseBody) + } catch (e: Exception) { + Log.e(TAG, "Failed to decode upload response: ${e.message}") + throw SyncException.DecodingError( + e.message ?: "Failed to decode response" + ) + } + } + 401 -> throw SyncException.Unauthorized + else -> { + val errorBody = response.body?.string() ?: "No error details" + Log.e(TAG, "Server error ${response.code}: $errorBody") + throw SyncException.ServerError(response.code) + } + } + } catch (e: IOException) { + throw SyncException.NetworkError(e.message ?: "Network error") + } + } + + suspend fun uploadImage(filename: String, imageData: ByteArray) = + withContext(Dispatchers.IO) { + if (!isConfigured) { + throw SyncException.NotConfigured + } + + // Server expects filename as query parameter and raw image data in body + // Extract just the filename without directory path + val justFilename = filename.substringAfterLast('/') + val requestBody = imageData.toRequestBody("image/*".toMediaType()) + + val request = + Request.Builder() + .url("$serverURL/images/upload?filename=$justFilename") + .post(requestBody) + .addHeader("Authorization", "Bearer $authToken") + .build() + + try { + val response = httpClient.newCall(request).execute() + + when (response.code) { + 200 -> Unit // Success + 401 -> throw SyncException.Unauthorized + else -> { + val errorBody = response.body?.string() ?: "No error details" + Log.e(TAG, "Image upload error ${response.code}: $errorBody") + throw SyncException.ServerError(response.code) + } + } + } catch (e: IOException) { + throw SyncException.NetworkError(e.message ?: "Network error") + } + } + + suspend fun downloadImage(filename: String): ByteArray = + withContext(Dispatchers.IO) { + if (!isConfigured) { + throw SyncException.NotConfigured + } + + Log.d(TAG, "Downloading image from server: $filename") + val request = + Request.Builder() + .url("$serverURL/images/download?filename=$filename") + .get() + .addHeader("Authorization", "Bearer $authToken") + .build() + + try { + val response = httpClient.newCall(request).execute() + Log.d(TAG, "Image download response for $filename: ${response.code}") + + when (response.code) { + 200 -> { + val imageBytes = + response.body?.bytes() + ?: throw SyncException.InvalidResponse( + "Empty image response" + ) + Log.d( + TAG, + "Successfully downloaded image $filename: ${imageBytes.size} bytes" + ) + imageBytes + } + 401 -> throw SyncException.Unauthorized + 404 -> { + Log.w(TAG, "Image not found on server: $filename") + throw SyncException.ImageNotFound(filename) + } + else -> { + val errorBody = response.body?.string() ?: "No error details" + Log.e( + TAG, + "Image download error ${response.code} for $filename: $errorBody" + ) + throw SyncException.ServerError(response.code) + } + } + } catch (e: IOException) { + Log.e(TAG, "Network error downloading image $filename: ${e.message}") + throw SyncException.NetworkError(e.message ?: "Network error") + } + } + + suspend fun syncWithServer() { + if (!isConfigured) { + throw SyncException.NotConfigured + } + + if (!_isConnected.value) { + throw SyncException.NotConnected + } + + // Prevent concurrent sync operations + syncMutex.withLock { + _isSyncing.value = true + _syncError.value = null + + try { + // Fix existing image paths first + Log.d(TAG, "Fixing existing image paths before sync") + val pathFixSuccess = fixImagePaths() + if (!pathFixSuccess) { + Log.w(TAG, "Image path fix failed, but continuing with sync") + } + + // Migrate images to consistent naming second + Log.d(TAG, "Performing image migration before sync") + val migrationSuccess = migrateImagesForSync() + if (!migrationSuccess) { + Log.w(TAG, "Image migration failed, but continuing with sync") + } + + // Get local backup data + val localBackup = createBackupFromRepository() + + // Download server data + val serverBackup = downloadData() + + // Check if we have any local data + val hasLocalData = + localBackup.gyms.isNotEmpty() || + localBackup.problems.isNotEmpty() || + localBackup.sessions.isNotEmpty() || + localBackup.attempts.isNotEmpty() + + val hasServerData = + serverBackup.gyms.isNotEmpty() || + serverBackup.problems.isNotEmpty() || + serverBackup.sessions.isNotEmpty() || + serverBackup.attempts.isNotEmpty() + + when { + !hasLocalData && hasServerData -> { + // Case 1: No local data - do full restore from server + Log.d(TAG, "No local data found, performing full restore from server") + val imagePathMapping = syncImagesFromServer(serverBackup) + importBackupToRepository(serverBackup, imagePathMapping) + Log.d(TAG, "Full restore completed") + } + hasLocalData && !hasServerData -> { + // Case 2: No server data - upload local data to server + Log.d(TAG, "No server data found, uploading local data to server") + uploadData(localBackup) + syncImagesForBackup(localBackup) + Log.d(TAG, "Initial upload completed") + } + hasLocalData && hasServerData -> { + // Case 3: Both have data - compare timestamps (last writer wins) + val localTimestamp = parseISO8601ToMillis(localBackup.exportedAt) + val serverTimestamp = parseISO8601ToMillis(serverBackup.exportedAt) + + Log.d( + TAG, + "Comparing timestamps: local=$localTimestamp, server=$serverTimestamp" + ) + + if (localTimestamp > serverTimestamp) { + // Local is newer - replace server with local data + Log.d(TAG, "Local data is newer, replacing server content") + uploadData(localBackup) + syncImagesForBackup(localBackup) + Log.d(TAG, "Server replaced with local data") + } else if (serverTimestamp > localTimestamp) { + // Server is newer - replace local with server data + Log.d(TAG, "Server data is newer, replacing local content") + val imagePathMapping = syncImagesFromServer(serverBackup) + importBackupToRepository(serverBackup, imagePathMapping) + Log.d(TAG, "Local data replaced with server data") + } else { + // Timestamps are equal - no sync needed + Log.d(TAG, "Data is in sync (timestamps equal), no action needed") + } + } + else -> { + Log.d(TAG, "No data to sync") + } + } + + // Update last sync time + val now = DateFormatUtils.nowISO8601() + _lastSyncTime.value = now + sharedPreferences.edit().putString(Keys.LAST_SYNC_TIME, now).apply() + } catch (e: Exception) { + _syncError.value = e.message + throw e + } finally { + _isSyncing.value = false + } + } + } + + private suspend fun syncImagesFromServer(backup: ClimbDataBackup): Map { + val imagePathMapping = mutableMapOf() + + Log.d(TAG, "Starting to download images from server") + var totalImages = 0 + var downloadedImages = 0 + var failedImages = 0 + + for (problem in backup.problems) { + val imageCount = problem.imagePaths?.size ?: 0 + if (imageCount > 0) { + Log.d( + TAG, + "Problem '${problem.name}' has $imageCount images: ${problem.imagePaths}" + ) + totalImages += imageCount + } + + problem.imagePaths?.forEachIndexed { index, imagePath -> + try { + Log.d(TAG, "Attempting to download image: $imagePath") + val imageData = downloadImage(imagePath) + + // Extract filename and ensure it follows our naming convention + val serverFilename = imagePath.substringAfterLast('/') + val consistentFilename = + if (ImageNamingUtils.isValidImageFilename(serverFilename)) { + serverFilename + } else { + // Generate consistent filename using problem ID and index + ImageNamingUtils.generateImageFilename(problem.id, index) + } + + val localImagePath = + ImageUtils.saveImageFromBytesWithFilename( + context, + imageData, + consistentFilename + ) + + if (localImagePath != null) { + // Map original server filename to the full local relative path + imagePathMapping[serverFilename] = localImagePath + downloadedImages++ + Log.d( + TAG, + "Downloaded and mapped image: $serverFilename -> $localImagePath" + ) + } else { + Log.w(TAG, "Failed to save downloaded image locally: $imagePath") + failedImages++ + } + } catch (e: Exception) { + Log.w(TAG, "Failed to download image $imagePath: ${e.message}") + failedImages++ + } + } + } + + Log.d( + TAG, + "Image download completed: $downloadedImages downloaded, $failedImages failed, $totalImages total" + ) + return imagePathMapping + } + + private suspend fun syncImagesToServer() { + val allProblems = repository.getAllProblems().first() + val backup = + ClimbDataBackup( + exportedAt = DateFormatUtils.nowISO8601(), + version = "2.0", + formatVersion = "2.0", + gyms = emptyList(), + problems = allProblems.map { BackupProblem.fromProblem(it) }, + sessions = emptyList(), + attempts = emptyList() + ) + syncImagesForBackup(backup) + } + + private suspend fun syncImagesForBackup(backup: ClimbDataBackup) { + Log.d(TAG, "Starting image sync for backup with ${backup.problems.size} problems") + + var totalImages = 0 + var uploadedImages = 0 + var failedImages = 0 + + for (problem in backup.problems) { + val imageCount = problem.imagePaths?.size ?: 0 + totalImages += imageCount + + Log.d(TAG, "Problem '${problem.name}' has $imageCount images: ${problem.imagePaths}") + + problem.imagePaths?.forEachIndexed { index, imagePath -> + try { + val imageFile = ImageUtils.getImageFile(context, imagePath) + Log.d(TAG, "Checking image file: $imagePath -> ${imageFile.absolutePath}") + Log.d( + TAG, + "Image file exists: ${imageFile.exists()}, size: ${if (imageFile.exists()) imageFile.length() else 0} bytes" + ) + + if (imageFile.exists() && imageFile.length() > 0) { + val imageData = imageFile.readBytes() + val filename = imagePath.substringAfterLast('/') + + // Ensure filename follows our naming convention + val consistentFilename = + if (ImageNamingUtils.isValidImageFilename(filename)) { + filename + } else { + // Generate consistent filename and rename the local file + val newFilename = + ImageNamingUtils.generateImageFilename( + problem.id, + index + ) + val newFile = java.io.File(imageFile.parent, newFilename) + if (imageFile.renameTo(newFile)) { + Log.d( + TAG, + "Renamed local image file: $filename -> $newFilename" + ) + // Update the problem's image path in memory for next sync + newFilename + } else { + Log.w( + TAG, + "Failed to rename local image file, using original" + ) + filename + } + } + + Log.d(TAG, "Uploading image: $consistentFilename (${imageData.size} bytes)") + uploadImage(consistentFilename, imageData) + uploadedImages++ + Log.d(TAG, "Successfully uploaded image: $consistentFilename") + } else { + Log.w( + TAG, + "Image file not found or empty: $imagePath at ${imageFile.absolutePath}" + ) + failedImages++ + } + } catch (e: Exception) { + Log.e(TAG, "Failed to upload image $imagePath: ${e.message}", e) + failedImages++ + } + } + } + + Log.d( + TAG, + "Image sync completed: $uploadedImages uploaded, $failedImages failed, $totalImages total" + ) + } + + private suspend fun createBackupFromRepository(): ClimbDataBackup { + val allGyms = repository.getAllGyms().first() + val allProblems = repository.getAllProblems().first() + val allSessions = repository.getAllSessions().first() + val allAttempts = repository.getAllAttempts().first() + + return ClimbDataBackup( + exportedAt = dataStateManager.getLastModified(), + version = "2.0", + formatVersion = "2.0", + gyms = allGyms.map { BackupGym.fromGym(it) }, + problems = allProblems.map { BackupProblem.fromProblem(it) }, + sessions = allSessions.map { BackupClimbSession.fromClimbSession(it) }, + attempts = allAttempts.map { BackupAttempt.fromAttempt(it) } + ) + } + + private suspend fun importBackupToRepository( + backup: ClimbDataBackup, + imagePathMapping: Map = emptyMap() + ) { + // Clear existing data to avoid conflicts + repository.resetAllData() + + // Import gyms first (problems depend on gyms) + backup.gyms.forEach { backupGym -> + try { + val gym = backupGym.toGym() + Log.d(TAG, "Importing gym: ${gym.name} (ID: ${gym.id})") + repository.insertGymWithoutSync(gym) + } catch (e: Exception) { + Log.e(TAG, "Failed to import gym '${backupGym.name}': ${e.message}") + throw e // Stop import if gym fails since problems depend on it + } + } + + // Import problems with updated image paths + backup.problems.forEach { backupProblem -> + try { + val updatedProblem = + if (imagePathMapping.isNotEmpty()) { + val newImagePaths = + backupProblem.imagePaths?.mapNotNull { oldPath -> + // Extract filename and check mapping + val filename = oldPath.substringAfterLast('/') + // Use mapped full path or fallback to consistent naming + // with full path + imagePathMapping[filename] + ?: if (ImageNamingUtils.isValidImageFilename( + filename + ) + ) { + "problem_images/$filename" + } else { + // Generate consistent filename as fallback with + // full path + val index = + backupProblem.imagePaths.indexOf( + oldPath + ) + val consistentFilename = + ImageNamingUtils.generateImageFilename( + backupProblem.id, + index + ) + "problem_images/$consistentFilename" + } + } + ?: emptyList() + backupProblem.withUpdatedImagePaths(newImagePaths) + } else { + backupProblem + } + repository.insertProblemWithoutSync(updatedProblem.toProblem()) + } catch (e: Exception) { + Log.e(TAG, "Failed to import problem '${backupProblem.name}': ${e.message}") + } + } + + // Import sessions + backup.sessions.forEach { backupSession -> + try { + repository.insertSessionWithoutSync(backupSession.toClimbSession()) + } catch (e: Exception) { + Log.e(TAG, "Failed to import session '${backupSession.id}': ${e.message}") + } + } + + // Import attempts last + backup.attempts.forEach { backupAttempt -> + try { + repository.insertAttemptWithoutSync(backupAttempt.toAttempt()) + } catch (e: Exception) { + Log.e(TAG, "Failed to import attempt '${backupAttempt.id}': ${e.message}") + } + } + + // Update local data state to match imported data timestamp + dataStateManager.setLastModified(backup.exportedAt) + Log.d(TAG, "Data state synchronized to imported timestamp: ${backup.exportedAt}") + } + + /** Parses ISO8601 timestamp to milliseconds for comparison */ + private fun parseISO8601ToMillis(timestamp: String): Long { + return try { + Instant.parse(timestamp).toEpochMilli() + } catch (e: Exception) { + Log.w(TAG, "Failed to parse timestamp: $timestamp, using 0", e) + 0L + } + } + + /** Converts milliseconds to ISO8601 timestamp */ + private fun millisToISO8601(millis: Long): String { + return DateFormatUtils.millisToISO8601(millis) + } + + /** + * Fixes existing image paths in the database to include the proper directory structure. This + * corrects paths like "problem_abc_0.jpg" to "problem_images/problem_abc_0.jpg" + */ + suspend fun fixImagePaths(): Boolean { + return try { + Log.d(TAG, "Fixing existing image paths in database") + + val allProblems = repository.getAllProblems().first() + var fixedCount = 0 + + for (problem in allProblems) { + if (problem.imagePaths.isNotEmpty()) { + val originalPaths = problem.imagePaths + val fixedPaths = + problem.imagePaths.map { path -> + if (!path.startsWith("problem_images/") && !path.contains("/")) { + // Just a filename, add the directory prefix + val fixedPath = "problem_images/$path" + Log.d(TAG, "Fixed path: $path -> $fixedPath") + fixedCount++ + fixedPath + } else { + path + } + } + + if (originalPaths != fixedPaths) { + val updatedProblem = problem.copy(imagePaths = fixedPaths) + repository.insertProblem(updatedProblem) + } + } + } + + Log.i(TAG, "Fixed $fixedCount image paths in database") + true + } catch (e: Exception) { + Log.e(TAG, "Failed to fix image paths: ${e.message}", e) + false + } + } + + /** + * Performs image migration to ensure all images use consistent naming convention before sync + * operations. This should be called before any sync to avoid filename conflicts. + */ + suspend fun migrateImagesForSync(): Boolean { + return try { + Log.d(TAG, "Starting image migration for sync compatibility") + val result = migrationService.performFullMigration() + + when (result) { + is com.atridad.openclimb.data.migration.ImageMigrationResult.AlreadyCompleted -> { + Log.d(TAG, "Image migration already completed") + true + } + is com.atridad.openclimb.data.migration.ImageMigrationResult.Success -> { + Log.i( + TAG, + "Image migration completed: ${result.totalMigrated} images migrated, ${result.errors} errors" + ) + true + } + is com.atridad.openclimb.data.migration.ImageMigrationResult.Failed -> { + Log.e(TAG, "Image migration failed: ${result.error}") + false + } + } + } catch (e: Exception) { + Log.e(TAG, "Image migration error: ${e.message}", e) + false + } + } + + suspend fun testConnection() { + if (!isConfigured) { + throw SyncException.NotConfigured + } + + _isTesting.value = true + _syncError.value = null + + try { + withContext(Dispatchers.IO) { + val request = + Request.Builder() + .url("$serverURL/sync") + .get() + .addHeader("Authorization", "Bearer $authToken") + .addHeader("Accept", "application/json") + .build() + + val response = httpClient.newCall(request).execute() + + when (response.code) { + 200 -> { + _isConnected.value = true + sharedPreferences.edit().putBoolean(Keys.IS_CONNECTED, true).apply() + } + 401 -> throw SyncException.Unauthorized + else -> throw SyncException.ServerError(response.code) + } + } + } catch (e: Exception) { + _isConnected.value = false + sharedPreferences.edit().putBoolean(Keys.IS_CONNECTED, false).apply() + _syncError.value = e.message + throw e + } finally { + _isTesting.value = false + } + } + + suspend fun triggerAutoSync() { + if (!isConfigured || !_isConnected.value || !isAutoSyncEnabled) { + return + } + + // Check if sync is already running to prevent duplicate attempts + if (_isSyncing.value) { + Log.d(TAG, "Sync already in progress, skipping auto-sync") + return + } + + try { + syncWithServer() + } catch (e: Exception) { + Log.e(TAG, "Auto-sync failed: ${e.message}") + _syncError.value = e.message + } + } + + // DEPRECATED: Complex merge logic replaced with simple timestamp-based sync + // These methods are no longer used but kept for reference + @Deprecated("Use simple timestamp-based sync instead") + private fun performIntelligentMerge( + local: ClimbDataBackup, + server: ClimbDataBackup + ): ClimbDataBackup { + Log.d(TAG, "Merging data - preserving all entities to prevent data loss") + + val mergedGyms = mergeGyms(local.gyms, server.gyms) + val mergedProblems = mergeProblems(local.problems, server.problems) + val mergedSessions = mergeSessions(local.sessions, server.sessions) + val mergedAttempts = mergeAttempts(local.attempts, server.attempts) + + Log.d( + TAG, + "Merge results: gyms=${mergedGyms.size}, problems=${mergedProblems.size}, " + + "sessions=${mergedSessions.size}, attempts=${mergedAttempts.size}" + ) + + return ClimbDataBackup( + exportedAt = DateFormatUtils.nowISO8601(), + version = "2.0", + formatVersion = "2.0", + gyms = mergedGyms, + problems = mergedProblems, + sessions = mergedSessions, + attempts = mergedAttempts + ) + } + + private fun mergeGyms(local: List, server: List): List { + val merged = mutableMapOf() + + // Add all local gyms + local.forEach { gym -> merged[gym.id] = gym } + + // Add server gyms, preferring newer updates + server.forEach { serverGym -> + val localGym = merged[serverGym.id] + if (localGym == null || isNewerThan(serverGym.updatedAt, localGym.updatedAt)) { + merged[serverGym.id] = serverGym + } + } + + return merged.values.toList() + } + + private fun mergeProblems( + local: List, + server: List + ): List { + val merged = mutableMapOf() + + // Add all local problems + local.forEach { problem -> merged[problem.id] = problem } + + // Add server problems, preferring newer updates + server.forEach { serverProblem -> + val localProblem = merged[serverProblem.id] + if (localProblem == null || isNewerThan(serverProblem.updatedAt, localProblem.updatedAt) + ) { + // Merge image paths to preserve all images + val allImagePaths = mutableSetOf() + localProblem?.imagePaths?.let { allImagePaths.addAll(it) } + serverProblem.imagePaths?.let { allImagePaths.addAll(it) } + + merged[serverProblem.id] = + serverProblem.withUpdatedImagePaths(allImagePaths.toList()) + } + } + + return merged.values.toList() + } + + private fun mergeSessions( + local: List, + server: List + ): List { + val merged = mutableMapOf() + + // Add all local sessions + local.forEach { session -> merged[session.id] = session } + + // Add server sessions, preferring newer updates + server.forEach { serverSession -> + val localSession = merged[serverSession.id] + if (localSession == null || isNewerThan(serverSession.updatedAt, localSession.updatedAt) + ) { + merged[serverSession.id] = serverSession + } + } + + return merged.values.toList() + } + + private fun mergeAttempts( + local: List, + server: List + ): List { + val merged = mutableMapOf() + + // Add all local attempts + local.forEach { attempt -> merged[attempt.id] = attempt } + + // Add server attempts, preferring newer updates + server.forEach { serverAttempt -> + val localAttempt = merged[serverAttempt.id] + if (localAttempt == null || isNewerThan(serverAttempt.createdAt, localAttempt.createdAt) + ) { + merged[serverAttempt.id] = serverAttempt + } + } + + return merged.values.toList() + } + + private fun isNewerThan(dateString1: String, dateString2: String): Boolean { + return try { + // Try parsing as instant first + val date1 = Instant.parse(dateString1) + val date2 = Instant.parse(dateString2) + date1.isAfter(date2) + } catch (e: Exception) { + // Fallback to string comparison + dateString1 > dateString2 + } + } + + fun disconnect() { + _isConnected.value = false + sharedPreferences.edit().putBoolean(Keys.IS_CONNECTED, false).apply() + _syncError.value = null + } + + fun clearConfiguration() { + serverURL = "" + authToken = "" + isAutoSyncEnabled = true + _lastSyncTime.value = null + _isConnected.value = false + _syncError.value = null + + sharedPreferences.edit().clear().apply() + } +} + +// Removed SyncTrigger enum - now using simple auto sync on any data change + +sealed class SyncException(message: String) : Exception(message) { + object NotConfigured : + SyncException("Sync is not configured. Please set server URL and auth token.") + object NotConnected : SyncException("Not connected to server. Please test connection first.") + object Unauthorized : SyncException("Unauthorized. Please check your auth token.") + object InvalidURL : SyncException("Invalid server URL.") + data class ServerError(val code: Int) : SyncException("Server error: HTTP $code") + data class InvalidResponse(val details: String) : + SyncException("Invalid server response: $details") + data class DecodingError(val details: String) : + SyncException("Failed to decode server response: $details") + data class ImageNotFound(val filename: String) : SyncException("Image not found: $filename") + data class NetworkError(val details: String) : SyncException("Network error: $details") +} diff --git a/android/app/src/main/java/com/atridad/openclimb/ui/OpenClimbApp.kt b/android/app/src/main/java/com/atridad/openclimb/ui/OpenClimbApp.kt index 83ec388..a8bbca2 100644 --- a/android/app/src/main/java/com/atridad/openclimb/ui/OpenClimbApp.kt +++ b/android/app/src/main/java/com/atridad/openclimb/ui/OpenClimbApp.kt @@ -11,7 +11,6 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.lifecycle.viewmodel.compose.viewModel -import androidx.navigation.NavController import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable @@ -20,6 +19,7 @@ import androidx.navigation.compose.rememberNavController import androidx.navigation.toRoute import com.atridad.openclimb.data.database.OpenClimbDatabase import com.atridad.openclimb.data.repository.ClimbRepository +import com.atridad.openclimb.data.sync.SyncService import com.atridad.openclimb.navigation.Screen import com.atridad.openclimb.navigation.bottomNavigationItems import com.atridad.openclimb.ui.components.NotificationPermissionDialog @@ -43,7 +43,9 @@ fun OpenClimbApp( val database = remember { OpenClimbDatabase.getDatabase(context) } val repository = remember { ClimbRepository(database, context) } - val viewModel: ClimbViewModel = viewModel(factory = ClimbViewModelFactory(repository)) + val syncService = remember { SyncService(context, repository) } + val viewModel: ClimbViewModel = + viewModel(factory = ClimbViewModelFactory(repository, syncService)) // Notification permission state var showNotificationPermissionDialog by remember { mutableStateOf(false) } @@ -73,6 +75,9 @@ fun OpenClimbApp( LaunchedEffect(Unit) { viewModel.ensureSessionTrackingServiceRunning(context) } + // Trigger auto-sync on app launch + LaunchedEffect(Unit) { syncService.triggerAutoSync() } + val activeSession by viewModel.activeSession.collectAsState() val gyms by viewModel.gyms.collectAsState() diff --git a/android/app/src/main/java/com/atridad/openclimb/ui/screens/SettingsScreen.kt b/android/app/src/main/java/com/atridad/openclimb/ui/screens/SettingsScreen.kt index f87eb53..d5ea537 100644 --- a/android/app/src/main/java/com/atridad/openclimb/ui/screens/SettingsScreen.kt +++ b/android/app/src/main/java/com/atridad/openclimb/ui/screens/SettingsScreen.kt @@ -18,412 +18,811 @@ import androidx.compose.ui.unit.dp import com.atridad.openclimb.R import com.atridad.openclimb.ui.viewmodel.ClimbViewModel import java.io.File +import java.time.Instant +import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @Composable -fun SettingsScreen( - viewModel: ClimbViewModel -) { +fun SettingsScreen(viewModel: ClimbViewModel) { val uiState by viewModel.uiState.collectAsState() val context = LocalContext.current - - // State for reset confirmation dialog + val coroutineScope = rememberCoroutineScope() + + // Sync service state + val syncService = viewModel.syncService + val isSyncing by syncService.isSyncing.collectAsState() + val isConnected by syncService.isConnected.collectAsState() + val isTesting by syncService.isTesting.collectAsState() + val lastSyncTime by syncService.lastSyncTime.collectAsState() + val syncError by syncService.syncError.collectAsState() + + // State for dialogs var showResetDialog by remember { mutableStateOf(false) } - - val packageInfo = remember { - context.packageManager.getPackageInfo(context.packageName, 0) - } + var showSyncConfigDialog by remember { mutableStateOf(false) } + var showDisconnectDialog by remember { mutableStateOf(false) } + + // Sync configuration state + var serverUrl by remember { mutableStateOf(syncService.serverURL) } + var authToken by remember { mutableStateOf(syncService.authToken) } + + val packageInfo = remember { context.packageManager.getPackageInfo(context.packageName, 0) } val appVersion = packageInfo.versionName - + // File picker launcher for import - only accepts ZIP files - val importLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.GetContent() - ) { uri -> - uri?.let { - try { - val inputStream = context.contentResolver.openInputStream(uri) - // Determine file extension from content resolver - val fileName = context.contentResolver.query(uri, null, null, null, null)?.use { cursor -> - val nameIndex = cursor.getColumnIndex(android.provider.OpenableColumns.DISPLAY_NAME) - if (nameIndex >= 0 && cursor.moveToFirst()) { - cursor.getString(nameIndex) - } else null - } ?: "import_file" - - // Only allow ZIP files - if (!fileName.lowercase().endsWith(".zip")) { - viewModel.setError("Only ZIP files are supported for import. Please use a ZIP file exported from OpenClimb.") - return@let - } - - val tempFile = File(context.cacheDir, "temp_import.zip") - - inputStream?.use { input -> - tempFile.outputStream().use { output -> - input.copyTo(output) + val importLauncher = + rememberLauncherForActivityResult(contract = ActivityResultContracts.GetContent()) { uri + -> + uri?.let { + try { + val inputStream = context.contentResolver.openInputStream(uri) + // Determine file extension from content resolver + val fileName = + context.contentResolver.query(uri, null, null, null, null)?.use { + cursor -> + val nameIndex = + cursor.getColumnIndex( + android.provider.OpenableColumns.DISPLAY_NAME + ) + if (nameIndex >= 0 && cursor.moveToFirst()) { + cursor.getString(nameIndex) + } else null + } + ?: "import_file" + + // Only allow ZIP files + if (!fileName.lowercase().endsWith(".zip")) { + viewModel.setError( + "Only ZIP files are supported for import. Please use a ZIP file exported from OpenClimb." + ) + return@let + } + + val tempFile = File(context.cacheDir, "temp_import.zip") + + inputStream?.use { input -> + tempFile.outputStream().use { output -> input.copyTo(output) } + } + viewModel.importData(tempFile) + } catch (e: Exception) { + viewModel.setError("Failed to read file: ${e.message}") } } - viewModel.importData(tempFile) - } catch (e: Exception) { - viewModel.setError("Failed to read file: ${e.message}") } - } - } - + // File picker launcher for export - ZIP format with images - val exportZipLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.CreateDocument("application/zip") - ) { uri -> - uri?.let { - try { - viewModel.exportDataToZipUri(context, uri) - } catch (e: Exception) { - viewModel.setError("Failed to save file: ${e.message}") + val exportZipLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.CreateDocument("application/zip") + ) { uri -> + uri?.let { + try { + viewModel.exportDataToZipUri(context, uri) + } catch (e: Exception) { + viewModel.setError("Failed to save file: ${e.message}") + } + } } - } - } - + LazyColumn( - modifier = Modifier - .fillMaxSize() - .padding(16.dp), - verticalArrangement = Arrangement.spacedBy(16.dp) + modifier = Modifier.fillMaxSize().padding(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) ) { item { Row( - modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(12.dp) + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) ) { Icon( - painter = painterResource(id = R.drawable.ic_mountains), - contentDescription = "OpenClimb Logo", - modifier = Modifier.size(32.dp), - tint = MaterialTheme.colorScheme.primary + painter = painterResource(id = R.drawable.ic_mountains), + contentDescription = "OpenClimb Logo", + modifier = Modifier.size(32.dp), + tint = MaterialTheme.colorScheme.primary ) Text( - text = "Settings", - style = MaterialTheme.typography.headlineMedium, - fontWeight = FontWeight.Bold + text = "Settings", + style = MaterialTheme.typography.headlineMedium, + fontWeight = FontWeight.Bold ) } } - + // Data Management Section item { - Card( - modifier = Modifier.fillMaxWidth(), - shape = RoundedCornerShape(16.dp) - ) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp) - ) { + Card(modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp)) { + Column(modifier = Modifier.fillMaxWidth().padding(16.dp)) { Text( - text = "Data Management", - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.Bold + text = "Data Management", + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.Bold ) - + Spacer(modifier = Modifier.height(12.dp)) - - // Export Data + + // Export Data Card( - shape = RoundedCornerShape(12.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f) - ) + shape = RoundedCornerShape(12.dp), + colors = + CardDefaults.cardColors( + containerColor = + MaterialTheme.colorScheme.surfaceVariant.copy( + alpha = 0.3f + ) + ) ) { ListItem( - headlineContent = { Text("Export Data with Images") }, - supportingContent = { Text("Export all your climbing data and images to ZIP file (recommended)") }, - leadingContent = { Icon(Icons.Default.Share, contentDescription = null) }, - trailingContent = { - TextButton( - onClick = { - val defaultFileName = "openclimb_export_${ + headlineContent = { Text("Export Data with Images") }, + supportingContent = { + Text( + "Export all your climbing data and images to ZIP file (recommended)" + ) + }, + leadingContent = { + Icon(Icons.Default.Share, contentDescription = null) + }, + trailingContent = { + TextButton( + onClick = { + val defaultFileName = + "openclimb_export_${ java.time.LocalDateTime.now() .toString() .replace(":", "-") .replace(".", "-") }.zip" - exportZipLauncher.launch(defaultFileName) - }, - enabled = !uiState.isLoading - ) { - if (uiState.isLoading) { - CircularProgressIndicator( - modifier = Modifier.size(16.dp), - strokeWidth = 2.dp - ) - } else { - Text("Export ZIP") + exportZipLauncher.launch(defaultFileName) + }, + enabled = !uiState.isLoading + ) { + if (uiState.isLoading) { + CircularProgressIndicator( + modifier = Modifier.size(16.dp), + strokeWidth = 2.dp + ) + } else { + Text("Export ZIP") + } } } - } ) } - + Spacer(modifier = Modifier.height(8.dp)) - + Card( - shape = RoundedCornerShape(12.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f) - ) + shape = RoundedCornerShape(12.dp), + colors = + CardDefaults.cardColors( + containerColor = + MaterialTheme.colorScheme.surfaceVariant.copy( + alpha = 0.3f + ) + ) ) { ListItem( - headlineContent = { Text("Import Data") }, - supportingContent = { Text("Import climbing data from ZIP file (recommended format)") }, - leadingContent = { Icon(Icons.Default.Add, contentDescription = null) }, - trailingContent = { - TextButton( - onClick = { - importLauncher.launch("application/zip") - }, - enabled = !uiState.isLoading - ) { - if (uiState.isLoading) { - CircularProgressIndicator( - modifier = Modifier.size(16.dp), - strokeWidth = 2.dp - ) - } else { - Text("Import") + headlineContent = { Text("Import Data") }, + supportingContent = { + Text("Import climbing data from ZIP file (recommended format)") + }, + leadingContent = { + Icon(Icons.Default.Add, contentDescription = null) + }, + trailingContent = { + TextButton( + onClick = { importLauncher.launch("application/zip") }, + enabled = !uiState.isLoading + ) { + if (uiState.isLoading) { + CircularProgressIndicator( + modifier = Modifier.size(16.dp), + strokeWidth = 2.dp + ) + } else { + Text("Import") + } } } - } ) } - + Spacer(modifier = Modifier.height(8.dp)) - + Card( - shape = RoundedCornerShape(12.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.errorContainer.copy(alpha = 0.3f) - ) + shape = RoundedCornerShape(12.dp), + colors = + CardDefaults.cardColors( + containerColor = + MaterialTheme.colorScheme.errorContainer.copy( + alpha = 0.3f + ) + ) ) { ListItem( - headlineContent = { Text("Reset All Data") }, - supportingContent = { Text("Permanently delete all gyms, problems, sessions, attempts, and images") }, - leadingContent = { Icon(Icons.Default.Delete, contentDescription = null, tint = MaterialTheme.colorScheme.error) }, - trailingContent = { - TextButton( - onClick = { - showResetDialog = true - }, - enabled = !uiState.isLoading - ) { - if (uiState.isLoading) { - CircularProgressIndicator( - modifier = Modifier.size(16.dp), - strokeWidth = 2.dp - ) - } else { - Text("Reset", color = MaterialTheme.colorScheme.error) + headlineContent = { Text("Reset All Data") }, + supportingContent = { + Text( + "Permanently delete all gyms, problems, sessions, attempts, and images" + ) + }, + leadingContent = { + Icon( + Icons.Default.Delete, + contentDescription = null, + tint = MaterialTheme.colorScheme.error + ) + }, + trailingContent = { + TextButton( + onClick = { showResetDialog = true }, + enabled = !uiState.isLoading + ) { + if (uiState.isLoading) { + CircularProgressIndicator( + modifier = Modifier.size(16.dp), + strokeWidth = 2.dp + ) + } else { + Text("Reset", color = MaterialTheme.colorScheme.error) + } } } - } ) } } } } - + + // Sync Section + item { + Card(modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp)) { + Column(modifier = Modifier.fillMaxWidth().padding(16.dp)) { + Text( + text = "Sync", + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.Bold + ) + + Spacer(modifier = Modifier.height(12.dp)) + + if (syncService.isConfigured) { + // Connected state + Card( + shape = RoundedCornerShape(12.dp), + colors = + CardDefaults.cardColors( + containerColor = + if (isConnected) + MaterialTheme.colorScheme + .primaryContainer.copy( + alpha = 0.3f + ) + else + MaterialTheme.colorScheme + .surfaceVariant.copy( + alpha = 0.3f + ) + ) + ) { + ListItem( + headlineContent = { + Text( + if (isConnected) "Connected to Server" + else "Server Configured" + ) + }, + supportingContent = { + Column { + Text("Server: ${syncService.serverURL}") + lastSyncTime?.let { time -> + Text( + "Last sync: ${ + try { + Instant.parse(time).toString() + } catch (e: Exception) { + time + } + }", + style = MaterialTheme.typography.bodySmall + ) + } + } + }, + leadingContent = { + Icon( + if (isConnected) Icons.Default.CloudDone + else Icons.Default.Cloud, + contentDescription = null, + tint = + if (isConnected) + MaterialTheme.colorScheme.primary + else + MaterialTheme.colorScheme + .onSurfaceVariant + ) + }, + trailingContent = { + Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { + // Manual Sync Button + TextButton( + onClick = { + coroutineScope.launch { + viewModel.performManualSync() + } + }, + enabled = isConnected && !isSyncing + ) { + if (isSyncing) { + CircularProgressIndicator( + modifier = Modifier.size(16.dp), + strokeWidth = 2.dp + ) + } else { + Text("Sync") + } + } + + // Configure Button + TextButton(onClick = { showSyncConfigDialog = true }) { + Text("Configure") + } + } + } + ) + } + + Spacer(modifier = Modifier.height(8.dp)) + + // Auto-sync settings + Card( + shape = RoundedCornerShape(12.dp), + colors = + CardDefaults.cardColors( + containerColor = + MaterialTheme.colorScheme.surfaceVariant + .copy(alpha = 0.3f) + ) + ) { + Column(modifier = Modifier.padding(16.dp)) { + Text( + text = "Sync Mode", + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight.Medium + ) + + Spacer(modifier = Modifier.height(8.dp)) + + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Column(modifier = Modifier.weight(1f)) { + Text("Auto-sync") + Text( + text = + "Sync automatically on app launch and data changes", + style = MaterialTheme.typography.bodySmall, + color = + MaterialTheme.colorScheme.onSurface.copy( + alpha = 0.7f + ), + maxLines = 2 + ) + } + Spacer(modifier = Modifier.width(16.dp)) + Switch( + checked = syncService.isAutoSyncEnabled, + onCheckedChange = { syncService.isAutoSyncEnabled = it } + ) + } + } + } + + Spacer(modifier = Modifier.height(8.dp)) + + // Disconnect option + Card( + shape = RoundedCornerShape(12.dp), + colors = + CardDefaults.cardColors( + containerColor = + MaterialTheme.colorScheme.errorContainer + .copy(alpha = 0.3f) + ) + ) { + ListItem( + headlineContent = { Text("Disconnect") }, + supportingContent = { Text("Clear sync configuration") }, + leadingContent = { + Icon( + Icons.Default.CloudOff, + contentDescription = null, + tint = MaterialTheme.colorScheme.error + ) + }, + trailingContent = { + TextButton(onClick = { showDisconnectDialog = true }) { + Text( + "Disconnect", + color = MaterialTheme.colorScheme.error + ) + } + } + ) + } + } else { + // Not configured state + Card( + shape = RoundedCornerShape(12.dp), + colors = + CardDefaults.cardColors( + containerColor = + MaterialTheme.colorScheme.surfaceVariant + .copy(alpha = 0.3f) + ) + ) { + ListItem( + headlineContent = { Text("Setup Sync") }, + supportingContent = { + Text("Connect to your OpenClimb sync server") + }, + leadingContent = { + Icon(Icons.Default.CloudSync, contentDescription = null) + }, + trailingContent = { + TextButton(onClick = { showSyncConfigDialog = true }) { + Text("Setup") + } + } + ) + } + } + + // Show sync error if any + syncError?.let { error -> + Spacer(modifier = Modifier.height(8.dp)) + Card( + shape = RoundedCornerShape(12.dp), + colors = + CardDefaults.cardColors( + containerColor = + MaterialTheme.colorScheme.errorContainer + ) + ) { + Row( + modifier = Modifier.fillMaxWidth().padding(12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + Icons.Default.Warning, + contentDescription = null, + tint = MaterialTheme.colorScheme.error + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = error, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onErrorContainer + ) + } + } + } + } + } + } + // App Information Section item { - Card( - modifier = Modifier.fillMaxWidth(), - shape = RoundedCornerShape(16.dp) - ) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp) - ) { + Card(modifier = Modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp)) { + Column(modifier = Modifier.fillMaxWidth().padding(16.dp)) { Text( - text = "App Information", - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.Bold + text = "App Information", + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.Bold ) - + Spacer(modifier = Modifier.height(12.dp)) - + Card( - shape = RoundedCornerShape(12.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f) - ) + shape = RoundedCornerShape(12.dp), + colors = + CardDefaults.cardColors( + containerColor = + MaterialTheme.colorScheme.surfaceVariant.copy( + alpha = 0.3f + ) + ) ) { ListItem( - headlineContent = { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - Icon( - painter = painterResource(id = R.drawable.ic_mountains), - contentDescription = "OpenClimb Logo", - modifier = Modifier.size(24.dp), - tint = MaterialTheme.colorScheme.primary - ) - Text("OpenClimb") - } - }, - supportingContent = { Text("Track your climbing progress") }, - leadingContent = { } + headlineContent = { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + painter = + painterResource( + id = R.drawable.ic_mountains + ), + contentDescription = "OpenClimb Logo", + modifier = Modifier.size(24.dp), + tint = MaterialTheme.colorScheme.primary + ) + Text("OpenClimb") + } + }, + supportingContent = { Text("Track your climbing progress") }, + leadingContent = {} ) } - + Spacer(modifier = Modifier.height(8.dp)) - + Card( - shape = RoundedCornerShape(12.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f) - ) + shape = RoundedCornerShape(12.dp), + colors = + CardDefaults.cardColors( + containerColor = + MaterialTheme.colorScheme.surfaceVariant.copy( + alpha = 0.3f + ) + ) ) { ListItem( - headlineContent = { Text("Version") }, - supportingContent = { Text(appVersion ?: "Unknown") }, - leadingContent = { Icon(Icons.Default.Info, contentDescription = null) } + headlineContent = { Text("Version") }, + supportingContent = { Text(appVersion ?: "Unknown") }, + leadingContent = { + Icon(Icons.Default.Info, contentDescription = null) + } ) } } } } - - } - + // Show loading/message states if (uiState.isLoading) { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { CircularProgressIndicator() } } - + uiState.message?.let { message -> LaunchedEffect(message) { kotlinx.coroutines.delay(5000) viewModel.clearMessage() } - + Card( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.primaryContainer - ), - shape = RoundedCornerShape(12.dp) + modifier = Modifier.fillMaxWidth().padding(16.dp), + colors = + CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.primaryContainer + ), + shape = RoundedCornerShape(12.dp) ) { Row( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), - verticalAlignment = Alignment.CenterVertically + modifier = Modifier.fillMaxWidth().padding(16.dp), + verticalAlignment = Alignment.CenterVertically ) { Icon( - Icons.Default.CheckCircle, - contentDescription = null, - tint = MaterialTheme.colorScheme.primary + Icons.Default.CheckCircle, + contentDescription = null, + tint = MaterialTheme.colorScheme.primary ) Spacer(modifier = Modifier.width(8.dp)) Text( - text = message, - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onPrimaryContainer + text = message, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onPrimaryContainer ) } } } - + uiState.error?.let { error -> LaunchedEffect(error) { kotlinx.coroutines.delay(5000) viewModel.clearError() } - + Card( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.errorContainer - ), - shape = RoundedCornerShape(12.dp) + modifier = Modifier.fillMaxWidth().padding(16.dp), + colors = + CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.errorContainer + ), + shape = RoundedCornerShape(12.dp) ) { Row( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), - verticalAlignment = Alignment.CenterVertically + modifier = Modifier.fillMaxWidth().padding(16.dp), + verticalAlignment = Alignment.CenterVertically ) { Icon( - Icons.Default.Warning, - contentDescription = null, - tint = MaterialTheme.colorScheme.error + Icons.Default.Warning, + contentDescription = null, + tint = MaterialTheme.colorScheme.error ) Spacer(modifier = Modifier.width(8.dp)) Text( - text = error, - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onErrorContainer + text = error, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onErrorContainer ) } } } - + // Reset confirmation dialog if (showResetDialog) { AlertDialog( - onDismissRequest = { showResetDialog = false }, - title = { Text("Reset All Data") }, - text = { - Column { - Text("Are you sure you want to reset all data?") - Spacer(modifier = Modifier.height(8.dp)) - Text( - text = "This will permanently delete:", - style = MaterialTheme.typography.bodySmall, - fontWeight = FontWeight.Medium - ) - Spacer(modifier = Modifier.height(4.dp)) - Text( - text = "• All gyms and their information\n• All problems and their images\n• All climbing sessions\n• All attempts and progress data", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.error - ) - Spacer(modifier = Modifier.height(8.dp)) - Text( - text = "This action cannot be undone. Consider exporting your data first.", - style = MaterialTheme.typography.bodySmall, - fontWeight = FontWeight.Medium, - color = MaterialTheme.colorScheme.error - ) - } - }, - confirmButton = { - TextButton( - onClick = { - viewModel.resetAllData() - showResetDialog = false + onDismissRequest = { showResetDialog = false }, + title = { Text("Reset All Data") }, + text = { + Column { + Text("Are you sure you want to reset all data?") + Spacer(modifier = Modifier.height(8.dp)) + Text( + text = "This will permanently delete:", + style = MaterialTheme.typography.bodySmall, + fontWeight = FontWeight.Medium + ) + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = + "• All gyms and their information\n• All problems and their images\n• All climbing sessions\n• All attempts and progress data", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.error + ) + Spacer(modifier = Modifier.height(8.dp)) + Text( + text = + "This action cannot be undone. Consider exporting your data first.", + style = MaterialTheme.typography.bodySmall, + fontWeight = FontWeight.Medium, + color = MaterialTheme.colorScheme.error + ) } - ) { - Text("Reset All Data", color = MaterialTheme.colorScheme.error) + }, + confirmButton = { + TextButton( + onClick = { + viewModel.resetAllData() + showResetDialog = false + } + ) { Text("Reset All Data", color = MaterialTheme.colorScheme.error) } + }, + dismissButton = { + TextButton(onClick = { showResetDialog = false }) { Text("Cancel") } } - }, - dismissButton = { - TextButton(onClick = { showResetDialog = false }) { - Text("Cancel") + ) + } + + // Sync Configuration Dialog + if (showSyncConfigDialog) { + AlertDialog( + onDismissRequest = { showSyncConfigDialog = false }, + title = { Text("Sync Configuration") }, + text = { + Column { + OutlinedTextField( + value = serverUrl, + onValueChange = { serverUrl = it }, + label = { Text("Server URL") }, + placeholder = { Text("https://your-server.com") }, + modifier = Modifier.fillMaxWidth(), + singleLine = true + ) + + Spacer(modifier = Modifier.height(8.dp)) + + OutlinedTextField( + value = authToken, + onValueChange = { authToken = it }, + label = { Text("Auth Token") }, + placeholder = { Text("your-secret-token") }, + modifier = Modifier.fillMaxWidth(), + singleLine = true + ) + + Spacer(modifier = Modifier.height(16.dp)) + + if (syncService.isConfigured) { + Text( + text = "Test connection before enabling sync features", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } else { + Text( + text = "Enter your server URL and auth token to enable sync", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + } + }, + confirmButton = { + Row { + if (syncService.isConfigured) { + TextButton( + onClick = { + coroutineScope.launch { + try { + // Save configuration first + syncService.serverURL = serverUrl.trim() + syncService.authToken = authToken.trim() + viewModel.testSyncConnection() + showSyncConfigDialog = false + } catch (e: Exception) { + // Error will be shown via syncError state + } + } + }, + enabled = + !isTesting && + serverUrl.isNotBlank() && + authToken.isNotBlank() + ) { + if (isTesting) { + CircularProgressIndicator( + modifier = Modifier.size(16.dp), + strokeWidth = 2.dp + ) + } else { + Text("Test Connection") + } + } + + Spacer(modifier = Modifier.width(8.dp)) + } + + TextButton( + onClick = { + syncService.serverURL = serverUrl.trim() + syncService.authToken = authToken.trim() + showSyncConfigDialog = false + }, + enabled = serverUrl.isNotBlank() && authToken.isNotBlank() + ) { Text("Save") } + } + }, + dismissButton = { + TextButton( + onClick = { + // Reset to current values + serverUrl = syncService.serverURL + authToken = syncService.authToken + showSyncConfigDialog = false + } + ) { Text("Cancel") } + } + ) + } + + // Disconnect Dialog + if (showDisconnectDialog) { + AlertDialog( + onDismissRequest = { showDisconnectDialog = false }, + title = { Text("Disconnect from Sync") }, + text = { + Text( + "Are you sure you want to disconnect from the sync server? This will clear your server configuration and disable auto-sync." + ) + }, + confirmButton = { + TextButton( + onClick = { + syncService.clearConfiguration() + serverUrl = "" + authToken = "" + showDisconnectDialog = false + } + ) { Text("Disconnect", color = MaterialTheme.colorScheme.error) } + }, + dismissButton = { + TextButton(onClick = { showDisconnectDialog = false }) { Text("Cancel") } } - } ) } } diff --git a/android/app/src/main/java/com/atridad/openclimb/ui/viewmodel/ClimbViewModel.kt b/android/app/src/main/java/com/atridad/openclimb/ui/viewmodel/ClimbViewModel.kt index 024f789..87c243f 100644 --- a/android/app/src/main/java/com/atridad/openclimb/ui/viewmodel/ClimbViewModel.kt +++ b/android/app/src/main/java/com/atridad/openclimb/ui/viewmodel/ClimbViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.atridad.openclimb.data.model.* import com.atridad.openclimb.data.repository.ClimbRepository +import com.atridad.openclimb.data.sync.SyncService import com.atridad.openclimb.service.SessionTrackingService import com.atridad.openclimb.utils.ImageUtils import com.atridad.openclimb.utils.SessionShareUtils @@ -15,7 +16,8 @@ import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -class ClimbViewModel(private val repository: ClimbRepository) : ViewModel() { +class ClimbViewModel(private val repository: ClimbRepository, val syncService: SyncService) : + ViewModel() { // UI State flows private val _uiState = MutableStateFlow(ClimbUiState()) @@ -112,6 +114,7 @@ class ClimbViewModel(private val repository: ClimbRepository) : ViewModel() { viewModelScope.launch { repository.insertProblem(problem) ClimbStatsWidgetProvider.updateAllWidgets(context) + // Auto-sync now happens automatically via repository callback } } @@ -265,6 +268,8 @@ class ClimbViewModel(private val repository: ClimbRepository) : ViewModel() { ClimbStatsWidgetProvider.updateAllWidgets(context) + // Auto-sync now happens automatically via repository callback + _uiState.value = _uiState.value.copy(message = "Session completed!") } } @@ -290,6 +295,7 @@ class ClimbViewModel(private val repository: ClimbRepository) : ViewModel() { viewModelScope.launch { repository.insertAttempt(attempt) ClimbStatsWidgetProvider.updateAllWidgets(context) + // Auto-sync now happens automatically via repository callback } } @@ -383,6 +389,23 @@ class ClimbViewModel(private val repository: ClimbRepository) : ViewModel() { _uiState.value = _uiState.value.copy(error = null) } + // Sync-related methods + suspend fun performManualSync() { + try { + syncService.syncWithServer() + } catch (e: Exception) { + setError("Sync failed: ${e.message}") + } + } + + suspend fun testSyncConnection() { + try { + syncService.testConnection() + } catch (e: Exception) { + setError("Connection test failed: ${e.message}") + } + } + fun setError(message: String) { _uiState.value = _uiState.value.copy(error = message) } diff --git a/android/app/src/main/java/com/atridad/openclimb/ui/viewmodel/ClimbViewModelFactory.kt b/android/app/src/main/java/com/atridad/openclimb/ui/viewmodel/ClimbViewModelFactory.kt index 1fe048e..ad928b4 100644 --- a/android/app/src/main/java/com/atridad/openclimb/ui/viewmodel/ClimbViewModelFactory.kt +++ b/android/app/src/main/java/com/atridad/openclimb/ui/viewmodel/ClimbViewModelFactory.kt @@ -3,15 +3,17 @@ package com.atridad.openclimb.ui.viewmodel import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import com.atridad.openclimb.data.repository.ClimbRepository +import com.atridad.openclimb.data.sync.SyncService class ClimbViewModelFactory( - private val repository: ClimbRepository + private val repository: ClimbRepository, + private val syncService: SyncService ) : ViewModelProvider.Factory { - + @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T { if (modelClass.isAssignableFrom(ClimbViewModel::class.java)) { - return ClimbViewModel(repository) as T + return ClimbViewModel(repository, syncService) as T } throw IllegalArgumentException("Unknown ViewModel class") } diff --git a/android/app/src/main/java/com/atridad/openclimb/utils/DateFormatUtils.kt b/android/app/src/main/java/com/atridad/openclimb/utils/DateFormatUtils.kt new file mode 100644 index 0000000..d7efbb9 --- /dev/null +++ b/android/app/src/main/java/com/atridad/openclimb/utils/DateFormatUtils.kt @@ -0,0 +1,68 @@ +package com.atridad.openclimb.utils + +import java.time.Instant +import java.time.ZoneOffset +import java.time.format.DateTimeFormatter + +object DateFormatUtils { + + /** + * ISO 8601 formatter matching iOS date format exactly Produces dates like: + * "2025-09-07T22:00:40.014Z" + */ + private val ISO_FORMATTER = + DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX").withZone(ZoneOffset.UTC) + + /** + * Get current timestamp in iOS-compatible ISO 8601 format + * @return Current timestamp as "2025-09-07T22:00:40.014Z" + */ + fun nowISO8601(): String { + return ISO_FORMATTER.format(Instant.now()) + } + + /** + * Format an Instant to iOS-compatible ISO 8601 format + * @param instant The instant to format + * @return Formatted timestamp as "2025-09-07T22:00:40.014Z" + */ + fun formatISO8601(instant: Instant): String { + return ISO_FORMATTER.format(instant) + } + + /** + * Parse an iOS-compatible ISO 8601 date string back to Instant + * @param dateString ISO 8601 formatted date string + * @return Instant object, or null if parsing fails + */ + fun parseISO8601(dateString: String): Instant? { + return try { + Instant.from(ISO_FORMATTER.parse(dateString)) + } catch (e: Exception) { + // Fallback - try standard Instant parsing + try { + Instant.parse(dateString) + } catch (e2: Exception) { + null + } + } + } + + /** + * Validate that a date string matches the expected iOS format + * @param dateString The date string to validate + * @return True if the format matches iOS expectations + */ + fun isValidISO8601(dateString: String): Boolean { + return parseISO8601(dateString) != null + } + + /** + * Convert milliseconds timestamp to iOS-compatible ISO 8601 format + * @param millis Milliseconds since epoch + * @return Formatted timestamp as "2025-09-07T22:00:40.014Z" + */ + fun millisToISO8601(millis: Long): String { + return ISO_FORMATTER.format(Instant.ofEpochMilli(millis)) + } +} diff --git a/android/app/src/main/java/com/atridad/openclimb/utils/ImageNamingUtils.kt b/android/app/src/main/java/com/atridad/openclimb/utils/ImageNamingUtils.kt new file mode 100644 index 0000000..94eac0f --- /dev/null +++ b/android/app/src/main/java/com/atridad/openclimb/utils/ImageNamingUtils.kt @@ -0,0 +1,147 @@ +package com.atridad.openclimb.utils + +import java.security.MessageDigest +import java.util.* + +/** + * Utility for creating consistent image filenames across iOS and Android platforms. Uses + * deterministic naming based on problem ID and timestamp to ensure sync compatibility. + */ +object ImageNamingUtils { + + private const val IMAGE_EXTENSION = ".jpg" + private const val HASH_LENGTH = 12 // First 12 chars of SHA-256 + + /** + * Generates a deterministic filename for a problem image. Format: + * "problem_{problemId}_{timestamp}_{index}.jpg" + * + * @param problemId The ID of the problem this image belongs to + * @param timestamp ISO8601 timestamp when the image was created + * @param imageIndex The index of this image for the problem (0, 1, 2, etc.) + * @return A consistent filename that will be the same across platforms + */ + fun generateImageFilename(problemId: String, timestamp: String, imageIndex: Int): String { + // Create a deterministic hash from problemId + timestamp + index + val input = "${problemId}_${timestamp}_${imageIndex}" + val hash = createHash(input) + + return "problem_${hash}_${imageIndex}${IMAGE_EXTENSION}" + } + + /** + * Generates a deterministic filename for a problem image using current timestamp. + * + * @param problemId The ID of the problem this image belongs to + * @param imageIndex The index of this image for the problem (0, 1, 2, etc.) + * @return A consistent filename + */ + fun generateImageFilename(problemId: String, imageIndex: Int): String { + val timestamp = DateFormatUtils.nowISO8601() + return generateImageFilename(problemId, timestamp, imageIndex) + } + + /** + * Extracts problem ID from an image filename created by this utility. Returns null if the + * filename doesn't match our naming convention. + * + * @param filename The image filename + * @return The problem ID or null if not a valid filename + */ + fun extractProblemIdFromFilename(filename: String): String? { + if (!filename.startsWith("problem_") || !filename.endsWith(IMAGE_EXTENSION)) { + return null + } + + // Format: problem_{hash}_{index}.jpg + val nameWithoutExtension = filename.substring(0, filename.length - IMAGE_EXTENSION.length) + val parts = nameWithoutExtension.split("_") + + if (parts.size != 3 || parts[0] != "problem") { + return null + } + + // We can't extract the original problem ID from the hash, + // but we can validate the format + return parts[1] // Return the hash as identifier + } + + /** + * Validates if a filename follows our naming convention. + * + * @param filename The filename to validate + * @return true if it matches our convention, false otherwise + */ + fun isValidImageFilename(filename: String): Boolean { + if (!filename.startsWith("problem_") || !filename.endsWith(IMAGE_EXTENSION)) { + return false + } + + val nameWithoutExtension = filename.substring(0, filename.length - IMAGE_EXTENSION.length) + val parts = nameWithoutExtension.split("_") + + return parts.size == 3 && + parts[0] == "problem" && + parts[1].length == HASH_LENGTH && + parts[2].toIntOrNull() != null + } + + /** + * Migrates an existing UUID-based filename to our naming convention. This is used during sync + * to rename downloaded images. + * + * @param oldFilename The existing filename (UUID-based) + * @param problemId The problem ID this image belongs to + * @param imageIndex The index of this image + * @return The new filename following our convention + */ + fun migrateFilename(oldFilename: String, problemId: String, imageIndex: Int): String { + // If it's already using our convention, keep it + if (isValidImageFilename(oldFilename)) { + return oldFilename + } + + // Generate new deterministic name + // Use a timestamp based on the old filename to maintain some consistency + val timestamp = DateFormatUtils.nowISO8601() + return generateImageFilename(problemId, timestamp, imageIndex) + } + + /** + * Creates a deterministic hash from input string. Uses SHA-256 and takes first 12 characters + * for filename safety. + * + * @param input The input string to hash + * @return First 12 characters of SHA-256 hash in lowercase + */ + private fun createHash(input: String): String { + val digest = MessageDigest.getInstance("SHA-256") + val hashBytes = digest.digest(input.toByteArray(Charsets.UTF_8)) + val hashHex = hashBytes.joinToString("") { "%02x".format(it) } + return hashHex.take(HASH_LENGTH) + } + + /** + * Batch renames images for a problem to use our naming convention. Returns a mapping of old + * filename -> new filename. + * + * @param problemId The problem ID + * @param existingFilenames List of current image filenames for this problem + * @return Map of old filename to new filename + */ + fun batchRenameForProblem( + problemId: String, + existingFilenames: List + ): Map { + val renameMap = mutableMapOf() + + existingFilenames.forEachIndexed { index, oldFilename -> + val newFilename = migrateFilename(oldFilename, problemId, index) + if (newFilename != oldFilename) { + renameMap[oldFilename] = newFilename + } + } + + return renameMap + } +} diff --git a/android/app/src/main/java/com/atridad/openclimb/utils/ImageUtils.kt b/android/app/src/main/java/com/atridad/openclimb/utils/ImageUtils.kt index e3448ca..78fb3cd 100644 --- a/android/app/src/main/java/com/atridad/openclimb/utils/ImageUtils.kt +++ b/android/app/src/main/java/com/atridad/openclimb/utils/ImageUtils.kt @@ -5,20 +5,18 @@ import android.content.Context import android.graphics.Bitmap import android.graphics.BitmapFactory import android.net.Uri +import androidx.core.graphics.scale import java.io.File import java.io.FileOutputStream import java.util.UUID -import androidx.core.graphics.scale object ImageUtils { - + private const val IMAGES_DIR = "problem_images" private const val MAX_IMAGE_SIZE = 1024 private const val IMAGE_QUALITY = 85 - - /** - * Creates the images directory if it doesn't exist - */ + + /** Creates the images directory if it doesn't exist */ private fun getImagesDirectory(context: Context): File { val imagesDir = File(context.filesDir, IMAGES_DIR) if (!imagesDir.exists()) { @@ -26,25 +24,39 @@ object ImageUtils { } return imagesDir } - + /** - * Saves an image from URI to app's private storage with compression + * Saves an image from a URI with compression and proper orientation * @param context Android context * @param imageUri URI of the image to save + * @param problemId The problem ID this image belongs to (optional) + * @param imageIndex The index of this image for the problem (optional) * @return The relative file path if successful, null otherwise */ - fun saveImageFromUri(context: Context, imageUri: Uri): String? { + fun saveImageFromUri( + context: Context, + imageUri: Uri, + problemId: String? = null, + imageIndex: Int? = null + ): String? { return try { // Decode bitmap from a fresh stream to avoid mark/reset dependency - val originalBitmap = context.contentResolver.openInputStream(imageUri)?.use { input -> - BitmapFactory.decodeStream(input) - } ?: return null + val originalBitmap = + context.contentResolver.openInputStream(imageUri)?.use { input -> + BitmapFactory.decodeStream(input) + } + ?: return null val orientedBitmap = correctImageOrientation(context, imageUri, originalBitmap) val compressedBitmap = compressImage(orientedBitmap) - // Generate unique filename - val filename = "${UUID.randomUUID()}.jpg" + // Generate filename using naming convention if problem info provided + val filename = + if (problemId != null && imageIndex != null) { + ImageNamingUtils.generateImageFilename(problemId, imageIndex) + } else { + "${UUID.randomUUID()}.jpg" + } val imageFile = File(getImagesDirectory(context), filename) // Save compressed image @@ -66,20 +78,19 @@ object ImageUtils { null } } - - /** - * Corrects image orientation based on EXIF data - */ + + /** Corrects image orientation based on EXIF data */ private fun correctImageOrientation(context: Context, imageUri: Uri, bitmap: Bitmap): Bitmap { return try { val inputStream = context.contentResolver.openInputStream(imageUri) inputStream?.use { input -> val exif = android.media.ExifInterface(input) - val orientation = exif.getAttributeInt( - android.media.ExifInterface.TAG_ORIENTATION, - android.media.ExifInterface.ORIENTATION_NORMAL - ) - + val orientation = + exif.getAttributeInt( + android.media.ExifInterface.TAG_ORIENTATION, + android.media.ExifInterface.ORIENTATION_NORMAL + ) + val matrix = android.graphics.Matrix() when (orientation) { android.media.ExifInterface.ORIENTATION_ROTATE_90 -> { @@ -106,36 +117,42 @@ object ImageUtils { matrix.postScale(-1f, 1f) } } - + if (matrix.isIdentity) { bitmap } else { android.graphics.Bitmap.createBitmap( - bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true + bitmap, + 0, + 0, + bitmap.width, + bitmap.height, + matrix, + true ) } - } ?: bitmap + } + ?: bitmap } catch (e: Exception) { e.printStackTrace() bitmap } } - - /** - * Compresses and resizes an image bitmap - */ + + /** Compresses and resizes an image bitmap */ @SuppressLint("UseKtx") private fun compressImage(original: Bitmap): Bitmap { val width = original.width val height = original.height - + // Calculate the scaling factor - val scaleFactor = if (width > height) { - if (width > MAX_IMAGE_SIZE) MAX_IMAGE_SIZE.toFloat() / width else 1f - } else { - if (height > MAX_IMAGE_SIZE) MAX_IMAGE_SIZE.toFloat() / height else 1f - } - + val scaleFactor = + if (width > height) { + if (width > MAX_IMAGE_SIZE) MAX_IMAGE_SIZE.toFloat() / width else 1f + } else { + if (height > MAX_IMAGE_SIZE) MAX_IMAGE_SIZE.toFloat() / height else 1f + } + return if (scaleFactor < 1f) { val newWidth = (width * scaleFactor).toInt() val newHeight = (height * scaleFactor).toInt() @@ -144,7 +161,7 @@ object ImageUtils { original } } - + /** * Gets the full file path for an image * @param context Android context @@ -152,9 +169,16 @@ object ImageUtils { * @return Full file path */ fun getImageFile(context: Context, relativePath: String): File { - return File(context.filesDir, relativePath) + // If relativePath already contains the directory, use it as-is + // Otherwise, assume it's just a filename and add the images directory + return if (relativePath.contains("/")) { + File(context.filesDir, relativePath) + } else { + // Just a filename - look in the images directory + File(getImagesDirectory(context), relativePath) + } } - + /** * Deletes an image file * @param context Android context @@ -180,12 +204,12 @@ object ImageUtils { fun importImageFile(context: Context, sourceFile: File): String? { return try { if (!sourceFile.exists()) return null - + // Generate new filename to avoid conflicts val extension = sourceFile.extension.ifEmpty { "jpg" } val filename = "${UUID.randomUUID()}.$extension" val destFile = File(getImagesDirectory(context), filename) - + sourceFile.copyTo(destFile, overwrite = true) "$IMAGES_DIR/$filename" } catch (e: Exception) { @@ -193,7 +217,7 @@ object ImageUtils { null } } - + /** * Gets all image files in the images directory * @param context Android context @@ -203,16 +227,148 @@ object ImageUtils { return try { val imagesDir = getImagesDirectory(context) imagesDir.listFiles()?.mapNotNull { file -> - if (file.isFile && (file.extension == "jpg" || file.extension == "jpeg" || file.extension == "png")) { + if (file.isFile && + (file.extension == "jpg" || + file.extension == "jpeg" || + file.extension == "png") + ) { "$IMAGES_DIR/${file.name}" } else null - } ?: emptyList() + } + ?: emptyList() } catch (e: Exception) { e.printStackTrace() emptyList() } } - + + /** + * Saves an image from byte array to app's private storage + * @param context Android context + * @param imageData Byte array of the image data + * @return The relative file path if successful, null otherwise + */ + fun saveImageFromBytes(context: Context, imageData: ByteArray): String? { + return try { + val bitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.size) ?: return null + + val compressedBitmap = compressImage(bitmap) + + // Generate unique filename + val filename = "${UUID.randomUUID()}.jpg" + val imageFile = File(getImagesDirectory(context), filename) + + // Save compressed image + FileOutputStream(imageFile).use { output -> + compressedBitmap.compress(Bitmap.CompressFormat.JPEG, IMAGE_QUALITY, output) + } + + // Clean up bitmaps + bitmap.recycle() + compressedBitmap.recycle() + + // Return relative path + "$IMAGES_DIR/$filename" + } catch (e: Exception) { + e.printStackTrace() + null + } + } + + /** + * Saves image data with a specific filename (used for sync to preserve server filenames) + * @param context Android context + * @param imageData The image data as byte array + * @param filename The specific filename to use (including extension) + * @return The relative file path if successful, null otherwise + */ + fun saveImageFromBytesWithFilename( + context: Context, + imageData: ByteArray, + filename: String + ): String? { + return try { + val bitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.size) ?: return null + + val compressedBitmap = compressImage(bitmap) + + // Use the provided filename instead of generating a new UUID + val imageFile = File(getImagesDirectory(context), filename) + + // Save compressed image + FileOutputStream(imageFile).use { output -> + compressedBitmap.compress(Bitmap.CompressFormat.JPEG, IMAGE_QUALITY, output) + } + + // Clean up bitmaps + bitmap.recycle() + compressedBitmap.recycle() + + // Return relative path + "$IMAGES_DIR/$filename" + } catch (e: Exception) { + e.printStackTrace() + null + } + } + + /** + * Migrates existing images to use consistent naming convention + * @param context Android context + * @param problemId The problem ID these images belong to + * @param currentImagePaths List of current image paths for this problem + * @return Map of old path -> new path for successfully migrated images + */ + fun migrateImageNaming( + context: Context, + problemId: String, + currentImagePaths: List + ): Map { + val migrationMap = mutableMapOf() + + currentImagePaths.forEachIndexed { index, oldPath -> + val oldFilename = oldPath.substringAfterLast('/') + val newFilename = ImageNamingUtils.migrateFilename(oldFilename, problemId, index) + + if (oldFilename != newFilename) { + try { + val oldFile = getImageFile(context, oldPath) + val newFile = File(getImagesDirectory(context), newFilename) + + if (oldFile.exists() && oldFile.renameTo(newFile)) { + val newPath = "$IMAGES_DIR/$newFilename" + migrationMap[oldPath] = newPath + } + } catch (e: Exception) { + // Log error but continue with other images + e.printStackTrace() + } + } + } + + return migrationMap + } + + /** + * Batch migrates all images in the system to use consistent naming + * @param context Android context + * @param problemImageMap Map of problem ID -> list of current image paths + * @return Map of old path -> new path for all migrated images + */ + fun batchMigrateAllImages( + context: Context, + problemImageMap: Map> + ): Map { + val allMigrations = mutableMapOf() + + problemImageMap.forEach { (problemId, imagePaths) -> + val migrations = migrateImageNaming(context, problemId, imagePaths) + allMigrations.putAll(migrations) + } + + return allMigrations + } + /** * Cleans up orphaned images that are not referenced by any problems * @param context Android context @@ -222,10 +378,8 @@ object ImageUtils { try { val allImages = getAllImages(context) val orphanedImages = allImages.filter { it !in referencedPaths } - - orphanedImages.forEach { path -> - deleteImage(context, path) - } + + orphanedImages.forEach { path -> deleteImage(context, path) } } catch (e: Exception) { e.printStackTrace() } diff --git a/android/app/src/test/java/com/atridad/openclimb/SyncMergeLogicTest.kt b/android/app/src/test/java/com/atridad/openclimb/SyncMergeLogicTest.kt new file mode 100644 index 0000000..fd687c9 --- /dev/null +++ b/android/app/src/test/java/com/atridad/openclimb/SyncMergeLogicTest.kt @@ -0,0 +1,451 @@ +package com.atridad.openclimb + +import com.atridad.openclimb.data.format.* +import com.atridad.openclimb.data.model.* +import org.junit.Assert.* +import org.junit.Test + +class SyncMergeLogicTest { + + @Test + fun `test intelligent merge preserves all data`() { + // Create local data + val localGyms = + listOf( + BackupGym( + id = "gym1", + name = "Local Gym 1", + location = "Local Location", + supportedClimbTypes = listOf(ClimbType.BOULDER), + difficultySystems = listOf(DifficultySystem.V_SCALE), + customDifficultyGrades = emptyList(), + notes = null, + createdAt = "2024-01-01T10:00:00", + updatedAt = "2024-01-01T10:00:00" + ) + ) + + val localProblems = + listOf( + BackupProblem( + id = "problem1", + gymId = "gym1", + name = "Local Problem", + description = "Local description", + climbType = ClimbType.BOULDER, + difficulty = DifficultyGrade(DifficultySystem.V_SCALE, "V5"), + tags = listOf("local"), + location = null, + imagePaths = listOf("local_image.jpg"), + isActive = true, + dateSet = null, + notes = null, + createdAt = "2024-01-01T10:00:00", + updatedAt = "2024-01-01T10:00:00" + ) + ) + + val localSessions = + listOf( + BackupClimbSession( + id = "session1", + gymId = "gym1", + date = "2024-01-01", + startTime = "2024-01-01T10:00:00", + endTime = "2024-01-01T12:00:00", + duration = 7200, + status = SessionStatus.COMPLETED, + notes = null, + createdAt = "2024-01-01T10:00:00", + updatedAt = "2024-01-01T10:00:00" + ) + ) + + val localAttempts = + listOf( + BackupAttempt( + id = "attempt1", + sessionId = "session1", + problemId = "problem1", + result = AttemptResult.COMPLETED, + highestHold = null, + notes = null, + duration = 300, + restTime = null, + timestamp = "2024-01-01T10:30:00", + createdAt = "2024-01-01T10:30:00" + ) + ) + + val localBackup = + ClimbDataBackup( + exportedAt = "2024-01-01T10:00:00", + version = "2.0", + formatVersion = "2.0", + gyms = localGyms, + problems = localProblems, + sessions = localSessions, + attempts = localAttempts + ) + + // Create server data with some overlapping and some unique data + val serverGyms = + listOf( + // Same gym but with newer update + BackupGym( + id = "gym1", + name = "Updated Gym 1", + location = "Updated Location", + supportedClimbTypes = listOf(ClimbType.BOULDER, ClimbType.SPORT), + difficultySystems = + listOf(DifficultySystem.V_SCALE, DifficultySystem.YDS), + customDifficultyGrades = emptyList(), + notes = "Updated notes", + createdAt = "2024-01-01T10:00:00", + updatedAt = "2024-01-01T12:00:00" // Newer update + ), + // Unique server gym + BackupGym( + id = "gym2", + name = "Server Gym 2", + location = "Server Location", + supportedClimbTypes = listOf(ClimbType.TRAD), + difficultySystems = listOf(DifficultySystem.YDS), + customDifficultyGrades = emptyList(), + notes = null, + createdAt = "2024-01-01T11:00:00", + updatedAt = "2024-01-01T11:00:00" + ) + ) + + val serverProblems = + listOf( + // Same problem but with newer update and different images + BackupProblem( + id = "problem1", + gymId = "gym1", + name = "Updated Problem", + description = "Updated description", + climbType = ClimbType.BOULDER, + difficulty = DifficultyGrade(DifficultySystem.V_SCALE, "V5"), + tags = listOf("updated", "server"), + location = "Updated location", + imagePaths = listOf("server_image.jpg"), + isActive = true, + dateSet = "2024-01-01", + notes = "Updated notes", + createdAt = "2024-01-01T10:00:00", + updatedAt = "2024-01-01T11:00:00" // Newer update + ), + // Unique server problem + BackupProblem( + id = "problem2", + gymId = "gym2", + name = "Server Problem", + description = "Server description", + climbType = ClimbType.TRAD, + difficulty = DifficultyGrade(DifficultySystem.YDS, "5.10a"), + tags = listOf("server"), + location = null, + imagePaths = null, + isActive = true, + dateSet = null, + notes = null, + createdAt = "2024-01-01T11:00:00", + updatedAt = "2024-01-01T11:00:00" + ) + ) + + val serverSessions = + listOf( + // Unique server session + BackupClimbSession( + id = "session2", + gymId = "gym2", + date = "2024-01-02", + startTime = "2024-01-02T14:00:00", + endTime = "2024-01-02T16:00:00", + duration = 7200, + status = SessionStatus.COMPLETED, + notes = "Server session", + createdAt = "2024-01-02T14:00:00", + updatedAt = "2024-01-02T14:00:00" + ) + ) + + val serverAttempts = + listOf( + // Unique server attempt + BackupAttempt( + id = "attempt2", + sessionId = "session2", + problemId = "problem2", + result = AttemptResult.FELL, + highestHold = "Last move", + notes = "Almost had it", + duration = 180, + restTime = 60, + timestamp = "2024-01-02T14:30:00", + createdAt = "2024-01-02T14:30:00" + ) + ) + + val serverBackup = + ClimbDataBackup( + exportedAt = "2024-01-01T12:00:00", + version = "2.0", + formatVersion = "2.0", + gyms = serverGyms, + problems = serverProblems, + sessions = serverSessions, + attempts = serverAttempts + ) + + // Simulate merge logic + val mergedBackup = performIntelligentMerge(localBackup, serverBackup) + + // Verify merge results + assertEquals("Should have 2 gyms (1 updated, 1 new)", 2, mergedBackup.gyms.size) + assertEquals("Should have 2 problems (1 updated, 1 new)", 2, mergedBackup.problems.size) + assertEquals("Should have 2 sessions (1 local, 1 server)", 2, mergedBackup.sessions.size) + assertEquals("Should have 2 attempts (1 local, 1 server)", 2, mergedBackup.attempts.size) + + // Verify gym merge - server version should win (newer update) + val mergedGym1 = mergedBackup.gyms.find { it.id == "gym1" }!! + assertEquals("Updated Gym 1", mergedGym1.name) + assertEquals("Updated Location", mergedGym1.location) + assertEquals("Updated notes", mergedGym1.notes) + assertEquals("2024-01-01T12:00:00", mergedGym1.updatedAt) + + // Verify unique server gym is preserved + val mergedGym2 = mergedBackup.gyms.find { it.id == "gym2" }!! + assertEquals("Server Gym 2", mergedGym2.name) + + // Verify problem merge - server version should win but images should be merged + val mergedProblem1 = mergedBackup.problems.find { it.id == "problem1" }!! + assertEquals("Updated Problem", mergedProblem1.name) + assertEquals("Updated description", mergedProblem1.description) + assertEquals("2024-01-01T11:00:00", mergedProblem1.updatedAt) + + // Images should be merged (both local and server images preserved) + assertTrue( + "Should contain local image", + mergedProblem1.imagePaths!!.contains("local_image.jpg") + ) + assertTrue( + "Should contain server image", + mergedProblem1.imagePaths!!.contains("server_image.jpg") + ) + assertEquals("Should have 2 images total", 2, mergedProblem1.imagePaths!!.size) + + // Verify unique server problem is preserved + val mergedProblem2 = mergedBackup.problems.find { it.id == "problem2" }!! + assertEquals("Server Problem", mergedProblem2.name) + + // Verify all sessions are preserved + assertTrue( + "Should contain local session", + mergedBackup.sessions.any { it.id == "session1" } + ) + assertTrue( + "Should contain server session", + mergedBackup.sessions.any { it.id == "session2" } + ) + + // Verify all attempts are preserved + assertTrue( + "Should contain local attempt", + mergedBackup.attempts.any { it.id == "attempt1" } + ) + assertTrue( + "Should contain server attempt", + mergedBackup.attempts.any { it.id == "attempt2" } + ) + } + + @Test + fun `test date comparison logic`() { + assertTrue( + "ISO instant should be newer", + isNewerThan("2024-01-01T12:00:00Z", "2024-01-01T10:00:00Z") + ) + assertFalse( + "ISO instant should be older", + isNewerThan("2024-01-01T10:00:00Z", "2024-01-01T12:00:00Z") + ) + assertTrue( + "String comparison should work as fallback", + isNewerThan("2024-01-02T10:00:00", "2024-01-01T10:00:00") + ) + } + + @Test + fun `test empty data scenarios`() { + val emptyBackup = + ClimbDataBackup( + exportedAt = "2024-01-01T10:00:00", + version = "2.0", + formatVersion = "2.0", + gyms = emptyList(), + problems = emptyList(), + sessions = emptyList(), + attempts = emptyList() + ) + + val dataBackup = + ClimbDataBackup( + exportedAt = "2024-01-01T10:00:00", + version = "2.0", + formatVersion = "2.0", + gyms = + listOf( + BackupGym( + id = "gym1", + name = "Test Gym", + location = null, + supportedClimbTypes = listOf(ClimbType.BOULDER), + difficultySystems = + listOf(DifficultySystem.V_SCALE), + customDifficultyGrades = emptyList(), + notes = null, + createdAt = "2024-01-01T10:00:00", + updatedAt = "2024-01-01T10:00:00" + ) + ), + problems = emptyList(), + sessions = emptyList(), + attempts = emptyList() + ) + + // Test merging empty with data + val merged1 = performIntelligentMerge(emptyBackup, dataBackup) + assertEquals("Should preserve data from non-empty backup", 1, merged1.gyms.size) + + // Test merging data with empty + val merged2 = performIntelligentMerge(dataBackup, emptyBackup) + assertEquals("Should preserve data from non-empty backup", 1, merged2.gyms.size) + + // Test merging empty with empty + val merged3 = performIntelligentMerge(emptyBackup, emptyBackup) + assertEquals("Should remain empty", 0, merged3.gyms.size) + } + + // Helper methods that simulate the merge logic from SyncService + private fun performIntelligentMerge( + local: ClimbDataBackup, + server: ClimbDataBackup + ): ClimbDataBackup { + val mergedGyms = mergeGyms(local.gyms, server.gyms) + val mergedProblems = mergeProblems(local.problems, server.problems) + val mergedSessions = mergeSessions(local.sessions, server.sessions) + val mergedAttempts = mergeAttempts(local.attempts, server.attempts) + + return ClimbDataBackup( + exportedAt = "2024-01-01T12:00:00", + version = "2.0", + formatVersion = "2.0", + gyms = mergedGyms, + problems = mergedProblems, + sessions = mergedSessions, + attempts = mergedAttempts + ) + } + + private fun mergeGyms(local: List, server: List): List { + val merged = mutableMapOf() + + // Add all local gyms + local.forEach { gym -> merged[gym.id] = gym } + + // Add server gyms, preferring newer updates + server.forEach { serverGym -> + val localGym = merged[serverGym.id] + if (localGym == null || isNewerThan(serverGym.updatedAt, localGym.updatedAt)) { + merged[serverGym.id] = serverGym + } + } + + return merged.values.toList() + } + + private fun mergeProblems( + local: List, + server: List + ): List { + val merged = mutableMapOf() + + // Add all local problems + local.forEach { problem -> merged[problem.id] = problem } + + // Add server problems, preferring newer updates + server.forEach { serverProblem -> + val localProblem = merged[serverProblem.id] + if (localProblem == null || isNewerThan(serverProblem.updatedAt, localProblem.updatedAt) + ) { + // Merge image paths to preserve all images + val allImagePaths = mutableSetOf() + localProblem?.imagePaths?.let { allImagePaths.addAll(it) } + serverProblem.imagePaths?.let { allImagePaths.addAll(it) } + + merged[serverProblem.id] = + serverProblem.withUpdatedImagePaths(allImagePaths.toList()) + } + } + + return merged.values.toList() + } + + private fun mergeSessions( + local: List, + server: List + ): List { + val merged = mutableMapOf() + + // Add all local sessions + local.forEach { session -> merged[session.id] = session } + + // Add server sessions, preferring newer updates + server.forEach { serverSession -> + val localSession = merged[serverSession.id] + if (localSession == null || isNewerThan(serverSession.updatedAt, localSession.updatedAt) + ) { + merged[serverSession.id] = serverSession + } + } + + return merged.values.toList() + } + + private fun mergeAttempts( + local: List, + server: List + ): List { + val merged = mutableMapOf() + + // Add all local attempts + local.forEach { attempt -> merged[attempt.id] = attempt } + + // Add server attempts, preferring newer updates + server.forEach { serverAttempt -> + val localAttempt = merged[serverAttempt.id] + if (localAttempt == null || isNewerThan(serverAttempt.createdAt, localAttempt.createdAt) + ) { + merged[serverAttempt.id] = serverAttempt + } + } + + return merged.values.toList() + } + + private fun isNewerThan(dateString1: String, dateString2: String): Boolean { + return try { + // Try parsing as instant first + val date1 = java.time.Instant.parse(dateString1) + val date2 = java.time.Instant.parse(dateString2) + date1.isAfter(date2) + } catch (e: Exception) { + // Fallback to string comparison + dateString1 > dateString2 + } + } +} diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index 38d2547..8b50bce 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -19,6 +19,7 @@ kotlinxSerialization = "1.9.0" kotlinxCoroutines = "1.10.2" coil = "2.7.0" ksp = "2.2.10-2.0.2" +okhttp = "4.12.0" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -65,6 +66,9 @@ mockk = { group = "io.mockk", name = "mockk", version = "1.14.5" } # Image Loading coil-compose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil" } +# HTTP Client +okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" } + [plugins] diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..178a980 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.jar @@ -0,0 +1,16 @@ + +404 Not Found + +

404 Not Found

+
nginx
+ + + + + + + + + + + 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 2f1b85e4b9d66a00a2d408c8053a913a3f8012f7..de72ced2219c65201568ca9c1dc04cd8862ff5b3 100644 GIT binary patch literal 124304 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 Xesh5z@j|NlRS8eRE6U59(z diff --git a/ios/OpenClimb.xcodeproj/xcshareddata/xcschemes/OpenClimb.xcscheme b/ios/OpenClimb.xcodeproj/xcshareddata/xcschemes/OpenClimb.xcscheme index e69de29..60b8335 100644 --- a/ios/OpenClimb.xcodeproj/xcshareddata/xcschemes/OpenClimb.xcscheme +++ b/ios/OpenClimb.xcodeproj/xcshareddata/xcschemes/OpenClimb.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/OpenClimb/ContentView.swift b/ios/OpenClimb/ContentView.swift index ea9c62f..9ced8fa 100644 --- a/ios/OpenClimb/ContentView.swift +++ b/ios/OpenClimb/ContentView.swift @@ -57,6 +57,8 @@ struct ContentView: View { } .onAppear { setupNotificationObservers() + // Trigger auto-sync on app launch + dataManager.syncService.triggerAutoSync(dataManager: dataManager) } .onDisappear { removeNotificationObservers() @@ -101,6 +103,8 @@ struct ContentView: View { Task { try? await Task.sleep(nanoseconds: 300_000_000) // 0.3 seconds await dataManager.onAppBecomeActive() + // Trigger auto-sync when app becomes active + dataManager.syncService.triggerAutoSync(dataManager: dataManager) } } diff --git a/ios/OpenClimb/Models/BackupFormat.swift b/ios/OpenClimb/Models/BackupFormat.swift index 1a0f95a..a0dcb3c 100644 --- a/ios/OpenClimb/Models/BackupFormat.swift +++ b/ios/OpenClimb/Models/BackupFormat.swift @@ -1,10 +1,5 @@ // // BackupFormat.swift -// OpenClimb -// -// Created by OpenClimb Team on 2024-12-19. -// Copyright © 2024 OpenClimb. All rights reserved. -// import Foundation diff --git a/ios/OpenClimb/Services/SyncService.swift b/ios/OpenClimb/Services/SyncService.swift new file mode 100644 index 0000000..61e4635 --- /dev/null +++ b/ios/OpenClimb/Services/SyncService.swift @@ -0,0 +1,978 @@ +import Combine +import Foundation +import UIKit + +@MainActor +class SyncService: ObservableObject { + + @Published var isSyncing = false + @Published var lastSyncTime: Date? + @Published var syncError: String? + @Published var isConnected = false + @Published var isTesting = false + + private let userDefaults = UserDefaults.standard + + private enum Keys { + static let serverURL = "sync_server_url" + static let authToken = "sync_auth_token" + static let lastSyncTime = "last_sync_time" + static let isConnected = "sync_is_connected" + static let autoSyncEnabled = "auto_sync_enabled" + } + + var serverURL: String { + get { userDefaults.string(forKey: Keys.serverURL) ?? "" } + set { userDefaults.set(newValue, forKey: Keys.serverURL) } + } + + var authToken: String { + get { userDefaults.string(forKey: Keys.authToken) ?? "" } + set { userDefaults.set(newValue, forKey: Keys.authToken) } + } + + var isConfigured: Bool { + return !serverURL.isEmpty && !authToken.isEmpty + } + + var isAutoSyncEnabled: Bool { + get { userDefaults.bool(forKey: Keys.autoSyncEnabled) } + set { userDefaults.set(newValue, forKey: Keys.autoSyncEnabled) } + } + + init() { + if let lastSync = userDefaults.object(forKey: Keys.lastSyncTime) as? Date { + self.lastSyncTime = lastSync + } + self.isConnected = userDefaults.bool(forKey: Keys.isConnected) + } + + func downloadData() async throws -> ClimbDataBackup { + guard isConfigured else { + throw SyncError.notConfigured + } + + guard let url = URL(string: "\(serverURL)/sync") else { + throw SyncError.invalidURL + } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + request.setValue("Bearer \(authToken)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Accept") + + let (data, response) = try await URLSession.shared.data(for: request) + + guard let httpResponse = response as? HTTPURLResponse else { + throw SyncError.invalidResponse + } + + switch httpResponse.statusCode { + case 200: + break + case 401: + throw SyncError.unauthorized + default: + throw SyncError.serverError(httpResponse.statusCode) + } + + do { + let backup = try JSONDecoder().decode(ClimbDataBackup.self, from: data) + return backup + } catch { + throw SyncError.decodingError(error) + } + } + + func uploadData(_ backup: ClimbDataBackup) async throws -> ClimbDataBackup { + guard isConfigured else { + throw SyncError.notConfigured + } + + guard let url = URL(string: "\(serverURL)/sync") else { + throw SyncError.invalidURL + } + + let encoder = JSONEncoder() + encoder.dateEncodingStrategy = .iso8601 + + let jsonData = try encoder.encode(backup) + + var request = URLRequest(url: url) + request.httpMethod = "PUT" + request.setValue("Bearer \(authToken)", forHTTPHeaderField: "Authorization") + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.httpBody = jsonData + + let (data, response) = try await URLSession.shared.data(for: request) + + guard let httpResponse = response as? HTTPURLResponse else { + throw SyncError.invalidResponse + } + + switch httpResponse.statusCode { + case 200: + break + case 401: + throw SyncError.unauthorized + case 400: + throw SyncError.badRequest + default: + throw SyncError.serverError(httpResponse.statusCode) + } + + do { + let responseBackup = try JSONDecoder().decode(ClimbDataBackup.self, from: data) + return responseBackup + } catch { + throw SyncError.decodingError(error) + } + } + + func uploadImage(filename: String, imageData: Data) async throws { + guard isConfigured else { + throw SyncError.notConfigured + } + + guard let url = URL(string: "\(serverURL)/images/upload?filename=\(filename)") else { + throw SyncError.invalidURL + } + + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.setValue("Bearer \(authToken)", forHTTPHeaderField: "Authorization") + request.setValue("application/octet-stream", forHTTPHeaderField: "Content-Type") + request.httpBody = imageData + + let (_, response) = try await URLSession.shared.data(for: request) + + guard let httpResponse = response as? HTTPURLResponse else { + throw SyncError.invalidResponse + } + + switch httpResponse.statusCode { + case 200: + break + case 401: + throw SyncError.unauthorized + default: + throw SyncError.serverError(httpResponse.statusCode) + } + } + + func downloadImage(filename: String) async throws -> Data { + guard isConfigured else { + throw SyncError.notConfigured + } + + guard let url = URL(string: "\(serverURL)/images/download?filename=\(filename)") else { + throw SyncError.invalidURL + } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + request.setValue("Bearer \(authToken)", forHTTPHeaderField: "Authorization") + + let (data, response) = try await URLSession.shared.data(for: request) + + guard let httpResponse = response as? HTTPURLResponse else { + + throw SyncError.invalidResponse + } + + switch httpResponse.statusCode { + case 200: + + return data + case 401: + + throw SyncError.unauthorized + case 404: + + throw SyncError.imageNotFound + default: + + throw SyncError.serverError(httpResponse.statusCode) + } + } + + func syncWithServer(dataManager: ClimbingDataManager) async throws { + guard isConfigured else { + throw SyncError.notConfigured + } + + guard isConnected else { + throw SyncError.notConnected + } + + isSyncing = true + syncError = nil + + defer { + isSyncing = false + } + + do { + // Get local backup data + let localBackup = createBackupFromDataManager(dataManager) + + // Download server data + let serverBackup = try await downloadData() + + // Check if we have any local data + let hasLocalData = + !dataManager.gyms.isEmpty || !dataManager.problems.isEmpty + || !dataManager.sessions.isEmpty || !dataManager.attempts.isEmpty + + let hasServerData = + !serverBackup.gyms.isEmpty || !serverBackup.problems.isEmpty + || !serverBackup.sessions.isEmpty || !serverBackup.attempts.isEmpty + + if !hasLocalData && hasServerData { + // Case 1: No local data - do full restore from server + print("🔄 iOS SYNC: Case 1 - No local data, performing full restore from server") + print("Syncing images from server first...") + let imagePathMapping = try await syncImagesFromServer( + backup: serverBackup, dataManager: dataManager) + print("Importing data after images...") + try importBackupToDataManager( + serverBackup, dataManager: dataManager, imagePathMapping: imagePathMapping) + print("Full restore completed") + } else if hasLocalData && !hasServerData { + // Case 2: No server data - upload local data to server + print("🔄 iOS SYNC: Case 2 - No server data, uploading local data to server") + let currentBackup = createBackupFromDataManager(dataManager) + _ = try await uploadData(currentBackup) + print("Uploading local images to server...") + try await syncImagesToServer(dataManager: dataManager) + print("Initial upload completed") + } else if hasLocalData && hasServerData { + // Case 3: Both have data - compare timestamps (last writer wins) + let localTimestamp = parseISO8601ToMillis(timestamp: localBackup.exportedAt) + let serverTimestamp = parseISO8601ToMillis(timestamp: serverBackup.exportedAt) + + print("🕐 DEBUG iOS Timestamp Comparison:") + print(" Local exportedAt: '\(localBackup.exportedAt)' -> \(localTimestamp)") + print(" Server exportedAt: '\(serverBackup.exportedAt)' -> \(serverTimestamp)") + print( + " DataStateManager last modified: '\(DataStateManager.shared.getLastModified())'" + ) + print(" Comparison result: local=\(localTimestamp), server=\(serverTimestamp)") + + if localTimestamp > serverTimestamp { + // Local is newer - replace server with local data + print("🔄 iOS SYNC: Case 3a - Local data is newer, replacing server content") + let currentBackup = createBackupFromDataManager(dataManager) + _ = try await uploadData(currentBackup) + try await syncImagesToServer(dataManager: dataManager) + print("Server replaced with local data") + } else if serverTimestamp > localTimestamp { + // Server is newer - replace local with server data + print("🔄 iOS SYNC: Case 3b - Server data is newer, replacing local content") + let imagePathMapping = try await syncImagesFromServer( + backup: serverBackup, dataManager: dataManager) + try importBackupToDataManager( + serverBackup, dataManager: dataManager, imagePathMapping: imagePathMapping) + print("Local data replaced with server data") + } else { + // Timestamps are equal - no sync needed + print( + "🔄 iOS SYNC: Case 3c - Data is in sync (timestamps equal), no action needed" + ) + } + } else { + print("No data to sync") + } + + // Update last sync time + lastSyncTime = Date() + userDefaults.set(lastSyncTime, forKey: Keys.lastSyncTime) + + } catch { + syncError = error.localizedDescription + throw error + } + } + + /// Parses ISO8601 timestamp to milliseconds for comparison + private func parseISO8601ToMillis(timestamp: String) -> Int64 { + let formatter = ISO8601DateFormatter() + if let date = formatter.date(from: timestamp) { + return Int64(date.timeIntervalSince1970 * 1000) + } + print("Failed to parse timestamp: \(timestamp), using 0") + return 0 + } + + private func syncImagesFromServer(backup: ClimbDataBackup, dataManager: ClimbingDataManager) + async throws -> [String: String] + { + var imagePathMapping: [String: String] = [:] + + // Process images by problem to maintain consistent naming + for problem in backup.problems { + guard let imagePaths = problem.imagePaths, !imagePaths.isEmpty else { continue } + + for (index, imagePath) in imagePaths.enumerated() { + let serverFilename = URL(fileURLWithPath: imagePath).lastPathComponent + + do { + let imageData = try await downloadImage(filename: serverFilename) + + // Generate consistent filename if needed + let consistentFilename = + ImageNamingUtils.isValidImageFilename(serverFilename) + ? serverFilename + : ImageNamingUtils.generateImageFilename( + problemId: problem.id, imageIndex: index) + + // Save image with consistent filename + let imageManager = ImageManager.shared + let localPath = try imageManager.saveImportedImage( + imageData, filename: consistentFilename) + + // Map server filename to consistent local filename + imagePathMapping[serverFilename] = consistentFilename + print("Downloaded and mapped image: \(serverFilename) -> \(consistentFilename)") + } catch SyncError.imageNotFound { + print("Image not found on server: \(serverFilename)") + continue + } catch { + print("Failed to download image \(serverFilename): \(error)") + continue + } + } + } + + return imagePathMapping + } + + private func syncImagesToServer(dataManager: ClimbingDataManager) async throws { + // Process images by problem to ensure consistent naming + for problem in dataManager.problems { + guard !problem.imagePaths.isEmpty else { continue } + + for (index, imagePath) in problem.imagePaths.enumerated() { + let filename = URL(fileURLWithPath: imagePath).lastPathComponent + + // Ensure filename follows consistent naming convention + let consistentFilename = + ImageNamingUtils.isValidImageFilename(filename) + ? filename + : ImageNamingUtils.generateImageFilename( + problemId: problem.id.uuidString, imageIndex: index) + + // Load image data + let imageManager = ImageManager.shared + let fullPath = imageManager.imagesDirectory.appendingPathComponent(filename).path + + if let imageData = imageManager.loadImageData(fromPath: fullPath) { + do { + // If filename changed, rename local file + if filename != consistentFilename { + let newPath = imageManager.imagesDirectory.appendingPathComponent( + consistentFilename + ).path + do { + try FileManager.default.moveItem(atPath: fullPath, toPath: newPath) + print("Renamed local image: \(filename) -> \(consistentFilename)") + + // Update problem's image path in memory for consistency + // Note: This would require updating the problem in the data manager + } catch { + print("Failed to rename local image, using original: \(error)") + } + } + + try await uploadImage(filename: consistentFilename, imageData: imageData) + print("Successfully uploaded image: \(consistentFilename)") + } catch { + print("Failed to upload image \(consistentFilename): \(error)") + // Continue with other images even if one fails + } + } + } + } + } + + private func createBackupFromDataManager(_ dataManager: ClimbingDataManager) -> ClimbDataBackup + { + return ClimbDataBackup( + exportedAt: DataStateManager.shared.getLastModified(), + gyms: dataManager.gyms.map { BackupGym(from: $0) }, + problems: dataManager.problems.map { BackupProblem(from: $0) }, + sessions: dataManager.sessions.map { BackupClimbSession(from: $0) }, + attempts: dataManager.attempts.map { BackupAttempt(from: $0) } + ) + } + + private func importBackupToDataManager( + _ backup: ClimbDataBackup, dataManager: ClimbingDataManager, + imagePathMapping: [String: String] = [:] + ) throws { + do { + + // Update problem image paths to point to downloaded images + let updatedBackup: ClimbDataBackup + if !imagePathMapping.isEmpty { + let updatedProblems = backup.problems.map { problem in + let updatedImagePaths = problem.imagePaths?.compactMap { oldPath in + imagePathMapping[oldPath] ?? oldPath + } + return BackupProblem( + id: problem.id, + gymId: problem.gymId, + name: problem.name, + description: problem.description, + climbType: problem.climbType, + difficulty: problem.difficulty, + tags: problem.tags, + location: problem.location, + imagePaths: updatedImagePaths, + isActive: problem.isActive, + dateSet: problem.dateSet, + notes: problem.notes, + createdAt: problem.createdAt, + updatedAt: problem.updatedAt + ) + } + updatedBackup = ClimbDataBackup( + exportedAt: backup.exportedAt, + version: backup.version, + formatVersion: backup.formatVersion, + gyms: backup.gyms, + problems: updatedProblems, + sessions: backup.sessions, + attempts: backup.attempts + ) + + } else { + updatedBackup = backup + } + + // Create a minimal ZIP with just the JSON data for existing import mechanism + let zipData = try createMinimalZipFromBackup(updatedBackup) + + // Use existing import method which properly handles data restoration + try dataManager.importData(from: zipData) + + // Update local data state to match imported data timestamp + DataStateManager.shared.setLastModified(backup.exportedAt) + print("Data state synchronized to imported timestamp: \(backup.exportedAt)") + + } catch { + + throw SyncError.importFailed(error) + } + } + + private func createMinimalZipFromBackup(_ backup: ClimbDataBackup) throws -> Data { + // Create JSON data + + let encoder = JSONEncoder() + encoder.outputFormatting = .prettyPrinted + encoder.dateEncodingStrategy = .custom { date, encoder in + let formatter = DateFormatter() + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS" + var container = encoder.singleValueContainer() + try container.encode(formatter.string(from: date)) + } + let jsonData = try encoder.encode(backup) + + // Collect all downloaded images from ImageManager + let imageManager = ImageManager.shared + var imageFiles: [(filename: String, data: Data)] = [] + let imagePaths = Set(backup.problems.flatMap { $0.imagePaths ?? [] }) + + for imagePath in imagePaths { + let filename = URL(fileURLWithPath: imagePath).lastPathComponent + let fullPath = imageManager.imagesDirectory.appendingPathComponent(filename).path + if let imageData = imageManager.loadImageData(fromPath: fullPath) { + imageFiles.append((filename: filename, data: imageData)) + + } + } + + // Create ZIP with data.json, metadata, and images + var zipData = Data() + var fileEntries: [(name: String, data: Data, offset: UInt32)] = [] + var currentOffset: UInt32 = 0 + + // Add data.json to ZIP + try addFileToMinimalZip( + filename: "data.json", + fileData: jsonData, + zipData: &zipData, + fileEntries: &fileEntries, + currentOffset: ¤tOffset + ) + + // Add metadata with correct image count + let metadata = "export_version=2.0\nformat_version=2.0\nimage_count=\(imageFiles.count)" + let metadataData = metadata.data(using: .utf8) ?? Data() + try addFileToMinimalZip( + filename: "metadata.txt", + fileData: metadataData, + zipData: &zipData, + fileEntries: &fileEntries, + currentOffset: ¤tOffset + ) + + // Add images to ZIP in images/ directory + for imageFile in imageFiles { + try addFileToMinimalZip( + filename: "images/\(imageFile.filename)", + fileData: imageFile.data, + zipData: &zipData, + fileEntries: &fileEntries, + currentOffset: ¤tOffset + ) + } + + // Add central directory + var centralDirectory = Data() + for entry in fileEntries { + centralDirectory.append(createCentralDirectoryHeader(entry: entry)) + } + + // Add end of central directory record + let endOfCentralDir = createEndOfCentralDirectoryRecord( + fileCount: UInt16(fileEntries.count), + centralDirSize: UInt32(centralDirectory.count), + centralDirOffset: currentOffset + ) + + zipData.append(centralDirectory) + zipData.append(endOfCentralDir) + + return zipData + } + + private func addFileToMinimalZip( + filename: String, + fileData: Data, + zipData: inout Data, + fileEntries: inout [(name: String, data: Data, offset: UInt32)], + currentOffset: inout UInt32 + ) throws { + let localFileHeader = createLocalFileHeader( + filename: filename, fileSize: UInt32(fileData.count)) + + fileEntries.append((name: filename, data: fileData, offset: currentOffset)) + + zipData.append(localFileHeader) + zipData.append(fileData) + + currentOffset += UInt32(localFileHeader.count + fileData.count) + } + + private func createLocalFileHeader(filename: String, fileSize: UInt32) -> Data { + var header = Data() + + // Local file header signature + header.append(Data([0x50, 0x4b, 0x03, 0x04])) + + // Version needed to extract (2.0) + header.append(Data([0x14, 0x00])) + + // General purpose bit flag + header.append(Data([0x00, 0x00])) + + // Compression method (no compression) + header.append(Data([0x00, 0x00])) + + // Last mod file time & date (dummy values) + header.append(Data([0x00, 0x00, 0x00, 0x00])) + + // CRC-32 (dummy - we're not compressing) + header.append(Data([0x00, 0x00, 0x00, 0x00])) + + // Compressed size + withUnsafeBytes(of: fileSize.littleEndian) { header.append(Data($0)) } + + // Uncompressed size + withUnsafeBytes(of: fileSize.littleEndian) { header.append(Data($0)) } + + // File name length + let filenameData = filename.data(using: .utf8) ?? Data() + let filenameLength = UInt16(filenameData.count) + withUnsafeBytes(of: filenameLength.littleEndian) { header.append(Data($0)) } + + // Extra field length + header.append(Data([0x00, 0x00])) + + // File name + header.append(filenameData) + + return header + } + + private func createCentralDirectoryHeader(entry: (name: String, data: Data, offset: UInt32)) + -> Data + { + var header = Data() + + // Central directory signature + header.append(Data([0x50, 0x4b, 0x01, 0x02])) + + // Version made by + header.append(Data([0x14, 0x00])) + + // Version needed to extract + header.append(Data([0x14, 0x00])) + + // General purpose bit flag + header.append(Data([0x00, 0x00])) + + // Compression method + header.append(Data([0x00, 0x00])) + + // Last mod file time & date + header.append(Data([0x00, 0x00, 0x00, 0x00])) + + // CRC-32 + header.append(Data([0x00, 0x00, 0x00, 0x00])) + + // Compressed size + let compressedSize = UInt32(entry.data.count) + withUnsafeBytes(of: compressedSize.littleEndian) { header.append(Data($0)) } + + // Uncompressed size + withUnsafeBytes(of: compressedSize.littleEndian) { header.append(Data($0)) } + + // File name length + let filenameData = entry.name.data(using: .utf8) ?? Data() + let filenameLength = UInt16(filenameData.count) + withUnsafeBytes(of: filenameLength.littleEndian) { header.append(Data($0)) } + + // Extra field length + header.append(Data([0x00, 0x00])) + + // File comment length + header.append(Data([0x00, 0x00])) + + // Disk number start + header.append(Data([0x00, 0x00])) + + // Internal file attributes + header.append(Data([0x00, 0x00])) + + // External file attributes + header.append(Data([0x00, 0x00, 0x00, 0x00])) + + // Relative offset of local header + withUnsafeBytes(of: entry.offset.littleEndian) { header.append(Data($0)) } + + // File name + header.append(filenameData) + + return header + } + + private func createEndOfCentralDirectoryRecord( + fileCount: UInt16, centralDirSize: UInt32, centralDirOffset: UInt32 + ) -> Data { + var record = Data() + + // End of central dir signature + record.append(Data([0x50, 0x4b, 0x05, 0x06])) + + // Number of this disk + record.append(Data([0x00, 0x00])) + + // Number of the disk with the start of the central directory + record.append(Data([0x00, 0x00])) + + // Total number of entries in the central directory on this disk + withUnsafeBytes(of: fileCount.littleEndian) { record.append(Data($0)) } + + // Total number of entries in the central directory + withUnsafeBytes(of: fileCount.littleEndian) { record.append(Data($0)) } + + // Size of the central directory + withUnsafeBytes(of: centralDirSize.littleEndian) { record.append(Data($0)) } + + // Offset of start of central directory + withUnsafeBytes(of: centralDirOffset.littleEndian) { record.append(Data($0)) } + + // ZIP file comment length + record.append(Data([0x00, 0x00])) + + return record + } + + func testConnection() async throws { + guard isConfigured else { + throw SyncError.notConfigured + } + + isTesting = true + defer { isTesting = false } + + guard let url = URL(string: "\(serverURL)/health") else { + throw SyncError.invalidURL + } + + var request = URLRequest(url: url) + request.httpMethod = "GET" + request.setValue("application/json", forHTTPHeaderField: "Accept") + request.timeoutInterval = 10 + + let (_, response) = try await URLSession.shared.data(for: request) + + guard let httpResponse = response as? HTTPURLResponse else { + throw SyncError.invalidResponse + } + + guard httpResponse.statusCode == 200 else { + throw SyncError.serverError(httpResponse.statusCode) + } + + // Connection successful, mark as connected + isConnected = true + userDefaults.set(true, forKey: Keys.isConnected) + } + + func triggerAutoSync(dataManager: ClimbingDataManager) { + guard isConnected && isConfigured && isAutoSyncEnabled else { return } + + Task { + do { + try await syncWithServer(dataManager: dataManager) + } catch { + print("Auto-sync failed: \(error)") + // Don't show UI errors for auto-sync failures + } + } + } + + // DEPRECATED: Complex merge logic replaced with simple timestamp-based sync + // These methods are no longer used but kept for reference + @available(*, deprecated, message: "Use simple timestamp-based sync instead") + private func performIntelligentMerge(local: ClimbDataBackup, server: ClimbDataBackup) throws + -> ClimbDataBackup + { + print("Merging data - preserving all entities to prevent data loss") + + // Merge gyms by ID, keeping most recently updated + let mergedGyms = mergeGyms(local: local.gyms, server: server.gyms) + + // Merge problems by ID, keeping most recently updated + let mergedProblems = mergeProblems(local: local.problems, server: server.problems) + + // Merge sessions by ID, keeping most recently updated + let mergedSessions = mergeSessions(local: local.sessions, server: server.sessions) + + // Merge attempts by ID, keeping most recently updated + let mergedAttempts = mergeAttempts(local: local.attempts, server: server.attempts) + + print( + "Merge results: gyms=\(mergedGyms.count), problems=\(mergedProblems.count), sessions=\(mergedSessions.count), attempts=\(mergedAttempts.count)" + ) + + return ClimbDataBackup( + exportedAt: ISO8601DateFormatter().string(from: Date()), + version: "2.0", + formatVersion: "2.0", + gyms: mergedGyms, + problems: mergedProblems, + sessions: mergedSessions, + attempts: mergedAttempts + ) + } + + private func mergeGyms(local: [BackupGym], server: [BackupGym]) -> [BackupGym] { + var merged: [String: BackupGym] = [:] + + // Add all local gyms + for gym in local { + merged[gym.id] = gym + } + + // Add server gyms, replacing if newer + for serverGym in server { + if let localGym = merged[serverGym.id] { + // Keep the most recently updated + if isNewerThan(serverGym.updatedAt, localGym.updatedAt) { + merged[serverGym.id] = serverGym + } + } else { + // New gym from server + merged[serverGym.id] = serverGym + } + } + + return Array(merged.values) + } + + private func mergeProblems(local: [BackupProblem], server: [BackupProblem]) -> [BackupProblem] { + var merged: [String: BackupProblem] = [:] + + // Add all local problems + for problem in local { + merged[problem.id] = problem + } + + // Add server problems, replacing if newer or merging image paths + for serverProblem in server { + if let localProblem = merged[serverProblem.id] { + // Merge image paths from both sources + let localImages = Set(localProblem.imagePaths ?? []) + let serverImages = Set(serverProblem.imagePaths ?? []) + let mergedImages = Array(localImages.union(serverImages)) + + // Use most recently updated problem data but with merged images + let newerProblem = + isNewerThan(serverProblem.updatedAt, localProblem.updatedAt) + ? serverProblem : localProblem + merged[serverProblem.id] = BackupProblem( + id: newerProblem.id, + gymId: newerProblem.gymId, + name: newerProblem.name, + description: newerProblem.description, + climbType: newerProblem.climbType, + difficulty: newerProblem.difficulty, + tags: newerProblem.tags, + location: newerProblem.location, + imagePaths: mergedImages.isEmpty ? nil : mergedImages, + isActive: newerProblem.isActive, + dateSet: newerProblem.dateSet, + notes: newerProblem.notes, + createdAt: newerProblem.createdAt, + updatedAt: newerProblem.updatedAt + ) + } else { + // New problem from server + merged[serverProblem.id] = serverProblem + } + } + + return Array(merged.values) + } + + private func mergeSessions(local: [BackupClimbSession], server: [BackupClimbSession]) + -> [BackupClimbSession] + { + var merged: [String: BackupClimbSession] = [:] + + // Add all local sessions + for session in local { + merged[session.id] = session + } + + // Add server sessions, replacing if newer + for serverSession in server { + if let localSession = merged[serverSession.id] { + // Keep the most recently updated + if isNewerThan(serverSession.updatedAt, localSession.updatedAt) { + merged[serverSession.id] = serverSession + } + } else { + // New session from server + merged[serverSession.id] = serverSession + } + } + + return Array(merged.values) + } + + private func mergeAttempts(local: [BackupAttempt], server: [BackupAttempt]) -> [BackupAttempt] { + var merged: [String: BackupAttempt] = [:] + + // Add all local attempts + for attempt in local { + merged[attempt.id] = attempt + } + + // Add server attempts, replacing if newer + for serverAttempt in server { + if let localAttempt = merged[serverAttempt.id] { + // Keep the most recently created (attempts don't typically get updated) + if isNewerThan(serverAttempt.createdAt, localAttempt.createdAt) { + merged[serverAttempt.id] = serverAttempt + } + } else { + // New attempt from server + merged[serverAttempt.id] = serverAttempt + } + } + + return Array(merged.values) + } + + private func isNewerThan(_ dateString1: String, _ dateString2: String) -> Bool { + let formatter = ISO8601DateFormatter() + guard let date1 = formatter.date(from: dateString1), + let date2 = formatter.date(from: dateString2) + else { + return false + } + return date1 > date2 + } + + func disconnect() { + isConnected = false + lastSyncTime = nil + syncError = nil + userDefaults.set(false, forKey: Keys.isConnected) + userDefaults.removeObject(forKey: Keys.lastSyncTime) + } + + func clearConfiguration() { + serverURL = "" + authToken = "" + lastSyncTime = nil + isConnected = false + isAutoSyncEnabled = true + userDefaults.removeObject(forKey: Keys.lastSyncTime) + userDefaults.removeObject(forKey: Keys.isConnected) + userDefaults.removeObject(forKey: Keys.autoSyncEnabled) + } +} + +// Removed SyncTrigger enum - now using simple auto sync on any data change + +enum SyncError: LocalizedError { + case notConfigured + case notConnected + case invalidURL + case invalidResponse + case unauthorized + case badRequest + case serverError(Int) + case decodingError(Error) + case exportFailed + case importFailed(Error) + case imageNotFound + case imageUploadFailed + + var errorDescription: String? { + switch self { + case .notConfigured: + return "Sync server not configured. Please set server URL and auth token." + case .notConnected: + return "Not connected to sync server. Please test connection first." + case .invalidURL: + return "Invalid server URL." + case .invalidResponse: + return "Invalid response from server." + case .unauthorized: + return "Authentication failed. Check your auth token." + case .badRequest: + return "Bad request. Check your data format." + case .serverError(let code): + return "Server error (code \(code))." + case .decodingError(let error): + return "Failed to decode response: \(error.localizedDescription)" + case .exportFailed: + return "Failed to export local data." + case .importFailed(let error): + return "Failed to import data: \(error.localizedDescription)" + case .imageNotFound: + return "Image not found on server." + case .imageUploadFailed: + return "Failed to upload image to server." + } + } +} diff --git a/ios/OpenClimb/Utils/DataStateManager.swift b/ios/OpenClimb/Utils/DataStateManager.swift new file mode 100644 index 0000000..d533284 --- /dev/null +++ b/ios/OpenClimb/Utils/DataStateManager.swift @@ -0,0 +1,85 @@ +// +// DataStateManager.swift + +import Foundation + +/// Manages the overall data state timestamp for sync purposes. This tracks when any data in the +/// local database was last modified, independent of individual entity timestamps. +class DataStateManager { + + private let userDefaults = UserDefaults.standard + + private enum Keys { + static let lastModified = "openclimb_data_last_modified" + static let initialized = "openclimb_data_state_initialized" + } + + /// Shared instance for app-wide use + static let shared = DataStateManager() + + private init() { + // Initialize with current timestamp if this is the first time + if !isInitialized() { + print("DataStateManager: First time initialization") + // Set initial timestamp to a very old date so server data will be considered newer + let epochTime = "1970-01-01T00:00:00.000Z" + userDefaults.set(epochTime, forKey: Keys.lastModified) + markAsInitialized() + print("DataStateManager initialized with epoch timestamp: \(epochTime)") + } else { + print("DataStateManager: Already initialized, current timestamp: \(getLastModified())") + } + } + + /// Updates the data state timestamp to the current time. Call this whenever any data is modified + /// (create, update, delete). + func updateDataState() { + let now = ISO8601DateFormatter().string(from: Date()) + userDefaults.set(now, forKey: Keys.lastModified) + print("📝 iOS Data state updated to: \(now)") + } + + /// Gets the current data state timestamp. This represents when any data was last modified + /// locally. + func getLastModified() -> String { + if let storedTimestamp = userDefaults.string(forKey: Keys.lastModified) { + print("📅 iOS DataStateManager returning stored timestamp: \(storedTimestamp)") + return storedTimestamp + } + + // If no timestamp is stored, return epoch time to indicate very old data + // This ensures server data will be considered newer than uninitialized local data + let epochTime = "1970-01-01T00:00:00.000Z" + print("⚠️ No data state timestamp found - returning epoch time: \(epochTime)") + return epochTime + } + + /// Sets the data state timestamp to a specific value. Used when importing data from server to + /// sync the state. + func setLastModified(_ timestamp: String) { + userDefaults.set(timestamp, forKey: Keys.lastModified) + print("Data state set to: \(timestamp)") + } + + /// Resets the data state (for testing or complete data wipe). + func reset() { + userDefaults.removeObject(forKey: Keys.lastModified) + userDefaults.removeObject(forKey: Keys.initialized) + print("Data state reset") + } + + /// Checks if the data state has been initialized. + private func isInitialized() -> Bool { + return userDefaults.bool(forKey: Keys.initialized) + } + + /// Marks the data state as initialized. + private func markAsInitialized() { + userDefaults.set(true, forKey: Keys.initialized) + } + + /// Gets debug information about the current state. + func getDebugInfo() -> String { + return "DataState(lastModified=\(getLastModified()), initialized=\(isInitialized()))" + } +} diff --git a/ios/OpenClimb/Utils/ImageNamingUtils.swift b/ios/OpenClimb/Utils/ImageNamingUtils.swift new file mode 100644 index 0000000..8aca2d1 --- /dev/null +++ b/ios/OpenClimb/Utils/ImageNamingUtils.swift @@ -0,0 +1,176 @@ +// +// ImageNamingUtils.swift + +import CryptoKit +import Foundation + +/// Utility for creating consistent image filenames across iOS and Android platforms. +/// Uses deterministic naming based on problem ID and timestamp to ensure sync compatibility. +class ImageNamingUtils { + + private static let imageExtension = ".jpg" + private static let hashLength = 12 // First 12 chars of SHA-256 + + /// Generates a deterministic filename for a problem image. + /// Format: "problem_{hash}_{index}.jpg" + /// + /// - Parameters: + /// - problemId: The ID of the problem this image belongs to + /// - timestamp: ISO8601 timestamp when the image was created + /// - imageIndex: The index of this image for the problem (0, 1, 2, etc.) + /// - Returns: A consistent filename that will be the same across platforms + static func generateImageFilename(problemId: String, timestamp: String, imageIndex: Int) + -> String + { + // Create a deterministic hash from problemId + timestamp + index + let input = "\(problemId)_\(timestamp)_\(imageIndex)" + let hash = createHash(from: input) + + return "problem_\(hash)_\(imageIndex)\(imageExtension)" + } + + /// Generates a deterministic filename for a problem image using current timestamp. + /// + /// - Parameters: + /// - problemId: The ID of the problem this image belongs to + /// - imageIndex: The index of this image for the problem (0, 1, 2, etc.) + /// - Returns: A consistent filename + static func generateImageFilename(problemId: String, imageIndex: Int) -> String { + let timestamp = ISO8601DateFormatter().string(from: Date()) + return generateImageFilename( + problemId: problemId, timestamp: timestamp, imageIndex: imageIndex) + } + + /// Extracts problem ID from an image filename created by this utility. + /// Returns nil if the filename doesn't match our naming convention. + /// + /// - Parameter filename: The image filename + /// - Returns: The hash identifier or nil if not a valid filename + static func extractProblemIdFromFilename(_ filename: String) -> String? { + guard filename.hasPrefix("problem_") && filename.hasSuffix(imageExtension) else { + return nil + } + + // Format: problem_{hash}_{index}.jpg + let nameWithoutExtension = String(filename.dropLast(imageExtension.count)) + let parts = nameWithoutExtension.components(separatedBy: "_") + + guard parts.count == 3 && parts[0] == "problem" else { + return nil + } + + // Return the hash as identifier + return parts[1] + } + + /// Validates if a filename follows our naming convention. + /// + /// - Parameter filename: The filename to validate + /// - Returns: true if it matches our convention, false otherwise + static func isValidImageFilename(_ filename: String) -> Bool { + guard filename.hasPrefix("problem_") && filename.hasSuffix(imageExtension) else { + return false + } + + let nameWithoutExtension = String(filename.dropLast(imageExtension.count)) + let parts = nameWithoutExtension.components(separatedBy: "_") + + return parts.count == 3 && parts[0] == "problem" && parts[1].count == hashLength + && Int(parts[2]) != nil + } + + /// Migrates an existing UUID-based filename to our naming convention. + /// This is used during sync to rename downloaded images. + /// + /// - Parameters: + /// - oldFilename: The existing filename (UUID-based) + /// - problemId: The problem ID this image belongs to + /// - imageIndex: The index of this image + /// - Returns: The new filename following our convention + static func migrateFilename(oldFilename: String, problemId: String, imageIndex: Int) -> String { + // If it's already using our convention, keep it + if isValidImageFilename(oldFilename) { + return oldFilename + } + + // Generate new deterministic name + // Use current timestamp to maintain some consistency + let timestamp = ISO8601DateFormatter().string(from: Date()) + return generateImageFilename( + problemId: problemId, timestamp: timestamp, imageIndex: imageIndex) + } + + /// Creates a deterministic hash from input string. + /// Uses SHA-256 and takes first 12 characters for filename safety. + /// + /// - Parameter input: The input string to hash + /// - Returns: First 12 characters of SHA-256 hash in lowercase + private static func createHash(from input: String) -> String { + let inputData = Data(input.utf8) + let hashed = SHA256.hash(data: inputData) + let hashString = hashed.compactMap { String(format: "%02x", $0) }.joined() + return String(hashString.prefix(hashLength)) + } + + /// Batch renames images for a problem to use our naming convention. + /// Returns a mapping of old filename -> new filename. + /// + /// - Parameters: + /// - problemId: The problem ID + /// - existingFilenames: List of current image filenames for this problem + /// - Returns: Dictionary mapping old filename to new filename + static func batchRenameForProblem(problemId: String, existingFilenames: [String]) -> [String: + String] + { + var renameMap: [String: String] = [:] + + for (index, oldFilename) in existingFilenames.enumerated() { + let newFilename = migrateFilename( + oldFilename: oldFilename, problemId: problemId, imageIndex: index) + if newFilename != oldFilename { + renameMap[oldFilename] = newFilename + } + } + + return renameMap + } + + /// Validates that a collection of filenames follow our naming convention. + /// + /// - Parameter filenames: Array of filenames to validate + /// - Returns: Dictionary with validation results + static func validateFilenames(_ filenames: [String]) -> ImageValidationResult { + var validImages: [String] = [] + var invalidImages: [String] = [] + + for filename in filenames { + if isValidImageFilename(filename) { + validImages.append(filename) + } else { + invalidImages.append(filename) + } + } + + return ImageValidationResult( + totalImages: filenames.count, + validImages: validImages, + invalidImages: invalidImages + ) + } +} + +/// Result of image filename validation +struct ImageValidationResult { + let totalImages: Int + let validImages: [String] + let invalidImages: [String] + + var isAllValid: Bool { + return invalidImages.isEmpty + } + + var validPercentage: Double { + guard totalImages > 0 else { return 100.0 } + return (Double(validImages.count) / Double(totalImages)) * 100.0 + } +} diff --git a/ios/OpenClimb/ViewModels/ClimbingDataManager.swift b/ios/OpenClimb/ViewModels/ClimbingDataManager.swift index 24719ec..3cad61f 100644 --- a/ios/OpenClimb/ViewModels/ClimbingDataManager.swift +++ b/ios/OpenClimb/ViewModels/ClimbingDataManager.swift @@ -29,6 +29,9 @@ class ClimbingDataManager: ObservableObject { private let decoder = JSONDecoder() private var liveActivityObserver: NSObjectProtocol? + // Sync service for automatic syncing + let syncService = SyncService() + private enum Keys { static let gyms = "openclimb_gyms" static let problems = "openclimb_problems" @@ -200,6 +203,7 @@ class ClimbingDataManager: ObservableObject { func addGym(_ gym: Gym) { gyms.append(gym) saveGyms() + DataStateManager.shared.updateDataState() successMessage = "Gym added successfully" clearMessageAfterDelay() } @@ -208,6 +212,7 @@ class ClimbingDataManager: ObservableObject { if let index = gyms.firstIndex(where: { $0.id == gym.id }) { gyms[index] = gym saveGyms() + DataStateManager.shared.updateDataState() successMessage = "Gym updated successfully" clearMessageAfterDelay() } @@ -229,6 +234,7 @@ class ClimbingDataManager: ObservableObject { // Delete the gym gyms.removeAll { $0.id == gym.id } saveGyms() + DataStateManager.shared.updateDataState() successMessage = "Gym deleted successfully" clearMessageAfterDelay() } @@ -240,14 +246,19 @@ class ClimbingDataManager: ObservableObject { func addProblem(_ problem: Problem) { problems.append(problem) saveProblems() + DataStateManager.shared.updateDataState() successMessage = "Problem added successfully" clearMessageAfterDelay() + + // Trigger auto-sync if enabled + syncService.triggerAutoSync(dataManager: self) } func updateProblem(_ problem: Problem) { if let index = problems.firstIndex(where: { $0.id == problem.id }) { problems[index] = problem saveProblems() + DataStateManager.shared.updateDataState() successMessage = "Problem updated successfully" clearMessageAfterDelay() } @@ -264,6 +275,7 @@ class ClimbingDataManager: ObservableObject { // Delete the problem problems.removeAll { $0.id == problem.id } saveProblems() + DataStateManager.shared.updateDataState() } func problem(withId id: UUID) -> Problem? { @@ -290,6 +302,7 @@ class ClimbingDataManager: ObservableObject { saveActiveSession() saveSessions() + DataStateManager.shared.updateDataState() successMessage = "Session started successfully" clearMessageAfterDelay() @@ -317,9 +330,13 @@ class ClimbingDataManager: ObservableObject { saveActiveSession() saveSessions() + DataStateManager.shared.updateDataState() successMessage = "Session completed successfully" clearMessageAfterDelay() + // Trigger auto-sync if enabled + syncService.triggerAutoSync(dataManager: self) + // MARK: - End Live Activity after session ends Task { await LiveActivityManager.shared.endLiveActivity() @@ -337,6 +354,7 @@ class ClimbingDataManager: ObservableObject { } saveSessions() + DataStateManager.shared.updateDataState() successMessage = "Session updated successfully" clearMessageAfterDelay() @@ -359,6 +377,7 @@ class ClimbingDataManager: ObservableObject { // Delete the session sessions.removeAll { $0.id == session.id } saveSessions() + DataStateManager.shared.updateDataState() successMessage = "Session deleted successfully" clearMessageAfterDelay() } @@ -380,8 +399,12 @@ class ClimbingDataManager: ObservableObject { func addAttempt(_ attempt: Attempt) { attempts.append(attempt) saveAttempts() + DataStateManager.shared.updateDataState() successMessage = "Attempt logged successfully" + + // Trigger auto-sync if enabled + syncService.triggerAutoSync(dataManager: self) clearMessageAfterDelay() // Update Live Activity when new attempt is added @@ -392,6 +415,7 @@ class ClimbingDataManager: ObservableObject { if let index = attempts.firstIndex(where: { $0.id == attempt.id }) { attempts[index] = attempt saveAttempts() + DataStateManager.shared.updateDataState() successMessage = "Attempt updated successfully" clearMessageAfterDelay() @@ -403,6 +427,7 @@ class ClimbingDataManager: ObservableObject { func deleteAttempt(_ attempt: Attempt) { attempts.removeAll { $0.id == attempt.id } saveAttempts() + DataStateManager.shared.updateDataState() successMessage = "Attempt deleted successfully" clearMessageAfterDelay() @@ -464,6 +489,7 @@ class ClimbingDataManager: ObservableObject { userDefaults.removeObject(forKey: Keys.attempts) userDefaults.removeObject(forKey: Keys.activeSession) + DataStateManager.shared.reset() successMessage = "All data has been reset" clearMessageAfterDelay() } @@ -557,6 +583,9 @@ class ClimbingDataManager: ObservableObject { saveSessions() saveAttempts() + // Update data state to current time since we just imported new data + DataStateManager.shared.updateDataState() + successMessage = "Data imported successfully with \(importResult.imagePathMapping.count) images" clearMessageAfterDelay() diff --git a/ios/OpenClimb/Views/SettingsView.swift b/ios/OpenClimb/Views/SettingsView.swift index 79a832e..56a2694 100644 --- a/ios/OpenClimb/Views/SettingsView.swift +++ b/ios/OpenClimb/Views/SettingsView.swift @@ -12,6 +12,9 @@ struct SettingsView: View { var body: some View { List { + SyncSection() + .environmentObject(dataManager.syncService) + DataManagementSection( activeSheet: $activeSheet ) @@ -303,6 +306,361 @@ struct ExportDataView: View { } } +struct SyncSection: View { + @EnvironmentObject var syncService: SyncService + @EnvironmentObject var dataManager: ClimbingDataManager + @State private var showingSyncSettings = false + @State private var showingDisconnectAlert = false + + var body: some View { + Section("Sync") { + // Sync Status + HStack { + Image( + systemName: syncService.isConnected + ? "checkmark.circle.fill" + : syncService.isConfigured + ? "exclamationmark.triangle.fill" + : "exclamationmark.circle.fill" + ) + .foregroundColor( + syncService.isConnected + ? .green + : syncService.isConfigured + ? .orange + : .red + ) + VStack(alignment: .leading) { + Text("Sync Server") + .font(.headline) + Text( + syncService.isConnected + ? "Connected" + : syncService.isConfigured + ? "Configured - Not tested" + : "Not configured" + ) + .font(.caption) + .foregroundColor(.secondary) + } + Spacer() + } + + // Configure Server + Button(action: { + showingSyncSettings = true + }) { + HStack { + Image(systemName: "gear") + .foregroundColor(.blue) + Text("Configure Server") + Spacer() + Image(systemName: "chevron.right") + .font(.caption) + .foregroundColor(.secondary) + } + } + .foregroundColor(.primary) + + if syncService.isConfigured { + + // Sync Now - only show if connected + if syncService.isConnected { + Button(action: { + performSync() + }) { + HStack { + if syncService.isSyncing { + ProgressView() + .scaleEffect(0.8) + Text("Syncing...") + .foregroundColor(.secondary) + } else { + Image(systemName: "arrow.triangle.2.circlepath") + .foregroundColor(.green) + Text("Sync Now") + Spacer() + if let lastSync = syncService.lastSyncTime { + Text( + RelativeDateTimeFormatter().localizedString( + for: lastSync, relativeTo: Date()) + ) + .font(.caption) + .foregroundColor(.secondary) + } + } + } + } + .disabled(syncService.isSyncing) + .foregroundColor(.primary) + } + + // Auto-sync configuration - always visible for testing + HStack { + VStack(alignment: .leading) { + Text("Auto-sync") + Text("Sync automatically on app launch and data changes") + .font(.caption) + .foregroundColor(.secondary) + } + Spacer() + Toggle( + "", + isOn: Binding( + get: { syncService.isAutoSyncEnabled }, + set: { syncService.isAutoSyncEnabled = $0 } + ) + ) + .disabled(!syncService.isConnected) + } + .foregroundColor(.primary) + + // Disconnect option - only show if connected + if syncService.isConnected { + Button(action: { + showingDisconnectAlert = true + }) { + HStack { + Image(systemName: "power") + .foregroundColor(.orange) + Text("Disconnect") + Spacer() + } + } + .foregroundColor(.primary) + } + + if let error = syncService.syncError { + Text(error) + .font(.caption) + .foregroundColor(.red) + .padding(.leading, 24) + } + } + } + .sheet(isPresented: $showingSyncSettings) { + SyncSettingsView() + .environmentObject(syncService) + } + .alert("Disconnect from Server", isPresented: $showingDisconnectAlert) { + Button("Cancel", role: .cancel) {} + Button("Disconnect", role: .destructive) { + syncService.disconnect() + } + } message: { + Text( + "This will sign you out but keep your server settings. You'll need to test the connection again to sync." + ) + } + } + + private func performSync() { + Task { + do { + try await syncService.syncWithServer(dataManager: dataManager) + } catch { + print("Sync failed: \(error)") + } + } + } +} + +struct SyncSettingsView: View { + @EnvironmentObject var syncService: SyncService + @Environment(\.dismiss) private var dismiss + @State private var serverURL: String = "" + @State private var authToken: String = "" + @State private var showingDisconnectAlert = false + @State private var isTesting = false + @State private var showingTestResult = false + @State private var testResultMessage = "" + + var body: some View { + NavigationView { + Form { + Section { + TextField("Server URL", text: $serverURL) + .textFieldStyle(.roundedBorder) + .keyboardType(.URL) + .autocapitalization(.none) + .disableAutocorrection(true) + .placeholder(when: serverURL.isEmpty) { + Text("http://your-server:8080") + .foregroundColor(.secondary) + } + + TextField("Auth Token", text: $authToken) + .textFieldStyle(.roundedBorder) + .autocapitalization(.none) + .disableAutocorrection(true) + .placeholder(when: authToken.isEmpty) { + Text("your-secret-token") + .foregroundColor(.secondary) + } + } header: { + Text("Server Configuration") + } footer: { + Text( + "Enter your sync server URL and authentication token. You must test the connection before syncing is available." + ) + } + + Section { + Button(action: { + testConnection() + }) { + HStack { + if isTesting { + ProgressView() + .scaleEffect(0.8) + Text("Testing...") + .foregroundColor(.secondary) + } else { + Image(systemName: "network") + .foregroundColor(.blue) + Text("Test Connection") + Spacer() + if syncService.isConnected { + Image(systemName: "checkmark.circle.fill") + .foregroundColor(.green) + } + } + } + } + .disabled( + isTesting + || serverURL.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + || authToken.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + ) + .foregroundColor(.primary) + } header: { + Text("Connection") + } footer: { + Text("Test the connection to verify your server settings before saving.") + } + + Section { + Button("Disconnect from Server") { + showingDisconnectAlert = true + } + .foregroundColor(.orange) + + Button("Clear Configuration") { + syncService.clearConfiguration() + serverURL = "" + authToken = "" + } + .foregroundColor(.red) + } footer: { + Text( + "Disconnect will sign you out but keep settings. Clear Configuration removes all sync settings." + ) + } + } + .navigationTitle("Sync Settings") + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .navigationBarLeading) { + Button("Cancel") { + dismiss() + } + } + ToolbarItem(placement: .navigationBarTrailing) { + Button("Save") { + let newURL = serverURL.trimmingCharacters(in: .whitespacesAndNewlines) + let newToken = authToken.trimmingCharacters(in: .whitespacesAndNewlines) + + // Mark as disconnected if settings changed + if newURL != syncService.serverURL || newToken != syncService.authToken { + syncService.isConnected = false + UserDefaults.standard.set(false, forKey: "sync_is_connected") + } + + syncService.serverURL = newURL + syncService.authToken = newToken + dismiss() + } + .fontWeight(.semibold) + } + } + } + .onAppear { + serverURL = syncService.serverURL + authToken = syncService.authToken + } + .alert("Disconnect from Server", isPresented: $showingDisconnectAlert) { + Button("Cancel", role: .cancel) {} + Button("Disconnect", role: .destructive) { + syncService.disconnect() + dismiss() + } + } message: { + Text( + "This will sign you out but keep your server settings. You'll need to test the connection again to sync." + ) + } + .alert("Connection Test", isPresented: $showingTestResult) { + Button("OK") {} + } message: { + Text(testResultMessage) + } + } + + private func testConnection() { + isTesting = true + + let testURL = serverURL.trimmingCharacters(in: .whitespacesAndNewlines) + let testToken = authToken.trimmingCharacters(in: .whitespacesAndNewlines) + + // Store original values in case test fails + let originalURL = syncService.serverURL + let originalToken = syncService.authToken + + Task { + do { + // Temporarily set the values for testing + syncService.serverURL = testURL + syncService.authToken = testToken + + try await syncService.testConnection() + + await MainActor.run { + isTesting = false + testResultMessage = + "Connection successful! You can now save and sync your data." + showingTestResult = true + } + } catch { + // Restore original values if test failed + syncService.serverURL = originalURL + syncService.authToken = originalToken + + await MainActor.run { + isTesting = false + testResultMessage = "Connection failed: \(error.localizedDescription)" + showingTestResult = true + } + } + } + } +} + +// Removed AutoSyncSettingsView - now using simple toggle in main settings + +extension View { + func placeholder( + when shouldShow: Bool, + alignment: Alignment = .leading, + @ViewBuilder placeholder: () -> Content + ) -> some View { + + ZStack(alignment: alignment) { + placeholder().opacity(shouldShow ? 1 : 0) + self + } + } +} + struct ImportDataView: View { @EnvironmentObject var dataManager: ClimbingDataManager @Environment(\.dismiss) private var dismiss diff --git a/sync-server/.env.example b/sync-server/.env.example new file mode 100644 index 0000000..bc6aa89 --- /dev/null +++ b/sync-server/.env.example @@ -0,0 +1,14 @@ +# OpenClimb Sync Server Configuration + +# Required: Secret token for authentication +# Generate a secure random token and share it between your apps and server +AUTH_TOKEN=your-secure-secret-token-here + +# Optional: Port to run the server on (default: 8080) +PORT=8080 + +# Optional: Path to store the sync data (default: ./data/climb_data.json) +DATA_FILE=./data/climb_data.json + +# Optional: Directory to store images (default: ./data/images) +IMAGES_DIR=./data/images diff --git a/sync-server/.gitignore b/sync-server/.gitignore new file mode 100644 index 0000000..9fc8fde --- /dev/null +++ b/sync-server/.gitignore @@ -0,0 +1,16 @@ +# Binaries +sync-server +openclimb-sync + +# Go workspace file +go.work + +# Data directory +data/ + +# Environment files +.env +.env.local + +# OS generated files +.DS_Store diff --git a/sync-server/Dockerfile b/sync-server/Dockerfile new file mode 100644 index 0000000..25442c0 --- /dev/null +++ b/sync-server/Dockerfile @@ -0,0 +1,14 @@ +FROM golang:1.25-alpine AS builder + +WORKDIR /app +COPY . . +RUN CGO_ENABLED=0 GOOS=linux go build -o sync-server . + +FROM alpine:latest +RUN apk --no-cache add ca-certificates +WORKDIR /root/ + +COPY --from=builder /app/sync-server . + +EXPOSE 8080 +CMD ["./sync-server"] diff --git a/sync-server/docker-compose.yml b/sync-server/docker-compose.yml new file mode 100644 index 0000000..b1bb740 --- /dev/null +++ b/sync-server/docker-compose.yml @@ -0,0 +1,14 @@ +version: "3.8" + +services: + openclimb-sync: + build: . + ports: + - "8080:8080" + environment: + - AUTH_TOKEN=${AUTH_TOKEN:-your-secret-token-here} + - DATA_FILE=/data/climb_data.json + - IMAGES_DIR=/data/images + volumes: + - ./data:/data + restart: unless-stopped diff --git a/sync-server/go.mod b/sync-server/go.mod new file mode 100644 index 0000000..3103696 --- /dev/null +++ b/sync-server/go.mod @@ -0,0 +1,3 @@ +module openclimb-sync + +go 1.25 diff --git a/sync-server/main.go b/sync-server/main.go new file mode 100644 index 0000000..7034a3f --- /dev/null +++ b/sync-server/main.go @@ -0,0 +1,358 @@ +package main + +import ( + "crypto/subtle" + "encoding/json" + "fmt" + "io" + "log" + "net/http" + "os" + "path/filepath" + "strings" + "time" +) + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +type ClimbDataBackup struct { + ExportedAt string `json:"exportedAt"` + Version string `json:"version"` + FormatVersion string `json:"formatVersion"` + Gyms []BackupGym `json:"gyms"` + Problems []BackupProblem `json:"problems"` + Sessions []BackupClimbSession `json:"sessions"` + Attempts []BackupAttempt `json:"attempts"` +} + +type BackupGym struct { + ID string `json:"id"` + Name string `json:"name"` + Location *string `json:"location,omitempty"` + SupportedClimbTypes []string `json:"supportedClimbTypes"` + DifficultySystems []string `json:"difficultySystems"` + CustomDifficultyGrades []string `json:"customDifficultyGrades"` + Notes *string `json:"notes,omitempty"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +type BackupProblem struct { + ID string `json:"id"` + GymID string `json:"gymId"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + ClimbType string `json:"climbType"` + Difficulty DifficultyGrade `json:"difficulty"` + Tags []string `json:"tags"` + Location *string `json:"location,omitempty"` + ImagePaths []string `json:"imagePaths,omitempty"` + IsActive bool `json:"isActive"` + DateSet *string `json:"dateSet,omitempty"` + Notes *string `json:"notes,omitempty"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +type DifficultyGrade struct { + System string `json:"system"` + Grade string `json:"grade"` + NumericValue int `json:"numericValue"` +} + +type BackupClimbSession struct { + ID string `json:"id"` + GymID string `json:"gymId"` + Date string `json:"date"` + StartTime *string `json:"startTime,omitempty"` + EndTime *string `json:"endTime,omitempty"` + Duration *int64 `json:"duration,omitempty"` + Status string `json:"status"` + Notes *string `json:"notes,omitempty"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +type BackupAttempt struct { + ID string `json:"id"` + SessionID string `json:"sessionId"` + ProblemID string `json:"problemId"` + Result string `json:"result"` + HighestHold *string `json:"highestHold,omitempty"` + Notes *string `json:"notes,omitempty"` + Duration *int64 `json:"duration,omitempty"` + RestTime *int64 `json:"restTime,omitempty"` + Timestamp string `json:"timestamp"` + CreatedAt string `json:"createdAt"` +} + +type SyncServer struct { + authToken string + dataFile string + imagesDir string +} + +func (s *SyncServer) authenticate(r *http.Request) bool { + authHeader := r.Header.Get("Authorization") + if !strings.HasPrefix(authHeader, "Bearer ") { + return false + } + + token := strings.TrimPrefix(authHeader, "Bearer ") + return subtle.ConstantTimeCompare([]byte(token), []byte(s.authToken)) == 1 +} + +func (s *SyncServer) loadData() (*ClimbDataBackup, error) { + log.Printf("Loading data from: %s", s.dataFile) + + if _, err := os.Stat(s.dataFile); os.IsNotExist(err) { + log.Printf("Data file does not exist, creating empty backup") + return &ClimbDataBackup{ + ExportedAt: time.Now().UTC().Format(time.RFC3339), + Version: "2.0", + FormatVersion: "2.0", + Gyms: []BackupGym{}, + Problems: []BackupProblem{}, + Sessions: []BackupClimbSession{}, + Attempts: []BackupAttempt{}, + }, nil + } + + data, err := os.ReadFile(s.dataFile) + if err != nil { + log.Printf("Failed to read data file: %v", err) + return nil, err + } + + log.Printf("Read %d bytes from data file", len(data)) + log.Printf("File content preview: %s", string(data[:min(200, len(data))])) + + var backup ClimbDataBackup + if err := json.Unmarshal(data, &backup); err != nil { + log.Printf("Failed to unmarshal JSON: %v", err) + return nil, err + } + + log.Printf("Loaded backup: gyms=%d, problems=%d, sessions=%d, attempts=%d", + len(backup.Gyms), len(backup.Problems), len(backup.Sessions), len(backup.Attempts)) + + return &backup, nil +} + +func (s *SyncServer) saveData(backup *ClimbDataBackup) error { + backup.ExportedAt = time.Now().UTC().Format(time.RFC3339) + + data, err := json.MarshalIndent(backup, "", " ") + if err != nil { + return err + } + + dir := filepath.Dir(s.dataFile) + if err := os.MkdirAll(dir, 0755); err != nil { + return err + } + + // Ensure images directory exists + if err := os.MkdirAll(s.imagesDir, 0755); err != nil { + return err + } + + return os.WriteFile(s.dataFile, data, 0644) +} + +func (s *SyncServer) handleGet(w http.ResponseWriter, r *http.Request) { + if !s.authenticate(r) { + log.Printf("Unauthorized access attempt from %s", r.RemoteAddr) + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } + + log.Printf("GET /sync request from %s", r.RemoteAddr) + backup, err := s.loadData() + if err != nil { + log.Printf("Failed to load data: %v", err) + http.Error(w, "Failed to load data", http.StatusInternalServerError) + return + } + + log.Printf("Sending data to %s: gyms=%d, problems=%d, sessions=%d, attempts=%d", + r.RemoteAddr, len(backup.Gyms), len(backup.Problems), len(backup.Sessions), len(backup.Attempts)) + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(backup) +} + +func (s *SyncServer) handlePut(w http.ResponseWriter, r *http.Request) { + if !s.authenticate(r) { + log.Printf("Unauthorized sync attempt from %s", r.RemoteAddr) + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } + + var backup ClimbDataBackup + if err := json.NewDecoder(r.Body).Decode(&backup); err != nil { + log.Printf("Invalid JSON from %s: %v", r.RemoteAddr, err) + http.Error(w, "Invalid JSON", http.StatusBadRequest) + return + } + + if err := s.saveData(&backup); err != nil { + log.Printf("Failed to save data: %v", err) + http.Error(w, "Failed to save data", http.StatusInternalServerError) + return + } + + log.Printf("Data synced by %s", r.RemoteAddr) + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(backup) +} + +func (s *SyncServer) handleHealth(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(map[string]string{ + "status": "healthy", + "time": time.Now().UTC().Format(time.RFC3339), + }) +} + +func (s *SyncServer) handleImageUpload(w http.ResponseWriter, r *http.Request) { + if !s.authenticate(r) { + log.Printf("Unauthorized image upload attempt from %s", r.RemoteAddr) + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } + + if r.Method != http.MethodPost { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + filename := r.URL.Query().Get("filename") + if filename == "" { + http.Error(w, "Missing filename parameter", http.StatusBadRequest) + return + } + + imageData, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, "Failed to read image data", http.StatusBadRequest) + return + } + + imagePath := filepath.Join(s.imagesDir, filename) + if err := os.WriteFile(imagePath, imageData, 0644); err != nil { + log.Printf("Failed to save image %s: %v", filename, err) + http.Error(w, "Failed to save image", http.StatusInternalServerError) + return + } + + log.Printf("Image uploaded: %s (%d bytes) by %s", filename, len(imageData), r.RemoteAddr) + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(map[string]string{"status": "uploaded"}) +} + +func (s *SyncServer) handleImageDownload(w http.ResponseWriter, r *http.Request) { + if !s.authenticate(r) { + log.Printf("Unauthorized image download attempt from %s", r.RemoteAddr) + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } + + if r.Method != http.MethodGet { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + filename := r.URL.Query().Get("filename") + if filename == "" { + http.Error(w, "Missing filename parameter", http.StatusBadRequest) + return + } + + imagePath := filepath.Join(s.imagesDir, filename) + imageData, err := os.ReadFile(imagePath) + if err != nil { + if os.IsNotExist(err) { + http.Error(w, "Image not found", http.StatusNotFound) + } else { + http.Error(w, "Failed to read image", http.StatusInternalServerError) + } + return + } + + // Set appropriate content type based on file extension + ext := filepath.Ext(filename) + switch ext { + case ".jpg", ".jpeg": + w.Header().Set("Content-Type", "image/jpeg") + case ".png": + w.Header().Set("Content-Type", "image/png") + case ".gif": + w.Header().Set("Content-Type", "image/gif") + case ".webp": + w.Header().Set("Content-Type", "image/webp") + default: + w.Header().Set("Content-Type", "application/octet-stream") + } + + w.WriteHeader(http.StatusOK) + w.Write(imageData) +} + +func (s *SyncServer) handleSync(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case http.MethodGet: + s.handleGet(w, r) + case http.MethodPut: + s.handlePut(w, r) + default: + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + } +} + +func main() { + authToken := os.Getenv("AUTH_TOKEN") + if authToken == "" { + log.Fatal("AUTH_TOKEN environment variable is required") + } + + dataFile := os.Getenv("DATA_FILE") + if dataFile == "" { + dataFile = "./data/climb_data.json" + } + + imagesDir := os.Getenv("IMAGES_DIR") + if imagesDir == "" { + imagesDir = "./data/images" + } + + port := os.Getenv("PORT") + if port == "" { + port = "8080" + } + + server := &SyncServer{ + authToken: authToken, + dataFile: dataFile, + imagesDir: imagesDir, + } + + http.HandleFunc("/sync", server.handleSync) + http.HandleFunc("/health", server.handleHealth) + http.HandleFunc("/images/upload", server.handleImageUpload) + http.HandleFunc("/images/download", server.handleImageDownload) + + fmt.Printf("OpenClimb sync server starting on port %s\n", port) + fmt.Printf("Data file: %s\n", dataFile) + fmt.Printf("Images directory: %s\n", imagesDir) + fmt.Printf("Health check available at /health\n") + fmt.Printf("Image upload: POST /images/upload?filename=\n") + fmt.Printf("Image download: GET /images/download?filename=\n") + + log.Fatal(http.ListenAndServe(":"+port, nil)) +} diff --git a/sync-server/run.sh b/sync-server/run.sh new file mode 100755 index 0000000..76a3382 --- /dev/null +++ b/sync-server/run.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# OpenClimb Sync Server Runner +set -e + +# Default values +AUTH_TOKEN=${AUTH_TOKEN:-} +PORT=${PORT:-8080} +DATA_FILE=${DATA_FILE:-./data/climb_data.json} + +# Check if AUTH_TOKEN is set +if [ -z "$AUTH_TOKEN" ]; then + echo "Error: AUTH_TOKEN environment variable must be set" + echo "Usage: AUTH_TOKEN=your-secret-token ./run.sh" + echo "Or: export AUTH_TOKEN=your-secret-token && ./run.sh" + exit 1 +fi + +# Create data directory if it doesn't exist +mkdir -p "$(dirname "$DATA_FILE")" + +# Build and run +echo "Building OpenClimb sync server..." +go build -o sync-server . + +echo "Starting server on port $PORT" +echo "Data will be stored in: $DATA_FILE" +echo "Images will be stored in: ${IMAGES_DIR:-./data/images}" +echo "Use Authorization: Bearer $AUTH_TOKEN in your requests" +echo "" + +exec ./sync-server From f7f1fba9aa4193d1e05755c90bf92fd3a506538b Mon Sep 17 00:00:00 2001 From: Atridad Lahiji Date: Sun, 28 Sep 2025 23:29:44 -0600 Subject: [PATCH 2/4] Added proper CI --- .github/workflows/deploy.yml | 43 +++ .../UserInterfaceState.xcuserstate | Bin 124304 -> 124520 bytes sync-server/DEPLOY.md | 303 ++++++++++++++++++ {sync-server => sync}/.env.example | 0 {sync-server => sync}/.gitignore | 0 {sync-server => sync}/Dockerfile | 0 {sync-server => sync}/docker-compose.yml | 4 +- {sync-server => sync}/go.mod | 0 {sync-server => sync}/main.go | 0 {sync-server => sync}/run.sh | 0 sync/version.md | 1 + 11 files changed, 348 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/deploy.yml create mode 100644 sync-server/DEPLOY.md rename {sync-server => sync}/.env.example (100%) rename {sync-server => sync}/.gitignore (100%) rename {sync-server => sync}/Dockerfile (100%) rename {sync-server => sync}/docker-compose.yml (90%) rename {sync-server => sync}/go.mod (100%) rename {sync-server => sync}/main.go (100%) rename {sync-server => sync}/run.sh (100%) create mode 100644 sync/version.md diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..51c2c10 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,43 @@ +name: OpenClimb Docker Deploy +on: + push: + branches: [main] + paths: + - "sync/**" + - ".github/workflows/deploy.yml" + pull_request: + branches: [main] + paths: + - "sync/**" + - ".github/workflows/deploy.yml" + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to Container Registry + uses: docker/login-action@v2 + with: + registry: ${{ secrets.REPO_HOST }} + username: ${{ github.repository_owner }} + password: ${{ secrets.DEPLOY_TOKEN }} + + - name: Build and push sync-server + uses: docker/build-push-action@v4 + with: + context: ./sync + file: ./sync/Dockerfile + platforms: linux/amd64 + push: true + tags: | + ${{ secrets.REPO_HOST }}/${{ github.repository_owner }}/openclimb-sync-server:${{ github.sha }} + ${{ secrets.REPO_HOST }}/${{ github.repository_owner }}/openclimb-sync-server:latest 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 de72ced2219c65201568ca9c1dc04cd8862ff5b3..63a5df08bb8d9c7ea0719b51780471182ec743b8 100644 GIT binary patch literal 124520 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

N+YPuw3SA&cPjCnnk-ThQ{XZ@Y* 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

(|!3)_sIUC=^!y7s4K1ZT;4|-};^P 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

mXRJ3|yL=zyJNaI+bD@e~7injzR(2K&#TZiW@S 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 Wm;e3o|NB=7|2Gi--@ifw4*oypAD~14 literal 124304 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 +cd OpenClimb/sync-server + +# Run the deployment script +./deploy.sh +``` + +The script will: +- Create necessary directories +- Pull the latest container image +- Stop any existing containers +- Start the new container +- Verify deployment success + +### 2. Manual Deployment + +```bash +# Pull the latest image +docker pull your-registry.com/username/openclimb-sync-server:latest + +# Create environment file +cp .env.example .env.prod +# Edit .env.prod with your configuration + +# Deploy with docker-compose +docker-compose -f docker-compose.prod.yml up -d +``` + +## Configuration + +### Environment Variables + +Create a `.env.prod` file with the following variables: + +```bash +# Container registry settings +REPO_HOST=your-registry.example.com +REPO_OWNER=your-username + +# Server configuration +AUTH_TOKEN=your-secure-auth-token-here-make-it-long-and-random +PORT=8080 + +# Optional: Custom domain (for Traefik) +TRAEFIK_HOST=sync.openclimb.example.com +``` + +### Required Secrets (GitHub) + +Configure these secrets in your GitHub repository settings: + +- `REPO_HOST`: Your container registry hostname +- `DEPLOY_TOKEN`: Authentication token for the registry + +## Container Build Process + +The GitHub Action (`sync-server-deploy.yml`) automatically: + +1. **Triggers on:** + - Push to `main` branch (when sync-server files change) + - Pull requests to `main` branch + +2. **Build Process:** + - Uses multi-stage Docker build + - Compiles Go binary in builder stage + - Creates minimal Alpine-based runtime image + - Pushes to container registry with tags: + - `latest` (always points to newest) + - `` (specific version) + +3. **Caching:** + - Uses GitHub Actions cache for faster builds + - Incremental builds when possible + +## Deployment Options + +### Option 1: Simple Docker Run +```bash +docker run -d \ + --name openclimb-sync-server \ + -p 8080:8080 \ + -v $(pwd)/data:/root/data \ + -e AUTH_TOKEN=your-token-here \ + your-registry.com/username/openclimb-sync-server:latest +``` + +### Option 2: Docker Compose (Recommended) +```bash +docker-compose -f docker-compose.prod.yml up -d +``` + +### Option 3: Kubernetes +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: openclimb-sync-server +spec: + replicas: 1 + selector: + matchLabels: + app: openclimb-sync-server + template: + metadata: + labels: + app: openclimb-sync-server + spec: + containers: + - name: sync-server + image: your-registry.com/username/openclimb-sync-server:latest + ports: + - containerPort: 8080 + env: + - name: AUTH_TOKEN + valueFrom: + secretKeyRef: + name: openclimb-secrets + key: auth-token + volumeMounts: + - name: data-volume + mountPath: /root/data + volumes: + - name: data-volume + persistentVolumeClaim: + claimName: openclimb-data +``` + +## Data Persistence + +The sync server stores data in `/root/data` inside the container. **Always mount a volume** to preserve data: + +```bash +# Local directory mounting +-v $(pwd)/data:/root/data + +# Named volume (recommended for production) +-v openclimb-data:/root/data +``` + +### Data Structure +``` +data/ +├── climb_data.json # Main sync data +├── images/ # Uploaded images +│ ├── problem_*.jpg +│ └── ... +└── logs/ # Server logs (optional) +``` + +## Monitoring and Maintenance + +### Health Check +```bash +curl http://localhost:8080/health +``` + +### View Logs +```bash +# Docker Compose +docker-compose -f docker-compose.prod.yml logs -f + +# Direct Docker +docker logs -f openclimb-sync-server +``` + +### Update to Latest Version +```bash +# Using deploy script +./deploy.sh + +# Manual update +docker-compose -f docker-compose.prod.yml pull +docker-compose -f docker-compose.prod.yml up -d +``` + +## Reverse Proxy Setup (Optional) + +### Nginx +```nginx +server { + listen 80; + server_name sync.openclimb.example.com; + + location / { + proxy_pass http://localhost:8080; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} +``` + +### Traefik (Labels included in docker-compose.prod.yml) +```yaml +labels: + - "traefik.enable=true" + - "traefik.http.routers.openclimb-sync.rule=Host(`sync.openclimb.example.com`)" + - "traefik.http.routers.openclimb-sync.tls.certresolver=letsencrypt" +``` + +## Security Considerations + +1. **AUTH_TOKEN**: Use a long, random token (32+ characters) +2. **HTTPS**: Always use HTTPS in production (via reverse proxy) +3. **Firewall**: Only expose port 8080 to your reverse proxy, not publicly +4. **Updates**: Regularly update to the latest container image +5. **Backups**: Regularly backup the `data/` directory + +## Troubleshooting + +### Container Won't Start +```bash +# Check logs +docker logs openclimb-sync-server + +# Common issues: +# - Missing AUTH_TOKEN environment variable +# - Port 8080 already in use +# - Insufficient permissions on data directory +``` + +### Sync Fails from Mobile Apps +```bash +# Verify server is accessible +curl -H "Authorization: Bearer your-token" http://your-server:8080/sync + +# Check server logs for authentication errors +docker logs openclimb-sync-server | grep "401\|403" +``` + +### Image Upload Issues +```bash +# Check disk space +df -h + +# Verify data directory permissions +ls -la data/ +``` + +## Performance Tuning + +For high-load deployments: + +```yaml +# docker-compose.prod.yml +services: + openclimb-sync-server: + deploy: + resources: + limits: + memory: 512M + cpus: '0.5' + reservations: + memory: 256M + cpus: '0.25' +``` + +## Backup Strategy + +```bash +#!/bin/bash +# backup.sh - Run daily via cron + +DATE=$(date +%Y%m%d_%H%M%S) +BACKUP_DIR="/backups/openclimb" + +# Create backup directory +mkdir -p "$BACKUP_DIR" + +# Backup data directory +tar -czf "$BACKUP_DIR/openclimb_data_$DATE.tar.gz" \ + -C /path/to/sync-server data/ + +# Keep only last 30 days +find "$BACKUP_DIR" -name "openclimb_data_*.tar.gz" -mtime +30 -delete +``` + +## Support + +- **Issues**: Create an issue in the GitHub repository +- **Documentation**: Check the main OpenClimb README +- **Logs**: Always diff --git a/sync-server/.env.example b/sync/.env.example similarity index 100% rename from sync-server/.env.example rename to sync/.env.example diff --git a/sync-server/.gitignore b/sync/.gitignore similarity index 100% rename from sync-server/.gitignore rename to sync/.gitignore diff --git a/sync-server/Dockerfile b/sync/Dockerfile similarity index 100% rename from sync-server/Dockerfile rename to sync/Dockerfile diff --git a/sync-server/docker-compose.yml b/sync/docker-compose.yml similarity index 90% rename from sync-server/docker-compose.yml rename to sync/docker-compose.yml index b1bb740..ca7977d 100644 --- a/sync-server/docker-compose.yml +++ b/sync/docker-compose.yml @@ -1,8 +1,6 @@ -version: "3.8" - services: openclimb-sync: - build: . + image: ${IMAGE} ports: - "8080:8080" environment: diff --git a/sync-server/go.mod b/sync/go.mod similarity index 100% rename from sync-server/go.mod rename to sync/go.mod diff --git a/sync-server/main.go b/sync/main.go similarity index 100% rename from sync-server/main.go rename to sync/main.go diff --git a/sync-server/run.sh b/sync/run.sh similarity index 100% rename from sync-server/run.sh rename to sync/run.sh diff --git a/sync/version.md b/sync/version.md new file mode 100644 index 0000000..3eefcb9 --- /dev/null +++ b/sync/version.md @@ -0,0 +1 @@ +1.0.0 From 56c501cef6332442d997ad96181c25e0148aa60e Mon Sep 17 00:00:00 2001 From: Atridad Lahiji Date: Sun, 28 Sep 2025 23:33:05 -0600 Subject: [PATCH 3/4] Version bumps --- ...otlin-compiler-12627972128363089919.salive | 0 android/app/build.gradle.kts | 4 ++-- ios/OpenClimb.xcodeproj/project.pbxproj | 18 ++++++++++-------- .../UserInterfaceState.xcuserstate | Bin 124520 -> 123874 bytes .../xcshareddata/xcschemes/OpenClimb.xcscheme | 2 +- ios/OpenClimb/ContentView.swift | 2 +- ios/OpenClimb/Services/SyncService.swift | 2 +- 7 files changed, 15 insertions(+), 13 deletions(-) create mode 100644 android/.kotlin/sessions/kotlin-compiler-12627972128363089919.salive diff --git a/android/.kotlin/sessions/kotlin-compiler-12627972128363089919.salive b/android/.kotlin/sessions/kotlin-compiler-12627972128363089919.salive new file mode 100644 index 0000000..e69de29 diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 2349fa4..a169fc6 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -16,8 +16,8 @@ android { applicationId = "com.atridad.openclimb" minSdk = 31 targetSdk = 36 - versionCode = 27 - versionName = "1.6.0" + versionCode = 28 + versionName = "1.7.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/ios/OpenClimb.xcodeproj/project.pbxproj b/ios/OpenClimb.xcodeproj/project.pbxproj index 0a60cb7..63bf078 100644 --- a/ios/OpenClimb.xcodeproj/project.pbxproj +++ b/ios/OpenClimb.xcodeproj/project.pbxproj @@ -324,6 +324,7 @@ MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; @@ -381,6 +382,7 @@ MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_COMPILATION_MODE = wholemodule; VALIDATE_PRODUCT = YES; }; @@ -394,7 +396,7 @@ CODE_SIGN_ENTITLEMENTS = OpenClimb/OpenClimb.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 10; + CURRENT_PROJECT_VERSION = 11; DEVELOPMENT_TEAM = 4BC9Y2LL4B; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -414,7 +416,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.0; + MARKETING_VERSION = 1.2.0; PRODUCT_BUNDLE_IDENTIFIER = com.atridad.OpenClimb; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -437,7 +439,7 @@ CODE_SIGN_ENTITLEMENTS = OpenClimb/OpenClimb.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 10; + CURRENT_PROJECT_VERSION = 11; DEVELOPMENT_TEAM = 4BC9Y2LL4B; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -457,7 +459,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.0; + MARKETING_VERSION = 1.2.0; PRODUCT_BUNDLE_IDENTIFIER = com.atridad.OpenClimb; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -479,7 +481,7 @@ ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; CODE_SIGN_ENTITLEMENTS = SessionStatusLiveExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 10; + CURRENT_PROJECT_VERSION = 11; DEVELOPMENT_TEAM = 4BC9Y2LL4B; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = SessionStatusLive/Info.plist; @@ -490,7 +492,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.1.0; + MARKETING_VERSION = 1.2.0; PRODUCT_BUNDLE_IDENTIFIER = com.atridad.OpenClimb.SessionStatusLive; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -509,7 +511,7 @@ ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; CODE_SIGN_ENTITLEMENTS = SessionStatusLiveExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 10; + CURRENT_PROJECT_VERSION = 11; DEVELOPMENT_TEAM = 4BC9Y2LL4B; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = SessionStatusLive/Info.plist; @@ -520,7 +522,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.1.0; + MARKETING_VERSION = 1.2.0; PRODUCT_BUNDLE_IDENTIFIER = com.atridad.OpenClimb.SessionStatusLive; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; 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 63a5df08bb8d9c7ea0719b51780471182ec743b8..5cd6516f18666203ed17020955c74718788258fb 100644 GIT binary patch literal 123874 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 z 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

N+YPuw3SA&cPjCnnk-ThQ{XZ@Y* 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

(|!3)_sIUC=^!y7s4K1ZT;4|-};^P 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

mXRJ3|yL=zyJNaI+bD@e~7injzR(2K&#TZiW@S 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 Wm;e3o|NB=7|2Gi--@ifw4*oypAD~14 diff --git a/ios/OpenClimb.xcodeproj/xcshareddata/xcschemes/OpenClimb.xcscheme b/ios/OpenClimb.xcodeproj/xcshareddata/xcschemes/OpenClimb.xcscheme index 60b8335..8f80ddb 100644 --- a/ios/OpenClimb.xcodeproj/xcshareddata/xcschemes/OpenClimb.xcscheme +++ b/ios/OpenClimb.xcodeproj/xcshareddata/xcschemes/OpenClimb.xcscheme @@ -1,6 +1,6 @@ Date: Sun, 28 Sep 2025 23:34:37 -0600 Subject: [PATCH 4/4] Sync server name change --- .github/workflows/deploy.yml | 4 ++-- ...otlin-compiler-12627972128363089919.salive | 0 .../UserInterfaceState.xcuserstate | Bin 123874 -> 124606 bytes 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 android/.kotlin/sessions/kotlin-compiler-12627972128363089919.salive diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 51c2c10..1ae4138 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -39,5 +39,5 @@ jobs: platforms: linux/amd64 push: true tags: | - ${{ secrets.REPO_HOST }}/${{ github.repository_owner }}/openclimb-sync-server:${{ github.sha }} - ${{ secrets.REPO_HOST }}/${{ github.repository_owner }}/openclimb-sync-server:latest + ${{ secrets.REPO_HOST }}/${{ github.repository_owner }}/openclimb-sync:${{ github.sha }} + ${{ secrets.REPO_HOST }}/${{ github.repository_owner }}/openclimb-sync:latest diff --git a/android/.kotlin/sessions/kotlin-compiler-12627972128363089919.salive b/android/.kotlin/sessions/kotlin-compiler-12627972128363089919.salive deleted file mode 100644 index e69de29..0000000 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 5cd6516f18666203ed17020955c74718788258fb..7fb5b300dda0de0183e6f123017578973ff51bfb 100644 GIT binary patch literal 124606 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�}3 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 SKNh?AfB*6S|M#H*5C0#I_{M?& literal 123874 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 z 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