diff --git a/core/database/schemas/com.toquete.boxbox.core.database.BoxBoxDatabase/11.json b/core/database/schemas/com.toquete.boxbox.core.database.BoxBoxDatabase/11.json new file mode 100644 index 00000000..0fc4ce7d --- /dev/null +++ b/core/database/schemas/com.toquete.boxbox.core.database.BoxBoxDatabase/11.json @@ -0,0 +1,682 @@ +{ + "formatVersion": 1, + "database": { + "version": 11, + "identityHash": "b45b8f66680aa1b484d231b5fe3c058f", + "entities": [ + { + "tableName": "driver_standings", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`position` INTEGER NOT NULL, `points` TEXT NOT NULL, `wins` TEXT NOT NULL, `driver_id` TEXT NOT NULL, `constructor_id` TEXT NOT NULL, PRIMARY KEY(`position`))", + "fields": [ + { + "fieldPath": "position", + "columnName": "position", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "points", + "columnName": "points", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "wins", + "columnName": "wins", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "driverId", + "columnName": "driver_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "constructorId", + "columnName": "constructor_id", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "position" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "drivers", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `number` TEXT NOT NULL, `code` TEXT, `url` TEXT NOT NULL, `first_name` TEXT NOT NULL, `last_name` TEXT NOT NULL, `date_of_birth` TEXT NOT NULL, `nationality` TEXT NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "code", + "columnName": "code", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "firstName", + "columnName": "first_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastName", + "columnName": "last_name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "dateOfBirth", + "columnName": "date_of_birth", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "nationality", + "columnName": "nationality", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "constructor_standings", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`position` INTEGER NOT NULL, `points` TEXT NOT NULL, `wins` TEXT NOT NULL, `constructor_id` TEXT NOT NULL, PRIMARY KEY(`position`))", + "fields": [ + { + "fieldPath": "position", + "columnName": "position", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "points", + "columnName": "points", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "wins", + "columnName": "wins", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "constructorId", + "columnName": "constructor_id", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "position" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "constructors", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `url` TEXT NOT NULL, `name` TEXT NOT NULL, `nationality` TEXT NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "nationality", + "columnName": "nationality", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "countries", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `nationality` TEXT NOT NULL, `flag_url` TEXT NOT NULL, `alternative_id` TEXT, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "nationality", + "columnName": "nationality", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "flagUrl", + "columnName": "flag_url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "alternativeId", + "columnName": "alternative_id", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "drivers_images", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `image_url` TEXT NOT NULL, `number_url` TEXT NOT NULL DEFAULT '', PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "imageUrl", + "columnName": "image_url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "numberUrl", + "columnName": "number_url", + "affinity": "TEXT", + "notNull": true, + "defaultValue": "''" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "constructors_images", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `image_url` TEXT NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "imageUrl", + "columnName": "image_url", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "circuits", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `circuitUrl` TEXT NOT NULL, `circuitName` TEXT NOT NULL, `latitude` TEXT NOT NULL, `longitude` TEXT NOT NULL, `locality` TEXT NOT NULL, `country` TEXT NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "circuitUrl", + "columnName": "circuitUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "circuitName", + "columnName": "circuitName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "latitude", + "columnName": "latitude", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "longitude", + "columnName": "longitude", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "locality", + "columnName": "locality", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "country", + "columnName": "country", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "races", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`season` TEXT NOT NULL, `round` INTEGER NOT NULL, `raceUrl` TEXT, `raceName` TEXT NOT NULL, `date` TEXT NOT NULL, `time` TEXT, `circuit_id` TEXT NOT NULL, `first_practice_date` TEXT, `first_practice_time` TEXT, `second_practice_date` TEXT, `second_practice_time` TEXT, `third_practice_date` TEXT, `third_practice_time` TEXT, `qualifying_date` TEXT, `qualifying_time` TEXT, `sprint_date` TEXT, `sprint_time` TEXT, PRIMARY KEY(`season`, `round`))", + "fields": [ + { + "fieldPath": "season", + "columnName": "season", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "round", + "columnName": "round", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "raceUrl", + "columnName": "raceUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "raceName", + "columnName": "raceName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "date", + "columnName": "date", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "time", + "columnName": "time", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "circuitId", + "columnName": "circuit_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "firstPracticeDate", + "columnName": "first_practice_date", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "firstPracticeTime", + "columnName": "first_practice_time", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "secondPracticeDate", + "columnName": "second_practice_date", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "secondPracticeTime", + "columnName": "second_practice_time", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "thirdPracticeDate", + "columnName": "third_practice_date", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "thirdPracticeTime", + "columnName": "third_practice_time", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "qualifyingDate", + "columnName": "qualifying_date", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "qualifyingTime", + "columnName": "qualifying_time", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sprintDate", + "columnName": "sprint_date", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sprintTime", + "columnName": "sprint_time", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "season", + "round" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "circuits_images", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `image_url` TEXT NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "imageUrl", + "columnName": "image_url", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "constructors_colors", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `accent_color` TEXT NOT NULL, `background_color` TEXT NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "accentColor", + "columnName": "accent_color", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "backgroundColor", + "columnName": "background_color", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "race_results", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`season` TEXT NOT NULL, `round` INTEGER NOT NULL, `position` INTEGER NOT NULL, `points` INTEGER NOT NULL, `driver_id` TEXT NOT NULL, `constructor_id` TEXT NOT NULL, `grid_position` INTEGER NOT NULL, `laps` TEXT NOT NULL, `status` TEXT NOT NULL, `time` TEXT, PRIMARY KEY(`season`, `round`, `position`))", + "fields": [ + { + "fieldPath": "season", + "columnName": "season", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "round", + "columnName": "round", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "position", + "columnName": "position", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "points", + "columnName": "points", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "driverId", + "columnName": "driver_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "constructorId", + "columnName": "constructor_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "gridPosition", + "columnName": "grid_position", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "laps", + "columnName": "laps", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "time", + "columnName": "time", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "season", + "round", + "position" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "sprint_race_results", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`season` TEXT NOT NULL, `round` INTEGER NOT NULL, `position` INTEGER NOT NULL, `points` INTEGER NOT NULL, `driver_id` TEXT NOT NULL, `constructor_id` TEXT NOT NULL, `grid_position` INTEGER NOT NULL, `laps` TEXT NOT NULL, `status` TEXT NOT NULL, `time` TEXT, PRIMARY KEY(`season`, `round`, `position`))", + "fields": [ + { + "fieldPath": "season", + "columnName": "season", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "round", + "columnName": "round", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "position", + "columnName": "position", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "points", + "columnName": "points", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "driverId", + "columnName": "driver_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "constructorId", + "columnName": "constructor_id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "gridPosition", + "columnName": "grid_position", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "laps", + "columnName": "laps", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "time", + "columnName": "time", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "season", + "round", + "position" + ] + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'b45b8f66680aa1b484d231b5fe3c058f')" + ] + } +} \ No newline at end of file diff --git a/core/database/src/main/java/com/toquete/boxbox/core/database/BoxBoxDatabase.kt b/core/database/src/main/java/com/toquete/boxbox/core/database/BoxBoxDatabase.kt index 62d36609..df5562fe 100644 --- a/core/database/src/main/java/com/toquete/boxbox/core/database/BoxBoxDatabase.kt +++ b/core/database/src/main/java/com/toquete/boxbox/core/database/BoxBoxDatabase.kt @@ -31,7 +31,7 @@ import com.toquete.boxbox.core.database.model.RaceResultEntity import com.toquete.boxbox.core.database.model.SprintRaceResultEntity @Database( - version = 10, + version = 11, entities = [ DriverStandingEntity::class, DriverEntity::class, @@ -54,6 +54,7 @@ import com.toquete.boxbox.core.database.model.SprintRaceResultEntity AutoMigration(from = 4, to = 5), AutoMigration(from = 7, to = 8), AutoMigration(from = 9, to = 10), + AutoMigration(from = 10, to = 11) ] ) @Suppress("TooManyFunctions") diff --git a/core/database/src/main/java/com/toquete/boxbox/core/database/model/RaceEntity.kt b/core/database/src/main/java/com/toquete/boxbox/core/database/model/RaceEntity.kt index 93cb4304..8727895b 100644 --- a/core/database/src/main/java/com/toquete/boxbox/core/database/model/RaceEntity.kt +++ b/core/database/src/main/java/com/toquete/boxbox/core/database/model/RaceEntity.kt @@ -7,7 +7,7 @@ import androidx.room.Entity data class RaceEntity( val season: String, val round: Int, - val raceUrl: String, + val raceUrl: String?, val raceName: String, val date: String, val time: String?, diff --git a/core/database/src/test/java/com/toquete/boxbox/core/database/migration/AutoMigrationTest.kt b/core/database/src/test/java/com/toquete/boxbox/core/database/migration/AutoMigrationTest.kt index e7c125af..a5e3163d 100644 --- a/core/database/src/test/java/com/toquete/boxbox/core/database/migration/AutoMigrationTest.kt +++ b/core/database/src/test/java/com/toquete/boxbox/core/database/migration/AutoMigrationTest.kt @@ -79,4 +79,14 @@ class AutoMigrationTest { helper.runMigrationsAndValidate(testDb, 10, true) } + + @Test + @Throws(IOException::class) + fun migrateFrom10To11() { + helper.createDatabase(testDb, 10).apply { + close() + } + + helper.runMigrationsAndValidate(testDb, 11, true) + } } diff --git a/core/model/src/main/java/com/toquete/boxbox/core/model/Race.kt b/core/model/src/main/java/com/toquete/boxbox/core/model/Race.kt index e23b43a0..74a6af2e 100644 --- a/core/model/src/main/java/com/toquete/boxbox/core/model/Race.kt +++ b/core/model/src/main/java/com/toquete/boxbox/core/model/Race.kt @@ -5,7 +5,7 @@ import kotlinx.datetime.Instant data class Race( val season: String, val round: Int, - val url: String, + val url: String?, val name: String, val circuit: Circuit, val dateTime: Instant?, diff --git a/core/network/src/main/java/com/toquete/boxbox/core/network/model/RaceResponse.kt b/core/network/src/main/java/com/toquete/boxbox/core/network/model/RaceResponse.kt index 28b17e63..ce4d31e3 100644 --- a/core/network/src/main/java/com/toquete/boxbox/core/network/model/RaceResponse.kt +++ b/core/network/src/main/java/com/toquete/boxbox/core/network/model/RaceResponse.kt @@ -10,7 +10,7 @@ data class RaceResponse( @SerialName("round") val round: String, @SerialName("url") - val url: String, + val url: String?, @SerialName("raceName") val raceName: String, @SerialName("Circuit") diff --git a/feature/home/src/main/java/com/toquete/boxbox/feature/home/ui/HomeViewModel.kt b/feature/home/src/main/java/com/toquete/boxbox/feature/home/ui/HomeViewModel.kt index 29246e8d..62a3b8af 100644 --- a/feature/home/src/main/java/com/toquete/boxbox/feature/home/ui/HomeViewModel.kt +++ b/feature/home/src/main/java/com/toquete/boxbox/feature/home/ui/HomeViewModel.kt @@ -19,6 +19,7 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import timber.log.Timber import javax.inject.Inject @HiltViewModel @@ -66,6 +67,7 @@ internal class HomeViewModel @Inject constructor( runCatching { syncRepository.sync() }.onFailure { + Timber.e(it) SnackbarManager.showMessage( messageTextId = R.string.home_fail_refresh, duration = SnackbarDuration.Long,