forked from github/szkolny
[App] Move per-register settings to JSON resource. Rewrite Config to use delegates. (#150)
* [App] Add base for AppData loading. * [UI] Fix timetable widget date navigation. * [UI] Migrate register-specific behavior to use AppData. * [App] Implement new delegate-based config base. * [Config] Migrate config and profile config. * [Config] Remove defaults from migrations. * [App] Apply event types and config overrides from AppData. * [Events] Change default event types for university type school.
This commit is contained in:
parent
6c93cd4217
commit
63c5720f63
7
.idea/codeStyles/Project.xml
generated
7
.idea/codeStyles/Project.xml
generated
@ -4,6 +4,13 @@
|
|||||||
<option name="ALLOW_TRAILING_COMMA" value="true" />
|
<option name="ALLOW_TRAILING_COMMA" value="true" />
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
</JetCodeStyleSettings>
|
</JetCodeStyleSettings>
|
||||||
|
<codeStyleSettings language="JSON">
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="4" />
|
||||||
|
<option name="USE_TAB_CHARACTER" value="true" />
|
||||||
|
<option name="SMART_TABS" value="true" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
<codeStyleSettings language="XML">
|
<codeStyleSettings language="XML">
|
||||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||||
<indentOptions>
|
<indentOptions>
|
||||||
|
1
.idea/dictionaries/Kuba.xml
generated
1
.idea/dictionaries/Kuba.xml
generated
@ -5,6 +5,7 @@
|
|||||||
<w>ciasteczko</w>
|
<w>ciasteczko</w>
|
||||||
<w>csrf</w>
|
<w>csrf</w>
|
||||||
<w>edziennik</w>
|
<w>edziennik</w>
|
||||||
|
<w>eggfall</w>
|
||||||
<w>elearning</w>
|
<w>elearning</w>
|
||||||
<w>gson</w>
|
<w>gson</w>
|
||||||
<w>hebe</w>
|
<w>hebe</w>
|
||||||
|
@ -12,6 +12,7 @@ import android.graphics.drawable.Icon
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.multidex.MultiDexApplication
|
import androidx.multidex.MultiDexApplication
|
||||||
import androidx.work.Configuration
|
import androidx.work.Configuration
|
||||||
@ -31,6 +32,7 @@ import kotlinx.coroutines.*
|
|||||||
import me.leolin.shortcutbadger.ShortcutBadger
|
import me.leolin.shortcutbadger.ShortcutBadger
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import pl.szczodrzynski.edziennik.config.AppData
|
||||||
import pl.szczodrzynski.edziennik.config.Config
|
import pl.szczodrzynski.edziennik.config.Config
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.ProfileListEmptyEvent
|
import pl.szczodrzynski.edziennik.data.api.events.ProfileListEmptyEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
|
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
|
||||||
@ -48,18 +50,27 @@ import pl.szczodrzynski.edziennik.sync.SyncWorker
|
|||||||
import pl.szczodrzynski.edziennik.sync.UpdateWorker
|
import pl.szczodrzynski.edziennik.sync.UpdateWorker
|
||||||
import pl.szczodrzynski.edziennik.ui.base.CrashActivity
|
import pl.szczodrzynski.edziennik.ui.base.CrashActivity
|
||||||
import pl.szczodrzynski.edziennik.ui.base.enums.NavTarget
|
import pl.szczodrzynski.edziennik.ui.base.enums.NavTarget
|
||||||
import pl.szczodrzynski.edziennik.utils.*
|
import pl.szczodrzynski.edziennik.utils.DebugLogFormat
|
||||||
|
import pl.szczodrzynski.edziennik.utils.PermissionChecker
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Themes
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
import pl.szczodrzynski.edziennik.utils.managers.*
|
import pl.szczodrzynski.edziennik.utils.managers.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
||||||
companion object {
|
companion object {
|
||||||
@Volatile
|
@Volatile
|
||||||
lateinit var db: AppDb
|
lateinit var db: AppDb
|
||||||
|
private set
|
||||||
lateinit var config: Config
|
lateinit var config: Config
|
||||||
|
// private set // for LabFragment
|
||||||
lateinit var profile: Profile
|
lateinit var profile: Profile
|
||||||
|
private set
|
||||||
|
lateinit var data: AppData
|
||||||
|
private set
|
||||||
val profileId
|
val profileId
|
||||||
get() = profile.id
|
get() = profile.id
|
||||||
|
|
||||||
@ -90,6 +101,8 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
|||||||
get() = App.profile
|
get() = App.profile
|
||||||
val profileId
|
val profileId
|
||||||
get() = App.profileId
|
get() = App.profileId
|
||||||
|
val data
|
||||||
|
get() = App.data
|
||||||
|
|
||||||
private val job = Job()
|
private val job = Job()
|
||||||
override val coroutineContext: CoroutineContext
|
override val coroutineContext: CoroutineContext
|
||||||
@ -124,9 +137,6 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
|||||||
SSLProviderInstaller.enableSupportedTls(builder, enableCleartext = true)
|
SSLProviderInstaller.enableSupportedTls(builder, enableCleartext = true)
|
||||||
|
|
||||||
if (devMode) {
|
if (devMode) {
|
||||||
HyperLog.initialize(this)
|
|
||||||
HyperLog.setLogLevel(Log.VERBOSE)
|
|
||||||
HyperLog.setLogFormat(DebugLogFormat(this))
|
|
||||||
if (enableChucker) {
|
if (enableChucker) {
|
||||||
val chuckerCollector = ChuckerCollector(this, true, RetentionManager.Period.ONE_HOUR)
|
val chuckerCollector = ChuckerCollector(this, true, RetentionManager.Period.ONE_HOUR)
|
||||||
val chuckerInterceptor = ChuckerInterceptor(this, chuckerCollector)
|
val chuckerInterceptor = ChuckerInterceptor(this, chuckerCollector)
|
||||||
@ -180,16 +190,24 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
|||||||
Iconics.init(applicationContext)
|
Iconics.init(applicationContext)
|
||||||
Iconics.respectFontBoundsDefault = true
|
Iconics.respectFontBoundsDefault = true
|
||||||
|
|
||||||
|
if (devMode) {
|
||||||
|
HyperLog.initialize(this)
|
||||||
|
HyperLog.setLogLevel(Log.VERBOSE)
|
||||||
|
HyperLog.setLogFormat(DebugLogFormat(this))
|
||||||
|
}
|
||||||
|
|
||||||
// initialize companion object values
|
// initialize companion object values
|
||||||
|
AppData.read(this)
|
||||||
App.db = AppDb(this)
|
App.db = AppDb(this)
|
||||||
App.config = Config(App.db)
|
App.config = Config(App.db)
|
||||||
App.profile = Profile(0, 0, LoginType.TEMPLATE, "")
|
|
||||||
debugMode = BuildConfig.DEBUG
|
debugMode = BuildConfig.DEBUG
|
||||||
devMode = config.devMode ?: debugMode
|
devMode = config.devMode ?: debugMode
|
||||||
enableChucker = config.enableChucker ?: devMode
|
enableChucker = config.enableChucker ?: devMode
|
||||||
|
|
||||||
if (!profileLoadById(config.lastProfileId)) {
|
if (!profileLoadById(config.lastProfileId)) {
|
||||||
db.profileDao().firstId?.let { profileLoadById(it) }
|
val success = db.profileDao().firstId?.let { profileLoadById(it) }
|
||||||
|
if (success != true)
|
||||||
|
profileLoad(Profile(0, 0, LoginType.TEMPLATE, ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
buildHttp()
|
buildHttp()
|
||||||
@ -381,10 +399,22 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun profileLoad(profile: Profile) {
|
||||||
|
App.profile = profile
|
||||||
|
App.config.lastProfileId = profile.id
|
||||||
|
try {
|
||||||
|
App.data = AppData.get(profile.loginStoreType)
|
||||||
|
d("App", "Loaded AppData: ${App.data}")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("App", "Cannot load AppData", e)
|
||||||
|
Toast.makeText(this, R.string.app_cannot_load_data, Toast.LENGTH_LONG).show()
|
||||||
|
exitProcess(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun profileLoadById(profileId: Int): Boolean {
|
private fun profileLoadById(profileId: Int): Boolean {
|
||||||
db.profileDao().getByIdNow(profileId)?.also {
|
db.profileDao().getByIdNow(profileId)?.also {
|
||||||
App.profile = it
|
profileLoad(it)
|
||||||
App.config.lastProfileId = it.id
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -42,7 +42,6 @@ import pl.szczodrzynski.edziennik.data.db.entity.Message
|
|||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata.*
|
import pl.szczodrzynski.edziennik.data.db.entity.Metadata.*
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
import pl.szczodrzynski.edziennik.data.db.enums.FeatureType
|
import pl.szczodrzynski.edziennik.data.db.enums.FeatureType
|
||||||
import pl.szczodrzynski.edziennik.data.db.enums.LoginType
|
|
||||||
import pl.szczodrzynski.edziennik.databinding.ActivitySzkolnyBinding
|
import pl.szczodrzynski.edziennik.databinding.ActivitySzkolnyBinding
|
||||||
import pl.szczodrzynski.edziennik.ext.*
|
import pl.szczodrzynski.edziennik.ext.*
|
||||||
import pl.szczodrzynski.edziennik.sync.AppManagerDetectedEvent
|
import pl.szczodrzynski.edziennik.sync.AppManagerDetectedEvent
|
||||||
@ -427,7 +426,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
|||||||
launch {
|
launch {
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
app.db.profileDao().allNow.forEach { profile ->
|
app.db.profileDao().allNow.forEach { profile ->
|
||||||
if (profile.loginStoreType != LoginType.LIBRUS)
|
if (!profile.getAppData().uiConfig.enableMarkAsReadAnnouncements)
|
||||||
app.db.metadataDao()
|
app.db.metadataDao()
|
||||||
.setAllSeenExceptMessagesAndAnnouncements(profile.id, true)
|
.setAllSeenExceptMessagesAndAnnouncements(profile.id, true)
|
||||||
else
|
else
|
||||||
@ -695,7 +694,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
|||||||
}
|
}
|
||||||
d(TAG, "}")
|
d(TAG, "}")
|
||||||
|
|
||||||
val intentProfileId = extras.getIntOrNull("profileId")
|
val intentProfileId = extras.getIntOrNull("profileId").takePositive()
|
||||||
var intentNavTarget = extras.getIntOrNull("fragmentId").asNavTargetOrNull()
|
var intentNavTarget = extras.getIntOrNull("fragmentId").asNavTargetOrNull()
|
||||||
|
|
||||||
if (extras?.containsKey("action") == true) {
|
if (extras?.containsKey("action") == true) {
|
||||||
@ -743,8 +742,8 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (extras?.containsKey("reloadProfileId") == true) {
|
if (extras?.containsKey("reloadProfileId") == true) {
|
||||||
val reloadProfileId = extras.getIntOrNull("reloadProfileId")
|
val reloadProfileId = extras.getIntOrNull("reloadProfileId").takePositive()
|
||||||
if (reloadProfileId == -1 || app.profile.id == reloadProfileId) {
|
if (reloadProfileId == null || app.profile.id == reloadProfileId) {
|
||||||
reloadTarget()
|
reloadTarget()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -767,7 +766,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
|||||||
navTarget = intentNavTarget,
|
navTarget = intentNavTarget,
|
||||||
args = extras,
|
args = extras,
|
||||||
)
|
)
|
||||||
intentProfileId != -1 -> navigate(
|
intentProfileId != null -> navigate(
|
||||||
profileId = intentProfileId,
|
profileId = intentProfileId,
|
||||||
navTarget = intentNavTarget,
|
navTarget = intentNavTarget,
|
||||||
args = extras,
|
args = extras,
|
||||||
@ -776,6 +775,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
|||||||
navTarget = intentNavTarget,
|
navTarget = intentNavTarget,
|
||||||
args = extras,
|
args = extras,
|
||||||
)
|
)
|
||||||
|
navLoading -> navigate()
|
||||||
else -> drawer.currentProfile = app.profile.id
|
else -> drawer.currentProfile = app.profile.id
|
||||||
}
|
}
|
||||||
navLoading = false
|
navLoading = false
|
||||||
@ -923,7 +923,8 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (profileChanged) {
|
if (profileChanged) {
|
||||||
App.profile = profile
|
if (App.profileId != profile.id)
|
||||||
|
app.profileLoad(profile)
|
||||||
MessagesFragment.pageSelection = -1
|
MessagesFragment.pageSelection = -1
|
||||||
// set new drawer items for this profile
|
// set new drawer items for this profile
|
||||||
setDrawerItems()
|
setDrawerItems()
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-11-27.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config
|
|
||||||
|
|
||||||
interface AbstractConfig {
|
|
||||||
fun set(key: String, value: String?)
|
|
||||||
}
|
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2022-10-21.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import com.google.gson.JsonParser
|
||||||
|
import com.google.gson.stream.JsonReader
|
||||||
|
import pl.szczodrzynski.edziennik.App
|
||||||
|
import pl.szczodrzynski.edziennik.R
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.enums.LoginType
|
||||||
|
import pl.szczodrzynski.edziennik.ext.getJsonObject
|
||||||
|
import pl.szczodrzynski.edziennik.ext.mergeWith
|
||||||
|
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.HtmlMode
|
||||||
|
|
||||||
|
data class AppData(
|
||||||
|
val configOverrides: Map<String, String>,
|
||||||
|
val messagesConfig: MessagesConfig,
|
||||||
|
val uiConfig: UIConfig,
|
||||||
|
val eventTypes: List<EventType>,
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
private var data: JsonObject? = null
|
||||||
|
private val appData = mutableMapOf<LoginType, AppData>()
|
||||||
|
|
||||||
|
fun read(app: App) {
|
||||||
|
val res = app.resources.openRawResource(R.raw.app_data)
|
||||||
|
data = JsonParser.parseReader(JsonReader(res.reader())).asJsonObject
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(loginType: LoginType): AppData {
|
||||||
|
if (loginType in appData)
|
||||||
|
return appData.getValue(loginType)
|
||||||
|
val json = data?.getJsonObject("base")?.deepCopy()
|
||||||
|
?: throw NoSuchElementException("Base data not found")
|
||||||
|
val overrides = setOf(loginType, loginType.schoolType)
|
||||||
|
for (overrideType in overrides) {
|
||||||
|
val override = data?.getJsonObject(overrideType.name.lowercase()) ?: continue
|
||||||
|
json.mergeWith(override)
|
||||||
|
}
|
||||||
|
val value = Gson().fromJson(json, AppData::class.java)
|
||||||
|
appData[loginType] = value
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class MessagesConfig(
|
||||||
|
val subjectLength: Int?,
|
||||||
|
val bodyLength: Int?,
|
||||||
|
val textStyling: Boolean,
|
||||||
|
val syncRecipientList: Boolean,
|
||||||
|
val htmlMode: HtmlMode,
|
||||||
|
val needsReadStatus: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class UIConfig(
|
||||||
|
val lessonHeight: Int,
|
||||||
|
val enableMarkAsReadAnnouncements: Boolean,
|
||||||
|
val enableNoticePoints: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class EventType(
|
||||||
|
val id: Int,
|
||||||
|
val color: String,
|
||||||
|
val name: String,
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2019-11-27.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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.config.db.ConfigEntry
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.AppDb
|
||||||
|
import pl.szczodrzynski.edziennik.ext.takePositive
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
|
abstract class BaseConfig(
|
||||||
|
val db: AppDb,
|
||||||
|
val profileId: Int? = null,
|
||||||
|
protected var entries: List<ConfigEntry>? = null,
|
||||||
|
) : CoroutineScope {
|
||||||
|
|
||||||
|
private val job = Job()
|
||||||
|
override val coroutineContext: CoroutineContext
|
||||||
|
get() = job + Dispatchers.Default
|
||||||
|
|
||||||
|
val values = hashMapOf<String, String?>()
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (entries == null)
|
||||||
|
entries = db.configDao().getAllNow()
|
||||||
|
values.clear()
|
||||||
|
for ((profileId, key, value) in entries!!) {
|
||||||
|
if (profileId.takePositive() != this.profileId)
|
||||||
|
continue
|
||||||
|
values[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun set(key: String, value: String?) {
|
||||||
|
values[key] = value
|
||||||
|
launch(Dispatchers.IO) {
|
||||||
|
db.configDao().add(ConfigEntry(profileId ?: -1, key, value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,151 +5,59 @@
|
|||||||
package pl.szczodrzynski.edziennik.config
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.BuildConfig
|
import pl.szczodrzynski.edziennik.BuildConfig
|
||||||
import pl.szczodrzynski.edziennik.config.db.ConfigEntry
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.*
|
import pl.szczodrzynski.edziennik.config.utils.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.response.Update
|
import pl.szczodrzynski.edziennik.data.api.szkolny.response.Update
|
||||||
import pl.szczodrzynski.edziennik.data.db.AppDb
|
import pl.szczodrzynski.edziennik.data.db.AppDb
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
class Config(val db: AppDb) : CoroutineScope, AbstractConfig {
|
@Suppress("RemoveExplicitTypeArguments")
|
||||||
|
class Config(db: AppDb) : BaseConfig(db) {
|
||||||
companion object {
|
companion object {
|
||||||
const val DATA_VERSION = 12
|
const val DATA_VERSION = 12
|
||||||
}
|
}
|
||||||
|
|
||||||
private val job = Job()
|
private val profileConfigs: HashMap<Int, ProfileConfig> = hashMapOf()
|
||||||
override val coroutineContext: CoroutineContext
|
|
||||||
get() = job + Dispatchers.Default
|
|
||||||
|
|
||||||
val values: HashMap<String, String?> = hashMapOf()
|
|
||||||
|
|
||||||
val ui by lazy { ConfigUI(this) }
|
val ui by lazy { ConfigUI(this) }
|
||||||
val sync by lazy { ConfigSync(this) }
|
val sync by lazy { ConfigSync(this) }
|
||||||
val timetable by lazy { ConfigTimetable(this) }
|
val timetable by lazy { ConfigTimetable(this) }
|
||||||
val grades by lazy { ConfigGrades(this) }
|
val grades by lazy { ConfigGrades(this) }
|
||||||
|
|
||||||
private var mDataVersion: Int? = null
|
var dataVersion by config<Int>(0)
|
||||||
var dataVersion: Int
|
var hash by config<String>("")
|
||||||
get() { mDataVersion = mDataVersion ?: values.get("dataVersion", 0); return mDataVersion ?: 0 }
|
|
||||||
set(value) { set("dataVersion", value); mDataVersion = value }
|
|
||||||
|
|
||||||
private var mHash: String? = null
|
var lastProfileId by config<Int>(0)
|
||||||
var hash: String
|
var loginFinished by config<Boolean>(false)
|
||||||
get() { mHash = mHash ?: values.get("hash", ""); return mHash ?: "" }
|
var privacyPolicyAccepted by config<Boolean>(false)
|
||||||
set(value) { set("hash", value); mHash = value }
|
var update by config<Update?>(null)
|
||||||
|
var updatesChannel by config<String>("release")
|
||||||
|
|
||||||
private var mLastProfileId: Int? = null
|
var devMode by config<Boolean?>(null)
|
||||||
var lastProfileId: Int
|
var devModePassword by config<String?>(null)
|
||||||
get() { mLastProfileId = mLastProfileId ?: values.get("lastProfileId", 0); return mLastProfileId ?: 0 }
|
var enableChucker by config<Boolean?>(null)
|
||||||
set(value) { set("lastProfileId", value); mLastProfileId = value }
|
|
||||||
|
|
||||||
private var mUpdatesChannel: String? = null
|
var apiAvailabilityCheck by config<Boolean>(true)
|
||||||
var updatesChannel: String
|
var apiInvalidCert by config<String?>(null)
|
||||||
get() { mUpdatesChannel = mUpdatesChannel ?: values.get("updatesChannel", "release"); return mUpdatesChannel ?: "release" }
|
var appInstalledTime by config<Long>(0L)
|
||||||
set(value) { set("updatesChannel", value); mUpdatesChannel = value }
|
var appRateSnackbarTime by config<Long>(0L)
|
||||||
private var mUpdate: Update? = null
|
var appVersion by config<Int>(BuildConfig.VERSION_CODE)
|
||||||
var update: Update?
|
var validation by config<String?>(null, "buildValidation")
|
||||||
get() { mUpdate = mUpdate ?: values.get("update", null as Update?); return mUpdate ?: null as Update? }
|
|
||||||
set(value) { set("update", value); mUpdate = value }
|
|
||||||
|
|
||||||
private var mAppVersion: Int? = null
|
var archiverEnabled by config<Boolean>(true)
|
||||||
var appVersion: Int
|
var runSync by config<Boolean>(false)
|
||||||
get() { mAppVersion = mAppVersion ?: values.get("appVersion", BuildConfig.VERSION_CODE); return mAppVersion ?: BuildConfig.VERSION_CODE }
|
var widgetConfigs by config<JsonObject> { JsonObject() }
|
||||||
set(value) { set("appVersion", value); mAppVersion = value }
|
|
||||||
|
|
||||||
private var mLoginFinished: Boolean? = null
|
|
||||||
var loginFinished: Boolean
|
|
||||||
get() { mLoginFinished = mLoginFinished ?: values.get("loginFinished", false); return mLoginFinished ?: false }
|
|
||||||
set(value) { set("loginFinished", value); mLoginFinished = value }
|
|
||||||
|
|
||||||
private var mPrivacyPolicyAccepted: Boolean? = null
|
|
||||||
var privacyPolicyAccepted: Boolean
|
|
||||||
get() { mPrivacyPolicyAccepted = mPrivacyPolicyAccepted ?: values.get("privacyPolicyAccepted", false); return mPrivacyPolicyAccepted ?: false }
|
|
||||||
set(value) { set("privacyPolicyAccepted", value); mPrivacyPolicyAccepted = value }
|
|
||||||
|
|
||||||
private var mDevMode: Boolean? = null
|
|
||||||
var devMode: Boolean?
|
|
||||||
get() { mDevMode = mDevMode ?: values.getBooleanOrNull("debugMode"); return mDevMode }
|
|
||||||
set(value) { set("debugMode", value?.toString()); mDevMode = value }
|
|
||||||
|
|
||||||
private var mEnableChucker: Boolean? = null
|
|
||||||
var enableChucker: Boolean?
|
|
||||||
get() { mEnableChucker = mEnableChucker ?: values.getBooleanOrNull("enableChucker"); return mEnableChucker }
|
|
||||||
set(value) { set("enableChucker", value?.toString()); mEnableChucker = value }
|
|
||||||
|
|
||||||
private var mDevModePassword: String? = null
|
|
||||||
var devModePassword: String?
|
|
||||||
get() { mDevModePassword = mDevModePassword ?: values.get("devModePassword", null as String?); return mDevModePassword }
|
|
||||||
set(value) { set("devModePassword", value); mDevModePassword = value }
|
|
||||||
|
|
||||||
private var mAppInstalledTime: Long? = null
|
|
||||||
var appInstalledTime: Long
|
|
||||||
get() { mAppInstalledTime = mAppInstalledTime ?: values.get("appInstalledTime", 0L); return mAppInstalledTime ?: 0L }
|
|
||||||
set(value) { set("appInstalledTime", value); mAppInstalledTime = value }
|
|
||||||
|
|
||||||
private var mAppRateSnackbarTime: Long? = null
|
|
||||||
var appRateSnackbarTime: Long
|
|
||||||
get() { mAppRateSnackbarTime = mAppRateSnackbarTime ?: values.get("appRateSnackbarTime", 0L); return mAppRateSnackbarTime ?: 0L }
|
|
||||||
set(value) { set("appRateSnackbarTime", value); mAppRateSnackbarTime = value }
|
|
||||||
|
|
||||||
private var mRunSync: Boolean? = null
|
|
||||||
var runSync: Boolean
|
|
||||||
get() { mRunSync = mRunSync ?: values.get("runSync", false); return mRunSync ?: false }
|
|
||||||
set(value) { set("runSync", value); mRunSync = value }
|
|
||||||
|
|
||||||
private var mWidgetConfigs: JsonObject? = null
|
|
||||||
var widgetConfigs: JsonObject
|
|
||||||
get() { mWidgetConfigs = mWidgetConfigs ?: values.get("widgetConfigs", JsonObject()); return mWidgetConfigs ?: JsonObject() }
|
|
||||||
set(value) { set("widgetConfigs", value); mWidgetConfigs = value }
|
|
||||||
|
|
||||||
private var mArchiverEnabled: Boolean? = null
|
|
||||||
var archiverEnabled: Boolean
|
|
||||||
get() { mArchiverEnabled = mArchiverEnabled ?: values.get("archiverEnabled", true); return mArchiverEnabled ?: true }
|
|
||||||
set(value) { set("archiverEnabled", value); mArchiverEnabled = value }
|
|
||||||
|
|
||||||
private var mValidation: String? = null
|
|
||||||
var validation: String?
|
|
||||||
get() { mValidation = mValidation ?: values["buildValidation"]; return mValidation }
|
|
||||||
set(value) { set("buildValidation", value); mValidation = value }
|
|
||||||
|
|
||||||
private var mApiInvalidCert: String? = null
|
|
||||||
var apiInvalidCert: String?
|
|
||||||
get() { mApiInvalidCert = mApiInvalidCert ?: values["apiInvalidCert"]; return mApiInvalidCert }
|
|
||||||
set(value) { set("apiInvalidCert", value); mApiInvalidCert = value }
|
|
||||||
|
|
||||||
private var mApiAvailabilityCheck: Boolean? = null
|
|
||||||
var apiAvailabilityCheck: Boolean
|
|
||||||
get() { mApiAvailabilityCheck = mApiAvailabilityCheck ?: values.get("apiAvailabilityCheck", true); return mApiAvailabilityCheck ?: true }
|
|
||||||
set(value) { set("apiAvailabilityCheck", value); mApiAvailabilityCheck = value }
|
|
||||||
|
|
||||||
private var rawEntries: List<ConfigEntry> = db.configDao().getAllNow()
|
|
||||||
private val profileConfigs: HashMap<Int, ProfileConfig> = hashMapOf()
|
|
||||||
init {
|
|
||||||
rawEntries.toHashMap(-1, values)
|
|
||||||
}
|
|
||||||
fun migrate(app: App) {
|
fun migrate(app: App) {
|
||||||
if (dataVersion < DATA_VERSION)
|
if (dataVersion < DATA_VERSION)
|
||||||
ConfigMigration(app, this)
|
ConfigMigration(app, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFor(profileId: Int): ProfileConfig {
|
fun getFor(profileId: Int): ProfileConfig {
|
||||||
return profileConfigs[profileId] ?: ProfileConfig(db, profileId, db.configDao().getAllNow(profileId)).also {
|
return profileConfigs[profileId] ?: ProfileConfig(db, profileId, entries).also {
|
||||||
profileConfigs[profileId] = it
|
profileConfigs[profileId] = it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun forProfile() = getFor(App.profileId)
|
fun forProfile() = getFor(App.profileId)
|
||||||
|
|
||||||
fun setProfile(profileId: Int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun set(key: String, value: String?) {
|
|
||||||
values[key] = value
|
|
||||||
launch {
|
|
||||||
db.configDao().add(ConfigEntry(-1, key, value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,10 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.get
|
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.ORDER_BY_DATE_DESC
|
||||||
import pl.szczodrzynski.edziennik.config.utils.set
|
|
||||||
import pl.szczodrzynski.edziennik.utils.managers.GradesManager
|
|
||||||
|
|
||||||
class ConfigGrades(private val config: Config) {
|
@Suppress("RemoveExplicitTypeArguments")
|
||||||
private var mOrderBy: Int? = null
|
class ConfigGrades(base: Config) {
|
||||||
var orderBy: Int
|
|
||||||
get() { mOrderBy = mOrderBy ?: config.values.get("gradesOrderBy", 0); return mOrderBy ?: GradesManager.ORDER_BY_DATE_DESC }
|
var orderBy by base.config<Int>("gradesOrderBy", ORDER_BY_DATE_DESC)
|
||||||
set(value) { config.set("gradesOrderBy", value); mOrderBy = value }
|
|
||||||
}
|
}
|
||||||
|
@ -4,139 +4,53 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
import com.google.gson.Gson
|
|
||||||
import com.google.gson.reflect.TypeToken
|
|
||||||
import pl.szczodrzynski.edziennik.BuildConfig
|
import pl.szczodrzynski.edziennik.BuildConfig
|
||||||
import pl.szczodrzynski.edziennik.config.utils.get
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.getIntList
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.set
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.setMap
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.szkolny.response.RegisterAvailabilityStatus
|
import pl.szczodrzynski.edziennik.data.api.szkolny.response.RegisterAvailabilityStatus
|
||||||
|
import pl.szczodrzynski.edziennik.ext.HOUR
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||||
|
|
||||||
class ConfigSync(private val config: Config) {
|
@Suppress("RemoveExplicitTypeArguments")
|
||||||
private val gson = Gson()
|
class ConfigSync(base: Config) {
|
||||||
|
|
||||||
private var mDontShowAppManagerDialog: Boolean? = null
|
var enabled by base.config<Boolean>("syncEnabled", true)
|
||||||
var dontShowAppManagerDialog: Boolean
|
var interval by base.config<Int>("syncInterval", 1 * HOUR.toInt())
|
||||||
get() { mDontShowAppManagerDialog = mDontShowAppManagerDialog ?: config.values.get("dontShowAppManagerDialog", false); return mDontShowAppManagerDialog ?: false }
|
var onlyWifi by base.config<Boolean>("syncOnlyWifi", false)
|
||||||
set(value) { config.set("dontShowAppManagerDialog", value); mDontShowAppManagerDialog = value }
|
|
||||||
|
|
||||||
private var mSyncEnabled: Boolean? = null
|
var dontShowAppManagerDialog by base.config<Boolean>(false)
|
||||||
var enabled: Boolean
|
var lastAppSync by base.config<Long>(0L)
|
||||||
get() { mSyncEnabled = mSyncEnabled ?: config.values.get("syncEnabled", true); return mSyncEnabled ?: true }
|
var notifyAboutUpdates by base.config<Boolean>(true)
|
||||||
set(value) { config.set("syncEnabled", value); mSyncEnabled = value }
|
var webPushEnabled by base.config<Boolean>(true)
|
||||||
|
|
||||||
private var mWebPushEnabled: Boolean? = null
|
// Quiet Hours
|
||||||
var webPushEnabled: Boolean
|
var quietHoursEnabled by base.config<Boolean>(false)
|
||||||
get() { mWebPushEnabled = mWebPushEnabled ?: config.values.get("webPushEnabled", true); return mWebPushEnabled ?: true }
|
var quietHoursStart by base.config<Time?>(null)
|
||||||
set(value) { config.set("webPushEnabled", value); mWebPushEnabled = value }
|
var quietHoursEnd by base.config<Time?>(null)
|
||||||
|
var quietDuringLessons by base.config<Boolean>(false)
|
||||||
|
|
||||||
private var mSyncOnlyWifi: Boolean? = null
|
// FCM Tokens
|
||||||
var onlyWifi: Boolean
|
var tokenApp by base.config<String?>(null)
|
||||||
get() { mSyncOnlyWifi = mSyncOnlyWifi ?: config.values.get("syncOnlyWifi", false); return mSyncOnlyWifi ?: notifyAboutUpdates }
|
var tokenMobidziennik by base.config<String?>(null)
|
||||||
set(value) { config.set("syncOnlyWifi", value); mSyncOnlyWifi = value }
|
var tokenLibrus by base.config<String?>(null)
|
||||||
|
var tokenVulcan by base.config<String?>(null)
|
||||||
|
var tokenVulcanHebe by base.config<String?>(null)
|
||||||
|
|
||||||
private var mSyncInterval: Int? = null
|
var tokenMobidziennikList by base.config<List<Int>> { listOf() }
|
||||||
var interval: Int
|
var tokenLibrusList by base.config<List<Int>> { listOf() }
|
||||||
get() { mSyncInterval = mSyncInterval ?: config.values.get("syncInterval", 60*60); return mSyncInterval ?: 60*60 }
|
var tokenVulcanList by base.config<List<Int>> { listOf() }
|
||||||
set(value) { config.set("syncInterval", value); mSyncInterval = value }
|
var tokenVulcanHebeList by base.config<List<Int>> { listOf() }
|
||||||
|
|
||||||
private var mNotifyAboutUpdates: Boolean? = null
|
// Register Availability
|
||||||
var notifyAboutUpdates: Boolean
|
private var registerAvailabilityMap by base.config<Map<String, RegisterAvailabilityStatus>>("registerAvailability") { mapOf() }
|
||||||
get() { mNotifyAboutUpdates = mNotifyAboutUpdates ?: config.values.get("notifyAboutUpdates", true); return mNotifyAboutUpdates ?: true }
|
private var registerAvailabilityFlavor by base.config<String?>(null)
|
||||||
set(value) { config.set("notifyAboutUpdates", value); mNotifyAboutUpdates = value }
|
|
||||||
|
|
||||||
private var mLastAppSync: Long? = null
|
|
||||||
var lastAppSync: Long
|
|
||||||
get() { mLastAppSync = mLastAppSync ?: config.values.get("lastAppSync", 0L); return mLastAppSync ?: 0L }
|
|
||||||
set(value) { config.set("lastAppSync", value); mLastAppSync = value }
|
|
||||||
|
|
||||||
/* ____ _ _ _
|
|
||||||
/ __ \ (_) | | | |
|
|
||||||
| | | |_ _ _ ___| |_ | |__ ___ _ _ _ __ ___
|
|
||||||
| | | | | | | |/ _ \ __| | '_ \ / _ \| | | | '__/ __|
|
|
||||||
| |__| | |_| | | __/ |_ | | | | (_) | |_| | | \__ \
|
|
||||||
\___\_\\__,_|_|\___|\__| |_| |_|\___/ \__,_|_| |__*/
|
|
||||||
private var mQuietHoursEnabled: Boolean? = null
|
|
||||||
var quietHoursEnabled: Boolean
|
|
||||||
get() { mQuietHoursEnabled = mQuietHoursEnabled ?: config.values.get("quietHoursEnabled", false); return mQuietHoursEnabled ?: false }
|
|
||||||
set(value) { config.set("quietHoursEnabled", value); mQuietHoursEnabled = value }
|
|
||||||
|
|
||||||
private var mQuietHoursStart: Time? = null
|
|
||||||
var quietHoursStart: Time?
|
|
||||||
get() { mQuietHoursStart = mQuietHoursStart ?: config.values.get("quietHoursStart", null as Time?); return mQuietHoursStart }
|
|
||||||
set(value) { config.set("quietHoursStart", value); mQuietHoursStart = value }
|
|
||||||
|
|
||||||
private var mQuietHoursEnd: Time? = null
|
|
||||||
var quietHoursEnd: Time?
|
|
||||||
get() { mQuietHoursEnd = mQuietHoursEnd ?: config.values.get("quietHoursEnd", null as Time?); return mQuietHoursEnd }
|
|
||||||
set(value) { config.set("quietHoursEnd", value); mQuietHoursEnd = value }
|
|
||||||
|
|
||||||
private var mQuietDuringLessons: Boolean? = null
|
|
||||||
var quietDuringLessons: Boolean
|
|
||||||
get() { mQuietDuringLessons = mQuietDuringLessons ?: config.values.get("quietDuringLessons", false); return mQuietDuringLessons ?: false }
|
|
||||||
set(value) { config.set("quietDuringLessons", value); mQuietDuringLessons = value }
|
|
||||||
|
|
||||||
/* ______ _____ __ __ _______ _
|
|
||||||
| ____/ ____| \/ | |__ __| | |
|
|
||||||
| |__ | | | \ / | | | ___ | | _____ _ __ ___
|
|
||||||
| __|| | | |\/| | | |/ _ \| |/ / _ \ '_ \/ __|
|
|
||||||
| | | |____| | | | | | (_) | < __/ | | \__ \
|
|
||||||
|_| \_____|_| |_| |_|\___/|_|\_\___|_| |_|__*/
|
|
||||||
private var mTokenApp: String? = null
|
|
||||||
var tokenApp: String?
|
|
||||||
get() { mTokenApp = mTokenApp ?: config.values.get("tokenApp", null as String?); return mTokenApp }
|
|
||||||
set(value) { config.set("tokenApp", value); mTokenApp = value }
|
|
||||||
private var mTokenMobidziennik: String? = null
|
|
||||||
var tokenMobidziennik: String?
|
|
||||||
get() { mTokenMobidziennik = mTokenMobidziennik ?: config.values.get("tokenMobidziennik", null as String?); return mTokenMobidziennik }
|
|
||||||
set(value) { config.set("tokenMobidziennik", value); mTokenMobidziennik = value }
|
|
||||||
private var mTokenLibrus: String? = null
|
|
||||||
var tokenLibrus: String?
|
|
||||||
get() { mTokenLibrus = mTokenLibrus ?: config.values.get("tokenLibrus", null as String?); return mTokenLibrus }
|
|
||||||
set(value) { config.set("tokenLibrus", value); mTokenLibrus = value }
|
|
||||||
private var mTokenVulcan: String? = null
|
|
||||||
var tokenVulcan: String?
|
|
||||||
get() { mTokenVulcan = mTokenVulcan ?: config.values.get("tokenVulcan", null as String?); return mTokenVulcan }
|
|
||||||
set(value) { config.set("tokenVulcan", value); mTokenVulcan = value }
|
|
||||||
private var mTokenVulcanHebe: String? = null
|
|
||||||
var tokenVulcanHebe: String?
|
|
||||||
get() { mTokenVulcanHebe = mTokenVulcanHebe ?: config.values.get("tokenVulcanHebe", null as String?); return mTokenVulcanHebe }
|
|
||||||
set(value) { config.set("tokenVulcanHebe", value); mTokenVulcanHebe = value }
|
|
||||||
|
|
||||||
private var mTokenMobidziennikList: List<Int>? = null
|
|
||||||
var tokenMobidziennikList: List<Int>
|
|
||||||
get() { mTokenMobidziennikList = mTokenMobidziennikList ?: config.values.getIntList("tokenMobidziennikList", listOf()); return mTokenMobidziennikList ?: listOf() }
|
|
||||||
set(value) { config.set("tokenMobidziennikList", value); mTokenMobidziennikList = value }
|
|
||||||
private var mTokenLibrusList: List<Int>? = null
|
|
||||||
var tokenLibrusList: List<Int>
|
|
||||||
get() { mTokenLibrusList = mTokenLibrusList ?: config.values.getIntList("tokenLibrusList", listOf()); return mTokenLibrusList ?: listOf() }
|
|
||||||
set(value) { config.set("tokenLibrusList", value); mTokenLibrusList = value }
|
|
||||||
private var mTokenVulcanList: List<Int>? = null
|
|
||||||
var tokenVulcanList: List<Int>
|
|
||||||
get() { mTokenVulcanList = mTokenVulcanList ?: config.values.getIntList("tokenVulcanList", listOf()); return mTokenVulcanList ?: listOf() }
|
|
||||||
set(value) { config.set("tokenVulcanList", value); mTokenVulcanList = value }
|
|
||||||
private var mTokenVulcanHebeList: List<Int>? = null
|
|
||||||
var tokenVulcanHebeList: List<Int>
|
|
||||||
get() { mTokenVulcanHebeList = mTokenVulcanHebeList ?: config.values.getIntList("tokenVulcanHebeList", listOf()); return mTokenVulcanHebeList ?: listOf() }
|
|
||||||
set(value) { config.set("tokenVulcanHebeList", value); mTokenVulcanHebeList = value }
|
|
||||||
|
|
||||||
private var mRegisterAvailability: Map<String, RegisterAvailabilityStatus>? = null
|
|
||||||
var registerAvailability: Map<String, RegisterAvailabilityStatus>
|
var registerAvailability: Map<String, RegisterAvailabilityStatus>
|
||||||
get() {
|
get() {
|
||||||
val flavor = config.values.get("registerAvailabilityFlavor", null as String?)
|
if (BuildConfig.FLAVOR != registerAvailabilityFlavor)
|
||||||
if (BuildConfig.FLAVOR != flavor)
|
|
||||||
return mapOf()
|
return mapOf()
|
||||||
|
return registerAvailabilityMap
|
||||||
mRegisterAvailability = mRegisterAvailability ?: config.values.get("registerAvailability", null as String?)?.let { it ->
|
|
||||||
gson.fromJson(it, object: TypeToken<Map<String, RegisterAvailabilityStatus>>(){}.type)
|
|
||||||
}
|
|
||||||
return mRegisterAvailability ?: mapOf()
|
|
||||||
}
|
}
|
||||||
set(value) {
|
set(value) {
|
||||||
config.setMap("registerAvailability", value)
|
registerAvailabilityMap = value
|
||||||
config.set("registerAvailabilityFlavor", BuildConfig.FLAVOR)
|
registerAvailabilityFlavor = BuildConfig.FLAVOR
|
||||||
mRegisterAvailability = value
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,23 +4,12 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.get
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.set
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||||
|
|
||||||
class ConfigTimetable(private val config: Config) {
|
@Suppress("RemoveExplicitTypeArguments")
|
||||||
private var mBellSyncMultiplier: Int? = null
|
class ConfigTimetable(base: Config) {
|
||||||
var bellSyncMultiplier: Int
|
|
||||||
get() { mBellSyncMultiplier = mBellSyncMultiplier ?: config.values.get("bellSyncMultiplier", 0); return mBellSyncMultiplier ?: 0 }
|
|
||||||
set(value) { config.set("bellSyncMultiplier", value); mBellSyncMultiplier = value }
|
|
||||||
|
|
||||||
private var mBellSyncDiff: Time? = null
|
var bellSyncMultiplier by base.config<Int>(0)
|
||||||
var bellSyncDiff: Time?
|
var bellSyncDiff by base.config<Time?>(null)
|
||||||
get() { mBellSyncDiff = mBellSyncDiff ?: config.values.get("bellSyncDiff", null as Time?); return mBellSyncDiff }
|
var countInSeconds by base.config<Boolean>(false)
|
||||||
set(value) { config.set("bellSyncDiff", value); mBellSyncDiff = value }
|
|
||||||
|
|
||||||
private var mCountInSeconds: Boolean? = null
|
|
||||||
var countInSeconds: Boolean
|
|
||||||
get() { mCountInSeconds = mCountInSeconds ?: config.values.get("countInSeconds", false); return mCountInSeconds ?: false }
|
|
||||||
set(value) { config.set("countInSeconds", value); mCountInSeconds = value }
|
|
||||||
}
|
}
|
@ -4,60 +4,32 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.get
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.getIntList
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.set
|
|
||||||
import pl.szczodrzynski.edziennik.ext.asNavTargetOrNull
|
|
||||||
import pl.szczodrzynski.edziennik.ui.base.enums.NavTarget
|
import pl.szczodrzynski.edziennik.ui.base.enums.NavTarget
|
||||||
|
|
||||||
class ConfigUI(private val config: Config) {
|
@Suppress("RemoveExplicitTypeArguments")
|
||||||
private var mTheme: Int? = null
|
class ConfigUI(base: Config) {
|
||||||
var theme: Int
|
|
||||||
get() { mTheme = mTheme ?: config.values.get("theme", 1); return mTheme ?: 1 }
|
|
||||||
set(value) { config.set("theme", value); mTheme = value }
|
|
||||||
|
|
||||||
private var mLanguage: String? = null
|
var theme by base.config<Int>(1)
|
||||||
var language: String?
|
var language by base.config<String?>(null)
|
||||||
get() { mLanguage = mLanguage ?: config.values.get("language", null as String?); return mLanguage }
|
|
||||||
set(value) { config.set("language", value); mLanguage = value }
|
|
||||||
|
|
||||||
private var mHeaderBackground: String? = null
|
var appBackground by base.config<String?>("appBg", null)
|
||||||
var headerBackground: String?
|
var headerBackground by base.config<String?>("headerBg", null)
|
||||||
get() { mHeaderBackground = mHeaderBackground ?: config.values.get("headerBg", null as String?); return mHeaderBackground }
|
|
||||||
set(value) { config.set("headerBg", value); mHeaderBackground = value }
|
|
||||||
|
|
||||||
private var mAppBackground: String? = null
|
var miniMenuVisible by base.config<Boolean>(false)
|
||||||
var appBackground: String?
|
var miniMenuButtons by base.config<Set<NavTarget>> {
|
||||||
get() { mAppBackground = mAppBackground ?: config.values.get("appBg", null as String?); return mAppBackground }
|
setOf(
|
||||||
set(value) { config.set("appBg", value); mAppBackground = value }
|
NavTarget.HOME,
|
||||||
|
NavTarget.TIMETABLE,
|
||||||
private var mMiniMenuVisible: Boolean? = null
|
NavTarget.AGENDA,
|
||||||
var miniMenuVisible: Boolean
|
NavTarget.GRADES,
|
||||||
get() { mMiniMenuVisible = mMiniMenuVisible ?: config.values.get("miniMenuVisible", false); return mMiniMenuVisible ?: false }
|
NavTarget.MESSAGES,
|
||||||
set(value) { config.set("miniMenuVisible", value); mMiniMenuVisible = value }
|
NavTarget.HOMEWORK,
|
||||||
|
NavTarget.SETTINGS
|
||||||
private var mMiniMenuButtons: Set<NavTarget>? = null
|
)
|
||||||
var miniMenuButtons: Set<NavTarget>
|
}
|
||||||
get() { mMiniMenuButtons = mMiniMenuButtons ?: config.values.getIntList("miniMenuButtons", listOf())?.mapNotNull { it.asNavTargetOrNull() }?.toSet(); return mMiniMenuButtons ?: setOf() }
|
var openDrawerOnBackPressed by base.config<Boolean>(false)
|
||||||
set(value) { config.set("miniMenuButtons", value.map { it.id }); mMiniMenuButtons = value }
|
|
||||||
|
var bottomSheetOpened by base.config<Boolean>(false)
|
||||||
private var mOpenDrawerOnBackPressed: Boolean? = null
|
var snowfall by base.config<Boolean>(false)
|
||||||
var openDrawerOnBackPressed: Boolean
|
var eggfall by base.config<Boolean>(false)
|
||||||
get() { mOpenDrawerOnBackPressed = mOpenDrawerOnBackPressed ?: config.values.get("openDrawerOnBackPressed", false); return mOpenDrawerOnBackPressed ?: false }
|
|
||||||
set(value) { config.set("openDrawerOnBackPressed", value); mOpenDrawerOnBackPressed = value }
|
|
||||||
|
|
||||||
private var mSnowfall: Boolean? = null
|
|
||||||
var snowfall: Boolean
|
|
||||||
get() { mSnowfall = mSnowfall ?: config.values.get("snowfall", false); return mSnowfall ?: false }
|
|
||||||
set(value) { config.set("snowfall", value); mSnowfall = value }
|
|
||||||
|
|
||||||
private var mEggfall: Boolean? = null
|
|
||||||
var eggfall: Boolean
|
|
||||||
get() { mEggfall = mEggfall ?: config.values.get("eggfall", false); return mEggfall ?: false }
|
|
||||||
set(value) { config.set("eggfall", value); mEggfall = value }
|
|
||||||
|
|
||||||
private var mBottomSheetOpened: Boolean? = null
|
|
||||||
var bottomSheetOpened: Boolean
|
|
||||||
get() { mBottomSheetOpened = mBottomSheetOpened ?: config.values.get("bottomSheetOpened", false); return mBottomSheetOpened ?: false }
|
|
||||||
set(value) { config.set("bottomSheetOpened", value); mBottomSheetOpened = value }
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2022-10-21.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.JsonArray
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
import pl.szczodrzynski.edziennik.ext.*
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||||
|
import java.lang.reflect.ParameterizedType
|
||||||
|
import java.lang.reflect.WildcardType
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
private val gson = Gson()
|
||||||
|
|
||||||
|
inline fun <reified T> BaseConfig.config(name: String? = null, noinline default: () -> T) = ConfigDelegate(
|
||||||
|
config = this,
|
||||||
|
type = T::class.java,
|
||||||
|
nullable = null is T,
|
||||||
|
typeToken = object : TypeToken<T>() {},
|
||||||
|
defaultFunc = default,
|
||||||
|
defaultValue = null,
|
||||||
|
fieldName = name,
|
||||||
|
)
|
||||||
|
|
||||||
|
inline fun <reified T> BaseConfig.config(default: T) = ConfigDelegate(
|
||||||
|
config = this,
|
||||||
|
type = T::class.java,
|
||||||
|
nullable = null is T,
|
||||||
|
typeToken = object : TypeToken<T>() {},
|
||||||
|
defaultFunc = null,
|
||||||
|
defaultValue = default,
|
||||||
|
fieldName = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
inline fun <reified T> BaseConfig.config(name: String? = null, default: T) = ConfigDelegate(
|
||||||
|
config = this,
|
||||||
|
type = T::class.java,
|
||||||
|
nullable = null is T,
|
||||||
|
typeToken = object : TypeToken<T>() {},
|
||||||
|
defaultFunc = null,
|
||||||
|
defaultValue = default,
|
||||||
|
fieldName = name,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
class ConfigDelegate<T>(
|
||||||
|
private val config: BaseConfig,
|
||||||
|
private val type: Class<T>,
|
||||||
|
private val nullable: Boolean,
|
||||||
|
private val typeToken: TypeToken<T>,
|
||||||
|
private val defaultFunc: (() -> T)?,
|
||||||
|
private val defaultValue: T?,
|
||||||
|
private val fieldName: String?,
|
||||||
|
) {
|
||||||
|
private var value: T? = null
|
||||||
|
private var isInitialized = false
|
||||||
|
|
||||||
|
private fun getDefault(): T = when {
|
||||||
|
defaultFunc != null -> defaultFunc.invoke()
|
||||||
|
else -> defaultValue as T
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getGenericType(index: Int = 0): Class<*> {
|
||||||
|
val parameterizedType = typeToken.type as ParameterizedType
|
||||||
|
val typeArgument = parameterizedType.actualTypeArguments[index] as WildcardType
|
||||||
|
return typeArgument.upperBounds[0] as Class<*>
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun setValue(_thisRef: Any, property: KProperty<*>, newValue: T) {
|
||||||
|
value = newValue
|
||||||
|
isInitialized = true
|
||||||
|
config.set(fieldName ?: property.name, serialize(newValue)?.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun getValue(_thisRef: Any, property: KProperty<*>): T {
|
||||||
|
if (isInitialized)
|
||||||
|
return value as T
|
||||||
|
val key = fieldName ?: property.name
|
||||||
|
|
||||||
|
if (key !in config.values) {
|
||||||
|
value = getDefault()
|
||||||
|
isInitialized = true
|
||||||
|
return value as T
|
||||||
|
}
|
||||||
|
val str = config.values[key]
|
||||||
|
|
||||||
|
value = if (str == null && nullable)
|
||||||
|
null as T
|
||||||
|
else if (str == null)
|
||||||
|
getDefault()
|
||||||
|
else
|
||||||
|
deserialize(str)
|
||||||
|
|
||||||
|
isInitialized = true
|
||||||
|
return value as T
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <I> serialize(value: I?, serializeObjects: Boolean = true): Any? {
|
||||||
|
if (value == null)
|
||||||
|
return null
|
||||||
|
|
||||||
|
return when (value) {
|
||||||
|
is String -> value
|
||||||
|
is Date -> value.stringY_m_d
|
||||||
|
is Time -> value.stringValue
|
||||||
|
is JsonObject -> value
|
||||||
|
is JsonArray -> value
|
||||||
|
// primitives
|
||||||
|
is Number -> value
|
||||||
|
is Boolean -> value
|
||||||
|
// enums, maps & collections
|
||||||
|
is Enum<*> -> value.toInt()
|
||||||
|
is Collection<*> -> JsonArray(value.map {
|
||||||
|
if (it is Number || it is Boolean) it else serialize(it, serializeObjects = false)
|
||||||
|
})
|
||||||
|
is Map<*, *> -> gson.toJson(value.mapValues { (_, it) ->
|
||||||
|
if (it is Number || it is Boolean) it else serialize(it, serializeObjects = false)
|
||||||
|
})
|
||||||
|
// objects or else
|
||||||
|
else -> if (serializeObjects) gson.toJson(value) else value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <I> deserialize(value: String?, type: Class<*> = this.type): I? {
|
||||||
|
if (value == null)
|
||||||
|
return null
|
||||||
|
|
||||||
|
@Suppress("TYPE_MISMATCH_WARNING")
|
||||||
|
return when (type) {
|
||||||
|
String::class.java -> value
|
||||||
|
Date::class.java -> Date.fromY_m_d(value)
|
||||||
|
Time::class.java -> Time.fromHms(value)
|
||||||
|
JsonObject::class.java -> value.toJsonObject()
|
||||||
|
JsonArray::class.java -> value.toJsonArray()
|
||||||
|
// primitives
|
||||||
|
java.lang.Integer::class.java -> value.toIntOrNull()
|
||||||
|
java.lang.Boolean::class.java -> value.toBooleanStrictOrNull()
|
||||||
|
java.lang.Long::class.java -> value.toLongOrNull()
|
||||||
|
java.lang.Float::class.java -> value.toFloatOrNull()
|
||||||
|
// enums, maps & collections
|
||||||
|
else -> when {
|
||||||
|
Enum::class.java.isAssignableFrom(type) -> value.toIntOrNull()?.toEnum(type) as Enum<*>
|
||||||
|
Collection::class.java.isAssignableFrom(type) -> {
|
||||||
|
val array = value.toJsonArray()
|
||||||
|
val genericType = getGenericType()
|
||||||
|
val list = array?.map {
|
||||||
|
val str = if (it.isJsonPrimitive) it.asString else it.toString()
|
||||||
|
deserialize<Any>(str, genericType)
|
||||||
|
}
|
||||||
|
when {
|
||||||
|
List::class.java.isAssignableFrom(type) -> list
|
||||||
|
Set::class.java.isAssignableFrom(type) -> list?.toSet()
|
||||||
|
else -> list?.toTypedArray()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Map::class.java.isAssignableFrom(type) -> {
|
||||||
|
val obj = value.toJsonObject()
|
||||||
|
val genericType = getGenericType(index = 1)
|
||||||
|
val map = obj?.entrySet()?.associate { (key, it) ->
|
||||||
|
val str = if (it.isJsonPrimitive) it.asString else it.toString()
|
||||||
|
key to deserialize<Any>(str, genericType)
|
||||||
|
}
|
||||||
|
map
|
||||||
|
}
|
||||||
|
// objects or else
|
||||||
|
else -> gson.fromJson(value, type)
|
||||||
|
}
|
||||||
|
} as? I
|
||||||
|
}
|
||||||
|
}
|
@ -4,29 +4,20 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config
|
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.config.db.ConfigEntry
|
import pl.szczodrzynski.edziennik.config.db.ConfigEntry
|
||||||
import pl.szczodrzynski.edziennik.config.utils.ProfileConfigMigration
|
import pl.szczodrzynski.edziennik.config.utils.ProfileConfigMigration
|
||||||
import pl.szczodrzynski.edziennik.config.utils.get
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.set
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.toHashMap
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.AppDb
|
import pl.szczodrzynski.edziennik.data.db.AppDb
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
class ProfileConfig(val db: AppDb, val profileId: Int, rawEntries: List<ConfigEntry>) : CoroutineScope, AbstractConfig {
|
@Suppress("RemoveExplicitTypeArguments")
|
||||||
|
class ProfileConfig(
|
||||||
|
db: AppDb,
|
||||||
|
profileId: Int,
|
||||||
|
entries: List<ConfigEntry>?,
|
||||||
|
) : BaseConfig(db, profileId, entries) {
|
||||||
companion object {
|
companion object {
|
||||||
const val DATA_VERSION = 3
|
const val DATA_VERSION = 4
|
||||||
}
|
}
|
||||||
|
|
||||||
private val job = Job()
|
|
||||||
override val coroutineContext: CoroutineContext
|
|
||||||
get() = job + Dispatchers.Default
|
|
||||||
|
|
||||||
val values: HashMap<String, String?> = hashMapOf()
|
|
||||||
|
|
||||||
val grades by lazy { ProfileConfigGrades(this) }
|
val grades by lazy { ProfileConfigGrades(this) }
|
||||||
val ui by lazy { ProfileConfigUI(this) }
|
val ui by lazy { ProfileConfigUI(this) }
|
||||||
val sync by lazy { ProfileConfigSync(this) }
|
val sync by lazy { ProfileConfigSync(this) }
|
||||||
@ -35,26 +26,11 @@ class ProfileConfig(val db: AppDb, val profileId: Int, rawEntries: List<ConfigEn
|
|||||||
val timetable by lazy { ConfigTimetable(this) }
|
val timetable by lazy { ConfigTimetable(this) }
|
||||||
val grades by lazy { ConfigGrades(this) }*/
|
val grades by lazy { ConfigGrades(this) }*/
|
||||||
|
|
||||||
private var mDataVersion: Int? = null
|
var dataVersion by config<Int>(0)
|
||||||
var dataVersion: Int
|
var hash by config<String>("")
|
||||||
get() { mDataVersion = mDataVersion ?: values.get("dataVersion", 0); return mDataVersion ?: 0 }
|
|
||||||
set(value) { set("dataVersion", value); mDataVersion = value }
|
|
||||||
|
|
||||||
private var mHash: String? = null
|
|
||||||
var hash: String
|
|
||||||
get() { mHash = mHash ?: values.get("hash", ""); return mHash ?: "" }
|
|
||||||
set(value) { set("hash", value); mHash = value }
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
rawEntries.toHashMap(profileId, values)
|
|
||||||
if (dataVersion < DATA_VERSION)
|
if (dataVersion < DATA_VERSION)
|
||||||
ProfileConfigMigration(this)
|
ProfileConfigMigration(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun set(key: String, value: String?) {
|
|
||||||
values[key] = value
|
|
||||||
launch {
|
|
||||||
db.configDao().add(ConfigEntry(profileId, key, value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -4,27 +4,11 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.get
|
@Suppress("RemoveExplicitTypeArguments")
|
||||||
import pl.szczodrzynski.edziennik.config.utils.set
|
class ProfileConfigAttendance(base: ProfileConfig) {
|
||||||
|
|
||||||
class ProfileConfigAttendance(private val config: ProfileConfig) {
|
var attendancePageSelection by base.config<Int>(1)
|
||||||
private var mAttendancePageSelection: Int? = null
|
var groupConsecutiveDays by base.config<Boolean>(true)
|
||||||
var attendancePageSelection: Int
|
var showPresenceInMonth by base.config<Boolean>(false)
|
||||||
get() { mAttendancePageSelection = mAttendancePageSelection ?: config.values.get("attendancePageSelection", 1); return mAttendancePageSelection ?: 1 }
|
var useSymbols by base.config<Boolean>(false)
|
||||||
set(value) { config.set("attendancePageSelection", value); mAttendancePageSelection = value }
|
|
||||||
|
|
||||||
private var mUseSymbols: Boolean? = null
|
|
||||||
var useSymbols: Boolean
|
|
||||||
get() { mUseSymbols = mUseSymbols ?: config.values.get("useSymbols", false); return mUseSymbols ?: false }
|
|
||||||
set(value) { config.set("useSymbols", value); mUseSymbols = value }
|
|
||||||
|
|
||||||
private var mGroupConsecutiveDays: Boolean? = null
|
|
||||||
var groupConsecutiveDays: Boolean
|
|
||||||
get() { mGroupConsecutiveDays = mGroupConsecutiveDays ?: config.values.get("groupConsecutiveDays", true); return mGroupConsecutiveDays ?: true }
|
|
||||||
set(value) { config.set("groupConsecutiveDays", value); mGroupConsecutiveDays = value }
|
|
||||||
|
|
||||||
private var mShowPresenceInMonth: Boolean? = null
|
|
||||||
var showPresenceInMonth: Boolean
|
|
||||||
get() { mShowPresenceInMonth = mShowPresenceInMonth ?: config.values.get("showPresenceInMonth", false); return mShowPresenceInMonth ?: false }
|
|
||||||
set(value) { config.set("showPresenceInMonth", value); mShowPresenceInMonth = value }
|
|
||||||
}
|
}
|
||||||
|
@ -4,54 +4,19 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.get
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.getFloat
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.set
|
|
||||||
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.COLOR_MODE_WEIGHTED
|
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.COLOR_MODE_WEIGHTED
|
||||||
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_ALL_GRADES
|
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_ALL_GRADES
|
||||||
|
|
||||||
class ProfileConfigGrades(private val config: ProfileConfig) {
|
@Suppress("RemoveExplicitTypeArguments")
|
||||||
private var mColorMode: Int? = null
|
class ProfileConfigGrades(base: ProfileConfig) {
|
||||||
var colorMode: Int
|
|
||||||
get() { mColorMode = mColorMode ?: config.values.get("gradesColorMode", COLOR_MODE_WEIGHTED); return mColorMode ?: COLOR_MODE_WEIGHTED }
|
|
||||||
set(value) { config.set("gradesColorMode", value); mColorMode = value }
|
|
||||||
|
|
||||||
private var mYearAverageMode: Int? = null
|
var averageWithoutWeight by base.config<Boolean>(true)
|
||||||
var yearAverageMode: Int
|
var colorMode by base.config<Int>(COLOR_MODE_WEIGHTED)
|
||||||
get() { mYearAverageMode = mYearAverageMode ?: config.values.get("yearAverageMode", YEAR_ALL_GRADES); return mYearAverageMode ?: YEAR_ALL_GRADES }
|
var dontCountEnabled by base.config<Boolean>(false)
|
||||||
set(value) { config.set("yearAverageMode", value); mYearAverageMode = value }
|
var dontCountGrades by base.config<List<String>> { listOf() }
|
||||||
|
var hideImproved by base.config<Boolean>(false)
|
||||||
private var mHideImproved: Boolean? = null
|
var hideSticksFromOld by base.config<Boolean>(false)
|
||||||
var hideImproved: Boolean
|
var minusValue by base.config<Float?>(null)
|
||||||
get() { mHideImproved = mHideImproved ?: config.values.get("hideImproved", false); return mHideImproved ?: false }
|
var plusValue by base.config<Float?>(null)
|
||||||
set(value) { config.set("hideImproved", value); mHideImproved = value }
|
var yearAverageMode by base.config<Int>(YEAR_ALL_GRADES)
|
||||||
|
|
||||||
private var mAverageWithoutWeight: Boolean? = null
|
|
||||||
var averageWithoutWeight: Boolean
|
|
||||||
get() { mAverageWithoutWeight = mAverageWithoutWeight ?: config.values.get("averageWithoutWeight", true); return mAverageWithoutWeight ?: true }
|
|
||||||
set(value) { config.set("averageWithoutWeight", value); mAverageWithoutWeight = value }
|
|
||||||
|
|
||||||
private var mPlusValue: Float? = null
|
|
||||||
var plusValue: Float?
|
|
||||||
get() { mPlusValue = mPlusValue ?: config.values.getFloat("plusValue"); return mPlusValue }
|
|
||||||
set(value) { config.set("plusValue", value); mPlusValue = value }
|
|
||||||
private var mMinusValue: Float? = null
|
|
||||||
var minusValue: Float?
|
|
||||||
get() { mMinusValue = mMinusValue ?: config.values.getFloat("minusValue"); return mMinusValue }
|
|
||||||
set(value) { config.set("minusValue", value); mMinusValue = value }
|
|
||||||
|
|
||||||
private var mDontCountEnabled: Boolean? = null
|
|
||||||
var dontCountEnabled: Boolean
|
|
||||||
get() { mDontCountEnabled = mDontCountEnabled ?: config.values.get("dontCountEnabled", false); return mDontCountEnabled ?: false }
|
|
||||||
set(value) { config.set("dontCountEnabled", value); mDontCountEnabled = value }
|
|
||||||
|
|
||||||
private var mDontCountGrades: List<String>? = null
|
|
||||||
var dontCountGrades: List<String>
|
|
||||||
get() { mDontCountGrades = mDontCountGrades ?: config.values.get("dontCountGrades", listOf()); return mDontCountGrades ?: listOf() }
|
|
||||||
set(value) { config.set("dontCountGrades", value); mDontCountGrades = value }
|
|
||||||
|
|
||||||
private var mHideSticksFromOld: Boolean? = null
|
|
||||||
var hideSticksFromOld: Boolean
|
|
||||||
get() { mHideSticksFromOld = mHideSticksFromOld ?: config.values.get("hideSticksFromOld", false); return mHideSticksFromOld ?: false }
|
|
||||||
set(value) { config.set("hideSticksFromOld", value); mHideSticksFromOld = value }
|
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,14 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.getIntList
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.set
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.enums.NotificationType
|
import pl.szczodrzynski.edziennik.data.db.enums.NotificationType
|
||||||
import pl.szczodrzynski.edziennik.ext.asNotificationTypeOrNull
|
|
||||||
|
|
||||||
class ProfileConfigSync(private val config: ProfileConfig) {
|
@Suppress("RemoveExplicitTypeArguments")
|
||||||
private var mNotificationFilter: Set<NotificationType>? = null
|
class ProfileConfigSync(base: ProfileConfig) {
|
||||||
var notificationFilter: Set<NotificationType>
|
|
||||||
get() { mNotificationFilter = mNotificationFilter ?: config.values.getIntList("notificationFilter", listOf())?.mapNotNull { it.asNotificationTypeOrNull() }?.toSet(); return mNotificationFilter ?: setOf() }
|
var notificationFilter by base.config<Set<NotificationType>> {
|
||||||
set(value) { config.set("notificationFilter", value.map { it.id }); mNotificationFilter = value }
|
NotificationType.values()
|
||||||
|
.filter { it.enabledByDefault == false }
|
||||||
|
.toSet()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,89 +4,29 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config
|
package pl.szczodrzynski.edziennik.config
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.get
|
|
||||||
import pl.szczodrzynski.edziennik.config.utils.set
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.AGENDA_DEFAULT
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.AGENDA_DEFAULT
|
||||||
import pl.szczodrzynski.edziennik.ui.home.HomeCardModel
|
import pl.szczodrzynski.edziennik.ui.home.HomeCardModel
|
||||||
|
|
||||||
class ProfileConfigUI(private val config: ProfileConfig) {
|
@Suppress("RemoveExplicitTypeArguments")
|
||||||
private var mAgendaViewType: Int? = null
|
class ProfileConfigUI(base: ProfileConfig) {
|
||||||
var agendaViewType: Int
|
|
||||||
get() { mAgendaViewType = mAgendaViewType ?: config.values.get("agendaViewType", 0); return mAgendaViewType ?: AGENDA_DEFAULT }
|
|
||||||
set(value) { config.set("agendaViewType", value); mAgendaViewType = value }
|
|
||||||
|
|
||||||
private var mAgendaCompactMode: Boolean? = null
|
var agendaViewType by base.config<Int>(AGENDA_DEFAULT)
|
||||||
var agendaCompactMode: Boolean
|
var agendaCompactMode by base.config<Boolean>(false)
|
||||||
get() { mAgendaCompactMode = mAgendaCompactMode ?: config.values.get("agendaCompactMode", false); return mAgendaCompactMode ?: false }
|
var agendaGroupByType by base.config<Boolean>(false)
|
||||||
set(value) { config.set("agendaCompactMode", value); mAgendaCompactMode = value }
|
var agendaLessonChanges by base.config<Boolean>(true)
|
||||||
|
var agendaTeacherAbsence by base.config<Boolean>(true)
|
||||||
|
var agendaElearningMark by base.config<Boolean>(false)
|
||||||
|
var agendaElearningGroup by base.config<Boolean>(true)
|
||||||
|
|
||||||
private var mAgendaGroupByType: Boolean? = null
|
var homeCards by base.config<List<HomeCardModel>> { listOf() }
|
||||||
var agendaGroupByType: Boolean
|
|
||||||
get() { mAgendaGroupByType = mAgendaGroupByType ?: config.values.get("agendaGroupByType", false); return mAgendaGroupByType ?: false }
|
|
||||||
set(value) { config.set("agendaGroupByType", value); mAgendaGroupByType = value }
|
|
||||||
|
|
||||||
private var mAgendaLessonChanges: Boolean? = null
|
var messagesGreetingOnCompose by base.config<Boolean>(true)
|
||||||
var agendaLessonChanges: Boolean
|
var messagesGreetingOnReply by base.config<Boolean>(true)
|
||||||
get() { mAgendaLessonChanges = mAgendaLessonChanges ?: config.values.get("agendaLessonChanges", true); return mAgendaLessonChanges ?: true }
|
var messagesGreetingOnForward by base.config<Boolean>(false)
|
||||||
set(value) { config.set("agendaLessonChanges", value); mAgendaLessonChanges = value }
|
var messagesGreetingText by base.config<String?>(null)
|
||||||
|
|
||||||
private var mAgendaTeacherAbsence: Boolean? = null
|
var timetableShowAttendance by base.config<Boolean>(true)
|
||||||
var agendaTeacherAbsence: Boolean
|
var timetableShowEvents by base.config<Boolean>(true)
|
||||||
get() { mAgendaTeacherAbsence = mAgendaTeacherAbsence ?: config.values.get("agendaTeacherAbsence", true); return mAgendaTeacherAbsence ?: true }
|
var timetableTrimHourRange by base.config<Boolean>(false)
|
||||||
set(value) { config.set("agendaTeacherAbsence", value); mAgendaTeacherAbsence = value }
|
var timetableColorSubjectName by base.config<Boolean>(false)
|
||||||
|
|
||||||
private var mAgendaElearningMark: Boolean? = null
|
|
||||||
var agendaElearningMark: Boolean
|
|
||||||
get() { mAgendaElearningMark = mAgendaElearningMark ?: config.values.get("agendaElearningMark", false); return mAgendaElearningMark ?: false }
|
|
||||||
set(value) { config.set("agendaElearningMark", value); mAgendaElearningMark = value }
|
|
||||||
|
|
||||||
private var mAgendaElearningGroup: Boolean? = null
|
|
||||||
var agendaElearningGroup: Boolean
|
|
||||||
get() { mAgendaElearningGroup = mAgendaElearningGroup ?: config.values.get("agendaElearningGroup", true); return mAgendaElearningGroup ?: true }
|
|
||||||
set(value) { config.set("agendaElearningGroup", value); mAgendaElearningGroup = value }
|
|
||||||
|
|
||||||
private var mHomeCards: List<HomeCardModel>? = null
|
|
||||||
var homeCards: List<HomeCardModel>
|
|
||||||
get() { mHomeCards = mHomeCards ?: config.values.get("homeCards", listOf(), HomeCardModel::class.java); return mHomeCards ?: listOf() }
|
|
||||||
set(value) { config.set("homeCards", value); mHomeCards = value }
|
|
||||||
|
|
||||||
private var mMessagesGreetingOnCompose: Boolean? = null
|
|
||||||
var messagesGreetingOnCompose: Boolean
|
|
||||||
get() { mMessagesGreetingOnCompose = mMessagesGreetingOnCompose ?: config.values.get("messagesGreetingOnCompose", true); return mMessagesGreetingOnCompose ?: true }
|
|
||||||
set(value) { config.set("messagesGreetingOnCompose", value); mMessagesGreetingOnCompose = value }
|
|
||||||
|
|
||||||
private var mMessagesGreetingOnReply: Boolean? = null
|
|
||||||
var messagesGreetingOnReply: Boolean
|
|
||||||
get() { mMessagesGreetingOnReply = mMessagesGreetingOnReply ?: config.values.get("messagesGreetingOnReply", true); return mMessagesGreetingOnReply ?: true }
|
|
||||||
set(value) { config.set("messagesGreetingOnReply", value); mMessagesGreetingOnReply = value }
|
|
||||||
|
|
||||||
private var mMessagesGreetingOnForward: Boolean? = null
|
|
||||||
var messagesGreetingOnForward: Boolean
|
|
||||||
get() { mMessagesGreetingOnForward = mMessagesGreetingOnForward ?: config.values.get("messagesGreetingOnForward", false); return mMessagesGreetingOnForward ?: false }
|
|
||||||
set(value) { config.set("messagesGreetingOnForward", value); mMessagesGreetingOnForward = value }
|
|
||||||
|
|
||||||
private var mMessagesGreetingText: String? = null
|
|
||||||
var messagesGreetingText: String?
|
|
||||||
get() { mMessagesGreetingText = mMessagesGreetingText ?: config.values["messagesGreetingText"]; return mMessagesGreetingText }
|
|
||||||
set(value) { config.set("messagesGreetingText", value); mMessagesGreetingText = value }
|
|
||||||
|
|
||||||
private var mTimetableShowAttendance: Boolean? = null
|
|
||||||
var timetableShowAttendance: Boolean
|
|
||||||
get() { mTimetableShowAttendance = mTimetableShowAttendance ?: config.values.get("timetableShowAttendance", true); return mTimetableShowAttendance ?: true }
|
|
||||||
set(value) { config.set("timetableShowAttendance", value); mTimetableShowAttendance = value }
|
|
||||||
|
|
||||||
private var mTimetableShowEvents: Boolean? = null
|
|
||||||
var timetableShowEvents: Boolean
|
|
||||||
get() { mTimetableShowEvents = mTimetableShowEvents ?: config.values.get("timetableShowEvents", true); return mTimetableShowEvents ?: true }
|
|
||||||
set(value) { config.set("timetableShowEvents", value); mTimetableShowEvents = value }
|
|
||||||
|
|
||||||
private var mTimetableTrimHourRange: Boolean? = null
|
|
||||||
var timetableTrimHourRange: Boolean
|
|
||||||
get() { mTimetableTrimHourRange = mTimetableTrimHourRange ?: config.values.get("timetableTrimHourRange", false); return mTimetableTrimHourRange ?: false }
|
|
||||||
set(value) { config.set("timetableTrimHourRange", value); mTimetableTrimHourRange = value }
|
|
||||||
|
|
||||||
private var mTimetableColorSubjectName: Boolean? = null
|
|
||||||
var timetableColorSubjectName: Boolean
|
|
||||||
get() { mTimetableColorSubjectName = mTimetableColorSubjectName ?: config.values.get("timetableColorSubjectName", false); return mTimetableColorSubjectName ?: false }
|
|
||||||
set(value) { config.set("timetableColorSubjectName", value); mTimetableColorSubjectName = value }
|
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ interface ConfigDao {
|
|||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
fun addAll(list: List<ConfigEntry>)
|
fun addAll(list: List<ConfigEntry>)
|
||||||
|
|
||||||
@Query("SELECT * FROM config WHERE profileId = -1")
|
@Query("SELECT * FROM config")
|
||||||
fun getAllNow(): List<ConfigEntry>
|
fun getAllNow(): List<ConfigEntry>
|
||||||
|
|
||||||
@Query("SELECT * FROM config WHERE profileId = :profileId")
|
@Query("SELECT * FROM config WHERE profileId = :profileId")
|
||||||
|
@ -1,113 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-11-27.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.config.utils
|
|
||||||
|
|
||||||
import com.google.gson.*
|
|
||||||
import com.google.gson.reflect.TypeToken
|
|
||||||
import pl.szczodrzynski.edziennik.config.AbstractConfig
|
|
||||||
import pl.szczodrzynski.edziennik.config.db.ConfigEntry
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
|
||||||
|
|
||||||
private val gson = Gson()
|
|
||||||
|
|
||||||
fun AbstractConfig.set(key: String, value: Int) {
|
|
||||||
set(key, value.toString())
|
|
||||||
}
|
|
||||||
fun AbstractConfig.set(key: String, value: Boolean) {
|
|
||||||
set(key, value.toString())
|
|
||||||
}
|
|
||||||
fun AbstractConfig.set(key: String, value: Long) {
|
|
||||||
set(key, value.toString())
|
|
||||||
}
|
|
||||||
fun AbstractConfig.set(key: String, value: Float) {
|
|
||||||
set(key, value.toString())
|
|
||||||
}
|
|
||||||
fun AbstractConfig.set(key: String, value: Date?) {
|
|
||||||
set(key, value?.stringY_m_d)
|
|
||||||
}
|
|
||||||
fun AbstractConfig.set(key: String, value: Time?) {
|
|
||||||
set(key, value?.stringValue)
|
|
||||||
}
|
|
||||||
fun AbstractConfig.set(key: String, value: JsonElement?) {
|
|
||||||
set(key, value?.toString())
|
|
||||||
}
|
|
||||||
fun AbstractConfig.set(key: String, value: List<Any>?) {
|
|
||||||
set(key, value?.let { gson.toJson(it) })
|
|
||||||
}
|
|
||||||
fun AbstractConfig.set(key: String, value: Any?) {
|
|
||||||
set(key, value?.let { gson.toJson(it) })
|
|
||||||
}
|
|
||||||
fun AbstractConfig.setStringList(key: String, value: List<String>?) {
|
|
||||||
set(key, value?.let { gson.toJson(it) })
|
|
||||||
}
|
|
||||||
fun AbstractConfig.setIntList(key: String, value: List<Int>?) {
|
|
||||||
set(key, value?.let { gson.toJson(it) })
|
|
||||||
}
|
|
||||||
fun AbstractConfig.setLongList(key: String, value: List<Long>?) {
|
|
||||||
set(key, value?.let { gson.toJson(it) })
|
|
||||||
}
|
|
||||||
fun <K, V> AbstractConfig.setMap(key: String, value: Map<K, V>?) {
|
|
||||||
set(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?>.getBooleanOrNull(key: String): Boolean? {
|
|
||||||
return this[key]?.toBooleanStrictOrNull()
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
inline fun <reified T> HashMap<String, String?>.get(key: String, default: T?): T? {
|
|
||||||
return this[key]?.let { Gson().fromJson(it, T::class.java) } ?: default
|
|
||||||
}
|
|
||||||
/* !!! cannot use mutable list here - modifying it will not update the DB */
|
|
||||||
fun <T> HashMap<String, String?>.get(key: String, default: List<T>?, classOfT: Class<T>): List<T>? {
|
|
||||||
return this[key]?.let { ConfigGsonUtils().deserializeList<T>(gson, it, classOfT) } ?: 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 HashMap<String, String?>.getFloat(key: String): Float? {
|
|
||||||
return this[key]?.toFloatOrNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun List<ConfigEntry>.toHashMap(profileId: Int, map: HashMap<String, String?>) {
|
|
||||||
map.clear()
|
|
||||||
forEach {
|
|
||||||
if (it.profileId == profileId)
|
|
||||||
map[it.key] = it.value
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-12-2.
|
|
||||||
*/
|
|
||||||
package pl.szczodrzynski.edziennik.config.utils
|
|
||||||
|
|
||||||
import com.google.gson.Gson
|
|
||||||
import com.google.gson.JsonParser
|
|
||||||
import pl.szczodrzynski.edziennik.ext.getInt
|
|
||||||
import pl.szczodrzynski.edziennik.ui.home.HomeCardModel
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
|
||||||
|
|
||||||
class ConfigGsonUtils {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
fun <T> deserializeList(gson: Gson, str: String?, classOfT: Class<T>): List<T> {
|
|
||||||
val json = JsonParser.parseString(str)
|
|
||||||
val list: MutableList<T> = mutableListOf()
|
|
||||||
if (!json.isJsonArray)
|
|
||||||
return list
|
|
||||||
|
|
||||||
json.asJsonArray.forEach { e ->
|
|
||||||
when (classOfT) {
|
|
||||||
String::class.java -> {
|
|
||||||
list += e.asString as T
|
|
||||||
}
|
|
||||||
HomeCardModel::class.java -> {
|
|
||||||
val o = e.asJsonObject
|
|
||||||
list += HomeCardModel(
|
|
||||||
o.getInt("profileId", 0),
|
|
||||||
o.getInt("cardId", 0)
|
|
||||||
) as T
|
|
||||||
}
|
|
||||||
Time::class.java -> {
|
|
||||||
val o = e.asJsonObject
|
|
||||||
list += Time(
|
|
||||||
o.getInt("hour", 0),
|
|
||||||
o.getInt("minute", 0),
|
|
||||||
o.getInt("second", 0)
|
|
||||||
) as T
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,7 +7,6 @@ package pl.szczodrzynski.edziennik.config.utils
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.BuildConfig
|
import pl.szczodrzynski.edziennik.BuildConfig
|
||||||
import pl.szczodrzynski.edziennik.MainActivity
|
|
||||||
import pl.szczodrzynski.edziennik.config.Config
|
import pl.szczodrzynski.edziennik.config.Config
|
||||||
import pl.szczodrzynski.edziennik.ext.HOUR
|
import pl.szczodrzynski.edziennik.ext.HOUR
|
||||||
import pl.szczodrzynski.edziennik.ui.base.enums.NavTarget
|
import pl.szczodrzynski.edziennik.ui.base.enums.NavTarget
|
||||||
@ -25,72 +24,9 @@ class ConfigMigration(app: App, config: Config) {
|
|||||||
AppConfigMigrationV3(p, config)
|
AppConfigMigrationV3(p, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataVersion < 2) {
|
|
||||||
appVersion = BuildConfig.VERSION_CODE
|
|
||||||
loginFinished = false
|
|
||||||
ui.language = null
|
|
||||||
ui.theme = 1
|
|
||||||
ui.appBackground = null
|
|
||||||
ui.headerBackground = null
|
|
||||||
ui.miniMenuVisible = false
|
|
||||||
ui.miniMenuButtons = setOf(
|
|
||||||
NavTarget.HOME,
|
|
||||||
NavTarget.TIMETABLE,
|
|
||||||
NavTarget.AGENDA,
|
|
||||||
NavTarget.GRADES,
|
|
||||||
NavTarget.MESSAGES,
|
|
||||||
NavTarget.HOMEWORK,
|
|
||||||
NavTarget.SETTINGS
|
|
||||||
)
|
|
||||||
sync.enabled = true
|
|
||||||
sync.interval = 1* HOUR.toInt()
|
|
||||||
sync.notifyAboutUpdates = true
|
|
||||||
sync.onlyWifi = false
|
|
||||||
sync.quietHoursEnabled = false
|
|
||||||
sync.quietHoursStart = null
|
|
||||||
sync.quietHoursEnd = null
|
|
||||||
sync.quietDuringLessons = false
|
|
||||||
sync.tokenApp = null
|
|
||||||
sync.tokenMobidziennik = null
|
|
||||||
sync.tokenMobidziennikList = listOf()
|
|
||||||
sync.tokenLibrus = null
|
|
||||||
sync.tokenLibrusList = listOf()
|
|
||||||
sync.tokenVulcan = null
|
|
||||||
sync.tokenVulcanList = listOf()
|
|
||||||
timetable.bellSyncMultiplier = 0
|
|
||||||
timetable.bellSyncDiff = null
|
|
||||||
timetable.countInSeconds = false
|
|
||||||
grades.orderBy = ORDER_BY_DATE_DESC
|
|
||||||
|
|
||||||
dataVersion = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dataVersion < 3) {
|
|
||||||
update = null
|
|
||||||
privacyPolicyAccepted = false
|
|
||||||
devMode = null
|
|
||||||
devModePassword = null
|
|
||||||
appInstalledTime = 0L
|
|
||||||
appRateSnackbarTime = 0L
|
|
||||||
|
|
||||||
dataVersion = 3
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dataVersion < 10) {
|
|
||||||
ui.openDrawerOnBackPressed = false
|
|
||||||
ui.snowfall = false
|
|
||||||
ui.bottomSheetOpened = false
|
|
||||||
sync.dontShowAppManagerDialog = false
|
|
||||||
sync.webPushEnabled = true
|
|
||||||
sync.lastAppSync = 0L
|
|
||||||
|
|
||||||
|
|
||||||
dataVersion = 10
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dataVersion < 11) {
|
if (dataVersion < 11) {
|
||||||
val startMillis = config.values.get("quietHoursStart", 0L)
|
val startMillis = config.values["quietHoursStart"]?.toLongOrNull() ?: 0L
|
||||||
val endMillis = config.values.get("quietHoursEnd", 0L)
|
val endMillis = config.values["quietHoursEnd"]?.toLongOrNull() ?: 0L
|
||||||
if (startMillis > 0) {
|
if (startMillis > 0) {
|
||||||
try {
|
try {
|
||||||
sync.quietHoursStart = Time.fromMillis(abs(startMillis))
|
sync.quietHoursStart = Time.fromMillis(abs(startMillis))
|
||||||
|
@ -7,6 +7,7 @@ package pl.szczodrzynski.edziennik.config.utils
|
|||||||
import pl.szczodrzynski.edziennik.config.ProfileConfig
|
import pl.szczodrzynski.edziennik.config.ProfileConfig
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.AGENDA_DEFAULT
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile.Companion.AGENDA_DEFAULT
|
||||||
import pl.szczodrzynski.edziennik.data.db.enums.NotificationType
|
import pl.szczodrzynski.edziennik.data.db.enums.NotificationType
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.enums.SchoolType
|
||||||
import pl.szczodrzynski.edziennik.ui.home.HomeCard
|
import pl.szczodrzynski.edziennik.ui.home.HomeCard
|
||||||
import pl.szczodrzynski.edziennik.ui.home.HomeCardModel
|
import pl.szczodrzynski.edziennik.ui.home.HomeCardModel
|
||||||
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.COLOR_MODE_WEIGHTED
|
import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.COLOR_MODE_WEIGHTED
|
||||||
@ -15,21 +16,6 @@ import pl.szczodrzynski.edziennik.utils.managers.GradesManager.Companion.YEAR_AL
|
|||||||
class ProfileConfigMigration(config: ProfileConfig) {
|
class ProfileConfigMigration(config: ProfileConfig) {
|
||||||
init { config.apply {
|
init { config.apply {
|
||||||
|
|
||||||
if (dataVersion < 1) {
|
|
||||||
grades.colorMode = COLOR_MODE_WEIGHTED
|
|
||||||
grades.yearAverageMode = YEAR_ALL_GRADES
|
|
||||||
grades.hideImproved = false
|
|
||||||
grades.averageWithoutWeight = true
|
|
||||||
grades.plusValue = null
|
|
||||||
grades.minusValue = null
|
|
||||||
grades.dontCountEnabled = false
|
|
||||||
grades.dontCountGrades = listOf()
|
|
||||||
ui.agendaViewType = AGENDA_DEFAULT
|
|
||||||
// no migration for ui.homeCards
|
|
||||||
|
|
||||||
dataVersion = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dataVersion < 2) {
|
if (dataVersion < 2) {
|
||||||
sync.notificationFilter = sync.notificationFilter + NotificationType.TEACHER_ABSENCE
|
sync.notificationFilter = sync.notificationFilter + NotificationType.TEACHER_ABSENCE
|
||||||
|
|
||||||
@ -38,12 +24,24 @@ class ProfileConfigMigration(config: ProfileConfig) {
|
|||||||
|
|
||||||
if (dataVersion < 3) {
|
if (dataVersion < 3) {
|
||||||
if (ui.homeCards.isNotEmpty()) {
|
if (ui.homeCards.isNotEmpty()) {
|
||||||
ui.homeCards = ui.homeCards.toMutableList().also {
|
ui.homeCards = ui.homeCards + HomeCardModel(
|
||||||
it.add(HomeCardModel(config.profileId, HomeCard.CARD_NOTES))
|
profileId = config.profileId ?: -1,
|
||||||
}
|
cardId = HomeCard.CARD_NOTES,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
dataVersion = 3
|
dataVersion = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dataVersion < 4) {
|
||||||
|
// switch to new event types (USOS)
|
||||||
|
dataVersion = 4
|
||||||
|
|
||||||
|
val profile = db.profileDao().getByIdNow(profileId ?: -1)
|
||||||
|
if (profile?.loginStoreType?.schoolType == SchoolType.UNIVERSITY) {
|
||||||
|
db.eventTypeDao().clear(profileId ?: -1)
|
||||||
|
db.eventTypeDao().addDefaultTypes(profile)
|
||||||
|
}
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
@ -3,15 +3,16 @@
|
|||||||
*/
|
*/
|
||||||
package pl.szczodrzynski.edziennik.data.db.dao
|
package pl.szczodrzynski.edziennik.data.db.dao
|
||||||
|
|
||||||
import android.content.Context
|
import android.graphics.Color
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
import androidx.room.OnConflictStrategy
|
import androidx.room.OnConflictStrategy
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_DEFAULT
|
import pl.szczodrzynski.edziennik.config.AppData
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.EventType
|
import pl.szczodrzynski.edziennik.data.db.entity.EventType
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.EventType.Companion.SOURCE_DEFAULT
|
import pl.szczodrzynski.edziennik.data.db.entity.EventType.Companion.SOURCE_DEFAULT
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
abstract class EventTypeDao {
|
abstract class EventTypeDao {
|
||||||
@ -36,17 +37,17 @@ abstract class EventTypeDao {
|
|||||||
@get:Query("SELECT * FROM eventTypes")
|
@get:Query("SELECT * FROM eventTypes")
|
||||||
abstract val allNow: List<EventType>
|
abstract val allNow: List<EventType>
|
||||||
|
|
||||||
fun addDefaultTypes(context: Context, profileId: Int): List<EventType> {
|
fun addDefaultTypes(profile: Profile): List<EventType> {
|
||||||
|
val data = AppData.get(profile.loginStoreType)
|
||||||
var order = 100
|
var order = 100
|
||||||
val colorMap = EventType.getTypeColorMap()
|
val typeList = data.eventTypes.map {
|
||||||
val typeList = EventType.getTypeNameMap().map { (id, name) ->
|
|
||||||
EventType(
|
EventType(
|
||||||
profileId = profileId,
|
profileId = profile.id,
|
||||||
id = id,
|
id = it.id.toLong(),
|
||||||
name = context.getString(name),
|
name = it.name,
|
||||||
color = colorMap[id] ?: COLOR_DEFAULT,
|
color = Color.parseColor(it.color),
|
||||||
order = order++,
|
order = order++,
|
||||||
source = SOURCE_DEFAULT
|
source = SOURCE_DEFAULT,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
addAll(typeList)
|
addAll(typeList)
|
||||||
|
@ -7,12 +7,13 @@ package pl.szczodrzynski.edziennik.data.db.enums
|
|||||||
enum class LoginType(
|
enum class LoginType(
|
||||||
val id: Int,
|
val id: Int,
|
||||||
val features: Set<FeatureType>,
|
val features: Set<FeatureType>,
|
||||||
|
val schoolType: SchoolType = SchoolType.STANDARD,
|
||||||
) {
|
) {
|
||||||
MOBIDZIENNIK(id = 1, features = FEATURES_MOBIDZIENNIK),
|
MOBIDZIENNIK(id = 1, features = FEATURES_MOBIDZIENNIK),
|
||||||
LIBRUS(id = 2, features = FEATURES_LIBRUS),
|
LIBRUS(id = 2, features = FEATURES_LIBRUS),
|
||||||
VULCAN(id = 4, features = FEATURES_VULCAN),
|
VULCAN(id = 4, features = FEATURES_VULCAN),
|
||||||
PODLASIE(id = 6, features = FEATURES_PODLASIE),
|
PODLASIE(id = 6, features = FEATURES_PODLASIE),
|
||||||
USOS(id = 7, features = FEATURES_USOS),
|
USOS(id = 7, features = FEATURES_USOS, schoolType = SchoolType.UNIVERSITY),
|
||||||
DEMO(id = 20, features = setOf()),
|
DEMO(id = 20, features = setOf()),
|
||||||
TEMPLATE(id = 21, features = setOf()),
|
TEMPLATE(id = 21, features = setOf()),
|
||||||
|
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kuba Szczodrzyński 2022-10-21.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.data.db.enums
|
||||||
|
|
||||||
|
enum class SchoolType {
|
||||||
|
STANDARD,
|
||||||
|
UNIVERSITY,
|
||||||
|
}
|
@ -8,6 +8,8 @@ import android.util.LongSparseArray
|
|||||||
import androidx.core.util.forEach
|
import androidx.core.util.forEach
|
||||||
import com.google.android.material.datepicker.CalendarConstraints
|
import com.google.android.material.datepicker.CalendarConstraints
|
||||||
import com.google.gson.JsonElement
|
import com.google.gson.JsonElement
|
||||||
|
import pl.szczodrzynski.edziennik.App
|
||||||
|
import pl.szczodrzynski.edziennik.config.AppData
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Team
|
import pl.szczodrzynski.edziennik.data.db.entity.Team
|
||||||
@ -48,3 +50,6 @@ fun Profile.getSchoolYearConstrains(): CalendarConstraints {
|
|||||||
|
|
||||||
fun Profile.hasFeature(featureType: FeatureType) = featureType in this.loginStoreType.features
|
fun Profile.hasFeature(featureType: FeatureType) = featureType in this.loginStoreType.features
|
||||||
fun Profile.hasUIFeature(featureType: FeatureType) = featureType.isUIAlwaysAvailable || hasFeature(featureType)
|
fun Profile.hasUIFeature(featureType: FeatureType) = featureType.isUIAlwaysAvailable || hasFeature(featureType)
|
||||||
|
|
||||||
|
fun Profile.getAppData() =
|
||||||
|
if (App.profileId == this.id) App.data else AppData.get(this.loginStoreType)
|
||||||
|
@ -46,6 +46,7 @@ inline fun <reified E : Enum<E>> JsonObject?.getEnum(key: String) = this?.getInt
|
|||||||
fun JsonObject.putEnum(key: String, value: Enum<*>) = addProperty(key, value.toInt())
|
fun JsonObject.putEnum(key: String, value: Enum<*>) = addProperty(key, value.toInt())
|
||||||
|
|
||||||
fun String.toJsonObject(): JsonObject? = try { JsonParser.parseString(this).asJsonObject } catch (ignore: Exception) { null }
|
fun String.toJsonObject(): JsonObject? = try { JsonParser.parseString(this).asJsonObject } catch (ignore: Exception) { null }
|
||||||
|
fun String.toJsonArray(): JsonArray? = try { JsonParser.parseString(this).asJsonArray } catch (ignore: Exception) { null }
|
||||||
|
|
||||||
operator fun JsonObject.set(key: String, value: JsonElement) = this.add(key, value)
|
operator fun JsonObject.set(key: String, value: JsonElement) = this.add(key, value)
|
||||||
operator fun JsonObject.set(key: String, value: Boolean) = this.addProperty(key, value)
|
operator fun JsonObject.set(key: String, value: Boolean) = this.addProperty(key, value)
|
||||||
@ -86,7 +87,9 @@ fun JsonObject.toBundle(): Bundle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun JsonArray(vararg properties: Any?): JsonArray {
|
fun JsonArray(vararg properties: Any?) = JsonArray(properties.toList())
|
||||||
|
|
||||||
|
fun JsonArray(properties: Collection<Any?>): JsonArray {
|
||||||
return JsonArray().apply {
|
return JsonArray().apply {
|
||||||
for (property in properties) {
|
for (property in properties) {
|
||||||
when (property) {
|
when (property) {
|
||||||
@ -112,3 +115,20 @@ operator fun JsonArray.plusAssign(o: String) = this.add(o)
|
|||||||
operator fun JsonArray.plusAssign(o: Char) = this.add(o)
|
operator fun JsonArray.plusAssign(o: Char) = this.add(o)
|
||||||
operator fun JsonArray.plusAssign(o: Number) = this.add(o)
|
operator fun JsonArray.plusAssign(o: Number) = this.add(o)
|
||||||
operator fun JsonArray.plusAssign(o: Boolean) = this.add(o)
|
operator fun JsonArray.plusAssign(o: Boolean) = this.add(o)
|
||||||
|
|
||||||
|
fun JsonObject.mergeWith(other: JsonObject): JsonObject {
|
||||||
|
for ((key, value) in other.entrySet()) {
|
||||||
|
when (value) {
|
||||||
|
is JsonObject -> when {
|
||||||
|
this.has(key) -> this.getJsonObject(key)?.mergeWith(value)
|
||||||
|
else -> this.add(key, value)
|
||||||
|
}
|
||||||
|
is JsonArray -> when {
|
||||||
|
this.has(key) -> this.getJsonArray(key)?.addAll(value)
|
||||||
|
else -> this.add(key, value)
|
||||||
|
}
|
||||||
|
else -> this.add(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
@ -72,3 +72,8 @@ fun pendingIntentFlag(): Int {
|
|||||||
return PendingIntent.FLAG_IMMUTABLE
|
return PendingIntent.FLAG_IMMUTABLE
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Int?.takeValue() = if (this == -1) null else this
|
||||||
|
fun Int?.takePositive() = if (this == -1 || this == 0) null else this
|
||||||
|
|
||||||
|
fun Any?.ignore() = Unit
|
||||||
|
@ -22,7 +22,6 @@ import pl.szczodrzynski.edziennik.App
|
|||||||
import pl.szczodrzynski.edziennik.MainActivity
|
import pl.szczodrzynski.edziennik.MainActivity
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.EventType
|
import pl.szczodrzynski.edziennik.data.db.entity.EventType
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||||
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
|
import pl.szczodrzynski.edziennik.data.db.enums.MetadataType
|
||||||
import pl.szczodrzynski.edziennik.databinding.FragmentAgendaCalendarBinding
|
import pl.szczodrzynski.edziennik.databinding.FragmentAgendaCalendarBinding
|
||||||
@ -33,7 +32,6 @@ import pl.szczodrzynski.edziennik.utils.Themes
|
|||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem
|
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem
|
||||||
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem
|
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem
|
||||||
import java.util.*
|
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
class AgendaFragment : Fragment(), CoroutineScope {
|
class AgendaFragment : Fragment(), CoroutineScope {
|
||||||
@ -144,7 +142,7 @@ class AgendaFragment : Fragment(), CoroutineScope {
|
|||||||
}
|
}
|
||||||
val defaultEventTypes = EventType.getTypeColorMap().keys
|
val defaultEventTypes = EventType.getTypeColorMap().keys
|
||||||
if (!eventTypes.containsAll(defaultEventTypes)) {
|
if (!eventTypes.containsAll(defaultEventTypes)) {
|
||||||
app.db.eventTypeDao().addDefaultTypes(activity, app.profileId)
|
app.db.eventTypeDao().addDefaultTypes(app.profile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ public class AnnouncementsFragment extends Fragment {
|
|||||||
if (app.getProfile().getLoginStoreType() == LoginType.LIBRUS) {
|
if (app.getProfile().getLoginStoreType() == LoginType.LIBRUS) {
|
||||||
EdziennikTask.Companion.announcementsRead(App.Companion.getProfileId()).enqueue(requireContext());
|
EdziennikTask.Companion.announcementsRead(App.Companion.getProfileId()).enqueue(requireContext());
|
||||||
} else {
|
} else {
|
||||||
AsyncTask.execute(() -> App.db.metadataDao().setAllSeen(App.Companion.getProfileId(), MetadataType.ANNOUNCEMENT, true));
|
AsyncTask.execute(() -> App.Companion.getDb().metadataDao().setAllSeen(App.Companion.getProfileId(), MetadataType.ANNOUNCEMENT, true));
|
||||||
Toast.makeText(activity, R.string.main_menu_mark_as_read_success, Toast.LENGTH_SHORT).show();
|
Toast.makeText(activity, R.string.main_menu_mark_as_read_success, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -103,7 +103,7 @@ public class AnnouncementsFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.db.announcementDao().getAll(App.Companion.getProfileId()).observe(getViewLifecycleOwner(), announcements -> {
|
app.getDb().announcementDao().getAll(App.Companion.getProfileId()).observe(getViewLifecycleOwner(), announcements -> {
|
||||||
if (app == null || activity == null || b == null || !isAdded())
|
if (app == null || activity == null || b == null || !isAdded())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ public class AnnouncementsFragment extends Fragment {
|
|||||||
b.text.setText(announcement.getTeacherName() +"\n\n"+ (announcement.getStartDate() != null ? announcement.getStartDate().getFormattedString() : "-") + (announcement.getEndDate() != null ? " do " + announcement.getEndDate().getFormattedString() : "")+"\n\n" +announcement.getText());
|
b.text.setText(announcement.getTeacherName() +"\n\n"+ (announcement.getStartDate() != null ? announcement.getStartDate().getFormattedString() : "-") + (announcement.getEndDate() != null ? " do " + announcement.getEndDate().getFormattedString() : "")+"\n\n" +announcement.getText());
|
||||||
if (!announcement.getSeen() && app.getProfile().getLoginStoreType() != LoginType.LIBRUS) {
|
if (!announcement.getSeen() && app.getProfile().getLoginStoreType() != LoginType.LIBRUS) {
|
||||||
announcement.setSeen(true);
|
announcement.setSeen(true);
|
||||||
AsyncTask.execute(() -> App.db.metadataDao().setSeen(App.Companion.getProfileId(), announcement, true));
|
AsyncTask.execute(() -> App.Companion.getDb().metadataDao().setSeen(App.Companion.getProfileId(), announcement, true));
|
||||||
if (recyclerView.getAdapter() != null)
|
if (recyclerView.getAdapter() != null)
|
||||||
recyclerView.getAdapter().notifyDataSetChanged();
|
recyclerView.getAdapter().notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ public class BehaviourFragment extends Fragment {
|
|||||||
.withIcon(CommunityMaterial.Icon.cmd_eye_check_outline)
|
.withIcon(CommunityMaterial.Icon.cmd_eye_check_outline)
|
||||||
.withOnClickListener(v3 -> {
|
.withOnClickListener(v3 -> {
|
||||||
activity.getBottomSheet().close();
|
activity.getBottomSheet().close();
|
||||||
AsyncTask.execute(() -> App.db.metadataDao().setAllSeen(App.Companion.getProfileId(), MetadataType.NOTICE, true));
|
AsyncTask.execute(() -> App.Companion.getDb().metadataDao().setAllSeen(App.Companion.getProfileId(), MetadataType.NOTICE, true));
|
||||||
Toast.makeText(activity, R.string.main_menu_mark_as_read_success, Toast.LENGTH_SHORT).show();
|
Toast.makeText(activity, R.string.main_menu_mark_as_read_success, Toast.LENGTH_SHORT).show();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@ -111,7 +111,7 @@ public class BehaviourFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.db.noticeDao().getAll(App.Companion.getProfileId()).observe(getViewLifecycleOwner(), notices -> {
|
app.getDb().noticeDao().getAll(App.Companion.getProfileId()).observe(getViewLifecycleOwner(), notices -> {
|
||||||
if (app == null || activity == null || b == null || !isAdded())
|
if (app == null || activity == null || b == null || !isAdded())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -19,7 +19,6 @@ import eu.szkolny.font.SzkolnyFont
|
|||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Notice
|
import pl.szczodrzynski.edziennik.data.db.entity.Notice
|
||||||
import pl.szczodrzynski.edziennik.data.db.enums.LoginType
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.NoticeFull
|
import pl.szczodrzynski.edziennik.data.db.full.NoticeFull
|
||||||
import pl.szczodrzynski.edziennik.utils.BetterLink
|
import pl.szczodrzynski.edziennik.utils.BetterLink
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.bs
|
import pl.szczodrzynski.edziennik.utils.Utils.bs
|
||||||
@ -40,7 +39,7 @@ class NoticesAdapter//getting the context and product list with constructor
|
|||||||
|
|
||||||
val notice = noticeList[position]
|
val notice = noticeList[position]
|
||||||
|
|
||||||
if (app.profile.loginStoreType == LoginType.MOBIDZIENNIK && false) {
|
if (app.data.uiConfig.enableNoticePoints && false) {
|
||||||
holder.noticesItemReason.text = bs(null, notice.category, "\n") + notice.text
|
holder.noticesItemReason.text = bs(null, notice.category, "\n") + notice.text
|
||||||
holder.noticesItemTeacherName.text = app.getString(R.string.notices_points_format, notice.teacherName, if (notice.points ?: 0f > 0) "+" + notice.points else notice.points)
|
holder.noticesItemTeacherName.text = app.getString(R.string.notices_points_format, notice.teacherName, if (notice.points ?: 0f > 0) "+" + notice.points else notice.points)
|
||||||
} else {
|
} else {
|
||||||
|
@ -26,7 +26,6 @@ import pl.szczodrzynski.edziennik.BuildConfig
|
|||||||
import pl.szczodrzynski.edziennik.MainActivity
|
import pl.szczodrzynski.edziennik.MainActivity
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.data.db.enums.FeatureType
|
import pl.szczodrzynski.edziennik.data.db.enums.FeatureType
|
||||||
import pl.szczodrzynski.edziennik.data.db.enums.LoginType
|
|
||||||
import pl.szczodrzynski.edziennik.databinding.FragmentHomeBinding
|
import pl.szczodrzynski.edziennik.databinding.FragmentHomeBinding
|
||||||
import pl.szczodrzynski.edziennik.ext.hasUIFeature
|
import pl.szczodrzynski.edziennik.ext.hasUIFeature
|
||||||
import pl.szczodrzynski.edziennik.ext.onClick
|
import pl.szczodrzynski.edziennik.ext.onClick
|
||||||
@ -127,7 +126,7 @@ class HomeFragment : Fragment(), CoroutineScope {
|
|||||||
.withOnClickListener(OnClickListener {
|
.withOnClickListener(OnClickListener {
|
||||||
activity.bottomSheet.close()
|
activity.bottomSheet.close()
|
||||||
launch { withContext(Dispatchers.Default) {
|
launch { withContext(Dispatchers.Default) {
|
||||||
if (app.profile.loginStoreType != LoginType.LIBRUS) {
|
if (!app.data.uiConfig.enableMarkAsReadAnnouncements) {
|
||||||
app.db.metadataDao().setAllSeenExceptMessagesAndAnnouncements(App.profileId, true)
|
app.db.metadataDao().setAllSeenExceptMessagesAndAnnouncements(App.profileId, true)
|
||||||
} else {
|
} else {
|
||||||
app.db.metadataDao().setAllSeenExceptMessages(App.profileId, true)
|
app.db.metadataDao().setAllSeenExceptMessages(App.profileId, true)
|
||||||
|
@ -11,14 +11,13 @@ import android.view.ViewGroup
|
|||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import androidx.navigation.Navigation
|
import androidx.navigation.Navigation
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.greenrobot.eventbus.Subscribe
|
import org.greenrobot.eventbus.Subscribe
|
||||||
import org.greenrobot.eventbus.ThreadMode
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
|
import pl.szczodrzynski.edziennik.config.AppData
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskAllFinishedEvent
|
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskAllFinishedEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent
|
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent
|
||||||
@ -29,6 +28,7 @@ import pl.szczodrzynski.edziennik.databinding.LoginSyncFragmentBinding
|
|||||||
import pl.szczodrzynski.edziennik.ext.Bundle
|
import pl.szczodrzynski.edziennik.ext.Bundle
|
||||||
import pl.szczodrzynski.edziennik.ext.asBoldSpannable
|
import pl.szczodrzynski.edziennik.ext.asBoldSpannable
|
||||||
import pl.szczodrzynski.edziennik.ext.concat
|
import pl.szczodrzynski.edziennik.ext.concat
|
||||||
|
import pl.szczodrzynski.edziennik.ext.ignore
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ class LoginSyncFragment : Fragment(), CoroutineScope {
|
|||||||
return b.root
|
return b.root
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) = launch {
|
||||||
|
|
||||||
EventBus.getDefault().removeStickyEvent(ApiTaskAllFinishedEvent::class.java)
|
EventBus.getDefault().removeStickyEvent(ApiTaskAllFinishedEvent::class.java)
|
||||||
EventBus.getDefault().removeStickyEvent(ApiTaskErrorEvent::class.java)
|
EventBus.getDefault().removeStickyEvent(ApiTaskErrorEvent::class.java)
|
||||||
@ -64,6 +64,7 @@ class LoginSyncFragment : Fragment(), CoroutineScope {
|
|||||||
val profiles = activity.profiles.filter { it.isSelected }.map { it.profile }
|
val profiles = activity.profiles.filter { it.isSelected }.map { it.profile }
|
||||||
val loginStores = activity.loginStores.filter { store -> profiles.any { it.loginStoreId == store.id } }
|
val loginStores = activity.loginStores.filter { store -> profiles.any { it.loginStoreId == store.id } }
|
||||||
|
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
val registrationAllowed = arguments?.getBoolean("registrationAllowed") ?: false
|
val registrationAllowed = arguments?.getBoolean("registrationAllowed") ?: false
|
||||||
profiles.forEach {
|
profiles.forEach {
|
||||||
it.registration = if (registrationAllowed)
|
it.registration = if (registrationAllowed)
|
||||||
@ -71,11 +72,18 @@ class LoginSyncFragment : Fragment(), CoroutineScope {
|
|||||||
else
|
else
|
||||||
Profile.REGISTRATION_DISABLED
|
Profile.REGISTRATION_DISABLED
|
||||||
|
|
||||||
app.db.eventTypeDao().addDefaultTypes(activity, it.id)
|
val data = AppData.get(it.loginStoreType)
|
||||||
|
val config = app.config.getFor(it.id)
|
||||||
|
for ((key, value) in data.configOverrides) {
|
||||||
|
config.set(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
app.db.eventTypeDao().addDefaultTypes(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
app.db.profileDao().addAll(profiles)
|
app.db.profileDao().addAll(profiles)
|
||||||
app.db.loginStoreDao().addAll(loginStores)
|
app.db.loginStoreDao().addAll(loginStores)
|
||||||
|
}
|
||||||
|
|
||||||
finishArguments = Bundle(
|
finishArguments = Bundle(
|
||||||
"firstProfileId" to profiles.firstOrNull()?.id
|
"firstProfileId" to profiles.firstOrNull()?.id
|
||||||
@ -83,7 +91,7 @@ class LoginSyncFragment : Fragment(), CoroutineScope {
|
|||||||
|
|
||||||
val profileIds = profiles.map { it.id }.toSet()
|
val profileIds = profiles.map { it.id }.toSet()
|
||||||
EdziennikTask.syncProfileList(profileIds).enqueue(activity)
|
EdziennikTask.syncProfileList(profileIds).enqueue(activity)
|
||||||
}
|
}.ignore()
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
fun onSyncStartedEvent(event: ApiTaskStartedEvent) {
|
fun onSyncStartedEvent(event: ApiTaskStartedEvent) {
|
||||||
|
@ -30,7 +30,6 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
|||||||
import pl.szczodrzynski.edziennik.data.api.events.MessageSentEvent
|
import pl.szczodrzynski.edziennik.data.api.events.MessageSentEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.RecipientListGetEvent
|
import pl.szczodrzynski.edziennik.data.api.events.RecipientListGetEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||||
import pl.szczodrzynski.edziennik.data.db.enums.LoginType
|
import pl.szczodrzynski.edziennik.data.db.enums.LoginType
|
||||||
@ -76,8 +75,6 @@ class MessagesComposeFragment : Fragment(), CoroutineScope {
|
|||||||
|
|
||||||
private lateinit var stylingConfig: StylingConfig
|
private lateinit var stylingConfig: StylingConfig
|
||||||
private lateinit var uiConfig: UIConfig
|
private lateinit var uiConfig: UIConfig
|
||||||
private val enableTextStyling
|
|
||||||
get() = app.profile.loginStoreType != LoginType.LIBRUS
|
|
||||||
private var changedRecipients = false
|
private var changedRecipients = false
|
||||||
private var changedSubject = false
|
private var changedSubject = false
|
||||||
private var changedBody = false
|
private var changedBody = false
|
||||||
@ -154,14 +151,14 @@ class MessagesComposeFragment : Fragment(), CoroutineScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getMessageBody(): String {
|
private fun getMessageBody(): String {
|
||||||
return if (enableTextStyling)
|
return if (app.data.messagesConfig.textStyling)
|
||||||
textStylingManager.getHtmlText(stylingConfig)
|
textStylingManager.getHtmlText(stylingConfig)
|
||||||
else
|
else
|
||||||
b.text.text?.toString() ?: ""
|
b.text.text?.toString() ?: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getRecipientList() {
|
private fun getRecipientList() {
|
||||||
if (System.currentTimeMillis() - app.profile.lastReceiversSync > 1 * DAY * 1000 && app.profile.loginStoreType != LoginType.VULCAN) {
|
if (app.data.messagesConfig.syncRecipientList && System.currentTimeMillis() - app.profile.lastReceiversSync > 1 * DAY * 1000) {
|
||||||
activity.snackbar("Pobieranie listy odbiorców...")
|
activity.snackbar("Pobieranie listy odbiorców...")
|
||||||
EdziennikTask.recipientListGet(App.profileId).enqueue(activity)
|
EdziennikTask.recipientListGet(App.profileId).enqueue(activity)
|
||||||
}
|
}
|
||||||
@ -262,8 +259,8 @@ class MessagesComposeFragment : Fragment(), CoroutineScope {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
b.fontStyle.root.isVisible = enableTextStyling
|
b.fontStyle.root.isVisible = app.data.messagesConfig.textStyling
|
||||||
if (enableTextStyling) {
|
if (app.data.messagesConfig.textStyling) {
|
||||||
textStylingManager.attach(stylingConfig)
|
textStylingManager.attach(stylingConfig)
|
||||||
b.fontStyle.styles.addOnButtonCheckedListener { _, _, _ ->
|
b.fontStyle.styles.addOnButtonCheckedListener { _, _, _ ->
|
||||||
changedBody = true
|
changedBody = true
|
||||||
@ -374,7 +371,7 @@ class MessagesComposeFragment : Fragment(), CoroutineScope {
|
|||||||
else -> b.text.requestFocus()
|
else -> b.text.requestFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!enableTextStyling)
|
if (!app.data.messagesConfig.textStyling)
|
||||||
b.text.setText(b.text.text?.toString())
|
b.text.setText(b.text.text?.toString())
|
||||||
b.text.setSelection(0)
|
b.text.setSelection(0)
|
||||||
(b.root as? ScrollView)?.smoothScrollTo(0, 0)
|
(b.root as? ScrollView)?.smoothScrollTo(0, 0)
|
||||||
|
@ -188,7 +188,7 @@ class MessageFragment : Fragment(), CoroutineScope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (app.profile.loginStoreType == LoginType.VULCAN) {
|
if (app.data.messagesConfig.needsReadStatus) {
|
||||||
// vulcan: change message status or download attachments
|
// vulcan: change message status or download attachments
|
||||||
if ((message.isReceived || message.isDeleted) && !message.seen || message.attachmentIds == null) {
|
if ((message.isReceived || message.isDeleted) && !message.seen || message.attachmentIds == null) {
|
||||||
EdziennikTask.messageGet(App.profileId, message).enqueue(activity)
|
EdziennikTask.messageGet(App.profileId, message).enqueue(activity)
|
||||||
|
@ -83,7 +83,7 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope {
|
|||||||
startHour = startHour,
|
startHour = startHour,
|
||||||
endHour = endHour,
|
endHour = endHour,
|
||||||
dividerHeight = 1.dp,
|
dividerHeight = 1.dp,
|
||||||
halfHourHeight = if (app.profile.loginStoreType == LoginType.USOS) 45.dp else 60.dp,
|
halfHourHeight = app.data.uiConfig.lessonHeight.dp,
|
||||||
hourDividerColor = R.attr.hourDividerColor.resolveAttr(context),
|
hourDividerColor = R.attr.hourDividerColor.resolveAttr(context),
|
||||||
halfHourDividerColor = R.attr.halfHourDividerColor.resolveAttr(context),
|
halfHourDividerColor = R.attr.halfHourDividerColor.resolveAttr(context),
|
||||||
hourLabelWidth = 40.dp,
|
hourLabelWidth = 40.dp,
|
||||||
|
@ -37,7 +37,8 @@ class EventTypeDropdown : TextInputDropDown {
|
|||||||
var types = db.eventTypeDao().getAllNow(profileId)
|
var types = db.eventTypeDao().getAllNow(profileId)
|
||||||
|
|
||||||
if (types.none { it.id in -1L..10L }) {
|
if (types.none { it.id in -1L..10L }) {
|
||||||
types = db.eventTypeDao().addDefaultTypes(context, profileId)
|
val profile = db.profileDao().getByIdNow(profileId) ?: return@withContext listOf()
|
||||||
|
types = db.eventTypeDao().addDefaultTypes(profile)
|
||||||
}
|
}
|
||||||
|
|
||||||
list += types.map {
|
list += types.map {
|
||||||
|
@ -85,7 +85,7 @@ public class WidgetConfigActivity extends Activity {
|
|||||||
opacity = 0.8f;
|
opacity = 0.8f;
|
||||||
|
|
||||||
AsyncTask.execute(() -> {
|
AsyncTask.execute(() -> {
|
||||||
profileList = App.db.profileDao().getAllNow();
|
profileList = App.Companion.getDb().profileDao().getAllNow();
|
||||||
profileList = filterOutArchived(profileList);
|
profileList = filterOutArchived(profileList);
|
||||||
|
|
||||||
if (widgetType == WIDGET_NOTIFICATIONS)
|
if (widgetType == WIDGET_NOTIFICATIONS)
|
||||||
|
@ -25,7 +25,9 @@ import com.mikepenz.iconics.IconicsDrawable
|
|||||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||||
import com.mikepenz.iconics.utils.colorInt
|
import com.mikepenz.iconics.utils.colorInt
|
||||||
import com.mikepenz.iconics.utils.sizeDp
|
import com.mikepenz.iconics.utils.sizeDp
|
||||||
import pl.szczodrzynski.edziennik.*
|
import pl.szczodrzynski.edziennik.App
|
||||||
|
import pl.szczodrzynski.edziennik.MainActivity
|
||||||
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
|
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Lesson.Companion.TYPE_NO_LESSONS
|
import pl.szczodrzynski.edziennik.data.db.entity.Lesson.Companion.TYPE_NO_LESSONS
|
||||||
@ -393,7 +395,7 @@ class WidgetTimetableProvider : AppWidgetProvider() {
|
|||||||
headerIntent.putExtra("profileId", it)
|
headerIntent.putExtra("profileId", it)
|
||||||
}
|
}
|
||||||
displayingDate?.let {
|
displayingDate?.let {
|
||||||
headerIntent.putExtra("timetableDate", it.value)
|
headerIntent.putExtra("timetableDate", it.stringY_m_d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
headerIntent.putExtras("fragmentId" to NavTarget.TIMETABLE)
|
headerIntent.putExtras("fragmentId" to NavTarget.TIMETABLE)
|
||||||
|
176
app/src/main/res/raw/app_data.json
Normal file
176
app/src/main/res/raw/app_data.json
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
{
|
||||||
|
"base": {
|
||||||
|
"messagesConfig": {
|
||||||
|
"subjectLength": null,
|
||||||
|
"bodyLength": null,
|
||||||
|
"textStyling": true,
|
||||||
|
"syncRecipientList": true,
|
||||||
|
"htmlMode": "ORIGINAL",
|
||||||
|
"needsReadStatus": false
|
||||||
|
},
|
||||||
|
"uiConfig": {
|
||||||
|
"lessonHeight": 60,
|
||||||
|
"enableMarkAsReadAnnouncements": true,
|
||||||
|
"enableNoticePoints": false
|
||||||
|
},
|
||||||
|
"eventTypes": [
|
||||||
|
{
|
||||||
|
"id": -5,
|
||||||
|
"color": "#f57f17",
|
||||||
|
"name": "lekcja online"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": -1,
|
||||||
|
"color": "#795548",
|
||||||
|
"name": "zadanie domowe"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"color": "#ffc107",
|
||||||
|
"name": "inny"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"standard": {
|
||||||
|
"eventTypes": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"color": "#f44336",
|
||||||
|
"name": "sprawdzian"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"color": "#76ff03",
|
||||||
|
"name": "kartkówka"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"color": "#4050b5",
|
||||||
|
"name": "wypracowanie"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"color": "#673ab7",
|
||||||
|
"name": "projekt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"color": "#90caf9",
|
||||||
|
"name": "zebranie z rodzicami"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"color": "#4caf50",
|
||||||
|
"name": "wycieczka"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"color": "#ffeb3b",
|
||||||
|
"name": "lektura"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"color": "#388e3c",
|
||||||
|
"name": "wydarzenie klasowe"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"color": "#039be5",
|
||||||
|
"name": "informacja"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"university": {
|
||||||
|
"configOverrides": {
|
||||||
|
"timetableColorSubjectName": true
|
||||||
|
},
|
||||||
|
"uiConfig": {
|
||||||
|
"lessonHeight": 45
|
||||||
|
},
|
||||||
|
"eventTypes": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"color": "#f44336",
|
||||||
|
"name": "egzamin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"color": "#e91e63",
|
||||||
|
"name": "kolokwium"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"color": "#76ff03",
|
||||||
|
"name": "kartkówka"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"color": "#ffeb3b",
|
||||||
|
"name": "wejściówka"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"color": "#90caf9",
|
||||||
|
"name": "zaliczenie"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"color": "#4050b5",
|
||||||
|
"name": "zadanie"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"color": "#673ab7",
|
||||||
|
"name": "projekt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"color": "#388e3c",
|
||||||
|
"name": "zajęcia"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"color": "#4caf50",
|
||||||
|
"name": "zajęcia dodatkowe"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10,
|
||||||
|
"color": "#039be5",
|
||||||
|
"name": "informacja"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"mobidziennik": {
|
||||||
|
"messagesConfig": {
|
||||||
|
"subjectLength": 100,
|
||||||
|
"htmlMode": "COMPATIBLE"
|
||||||
|
},
|
||||||
|
"uiConfig": {
|
||||||
|
"enableNoticePoints": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"librus": {
|
||||||
|
"messagesConfig": {
|
||||||
|
"subjectLength": 150,
|
||||||
|
"bodyLength": 20000,
|
||||||
|
"textStyling": false
|
||||||
|
},
|
||||||
|
"uiConfig": {
|
||||||
|
"enableMarkAsReadAnnouncements": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"vulcan": {
|
||||||
|
"messagesConfig": {
|
||||||
|
"subjectLength": 200,
|
||||||
|
"syncRecipientList": false,
|
||||||
|
"needsReadStatus": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idziennik": {
|
||||||
|
"messagesConfig": {
|
||||||
|
"subjectLength": 180,
|
||||||
|
"bodyLength": 1983,
|
||||||
|
"textStyling": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1548,4 +1548,5 @@
|
|||||||
<string name="login_mode_usos_oauth_guide">TODO</string>
|
<string name="login_mode_usos_oauth_guide">TODO</string>
|
||||||
<string name="notification_user_action_required_oauth_usos">USOS - wymagane logowanie z użyciem przeglądarki</string>
|
<string name="notification_user_action_required_oauth_usos">USOS - wymagane logowanie z użyciem przeglądarki</string>
|
||||||
<string name="oauth_dialog_title">Zaloguj się</string>
|
<string name="oauth_dialog_title">Zaloguj się</string>
|
||||||
|
<string name="app_cannot_load_data">Nie można załadować danych aplikacji</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user