5f45a344b7
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>
39 lines
1.2 KiB
Kotlin
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
|
|
}
|