2021-02-08 21:46:31 +01:00
|
|
|
package org.moire.ultrasonic.fragment
|
2020-09-18 09:37:19 +02:00
|
|
|
|
2021-04-21 23:01:59 +02:00
|
|
|
import android.app.Application
|
2020-09-18 09:37:19 +02:00
|
|
|
import android.content.SharedPreferences
|
2021-04-21 23:01:59 +02:00
|
|
|
import androidx.lifecycle.AndroidViewModel
|
2020-09-18 09:37:19 +02:00
|
|
|
import androidx.lifecycle.LiveData
|
|
|
|
import androidx.lifecycle.viewModelScope
|
2021-02-15 16:27:33 +01:00
|
|
|
import androidx.preference.PreferenceManager
|
2021-02-17 18:36:36 +01:00
|
|
|
import kotlinx.coroutines.CoroutineScope
|
|
|
|
import kotlinx.coroutines.Dispatchers
|
|
|
|
import kotlinx.coroutines.SupervisorJob
|
2020-09-18 09:37:19 +02:00
|
|
|
import kotlinx.coroutines.launch
|
2020-09-19 11:56:10 +02:00
|
|
|
import kotlinx.coroutines.runBlocking
|
2020-09-18 09:37:19 +02:00
|
|
|
import org.moire.ultrasonic.data.ActiveServerProvider
|
|
|
|
import org.moire.ultrasonic.data.ServerSetting
|
|
|
|
import org.moire.ultrasonic.data.ServerSettingDao
|
2020-09-30 14:47:59 +02:00
|
|
|
import timber.log.Timber
|
2020-09-18 09:37:19 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* ViewModel to be used in Activities which will handle Server Settings
|
|
|
|
*/
|
|
|
|
class ServerSettingsModel(
|
|
|
|
private val repository: ServerSettingDao,
|
|
|
|
private val activeServerProvider: ActiveServerProvider,
|
2021-04-21 23:01:59 +02:00
|
|
|
application: Application
|
|
|
|
) : AndroidViewModel(application) {
|
2020-09-18 09:37:19 +02:00
|
|
|
|
|
|
|
companion object {
|
2020-09-24 21:00:21 +02:00
|
|
|
private const val PREFERENCES_KEY_SERVER_MIGRATED = "serverMigrated"
|
2020-09-18 09:37:19 +02:00
|
|
|
// These constants were removed from Constants.java as they are deprecated and only used here
|
|
|
|
private const val PREFERENCES_KEY_JUKEBOX_BY_DEFAULT = "jukeboxEnabled"
|
|
|
|
private const val PREFERENCES_KEY_SERVER_NAME = "serverName"
|
|
|
|
private const val PREFERENCES_KEY_SERVER_URL = "serverUrl"
|
|
|
|
private const val PREFERENCES_KEY_ACTIVE_SERVERS = "activeServers"
|
|
|
|
private const val PREFERENCES_KEY_USERNAME = "username"
|
|
|
|
private const val PREFERENCES_KEY_PASSWORD = "password"
|
|
|
|
private const val PREFERENCES_KEY_ALLOW_SELF_SIGNED_CERTIFICATE = "allowSSCertificate"
|
|
|
|
private const val PREFERENCES_KEY_LDAP_SUPPORT = "enableLdapSupport"
|
|
|
|
private const val PREFERENCES_KEY_MUSIC_FOLDER_ID = "musicFolderId"
|
|
|
|
}
|
|
|
|
|
2021-02-17 18:36:36 +01:00
|
|
|
private val appScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
|
|
|
|
2020-09-18 09:37:19 +02:00
|
|
|
/**
|
2020-09-19 11:56:10 +02:00
|
|
|
* This function will try and convert settings from the Preferences to the Database
|
|
|
|
* @return True, if the migration was executed, False otherwise
|
2020-09-18 09:37:19 +02:00
|
|
|
*/
|
2020-09-19 11:56:10 +02:00
|
|
|
fun migrateFromPreferences(): Boolean {
|
|
|
|
var migrated = true
|
|
|
|
|
|
|
|
runBlocking {
|
2020-09-22 17:03:04 +02:00
|
|
|
val rowCount = repository.count()
|
2020-09-18 09:37:19 +02:00
|
|
|
|
2020-09-22 17:03:04 +02:00
|
|
|
if (rowCount == null || rowCount == 0) {
|
2020-09-18 09:37:19 +02:00
|
|
|
// First time load up the server settings from the Preferences
|
2020-09-22 17:03:04 +02:00
|
|
|
val dbServerList = mutableListOf<ServerSetting>()
|
2021-04-21 23:01:59 +02:00
|
|
|
val context = getApplication<Application>().applicationContext
|
2020-09-18 09:37:19 +02:00
|
|
|
val settings = PreferenceManager.getDefaultSharedPreferences(context)
|
|
|
|
val serverNum = settings.getInt(PREFERENCES_KEY_ACTIVE_SERVERS, 0)
|
|
|
|
|
|
|
|
if (serverNum != 0) {
|
2020-09-22 20:18:36 +02:00
|
|
|
var index = 1
|
2020-09-18 09:37:19 +02:00
|
|
|
for (x in 1 until serverNum + 1) {
|
2020-09-22 21:50:53 +02:00
|
|
|
val newServerSetting = loadServerSettingFromPreferences(x, index, settings)
|
2020-09-19 11:56:10 +02:00
|
|
|
if (newServerSetting != null) {
|
|
|
|
dbServerList.add(newServerSetting)
|
|
|
|
repository.insert(newServerSetting)
|
2020-09-22 20:18:36 +02:00
|
|
|
index++
|
2020-09-30 14:47:59 +02:00
|
|
|
Timber.i(
|
2020-09-19 11:56:10 +02:00
|
|
|
"Imported server from Preferences to Database:" +
|
|
|
|
" ${newServerSetting.name}"
|
|
|
|
)
|
|
|
|
}
|
2020-09-18 09:37:19 +02:00
|
|
|
}
|
2020-09-19 11:56:10 +02:00
|
|
|
} else {
|
|
|
|
migrated = false
|
2020-09-18 09:37:19 +02:00
|
|
|
}
|
|
|
|
}
|
2020-09-19 11:56:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return migrated
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieves the list of the configured servers from the database.
|
|
|
|
* This function is asynchronous, uses LiveData to provide the Setting.
|
|
|
|
*/
|
|
|
|
fun getServerList(): LiveData<List<ServerSetting>> {
|
2020-09-24 20:32:51 +02:00
|
|
|
// This check should run before returning any result
|
|
|
|
runBlocking {
|
|
|
|
if (areIndexesMissing()) {
|
|
|
|
reindexSettings()
|
2020-09-24 18:20:59 +02:00
|
|
|
}
|
2020-09-18 09:37:19 +02:00
|
|
|
}
|
2020-09-24 20:32:51 +02:00
|
|
|
return repository.loadAllServerSettings()
|
2020-09-18 09:37:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieves a single Server Setting by its index
|
|
|
|
* This function is asynchronous, uses LiveData to provide the Setting.
|
|
|
|
*/
|
|
|
|
fun getServerSetting(index: Int): LiveData<ServerSetting?> {
|
2020-09-24 20:32:51 +02:00
|
|
|
return repository.getLiveServerSettingByIndex(index)
|
2020-09-18 09:37:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Moves a Setting up in the Server List by decreasing its index
|
|
|
|
*/
|
|
|
|
fun moveItemUp(index: Int) {
|
2020-09-24 20:32:51 +02:00
|
|
|
if (index <= 1) return
|
2020-09-18 09:37:19 +02:00
|
|
|
|
2020-09-24 20:32:51 +02:00
|
|
|
viewModelScope.launch {
|
|
|
|
val itemToBeMoved = repository.findByIndex(index)
|
|
|
|
val previousItem = repository.findByIndex(index - 1)
|
2020-09-18 09:37:19 +02:00
|
|
|
|
2020-09-24 20:32:51 +02:00
|
|
|
if (itemToBeMoved != null && previousItem != null) {
|
|
|
|
itemToBeMoved.index = previousItem.index
|
|
|
|
previousItem.index = index
|
2020-09-18 09:37:19 +02:00
|
|
|
|
2020-09-24 20:32:51 +02:00
|
|
|
repository.update(itemToBeMoved, previousItem)
|
|
|
|
activeServerProvider.invalidateCache()
|
|
|
|
}
|
2020-09-18 09:37:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Moves a Setting down in the Server List by increasing its index
|
|
|
|
*/
|
|
|
|
fun moveItemDown(index: Int) {
|
2020-09-24 20:32:51 +02:00
|
|
|
viewModelScope.launch {
|
|
|
|
if (index < repository.getMaxIndex() ?: 0) {
|
|
|
|
val itemToBeMoved = repository.findByIndex(index)
|
|
|
|
val nextItem = repository.findByIndex(index + 1)
|
2020-09-18 09:37:19 +02:00
|
|
|
|
2020-09-24 20:32:51 +02:00
|
|
|
if (itemToBeMoved != null && nextItem != null) {
|
|
|
|
itemToBeMoved.index = nextItem.index
|
|
|
|
nextItem.index = index
|
2020-09-18 09:37:19 +02:00
|
|
|
|
2020-09-24 20:32:51 +02:00
|
|
|
repository.update(itemToBeMoved, nextItem)
|
|
|
|
activeServerProvider.invalidateCache()
|
|
|
|
}
|
|
|
|
}
|
2020-09-18 09:37:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes a Setting from the database
|
|
|
|
*/
|
|
|
|
fun deleteItem(index: Int) {
|
|
|
|
if (index == 0) return
|
|
|
|
|
|
|
|
viewModelScope.launch {
|
2020-09-24 20:32:51 +02:00
|
|
|
val itemToBeDeleted = repository.findByIndex(index)
|
|
|
|
if (itemToBeDeleted != null) {
|
|
|
|
repository.delete(itemToBeDeleted)
|
2020-09-30 14:47:59 +02:00
|
|
|
Timber.d("deleteItem deleted index: $index")
|
2020-09-24 20:32:51 +02:00
|
|
|
reindexSettings()
|
|
|
|
activeServerProvider.invalidateCache()
|
2020-09-18 09:37:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates a Setting in the database
|
|
|
|
*/
|
|
|
|
fun updateItem(serverSetting: ServerSetting?) {
|
|
|
|
if (serverSetting == null) return
|
|
|
|
|
2021-02-17 18:36:36 +01:00
|
|
|
appScope.launch {
|
2020-09-18 09:37:19 +02:00
|
|
|
repository.update(serverSetting)
|
|
|
|
activeServerProvider.invalidateCache()
|
2020-09-30 14:47:59 +02:00
|
|
|
Timber.d("updateItem updated server setting: $serverSetting")
|
2020-09-18 09:37:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Inserts a new Setting into the database
|
|
|
|
*/
|
|
|
|
fun saveNewItem(serverSetting: ServerSetting?) {
|
|
|
|
if (serverSetting == null) return
|
|
|
|
|
2021-02-17 18:36:36 +01:00
|
|
|
appScope.launch {
|
2020-09-22 17:03:04 +02:00
|
|
|
serverSetting.index = (repository.count() ?: 0) + 1
|
2020-09-24 18:20:59 +02:00
|
|
|
serverSetting.id = (repository.getMaxId() ?: 0) + 1
|
2020-09-18 09:37:19 +02:00
|
|
|
repository.insert(serverSetting)
|
2020-09-30 14:47:59 +02:00
|
|
|
Timber.d("saveNewItem saved server setting: $serverSetting")
|
2020-09-18 09:37:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads up a Server Setting stored in the obsolete Preferences
|
|
|
|
*/
|
|
|
|
private fun loadServerSettingFromPreferences(
|
2020-09-22 21:50:53 +02:00
|
|
|
preferenceId: Int,
|
|
|
|
serverId: Int,
|
2020-09-18 09:37:19 +02:00
|
|
|
settings: SharedPreferences
|
2020-09-19 11:56:10 +02:00
|
|
|
): ServerSetting? {
|
2020-09-22 21:50:53 +02:00
|
|
|
val url = settings.getString(PREFERENCES_KEY_SERVER_URL + preferenceId, "")
|
|
|
|
val userName = settings.getString(PREFERENCES_KEY_USERNAME + preferenceId, "")
|
2020-09-24 21:00:21 +02:00
|
|
|
val isMigrated = settings.getBoolean(PREFERENCES_KEY_SERVER_MIGRATED + preferenceId, false)
|
2020-09-19 11:56:10 +02:00
|
|
|
|
2020-09-24 21:00:21 +02:00
|
|
|
if (url.isNullOrEmpty() || userName.isNullOrEmpty() || isMigrated) return null
|
|
|
|
setServerMigrated(settings, preferenceId)
|
2020-09-19 11:56:10 +02:00
|
|
|
|
2020-09-18 09:37:19 +02:00
|
|
|
return ServerSetting(
|
2020-09-23 16:26:54 +02:00
|
|
|
preferenceId,
|
2020-09-22 21:50:53 +02:00
|
|
|
serverId,
|
|
|
|
settings.getString(PREFERENCES_KEY_SERVER_NAME + preferenceId, "")!!,
|
2020-09-19 11:56:10 +02:00
|
|
|
url,
|
|
|
|
userName,
|
2020-09-22 21:50:53 +02:00
|
|
|
settings.getString(PREFERENCES_KEY_PASSWORD + preferenceId, "")!!,
|
|
|
|
settings.getBoolean(PREFERENCES_KEY_JUKEBOX_BY_DEFAULT + preferenceId, false),
|
2020-09-22 22:01:33 +02:00
|
|
|
settings.getBoolean(
|
|
|
|
PREFERENCES_KEY_ALLOW_SELF_SIGNED_CERTIFICATE + preferenceId,
|
|
|
|
false
|
|
|
|
),
|
2020-09-22 21:50:53 +02:00
|
|
|
settings.getBoolean(PREFERENCES_KEY_LDAP_SUPPORT + preferenceId, false),
|
2020-10-13 21:41:01 +02:00
|
|
|
settings.getString(PREFERENCES_KEY_MUSIC_FOLDER_ID + preferenceId, null),
|
|
|
|
null
|
2020-09-18 09:37:19 +02:00
|
|
|
)
|
|
|
|
}
|
2020-09-24 18:20:59 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if there are any missing indexes in the ServerSetting list
|
|
|
|
* For displaying the Server Settings in a ListView, it is mandatory that their indexes
|
|
|
|
* are'nt missing. Ideally the indexes are continuous, but some circumstances (e.g.
|
|
|
|
* concurrency or migration errors) may get them out of order.
|
|
|
|
* This would make the List Adapter crash, so it is best to prepare and check the list.
|
|
|
|
*/
|
2020-09-24 20:32:51 +02:00
|
|
|
private suspend fun areIndexesMissing(): Boolean {
|
|
|
|
for (i in 1 until getMaximumIndexToCheck() + 1) {
|
|
|
|
if (repository.findByIndex(i) == null) return true
|
2020-09-24 18:20:59 +02:00
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This function updates all the Server Settings in the DB so their indexing is continuous.
|
|
|
|
*/
|
2020-09-24 20:32:51 +02:00
|
|
|
private suspend fun reindexSettings() {
|
|
|
|
var newIndex = 1
|
|
|
|
for (i in 1 until getMaximumIndexToCheck() + 1) {
|
2020-09-24 21:00:21 +02:00
|
|
|
val setting = repository.findByIndex(i)
|
2020-09-24 20:32:51 +02:00
|
|
|
if (setting != null) {
|
|
|
|
setting.index = newIndex
|
|
|
|
newIndex++
|
|
|
|
repository.update(setting)
|
2020-09-30 14:47:59 +02:00
|
|
|
Timber.d("reindexSettings saved $setting")
|
2020-09-24 20:32:51 +02:00
|
|
|
}
|
2020-09-24 18:20:59 +02:00
|
|
|
}
|
2020-09-24 20:32:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private suspend fun getMaximumIndexToCheck(): Int {
|
|
|
|
val rowsInDatabase = repository.count() ?: 0
|
|
|
|
val indexesInDatabase = repository.getMaxIndex() ?: 0
|
|
|
|
if (rowsInDatabase > indexesInDatabase) return rowsInDatabase
|
|
|
|
return indexesInDatabase
|
2020-09-24 18:20:59 +02:00
|
|
|
}
|
2020-09-24 21:00:21 +02:00
|
|
|
|
|
|
|
private fun setServerMigrated(settings: SharedPreferences, preferenceId: Int) {
|
|
|
|
val editor = settings.edit()
|
|
|
|
editor.putBoolean(PREFERENCES_KEY_SERVER_MIGRATED + preferenceId, true)
|
|
|
|
editor.apply()
|
|
|
|
}
|
2020-09-18 09:37:19 +02:00
|
|
|
}
|