Files
SyncFlow/app/src/main/kotlin/com/syncflow/data/db/SyncDatabase.kt
T
amir 5f45a344b7 fix: epoch-millis DB converter + biometric from onResume
Sync change detection:
- DbConverters was using epochSecond but comparisons used epochMilli —
  every file appeared modified on every scan, causing full re-sync each time
- DB migration 2→3 clears sync_file_states (all stored timestamps wrong)
- First sync after upgrade re-learns state; subsequent syncs skip unchanged files

Biometric:
- Move prompt trigger from LaunchedEffect to onResume() — guarantees
  the activity is in RESUMED state when authenticate() is called
- Add bestAuthenticators(): tries BIOMETRIC_STRONG|DEVICE_CREDENTIAL first,
  falls back to BIOMETRIC_WEAK|DEVICE_CREDENTIAL for side-sensor phones
- canAuthenticate() now accepts either strong or weak+credential
- onAuthenticationError always shows Unlock button (no infinite retry loop)
- isLocked/showRetry are Activity-level state, no need for Compose remember

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 23:59:20 +00:00

39 lines
1.2 KiB
Kotlin

package com.syncflow.data.db
import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.syncflow.data.db.entities.*
@Database(
entities = [
CloudAccountEntity::class,
SyncPairEntity::class,
SyncFileStateEntity::class,
SyncConflictEntity::class,
SyncEventEntity::class,
],
version = 3,
exportSchema = true,
)
@TypeConverters(DbConverters::class)
abstract class SyncDatabase : RoomDatabase() {
companion object {
// Wipe file states: timestamps were stored as epoch-seconds, now epoch-millis.
// All previously saved states are wrong so we drop and re-learn on next sync.
val MIGRATION_2_3 = object : Migration(2, 3) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL("DELETE FROM sync_file_states")
}
}
}
abstract fun cloudAccountDao(): CloudAccountDao
abstract fun syncPairDao(): SyncPairDao
abstract fun syncFileStateDao(): SyncFileStateDao
abstract fun syncConflictDao(): SyncConflictDao
abstract fun syncEventDao(): SyncEventDao
}