Make it clear which ID the OfflineServer has (-1)

Also provide migration path to future version
This commit is contained in:
tzugen 2022-03-27 13:43:03 +02:00
parent 1d88c585c4
commit 1a46f7e2c6
No known key found for this signature in database
GPG Key ID: 61E9C34BC10EC930
6 changed files with 133 additions and 41 deletions

View File

@ -1,4 +1,4 @@
package org.moire.ultrasonic.fragment package org.moire.ultrasonic.adapters
import android.content.Context import android.content.Context
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable

View File

@ -19,8 +19,6 @@ import timber.log.Timber
/** /**
* This class can be used to retrieve the properties of the Active Server * This class can be used to retrieve the properties of the Active Server
* It caches the settings read up from the DB to improve performance. * It caches the settings read up from the DB to improve performance.
*
* TODO: There seems to be some confusion whether offline id is 0 or -1. Clean this up (carefully!)
*/ */
class ActiveServerProvider( class ActiveServerProvider(
private val repository: ServerSettingDao private val repository: ServerSettingDao
@ -35,7 +33,7 @@ class ActiveServerProvider(
*/ */
@JvmOverloads @JvmOverloads
fun getActiveServer(serverId: Int = getActiveServerId()): ServerSetting { fun getActiveServer(serverId: Int = getActiveServerId()): ServerSetting {
if (serverId > 0) { if (serverId > OFFLINE_DB_ID) {
if (cachedServer != null && cachedServer!!.id == serverId) return cachedServer!! if (cachedServer != null && cachedServer!!.id == serverId) return cachedServer!!
// Ideally this is the only call where we block the thread while using the repository // Ideally this is the only call where we block the thread while using the repository
@ -53,22 +51,11 @@ class ActiveServerProvider(
return cachedServer!! return cachedServer!!
} }
setActiveServerId(0) // Fallback to Offline
setActiveServerId(OFFLINE_DB_ID)
} }
return ServerSetting( return OFFLINE_DB
id = -1,
index = 0,
name = UApp.applicationContext().getString(R.string.main_offline),
url = "http://localhost",
userName = "",
password = "",
jukeboxByDefault = false,
allowSelfSignedCertificate = false,
ldapSupport = false,
musicFolderId = "",
minimumApiVersion = null
)
} }
/** /**
@ -77,9 +64,9 @@ class ActiveServerProvider(
*/ */
fun setActiveServerByIndex(index: Int) { fun setActiveServerByIndex(index: Int) {
Timber.d("setActiveServerByIndex $index") Timber.d("setActiveServerByIndex $index")
if (index < 1) { if (index <= OFFLINE_DB_INDEX) {
// Offline mode is selected // Offline mode is selected
setActiveServerId(0) setActiveServerId(OFFLINE_DB_ID)
return return
} }
@ -103,22 +90,20 @@ class ActiveServerProvider(
Timber.i("Switching to new database, id:$activeServer") Timber.i("Switching to new database, id:$activeServer")
cachedServerId = activeServer cachedServerId = activeServer
return Room.databaseBuilder( return buildDatabase(cachedServerId)
UApp.applicationContext(),
MetaDatabase::class.java,
METADATA_DB + cachedServerId
)
.fallbackToDestructiveMigrationOnDowngrade()
.build()
} }
val offlineMetaDatabase: MetaDatabase by lazy { val offlineMetaDatabase: MetaDatabase by lazy {
Room.databaseBuilder( buildDatabase(OFFLINE_DB_ID)
}
private fun buildDatabase(id: Int?): MetaDatabase {
return Room.databaseBuilder(
UApp.applicationContext(), UApp.applicationContext(),
MetaDatabase::class.java, MetaDatabase::class.java,
METADATA_DB + 0 METADATA_DB + id
) )
.fallbackToDestructiveMigrationOnDowngrade() .fallbackToDestructiveMigration()
.build() .build()
} }
@ -177,8 +162,24 @@ class ActiveServerProvider(
} }
companion object { companion object {
const val METADATA_DB = "$DB_FILENAME-meta-" const val METADATA_DB = "$DB_FILENAME-meta-"
const val OFFLINE_DB_ID = -1
const val OFFLINE_DB_INDEX = 0
val OFFLINE_DB = ServerSetting(
id = OFFLINE_DB_ID,
index = OFFLINE_DB_INDEX,
name = UApp.applicationContext().getString(R.string.main_offline),
url = "http://localhost",
userName = "",
password = "",
jukeboxByDefault = false,
allowSelfSignedCertificate = false,
ldapSupport = false,
musicFolderId = "",
minimumApiVersion = null
)
val liveActiveServerId: MutableLiveData<Int> = MutableLiveData(getActiveServerId()) val liveActiveServerId: MutableLiveData<Int> = MutableLiveData(getActiveServerId())
/** /**
@ -186,7 +187,7 @@ class ActiveServerProvider(
* @return True, if the "Offline" mode is selected * @return True, if the "Offline" mode is selected
*/ */
fun isOffline(): Boolean { fun isOffline(): Boolean {
return getActiveServerId() < 1 return getActiveServerId() == OFFLINE_DB_ID
} }
/** /**

View File

@ -9,7 +9,11 @@ import androidx.sqlite.db.SupportSQLiteDatabase
* Room Database to be used to store global data for the whole app. * Room Database to be used to store global data for the whole app.
* This could be settings or data that are not specific to any remote music database * This could be settings or data that are not specific to any remote music database
*/ */
@Database(entities = [ServerSetting::class], version = 4) @Database(
entities = [ServerSetting::class],
version = 4,
exportSchema = true
)
abstract class AppDatabase : RoomDatabase() { abstract class AppDatabase : RoomDatabase() {
/** /**
@ -175,3 +179,89 @@ val MIGRATION_4_3: Migration = object : Migration(4, 3) {
) )
} }
} }
val MIGRATION_4_5: Migration = object : Migration(4, 5) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL(
"""
CREATE TABLE IF NOT EXISTS `_new_ServerSetting` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`index` INTEGER NOT NULL,
`name` TEXT NOT NULL,
`url` TEXT NOT NULL,
`color` INTEGER,
`userName` TEXT NOT NULL,
`password` TEXT NOT NULL,
`jukeboxByDefault` INTEGER NOT NULL,
`allowSelfSignedCertificate` INTEGER NOT NULL,
`ldapSupport` INTEGER NOT NULL,
`musicFolderId` TEXT,
`minimumApiVersion` TEXT,
`chatSupport` INTEGER,
`bookmarkSupport` INTEGER,
`shareSupport` INTEGER,
`podcastSupport` INTEGER
)
""".trimIndent()
)
database.execSQL(
"""
INSERT INTO `_new_ServerSetting` (
`ldapSupport`,`musicFolderId`,`color`,`index`,`userName`,`minimumApiVersion`,
`jukeboxByDefault`,`url`,`password`,`shareSupport`,`bookmarkSupport`,`name`,
`podcastSupport`,`id`,`allowSelfSignedCertificate`,`chatSupport`
)
SELECT `ldapSupport`,`musicFolderId`,`color`,`index`,`userName`,
`minimumApiVersion`,`jukeboxByDefault`,`url`,`password`,`shareSupport`,
`bookmarkSupport`,`name`,`podcastSupport`,`id`,`allowSelfSignedCertificate`,
`chatSupport`
FROM `ServerSetting`
""".trimIndent()
)
database.execSQL("DROP TABLE `ServerSetting`")
database.execSQL("ALTER TABLE `_new_ServerSetting` RENAME TO `ServerSetting`")
}
}
val MIGRATION_5_4: Migration = object : Migration(5, 4) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL(
"""
CREATE TABLE IF NOT EXISTS `_new_ServerSetting` (
`id` INTEGER PRIMARY KEY NOT NULL,
`index` INTEGER NOT NULL,
`name` TEXT NOT NULL,
`url` TEXT NOT NULL,
`color` INTEGER,
`userName` TEXT NOT NULL,
`password` TEXT NOT NULL,
`jukeboxByDefault` INTEGER NOT NULL,
`allowSelfSignedCertificate` INTEGER NOT NULL,
`ldapSupport` INTEGER NOT NULL,
`musicFolderId` TEXT,
`minimumApiVersion` TEXT,
`chatSupport` INTEGER,
`bookmarkSupport` INTEGER,
`shareSupport` INTEGER,
`podcastSupport` INTEGER
)
""".trimIndent()
)
database.execSQL(
"""
INSERT INTO `_new_ServerSetting` (
`ldapSupport`,`musicFolderId`,`color`,`index`,`userName`,`minimumApiVersion`,
`jukeboxByDefault`,`url`,`password`,`shareSupport`,`bookmarkSupport`,`name`,
`podcastSupport`,`id`,`allowSelfSignedCertificate`,`chatSupport`
)
SELECT `ldapSupport`,`musicFolderId`,`color`,`index`,`userName`,
`minimumApiVersion`,`jukeboxByDefault`,`url`,`password`,`shareSupport`,
`bookmarkSupport`,`name`,`podcastSupport`,`id`,`allowSelfSignedCertificate`,
`chatSupport`
FROM `ServerSetting`
""".trimIndent()
)
database.execSQL("DROP TABLE `ServerSetting`")
database.execSQL("ALTER TABLE `_new_ServerSetting` RENAME TO `ServerSetting`")
}
}

View File

@ -39,7 +39,4 @@ data class ServerSetting(
constructor() : this ( constructor() : this (
-1, 0, "", "", null, "", "", false, false, false, null, null -1, 0, "", "", null, "", "", false, false, false, null, null
) )
constructor(name: String, url: String) : this(
-1, 0, name, url, null, "", "", false, false, false, null, null
)
} }

View File

@ -12,6 +12,8 @@ import org.moire.ultrasonic.data.MIGRATION_2_3
import org.moire.ultrasonic.data.MIGRATION_3_2 import org.moire.ultrasonic.data.MIGRATION_3_2
import org.moire.ultrasonic.data.MIGRATION_3_4 import org.moire.ultrasonic.data.MIGRATION_3_4
import org.moire.ultrasonic.data.MIGRATION_4_3 import org.moire.ultrasonic.data.MIGRATION_4_3
import org.moire.ultrasonic.data.MIGRATION_4_5
import org.moire.ultrasonic.data.MIGRATION_5_4
import org.moire.ultrasonic.model.ServerSettingsModel import org.moire.ultrasonic.model.ServerSettingsModel
import org.moire.ultrasonic.util.Settings import org.moire.ultrasonic.util.Settings
@ -36,6 +38,8 @@ val appPermanentStorage = module {
.addMigrations(MIGRATION_3_2) .addMigrations(MIGRATION_3_2)
.addMigrations(MIGRATION_3_4) .addMigrations(MIGRATION_3_4)
.addMigrations(MIGRATION_4_3) .addMigrations(MIGRATION_4_3)
.addMigrations(MIGRATION_4_5)
.addMigrations(MIGRATION_5_4)
.build() .build()
} }

View File

@ -15,6 +15,7 @@ import kotlinx.coroutines.withContext
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
import org.moire.ultrasonic.R import org.moire.ultrasonic.R
import org.moire.ultrasonic.adapters.ServerRowAdapter
import org.moire.ultrasonic.data.ActiveServerProvider import org.moire.ultrasonic.data.ActiveServerProvider
import org.moire.ultrasonic.fragment.EditServerFragment.Companion.EDIT_SERVER_INTENT_INDEX import org.moire.ultrasonic.fragment.EditServerFragment.Companion.EDIT_SERVER_INTENT_INDEX
import org.moire.ultrasonic.model.ServerSettingsModel import org.moire.ultrasonic.model.ServerSettingsModel
@ -103,11 +104,10 @@ class ServerSelectorFragment : Fragment() {
super.onResume() super.onResume()
val serverList = serverSettingsModel.getServerList() val serverList = serverSettingsModel.getServerList()
serverList.observe( serverList.observe(
this, this
{ t -> ) { t ->
serverRowAdapter!!.setData(t.toTypedArray()) serverRowAdapter!!.setData(t.toTypedArray())
} }
)
} }
/** /**