diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/database/QsoDao.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/database/QsoDao.kt index d747afe5..b1c96a14 100644 --- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/database/QsoDao.kt +++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/database/QsoDao.kt @@ -47,4 +47,7 @@ interface QsoDao { @Query("UPDATE qso_records SET lotwUploaded = 1 WHERE id IN (:ids)") suspend fun markUploaded(ids: List) + + @Query("UPDATE qso_records SET wavelogUploaded = 1 WHERE id IN (:ids)") + suspend fun markWavelogUploaded(ids: List) } diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/database/QsoDatabase.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/database/QsoDatabase.kt index 0cd8a961..ef716c0a 100644 --- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/database/QsoDatabase.kt +++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/database/QsoDatabase.kt @@ -20,7 +20,7 @@ import com.rtbishop.look4sat.core.data.database.entity.QsoEntity * upload receipts). Kept apart from [Look4SatDb] so existing installations * never need a migration of the satellite database. */ -@Database(entities = [QsoEntity::class], version = 3, exportSchema = false) +@Database(entities = [QsoEntity::class], version = 4, exportSchema = false) abstract class QsoDatabase : RoomDatabase() { abstract fun qsoDao(): QsoDao } @@ -38,3 +38,10 @@ val MIGRATION_QSO_2_3 = object : Migration(2, 3) { db.execSQL("ALTER TABLE qso_records ADD COLUMN theirVuccGrids TEXT NOT NULL DEFAULT ''") } } + +/** v3 → v4: track whether a QSO was uploaded to Wavelog (independent of the LoTW state). */ +val MIGRATION_QSO_3_4 = object : Migration(3, 4) { + override fun migrate(db: SupportSQLiteDatabase) { + db.execSQL("ALTER TABLE qso_records ADD COLUMN wavelogUploaded INTEGER NOT NULL DEFAULT 0") + } +} diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/database/entity/QsoEntity.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/database/entity/QsoEntity.kt index 574304c7..e34c188f 100644 --- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/database/entity/QsoEntity.kt +++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/database/entity/QsoEntity.kt @@ -44,6 +44,7 @@ data class QsoEntity( @ColumnInfo(defaultValue = "''") val propagationMode: String = "", @ColumnInfo(defaultValue = "0") val lotwConfirmed: Boolean = false, @ColumnInfo(defaultValue = "0") val lotwUploaded: Boolean = false, + @ColumnInfo(defaultValue = "0") val wavelogUploaded: Boolean = false, @ColumnInfo(defaultValue = "0") val lotwReceived: Boolean = false, @ColumnInfo(defaultValue = "''") val lotwQslDate: String = "", @ColumnInfo(defaultValue = "''") val vuccGrids: String = "", diff --git a/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/QsoRepository.kt b/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/QsoRepository.kt index fff4357f..7380f575 100644 --- a/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/QsoRepository.kt +++ b/core/data/src/main/java/com/rtbishop/look4sat/core/data/repository/QsoRepository.kt @@ -51,12 +51,14 @@ class QsoRepository( // place: that contact already exists on LoTW under the old values. The original row // keeps its upload/confirmation state, and the edited content is saved as a NEW // record (without any LoTW state, so it can be uploaded again). - if (previous != null && (previous.lotwUploaded || previous.lotwConfirmed) && + if (previous != null && + (previous.lotwUploaded || previous.lotwConfirmed || previous.wavelogUploaded) && !record.sameEditableContentAs(previous) ) { dao.save(record.copy( id = 0L, lotwUploaded = false, lotwConfirmed = false, lotwReceived = false, + wavelogUploaded = false, lotwQslDate = "", vuccGrids = emptyList(), theirVuccGrids = emptyList(), dxcc = null, country = "", cqZone = null, region = "" ).toEntity()) @@ -93,6 +95,11 @@ class QsoRepository( if (stamped.isNotEmpty()) dao.saveBatch(stamped.map { it.toEntity() }) } + override suspend fun markWavelogUploaded(ids: List) = withContext(dispatcher) { + if (ids.isEmpty()) return@withContext + importMutex.withLock { dao.markWavelogUploaded(ids) } + } + override suspend fun exportAdi(ids: Set?, includeIncomplete: Boolean): String = withContext(dispatcher) { val records = dao.getAll() .asSequence() @@ -286,6 +293,7 @@ private fun QsoEntity.toDomain() = QsoRecord( propagationMode = propagationMode, lotwConfirmed = lotwConfirmed, lotwUploaded = lotwUploaded, + wavelogUploaded = wavelogUploaded, lotwReceived = lotwReceived, lotwQslDate = lotwQslDate, vuccGrids = vuccGrids.split(',').filter(String::isNotBlank), @@ -323,6 +331,7 @@ private fun QsoRecord.toEntity() = QsoEntity( propagationMode = propagationMode.ifBlank { if (satelliteName.isNotBlank()) "SAT" else "" }, lotwConfirmed = lotwConfirmed, lotwUploaded = lotwUploaded, + wavelogUploaded = wavelogUploaded, lotwReceived = lotwReceived, lotwQslDate = lotwQslDate, vuccGrids = vuccGrids.joinToString(","), diff --git a/core/data/src/test/java/com/rtbishop/look4sat/core/data/repository/QsoRepositoryTest.kt b/core/data/src/test/java/com/rtbishop/look4sat/core/data/repository/QsoRepositoryTest.kt index eda9c4ce..2e48600e 100644 --- a/core/data/src/test/java/com/rtbishop/look4sat/core/data/repository/QsoRepositoryTest.kt +++ b/core/data/src/test/java/com/rtbishop/look4sat/core/data/repository/QsoRepositoryTest.kt @@ -295,6 +295,27 @@ class QsoRepositoryTest { assertEquals(1, dao.getAll().size) } + @Test + fun markWavelogUploaded_setsOnlyTheWavelogFlag() = runBlocking { + val id = dao.save(loggedInApp("SO-50", lotwUploaded = false).toEntity()) + + repository.markWavelogUploaded(listOf(id)) + + val row = dao.getAll().single() + assertTrue(row.wavelogUploaded) + assertFalse(row.lotwUploaded) + } + + @Test + fun save_editingAWavelogUploadedRecordCreatesANewRecord() = runBlocking { + val id = dao.save(loggedInApp("SO-50", lotwUploaded = false).copy(wavelogUploaded = true).toEntity()) + + repository.save(loggedInApp("SO-50", lotwUploaded = false).copy(id = id, theirCallsign = "BG5JVM")) + + assertEquals(2, dao.getAll().size) + assertEquals(1, dao.getAll().count { it.wavelogUploaded }) + } + /** A record as the log page creates it: tracker name, repeater pair, uplink band. */ private fun loggedInApp(satelliteName: String, lotwUploaded: Boolean) = QsoRecord( startUtcMillis = qsoStart, @@ -355,6 +376,7 @@ class QsoRepositoryTest { propagationMode = propagationMode, lotwConfirmed = lotwConfirmed, lotwUploaded = lotwUploaded, + wavelogUploaded = wavelogUploaded, lotwReceived = lotwReceived, lotwQslDate = lotwQslDate, vuccGrids = vuccGrids.joinToString(","), @@ -393,5 +415,9 @@ class QsoRepositoryTest { override suspend fun markUploaded(ids: List) { ids.forEach { id -> rows[id]?.let { rows[id] = it.copy(lotwUploaded = true) } } } + + override suspend fun markWavelogUploaded(ids: List) { + ids.forEach { id -> rows[id]?.let { rows[id] = it.copy(wavelogUploaded = true) } } + } } } diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/logbook/IQsoRepository.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/logbook/IQsoRepository.kt index 6e6e7672..a45db5ce 100644 --- a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/logbook/IQsoRepository.kt +++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/logbook/IQsoRepository.kt @@ -23,6 +23,10 @@ interface IQsoRepository { * logbook row can show which grids the QSO went out under. */ suspend fun markUploaded(ids: List, grids: List = emptyList()) + + /** Marks the batch as uploaded to Wavelog (independent of the LoTW upload state). */ + suspend fun markWavelogUploaded(ids: List) + suspend fun exportAdi(ids: Set? = null, includeIncomplete: Boolean = false): String suspend fun importAdi(content: String): AdifImportResult suspend fun mergeConfirmed(records: List): AdifImportResult diff --git a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/logbook/QsoModels.kt b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/logbook/QsoModels.kt index 19c0da09..fce1d117 100644 --- a/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/logbook/QsoModels.kt +++ b/core/domain/src/main/java/com/rtbishop/look4sat/core/domain/logbook/QsoModels.kt @@ -40,6 +40,8 @@ data class QsoRecord( val propagationMode: String = if (satelliteName.isNotBlank()) "SAT" else "", val lotwConfirmed: Boolean = false, val lotwUploaded: Boolean = false, + /** Internal: set after a successful Wavelog upload; keeps the pending filter small. Not shown in any list. */ + val wavelogUploaded: Boolean = false, val lotwReceived: Boolean = false, val lotwQslDate: String = "", val vuccGrids: List = emptyList(),