mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-01-31 13:48:20 +01:00
[Config] Implement (basic) new app config storage.
This commit is contained in:
parent
d1a5d8cba9
commit
c2e7931ea6
@ -68,6 +68,7 @@ import me.leolin.shortcutbadger.ShortcutBadger;
|
||||
import okhttp3.ConnectionSpec;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.TlsVersion;
|
||||
import pl.szczodrzynski.edziennik.config.Config;
|
||||
import pl.szczodrzynski.edziennik.data.db.AppDb;
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.debuglog.DebugLog;
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore;
|
||||
@ -145,6 +146,7 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
||||
//public Register register; // REGISTER for current profile, read from registerStore
|
||||
|
||||
public ProfileFull profile;
|
||||
public Config config;
|
||||
|
||||
// other stuff
|
||||
public Gson gson;
|
||||
@ -194,6 +196,8 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
||||
gson = new Gson();
|
||||
networkUtils = new NetworkUtils(this);
|
||||
|
||||
config = new Config(db);
|
||||
|
||||
Iconics.init(getApplicationContext());
|
||||
Iconics.registerFont(SzkolnyFont.INSTANCE);
|
||||
|
||||
@ -636,6 +640,7 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
|
||||
MainActivity.Companion.setUseOldMessages(profile.getLoginStoreType() == LOGIN_TYPE_MOBIDZIENNIK && appConfig.mobidziennikOldMessages == 1);
|
||||
profileId = profile.getId();
|
||||
appSharedPrefs.edit().putInt("current_profile_id", profile.getId()).apply();
|
||||
config.setProfile(profileId);
|
||||
}
|
||||
else if (!loadedLast) {
|
||||
profileLoadById(profileLastId(), true);
|
||||
|
@ -973,7 +973,7 @@ class MainActivity : AppCompatActivity() {
|
||||
val item = DrawerPrimaryItem()
|
||||
.withIdentifier(target.id.toLong())
|
||||
.withName(target.name)
|
||||
.withHiddenInMiniDrawer(!app.appConfig.miniDrawerButtonIds.contains(target.id))
|
||||
.withHiddenInMiniDrawer(!app.config.ui.miniMenuButtons.contains(target.id))
|
||||
.also { if (target.description != null) it.withDescription(target.description!!) }
|
||||
.also { if (target.icon != null) it.withIcon(target.icon!!) }
|
||||
.also { if (target.title != null) it.withAppTitle(getString(target.title!!)) }
|
||||
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.config
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import pl.szczodrzynski.edziennik.data.db.AppDb
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class Config(val db: AppDb) : CoroutineScope {
|
||||
companion object {
|
||||
const val DATA_VERSION = 1
|
||||
}
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Default
|
||||
|
||||
private var profileId: Int? = null
|
||||
val values: HashMap<String, String?> = hashMapOf()
|
||||
//private val profileValues: HashMap<String, String?> = hashMapOf()
|
||||
|
||||
val ui by lazy { ConfigUI(this) }
|
||||
val sync by lazy { ConfigSync(this) }
|
||||
val timetable by lazy { ConfigTimetable(this) }
|
||||
val grades by lazy { ConfigGrades(this) }
|
||||
|
||||
private var mDataVersion: Int? = null
|
||||
var dataVersion: Int
|
||||
get() { mDataVersion = mDataVersion ?: values.get("dataVersion", 0); return mDataVersion ?: 0 }
|
||||
set(value) { set(-1, "dataVersion", value); mDataVersion = value }
|
||||
|
||||
init {
|
||||
db.configDao().getAllNow().toHashMap(values)
|
||||
if (dataVersion < DATA_VERSION)
|
||||
ConfigMigration(this)
|
||||
}
|
||||
fun setProfile(profileId: Int) {
|
||||
this.profileId = profileId
|
||||
//profileValues.clear()
|
||||
//db.configDao().getAllNow(profileId).toHashMap(profileValues)
|
||||
}
|
||||
|
||||
fun set(profileId: Int, key: String, value: String?) {
|
||||
//if (profileId == -1)
|
||||
values[key] = value
|
||||
/*else
|
||||
profileValues[key] = value*/
|
||||
launch {
|
||||
db.configDao().add(ConfigEntry(profileId, key, value))
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.config
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
|
||||
@Dao
|
||||
interface ConfigDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun add(entry: ConfigEntry)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun addAll(list: List<ConfigEntry>)
|
||||
|
||||
@Query("SELECT * FROM config WHERE profileId = -1")
|
||||
fun getAllNow(): List<ConfigEntry>
|
||||
|
||||
@Query("SELECT * FROM config WHERE profileId = :profileId")
|
||||
fun getAllNow(profileId: Int): List<ConfigEntry>
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.config
|
||||
|
||||
import androidx.room.Entity
|
||||
|
||||
@Entity(tableName = "config", primaryKeys = ["profileId", "key"])
|
||||
data class ConfigEntry(
|
||||
val profileId: Int = -1,
|
||||
val key: String,
|
||||
val value: String?
|
||||
)
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.config
|
||||
|
||||
import com.google.gson.*
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
|
||||
private val gson = Gson()
|
||||
|
||||
fun Config.set(profileId: Int, key: String, value: Int) {
|
||||
set(profileId, key, value.toString())
|
||||
}
|
||||
fun Config.set(profileId: Int, key: String, value: Boolean) {
|
||||
set(profileId, key, value.toString())
|
||||
}
|
||||
fun Config.set(profileId: Int, key: String, value: Long) {
|
||||
set(profileId, key, value.toString())
|
||||
}
|
||||
fun Config.set(profileId: Int, key: String, value: Float) {
|
||||
set(profileId, key, value.toString())
|
||||
}
|
||||
fun Config.set(profileId: Int, key: String, value: Date?) {
|
||||
set(profileId, key, value?.stringY_m_d)
|
||||
}
|
||||
fun Config.set(profileId: Int, key: String, value: Time?) {
|
||||
set(profileId, key, value?.stringValue)
|
||||
}
|
||||
fun Config.set(profileId: Int, key: String, value: JsonElement?) {
|
||||
set(profileId, key, value?.toString())
|
||||
}
|
||||
fun Config.set(profileId: Int, key: String, value: List<Any>?) {
|
||||
set(profileId, key, value?.let { gson.toJson(it) })
|
||||
}
|
||||
fun Config.setStringList(profileId: Int, key: String, value: List<String>?) {
|
||||
set(profileId, key, value?.let { gson.toJson(it) })
|
||||
}
|
||||
fun Config.setIntList(profileId: Int, key: String, value: List<Int>?) {
|
||||
set(profileId, key, value?.let { gson.toJson(it) })
|
||||
}
|
||||
fun Config.setLongList(profileId: Int, key: String, value: List<Long>?) {
|
||||
set(profileId, key, value?.let { gson.toJson(it) })
|
||||
}
|
||||
|
||||
fun HashMap<String, String?>.get(key: String, default: String?): String? {
|
||||
return this[key] ?: default
|
||||
}
|
||||
fun HashMap<String, String?>.get(key: String, default: Boolean): Boolean {
|
||||
return this[key]?.toBoolean() ?: default
|
||||
}
|
||||
fun HashMap<String, String?>.get(key: String, default: Int): Int {
|
||||
return this[key]?.toIntOrNull() ?: default
|
||||
}
|
||||
fun HashMap<String, String?>.get(key: String, default: Long): Long {
|
||||
return this[key]?.toLongOrNull() ?: default
|
||||
}
|
||||
fun HashMap<String, String?>.get(key: String, default: Float): Float {
|
||||
return this[key]?.toFloatOrNull() ?: default
|
||||
}
|
||||
fun HashMap<String, String?>.get(key: String, default: Date?): Date? {
|
||||
return this[key]?.let { Date.fromY_m_d(it) } ?: default
|
||||
}
|
||||
fun HashMap<String, String?>.get(key: String, default: Time?): Time? {
|
||||
return this[key]?.let { Time.fromHms(it) } ?: default
|
||||
}
|
||||
fun HashMap<String, String?>.get(key: String, default: JsonObject?): JsonObject? {
|
||||
return this[key]?.let { JsonParser().parse(it)?.asJsonObject } ?: default
|
||||
}
|
||||
fun HashMap<String, String?>.get(key: String, default: JsonArray?): JsonArray? {
|
||||
return this[key]?.let { JsonParser().parse(it)?.asJsonArray } ?: default
|
||||
}
|
||||
fun <T> HashMap<String, String?>.get(key: String, default: List<T>?): List<T>? {
|
||||
return this[key]?.let { gson.fromJson<List<T>>(it, object: TypeToken<List<T>>(){}.type) } ?: default
|
||||
}
|
||||
fun HashMap<String, String?>.getStringList(key: String, default: List<String>?): List<String>? {
|
||||
return this[key]?.let { gson.fromJson<List<String>>(it, object: TypeToken<List<String>>(){}.type) } ?: default
|
||||
}
|
||||
fun HashMap<String, String?>.getIntList(key: String, default: List<Int>?): List<Int>? {
|
||||
return this[key]?.let { gson.fromJson<List<Int>>(it, object: TypeToken<List<Int>>(){}.type) } ?: default
|
||||
}
|
||||
fun HashMap<String, String?>.getLongList(key: String, default: List<Long>?): List<Long>? {
|
||||
return this[key]?.let { gson.fromJson<List<Long>>(it, object: TypeToken<List<Long>>(){}.type) } ?: default
|
||||
}
|
||||
|
||||
fun List<ConfigEntry>.toHashMap(map: HashMap<String, String?>) {
|
||||
map.clear()
|
||||
forEach {
|
||||
map[it.key] = it.value
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.config
|
||||
|
||||
class ConfigGrades(val config: Config) {
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.config
|
||||
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
|
||||
class ConfigMigration(config: Config) {
|
||||
init { config.apply {
|
||||
if (dataVersion < 1) {
|
||||
ui.theme = 1
|
||||
sync.enabled = true
|
||||
sync.interval = 60*60; // seconds
|
||||
ui.miniMenuButtons = listOf(
|
||||
MainActivity.DRAWER_ITEM_HOME,
|
||||
MainActivity.DRAWER_ITEM_TIMETABLE,
|
||||
MainActivity.DRAWER_ITEM_AGENDA,
|
||||
MainActivity.DRAWER_ITEM_GRADES,
|
||||
MainActivity.DRAWER_ITEM_MESSAGES,
|
||||
MainActivity.DRAWER_ITEM_HOMEWORK,
|
||||
MainActivity.DRAWER_ITEM_SETTINGS
|
||||
)
|
||||
dataVersion = 1
|
||||
}
|
||||
}}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.config
|
||||
|
||||
class ConfigSync(val config: Config) {
|
||||
private var mSyncEnabled: Boolean? = null
|
||||
var enabled: Boolean
|
||||
get() { mSyncEnabled = mSyncEnabled ?: config.values.get("syncEnabled", true); return mSyncEnabled ?: true }
|
||||
set(value) { config.set(-1, "syncEnabled", value); mSyncEnabled = value }
|
||||
|
||||
private var mSyncOnlyWifi: Boolean? = null
|
||||
var onlyWifi: Boolean
|
||||
get() { mSyncOnlyWifi = mSyncOnlyWifi ?: config.values.get("syncOnlyWifi", false); return mSyncOnlyWifi ?: notifyAboutUpdates }
|
||||
set(value) { config.set(-1, "syncOnlyWifi", value); mSyncOnlyWifi = value }
|
||||
|
||||
private var mSyncInterval: Int? = null
|
||||
var interval: Int
|
||||
get() { mSyncInterval = mSyncInterval ?: config.values.get("syncInterval", 60*60); return mSyncInterval ?: 60*60 }
|
||||
set(value) { config.set(-1, "syncInterval", value); mSyncInterval = value }
|
||||
|
||||
private var mNotifyAboutUpdates: Boolean? = null
|
||||
var notifyAboutUpdates: Boolean
|
||||
get() { mNotifyAboutUpdates = mNotifyAboutUpdates ?: config.values.get("notifyAboutUpdates", true); return mNotifyAboutUpdates ?: true }
|
||||
set(value) { config.set(-1, "notifyAboutUpdates", value); mNotifyAboutUpdates = value }
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.config
|
||||
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
|
||||
class ConfigTimetable(val config: Config) {
|
||||
private var mBellSyncMultiplier: Int? = null
|
||||
var bellSyncMultiplier: Int
|
||||
get() { mBellSyncMultiplier = mBellSyncMultiplier ?: config.values.get("bellSyncMultiplier", 0); return mBellSyncMultiplier ?: 0 }
|
||||
set(value) { config.set(-1, "bellSyncMultiplier", value); mBellSyncMultiplier = value }
|
||||
|
||||
private var mBellSyncDiff: Time? = null
|
||||
var bellSyncDiff: Time?
|
||||
get() { mBellSyncDiff = mBellSyncDiff ?: config.values.get("bellSyncDiff", null as Time?); return mBellSyncDiff }
|
||||
set(value) { config.set(-1, "bellSyncDiff", value); mBellSyncDiff = value }
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-11-26.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.config
|
||||
|
||||
class ConfigUI(val config: Config) {
|
||||
private var mTheme: Int? = null
|
||||
var theme: Int
|
||||
get() { mTheme = mTheme ?: config.values.get("theme", 1); return mTheme ?: 1 }
|
||||
set(value) { config.set(-1, "theme", value); mTheme = value }
|
||||
|
||||
private var mHeaderBackground: String? = null
|
||||
var headerBackground: String?
|
||||
get() { mHeaderBackground = mHeaderBackground ?: config.values.get("headerBackground", null as String?); return mHeaderBackground }
|
||||
set(value) { config.set(-1, "headerBg", value); mHeaderBackground = value }
|
||||
|
||||
private var mAppBackground: String? = null
|
||||
var appBackground: String?
|
||||
get() { mAppBackground = mAppBackground ?: config.values.get("appBackground", null as String?); return mAppBackground }
|
||||
set(value) { config.set(-1, "appBg", value); mAppBackground = value }
|
||||
|
||||
private var mMiniMenuVisible: Boolean? = null
|
||||
var miniMenuVisible: Boolean
|
||||
get() { mMiniMenuVisible = mMiniMenuVisible ?: config.values.get("miniMenuVisible", false); return mMiniMenuVisible ?: false }
|
||||
set(value) { config.set(-1, "miniMenuVisible", value); mMiniMenuVisible = value }
|
||||
|
||||
private var mMiniMenuButtons: List<Int>? = null
|
||||
var miniMenuButtons: List<Int>
|
||||
get() { mMiniMenuButtons = mMiniMenuButtons ?: config.values.getIntList("miniMenuButtons", listOf()); return mMiniMenuButtons ?: listOf() }
|
||||
set(value) { config.set(-1, "miniMenuButtons", value); mMiniMenuButtons = value }
|
||||
}
|
@ -10,6 +10,8 @@ import androidx.room.TypeConverters;
|
||||
import androidx.room.migration.Migration;
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
||||
|
||||
import pl.szczodrzynski.edziennik.config.ConfigDao;
|
||||
import pl.szczodrzynski.edziennik.config.ConfigEntry;
|
||||
import pl.szczodrzynski.edziennik.data.db.converters.ConverterDate;
|
||||
import pl.szczodrzynski.edziennik.data.db.converters.ConverterDateInt;
|
||||
import pl.szczodrzynski.edziennik.data.db.converters.ConverterJsonObject;
|
||||
@ -105,7 +107,8 @@ import pl.szczodrzynski.edziennik.utils.models.Date;
|
||||
NoticeType.class,
|
||||
AttendanceType.class,
|
||||
pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson.class,
|
||||
Metadata.class}, version = 64)
|
||||
ConfigEntry.class,
|
||||
Metadata.class}, version = 66)
|
||||
@TypeConverters({
|
||||
ConverterTime.class,
|
||||
ConverterDate.class,
|
||||
@ -144,6 +147,7 @@ public abstract class AppDb extends RoomDatabase {
|
||||
public abstract NoticeTypeDao noticeTypeDao();
|
||||
public abstract AttendanceTypeDao attendanceTypeDao();
|
||||
public abstract TimetableDao timetableDao();
|
||||
public abstract ConfigDao configDao();
|
||||
public abstract MetadataDao metadataDao();
|
||||
|
||||
private static volatile AppDb INSTANCE;
|
||||
@ -763,6 +767,27 @@ public abstract class AppDb extends RoomDatabase {
|
||||
database.execSQL("CREATE INDEX index_lessons_profileId_type_oldDate ON timetable (profileId, type, oldDate);");
|
||||
}
|
||||
};
|
||||
private static final Migration MIGRATION_64_65 = new Migration(64, 65) {
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
database.execSQL("CREATE TABLE config (" +
|
||||
"profileId INTEGER NOT NULL DEFAULT -1," +
|
||||
"`key` TEXT NOT NULL," +
|
||||
"value TEXT NOT NULL," +
|
||||
"PRIMARY KEY(profileId, `key`));");
|
||||
}
|
||||
};
|
||||
private static final Migration MIGRATION_65_66 = new Migration(65, 66) {
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
database.execSQL("DROP TABLE config;");
|
||||
database.execSQL("CREATE TABLE config (" +
|
||||
"profileId INTEGER NOT NULL DEFAULT -1," +
|
||||
"`key` TEXT NOT NULL," +
|
||||
"value TEXT," +
|
||||
"PRIMARY KEY(profileId, `key`));");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public static AppDb getDatabase(final Context context) {
|
||||
@ -824,7 +849,9 @@ public abstract class AppDb extends RoomDatabase {
|
||||
MIGRATION_60_61,
|
||||
MIGRATION_61_62,
|
||||
MIGRATION_62_63,
|
||||
MIGRATION_63_64
|
||||
MIGRATION_63_64,
|
||||
MIGRATION_64_65,
|
||||
MIGRATION_65_66
|
||||
)
|
||||
.allowMainThreadQueries()
|
||||
//.fallbackToDestructiveMigration()
|
||||
|
@ -372,7 +372,7 @@ public class SettingsNewFragment extends MaterialAboutFragment {
|
||||
buttonCaptions.add(getString(R.string.menu_settings));
|
||||
//buttonCaptions.add(getString(R.string.title_debugging));
|
||||
List<Integer> selectedIds = new ArrayList<>();
|
||||
for (int id: app.appConfig.miniDrawerButtonIds) {
|
||||
for (int id: app.config.getUi().getMiniMenuButtons()) {
|
||||
selectedIds.add(buttonIds.indexOf(id));
|
||||
}
|
||||
new MaterialDialog.Builder(activity)
|
||||
@ -380,16 +380,16 @@ public class SettingsNewFragment extends MaterialAboutFragment {
|
||||
.content(getString(R.string.settings_theme_mini_drawer_buttons_dialog_text))
|
||||
.items(buttonCaptions)
|
||||
.itemsCallbackMultiChoice(selectedIds.toArray(new Integer[0]), (dialog, which, text) -> {
|
||||
app.appConfig.miniDrawerButtonIds.clear();
|
||||
List<Integer> list = new ArrayList<>();
|
||||
for (int index: which) {
|
||||
if (index == -1)
|
||||
continue;
|
||||
// wtf
|
||||
|
||||
int id = buttonIds.get(index);
|
||||
app.appConfig.miniDrawerButtonIds.add(id);
|
||||
list.add(id);
|
||||
}
|
||||
app.saveConfig("miniDrawerButtonIds");
|
||||
app.config.getUi().setMiniMenuButtons(list);
|
||||
activity.setDrawerItems();
|
||||
activity.getDrawer().updateBadges();
|
||||
return true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user