) {
+ Bundle().apply {
+ params.forEach { (key, value) ->
+ if (value == null) return@forEach
+ when (value) {
+ is String -> putString(key, value)
+ is Int -> putInt(key, value)
+ is Boolean -> putBoolean(key, value)
+ }
+ }
+ analytics.onEvent(name, this)
+ }
+ }
+
+ fun setCurrentScreen(activity: Activity, name: String?) {
+ analytics.pageStart(name, activity::class.simpleName)
+ }
+
+ fun popCurrentScreen(name: String?) {
+ analytics.pageEnd(name)
+ }
+}
diff --git a/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt b/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt
new file mode 100644
index 00000000..2b1f1d30
--- /dev/null
+++ b/app/src/hms/java/io/github/wulkanowy/utils/CrashLogUtils.kt
@@ -0,0 +1,32 @@
+package io.github.wulkanowy.utils
+
+import android.util.Log
+import com.huawei.agconnect.crash.AGConnectCrash
+import fr.bipi.treessence.base.FormatterPriorityTree
+import fr.bipi.treessence.common.StackTraceRecorder
+
+class CrashLogTree : FormatterPriorityTree(Log.VERBOSE) {
+
+ private val connectCrash by lazy { AGConnectCrash.getInstance() }
+
+ override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
+ if (skipLog(priority, tag, message, t)) return
+
+ connectCrash.log(format(priority, tag, message))
+ }
+}
+
+class CrashLogExceptionTree : FormatterPriorityTree(Log.ERROR, ExceptionFilter) {
+
+ private val connectCrash by lazy { AGConnectCrash.getInstance() }
+
+ override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
+ if (skipLog(priority, tag, message, t)) return
+
+ if (t != null) {
+ connectCrash.recordException(t)
+ } else {
+ connectCrash.recordException(StackTraceRecorder(format(priority, tag, message)))
+ }
+ }
+}
diff --git a/app/src/hms/java/io/github/wulkanowy/utils/InAppReviewHelper.kt b/app/src/hms/java/io/github/wulkanowy/utils/InAppReviewHelper.kt
new file mode 100644
index 00000000..adb162fd
--- /dev/null
+++ b/app/src/hms/java/io/github/wulkanowy/utils/InAppReviewHelper.kt
@@ -0,0 +1,18 @@
+package io.github.wulkanowy.utils
+
+import android.content.Context
+import dagger.hilt.android.qualifiers.ApplicationContext
+import io.github.wulkanowy.ui.modules.main.MainActivity
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+@Suppress("UNUSED_PARAMETER", "unused")
+class InAppReviewHelper @Inject constructor(
+ @ApplicationContext private val context: Context
+) {
+
+ fun showInAppReview(activity: MainActivity) {
+ // do nothing
+ }
+}
diff --git a/app/src/hms/java/io/github/wulkanowy/utils/InAppUpdateHelper.kt b/app/src/hms/java/io/github/wulkanowy/utils/InAppUpdateHelper.kt
new file mode 100644
index 00000000..51b22ec7
--- /dev/null
+++ b/app/src/hms/java/io/github/wulkanowy/utils/InAppUpdateHelper.kt
@@ -0,0 +1,13 @@
+package io.github.wulkanowy.utils
+
+import android.view.View
+import javax.inject.Inject
+
+class InAppUpdateHelper @Inject constructor() {
+
+ lateinit var messageContainer: View
+
+ fun checkAndInstallUpdates() {}
+
+ fun onResume() {}
+}
diff --git a/app/src/hms/java/io/github/wulkanowy/utils/IntegrityHelper.kt b/app/src/hms/java/io/github/wulkanowy/utils/IntegrityHelper.kt
new file mode 100644
index 00000000..7af68058
--- /dev/null
+++ b/app/src/hms/java/io/github/wulkanowy/utils/IntegrityHelper.kt
@@ -0,0 +1,11 @@
+package io.github.wulkanowy.utils
+
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class IntegrityHelper @Inject constructor() {
+
+ @Suppress("UNUSED_PARAMETER")
+ fun getIntegrityToken(requestId: String): String? = null
+}
diff --git a/app/src/hms/java/io/github/wulkanowy/utils/RemoteConfigHelper.kt b/app/src/hms/java/io/github/wulkanowy/utils/RemoteConfigHelper.kt
new file mode 100644
index 00000000..88f2598f
--- /dev/null
+++ b/app/src/hms/java/io/github/wulkanowy/utils/RemoteConfigHelper.kt
@@ -0,0 +1,7 @@
+package io.github.wulkanowy.utils
+
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class RemoteConfigHelper @Inject constructor() : BaseRemoteConfigHelper()
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 42c75475..79d75bc0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,29 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ android:resizeableActivity="true"
+ tools:ignore="DataExtractionRules,UnusedAttribute">
+ tools:ignore="DiscouragedApi,LockedOrientationActivity">
@@ -33,13 +61,14 @@
android:name=".ui.modules.login.LoginActivity"
android:configChanges="orientation|screenSize"
android:label="@string/login_title"
- android:theme="@style/WulkanowyTheme.NoActionBar"
+ android:theme="@style/WulkanowyTheme.Login"
android:windowSoftInputMode="adjustResize" />
+ android:theme="@style/WulkanowyTheme.NoActionBar"
+ android:windowSoftInputMode="adjustPan" />
@@ -58,6 +88,7 @@
@@ -68,6 +99,22 @@
+
+
+
+
+
+
+
+
+
+
@@ -91,12 +139,12 @@
android:resource="@xml/provider_widget_lucky_number" />
-
+
+
-
-
+ android:name="install_channel"
+ android:value="${install_channel}" />
-
+ android:resource="@drawable/ic_stat_all" />
+
+
diff --git a/app/src/main/assets/contributors.json b/app/src/main/assets/contributors.json
index 40aff4c4..97ac9356 100644
--- a/app/src/main/assets/contributors.json
+++ b/app/src/main/assets/contributors.json
@@ -33,6 +33,30 @@
},
{
"displayName": "Mateusz Idziejczak",
- "githubUsername": "PanTajemnic"
+ "githubUsername": "Luncenok"
+ },
+ {
+ "displayName": "Daniel Olczyk",
+ "githubUsername": "MRmlik12"
+ },
+ {
+ "displayName": "Damian Czupryn",
+ "githubUsername": "Daxxxis"
+ },
+ {
+ "displayName": "Kamil Studziński",
+ "githubUsername": "studzinskik"
+ },
+ {
+ "displayName": "Tomasz F.",
+ "githubUsername": "Pengwius"
+ },
+ {
+ "displayName": "Antoni Paduch",
+ "githubUsername": "janAte1"
+ },
+ {
+ "displayName": "Kamil Wąsik",
+ "githubUsername": "JestemKamil"
}
]
diff --git a/app/src/main/assets/message-print-page.html b/app/src/main/assets/message-print-page.html
new file mode 100644
index 00000000..8da7dec6
--- /dev/null
+++ b/app/src/main/assets/message-print-page.html
@@ -0,0 +1,94 @@
+
+
+
+
+ %SUBJECT% | Wulkanowy
+
+
+
+%SUBJECT%
+
+
+ %INFO%
+
+
+
+
+
Treść wiadomości
+ %CONTENT%
+
+
+
diff --git a/app/src/main/assets/wulkanowy-logo-black.svg b/app/src/main/assets/wulkanowy-logo-black.svg
new file mode 100644
index 00000000..9bfbe2c0
--- /dev/null
+++ b/app/src/main/assets/wulkanowy-logo-black.svg
@@ -0,0 +1,74 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt b/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt
index 96ec7cb8..38fade0a 100644
--- a/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt
+++ b/app/src/main/java/io/github/wulkanowy/WulkanowyApp.kt
@@ -1,37 +1,28 @@
package io.github.wulkanowy
-import android.content.Context
+import android.app.Application
import android.util.Log.DEBUG
import android.util.Log.INFO
import android.util.Log.VERBOSE
-import androidx.multidex.MultiDex
+import androidx.hilt.work.HiltWorkerFactory
import androidx.work.Configuration
-import com.jakewharton.threetenabp.AndroidThreeTen
import com.yariksoffice.lingver.Lingver
-import dagger.android.AndroidInjector
-import dagger.android.support.DaggerApplication
-import eu.davidea.flexibleadapter.FlexibleAdapter
-import eu.davidea.flexibleadapter.utils.Log
-import fr.bipi.tressence.file.FileLoggerTree
-import io.github.wulkanowy.di.DaggerAppComponent
-import io.github.wulkanowy.services.sync.SyncWorkerFactory
+import dagger.hilt.android.HiltAndroidApp
+import fr.bipi.treessence.file.FileLoggerTree
+import io.github.wulkanowy.data.repositories.PreferencesRepository
import io.github.wulkanowy.ui.base.ThemeManager
import io.github.wulkanowy.utils.ActivityLifecycleLogger
+import io.github.wulkanowy.utils.AnalyticsHelper
import io.github.wulkanowy.utils.AppInfo
-import io.github.wulkanowy.utils.CrashlyticsExceptionTree
-import io.github.wulkanowy.utils.CrashlyticsTree
+import io.github.wulkanowy.utils.CrashLogExceptionTree
+import io.github.wulkanowy.utils.CrashLogTree
import io.github.wulkanowy.utils.DebugLogTree
-import io.github.wulkanowy.utils.initCrashlytics
-import io.reactivex.exceptions.UndeliverableException
-import io.reactivex.plugins.RxJavaPlugins
+import io.github.wulkanowy.utils.RemoteConfigHelper
import timber.log.Timber
-import java.io.IOException
import javax.inject.Inject
-class WulkanowyApp : DaggerApplication(), Configuration.Provider {
-
- @Inject
- lateinit var workerFactory: SyncWorkerFactory
+@HiltAndroidApp
+class WulkanowyApp : Application(), Configuration.Provider {
@Inject
lateinit var themeManager: ThemeManager
@@ -39,54 +30,58 @@ class WulkanowyApp : DaggerApplication(), Configuration.Provider {
@Inject
lateinit var appInfo: AppInfo
- override fun attachBaseContext(base: Context?) {
- super.attachBaseContext(base)
- MultiDex.install(this)
- }
+ @Inject
+ lateinit var preferencesRepository: PreferencesRepository
+
+ @Inject
+ lateinit var analyticsHelper: AnalyticsHelper
+
+ @Inject
+ lateinit var remoteConfigHelper: RemoteConfigHelper
+
+ @Inject
+ lateinit var workerFactory: HiltWorkerFactory
+
+ override val workManagerConfiguration: Configuration
+ get() = Configuration.Builder()
+ .setWorkerFactory(workerFactory)
+ .setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO)
+ .build()
override fun onCreate() {
super.onCreate()
- AndroidThreeTen.init(this)
- RxJavaPlugins.setErrorHandler(::onError)
- Lingver.init(this)
+ initializeAppLanguage()
themeManager.applyDefaultTheme()
-
+ remoteConfigHelper.initialize()
initLogging()
- initCrashlytics(this, appInfo)
}
private fun initLogging() {
if (appInfo.isDebug) {
- FlexibleAdapter.enableLogs(Log.Level.DEBUG)
Timber.plant(DebugLogTree())
- Timber.plant(FileLoggerTree.Builder()
- .withFileName("wulkanowy.%g.log")
- .withDirName(applicationContext.filesDir.absolutePath)
- .withFileLimit(10)
- .withMinPriority(DEBUG)
- .build()
+ Timber.plant(
+ FileLoggerTree.Builder()
+ .withFileName("wulkanowy.%g.log")
+ .withDirName(applicationContext.filesDir.absolutePath)
+ .withFileLimit(10)
+ .withMinPriority(DEBUG)
+ .build()
)
} else {
- Timber.plant(CrashlyticsExceptionTree())
- Timber.plant(CrashlyticsTree())
+ Timber.plant(CrashLogExceptionTree())
+ Timber.plant(CrashLogTree())
}
registerActivityLifecycleCallbacks(ActivityLifecycleLogger())
}
- private fun onError(error: Throwable) {
- //RxJava's too deep stack traces may cause SOE on older android devices
- val cause = error.cause
- if (error is UndeliverableException && cause is IOException || cause is InterruptedException || cause is StackOverflowError) {
- Timber.e(cause, "An undeliverable error occurred")
- } else throw error
- }
+ private fun initializeAppLanguage() {
+ Lingver.init(this)
- override fun applicationInjector(): AndroidInjector {
- return DaggerAppComponent.factory().create(this)
+ if (preferencesRepository.appLanguage == "system") {
+ Lingver.getInstance().setFollowSystemLocale(this)
+ analyticsHelper.logEvent("language", "startup" to appInfo.systemLanguage)
+ } else {
+ analyticsHelper.logEvent("language", "startup" to preferencesRepository.appLanguage)
+ }
}
-
- override fun getWorkManagerConfiguration() = Configuration.Builder()
- .setWorkerFactory(workerFactory)
- .setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO)
- .build()
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/DataModule.kt b/app/src/main/java/io/github/wulkanowy/data/DataModule.kt
new file mode 100644
index 00000000..a21d56cc
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/DataModule.kt
@@ -0,0 +1,246 @@
+package io.github.wulkanowy.data
+
+import android.content.Context
+import android.content.SharedPreferences
+import androidx.preference.PreferenceManager
+import com.chuckerteam.chucker.api.ChuckerCollector
+import com.chuckerteam.chucker.api.ChuckerInterceptor
+import com.chuckerteam.chucker.api.RetentionManager
+import com.fredporciuncula.flow.preferences.FlowSharedPreferences
+import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
+import dagger.Module
+import dagger.Provides
+import dagger.hilt.InstallIn
+import dagger.hilt.android.qualifiers.ApplicationContext
+import dagger.hilt.components.SingletonComponent
+import io.github.wulkanowy.data.api.services.SchoolsService
+import io.github.wulkanowy.data.api.services.WulkanowyService
+import io.github.wulkanowy.data.db.AppDatabase
+import io.github.wulkanowy.data.db.SharedPrefProvider
+import io.github.wulkanowy.data.repositories.PreferencesRepository
+import io.github.wulkanowy.utils.AppInfo
+import kotlinx.serialization.json.Json
+import okhttp3.MediaType.Companion.toMediaType
+import okhttp3.OkHttpClient
+import okhttp3.logging.HttpLoggingInterceptor
+import retrofit2.Retrofit
+import retrofit2.create
+import java.util.concurrent.TimeUnit
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal class DataModule {
+
+ @Singleton
+ @Provides
+ fun provideChuckerCollector(
+ @ApplicationContext context: Context,
+ prefRepository: PreferencesRepository
+ ) = ChuckerCollector(
+ context = context,
+ showNotification = prefRepository.isDebugNotificationEnable,
+ retentionPeriod = RetentionManager.Period.ONE_HOUR
+ )
+
+ @Singleton
+ @Provides
+ fun provideChuckerInterceptor(
+ @ApplicationContext context: Context,
+ chuckerCollector: ChuckerCollector
+ ) = ChuckerInterceptor.Builder(context)
+ .collector(chuckerCollector)
+ .alwaysReadResponseBody(true)
+ .build()
+
+ @Singleton
+ @Provides
+ fun provideOkHttpClient(chuckerInterceptor: ChuckerInterceptor): OkHttpClient =
+ OkHttpClient.Builder()
+ .addNetworkInterceptor(chuckerInterceptor)
+ .addInterceptor(HttpLoggingInterceptor().apply {
+ level = HttpLoggingInterceptor.Level.BASIC
+ })
+ .connectTimeout(30, TimeUnit.SECONDS)
+ .readTimeout(30, TimeUnit.SECONDS)
+ .build()
+
+ @Singleton
+ @Provides
+ fun provideAdminMessageService(
+ okHttpClient: OkHttpClient,
+ json: Json,
+ appInfo: AppInfo
+ ): WulkanowyService = Retrofit.Builder()
+ .baseUrl(appInfo.messagesBaseUrl)
+ .client(okHttpClient)
+ .addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
+ .build()
+ .create()
+
+ @Singleton
+ @Provides
+ fun provideSchoolsService(
+ okHttpClient: OkHttpClient,
+ json: Json,
+ appInfo: AppInfo,
+ ): SchoolsService = Retrofit.Builder()
+ .baseUrl(appInfo.schoolsBaseUrl)
+ .client(okHttpClient)
+ .addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
+ .build()
+ .create()
+
+ @Singleton
+ @Provides
+ fun provideDatabase(
+ @ApplicationContext context: Context,
+ sharedPrefProvider: SharedPrefProvider,
+ appInfo: AppInfo
+ ) = AppDatabase.newInstance(context, sharedPrefProvider, appInfo)
+
+ @Singleton
+ @Provides
+ fun provideSharedPref(@ApplicationContext context: Context): SharedPreferences =
+ PreferenceManager.getDefaultSharedPreferences(context)
+
+ @Singleton
+ @Provides
+ fun provideFlowSharedPref(sharedPreferences: SharedPreferences) =
+ FlowSharedPreferences(sharedPreferences)
+
+ @Singleton
+ @Provides
+ fun provideJson() = Json {
+ ignoreUnknownKeys = true
+ }
+
+ @Singleton
+ @Provides
+ fun provideStudentDao(database: AppDatabase) = database.studentDao
+
+ @Singleton
+ @Provides
+ fun provideSemesterDao(database: AppDatabase) = database.semesterDao
+
+ @Singleton
+ @Provides
+ fun provideGradeDao(database: AppDatabase) = database.gradeDao
+
+ @Singleton
+ @Provides
+ fun provideGradeSummaryDao(database: AppDatabase) = database.gradeSummaryDao
+
+ @Singleton
+ @Provides
+ fun provideGradePartialStatisticsDao(database: AppDatabase) = database.gradePartialStatisticsDao
+
+ @Singleton
+ @Provides
+ fun provideGradeSemesterStatisticsDao(database: AppDatabase) =
+ database.gradeSemesterStatisticsDao
+
+ @Singleton
+ @Provides
+ fun provideGradePointsStatisticsDao(database: AppDatabase) = database.gradePointsStatisticsDao
+
+ @Singleton
+ @Provides
+ fun provideMessagesDao(database: AppDatabase) = database.messagesDao
+
+ @Singleton
+ @Provides
+ fun provideMessageAttachmentsDao(database: AppDatabase) = database.messageAttachmentDao
+
+ @Singleton
+ @Provides
+ fun provideExamDao(database: AppDatabase) = database.examsDao
+
+ @Singleton
+ @Provides
+ fun provideAttendanceDao(database: AppDatabase) = database.attendanceDao
+
+ @Singleton
+ @Provides
+ fun provideAttendanceSummaryDao(database: AppDatabase) = database.attendanceSummaryDao
+
+ @Singleton
+ @Provides
+ fun provideTimetableDao(database: AppDatabase) = database.timetableDao
+
+ @Singleton
+ @Provides
+ fun provideNoteDao(database: AppDatabase) = database.noteDao
+
+ @Singleton
+ @Provides
+ fun provideHomeworkDao(database: AppDatabase) = database.homeworkDao
+
+ @Singleton
+ @Provides
+ fun provideSubjectDao(database: AppDatabase) = database.subjectDao
+
+ @Singleton
+ @Provides
+ fun provideLuckyNumberDao(database: AppDatabase) = database.luckyNumberDao
+
+ @Singleton
+ @Provides
+ fun provideCompletedLessonsDao(database: AppDatabase) = database.completedLessonsDao
+
+ @Singleton
+ @Provides
+ fun provideMailboxesDao(database: AppDatabase) = database.mailboxDao
+
+ @Singleton
+ @Provides
+ fun provideRecipientDao(database: AppDatabase) = database.recipientDao
+
+ @Singleton
+ @Provides
+ fun provideMobileDevicesDao(database: AppDatabase) = database.mobileDeviceDao
+
+ @Singleton
+ @Provides
+ fun provideTeacherDao(database: AppDatabase) = database.teacherDao
+
+ @Singleton
+ @Provides
+ fun provideSchoolInfoDao(database: AppDatabase) = database.schoolDao
+
+ @Singleton
+ @Provides
+ fun provideConferenceDao(database: AppDatabase) = database.conferenceDao
+
+ @Singleton
+ @Provides
+ fun provideTimetableAdditionalDao(database: AppDatabase) = database.timetableAdditionalDao
+
+ @Singleton
+ @Provides
+ fun provideStudentInfoDao(database: AppDatabase) = database.studentInfoDao
+
+ @Singleton
+ @Provides
+ fun provideTimetableHeaderDao(database: AppDatabase) = database.timetableHeaderDao
+
+ @Singleton
+ @Provides
+ fun provideSchoolAnnouncementDao(database: AppDatabase) = database.schoolAnnouncementDao
+
+ @Singleton
+ @Provides
+ fun provideNotificationDao(database: AppDatabase) = database.notificationDao
+
+ @Singleton
+ @Provides
+ fun provideAdminMessageDao(database: AppDatabase) = database.adminMessagesDao
+
+ @Singleton
+ @Provides
+ fun provideMutesDao(database: AppDatabase) = database.mutedMessageSendersDao
+
+ @Singleton
+ @Provides
+ fun provideGradeDescriptiveDao(database: AppDatabase) = database.gradeDescriptiveDao
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt b/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt
deleted file mode 100644
index 43c27c52..00000000
--- a/app/src/main/java/io/github/wulkanowy/data/RepositoryModule.kt
+++ /dev/null
@@ -1,159 +0,0 @@
-package io.github.wulkanowy.data
-
-import android.content.Context
-import android.content.SharedPreferences
-import android.content.res.AssetManager
-import android.content.res.Resources
-import androidx.preference.PreferenceManager
-import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings
-import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.strategy.WalledGardenInternetObservingStrategy
-import com.chuckerteam.chucker.api.ChuckerCollector
-import com.chuckerteam.chucker.api.ChuckerInterceptor
-import com.chuckerteam.chucker.api.RetentionManager
-import dagger.Module
-import dagger.Provides
-import io.github.wulkanowy.data.db.AppDatabase
-import io.github.wulkanowy.data.db.SharedPrefProvider
-import io.github.wulkanowy.data.repositories.preferences.PreferencesRepository
-import io.github.wulkanowy.sdk.Sdk
-import timber.log.Timber
-import javax.inject.Singleton
-
-@Module
-internal class RepositoryModule {
-
- @Singleton
- @Provides
- fun provideInternetObservingSettings(): InternetObservingSettings {
- return InternetObservingSettings.builder()
- .strategy(WalledGardenInternetObservingStrategy())
- .build()
- }
-
- @Singleton
- @Provides
- fun provideSdk(chuckerCollector: ChuckerCollector, context: Context): Sdk {
- return Sdk().apply {
- androidVersion = android.os.Build.VERSION.RELEASE
- buildTag = android.os.Build.MODEL
- setSimpleHttpLogger { Timber.d(it) }
-
- // for debug only
- addInterceptor(ChuckerInterceptor(context, chuckerCollector), true)
- }
- }
-
- @Singleton
- @Provides
- fun provideChuckerCollector(context: Context, prefRepository: PreferencesRepository): ChuckerCollector {
- return ChuckerCollector(
- context = context,
- showNotification = prefRepository.isDebugNotificationEnable,
- retentionPeriod = RetentionManager.Period.ONE_HOUR
- )
- }
-
- @Singleton
- @Provides
- fun provideDatabase(context: Context, sharedPrefProvider: SharedPrefProvider) = AppDatabase.newInstance(context, sharedPrefProvider)
-
- @Singleton
- @Provides
- fun provideResources(context: Context): Resources = context.resources
-
- @Singleton
- @Provides
- fun provideAssets(context: Context): AssetManager = context.assets
-
- @Singleton
- @Provides
- fun provideSharedPref(context: Context): SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
-
- @Singleton
- @Provides
- fun provideStudentDao(database: AppDatabase) = database.studentDao
-
- @Singleton
- @Provides
- fun provideSemesterDao(database: AppDatabase) = database.semesterDao
-
- @Singleton
- @Provides
- fun provideGradeDao(database: AppDatabase) = database.gradeDao
-
- @Singleton
- @Provides
- fun provideGradeSummaryDao(database: AppDatabase) = database.gradeSummaryDao
-
- @Singleton
- @Provides
- fun provideGradeStatisticsDao(database: AppDatabase) = database.gradeStatistics
-
- @Singleton
- @Provides
- fun provideGradePointsStatisticsDao(database: AppDatabase) = database.gradePointsStatistics
-
- @Singleton
- @Provides
- fun provideMessagesDao(database: AppDatabase) = database.messagesDao
-
- @Singleton
- @Provides
- fun provideMessageAttachmentsDao(database: AppDatabase) = database.messageAttachmentDao
-
- @Singleton
- @Provides
- fun provideExamDao(database: AppDatabase) = database.examsDao
-
- @Singleton
- @Provides
- fun provideAttendanceDao(database: AppDatabase) = database.attendanceDao
-
- @Singleton
- @Provides
- fun provideAttendanceSummaryDao(database: AppDatabase) = database.attendanceSummaryDao
-
- @Singleton
- @Provides
- fun provideTimetableDao(database: AppDatabase) = database.timetableDao
-
- @Singleton
- @Provides
- fun provideNoteDao(database: AppDatabase) = database.noteDao
-
- @Singleton
- @Provides
- fun provideHomeworkDao(database: AppDatabase) = database.homeworkDao
-
- @Singleton
- @Provides
- fun provideSubjectDao(database: AppDatabase) = database.subjectDao
-
- @Singleton
- @Provides
- fun provideLuckyNumberDao(database: AppDatabase) = database.luckyNumberDao
-
- @Singleton
- @Provides
- fun provideCompletedLessonsDao(database: AppDatabase) = database.completedLessonsDao
-
- @Singleton
- @Provides
- fun provideReportingUnitDao(database: AppDatabase) = database.reportingUnitDao
-
- @Singleton
- @Provides
- fun provideRecipientDao(database: AppDatabase) = database.recipientDao
-
- @Singleton
- @Provides
- fun provideMobileDevicesDao(database: AppDatabase) = database.mobileDeviceDao
-
- @Singleton
- @Provides
- fun provideTeacherDao(database: AppDatabase) = database.teacherDao
-
- @Singleton
- @Provides
- fun provideSchoolInfoDao(database: AppDatabase) = database.schoolDao
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/Resource.kt b/app/src/main/java/io/github/wulkanowy/data/Resource.kt
new file mode 100644
index 00000000..712a946f
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/Resource.kt
@@ -0,0 +1,285 @@
+package io.github.wulkanowy.data
+
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.FlowPreview
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.catch
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.debounce
+import kotlinx.coroutines.flow.emitAll
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.filterNot
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.takeWhile
+import kotlinx.coroutines.sync.Mutex
+import kotlinx.coroutines.sync.withLock
+import timber.log.Timber
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.seconds
+
+sealed interface Resource {
+ /**
+ * The initial value of a resource flow. Indicates no data that is currently available to be shown,
+ * however with the expectation that the state will transition to another one soon.
+ */
+ open class Loading : Resource
+
+ /**
+ * A semi-loading state with some data available to be displayed (usually cached data loaded from
+ * the database). Still not the target state and it's expected to transition into another one soon.
+ */
+ data class Intermediate(val data: T) : Loading()
+
+ /**
+ * The happy-path target state. Data can either be:
+ * - loaded from the database - while it may seem like this case is already handled by the
+ * Intermediate state, the difference here is semantic. Cached data is returned as Intermediate
+ * when there's a API request in progress (or soon expected to be), however when there is no
+ * intention of immediately querying the API, the cached data is returned as a Success.
+ * - fetched from the API.
+ */
+ data class Success(val data: T) : Resource
+
+ /**
+ * Something bad happened and we were unable to get the requested data. This can be caused by
+ * a database error, a network error, or really just any other error. Upon receiving this state
+ * the UI can either: display a full screen error, or, when it has received any data previously,
+ * display a snack bar informing of the problem.
+ */
+ data class Error(val error: Throwable) : Resource
+}
+
+val Resource.dataOrNull: T?
+ get() = when (this) {
+ is Resource.Success -> this.data
+ is Resource.Intermediate -> this.data
+ else -> null
+ }
+
+val Resource.dataOrThrow: T
+ get() = when (this) {
+ is Resource.Success -> this.data
+ is Resource.Intermediate -> this.data
+ is Resource.Loading -> throw IllegalStateException("Resource is in loading state")
+ is Resource.Error -> throw this.error
+ }
+
+val Resource.errorOrNull: Throwable?
+ get() = when (this) {
+ is Resource.Error -> this.error
+ else -> null
+ }
+
+fun resourceFlow(block: suspend () -> T) = flow {
+ emit(Resource.Loading())
+ emit(Resource.Success(block()))
+}.catch { emit(Resource.Error(it)) }
+
+fun flatResourceFlow(block: suspend () -> Flow>) = flow {
+ emit(Resource.Loading())
+ emitAll(block().filter { it is Resource.Intermediate || it !is Resource.Loading })
+}.catch { emit(Resource.Error(it)) }
+
+fun Resource.mapData(block: (T) -> U) = when (this) {
+ is Resource.Success -> Resource.Success(block(this.data))
+ is Resource.Intermediate -> Resource.Intermediate(block(this.data))
+ is Resource.Loading -> Resource.Loading()
+ is Resource.Error -> Resource.Error(this.error)
+}
+
+/**
+ * Injects another flow into this flow's resource data.
+ */
+inline fun Flow>.combineWithResourceData(
+ flow: Flow,
+ crossinline block: suspend (T1, T2) -> R
+): Flow> =
+ combine(flow) { resource, inject ->
+ when (resource) {
+ is Resource.Success -> Resource.Success(block(resource.data, inject))
+ is Resource.Intermediate -> Resource.Intermediate(block(resource.data, inject))
+ is Resource.Loading -> Resource.Loading()
+ is Resource.Error -> Resource.Error(resource.error)
+ }
+ }
+
+fun Flow>.logResourceStatus(name: String, showData: Boolean = false) = onEach {
+ val description = when (it) {
+ is Resource.Intermediate -> "intermediate data received" + if (showData) " (data: `${it.data}`)" else ""
+ is Resource.Loading -> "started"
+ is Resource.Success -> "success" + if (showData) " (data: `${it.data}`)" else ""
+ is Resource.Error -> "exception occurred: ${it.error}"
+ }
+ Timber.i("$name: $description")
+}
+
+inline fun Flow>.mapResourceData(crossinline block: suspend (T) -> U) = map {
+ when (it) {
+ is Resource.Success -> Resource.Success(block(it.data))
+ is Resource.Intermediate -> Resource.Intermediate(block(it.data))
+ is Resource.Loading -> Resource.Loading()
+ is Resource.Error -> Resource.Error(it.error)
+ }
+}
+
+@OptIn(ExperimentalCoroutinesApi::class)
+fun Flow>.flatMapResourceData(
+ inheritIntermediate: Boolean = true, block: suspend (T) -> Flow>
+) = flatMapLatest {
+ when (it) {
+ is Resource.Success -> block(it.data)
+ is Resource.Intermediate -> block(it.data).map { newRes ->
+ if (inheritIntermediate && newRes is Resource.Success) Resource.Intermediate(newRes.data)
+ else newRes
+ }
+
+ is Resource.Loading -> flowOf(Resource.Loading())
+ is Resource.Error -> flowOf(Resource.Error(it.error))
+ }
+}
+
+fun Flow>.onResourceData(block: suspend (T) -> Unit) = onEach {
+ when (it) {
+ is Resource.Success -> block(it.data)
+ is Resource.Intermediate -> block(it.data)
+ is Resource.Error,
+ is Resource.Loading -> Unit
+ }
+}
+
+fun Flow>.onResourceLoading(block: suspend () -> Unit) = onEach {
+ if (it is Resource.Loading) {
+ block()
+ }
+}
+
+fun Flow>.onResourceIntermediate(block: suspend (T) -> Unit) = onEach {
+ if (it is Resource.Intermediate) {
+ block(it.data)
+ }
+}
+
+fun Flow>.onResourceSuccess(block: suspend (T) -> Unit) = onEach {
+ if (it is Resource.Success) {
+ block(it.data)
+ }
+}
+
+fun Flow>.onResourceError(block: suspend (Throwable) -> Unit) = onEach {
+ if (it is Resource.Error) {
+ block(it.error)
+ }
+}
+
+fun Flow>.onResourceNotLoading(block: suspend () -> Unit) = onEach {
+ if (it !is Resource.Loading) {
+ block()
+ }
+}
+
+suspend fun Flow>.toFirstResult() = filter { it !is Resource.Loading }.first()
+
+suspend fun Flow>.waitForResult() = takeWhile { it is Resource.Loading }.collect()
+
+// Can cause excessive amounts of `Resource.Intermediate` to be emitted. Unless that is desired,
+// use `debounceIntermediates` to alleviate this behavior.
+inline fun combineResourceFlows(flows: Iterable>>): Flow>> =
+ combine(flows) { items ->
+ var isIntermediate = false
+ val data = mutableListOf()
+ for (item in items) {
+ when (item) {
+ is Resource.Success -> data.add(item.data)
+ is Resource.Intermediate -> {
+ isIntermediate = true
+ data.add(item.data)
+ }
+
+ is Resource.Loading -> return@combine Resource.Loading()
+ is Resource.Error -> continue
+ }
+ }
+ if (data.isEmpty()) {
+ // All items have to be errors for this to happen, so just return the first one.
+ // mapData is functionally useless and exists only to satisfy the type checker
+ items.first().mapData { listOf(it) }
+ } else if (isIntermediate) {
+ Resource.Intermediate(data)
+ } else {
+ Resource.Success(data)
+ }
+ }
+
+@OptIn(FlowPreview::class)
+fun Flow>.debounceIntermediates(timeout: Duration = 5.seconds) = flow {
+ var wasIntermediate = false
+
+ emitAll(this@debounceIntermediates.debounce {
+ if (it is Resource.Intermediate) {
+ if (!wasIntermediate) {
+ wasIntermediate = true
+ Duration.ZERO
+ } else {
+ timeout
+ }
+ } else {
+ wasIntermediate = false
+ Duration.ZERO
+ }
+ })
+}
+
+
+inline fun networkBoundResource(
+ mutex: Mutex = Mutex(),
+ crossinline isResultEmpty: (OutputType) -> Boolean,
+ crossinline query: () -> Flow,
+ crossinline fetch: suspend () -> ApiType,
+ crossinline saveFetchResult: suspend (old: OutputType, new: ApiType) -> Unit,
+ crossinline shouldFetch: (OutputType) -> Boolean = { true },
+ crossinline filterResult: (OutputType) -> OutputType = { it }
+) = networkBoundResource(
+ mutex = mutex,
+ isResultEmpty = isResultEmpty,
+ query = query,
+ fetch = fetch,
+ saveFetchResult = saveFetchResult,
+ shouldFetch = shouldFetch,
+ mapResult = filterResult
+)
+
+@JvmName("networkBoundResourceWithMap")
+inline fun networkBoundResource(
+ mutex: Mutex = Mutex(),
+ crossinline isResultEmpty: (OutputType) -> Boolean,
+ crossinline query: () -> Flow,
+ crossinline fetch: suspend () -> ApiType,
+ crossinline saveFetchResult: suspend (old: DatabaseType, new: ApiType) -> Unit,
+ crossinline shouldFetch: (DatabaseType) -> Boolean = { true },
+ crossinline mapResult: (DatabaseType) -> OutputType,
+) = flow {
+ emit(Resource.Loading())
+
+ val data = query().first()
+ if (shouldFetch(data)) {
+ emit(Resource.Intermediate(data))
+
+ try {
+ val newData = fetch()
+ mutex.withLock { saveFetchResult(query().first(), newData) }
+ } catch (throwable: Throwable) {
+ emit(Resource.Error(throwable))
+ return@flow
+ }
+ }
+
+ emitAll(query().map { Resource.Success(it) })
+}
+ .mapResourceData { mapResult(it) }
+ .filterNot { it is Resource.Intermediate && isResultEmpty(it.data) }
diff --git a/app/src/main/java/io/github/wulkanowy/data/WulkanowySdkFactory.kt b/app/src/main/java/io/github/wulkanowy/data/WulkanowySdkFactory.kt
new file mode 100644
index 00000000..dbd34cee
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/WulkanowySdkFactory.kt
@@ -0,0 +1,143 @@
+package io.github.wulkanowy.data
+
+import com.chuckerteam.chucker.api.ChuckerInterceptor
+import io.github.wulkanowy.data.db.dao.StudentDao
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.db.entities.StudentIsEduOne
+import io.github.wulkanowy.data.repositories.WulkanowyRepository
+import io.github.wulkanowy.sdk.Sdk
+import io.github.wulkanowy.utils.RemoteConfigHelper
+import io.github.wulkanowy.utils.WebkitCookieManagerProxy
+import kotlinx.coroutines.sync.Mutex
+import kotlinx.coroutines.sync.withLock
+import timber.log.Timber
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class WulkanowySdkFactory @Inject constructor(
+ private val chuckerInterceptor: ChuckerInterceptor,
+ private val remoteConfig: RemoteConfigHelper,
+ private val webkitCookieManagerProxy: WebkitCookieManagerProxy,
+ private val studentDb: StudentDao,
+ private val wulkanowyRepository: WulkanowyRepository,
+) {
+
+ private val eduOneMutex = Mutex()
+ private val migrationFailedStudentIds = mutableSetOf()
+
+ private val sdk = Sdk().apply {
+ androidVersion = android.os.Build.VERSION.RELEASE
+ buildTag = android.os.Build.MODEL
+ userAgentTemplate = remoteConfig.userAgentTemplate
+ setSimpleHttpLogger { Timber.d(it) }
+ setAdditionalCookieManager(webkitCookieManagerProxy)
+
+ // for debug only
+ addInterceptor(chuckerInterceptor, network = true)
+ }
+
+ fun createBase() = sdk
+
+ suspend fun create(): Sdk {
+ val mapping = wulkanowyRepository.getMapping()
+
+ return createBase().apply {
+ if (mapping != null) {
+ endpointsMapping = mapping.endpoints
+ vTokenMapping = mapping.vTokens
+ vTokenSchemeMapping = mapping.vTokenScheme
+ }
+ }
+ }
+
+ suspend fun create(student: Student, semester: Semester? = null): Sdk {
+ val overrideIsEduOne = checkEduOneAndMigrateIfNecessary(student)
+ return buildSdk(student, semester, overrideIsEduOne)
+ }
+
+ private suspend fun buildSdk(
+ student: Student,
+ semester: Semester?,
+ isStudentEduOne: Boolean
+ ): Sdk {
+ return create().apply {
+ email = student.email
+ password = student.password
+ symbol = student.symbol
+ schoolSymbol = student.schoolSymbol
+ studentId = student.studentId
+ classId = student.classId
+ emptyCookieJarInterceptor = true
+ isEduOne = isStudentEduOne
+
+ if (Sdk.Mode.valueOf(student.loginMode) == Sdk.Mode.HEBE) {
+ mobileBaseUrl = student.mobileBaseUrl
+ } else {
+ scrapperBaseUrl = student.scrapperBaseUrl
+ domainSuffix = student.scrapperDomainSuffix
+ loginType = Sdk.ScrapperLoginType.valueOf(student.loginType)
+ }
+
+ mode = Sdk.Mode.valueOf(student.loginMode)
+ mobileBaseUrl = student.mobileBaseUrl
+ keyId = student.certificateKey
+ privatePem = student.privateKey
+
+ if (semester != null) {
+ diaryId = semester.diaryId
+ kindergartenDiaryId = semester.kindergartenDiaryId
+ schoolYear = semester.schoolYear
+ unitId = semester.unitId
+ }
+ }
+ }
+
+ private suspend fun checkEduOneAndMigrateIfNecessary(student: Student): Boolean {
+ if (student.isEduOne != null) return student.isEduOne
+
+ if (student.id in migrationFailedStudentIds) {
+ Timber.i("Migration eduOne: skipping because of previous failure")
+ return false
+ }
+
+ eduOneMutex.withLock {
+ if (student.id in migrationFailedStudentIds) {
+ Timber.i("Migration eduOne: skipping because of previous failure")
+ return false
+ }
+
+ val studentFromDatabase = studentDb.loadById(student.id)
+ if (studentFromDatabase?.isEduOne != null) {
+ Timber.i("Migration eduOne: already done")
+ return studentFromDatabase.isEduOne
+ }
+
+ Timber.i("Migration eduOne: flag missing. Running migration...")
+ val initializedSdk = buildSdk(
+ student = student,
+ semester = null,
+ isStudentEduOne = false, // doesn't matter
+ )
+ val newCurrentStudent = runCatching { initializedSdk.getCurrentStudent() }
+ .onFailure { Timber.e(it, "Migration eduOne: can't get current student") }
+ .getOrNull()
+
+ if (newCurrentStudent == null) {
+ Timber.i("Migration eduOne: failed, so skipping")
+ migrationFailedStudentIds.add(student.id)
+ return false
+ }
+
+ Timber.i("Migration eduOne: success. New isEduOne flag: ${newCurrentStudent.isEduOne}")
+
+ val studentIsEduOne = StudentIsEduOne(
+ id = student.id,
+ isEduOne = newCurrentStudent.isEduOne
+ )
+ studentDb.update(studentIsEduOne)
+ return newCurrentStudent.isEduOne
+ }
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/api/models/Mapping.kt b/app/src/main/java/io/github/wulkanowy/data/api/models/Mapping.kt
new file mode 100644
index 00000000..c4667a47
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/api/models/Mapping.kt
@@ -0,0 +1,17 @@
+package io.github.wulkanowy.data.api.models
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class Mapping(
+
+ @SerialName("endpoints")
+ val endpoints: Map>>,
+
+ @SerialName("vTokens")
+ val vTokens: Map>>,
+
+ @SerialName("vTokenScheme")
+ val vTokenScheme: Map> = emptyMap(),
+)
diff --git a/app/src/main/java/io/github/wulkanowy/data/api/services/SchoolsService.kt b/app/src/main/java/io/github/wulkanowy/data/api/services/SchoolsService.kt
new file mode 100644
index 00000000..07fbeb89
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/api/services/SchoolsService.kt
@@ -0,0 +1,14 @@
+package io.github.wulkanowy.data.api.services
+
+import io.github.wulkanowy.data.pojos.IntegrityRequest
+import io.github.wulkanowy.data.pojos.LoginEvent
+import retrofit2.http.Body
+import retrofit2.http.POST
+import javax.inject.Singleton
+
+@Singleton
+interface SchoolsService {
+
+ @POST("/log/loginEvent")
+ suspend fun logLoginEvent(@Body request: IntegrityRequest)
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/api/services/WulkanowyService.kt b/app/src/main/java/io/github/wulkanowy/data/api/services/WulkanowyService.kt
new file mode 100644
index 00000000..161e93d6
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/api/services/WulkanowyService.kt
@@ -0,0 +1,16 @@
+package io.github.wulkanowy.data.api.services
+
+import io.github.wulkanowy.data.api.models.Mapping
+import io.github.wulkanowy.data.db.entities.AdminMessage
+import retrofit2.http.GET
+import javax.inject.Singleton
+
+@Singleton
+interface WulkanowyService {
+
+ @GET("/v1.json")
+ suspend fun getAdminMessages(): List
+
+ @GET("/mapping2.json")
+ suspend fun getMapping(): Mapping
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt
index 762c52f8..f23c79de 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/AppDatabase.kt
@@ -1,56 +1,76 @@
package io.github.wulkanowy.data.db
import android.content.Context
+import androidx.room.AutoMigration
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.RoomDatabase.JournalMode.TRUNCATE
import androidx.room.TypeConverters
-import androidx.room.migration.Migration
+import io.github.wulkanowy.data.db.dao.AdminMessageDao
import io.github.wulkanowy.data.db.dao.AttendanceDao
import io.github.wulkanowy.data.db.dao.AttendanceSummaryDao
import io.github.wulkanowy.data.db.dao.CompletedLessonsDao
+import io.github.wulkanowy.data.db.dao.ConferenceDao
import io.github.wulkanowy.data.db.dao.ExamDao
import io.github.wulkanowy.data.db.dao.GradeDao
+import io.github.wulkanowy.data.db.dao.GradeDescriptiveDao
+import io.github.wulkanowy.data.db.dao.GradePartialStatisticsDao
import io.github.wulkanowy.data.db.dao.GradePointsStatisticsDao
-import io.github.wulkanowy.data.db.dao.GradeStatisticsDao
+import io.github.wulkanowy.data.db.dao.GradeSemesterStatisticsDao
import io.github.wulkanowy.data.db.dao.GradeSummaryDao
import io.github.wulkanowy.data.db.dao.HomeworkDao
import io.github.wulkanowy.data.db.dao.LuckyNumberDao
+import io.github.wulkanowy.data.db.dao.MailboxDao
import io.github.wulkanowy.data.db.dao.MessageAttachmentDao
import io.github.wulkanowy.data.db.dao.MessagesDao
import io.github.wulkanowy.data.db.dao.MobileDeviceDao
+import io.github.wulkanowy.data.db.dao.MutedMessageSendersDao
import io.github.wulkanowy.data.db.dao.NoteDao
+import io.github.wulkanowy.data.db.dao.NotificationDao
import io.github.wulkanowy.data.db.dao.RecipientDao
-import io.github.wulkanowy.data.db.dao.ReportingUnitDao
+import io.github.wulkanowy.data.db.dao.SchoolAnnouncementDao
import io.github.wulkanowy.data.db.dao.SchoolDao
import io.github.wulkanowy.data.db.dao.SemesterDao
import io.github.wulkanowy.data.db.dao.StudentDao
+import io.github.wulkanowy.data.db.dao.StudentInfoDao
import io.github.wulkanowy.data.db.dao.SubjectDao
import io.github.wulkanowy.data.db.dao.TeacherDao
+import io.github.wulkanowy.data.db.dao.TimetableAdditionalDao
import io.github.wulkanowy.data.db.dao.TimetableDao
+import io.github.wulkanowy.data.db.dao.TimetableHeaderDao
+import io.github.wulkanowy.data.db.entities.AdminMessage
import io.github.wulkanowy.data.db.entities.Attendance
import io.github.wulkanowy.data.db.entities.AttendanceSummary
import io.github.wulkanowy.data.db.entities.CompletedLesson
+import io.github.wulkanowy.data.db.entities.Conference
import io.github.wulkanowy.data.db.entities.Exam
import io.github.wulkanowy.data.db.entities.Grade
+import io.github.wulkanowy.data.db.entities.GradeDescriptive
+import io.github.wulkanowy.data.db.entities.GradePartialStatistics
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
-import io.github.wulkanowy.data.db.entities.GradeStatistics
+import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
import io.github.wulkanowy.data.db.entities.GradeSummary
import io.github.wulkanowy.data.db.entities.Homework
import io.github.wulkanowy.data.db.entities.LuckyNumber
+import io.github.wulkanowy.data.db.entities.Mailbox
import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.MessageAttachment
import io.github.wulkanowy.data.db.entities.MobileDevice
+import io.github.wulkanowy.data.db.entities.MutedMessageSender
import io.github.wulkanowy.data.db.entities.Note
+import io.github.wulkanowy.data.db.entities.Notification
import io.github.wulkanowy.data.db.entities.Recipient
-import io.github.wulkanowy.data.db.entities.ReportingUnit
import io.github.wulkanowy.data.db.entities.School
+import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.data.db.entities.StudentInfo
import io.github.wulkanowy.data.db.entities.Subject
import io.github.wulkanowy.data.db.entities.Teacher
import io.github.wulkanowy.data.db.entities.Timetable
+import io.github.wulkanowy.data.db.entities.TimetableAdditional
+import io.github.wulkanowy.data.db.entities.TimetableHeader
import io.github.wulkanowy.data.db.migrations.Migration10
import io.github.wulkanowy.data.db.migrations.Migration11
import io.github.wulkanowy.data.db.migrations.Migration12
@@ -68,13 +88,43 @@ import io.github.wulkanowy.data.db.migrations.Migration22
import io.github.wulkanowy.data.db.migrations.Migration23
import io.github.wulkanowy.data.db.migrations.Migration24
import io.github.wulkanowy.data.db.migrations.Migration25
+import io.github.wulkanowy.data.db.migrations.Migration26
+import io.github.wulkanowy.data.db.migrations.Migration27
+import io.github.wulkanowy.data.db.migrations.Migration28
+import io.github.wulkanowy.data.db.migrations.Migration29
import io.github.wulkanowy.data.db.migrations.Migration3
+import io.github.wulkanowy.data.db.migrations.Migration30
+import io.github.wulkanowy.data.db.migrations.Migration31
+import io.github.wulkanowy.data.db.migrations.Migration32
+import io.github.wulkanowy.data.db.migrations.Migration33
+import io.github.wulkanowy.data.db.migrations.Migration34
+import io.github.wulkanowy.data.db.migrations.Migration35
+import io.github.wulkanowy.data.db.migrations.Migration36
+import io.github.wulkanowy.data.db.migrations.Migration37
+import io.github.wulkanowy.data.db.migrations.Migration38
+import io.github.wulkanowy.data.db.migrations.Migration39
import io.github.wulkanowy.data.db.migrations.Migration4
+import io.github.wulkanowy.data.db.migrations.Migration40
+import io.github.wulkanowy.data.db.migrations.Migration41
+import io.github.wulkanowy.data.db.migrations.Migration42
+import io.github.wulkanowy.data.db.migrations.Migration43
+import io.github.wulkanowy.data.db.migrations.Migration44
+import io.github.wulkanowy.data.db.migrations.Migration46
+import io.github.wulkanowy.data.db.migrations.Migration49
import io.github.wulkanowy.data.db.migrations.Migration5
+import io.github.wulkanowy.data.db.migrations.Migration50
+import io.github.wulkanowy.data.db.migrations.Migration51
+import io.github.wulkanowy.data.db.migrations.Migration53
+import io.github.wulkanowy.data.db.migrations.Migration54
+import io.github.wulkanowy.data.db.migrations.Migration55
+import io.github.wulkanowy.data.db.migrations.Migration57
+import io.github.wulkanowy.data.db.migrations.Migration58
import io.github.wulkanowy.data.db.migrations.Migration6
+import io.github.wulkanowy.data.db.migrations.Migration63
import io.github.wulkanowy.data.db.migrations.Migration7
import io.github.wulkanowy.data.db.migrations.Migration8
import io.github.wulkanowy.data.db.migrations.Migration9
+import io.github.wulkanowy.utils.AppInfo
import javax.inject.Singleton
@Singleton
@@ -88,8 +138,9 @@ import javax.inject.Singleton
AttendanceSummary::class,
Grade::class,
GradeSummary::class,
- GradeStatistics::class,
+ GradePartialStatistics::class,
GradePointsStatistics::class,
+ GradeSemesterStatistics::class,
Message::class,
MessageAttachment::class,
Note::class,
@@ -97,11 +148,36 @@ import javax.inject.Singleton
Subject::class,
LuckyNumber::class,
CompletedLesson::class,
- ReportingUnit::class,
+ Mailbox::class,
Recipient::class,
MobileDevice::class,
Teacher::class,
- School::class
+ School::class,
+ Conference::class,
+ TimetableAdditional::class,
+ StudentInfo::class,
+ TimetableHeader::class,
+ SchoolAnnouncement::class,
+ Notification::class,
+ AdminMessage::class,
+ MutedMessageSender::class,
+ GradeDescriptive::class,
+ ],
+ autoMigrations = [
+ AutoMigration(from = 44, to = 45),
+ AutoMigration(from = 46, to = 47),
+ AutoMigration(from = 47, to = 48),
+ AutoMigration(from = 51, to = 52),
+ AutoMigration(from = 54, to = 55, spec = Migration55::class),
+ AutoMigration(from = 55, to = 56),
+ AutoMigration(from = 56, to = 57, spec = Migration57::class),
+ AutoMigration(from = 57, to = 58, spec = Migration58::class),
+ AutoMigration(from = 58, to = 59),
+ AutoMigration(from = 59, to = 60),
+ AutoMigration(from = 60, to = 61),
+ AutoMigration(from = 61, to = 62),
+ AutoMigration(from = 62, to = 63, spec = Migration63::class),
+ AutoMigration(from = 63, to = 64),
],
version = AppDatabase.VERSION_SCHEMA,
exportSchema = true
@@ -110,45 +186,70 @@ import javax.inject.Singleton
abstract class AppDatabase : RoomDatabase() {
companion object {
- const val VERSION_SCHEMA = 25
+ const val VERSION_SCHEMA = 64
- fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array {
- return arrayOf(
- Migration2(),
- Migration3(),
- Migration4(),
- Migration5(),
- Migration6(),
- Migration7(),
- Migration8(),
- Migration9(),
- Migration10(),
- Migration11(),
- Migration12(),
- Migration13(),
- Migration14(),
- Migration15(),
- Migration16(),
- Migration17(),
- Migration18(),
- Migration19(sharedPrefProvider),
- Migration20(),
- Migration21(),
- Migration22(),
- Migration23(),
- Migration24(),
- Migration25()
- )
- }
+ fun getMigrations(sharedPrefProvider: SharedPrefProvider, appInfo: AppInfo) = arrayOf(
+ Migration2(),
+ Migration3(),
+ Migration4(),
+ Migration5(),
+ Migration6(),
+ Migration7(),
+ Migration8(),
+ Migration9(),
+ Migration10(),
+ Migration11(),
+ Migration12(),
+ Migration13(),
+ Migration14(),
+ Migration15(),
+ Migration16(),
+ Migration17(),
+ Migration18(),
+ Migration19(sharedPrefProvider),
+ Migration20(),
+ Migration21(),
+ Migration22(),
+ Migration23(),
+ Migration24(),
+ Migration25(),
+ Migration26(),
+ Migration27(),
+ Migration28(),
+ Migration29(),
+ Migration30(),
+ Migration31(),
+ Migration32(),
+ Migration33(),
+ Migration34(),
+ Migration35(appInfo),
+ Migration36(),
+ Migration37(),
+ Migration38(),
+ Migration39(),
+ Migration40(),
+ Migration41(sharedPrefProvider),
+ Migration42(),
+ Migration43(),
+ Migration44(),
+ Migration46(),
+ Migration49(),
+ Migration50(),
+ Migration51(),
+ Migration53(),
+ Migration54(),
+ )
- fun newInstance(context: Context, sharedPrefProvider: SharedPrefProvider): AppDatabase {
- return Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database")
- .setJournalMode(TRUNCATE)
- .fallbackToDestructiveMigrationFrom(VERSION_SCHEMA + 1)
- .fallbackToDestructiveMigrationOnDowngrade()
- .addMigrations(*getMigrations(sharedPrefProvider))
- .build()
- }
+ fun newInstance(
+ context: Context,
+ sharedPrefProvider: SharedPrefProvider,
+ appInfo: AppInfo
+ ) = Room.databaseBuilder(context, AppDatabase::class.java, "wulkanowy_database")
+ .setJournalMode(TRUNCATE)
+ .fallbackToDestructiveMigrationFrom(VERSION_SCHEMA + 1)
+ .fallbackToDestructiveMigrationOnDowngrade()
+ .addMigrations(*getMigrations(sharedPrefProvider, appInfo))
+ .build()
}
abstract val studentDao: StudentDao
@@ -167,9 +268,11 @@ abstract class AppDatabase : RoomDatabase() {
abstract val gradeSummaryDao: GradeSummaryDao
- abstract val gradeStatistics: GradeStatisticsDao
+ abstract val gradePartialStatisticsDao: GradePartialStatisticsDao
- abstract val gradePointsStatistics: GradePointsStatisticsDao
+ abstract val gradePointsStatisticsDao: GradePointsStatisticsDao
+
+ abstract val gradeSemesterStatisticsDao: GradeSemesterStatisticsDao
abstract val messagesDao: MessagesDao
@@ -185,7 +288,7 @@ abstract class AppDatabase : RoomDatabase() {
abstract val completedLessonsDao: CompletedLessonsDao
- abstract val reportingUnitDao: ReportingUnitDao
+ abstract val mailboxDao: MailboxDao
abstract val recipientDao: RecipientDao
@@ -194,4 +297,22 @@ abstract class AppDatabase : RoomDatabase() {
abstract val teacherDao: TeacherDao
abstract val schoolDao: SchoolDao
+
+ abstract val conferenceDao: ConferenceDao
+
+ abstract val timetableAdditionalDao: TimetableAdditionalDao
+
+ abstract val studentInfoDao: StudentInfoDao
+
+ abstract val timetableHeaderDao: TimetableHeaderDao
+
+ abstract val schoolAnnouncementDao: SchoolAnnouncementDao
+
+ abstract val notificationDao: NotificationDao
+
+ abstract val adminMessagesDao: AdminMessageDao
+
+ abstract val mutedMessageSendersDao: MutedMessageSendersDao
+
+ abstract val gradeDescriptiveDao: GradeDescriptiveDao
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt b/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt
index 294f73d3..7bc8d12a 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/Converters.kt
@@ -1,37 +1,37 @@
package io.github.wulkanowy.data.db
import androidx.room.TypeConverter
-import com.google.gson.Gson
-import com.google.gson.reflect.TypeToken
-import org.threeten.bp.DateTimeUtils
-import org.threeten.bp.Instant
-import org.threeten.bp.LocalDate
-import org.threeten.bp.LocalDateTime
-import org.threeten.bp.Month
-import org.threeten.bp.ZoneOffset
-import java.util.Date
+import io.github.wulkanowy.data.enums.MessageType
+import io.github.wulkanowy.ui.modules.Destination
+import io.github.wulkanowy.utils.toTimestamp
+import kotlinx.serialization.SerializationException
+import kotlinx.serialization.decodeFromString
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.Json
+import java.time.*
+import java.util.*
+import java.time.Instant
+import java.time.LocalDate
+import java.time.Month
+import java.time.ZoneOffset
+import java.util.*
class Converters {
- @TypeConverter
- fun timestampToDate(value: Long?): LocalDate? = value?.run {
- DateTimeUtils.toInstant(Date(value)).atZone(ZoneOffset.UTC).toLocalDate()
- }
+ private val json = Json
@TypeConverter
- fun dateToTimestamp(date: LocalDate?): Long? {
- return date?.atStartOfDay()?.toInstant(ZoneOffset.UTC)?.toEpochMilli()
- }
+ fun timestampToLocalDate(value: Long?): LocalDate? =
+ value?.let(::Date)?.toInstant()?.atZone(ZoneOffset.UTC)?.toLocalDate()
@TypeConverter
- fun timestampToTime(value: Long?): LocalDateTime? = value?.let {
- LocalDateTime.ofInstant(Instant.ofEpochMilli(value), ZoneOffset.UTC)
- }
+ fun dateToTimestamp(date: LocalDate?): Long? = date?.toTimestamp()
@TypeConverter
- fun timeToTimestamp(date: LocalDateTime?): Long? {
- return date?.atZone(ZoneOffset.UTC)?.toInstant()?.toEpochMilli()
- }
+ fun instantToTimestamp(instant: Instant?): Long? = instant?.toEpochMilli()
+
+ @TypeConverter
+ fun timestampToInstant(timestamp: Long?): Instant? = timestamp?.let(Instant::ofEpochMilli)
@TypeConverter
fun monthToInt(month: Month?) = month?.value
@@ -40,22 +40,38 @@ class Converters {
fun intToMonth(value: Int?) = value?.let { Month.of(it) }
@TypeConverter
- fun intListToGson(list: List): String {
- return Gson().toJson(list)
+ fun intListToJson(list: List): String {
+ return json.encodeToString(list)
}
@TypeConverter
- fun gsonToIntList(value: String): List {
- return Gson().fromJson(value, object : TypeToken>() {}.type)
+ fun jsonToIntList(value: String): List {
+ return json.decodeFromString(value)
}
@TypeConverter
- fun stringPairListToGson(list: List>): String {
- return Gson().toJson(list)
+ fun stringPairListToJson(list: List>): String {
+ return json.encodeToString(list)
}
@TypeConverter
- fun gsonToStringPairList(value: String): List> {
- return Gson().fromJson(value, object : TypeToken>>() {}.type)
+ fun jsonToStringPairList(value: String): List> {
+ return try {
+ json.decodeFromString(value)
+ } catch (e: SerializationException) {
+ emptyList() // handle errors from old gson Pair serialized data
+ }
}
+
+ @TypeConverter
+ fun destinationToString(destination: Destination) = json.encodeToString(destination)
+
+ @TypeConverter
+ fun stringToDestination(destination: String): Destination = json.decodeFromString(destination)
+
+ @TypeConverter
+ fun messageTypesToString(types: List): String = json.encodeToString(types)
+
+ @TypeConverter
+ fun stringToMessageTypes(text: String): List = json.decodeFromString(text)
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt b/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt
index 4a4aaf74..4929f046 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/SharedPrefProvider.kt
@@ -6,7 +6,9 @@ import javax.inject.Inject
import javax.inject.Singleton
@Singleton
-class SharedPrefProvider @Inject constructor(private val sharedPref: SharedPreferences) {
+class SharedPrefProvider @Inject constructor(
+ private val sharedPref: SharedPreferences
+) {
companion object {
const val APP_VERSION_CODE_KEY = "app_version_code"
@@ -18,9 +20,18 @@ class SharedPrefProvider @Inject constructor(private val sharedPref: SharedPrefe
fun getLong(key: String, defaultValue: Long) = sharedPref.getLong(key, defaultValue)
- fun getString(key: String, defaultValue: String): String = sharedPref.getString(key, defaultValue) ?: defaultValue
+ fun getString(key: String) = sharedPref.getString(key, null)
- fun putString(key: String, value: String, sync: Boolean = false) {
+ fun getString(key: String, defaultValue: String): String =
+ sharedPref.getString(key, defaultValue) ?: defaultValue
+
+ fun getBoolean(key: String, defaultValue: Boolean): Boolean =
+ sharedPref.getBoolean(key, defaultValue)
+
+ fun putBoolean(key: String, value: Boolean, sync: Boolean = false) =
+ sharedPref.edit(sync) { putBoolean(key, value) }
+
+ fun putString(key: String, value: String?, sync: Boolean = false) {
sharedPref.edit(sync) { putString(key, value) }
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/AdminMessageDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/AdminMessageDao.kt
new file mode 100644
index 00000000..6c8d7e47
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/AdminMessageDao.kt
@@ -0,0 +1,15 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.AdminMessage
+import kotlinx.coroutines.flow.Flow
+import javax.inject.Singleton
+
+@Singleton
+@Dao
+interface AdminMessageDao : BaseDao {
+
+ @Query("SELECT * FROM AdminMessages")
+ fun loadAll(): Flow>
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceDao.kt
index 3eb57473..7d20c9a7 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceDao.kt
@@ -3,14 +3,20 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Attendance
-import io.reactivex.Maybe
-import org.threeten.bp.LocalDate
+import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
+import kotlinx.coroutines.flow.Flow
+import java.time.LocalDate
import javax.inject.Singleton
@Singleton
@Dao
interface AttendanceDao : BaseDao {
- @Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
- fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe>
+ @Query("SELECT * FROM Attendance WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :start AND date <= :end")
+ fun loadAll(
+ diaryId: Int,
+ studentId: Int,
+ start: LocalDate,
+ end: LocalDate
+ ): Flow>
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceSummaryDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceSummaryDao.kt
index fd58533f..4218855c 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceSummaryDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/AttendanceSummaryDao.kt
@@ -3,11 +3,11 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.AttendanceSummary
-import io.reactivex.Maybe
+import kotlinx.coroutines.flow.Flow
@Dao
interface AttendanceSummaryDao : BaseDao {
@Query("SELECT * FROM AttendanceSummary WHERE diary_id = :diaryId AND student_id = :studentId AND subject_id = :subjectId")
- fun loadAll(diaryId: Int, studentId: Int, subjectId: Int): Maybe>
+ fun loadAll(diaryId: Int, studentId: Int, subjectId: Int): Flow>
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/BaseDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/BaseDao.kt
index 32dbadb8..937e9824 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/BaseDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/BaseDao.kt
@@ -2,16 +2,24 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Delete
import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Transaction
import androidx.room.Update
interface BaseDao {
- @Insert
- fun insertAll(items: List): List
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ suspend fun insertAll(items: List): List
@Update
- fun updateAll(items: List)
+ suspend fun updateAll(items: List)
@Delete
- fun deleteAll(items: List)
+ suspend fun deleteAll(items: List)
+
+ @Transaction
+ suspend fun removeOldAndSaveNew(oldItems: List, newItems: List) {
+ deleteAll(oldItems)
+ insertAll(newItems)
+ }
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/CompletedLessonsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/CompletedLessonsDao.kt
index e13e569b..097ad7c8 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/CompletedLessonsDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/CompletedLessonsDao.kt
@@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.CompletedLesson
-import io.reactivex.Maybe
-import org.threeten.bp.LocalDate
+import kotlinx.coroutines.flow.Flow
+import java.time.LocalDate
import javax.inject.Singleton
@Singleton
@@ -12,5 +12,5 @@ import javax.inject.Singleton
interface CompletedLessonsDao : BaseDao {
@Query("SELECT * FROM CompletedLesson WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
- fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe>
+ fun loadAll(studentId: Int, diaryId: Int, from: LocalDate, end: LocalDate): Flow>
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/ConferenceDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/ConferenceDao.kt
new file mode 100644
index 00000000..ca9da9ea
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/ConferenceDao.kt
@@ -0,0 +1,16 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.Conference
+import kotlinx.coroutines.flow.Flow
+import java.time.Instant
+import javax.inject.Singleton
+
+@Dao
+@Singleton
+interface ConferenceDao : BaseDao {
+
+ @Query("SELECT * FROM Conferences WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :startDate")
+ fun loadAll(diaryId: Int, studentId: Int, startDate: Instant): Flow>
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/ExamDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/ExamDao.kt
index ca6b32df..311eeb9c 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/ExamDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/ExamDao.kt
@@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Exam
-import io.reactivex.Maybe
-import org.threeten.bp.LocalDate
+import kotlinx.coroutines.flow.Flow
+import java.time.LocalDate
import javax.inject.Singleton
@Singleton
@@ -12,5 +12,5 @@ import javax.inject.Singleton
interface ExamDao : BaseDao {
@Query("SELECT * FROM Exams WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
- fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe>
+ fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow>
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeDao.kt
index c74d1937..ff332618 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeDao.kt
@@ -3,7 +3,7 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Grade
-import io.reactivex.Maybe
+import kotlinx.coroutines.flow.Flow
import javax.inject.Singleton
@Singleton
@@ -11,6 +11,9 @@ import javax.inject.Singleton
interface GradeDao : BaseDao {
@Query("SELECT * FROM Grades WHERE semester_id = :semesterId AND student_id = :studentId")
- fun loadAll(semesterId: Int, studentId: Int): Maybe>
+ fun loadAll(semesterId: Int, studentId: Int): Flow>
+ @Query("SELECT * FROM Grades WHERE semester_id = :semesterId AND student_id = :studentId " +
+ "AND entry NOT IN(:censoredEntries)")
+ fun loadAllCensored(semesterId: Int, studentId: Int, censoredEntries: Array): Flow>
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeDescriptiveDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeDescriptiveDao.kt
new file mode 100644
index 00000000..6282c080
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeDescriptiveDao.kt
@@ -0,0 +1,15 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.GradeDescriptive
+import kotlinx.coroutines.flow.Flow
+import javax.inject.Singleton
+
+@Singleton
+@Dao
+interface GradeDescriptiveDao : BaseDao {
+
+ @Query("SELECT * FROM GradesDescriptive WHERE semester_id = :semesterId AND student_id = :studentId")
+ fun loadAll(semesterId: Int, studentId: Int): Flow>
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePartialStatisticsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePartialStatisticsDao.kt
new file mode 100644
index 00000000..bce6ce57
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePartialStatisticsDao.kt
@@ -0,0 +1,13 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.GradePartialStatistics
+import kotlinx.coroutines.flow.Flow
+
+@Dao
+interface GradePartialStatisticsDao : BaseDao {
+
+ @Query("SELECT * FROM GradePartialStatistics WHERE student_id = :studentId AND semester_id = :semesterId")
+ fun loadAll(semesterId: Int, studentId: Int): Flow>
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePointsStatisticsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePointsStatisticsDao.kt
index da182866..e8074f00 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePointsStatisticsDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradePointsStatisticsDao.kt
@@ -3,7 +3,7 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.GradePointsStatistics
-import io.reactivex.Maybe
+import kotlinx.coroutines.flow.Flow
import javax.inject.Singleton
@Singleton
@@ -11,8 +11,8 @@ import javax.inject.Singleton
interface GradePointsStatisticsDao : BaseDao {
@Query("SELECT * FROM GradesPointsStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName")
- fun loadSubject(semesterId: Int, studentId: Int, subjectName: String): Maybe>
+ fun loadSubject(semesterId: Int, studentId: Int, subjectName: String): Flow>
@Query("SELECT * FROM GradesPointsStatistics WHERE student_id = :studentId AND semester_id = :semesterId")
- fun loadAll(semesterId: Int, studentId: Int): Maybe>
+ fun loadAll(semesterId: Int, studentId: Int): Flow>
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSemesterStatisticsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSemesterStatisticsDao.kt
new file mode 100644
index 00000000..09ae8171
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSemesterStatisticsDao.kt
@@ -0,0 +1,13 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
+import kotlinx.coroutines.flow.Flow
+
+@Dao
+interface GradeSemesterStatisticsDao : BaseDao {
+
+ @Query("SELECT * FROM GradeSemesterStatistics WHERE student_id = :studentId AND semester_id = :semesterId")
+ fun loadAll(semesterId: Int, studentId: Int): Flow>
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeStatisticsDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeStatisticsDao.kt
deleted file mode 100644
index 6faa35d0..00000000
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeStatisticsDao.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package io.github.wulkanowy.data.db.dao
-
-import androidx.room.Dao
-import androidx.room.Query
-import io.github.wulkanowy.data.db.entities.GradeStatistics
-import io.reactivex.Maybe
-import javax.inject.Singleton
-
-@Singleton
-@Dao
-interface GradeStatisticsDao : BaseDao {
-
- @Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND subject = :subjectName AND is_semester = :isSemester")
- fun loadSubject(semesterId: Int, studentId: Int, subjectName: String, isSemester: Boolean): Maybe>
-
- @Query("SELECT * FROM GradesStatistics WHERE student_id = :studentId AND semester_id = :semesterId AND is_semester = :isSemester")
- fun loadAll(semesterId: Int, studentId: Int, isSemester: Boolean): Maybe>
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSummaryDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSummaryDao.kt
index 1165ef07..fc9ad66e 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSummaryDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/GradeSummaryDao.kt
@@ -3,7 +3,7 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.GradeSummary
-import io.reactivex.Maybe
+import kotlinx.coroutines.flow.Flow
import javax.inject.Singleton
@Singleton
@@ -11,5 +11,5 @@ import javax.inject.Singleton
interface GradeSummaryDao : BaseDao {
@Query("SELECT * FROM GradesSummary WHERE student_id = :studentId AND semester_id = :semesterId")
- fun loadAll(semesterId: Int, studentId: Int): Maybe>
+ fun loadAll(semesterId: Int, studentId: Int): Flow>
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/HomeworkDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/HomeworkDao.kt
index 1947a0df..2092de49 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/HomeworkDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/HomeworkDao.kt
@@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Homework
-import io.reactivex.Maybe
-import org.threeten.bp.LocalDate
+import kotlinx.coroutines.flow.Flow
+import java.time.LocalDate
import javax.inject.Singleton
@Singleton
@@ -12,5 +12,5 @@ import javax.inject.Singleton
interface HomeworkDao : BaseDao {
@Query("SELECT * FROM Homework WHERE semester_id = :semesterId AND student_id = :studentId AND date >= :from AND date <= :end")
- fun loadAll(semesterId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe>
+ fun loadAll(semesterId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow>
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/LuckyNumberDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/LuckyNumberDao.kt
index f16c28d9..d9aa2436 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/LuckyNumberDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/LuckyNumberDao.kt
@@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.LuckyNumber
-import io.reactivex.Maybe
-import org.threeten.bp.LocalDate
+import kotlinx.coroutines.flow.Flow
+import java.time.LocalDate
import javax.inject.Singleton
@Singleton
@@ -12,5 +12,8 @@ import javax.inject.Singleton
interface LuckyNumberDao : BaseDao {
@Query("SELECT * FROM LuckyNumbers WHERE student_id = :studentId AND date = :date")
- fun load(studentId: Int, date: LocalDate): Maybe
+ fun load(studentId: Int, date: LocalDate): Flow
+
+ @Query("SELECT * FROM LuckyNumbers WHERE student_id = :studentId AND date >= :start AND date <= :end")
+ fun getAll(studentId: Int, start: LocalDate, end: LocalDate): Flow>
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/MailboxDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/MailboxDao.kt
new file mode 100644
index 00000000..084192a0
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/MailboxDao.kt
@@ -0,0 +1,18 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.Mailbox
+import kotlinx.coroutines.flow.Flow
+import javax.inject.Singleton
+
+@Singleton
+@Dao
+interface MailboxDao : BaseDao {
+
+ @Query("SELECT * FROM Mailboxes WHERE email = :email")
+ suspend fun loadAll(email: String): List
+
+ @Query("SELECT * FROM Mailboxes WHERE email = :email AND symbol = :symbol AND schoolId = :schoolId")
+ fun loadAll(email: String, symbol: String, schoolId: String): Flow>
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/MessageAttachmentDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/MessageAttachmentDao.kt
index 3c511a27..b69083a1 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/MessageAttachmentDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/MessageAttachmentDao.kt
@@ -9,5 +9,5 @@ import io.github.wulkanowy.data.db.entities.MessageAttachment
interface MessageAttachmentDao : BaseDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
- fun insertAttachments(items: List): List
+ suspend fun insertAttachments(items: List): List
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt
index 7a69e270..11e6da1e 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/MessagesDao.kt
@@ -5,19 +5,26 @@ import androidx.room.Query
import androidx.room.Transaction
import io.github.wulkanowy.data.db.entities.Message
import io.github.wulkanowy.data.db.entities.MessageWithAttachment
-import io.reactivex.Maybe
-import io.reactivex.Single
+import io.github.wulkanowy.data.db.entities.MessageWithMutedAuthor
+import kotlinx.coroutines.flow.Flow
@Dao
interface MessagesDao : BaseDao {
+ @Transaction
+ @Query("SELECT * FROM Messages WHERE message_global_key = :messageGlobalKey")
+ fun loadMessageWithAttachment(messageGlobalKey: String): Flow
@Transaction
- @Query("SELECT * FROM Messages WHERE student_id = :studentId AND message_id = :messageId")
- fun loadMessageWithAttachment(studentId: Int, messageId: Int): Single
+ @Query("SELECT * FROM Messages WHERE mailbox_key = :mailboxKey AND folder_id = :folder ORDER BY date DESC")
+ fun loadMessagesWithMutedAuthor(mailboxKey: String, folder: Int): Flow>
- @Query("SELECT * FROM Messages WHERE student_id = :studentId AND folder_id = :folder AND removed = 0 ORDER BY date DESC")
- fun loadAll(studentId: Int, folder: Int): Maybe>
+ @Transaction
+ @Query("SELECT * FROM Messages WHERE email = :email AND folder_id = :folder ORDER BY date DESC")
+ fun loadMessagesWithMutedAuthor(folder: Int, email: String): Flow>
- @Query("SELECT * FROM Messages WHERE student_id = :studentId AND removed = 1 ORDER BY date DESC")
- fun loadDeleted(studentId: Int): Maybe>
+ @Query("SELECT * FROM Messages WHERE mailbox_key = :mailboxKey AND folder_id = :folder ORDER BY date DESC")
+ fun loadAll(mailboxKey: String, folder: Int): Flow>
+
+ @Query("SELECT * FROM Messages WHERE email = :email AND folder_id = :folder ORDER BY date DESC")
+ fun loadAll(folder: Int, email: String): Flow>
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/MobileDeviceDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/MobileDeviceDao.kt
index b05b2d9c..5ddb4dd0 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/MobileDeviceDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/MobileDeviceDao.kt
@@ -3,11 +3,11 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.MobileDevice
-import io.reactivex.Maybe
+import kotlinx.coroutines.flow.Flow
@Dao
interface MobileDeviceDao : BaseDao {
- @Query("SELECT * FROM MobileDevices WHERE student_id = :studentId ORDER BY date DESC")
- fun loadAll(studentId: Int): Maybe>
+ @Query("SELECT * FROM MobileDevices WHERE user_login_id = :studentId ORDER BY date DESC")
+ fun loadAll(studentId: Int): Flow>
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/MutedMessageSendersDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/MutedMessageSendersDao.kt
new file mode 100644
index 00000000..0a866401
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/MutedMessageSendersDao.kt
@@ -0,0 +1,20 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.MutedMessageSender
+
+@Dao
+interface MutedMessageSendersDao : BaseDao {
+
+ @Query("SELECT COUNT(*) FROM MutedMessageSenders WHERE author = :author")
+ suspend fun checkMute(author: String): Boolean
+
+ @Insert(onConflict = OnConflictStrategy.IGNORE)
+ suspend fun insertMute(mute: MutedMessageSender): Long
+
+ @Query("DELETE FROM MutedMessageSenders WHERE author = :author")
+ suspend fun deleteMute(author: String)
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/NoteDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/NoteDao.kt
index ea2fc6eb..98de5ba3 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/NoteDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/NoteDao.kt
@@ -3,13 +3,12 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Note
-import io.reactivex.Maybe
+import kotlinx.coroutines.flow.Flow
import javax.inject.Singleton
@Singleton
@Dao
interface NoteDao : BaseDao {
-
@Query("SELECT * FROM Notes WHERE student_id = :studentId")
- fun loadAll(studentId: Int): Maybe>
+ fun loadAll(studentId: Int): Flow>
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/NotificationDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/NotificationDao.kt
new file mode 100644
index 00000000..c5ae21bc
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/NotificationDao.kt
@@ -0,0 +1,15 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.Notification
+import kotlinx.coroutines.flow.Flow
+import javax.inject.Singleton
+
+@Singleton
+@Dao
+interface NotificationDao : BaseDao {
+
+ @Query("SELECT * FROM Notifications WHERE student_id = :studentId OR student_id = -1")
+ fun loadAll(studentId: Long): Flow>
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt
index afb941b1..1956261e 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/RecipientDao.kt
@@ -2,14 +2,14 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.MailboxType
import io.github.wulkanowy.data.db.entities.Recipient
-import io.reactivex.Maybe
import javax.inject.Singleton
@Singleton
@Dao
interface RecipientDao : BaseDao {
- @Query("SELECT * FROM Recipients WHERE student_id = :studentId AND role = :role AND unit_id = :unitId")
- fun load(studentId: Int, role: Int, unitId: Int): Maybe>
+ @Query("SELECT * FROM Recipients WHERE type = :type AND studentMailboxGlobalKey = :studentMailboxGlobalKey")
+ suspend fun loadAll(type: MailboxType, studentMailboxGlobalKey: String): List
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/ReportingUnitDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/ReportingUnitDao.kt
deleted file mode 100644
index 6ddfd494..00000000
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/ReportingUnitDao.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package io.github.wulkanowy.data.db.dao
-
-import androidx.room.Dao
-import androidx.room.Query
-import io.github.wulkanowy.data.db.entities.ReportingUnit
-import io.reactivex.Maybe
-import javax.inject.Singleton
-
-@Singleton
-@Dao
-interface ReportingUnitDao : BaseDao {
-
- @Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId")
- fun load(studentId: Int): Maybe>
-
- @Query("SELECT * FROM ReportingUnits WHERE student_id = :studentId AND real_id = :unitId")
- fun loadOne(studentId: Int, unitId: Int): Maybe
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolAnnouncementDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolAnnouncementDao.kt
new file mode 100644
index 00000000..64d49bce
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolAnnouncementDao.kt
@@ -0,0 +1,15 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
+import kotlinx.coroutines.flow.Flow
+import javax.inject.Singleton
+
+@Dao
+@Singleton
+interface SchoolAnnouncementDao : BaseDao {
+
+ @Query("SELECT * FROM SchoolAnnouncements WHERE user_login_id = :studentId ORDER BY date DESC")
+ fun loadAll(studentId: Int): Flow>
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolDao.kt
index e9bd6755..f39791f6 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/SchoolDao.kt
@@ -3,7 +3,7 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.School
-import io.reactivex.Maybe
+import kotlinx.coroutines.flow.Flow
import javax.inject.Singleton
@Singleton
@@ -11,5 +11,5 @@ import javax.inject.Singleton
interface SchoolDao : BaseDao {
@Query("SELECT * FROM School WHERE student_id = :studentId AND class_id = :classId")
- fun load(studentId: Int, classId: Int): Maybe
+ fun load(studentId: Int, classId: Int): Flow
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt
index 654b80f3..bf9a34d0 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/SemesterDao.kt
@@ -1,15 +1,19 @@
package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Semester
-import io.reactivex.Maybe
import javax.inject.Singleton
@Singleton
@Dao
interface SemesterDao : BaseDao {
- @Query("SELECT * FROM Semesters WHERE student_id = :studentId AND class_id = :classId")
- fun loadAll(studentId: Int, classId: Int): Maybe>
+ @Insert(onConflict = OnConflictStrategy.IGNORE)
+ suspend fun insertSemesters(items: List): List
+
+ @Query("SELECT * FROM Semesters WHERE (student_id = :studentId AND class_id = :classId) OR (student_id = :studentId AND class_id = 0)")
+ suspend fun loadAll(studentId: Int, classId: Int): List
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt
index 901ddc73..5302b320 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentDao.kt
@@ -3,34 +3,69 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
-import androidx.room.OnConflictStrategy.ABORT
+import androidx.room.OnConflictStrategy
import androidx.room.Query
+import androidx.room.Transaction
+import androidx.room.Update
+import io.github.wulkanowy.data.db.entities.Semester
import io.github.wulkanowy.data.db.entities.Student
-import io.reactivex.Maybe
+import io.github.wulkanowy.data.db.entities.StudentIsAuthorized
+import io.github.wulkanowy.data.db.entities.StudentIsEduOne
+import io.github.wulkanowy.data.db.entities.StudentName
+import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar
import javax.inject.Singleton
@Singleton
@Dao
-interface StudentDao {
+abstract class StudentDao {
- @Insert(onConflict = ABORT)
- fun insertAll(student: List): List
+ @Insert(onConflict = OnConflictStrategy.ABORT)
+ abstract suspend fun insertAll(student: List): List
@Delete
- fun delete(student: Student)
+ abstract suspend fun delete(student: Student)
+
+ @Update(entity = Student::class)
+ abstract suspend fun update(studentIsAuthorized: StudentIsAuthorized)
+
+ @Update(entity = Student::class)
+ abstract suspend fun update(studentIsEduOne: StudentIsEduOne)
+
+ @Update(entity = Student::class)
+ abstract suspend fun update(studentNickAndAvatar: StudentNickAndAvatar)
+
+ @Update(entity = Student::class)
+ abstract suspend fun update(studentName: StudentName)
@Query("SELECT * FROM Students WHERE is_current = 1")
- fun loadCurrent(): Maybe
+ abstract suspend fun loadCurrent(): Student?
@Query("SELECT * FROM Students WHERE id = :id")
- fun loadById(id: Int): Maybe
+ abstract suspend fun loadById(id: Long): Student?
@Query("SELECT * FROM Students")
- fun loadAll(): Maybe>
+ abstract suspend fun loadAll(): List
+
+ @Transaction
+ @Query("SELECT * FROM Students JOIN Semesters ON (Students.student_id = Semesters.student_id AND Students.class_id = Semesters.class_id) OR (Students.student_id = Semesters.student_id AND Semesters.class_id = 0)")
+ abstract suspend fun loadStudentsWithSemesters(): Map>
+
+ @Transaction
+ @Query("SELECT * FROM Students JOIN Semesters ON (Students.student_id = Semesters.student_id AND Students.class_id = Semesters.class_id) OR (Students.student_id = Semesters.student_id AND Semesters.class_id = 0) WHERE Students.id = :id")
+ abstract suspend fun loadStudentWithSemestersById(id: Long): Map>
@Query("UPDATE Students SET is_current = 1 WHERE id = :id")
- fun updateCurrent(id: Long)
+ abstract suspend fun updateCurrent(id: Long)
@Query("UPDATE Students SET is_current = 0")
- fun resetCurrent()
+ abstract suspend fun resetCurrent()
+
+ @Query("DELETE FROM Students WHERE email = :email AND user_name = :userName")
+ abstract suspend fun deleteByEmailAndUserName(email: String, userName: String)
+
+ @Transaction
+ open suspend fun switchCurrent(id: Long) {
+ resetCurrent()
+ updateCurrent(id)
+ }
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentInfoDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentInfoDao.kt
new file mode 100644
index 00000000..5ec86af1
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/StudentInfoDao.kt
@@ -0,0 +1,15 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.StudentInfo
+import kotlinx.coroutines.flow.Flow
+import javax.inject.Singleton
+
+@Singleton
+@Dao
+interface StudentInfoDao : BaseDao {
+
+ @Query("SELECT * FROM StudentInfo WHERE student_id = :studentId")
+ fun loadStudentInfo(studentId: Int): Flow
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/SubjectDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/SubjectDao.kt
index 525a7129..4cd742b5 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/SubjectDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/SubjectDao.kt
@@ -3,11 +3,11 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Subject
-import io.reactivex.Maybe
+import kotlinx.coroutines.flow.Flow
@Dao
interface SubjectDao : BaseDao {
@Query("SELECT * FROM Subjects WHERE diary_id = :diaryId AND student_id = :studentId")
- fun loadAll(diaryId: Int, studentId: Int): Maybe>
+ fun loadAll(diaryId: Int, studentId: Int): Flow>
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/TeacherDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/TeacherDao.kt
index 5ea237a8..6adac220 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/TeacherDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/TeacherDao.kt
@@ -3,7 +3,7 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Teacher
-import io.reactivex.Maybe
+import kotlinx.coroutines.flow.Flow
import javax.inject.Singleton
@Singleton
@@ -11,5 +11,5 @@ import javax.inject.Singleton
interface TeacherDao : BaseDao {
@Query("SELECT * FROM Teachers WHERE student_id = :studentId AND class_id = :classId")
- fun loadAll(studentId: Int, classId: Int): Maybe>
+ fun loadAll(studentId: Int, classId: Int): Flow>
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableAdditionalDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableAdditionalDao.kt
new file mode 100644
index 00000000..914ce340
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableAdditionalDao.kt
@@ -0,0 +1,25 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.TimetableAdditional
+import kotlinx.coroutines.flow.Flow
+import java.time.LocalDate
+import java.util.UUID
+import javax.inject.Singleton
+
+@Dao
+@Singleton
+interface TimetableAdditionalDao : BaseDao {
+
+ @Query("SELECT * FROM TimetableAdditional WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
+ fun loadAll(
+ diaryId: Int,
+ studentId: Int,
+ from: LocalDate,
+ end: LocalDate
+ ): Flow>
+
+ @Query("DELETE FROM TimetableAdditional WHERE repeat_id = :repeatId")
+ suspend fun deleteAllByRepeatId(repeatId: UUID)
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableDao.kt
index 6b62cc82..40d97ea9 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableDao.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableDao.kt
@@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.dao
import androidx.room.Dao
import androidx.room.Query
import io.github.wulkanowy.data.db.entities.Timetable
-import io.reactivex.Maybe
-import org.threeten.bp.LocalDate
+import kotlinx.coroutines.flow.Flow
+import java.time.LocalDate
import javax.inject.Singleton
@Singleton
@@ -12,5 +12,8 @@ import javax.inject.Singleton
interface TimetableDao : BaseDao {
@Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
- fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Maybe>
+ fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow>
+
+ @Query("SELECT * FROM Timetable WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
+ suspend fun load(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): List
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableHeaderDao.kt b/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableHeaderDao.kt
new file mode 100644
index 00000000..916d1901
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/dao/TimetableHeaderDao.kt
@@ -0,0 +1,16 @@
+package io.github.wulkanowy.data.db.dao
+
+import androidx.room.Dao
+import androidx.room.Query
+import io.github.wulkanowy.data.db.entities.TimetableHeader
+import kotlinx.coroutines.flow.Flow
+import java.time.LocalDate
+import javax.inject.Singleton
+
+@Dao
+@Singleton
+interface TimetableHeaderDao : BaseDao {
+
+ @Query("SELECT * FROM TimetableHeaders WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
+ fun loadAll(diaryId: Int, studentId: Int, from: LocalDate, end: LocalDate): Flow>
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/AdminMessage.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/AdminMessage.kt
new file mode 100644
index 00000000..a8604c5c
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/AdminMessage.kt
@@ -0,0 +1,49 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import io.github.wulkanowy.data.enums.MessageType
+import io.github.wulkanowy.data.serializers.SafeMessageTypeEnumListSerializer
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+@Entity(tableName = "AdminMessages")
+data class AdminMessage(
+
+ @PrimaryKey
+ val id: Int,
+
+ val title: String,
+
+ val content: String,
+
+ @ColumnInfo(name = "version_name")
+ val versionMin: Int? = null,
+
+ @ColumnInfo(name = "version_max")
+ val versionMax: Int? = null,
+
+ @ColumnInfo(name = "target_register_host")
+ val targetRegisterHost: String? = null,
+
+ @ColumnInfo(name = "target_flavor")
+ val targetFlavor: String? = null,
+
+ @ColumnInfo(name = "destination_url")
+ val destinationUrl: String? = null,
+
+ val priority: String,
+
+ @SerialName("messageTypes")
+ @Serializable(with = SafeMessageTypeEnumListSerializer::class)
+ @ColumnInfo(name = "types", defaultValue = "[]")
+ val types: List = emptyList(),
+
+ @ColumnInfo(name = "is_ok_visible", defaultValue = "0")
+ val isOkVisible: Boolean = false,
+
+ @ColumnInfo(name = "is_x_visible", defaultValue = "0")
+ val isXVisible: Boolean = false
+)
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Attendance.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Attendance.kt
index aa8da8db..b40dd52e 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Attendance.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Attendance.kt
@@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
-import org.threeten.bp.LocalDate
import java.io.Serializable
+import java.time.LocalDate
@Entity(tableName = "Attendance")
data class Attendance(
@@ -47,4 +47,7 @@ data class Attendance(
@PrimaryKey(autoGenerate = true)
var id: Long = 0
+
+ @ColumnInfo(name = "is_notified")
+ var isNotified: Boolean = true
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/AttendanceSummary.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/AttendanceSummary.kt
index d2e1f174..7d628eba 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/AttendanceSummary.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/AttendanceSummary.kt
@@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
-import org.threeten.bp.Month
import java.io.Serializable
+import java.time.Month
@Entity(tableName = "AttendanceSummary")
data class AttendanceSummary(
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/CompletedLesson.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/CompletedLesson.kt
index 775f3f55..e305d467 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/CompletedLesson.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/CompletedLesson.kt
@@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
-import org.threeten.bp.LocalDate
import java.io.Serializable
+import java.time.LocalDate
@Entity(tableName = "CompletedLesson")
data class CompletedLesson(
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Conference.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Conference.kt
new file mode 100644
index 00000000..ba3958db
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Conference.kt
@@ -0,0 +1,38 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import java.io.Serializable
+import java.time.Instant
+
+@Entity(tableName = "Conferences")
+data class Conference(
+
+ @ColumnInfo(name = "student_id")
+ val studentId: Int,
+
+ @ColumnInfo(name = "diary_id")
+ val diaryId: Int,
+
+ val title: String,
+
+ val subject: String,
+
+ val agenda: String,
+
+ @ColumnInfo(name = "present_on_conference")
+ val presentOnConference: String,
+
+ @ColumnInfo(name = "conference_id")
+ val conferenceId: Int,
+
+ val date: Instant,
+) : Serializable {
+
+ @PrimaryKey(autoGenerate = true)
+ var id: Long = 0
+
+ @ColumnInfo(name = "is_notified")
+ var isNotified: Boolean = true
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Exam.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Exam.kt
index 9ae795e7..2292c3e6 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Exam.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Exam.kt
@@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
-import org.threeten.bp.LocalDate
import java.io.Serializable
+import java.time.LocalDate
@Entity(tableName = "Exams")
data class Exam(
@@ -22,6 +22,7 @@ data class Exam(
val subject: String,
+ @Deprecated("not available anymore")
val group: String,
val type: String,
@@ -36,4 +37,7 @@ data class Exam(
@PrimaryKey(autoGenerate = true)
var id: Long = 0
+
+ @ColumnInfo(name = "is_notified")
+ var isNotified: Boolean = true
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Grade.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Grade.kt
index 3f69c61b..a0f1c3a6 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Grade.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Grade.kt
@@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
-import org.threeten.bp.LocalDate
import java.io.Serializable
+import java.time.LocalDate
@Entity(tableName = "Grades")
data class Grade(
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeStatistics.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeDescriptive.kt
similarity index 61%
rename from app/src/main/java/io/github/wulkanowy/data/db/entities/GradeStatistics.kt
rename to app/src/main/java/io/github/wulkanowy/data/db/entities/GradeDescriptive.kt
index 8ad8b8b8..9aec9599 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeStatistics.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeDescriptive.kt
@@ -3,25 +3,25 @@ package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
+import java.io.Serializable
-@Entity(tableName = "GradesStatistics")
-data class GradeStatistics(
-
- @ColumnInfo(name = "student_id")
- val studentId: Int,
+@Entity(tableName = "GradesDescriptive")
+data class GradeDescriptive(
@ColumnInfo(name = "semester_id")
val semesterId: Int,
+ @ColumnInfo(name = "student_id")
+ val studentId: Int,
+
val subject: String,
- val grade: Int,
+ val description: String,
+) : Serializable {
- val amount: Int,
-
- @ColumnInfo(name = "is_semester")
- val semester: Boolean
-) {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
+
+ @ColumnInfo(name = "is_notified")
+ var isNotified: Boolean = true
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradePartialStatistics.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradePartialStatistics.kt
new file mode 100644
index 00000000..db164afd
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradePartialStatistics.kt
@@ -0,0 +1,33 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "GradePartialStatistics")
+data class GradePartialStatistics(
+
+ @ColumnInfo(name = "student_id")
+ val studentId: Int,
+
+ @ColumnInfo(name = "semester_id")
+ val semesterId: Int,
+
+ val subject: String,
+
+ @ColumnInfo(name = "class_average")
+ val classAverage: String,
+
+ @ColumnInfo(name = "student_average")
+ val studentAverage: String,
+
+ @ColumnInfo(name = "class_amounts")
+ val classAmounts: List,
+
+ @ColumnInfo(name = "student_amounts")
+ val studentAmounts: List
+
+) {
+ @PrimaryKey(autoGenerate = true)
+ var id: Long = 0
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeSemesterStatistics.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeSemesterStatistics.kt
new file mode 100644
index 00000000..9e08b86b
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeSemesterStatistics.kt
@@ -0,0 +1,31 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "GradeSemesterStatistics")
+data class GradeSemesterStatistics(
+
+ @ColumnInfo(name = "student_id")
+ val studentId: Int,
+
+ @ColumnInfo(name = "semester_id")
+ val semesterId: Int,
+
+ val subject: String,
+
+ val amounts: List,
+
+ @ColumnInfo(name = "student_grade")
+ val studentGrade: Int
+) {
+ @PrimaryKey(autoGenerate = true)
+ var id: Long = 0
+
+ @Transient
+ var classAverage: String = ""
+
+ @Transient
+ var studentAverage: String = ""
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeSummary.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeSummary.kt
index 6e29112b..f8a357a3 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeSummary.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/GradeSummary.kt
@@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
+import java.time.Instant
@Entity(tableName = "GradesSummary")
data class GradeSummary(
@@ -32,8 +33,26 @@ data class GradeSummary(
@ColumnInfo(name = "points_sum")
val pointsSum: String,
- val average: Double
+ @ColumnInfo(name = "points_sum_all_year")
+ val pointsSumAllYear: String?,
+
+ val average: Double,
+
+ @ColumnInfo(name = "average_all_year")
+ val averageAllYear: Double? = null,
) {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
+
+ @ColumnInfo(name = "is_predicted_grade_notified")
+ var isPredictedGradeNotified: Boolean = true
+
+ @ColumnInfo(name = "is_final_grade_notified")
+ var isFinalGradeNotified: Boolean = true
+
+ @ColumnInfo(name = "predicted_grade_last_change")
+ var predictedGradeLastChange: Instant = Instant.now()
+
+ @ColumnInfo(name = "final_grade_last_change")
+ var finalGradeLastChange: Instant = Instant.now()
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Homework.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Homework.kt
index cd7d153e..4538cf31 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Homework.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Homework.kt
@@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
-import org.threeten.bp.LocalDate
import java.io.Serializable
+import java.time.LocalDate
@Entity(tableName = "Homework")
data class Homework(
@@ -37,4 +37,10 @@ data class Homework(
@ColumnInfo(name = "is_done")
var isDone: Boolean = false
+
+ @ColumnInfo(name = "is_notified")
+ var isNotified: Boolean = true
+
+ @ColumnInfo(name = "is_added_by_user")
+ var isAddedByUser: Boolean = false
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/LuckyNumber.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/LuckyNumber.kt
index 5b9130f5..7c24c8f5 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/LuckyNumber.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/LuckyNumber.kt
@@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
-import org.threeten.bp.LocalDate
import java.io.Serializable
+import java.time.LocalDate
@Entity(tableName = "LuckyNumbers")
data class LuckyNumber (
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Mailbox.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Mailbox.kt
new file mode 100644
index 00000000..e65e213d
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Mailbox.kt
@@ -0,0 +1,32 @@
+package io.github.wulkanowy.data.db.entities
+
+import android.os.Parcelable
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+@Entity(tableName = "Mailboxes")
+data class Mailbox(
+
+ @PrimaryKey
+ val globalKey: String,
+
+ val email: String,
+ val symbol: String,
+ val schoolId: String,
+
+ val fullName: String,
+ val userName: String,
+ val studentName: String,
+ val schoolNameShort: String,
+ val type: MailboxType,
+) : java.io.Serializable, Parcelable
+
+enum class MailboxType {
+ STUDENT,
+ PARENT,
+ GUARDIAN,
+ EMPLOYEE,
+ UNKNOWN,
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Message.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Message.kt
index 05829841..d1356b33 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Message.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Message.kt
@@ -3,48 +3,40 @@ package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
-import org.threeten.bp.LocalDateTime
import java.io.Serializable
+import java.time.Instant
@Entity(tableName = "Messages")
data class Message(
- @ColumnInfo(name = "student_id")
- val studentId: Int,
+ @ColumnInfo(name = "email")
+ val email: String,
- @ColumnInfo(name = "real_id")
- val realId: Int,
+ @ColumnInfo(name = "message_global_key")
+ val messageGlobalKey: String,
+
+ @ColumnInfo(name = "mailbox_key")
+ val mailboxKey: String,
@ColumnInfo(name = "message_id")
val messageId: Int,
- @ColumnInfo(name = "sender_name")
- val sender: String,
-
- @ColumnInfo(name = "sender_id")
- val senderId: Int,
-
- @ColumnInfo(name = "recipient_name")
- val recipient: String,
+ val correspondents: String,
val subject: String,
- var content: String,
-
- val date: LocalDateTime,
+ val date: Instant,
@ColumnInfo(name = "folder_id")
val folderId: Int,
var unread: Boolean,
- @ColumnInfo(name = "unread_by")
- val unreadBy: Int,
-
@ColumnInfo(name = "read_by")
- val readBy: Int,
+ val readBy: Int?,
- val removed: Boolean,
+ @ColumnInfo(name = "unread_by")
+ val unreadBy: Int?,
@ColumnInfo(name = "has_attachments")
val hasAttachments: Boolean
@@ -55,4 +47,8 @@ data class Message(
@ColumnInfo(name = "is_notified")
var isNotified: Boolean = true
+
+ var content: String = ""
+ var sender: String? = null
+ var recipients: String? = null
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt
index d1886e91..6f0c84ad 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageAttachment.kt
@@ -2,21 +2,16 @@ package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
-import androidx.room.PrimaryKey
import java.io.Serializable
-@Entity(tableName = "MessageAttachments")
+@Entity(
+ tableName = "MessageAttachments",
+ primaryKeys = ["message_global_key", "url", "filename"],
+)
data class MessageAttachment(
- @PrimaryKey
- @ColumnInfo(name = "real_id")
- val realId: Int,
-
- @ColumnInfo(name = "message_id")
- val messageId: Int,
-
- @ColumnInfo(name = "one_drive_id")
- val oneDriveId: String,
+ @ColumnInfo(name = "message_global_key")
+ val messageGlobalKey: String,
@ColumnInfo(name = "url")
val url: String,
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithAttachment.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithAttachment.kt
index 2e7af0f4..fc890e76 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithAttachment.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithAttachment.kt
@@ -2,11 +2,15 @@ package io.github.wulkanowy.data.db.entities
import androidx.room.Embedded
import androidx.room.Relation
+import java.io.Serializable
data class MessageWithAttachment(
@Embedded
val message: Message,
- @Relation(parentColumn = "message_id", entityColumn = "message_id")
- val attachments: List
-)
+ @Relation(parentColumn = "message_global_key", entityColumn = "message_global_key")
+ val attachments: List,
+
+ @Relation(parentColumn = "correspondents", entityColumn = "author")
+ val mutedMessageSender: MutedMessageSender?,
+) : Serializable
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithMutedAuthor.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithMutedAuthor.kt
new file mode 100644
index 00000000..e3cd1ca7
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/MessageWithMutedAuthor.kt
@@ -0,0 +1,12 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.Embedded
+import androidx.room.Relation
+
+data class MessageWithMutedAuthor(
+ @Embedded
+ val message: Message,
+
+ @Relation(parentColumn = "correspondents", entityColumn = "author")
+ val mutedMessageSender: MutedMessageSender?,
+)
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MobileDevice.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MobileDevice.kt
index f67ed599..44e90064 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/MobileDevice.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/MobileDevice.kt
@@ -3,13 +3,13 @@ package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
-import org.threeten.bp.LocalDateTime
import java.io.Serializable
+import java.time.Instant
@Entity(tableName = "MobileDevices")
data class MobileDevice(
- @ColumnInfo(name = "student_id")
+ @ColumnInfo(name = "user_login_id") // todo: change column name
val studentId: Int,
@ColumnInfo(name = "device_id")
@@ -17,7 +17,7 @@ data class MobileDevice(
val name: String,
- val date: LocalDateTime
+ val date: Instant,
) : Serializable {
@PrimaryKey(autoGenerate = true)
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/MutedMessageSender.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/MutedMessageSender.kt
new file mode 100644
index 00000000..f1770e64
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/MutedMessageSender.kt
@@ -0,0 +1,15 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import java.io.Serializable
+
+@Entity(tableName = "MutedMessageSenders")
+data class MutedMessageSender(
+ @ColumnInfo(name = "author")
+ val author: String,
+) : Serializable {
+ @PrimaryKey(autoGenerate = true)
+ var id: Long = 0
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Note.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Note.kt
index 6f707a66..cfd54962 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Note.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Note.kt
@@ -3,8 +3,8 @@ package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
-import org.threeten.bp.LocalDate
import java.io.Serializable
+import java.time.LocalDate
@Entity(tableName = "Notes")
data class Note(
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Notification.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Notification.kt
new file mode 100644
index 00000000..c3267f24
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Notification.kt
@@ -0,0 +1,31 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import io.github.wulkanowy.services.sync.notifications.NotificationType
+import io.github.wulkanowy.ui.modules.Destination
+import java.time.Instant
+
+@Entity(tableName = "Notifications")
+data class Notification(
+
+ @ColumnInfo(name = "student_id")
+ val studentId: Long,
+
+ val title: String,
+
+ val content: String,
+
+ val type: NotificationType,
+
+ @ColumnInfo(defaultValue = "{\"type\":\"io.github.wulkanowy.ui.modules.Destination.Dashboard\"}")
+ val destination: Destination,
+
+ val date: Instant,
+
+ val data: String? = null
+) {
+ @PrimaryKey(autoGenerate = true)
+ var id: Long = 0
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt
index 3021da72..d09742cd 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Recipient.kt
@@ -1,38 +1,22 @@
package io.github.wulkanowy.data.db.entities
-import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.io.Serializable
+@kotlinx.serialization.Serializable
@Entity(tableName = "Recipients")
data class Recipient(
-
- @ColumnInfo(name = "student_id")
- val studentId: Int,
-
- @ColumnInfo(name = "real_id")
- val realId: String,
-
- val name: String,
-
- @ColumnInfo(name = "real_name")
- val realName: String,
-
- @ColumnInfo(name = "login_id")
- val loginId: Int,
-
- @ColumnInfo(name = "unit_id")
- val unitId: Int,
-
- val role: Int,
-
- val hash: String
-
+ val mailboxGlobalKey: String,
+ val studentMailboxGlobalKey: String,
+ val fullName: String,
+ val userName: String,
+ val schoolShortName: String,
+ val type: MailboxType,
) : Serializable {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
- override fun toString() = name
+ override fun toString() = userName
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/ReportingUnit.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/ReportingUnit.kt
deleted file mode 100644
index 601d8aac..00000000
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/ReportingUnit.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package io.github.wulkanowy.data.db.entities
-
-import androidx.room.ColumnInfo
-import androidx.room.Entity
-import androidx.room.PrimaryKey
-import java.io.Serializable
-
-@Entity(tableName = "ReportingUnits")
-data class ReportingUnit(
-
- @ColumnInfo(name = "student_id")
- val studentId: Int,
-
- @ColumnInfo(name = "real_id")
- val realId: Int,
-
- @ColumnInfo(name = "short")
- val shortName: String,
-
- @ColumnInfo(name = "sender_id")
- val senderId: Int,
-
- @ColumnInfo(name = "sender_name")
- val senderName: String,
-
- val roles: List
-
-) : Serializable {
-
- @PrimaryKey(autoGenerate = true)
- var id: Long = 0
-}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/SchoolAnnouncement.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/SchoolAnnouncement.kt
new file mode 100644
index 00000000..814a3c8d
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/SchoolAnnouncement.kt
@@ -0,0 +1,29 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import java.io.Serializable
+import java.time.LocalDate
+
+@Entity(tableName = "SchoolAnnouncements")
+data class SchoolAnnouncement(
+
+ @ColumnInfo(name = "user_login_id") // todo: change column name
+ val studentId: Int,
+
+ val date: LocalDate,
+
+ val subject: String,
+
+ val content: String,
+
+ val author: String? = null,
+) : Serializable {
+
+ @PrimaryKey(autoGenerate = true)
+ var id: Long = 0
+
+ @ColumnInfo(name = "is_notified")
+ var isNotified: Boolean = true
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Semester.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Semester.kt
index 0641e0b6..187890c9 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Semester.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Semester.kt
@@ -4,9 +4,15 @@ import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
-import org.threeten.bp.LocalDate
+import java.io.Serializable
+import java.time.LocalDate
-@Entity(tableName = "Semesters", indices = [Index(value = ["student_id", "diary_id", "semester_id"], unique = true)])
+@Entity(
+ tableName = "Semesters", indices = [Index(
+ value = ["student_id", "diary_id", "kindergarten_diary_id", "semester_id"],
+ unique = true
+ )]
+)
data class Semester(
@ColumnInfo(name = "student_id")
@@ -15,6 +21,9 @@ data class Semester(
@ColumnInfo(name = "diary_id")
val diaryId: Int,
+ @ColumnInfo(name = "kindergarten_diary_id", defaultValue = "0")
+ val kindergartenDiaryId: Int,
+
@ColumnInfo(name = "diary_name")
val diaryName: String,
@@ -36,12 +45,11 @@ data class Semester(
@ColumnInfo(name = "unit_id")
val unitId: Int
-) {
+) : Serializable {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
-
@ColumnInfo(name = "is_current")
var current: Boolean = false
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt
index 905979f9..0300506a 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Student.kt
@@ -4,15 +4,24 @@ import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
-import org.threeten.bp.LocalDateTime
import java.io.Serializable
+import java.time.Instant
-@Entity(tableName = "Students", indices = [Index(value = ["email", "symbol", "student_id", "school_id", "class_id"], unique = true)])
+@Entity(
+ tableName = "Students",
+ indices = [Index(
+ value = ["email", "symbol", "student_id", "school_id", "class_id"],
+ unique = true
+ )]
+)
data class Student(
@ColumnInfo(name = "scrapper_base_url")
val scrapperBaseUrl: String,
+ @ColumnInfo(name = "scrapper_domain_suffix", defaultValue = "")
+ val scrapperDomainSuffix: String,
+
@ColumnInfo(name = "mobile_base_url")
val mobileBaseUrl: String,
@@ -40,16 +49,20 @@ data class Student(
@ColumnInfo(name = "student_id")
val studentId: Int,
+ @Deprecated("not available in VULCAN anymore")
@ColumnInfo(name = "user_login_id")
val userLoginId: Int,
+ @ColumnInfo(name = "user_name")
+ val userName: String,
+
@ColumnInfo(name = "student_name")
val studentName: String,
@ColumnInfo(name = "school_id")
val schoolSymbol: String,
- @ColumnInfo(name ="school_short")
+ @ColumnInfo(name = "school_short")
val schoolShortName: String,
@ColumnInfo(name = "school_name")
@@ -65,9 +78,40 @@ data class Student(
val isCurrent: Boolean,
@ColumnInfo(name = "registration_date")
- val registrationDate: LocalDateTime
+ val registrationDate: Instant,
+
+ @ColumnInfo(name = "is_authorized", defaultValue = "0")
+ val isAuthorized: Boolean,
+
+ @ColumnInfo(name = "is_edu_one", defaultValue = "NULL")
+ val isEduOne: Boolean?,
+
) : Serializable {
@PrimaryKey(autoGenerate = true)
var id: Long = 0
+
+ var nick = ""
+
+ @ColumnInfo(name = "avatar_color")
+ var avatarColor = 0L
}
+
+@Entity
+data class StudentIsAuthorized(
+
+ @PrimaryKey
+ var id: Long,
+
+ @ColumnInfo(name = "is_authorized", defaultValue = "NULL")
+ val isAuthorized: Boolean?,
+) : Serializable
+
+@Entity
+data class StudentIsEduOne(
+ @PrimaryKey
+ var id: Long,
+
+ @ColumnInfo(name = "is_edu_one", defaultValue = "NULL")
+ val isEduOne: Boolean?,
+) : Serializable
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentInfo.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentInfo.kt
new file mode 100644
index 00000000..7366e547
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentInfo.kt
@@ -0,0 +1,85 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Embedded
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import io.github.wulkanowy.data.enums.Gender
+import java.io.Serializable
+import java.time.LocalDate
+
+@Entity(tableName = "StudentInfo")
+data class StudentInfo(
+
+ @ColumnInfo(name = "student_id")
+ val studentId: Int,
+
+ @ColumnInfo(name = "full_name")
+ val fullName: String,
+
+ @ColumnInfo(name = "first_name")
+ val firstName: String,
+
+ @ColumnInfo(name = "second_name")
+ val secondName: String,
+
+ val surname: String,
+
+ @ColumnInfo(name = "birth_date")
+ val birthDate: LocalDate,
+
+ @ColumnInfo(name = "birth_place")
+ val birthPlace: String,
+
+ val gender: Gender,
+
+ @ColumnInfo(name = "has_polish_citizenship")
+ val hasPolishCitizenship: Boolean,
+
+ @ColumnInfo(name = "family_name")
+ val familyName: String,
+
+ @ColumnInfo(name = "parents_names")
+ val parentsNames: String,
+
+ val address: String,
+
+ @ColumnInfo(name = "registered_address")
+ val registeredAddress: String,
+
+ @ColumnInfo(name = "correspondence_address")
+ val correspondenceAddress: String,
+
+ @ColumnInfo(name = "phone_number")
+ val phoneNumber: String,
+
+ @ColumnInfo(name = "cell_phone_number")
+ val cellPhoneNumber: String,
+
+ val email: String,
+
+ @Embedded(prefix = "first_guardian_")
+ val firstGuardian: StudentGuardian?,
+
+ @Embedded(prefix = "second_guardian_")
+ val secondGuardian: StudentGuardian?
+
+) : Serializable {
+
+ @PrimaryKey(autoGenerate = true)
+ var id: Long = 0
+}
+
+data class StudentGuardian(
+
+ @ColumnInfo(name = "full_name")
+ val fullName: String,
+
+ val kinship: String,
+
+ val address: String,
+
+ val phones: String,
+
+ val email: String
+) : Serializable
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentName.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentName.kt
new file mode 100644
index 00000000..46f754b5
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentName.kt
@@ -0,0 +1,18 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import java.io.Serializable
+
+@Entity
+data class StudentName(
+
+ @ColumnInfo(name = "student_name")
+ val studentName: String
+
+) : Serializable {
+
+ @PrimaryKey
+ var id: Long = 0
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentNickAndAvatar.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentNickAndAvatar.kt
new file mode 100644
index 00000000..546059ee
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentNickAndAvatar.kt
@@ -0,0 +1,20 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import java.io.Serializable
+
+@Entity
+data class StudentNickAndAvatar(
+
+ val nick: String,
+
+ @ColumnInfo(name = "avatar_color")
+ var avatarColor: Long
+
+) : Serializable {
+
+ @PrimaryKey
+ var id: Long = 0
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentWithSemesters.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentWithSemesters.kt
new file mode 100644
index 00000000..f9869d4e
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/StudentWithSemesters.kt
@@ -0,0 +1,8 @@
+package io.github.wulkanowy.data.db.entities
+
+import java.io.Serializable
+
+data class StudentWithSemesters(
+ val student: Student,
+ val semesters: List
+) : Serializable
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/Timetable.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/Timetable.kt
index cad3b7c6..d23d388f 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/entities/Timetable.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/Timetable.kt
@@ -3,9 +3,9 @@ package io.github.wulkanowy.data.db.entities
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
-import org.threeten.bp.LocalDate
-import org.threeten.bp.LocalDateTime
import java.io.Serializable
+import java.time.Instant
+import java.time.LocalDate
@Entity(tableName = "Timetable")
data class Timetable(
@@ -18,9 +18,9 @@ data class Timetable(
val number: Int,
- val start: LocalDateTime,
+ val start: Instant,
- val end: LocalDateTime,
+ val end: Instant,
val date: LocalDate,
@@ -50,4 +50,7 @@ data class Timetable(
@PrimaryKey(autoGenerate = true)
var id: Long = 0
+
+ @ColumnInfo(name = "is_notified")
+ var isNotified: Boolean = true
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/TimetableAdditional.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/TimetableAdditional.kt
new file mode 100644
index 00000000..47802610
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/TimetableAdditional.kt
@@ -0,0 +1,37 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import java.io.Serializable
+import java.time.Instant
+import java.time.LocalDate
+import java.util.*
+
+@Entity(tableName = "TimetableAdditional")
+data class TimetableAdditional(
+
+ @ColumnInfo(name = "student_id")
+ val studentId: Int,
+
+ @ColumnInfo(name = "diary_id")
+ val diaryId: Int,
+
+ val start: Instant,
+
+ val end: Instant,
+
+ val date: LocalDate,
+
+ val subject: String,
+) : Serializable {
+
+ @PrimaryKey(autoGenerate = true)
+ var id: Long = 0
+
+ @ColumnInfo(name = "repeat_id", defaultValue = "NULL")
+ var repeatId: UUID? = null
+
+ @ColumnInfo(name = "is_added_by_user", defaultValue = "0")
+ var isAddedByUser: Boolean = false
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/entities/TimetableHeader.kt b/app/src/main/java/io/github/wulkanowy/data/db/entities/TimetableHeader.kt
new file mode 100644
index 00000000..7f21bf54
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/entities/TimetableHeader.kt
@@ -0,0 +1,25 @@
+package io.github.wulkanowy.data.db.entities
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import java.io.Serializable
+import java.time.LocalDate
+
+@Entity(tableName = "TimetableHeaders")
+data class TimetableHeader(
+
+ @ColumnInfo(name = "student_id")
+ val studentId: Int,
+
+ @ColumnInfo(name = "diary_id")
+ val diaryId: Int,
+
+ val date: LocalDate,
+
+ val content: String,
+) : Serializable {
+
+ @PrimaryKey(autoGenerate = true)
+ var id: Long = 0
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration10.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration10.kt
index c26a02d1..0e7e1409 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration10.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration10.kt
@@ -5,7 +5,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration10 : Migration(9, 10) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("ALTER TABLE Grades_Summary RENAME TO GradesSummary")
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE Grades_Summary RENAME TO GradesSummary")
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration11.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration11.kt
index 6d129bca..342e2e2e 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration11.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration11.kt
@@ -5,8 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration11 : Migration(10, 11) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("""
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS Grades_temp (
id INTEGER PRIMARY KEY NOT NULL,
is_read INTEGER NOT NULL,
@@ -26,9 +27,10 @@ class Migration11 : Migration(10, 11) {
date INTEGER NOT NULL,
teacher TEXT NOT NULL
)
- """)
- database.execSQL("INSERT INTO Grades_temp SELECT * FROM Grades")
- database.execSQL("DROP TABLE Grades")
- database.execSQL("ALTER TABLE Grades_temp RENAME TO Grades")
+ """
+ )
+ db.execSQL("INSERT INTO Grades_temp SELECT * FROM Grades")
+ db.execSQL("DROP TABLE Grades")
+ db.execSQL("ALTER TABLE Grades_temp RENAME TO Grades")
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration12.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration12.kt
index 1dc38e14..6cc72695 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration12.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration12.kt
@@ -5,16 +5,17 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration12 : Migration(11, 12) {
- override fun migrate(database: SupportSQLiteDatabase) {
- createTempStudentsTable(database)
- replaceStudentTable(database)
- updateStudentsWithClassId(database, getStudentsIds(database))
- removeStudentsWithNoClassId(database)
- ensureThereIsOnlyOneCurrentStudent(database)
+ override fun migrate(db: SupportSQLiteDatabase) {
+ createTempStudentsTable(db)
+ replaceStudentTable(db)
+ updateStudentsWithClassId(db, getStudentsIds(db))
+ removeStudentsWithNoClassId(db)
+ ensureThereIsOnlyOneCurrentStudent(db)
}
- private fun createTempStudentsTable(database: SupportSQLiteDatabase) {
- database.execSQL("""
+ private fun createTempStudentsTable(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS Students_tmp (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
endpoint TEXT NOT NULL,
@@ -30,40 +31,43 @@ class Migration12 : Migration(11, 12) {
registration_date INTEGER NOT NULL,
class_id INTEGER NOT NULL
)
- """)
- database.execSQL("CREATE UNIQUE INDEX index_Students_email_symbol_student_id_school_id_class_id ON Students_tmp (email, symbol, student_id, school_id, class_id)")
+ """
+ )
+ db.execSQL("CREATE UNIQUE INDEX index_Students_email_symbol_student_id_school_id_class_id ON Students_tmp (email, symbol, student_id, school_id, class_id)")
}
- private fun replaceStudentTable(database: SupportSQLiteDatabase) {
- database.execSQL("ALTER TABLE Students ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL")
- database.execSQL("INSERT INTO Students_tmp SELECT * FROM Students")
- database.execSQL("DROP TABLE Students")
- database.execSQL("ALTER TABLE Students_tmp RENAME TO Students")
+ private fun replaceStudentTable(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE Students ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL")
+ db.execSQL("INSERT INTO Students_tmp SELECT * FROM Students")
+ db.execSQL("DROP TABLE Students")
+ db.execSQL("ALTER TABLE Students_tmp RENAME TO Students")
}
private fun getStudentsIds(database: SupportSQLiteDatabase): List {
val students = mutableListOf()
- val studentsCursor = database.query("SELECT student_id FROM Students")
- if (studentsCursor.moveToFirst()) {
- do {
- students.add(studentsCursor.getInt(0))
- } while (studentsCursor.moveToNext())
+ database.query("SELECT student_id FROM Students").use {
+ if (it.moveToFirst()) {
+ do {
+ students.add(it.getInt(0))
+ } while (it.moveToNext())
+ }
}
+
return students
}
- private fun updateStudentsWithClassId(database: SupportSQLiteDatabase, students: List) {
+ private fun updateStudentsWithClassId(db: SupportSQLiteDatabase, students: List) {
students.forEach {
- database.execSQL("UPDATE Students SET class_id = IFNULL((SELECT class_id FROM Semesters WHERE student_id = $it), 0) WHERE student_id = $it")
+ db.execSQL("UPDATE Students SET class_id = IFNULL((SELECT class_id FROM Semesters WHERE student_id = $it), 0) WHERE student_id = $it")
}
}
- private fun removeStudentsWithNoClassId(database: SupportSQLiteDatabase) {
- database.execSQL("DELETE FROM Students WHERE class_id = 0")
+ private fun removeStudentsWithNoClassId(db: SupportSQLiteDatabase) {
+ db.execSQL("DELETE FROM Students WHERE class_id = 0")
}
- private fun ensureThereIsOnlyOneCurrentStudent(database: SupportSQLiteDatabase) {
- database.execSQL("UPDATE Students SET is_current = 0")
- database.execSQL("UPDATE Students SET is_current = 1 WHERE id = (SELECT MAX(id) FROM Students)")
+ private fun ensureThereIsOnlyOneCurrentStudent(db: SupportSQLiteDatabase) {
+ db.execSQL("UPDATE Students SET is_current = 0")
+ db.execSQL("UPDATE Students SET is_current = 1 WHERE id = (SELECT MAX(id) FROM Students)")
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt
index 0cf8cd9b..c5030232 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration13.kt
@@ -5,60 +5,70 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration13 : Migration(12, 13) {
- override fun migrate(database: SupportSQLiteDatabase) {
- addClassNameToStudents(database, getStudentsIds(database))
- updateSemestersTable(database)
- markAtLeastAndOnlyOneSemesterAtCurrent(database, getStudentsAndClassIds(database))
- clearMessagesTable(database)
+ override fun migrate(db: SupportSQLiteDatabase) {
+ addClassNameToStudents(db, getStudentsIds(db))
+ updateSemestersTable(db)
+ markAtLeastAndOnlyOneSemesterAtCurrent(db, getStudentsAndClassIds(db))
+ clearMessagesTable(db)
}
- private fun addClassNameToStudents(database: SupportSQLiteDatabase, students: List>) {
- database.execSQL("ALTER TABLE Students ADD COLUMN class_name TEXT DEFAULT \"\" NOT NULL")
+ private fun addClassNameToStudents(
+ db: SupportSQLiteDatabase,
+ students: List>
+ ) {
+ db.execSQL("ALTER TABLE Students ADD COLUMN class_name TEXT DEFAULT \"\" NOT NULL")
students.forEach { (id, name) ->
val schoolName = name.substringAfter(" - ")
val className = name.substringBefore(" - ", "").replace("Klasa ", "")
- database.execSQL("UPDATE Students SET class_name = '$className' WHERE id = '$id'")
- database.execSQL("UPDATE Students SET school_name = '$schoolName' WHERE id = '$id'")
+ db.execSQL("UPDATE Students SET class_name = '$className' WHERE id = '$id'")
+ db.execSQL("UPDATE Students SET school_name = '$schoolName' WHERE id = '$id'")
}
}
- private fun getStudentsIds(database: SupportSQLiteDatabase): MutableList> {
+ private fun getStudentsIds(db: SupportSQLiteDatabase): MutableList> {
val students = mutableListOf>()
- val studentsCursor = database.query("SELECT id, school_name FROM Students")
- if (studentsCursor.moveToFirst()) {
- do {
- students.add(studentsCursor.getInt(0) to studentsCursor.getString(1))
- } while (studentsCursor.moveToNext())
+ db.query("SELECT id, school_name FROM Students").use {
+ if (it.moveToFirst()) {
+ do {
+ students.add(it.getInt(0) to it.getString(1))
+ } while (it.moveToNext())
+ }
}
+
return students
}
- private fun updateSemestersTable(database: SupportSQLiteDatabase) {
- database.execSQL("ALTER TABLE Semesters ADD COLUMN school_year INTEGER DEFAULT 1970 NOT NULL")
- database.execSQL("ALTER TABLE Semesters ADD COLUMN start INTEGER DEFAULT 0 NOT NULL")
- database.execSQL("ALTER TABLE Semesters ADD COLUMN `end` INTEGER DEFAULT 0 NOT NULL")
+ private fun updateSemestersTable(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE Semesters ADD COLUMN school_year INTEGER DEFAULT 1970 NOT NULL")
+ db.execSQL("ALTER TABLE Semesters ADD COLUMN start INTEGER DEFAULT 0 NOT NULL")
+ db.execSQL("ALTER TABLE Semesters ADD COLUMN `end` INTEGER DEFAULT 0 NOT NULL")
}
- private fun getStudentsAndClassIds(database: SupportSQLiteDatabase): List> {
+ private fun getStudentsAndClassIds(db: SupportSQLiteDatabase): List> {
val students = mutableListOf>()
- val studentsCursor = database.query("SELECT student_id, class_id FROM Students")
- if (studentsCursor.moveToFirst()) {
- do {
- students.add(studentsCursor.getInt(0) to studentsCursor.getInt(1))
- } while (studentsCursor.moveToNext())
+ db.query("SELECT student_id, class_id FROM Students").use {
+ if (it.moveToFirst()) {
+ do {
+ students.add(it.getInt(0) to it.getInt(1))
+ } while (it.moveToNext())
+ }
}
+
return students
}
- private fun markAtLeastAndOnlyOneSemesterAtCurrent(database: SupportSQLiteDatabase, students: List>) {
+ private fun markAtLeastAndOnlyOneSemesterAtCurrent(
+ db: SupportSQLiteDatabase,
+ students: List>
+ ) {
students.forEach { (studentId, classId) ->
- database.execSQL("UPDATE Semesters SET is_current = 0 WHERE student_id = '$studentId' AND class_id = '$classId'")
- database.execSQL("UPDATE Semesters SET is_current = 1 WHERE id = (SELECT id FROM Semesters WHERE student_id = '$studentId' AND class_id = '$classId' ORDER BY semester_id DESC)")
+ db.execSQL("UPDATE Semesters SET is_current = 0 WHERE student_id = '$studentId' AND class_id = '$classId'")
+ db.execSQL("UPDATE Semesters SET is_current = 1 WHERE id = (SELECT id FROM Semesters WHERE student_id = '$studentId' AND class_id = '$classId' ORDER BY semester_id DESC)")
}
}
- private fun clearMessagesTable(database: SupportSQLiteDatabase) {
- database.execSQL("DELETE FROM Messages")
+ private fun clearMessagesTable(db: SupportSQLiteDatabase) {
+ db.execSQL("DELETE FROM Messages")
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration14.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration14.kt
index 4dac0d30..793b4a9d 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration14.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration14.kt
@@ -5,9 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration14 : Migration(13, 14) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("DROP TABLE IF EXISTS GradesSummary")
- database.execSQL("""
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("DROP TABLE IF EXISTS GradesSummary")
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS GradesSummary (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
semester_id INTEGER NOT NULL,
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration15.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration15.kt
index 5be49a95..5ff44e9c 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration15.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration15.kt
@@ -5,8 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration15 : Migration(14, 15) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("""
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS MobileDevices (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
student_id INTEGER NOT NULL,
@@ -14,6 +15,7 @@ class Migration15 : Migration(14, 15) {
name TEXT NOT NULL,
date INTEGER NOT NULL
)
- """)
+ """
+ )
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration16.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration16.kt
index 7f40c0f8..8a8f5b8f 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration16.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration16.kt
@@ -5,8 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration16 : Migration(15, 16) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("""
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS Teachers (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
student_id INTEGER NOT NULL,
@@ -15,6 +16,7 @@ class Migration16 : Migration(15, 16) {
name TEXT NOT NULL,
short_name TEXT NOT NULL
)
- """)
+ """
+ )
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration17.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration17.kt
index e2a2574d..cf3318ad 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration17.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration17.kt
@@ -5,13 +5,14 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration17 : Migration(16, 17) {
- override fun migrate(database: SupportSQLiteDatabase) {
- createGradesPointsStatisticsTable(database)
- truncateSemestersTable(database)
+ override fun migrate(db: SupportSQLiteDatabase) {
+ createGradesPointsStatisticsTable(db)
+ truncateSemestersTable(db)
}
- private fun createGradesPointsStatisticsTable(database: SupportSQLiteDatabase) {
- database.execSQL("""
+ private fun createGradesPointsStatisticsTable(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS GradesPointsStatistics(
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
student_id INTEGER NOT NULL,
@@ -20,10 +21,11 @@ class Migration17 : Migration(16, 17) {
others REAL NOT NULL,
student REAL NOT NULL
)
- """)
+ """
+ )
}
- private fun truncateSemestersTable(database: SupportSQLiteDatabase) {
- database.execSQL("DELETE FROM Semesters")
+ private fun truncateSemestersTable(db: SupportSQLiteDatabase) {
+ db.execSQL("DELETE FROM Semesters")
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration18.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration18.kt
index 6c5e56c6..713f8e72 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration18.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration18.kt
@@ -5,8 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration18 : Migration(17, 18) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("""
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS School (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
student_id INTEGER NOT NULL,
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration19.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration19.kt
index d38f1245..021cdbb3 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration19.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration19.kt
@@ -6,16 +6,17 @@ import io.github.wulkanowy.data.db.SharedPrefProvider
class Migration19(private val sharedPrefProvider: SharedPrefProvider) : Migration(18, 19) {
- override fun migrate(database: SupportSQLiteDatabase) {
- migrateMessages(database)
- migrateGrades(database)
- migrateStudents(database)
+ override fun migrate(db: SupportSQLiteDatabase) {
+ migrateMessages(db)
+ migrateGrades(db)
+ migrateStudents(db)
migrateSharedPreferences()
}
- private fun migrateMessages(database: SupportSQLiteDatabase) {
- database.execSQL("DROP TABLE Messages")
- database.execSQL("""
+ private fun migrateMessages(db: SupportSQLiteDatabase) {
+ db.execSQL("DROP TABLE Messages")
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS Messages (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
is_notified INTEGER NOT NULL,
@@ -34,12 +35,14 @@ class Migration19(private val sharedPrefProvider: SharedPrefProvider) : Migratio
read_by INTEGER NOT NULL,
removed INTEGER NOT NULL
)
- """)
+ """
+ )
}
- private fun migrateGrades(database: SupportSQLiteDatabase) {
- database.execSQL("DROP TABLE Grades")
- database.execSQL("""
+ private fun migrateGrades(db: SupportSQLiteDatabase) {
+ db.execSQL("DROP TABLE Grades")
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS Grades (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
is_read INTEGER NOT NULL,
@@ -59,11 +62,13 @@ class Migration19(private val sharedPrefProvider: SharedPrefProvider) : Migratio
date INTEGER NOT NULL,
teacher TEXT NOT NULL
)
- """)
+ """
+ )
}
- private fun migrateStudents(database: SupportSQLiteDatabase) {
- database.execSQL("""
+ private fun migrateStudents(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS Students_tmp (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
scrapper_base_url TEXT NOT NULL,
@@ -86,26 +91,29 @@ class Migration19(private val sharedPrefProvider: SharedPrefProvider) : Migratio
is_current INTEGER NOT NULL,
registration_date INTEGER NOT NULL
)
- """)
+ """
+ )
- database.execSQL("ALTER TABLE Students ADD COLUMN scrapperBaseUrl TEXT NOT NULL DEFAULT \"\";")
- database.execSQL("ALTER TABLE Students ADD COLUMN apiBaseUrl TEXT NOT NULL DEFAULT \"\";")
- database.execSQL("ALTER TABLE Students ADD COLUMN is_parent INT NOT NULL DEFAULT 0;")
- database.execSQL("ALTER TABLE Students ADD COLUMN loginMode TEXT NOT NULL DEFAULT \"\";")
- database.execSQL("ALTER TABLE Students ADD COLUMN certificateKey TEXT NOT NULL DEFAULT \"\";")
- database.execSQL("ALTER TABLE Students ADD COLUMN privateKey TEXT NOT NULL DEFAULT \"\";")
- database.execSQL("ALTER TABLE Students ADD COLUMN user_login_id INTEGER NOT NULL DEFAULT 0;")
+ db.execSQL("ALTER TABLE Students ADD COLUMN scrapperBaseUrl TEXT NOT NULL DEFAULT \"\";")
+ db.execSQL("ALTER TABLE Students ADD COLUMN apiBaseUrl TEXT NOT NULL DEFAULT \"\";")
+ db.execSQL("ALTER TABLE Students ADD COLUMN is_parent INT NOT NULL DEFAULT 0;")
+ db.execSQL("ALTER TABLE Students ADD COLUMN loginMode TEXT NOT NULL DEFAULT \"\";")
+ db.execSQL("ALTER TABLE Students ADD COLUMN certificateKey TEXT NOT NULL DEFAULT \"\";")
+ db.execSQL("ALTER TABLE Students ADD COLUMN privateKey TEXT NOT NULL DEFAULT \"\";")
+ db.execSQL("ALTER TABLE Students ADD COLUMN user_login_id INTEGER NOT NULL DEFAULT 0;")
- database.execSQL("""
+ db.execSQL(
+ """
INSERT INTO Students_tmp(
id, scrapper_base_url, mobile_base_url, is_parent, login_type, login_mode, certificate_key, private_key, email, password, symbol, student_id, user_login_id, student_name, school_id, school_name, school_id, school_name, class_name, class_id, is_current, registration_date)
SELECT
id, endpoint, apiBaseUrl, is_parent, loginType, "SCRAPPER", certificateKey, privateKey, email, password, symbol, student_id, user_login_id, student_name, school_id, school_name, school_id, school_name, class_name, class_id, is_current, registration_date
FROM Students
- """)
- database.execSQL("DROP TABLE Students")
- database.execSQL("ALTER TABLE Students_tmp RENAME TO Students")
- database.execSQL("CREATE UNIQUE INDEX index_Students_email_symbol_student_id_school_id_class_id ON Students (email, symbol, student_id, school_id, class_id)")
+ """
+ )
+ db.execSQL("DROP TABLE Students")
+ db.execSQL("ALTER TABLE Students_tmp RENAME TO Students")
+ db.execSQL("CREATE UNIQUE INDEX index_Students_email_symbol_student_id_school_id_class_id ON Students (email, symbol, student_id, school_id, class_id)")
}
private fun migrateSharedPreferences() {
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration2.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration2.kt
index c5a30991..be867509 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration2.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration2.kt
@@ -5,14 +5,16 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration2 : Migration(1, 2) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("""
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS LuckyNumbers (
id INTEGER PRIMARY KEY NOT NULL,
is_notified INTEGER NOT NULL,
student_id INTEGER NOT NULL,
date INTEGER NOT NULL,
lucky_number INTEGER NOT NULL)
- """)
+ """
+ )
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration20.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration20.kt
index 2fcfc183..7ad43230 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration20.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration20.kt
@@ -5,14 +5,15 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration20 : Migration(19, 20) {
- override fun migrate(database: SupportSQLiteDatabase) {
- migrateTimetable(database)
- truncateSubjects(database)
+ override fun migrate(db: SupportSQLiteDatabase) {
+ migrateTimetable(db)
+ truncateSubjects(db)
}
- private fun migrateTimetable(database: SupportSQLiteDatabase) {
- database.execSQL("DROP TABLE Timetable")
- database.execSQL("""
+ private fun migrateTimetable(db: SupportSQLiteDatabase) {
+ db.execSQL("DROP TABLE Timetable")
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS `Timetable` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`student_id` INTEGER NOT NULL,
@@ -33,10 +34,11 @@ class Migration20 : Migration(19, 20) {
`changes` INTEGER NOT NULL,
`canceled` INTEGER NOT NULL
)
- """)
+ """
+ )
}
- private fun truncateSubjects(database: SupportSQLiteDatabase) {
- database.execSQL("DELETE FROM Subjects")
+ private fun truncateSubjects(db: SupportSQLiteDatabase) {
+ db.execSQL("DELETE FROM Subjects")
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration21.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration21.kt
index bc0ff900..60e044cd 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration21.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration21.kt
@@ -5,11 +5,11 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration21 : Migration(20, 21) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("ALTER TABLE Attendance ADD COLUMN excusable INTEGER NOT NULL DEFAULT 0")
- database.execSQL("ALTER TABLE Attendance ADD COLUMN time_id INTEGER NOT NULL DEFAULT 0")
- database.execSQL("ALTER TABLE Attendance ADD COLUMN excuse_status TEXT DEFAULT NULL")
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE Attendance ADD COLUMN excusable INTEGER NOT NULL DEFAULT 0")
+ db.execSQL("ALTER TABLE Attendance ADD COLUMN time_id INTEGER NOT NULL DEFAULT 0")
+ db.execSQL("ALTER TABLE Attendance ADD COLUMN excuse_status TEXT DEFAULT NULL")
- database.execSQL("DELETE FROM Semesters")
+ db.execSQL("DELETE FROM Semesters")
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration22.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration22.kt
index cf50a6c3..ef525a49 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration22.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration22.kt
@@ -5,7 +5,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration22 : Migration(21, 22) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("ALTER TABLE Students ADD COLUMN school_short TEXT NOT NULL DEFAULT ''")
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE Students ADD COLUMN school_short TEXT NOT NULL DEFAULT ''")
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration23.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration23.kt
index 22de94c3..3650307a 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration23.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration23.kt
@@ -5,10 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration23 : Migration(22, 23) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("ALTER TABLE Notes ADD COLUMN teacher_symbol TEXT NOT NULL DEFAULT ''")
- database.execSQL("ALTER TABLE Notes ADD COLUMN category_type INTEGER NOT NULL DEFAULT 0")
- database.execSQL("ALTER TABLE Notes ADD COLUMN is_points_show INTEGER NOT NULL DEFAULT 0")
- database.execSQL("ALTER TABLE Notes ADD COLUMN points INTEGER NOT NULL DEFAULT 0")
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE Notes ADD COLUMN teacher_symbol TEXT NOT NULL DEFAULT ''")
+ db.execSQL("ALTER TABLE Notes ADD COLUMN category_type INTEGER NOT NULL DEFAULT 0")
+ db.execSQL("ALTER TABLE Notes ADD COLUMN is_points_show INTEGER NOT NULL DEFAULT 0")
+ db.execSQL("ALTER TABLE Notes ADD COLUMN points INTEGER NOT NULL DEFAULT 0")
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration24.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration24.kt
index 604ed487..a3cd9819 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration24.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration24.kt
@@ -5,9 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration24 : Migration(23, 24) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("ALTER TABLE Messages ADD COLUMN has_attachments INTEGER NOT NULL DEFAULT 0")
- database.execSQL("""
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE Messages ADD COLUMN has_attachments INTEGER NOT NULL DEFAULT 0")
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS MessageAttachments (
real_id INTEGER NOT NULL,
message_id INTEGER NOT NULL,
@@ -16,6 +17,7 @@ class Migration24 : Migration(23, 24) {
filename TEXT NOT NULL,
PRIMARY KEY(real_id)
)
- """)
+ """
+ )
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration25.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration25.kt
index 4749bac7..cb395d7e 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration25.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration25.kt
@@ -5,8 +5,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration25 : Migration(24, 25) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("ALTER TABLE Homework ADD COLUMN is_done INTEGER NOT NULL DEFAULT 0")
- database.execSQL("ALTER TABLE Homework ADD COLUMN attachments TEXT NOT NULL DEFAULT \"[]\"")
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE Homework ADD COLUMN is_done INTEGER NOT NULL DEFAULT 0")
+ db.execSQL("ALTER TABLE Homework ADD COLUMN attachments TEXT NOT NULL DEFAULT \"[]\"")
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration26.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration26.kt
new file mode 100644
index 00000000..94746b45
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration26.kt
@@ -0,0 +1,14 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration26 : Migration(25, 26) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE GradesSummary ADD COLUMN is_predicted_grade_notified INTEGER NOT NULL DEFAULT 1")
+ db.execSQL("ALTER TABLE GradesSummary ADD COLUMN is_final_grade_notified INTEGER NOT NULL DEFAULT 1")
+ db.execSQL("ALTER TABLE GradesSummary ADD COLUMN predicted_grade_last_change INTEGER NOT NULL DEFAULT 0")
+ db.execSQL("ALTER TABLE GradesSummary ADD COLUMN final_grade_last_change INTEGER NOT NULL DEFAULT 0")
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration27.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration27.kt
new file mode 100644
index 00000000..a7ba763d
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration27.kt
@@ -0,0 +1,50 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration27 : Migration(26, 27) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE Students ADD COLUMN user_name TEXT NOT NULL DEFAULT \"\"")
+
+ val students = getStudentsIdsAndNames(db)
+ val units = getReportingUnits(db)
+
+ students.forEach { (id, userLoginId, studentName) ->
+ val userNameFromUnits =
+ units.singleOrNull { (senderId, _) -> senderId == userLoginId }?.second
+ val normalizedStudentName = studentName.split(" ").asReversed().joinToString(" ")
+
+ val userName = userNameFromUnits ?: normalizedStudentName
+ db.execSQL("UPDATE Students SET user_name = '$userName' WHERE id = '$id'")
+ }
+ }
+
+ private fun getStudentsIdsAndNames(db: SupportSQLiteDatabase): MutableList> {
+ val students = mutableListOf>()
+ db.query("SELECT id, user_login_id, student_name FROM Students").use {
+ if (it.moveToFirst()) {
+ do {
+ students.add(Triple(it.getLong(0), it.getInt(1), it.getString(2)))
+ } while (it.moveToNext())
+ }
+ }
+
+ return students
+ }
+
+ private fun getReportingUnits(db: SupportSQLiteDatabase): MutableList> {
+ val units = mutableListOf>()
+ db.query("SELECT sender_id, sender_name FROM ReportingUnits").use {
+ if (it.moveToFirst()) {
+ do {
+ units.add(it.getInt(0) to it.getString(1))
+ } while (it.moveToNext())
+ }
+ }
+
+
+ return units
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration28.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration28.kt
new file mode 100644
index 00000000..e8a5a4a8
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration28.kt
@@ -0,0 +1,24 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration28 : Migration(27, 28) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS Conferences (
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ student_id INTEGER NOT NULL,
+ diary_id INTEGER NOT NULL,
+ title TEXT NOT NULL,
+ subject TEXT NOT NULL,
+ agenda TEXT NOT NULL,
+ present_on_conference TEXT NOT NULL,
+ conference_id INTEGER NOT NULL,
+ date INTEGER NOT NULL
+ )
+ """)
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration29.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration29.kt
new file mode 100644
index 00000000..dac303d2
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration29.kt
@@ -0,0 +1,36 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration29 : Migration(28, 29) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("DROP TABLE IF EXISTS GradesStatistics")
+ db.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS GradeSemesterStatistics (
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ student_id INTEGER NOT NULL,
+ semester_id INTEGER NOT NULL,
+ subject TEXT NOT NULL,
+ amounts TEXT NOT NULL,
+ student_grade INTEGER NOT NULL
+ )
+ """
+ )
+ db.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS GradePartialStatistics (
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ student_id INTEGER NOT NULL,
+ semester_id INTEGER NOT NULL,
+ subject TEXT NOT NULL,
+ class_average TEXT NOT NULL,
+ student_average TEXT NOT NULL,
+ class_amounts TEXT NOT NULL,
+ student_amounts TEXT NOT NULL
+ )
+ """)
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration3.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration3.kt
index d9699c0f..44d42164 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration3.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration3.kt
@@ -5,8 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration3 : Migration(2, 3) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("""
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS CompletedLesson (
id INTEGER PRIMARY KEY NOT NULL,
student_id INTEGER NOT NULL,
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration30.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration30.kt
new file mode 100644
index 00000000..3fea8ec0
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration30.kt
@@ -0,0 +1,23 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration30 : Migration(29, 30) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """
+ CREATE TABLE TimetableAdditional (
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ student_id INTEGER NOT NULL,
+ diary_id INTEGER NOT NULL,
+ start INTEGER NOT NULL,
+ `end` INTEGER NOT NULL,
+ date INTEGER NOT NULL,
+ subject TEXT NOT NULL
+ )
+ """
+ )
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration31.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration31.kt
new file mode 100644
index 00000000..28fb1056
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration31.kt
@@ -0,0 +1,42 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration31 : Migration(30, 31) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """CREATE TABLE IF NOT EXISTS StudentInfo (
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ student_id INTEGER NOT NULL,
+ full_name TEXT NOT NULL,
+ first_name TEXT NOT NULL,
+ second_name TEXT NOT NULL,
+ surname TEXT NOT NULL,
+ birth_date INTEGER NOT NULL,
+ birth_place TEXT NOT NULL,
+ gender TEXT NOT NULL,
+ has_polish_citizenship INTEGER NOT NULL,
+ family_name TEXT NOT NULL,
+ parents_names TEXT NOT NULL,
+ address TEXT NOT NULL,
+ registered_address TEXT NOT NULL,
+ correspondence_address TEXT NOT NULL,
+ phone_number TEXT NOT NULL,
+ cell_phone_number TEXT NOT NULL,
+ email TEXT NOT NULL,
+ first_guardian_full_name TEXT NOT NULL,
+ first_guardian_kinship TEXT NOT NULL,
+ first_guardian_address TEXT NOT NULL,
+ first_guardian_phones TEXT NOT NULL,
+ first_guardian_email TEXT NOT NULL,
+ second_guardian_full_name TEXT NOT NULL,
+ second_guardian_kinship TEXT NOT NULL,
+ second_guardian_address TEXT NOT NULL,
+ second_guardian_phones TEXT NOT NULL,
+ second_guardian_email TEXT NOT NULL)
+ """
+ )
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration32.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration32.kt
new file mode 100644
index 00000000..34787393
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration32.kt
@@ -0,0 +1,12 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration32 : Migration(31, 32) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE Students ADD COLUMN nick TEXT NOT NULL DEFAULT \"\"")
+ }
+}
+
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration33.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration33.kt
new file mode 100644
index 00000000..9778d279
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration33.kt
@@ -0,0 +1,45 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration33 : Migration(32, 33) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("DROP TABLE IF EXISTS StudentInfo")
+
+ db.execSQL(
+ """CREATE TABLE IF NOT EXISTS StudentInfo (
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ student_id INTEGER NOT NULL,
+ full_name TEXT NOT NULL,
+ first_name TEXT NOT NULL,
+ second_name TEXT NOT NULL,
+ surname TEXT NOT NULL,
+ birth_date INTEGER NOT NULL,
+ birth_place TEXT NOT NULL,
+ gender TEXT NOT NULL,
+ has_polish_citizenship INTEGER NOT NULL,
+ family_name TEXT NOT NULL,
+ parents_names TEXT NOT NULL,
+ address TEXT NOT NULL,
+ registered_address TEXT NOT NULL,
+ correspondence_address TEXT NOT NULL,
+ phone_number TEXT NOT NULL,
+ cell_phone_number TEXT NOT NULL,
+ email TEXT NOT NULL,
+ first_guardian_full_name TEXT,
+ first_guardian_kinship TEXT,
+ first_guardian_address TEXT,
+ first_guardian_phones TEXT,
+ first_guardian_email TEXT,
+ second_guardian_full_name TEXT,
+ second_guardian_kinship TEXT,
+ second_guardian_address TEXT,
+ second_guardian_phones TEXT,
+ second_guardian_email TEXT)
+ """
+ )
+ }
+}
+
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration34.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration34.kt
new file mode 100644
index 00000000..e9eec58c
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration34.kt
@@ -0,0 +1,13 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration34 : Migration(33, 34) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("DELETE FROM ReportingUnits")
+ db.execSQL("DELETE FROM Recipients")
+ }
+}
+
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration35.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration35.kt
new file mode 100644
index 00000000..b238ce8b
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration35.kt
@@ -0,0 +1,26 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.core.database.getLongOrNull
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+import io.github.wulkanowy.utils.AppInfo
+
+class Migration35(private val appInfo: AppInfo) : Migration(34, 35) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE Students ADD COLUMN `avatar_color` INTEGER NOT NULL DEFAULT 0")
+
+ db.query("SELECT * FROM Students").use {
+ while (it.moveToNext()) {
+ val studentId = it.getLongOrNull(0)
+ db.execSQL(
+ """
+ UPDATE Students
+ SET avatar_color = ${appInfo.defaultColorsForAvatar.random()}
+ WHERE id = $studentId
+ """
+ )
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration36.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration36.kt
new file mode 100644
index 00000000..62ce346c
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration36.kt
@@ -0,0 +1,12 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration36 : Migration(35, 36) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE Exams ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
+ db.execSQL("ALTER TABLE Homework ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration37.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration37.kt
new file mode 100644
index 00000000..9ab35514
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration37.kt
@@ -0,0 +1,21 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration37 : Migration(36, 37) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS TimetableHeaders (
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ student_id INTEGER NOT NULL,
+ diary_id INTEGER NOT NULL,
+ date INTEGER NOT NULL,
+ content TEXT NOT NULL
+ )
+ """
+ )
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration38.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration38.kt
new file mode 100644
index 00000000..bb9b32bf
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration38.kt
@@ -0,0 +1,21 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration38 : Migration(37, 38) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS `SchoolAnnouncements` (
+ `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ `student_id` INTEGER NOT NULL,
+ `date` INTEGER NOT NULL,
+ `subject` TEXT NOT NULL,
+ `content` TEXT NOT NULL
+ )
+ """
+ )
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration39.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration39.kt
new file mode 100644
index 00000000..2e5315bf
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration39.kt
@@ -0,0 +1,12 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration39 : Migration(38, 39) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE Conferences ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
+ db.execSQL("ALTER TABLE SchoolAnnouncements ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration4.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration4.kt
index 0ae89bdd..b6089aa6 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration4.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration4.kt
@@ -5,9 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration4 : Migration(3, 4) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("DROP TABLE IF EXISTS Messages")
- database.execSQL("""
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("DROP TABLE IF EXISTS Messages")
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS Messages (
id INTEGER PRIMARY KEY NOT NULL,
is_notified INTEGER NOT NULL,
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration40.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration40.kt
new file mode 100644
index 00000000..8e38b0c8
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration40.kt
@@ -0,0 +1,23 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration40 : Migration(39, 40) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS `Notifications` (
+ `student_id` INTEGER NOT NULL,
+ `title` TEXT NOT NULL,
+ `content` TEXT NOT NULL,
+ `type` TEXT NOT NULL,
+ `date` INTEGER NOT NULL,
+ `data` TEXT,
+ `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL
+ )
+ """
+ )
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration41.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration41.kt
new file mode 100644
index 00000000..bfc28334
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration41.kt
@@ -0,0 +1,21 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+import io.github.wulkanowy.data.db.SharedPrefProvider
+import io.github.wulkanowy.data.enums.GradeExpandMode
+
+class Migration41(private val sharedPrefProvider: SharedPrefProvider) : Migration(40, 41) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ migrateSharedPreferences()
+ db.execSQL("ALTER TABLE Homework ADD COLUMN is_added_by_user INTEGER NOT NULL DEFAULT 0")
+ }
+
+ private fun migrateSharedPreferences() {
+ if (sharedPrefProvider.getBoolean("pref_key_expand_grade", false)) {
+ sharedPrefProvider.putString("pref_key_expand_grade_mode", GradeExpandMode.ALWAYS_EXPANDED.value)
+ }
+ sharedPrefProvider.delete("pref_key_expand_grade")
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration42.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration42.kt
new file mode 100644
index 00000000..14356e27
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration42.kt
@@ -0,0 +1,24 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration42 : Migration(41, 42) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """CREATE TABLE IF NOT EXISTS `AdminMessages` (
+ `id` INTEGER NOT NULL,
+ `title` TEXT NOT NULL,
+ `content` TEXT NOT NULL,
+ `version_name` INTEGER,
+ `version_max` INTEGER,
+ `target_register_host` TEXT,
+ `target_flavor` TEXT,
+ `destination_url` TEXT,
+ `priority` TEXT NOT NULL,
+ `type` TEXT NOT NULL,
+ PRIMARY KEY(`id`))"""
+ )
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration43.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration43.kt
new file mode 100644
index 00000000..ef810816
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration43.kt
@@ -0,0 +1,12 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration43 : Migration(42, 43) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE Timetable ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
+ db.execSQL("ALTER TABLE Attendance ADD COLUMN is_notified INTEGER NOT NULL DEFAULT 1")
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration44.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration44.kt
new file mode 100644
index 00000000..0a4e5f96
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration44.kt
@@ -0,0 +1,11 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration44 : Migration(43, 44) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE AdminMessages ADD COLUMN is_dismissible INTEGER NOT NULL DEFAULT 0")
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration46.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration46.kt
new file mode 100644
index 00000000..0bacbaa0
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration46.kt
@@ -0,0 +1,102 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+import java.time.Instant
+import java.time.ZoneId
+import java.time.ZoneOffset
+
+class Migration46 : Migration(45, 46) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ migrateConferences(db)
+ migrateMessages(db)
+ migrateMobileDevices(db)
+ migrateNotifications(db)
+ migrateTimetable(db)
+ migrateTimetableAdditional(db)
+ }
+
+ private fun migrateConferences(db: SupportSQLiteDatabase) {
+ db.query("SELECT * FROM Conferences").use {
+ while (it.moveToNext()) {
+ val id = it.getLong(it.getColumnIndexOrThrow("id"))
+ val timestampLocal = it.getLong(it.getColumnIndexOrThrow("date"))
+ val timestampUtc = timestampLocal.timestampLocalToUTC()
+
+ db.execSQL("UPDATE Conferences SET date = $timestampUtc WHERE id = $id")
+ }
+ }
+ }
+
+ private fun migrateMessages(db: SupportSQLiteDatabase) {
+ db.query("SELECT * FROM Messages").use {
+ while (it.moveToNext()) {
+ val id = it.getLong(it.getColumnIndexOrThrow("id"))
+ val timestampLocal = it.getLong(it.getColumnIndexOrThrow("date"))
+ val timestampUtc = timestampLocal.timestampLocalToUTC()
+
+ db.execSQL("UPDATE Messages SET date = $timestampUtc WHERE id = $id")
+ }
+ }
+ }
+
+ private fun migrateMobileDevices(db: SupportSQLiteDatabase) {
+ db.query("SELECT * FROM MobileDevices").use {
+ while (it.moveToNext()) {
+ val id = it.getLong(it.getColumnIndexOrThrow("id"))
+ val timestampLocal = it.getLong(it.getColumnIndexOrThrow("date"))
+ val timestampUtc = timestampLocal.timestampLocalToUTC()
+
+ db.execSQL("UPDATE MobileDevices SET date = $timestampUtc WHERE id = $id")
+ }
+ }
+ }
+
+ private fun migrateNotifications(db: SupportSQLiteDatabase) {
+ db.query("SELECT * FROM Notifications").use {
+ while (it.moveToNext()) {
+ val id = it.getLong(it.getColumnIndexOrThrow("id"))
+ val timestampLocal = it.getLong(it.getColumnIndexOrThrow("date"))
+ val timestampUtc = timestampLocal.timestampLocalToUTC()
+
+ db.execSQL("UPDATE Notifications SET date = $timestampUtc WHERE id = $id")
+ }
+ }
+ }
+
+ private fun migrateTimetable(db: SupportSQLiteDatabase) {
+ db.query("SELECT * FROM Timetable").use {
+ while (it.moveToNext()) {
+ val id = it.getLong(it.getColumnIndexOrThrow("id"))
+ val timestampLocalStart = it.getLong(it.getColumnIndexOrThrow("start"))
+ val timestampLocalEnd = it.getLong(it.getColumnIndexOrThrow("end"))
+ val timestampUtcStart = timestampLocalStart.timestampLocalToUTC()
+ val timestampUtcEnd = timestampLocalEnd.timestampLocalToUTC()
+
+ db.execSQL("UPDATE Timetable SET start = $timestampUtcStart, end = $timestampUtcEnd WHERE id = $id")
+ }
+ }
+ }
+
+ private fun migrateTimetableAdditional(db: SupportSQLiteDatabase) {
+ db.query("SELECT * FROM TimetableAdditional").use {
+ while (it.moveToNext()) {
+ val id = it.getLong(it.getColumnIndexOrThrow("id"))
+ val timestampLocalStart = it.getLong(it.getColumnIndexOrThrow("start"))
+ val timestampLocalEnd = it.getLong(it.getColumnIndexOrThrow("end"))
+ val timestampUtcStart = timestampLocalStart.timestampLocalToUTC()
+ val timestampUtcEnd = timestampLocalEnd.timestampLocalToUTC()
+
+ db.execSQL("UPDATE TimetableAdditional SET start = $timestampUtcStart, end = $timestampUtcEnd WHERE id = $id")
+ }
+ }
+ }
+
+ private fun Long.timestampLocalToUTC(): Long = Instant.ofEpochMilli(this)
+ .atZone(ZoneOffset.UTC)
+ .withZoneSameLocal(ZoneId.of("Europe/Warsaw"))
+ .withZoneSameInstant(ZoneId.systemDefault())
+ .toInstant()
+ .toEpochMilli()
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration49.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration49.kt
new file mode 100644
index 00000000..97766c01
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration49.kt
@@ -0,0 +1,23 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration49 : Migration(48, 49) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("DROP TABLE IF EXISTS SchoolAnnouncements")
+
+ db.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS `SchoolAnnouncements` (
+ `user_login_id` INTEGER NOT NULL,
+ `date` INTEGER NOT NULL,
+ `subject` TEXT NOT NULL,
+ `content` TEXT NOT NULL,
+ `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ `is_notified` INTEGER NOT NULL)
+ """.trimIndent()
+ )
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration5.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration5.kt
index fe0dec48..a5b4e8e1 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration5.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration5.kt
@@ -2,16 +2,21 @@ package io.github.wulkanowy.data.db.migrations
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
-import org.threeten.bp.LocalDateTime.now
-import org.threeten.bp.ZoneOffset
+import java.time.LocalDateTime.now
+import java.time.ZoneOffset
class Migration5 : Migration(4, 5) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("ALTER TABLE Students ADD COLUMN registration_date INTEGER DEFAULT 0 NOT NULL")
- database.execSQL("UPDATE Students SET registration_date = '${now().atZone(ZoneOffset.UTC).toInstant().toEpochMilli()}'")
- database.execSQL("DROP TABLE IF EXISTS Notes")
- database.execSQL("""
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE Students ADD COLUMN registration_date INTEGER DEFAULT 0 NOT NULL")
+ db.execSQL(
+ "UPDATE Students SET registration_date = '${
+ now().atZone(ZoneOffset.UTC).toInstant().toEpochMilli()
+ }'"
+ )
+ db.execSQL("DROP TABLE IF EXISTS Notes")
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS Notes (
id INTEGER PRIMARY KEY NOT NULL,
is_read INTEGER NOT NULL,
@@ -21,6 +26,7 @@ class Migration5 : Migration(4, 5) {
teacher TEXT NOT NULL,
category TEXT NOT NULL,
content TEXT NOT NULL)
- """)
+ """
+ )
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration50.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration50.kt
new file mode 100644
index 00000000..577998ca
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration50.kt
@@ -0,0 +1,21 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration50 : Migration(49, 50) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("DROP TABLE IF EXISTS MobileDevices")
+ db.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS `MobileDevices` (
+ `user_login_id` INTEGER NOT NULL,
+ `device_id` INTEGER NOT NULL,
+ `name` TEXT NOT NULL,
+ `date` INTEGER NOT NULL,
+ `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)
+ """.trimIndent()
+ )
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration51.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration51.kt
new file mode 100644
index 00000000..7023049f
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration51.kt
@@ -0,0 +1,88 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration51 : Migration(50, 51) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ createMailboxTable(db)
+ recreateMessagesTable(db)
+ recreateMessageAttachmentsTable(db)
+ recreateRecipientsTable(db)
+ deleteReportingUnitTable(db)
+ }
+
+ private fun createMailboxTable(db: SupportSQLiteDatabase) {
+ db.execSQL("DROP TABLE IF EXISTS Mailboxes")
+ db.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS `Mailboxes` (
+ `globalKey` TEXT NOT NULL,
+ `fullName` TEXT NOT NULL,
+ `userName` TEXT NOT NULL,
+ `userLoginId` INTEGER NOT NULL,
+ `studentName` TEXT NOT NULL,
+ `schoolNameShort` TEXT NOT NULL,
+ `type` TEXT NOT NULL,
+ PRIMARY KEY(`globalKey`)
+ )""".trimIndent()
+ )
+ }
+
+ private fun recreateMessagesTable(db: SupportSQLiteDatabase) {
+ db.execSQL("DROP TABLE IF EXISTS Messages")
+ db.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS `Messages` (
+ `message_global_key` TEXT NOT NULL,
+ `mailbox_key` TEXT NOT NULL,
+ `message_id` INTEGER NOT NULL,
+ `correspondents` TEXT NOT NULL,
+ `subject` TEXT NOT NULL,
+ `date` INTEGER NOT NULL,
+ `folder_id` INTEGER NOT NULL,
+ `unread` INTEGER NOT NULL,
+ `has_attachments` INTEGER NOT NULL,
+ `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ `is_notified` INTEGER NOT NULL,
+ `content` TEXT NOT NULL,
+ `sender` TEXT, `recipients` TEXT
+ )""".trimIndent()
+ )
+ }
+
+ private fun recreateMessageAttachmentsTable(db: SupportSQLiteDatabase) {
+ db.execSQL("DROP TABLE IF EXISTS MessageAttachments")
+ db.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS `MessageAttachments` (
+ `real_id` INTEGER NOT NULL,
+ `message_global_key` TEXT NOT NULL,
+ `url` TEXT NOT NULL,
+ `filename` TEXT NOT NULL,
+ PRIMARY KEY(`real_id`)
+ )""".trimIndent()
+ )
+ }
+
+ private fun recreateRecipientsTable(db: SupportSQLiteDatabase) {
+ db.execSQL("DROP TABLE IF EXISTS Recipients")
+ db.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS `Recipients` (
+ `mailboxGlobalKey` TEXT NOT NULL,
+ `studentMailboxGlobalKey` TEXT NOT NULL,
+ `fullName` TEXT NOT NULL,
+ `userName` TEXT NOT NULL,
+ `schoolShortName` TEXT NOT NULL,
+ `type` TEXT NOT NULL,
+ `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL
+ )""".trimIndent()
+ )
+ }
+
+ private fun deleteReportingUnitTable(db: SupportSQLiteDatabase) {
+ db.execSQL("DROP TABLE IF EXISTS ReportingUnits")
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration53.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration53.kt
new file mode 100644
index 00000000..dd9e68c9
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration53.kt
@@ -0,0 +1,57 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration53 : Migration(52, 53) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ createMailboxTable(db)
+ recreateMessagesTable(db)
+ }
+
+ private fun createMailboxTable(db: SupportSQLiteDatabase) {
+ db.execSQL("DROP TABLE IF EXISTS Mailboxes")
+ db.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS `Mailboxes` (
+ `globalKey` TEXT NOT NULL,
+ `email` TEXT NOT NULL,
+ `symbol` TEXT NOT NULL,
+ `schoolId` TEXT NOT NULL,
+ `fullName` TEXT NOT NULL,
+ `userName` TEXT NOT NULL,
+ `studentName` TEXT NOT NULL,
+ `schoolNameShort` TEXT NOT NULL,
+ `type` TEXT NOT NULL,
+ PRIMARY KEY(`globalKey`)
+ )""".trimIndent()
+ )
+ }
+
+ private fun recreateMessagesTable(db: SupportSQLiteDatabase) {
+ db.execSQL("DROP TABLE IF EXISTS Messages")
+ db.execSQL(
+ """
+ CREATE TABLE IF NOT EXISTS `Messages` (
+ `email` TEXT NOT NULL,
+ `message_global_key` TEXT NOT NULL,
+ `mailbox_key` TEXT NOT NULL,
+ `message_id` INTEGER NOT NULL,
+ `correspondents` TEXT NOT NULL,
+ `subject` TEXT NOT NULL,
+ `date` INTEGER NOT NULL,
+ `folder_id` INTEGER NOT NULL,
+ `unread` INTEGER NOT NULL,
+ `read_by` INTEGER,
+ `unread_by` INTEGER,
+ `has_attachments` INTEGER NOT NULL,
+ `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ `is_notified` INTEGER NOT NULL,
+ `content` TEXT NOT NULL,
+ `sender` TEXT,
+ `recipients` TEXT
+ )""".trimIndent()
+ )
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration54.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration54.kt
new file mode 100644
index 00000000..60bd21f0
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration54.kt
@@ -0,0 +1,28 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration54 : Migration(53, 54) {
+
+ override fun migrate(db: SupportSQLiteDatabase) {
+ migrateResman(db)
+ removeTomaszowMazowieckiStudents(db)
+ }
+
+ private fun migrateResman(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """
+ UPDATE Students SET
+ scrapper_base_url = 'https://vulcan.net.pl',
+ login_type = 'ADFSLightScoped',
+ symbol = 'rzeszowprojekt'
+ WHERE scrapper_base_url = 'https://resman.pl'
+ """.trimIndent()
+ )
+ }
+
+ private fun removeTomaszowMazowieckiStudents(db: SupportSQLiteDatabase) {
+ db.execSQL("DELETE FROM Students WHERE symbol = 'tomaszowmazowiecki'")
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration55.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration55.kt
new file mode 100644
index 00000000..424be171
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration55.kt
@@ -0,0 +1,17 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.DeleteColumn
+import androidx.room.migration.AutoMigrationSpec
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+@DeleteColumn(
+ tableName = "MessageAttachments",
+ columnName = "real_id",
+)
+class Migration55 : AutoMigrationSpec {
+
+ override fun onPostMigrate(db: SupportSQLiteDatabase) {
+ db.execSQL("DELETE FROM Messages")
+ db.execSQL("DELETE FROM MessageAttachments")
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration57.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration57.kt
new file mode 100644
index 00000000..2fc8718f
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration57.kt
@@ -0,0 +1,10 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.DeleteColumn
+import androidx.room.migration.AutoMigrationSpec
+
+@DeleteColumn(
+ tableName = "AdminMessages",
+ columnName = "type",
+)
+class Migration57 : AutoMigrationSpec
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration58.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration58.kt
new file mode 100644
index 00000000..c440d58d
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration58.kt
@@ -0,0 +1,10 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.DeleteColumn
+import androidx.room.migration.AutoMigrationSpec
+
+@DeleteColumn(
+ tableName = "AdminMessages",
+ columnName = "is_dismissible",
+)
+class Migration58 : AutoMigrationSpec
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration6.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration6.kt
index fa943618..06cd5f0f 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration6.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration6.kt
@@ -5,8 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration6 : Migration(5, 6) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("""
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS ReportingUnits (
id INTEGER PRIMARY KEY NOT NULL,
student_id INTEGER NOT NULL,
@@ -15,9 +16,11 @@ class Migration6 : Migration(5, 6) {
sender_id INTEGER NOT NULL,
sender_name TEXT NOT NULL,
roles TEXT NOT NULL)
- """)
+ """
+ )
- database.execSQL("""
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS Recipients (
id INTEGER PRIMARY KEY NOT NULL,
student_id INTEGER NOT NULL,
@@ -28,10 +31,11 @@ class Migration6 : Migration(5, 6) {
unit_id INTEGER NOT NULL,
role INTEGER NOT NULL,
hash TEXT NOT NULL)
- """)
+ """
+ )
- database.execSQL("DELETE FROM Semesters WHERE 1")
- database.execSQL("ALTER TABLE Semesters ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL")
- database.execSQL("ALTER TABLE Semesters ADD COLUMN unit_id INTEGER DEFAULT 0 NOT NULL")
+ db.execSQL("DELETE FROM Semesters WHERE 1")
+ db.execSQL("ALTER TABLE Semesters ADD COLUMN class_id INTEGER DEFAULT 0 NOT NULL")
+ db.execSQL("ALTER TABLE Semesters ADD COLUMN unit_id INTEGER DEFAULT 0 NOT NULL")
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration63.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration63.kt
new file mode 100644
index 00000000..f88d31fc
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration63.kt
@@ -0,0 +1,11 @@
+package io.github.wulkanowy.data.db.migrations
+
+import androidx.room.migration.AutoMigrationSpec
+import androidx.sqlite.db.SupportSQLiteDatabase
+
+class Migration63 : AutoMigrationSpec {
+
+ override fun onPostMigrate(db: SupportSQLiteDatabase) {
+ db.execSQL("UPDATE Students SET is_edu_one = NULL WHERE is_edu_one = 0")
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration7.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration7.kt
index 120716c8..83a822f2 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration7.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration7.kt
@@ -5,8 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration7 : Migration(6, 7) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("""
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS GradesStatistics (
id INTEGER PRIMARY KEY NOT NULL,
student_id INTEGER NOT NULL,
@@ -15,6 +16,7 @@ class Migration7 : Migration(6, 7) {
grade INTEGER NOT NULL,
amount INTEGER NOT NULL,
is_semester INTEGER NOT NULL)
- """)
+ """
+ )
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration8.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration8.kt
index 7009ee12..992e8c68 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration8.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration8.kt
@@ -5,9 +5,9 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration8 : Migration(7, 8) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("ALTER TABLE Timetable ADD COLUMN subjectOld TEXT DEFAULT \"\" NOT NULL")
- database.execSQL("ALTER TABLE Timetable ADD COLUMN roomOld TEXT DEFAULT \"\" NOT NULL")
- database.execSQL("ALTER TABLE Timetable ADD COLUMN teacherOld TEXT DEFAULT \"\" NOT NULL")
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("ALTER TABLE Timetable ADD COLUMN subjectOld TEXT DEFAULT \"\" NOT NULL")
+ db.execSQL("ALTER TABLE Timetable ADD COLUMN roomOld TEXT DEFAULT \"\" NOT NULL")
+ db.execSQL("ALTER TABLE Timetable ADD COLUMN teacherOld TEXT DEFAULT \"\" NOT NULL")
}
}
diff --git a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration9.kt b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration9.kt
index d79a5706..b83c34c4 100644
--- a/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration9.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/db/migrations/Migration9.kt
@@ -5,9 +5,10 @@ import androidx.sqlite.db.SupportSQLiteDatabase
class Migration9 : Migration(8, 9) {
- override fun migrate(database: SupportSQLiteDatabase) {
- database.execSQL("DROP TABLE IF EXISTS Messages")
- database.execSQL("""
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("DROP TABLE IF EXISTS Messages")
+ db.execSQL(
+ """
CREATE TABLE IF NOT EXISTS Messages (
id INTEGER PRIMARY KEY NOT NULL,
student_id INTEGER NOT NULL,
diff --git a/app/src/main/java/io/github/wulkanowy/data/enums/AppTheme.kt b/app/src/main/java/io/github/wulkanowy/data/enums/AppTheme.kt
new file mode 100644
index 00000000..acff9d2e
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/enums/AppTheme.kt
@@ -0,0 +1,12 @@
+package io.github.wulkanowy.data.enums
+
+enum class AppTheme(val value: String) {
+ SYSTEM("system"),
+ LIGHT("light"),
+ DARK("dark"),
+ BLACK("black");
+
+ companion object {
+ fun getByValue(value: String) = entries.find { it.value == value } ?: LIGHT
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/enums/AttendanceCalculatorSortingMode.kt b/app/src/main/java/io/github/wulkanowy/data/enums/AttendanceCalculatorSortingMode.kt
new file mode 100644
index 00000000..77dd5fc4
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/enums/AttendanceCalculatorSortingMode.kt
@@ -0,0 +1,13 @@
+package io.github.wulkanowy.data.enums
+
+enum class AttendanceCalculatorSortingMode(private val value: String) {
+ ALPHABETIC("alphabetic"),
+ ATTENDANCE("attendance_percentage"),
+ LESSON_BALANCE("lesson_balance");
+
+ companion object {
+ fun getByValue(value: String) =
+ AttendanceCalculatorSortingMode.values()
+ .find { it.value == value } ?: ALPHABETIC
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/enums/Gender.kt b/app/src/main/java/io/github/wulkanowy/data/enums/Gender.kt
new file mode 100644
index 00000000..df93dcbe
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/enums/Gender.kt
@@ -0,0 +1,3 @@
+package io.github.wulkanowy.data.enums
+
+enum class Gender { MALE, FEMALE }
diff --git a/app/src/main/java/io/github/wulkanowy/data/enums/GradeColorTheme.kt b/app/src/main/java/io/github/wulkanowy/data/enums/GradeColorTheme.kt
new file mode 100644
index 00000000..48b81670
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/enums/GradeColorTheme.kt
@@ -0,0 +1,13 @@
+package io.github.wulkanowy.data.enums
+
+import java.io.Serializable
+
+enum class GradeColorTheme(val value: String) : Serializable {
+ VULCAN("vulcan"),
+ MATERIAL("material"),
+ GRADE_COLOR("grade_color");
+
+ companion object {
+ fun getByValue(value: String) = entries.find { it.value == value } ?: VULCAN
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/enums/GradeExpandMode.kt b/app/src/main/java/io/github/wulkanowy/data/enums/GradeExpandMode.kt
new file mode 100644
index 00000000..f99fe7a8
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/enums/GradeExpandMode.kt
@@ -0,0 +1,11 @@
+package io.github.wulkanowy.data.enums
+
+enum class GradeExpandMode(val value: String) {
+ ONE("one"),
+ UNLIMITED("any"),
+ ALWAYS_EXPANDED("always");
+
+ companion object {
+ fun getByValue(value: String) = entries.find { it.value == value } ?: ONE
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/enums/GradeSortingMode.kt b/app/src/main/java/io/github/wulkanowy/data/enums/GradeSortingMode.kt
new file mode 100644
index 00000000..e2872728
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/enums/GradeSortingMode.kt
@@ -0,0 +1,11 @@
+package io.github.wulkanowy.data.enums
+
+enum class GradeSortingMode(val value: String) {
+ ALPHABETIC("alphabetic"),
+ DATE("date"),
+ AVERAGE("average");
+
+ companion object {
+ fun getByValue(value: String) = entries.find { it.value == value } ?: ALPHABETIC
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/enums/MessageFolder.kt b/app/src/main/java/io/github/wulkanowy/data/enums/MessageFolder.kt
new file mode 100644
index 00000000..7cb4202a
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/enums/MessageFolder.kt
@@ -0,0 +1,12 @@
+package io.github.wulkanowy.data.enums
+
+enum class MessageFolder(val id: Int = 1) {
+ RECEIVED(1),
+ SENT(2),
+ TRASHED(3),
+ ;
+
+ companion object {
+ fun byId(id: Int) = entries.first { it.id == id }
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/enums/MessageType.kt b/app/src/main/java/io/github/wulkanowy/data/enums/MessageType.kt
new file mode 100644
index 00000000..ecd8d916
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/enums/MessageType.kt
@@ -0,0 +1,11 @@
+package io.github.wulkanowy.data.enums
+
+enum class MessageType {
+ GENERAL_MESSAGE,
+ DASHBOARD_MESSAGE,
+ LOGIN_MESSAGE,
+ LOGIN_STUDENT_SELECT_MESSAGE,
+ LOGIN_SYMBOL_MESSAGE,
+ PASS_RESET_MESSAGE,
+ ERROR_OVERRIDE,
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/SentExcuseStatus.kt b/app/src/main/java/io/github/wulkanowy/data/enums/SentExcuseStatus.kt
similarity index 60%
rename from app/src/main/java/io/github/wulkanowy/data/repositories/attendance/SentExcuseStatus.kt
rename to app/src/main/java/io/github/wulkanowy/data/enums/SentExcuseStatus.kt
index 50d6b8ed..99878152 100644
--- a/app/src/main/java/io/github/wulkanowy/data/repositories/attendance/SentExcuseStatus.kt
+++ b/app/src/main/java/io/github/wulkanowy/data/enums/SentExcuseStatus.kt
@@ -1,4 +1,4 @@
-package io.github.wulkanowy.data.repositories.attendance
+package io.github.wulkanowy.data.enums
enum class SentExcuseStatus(val id: Int = 0) {
WAITING,
diff --git a/app/src/main/java/io/github/wulkanowy/data/enums/ShowAdditionalLessonsMode.kt b/app/src/main/java/io/github/wulkanowy/data/enums/ShowAdditionalLessonsMode.kt
new file mode 100644
index 00000000..3e7cdef5
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/enums/ShowAdditionalLessonsMode.kt
@@ -0,0 +1,11 @@
+package io.github.wulkanowy.data.enums
+
+enum class ShowAdditionalLessonsMode(val value: String) {
+ NONE("none"),
+ INLINE("inline"),
+ BELOW("below");
+
+ companion object {
+ fun getByValue(value: String) = entries.find { it.value == value } ?: INLINE
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/enums/TimetableGapsMode.kt b/app/src/main/java/io/github/wulkanowy/data/enums/TimetableGapsMode.kt
new file mode 100644
index 00000000..c8310c02
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/enums/TimetableGapsMode.kt
@@ -0,0 +1,11 @@
+package io.github.wulkanowy.data.enums
+
+enum class TimetableGapsMode(val value: String) {
+ NO_GAPS("no_gaps"),
+ BETWEEN_LESSONS("between"),
+ BETWEEN_AND_BEFORE_LESSONS("before_and_between");
+
+ companion object {
+ fun getByValue(value: String) = entries.find { it.value == value } ?: BETWEEN_LESSONS
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/enums/TimetableMode.kt b/app/src/main/java/io/github/wulkanowy/data/enums/TimetableMode.kt
new file mode 100644
index 00000000..b2eeec38
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/enums/TimetableMode.kt
@@ -0,0 +1,11 @@
+package io.github.wulkanowy.data.enums
+
+enum class TimetableMode(val value: String) {
+ WHOLE_PLAN("yes"),
+ ONLY_CURRENT_GROUP("no"),
+ SMALL_OTHER_GROUP("small");
+
+ companion object {
+ fun getByValue(value: String) = entries.find { it.value == value } ?: ONLY_CURRENT_GROUP
+ }
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/AttendanceMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/AttendanceMapper.kt
new file mode 100644
index 00000000..c0ed0c8c
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/AttendanceMapper.kt
@@ -0,0 +1,48 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.Attendance
+import io.github.wulkanowy.data.db.entities.AttendanceSummary
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.db.entities.Timetable
+import io.github.wulkanowy.sdk.pojo.Attendance as SdkAttendance
+import io.github.wulkanowy.sdk.pojo.AttendanceSummary as SdkAttendanceSummary
+
+fun List.mapToEntities(semester: Semester, lessons: List) = map {
+ Attendance(
+ studentId = semester.studentId,
+ diaryId = semester.diaryId,
+ date = it.date,
+ timeId = it.timeId,
+ number = it.number,
+ subject = it.subject.ifBlank {
+ lessons.find { lesson ->
+ lesson.date == it.date && lesson.number == it.number
+ }?.subject.orEmpty()
+ },
+ name = it.name,
+ presence = it.presence,
+ absence = it.absence,
+ exemption = it.exemption,
+ lateness = it.lateness,
+ excused = it.excused,
+ deleted = it.deleted,
+ excusable = it.excusable,
+ excuseStatus = it.excuseStatus?.name
+ )
+}
+
+fun List.mapToEntities(semester: Semester, subjectId: Int) = map {
+ AttendanceSummary(
+ studentId = semester.studentId,
+ diaryId = semester.diaryId,
+ subjectId = subjectId,
+ month = it.month,
+ presence = it.presence,
+ absence = it.absence,
+ absenceExcused = it.absenceExcused,
+ absenceForSchoolReasons = it.absenceForSchoolReasons,
+ lateness = it.lateness,
+ latenessExcused = it.latenessExcused,
+ exemption = it.exemption
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/CompletedLessonsMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/CompletedLessonsMapper.kt
new file mode 100644
index 00000000..c42126eb
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/CompletedLessonsMapper.kt
@@ -0,0 +1,21 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.CompletedLesson
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.sdk.pojo.CompletedLesson as SdkCompletedLesson
+
+fun List.mapToEntities(semester: Semester) = map {
+ CompletedLesson(
+ studentId = semester.studentId,
+ diaryId = semester.diaryId,
+ date = it.date,
+ number = it.number,
+ subject = it.subject,
+ topic = it.topic,
+ teacher = it.teacher,
+ teacherSymbol = it.teacherSymbol,
+ substitution = it.substitution,
+ absence = it.absence,
+ resources = it.resources
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/ConferenceMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/ConferenceMapper.kt
new file mode 100644
index 00000000..add6439d
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/ConferenceMapper.kt
@@ -0,0 +1,18 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.Conference
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.sdk.pojo.Conference as SdkConference
+
+fun List.mapToEntities(semester: Semester) = map {
+ Conference(
+ studentId = semester.studentId,
+ diaryId = semester.diaryId,
+ agenda = it.agenda,
+ conferenceId = it.id,
+ date = it.date.toInstant(),
+ presentOnConference = it.presentOnConference,
+ subject = it.topic,
+ title = it.place,
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/DirectorInformationMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/DirectorInformationMapper.kt
new file mode 100644
index 00000000..1a84a6a5
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/DirectorInformationMapper.kt
@@ -0,0 +1,28 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
+import io.github.wulkanowy.data.db.entities.Student
+import io.github.wulkanowy.sdk.pojo.DirectorInformation as SdkDirectorInformation
+import io.github.wulkanowy.sdk.pojo.LastAnnouncement as SdkLastAnnouncement
+
+@JvmName("mapDirectorInformationToEntities")
+fun List.mapToEntities(student: Student) = map {
+ SchoolAnnouncement(
+ studentId = student.studentId,
+ date = it.date,
+ subject = it.subject,
+ content = it.content,
+ author = null,
+ )
+}
+
+@JvmName("mapLastAnnouncementsToEntities")
+fun List.mapToEntities(student: Student) = map {
+ SchoolAnnouncement(
+ studentId = student.studentId,
+ date = it.date,
+ subject = it.subject,
+ content = it.content,
+ author = it.author,
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/ExamMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/ExamMapper.kt
new file mode 100644
index 00000000..173dfebf
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/ExamMapper.kt
@@ -0,0 +1,20 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.Exam
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.sdk.pojo.Exam as SdkExam
+
+fun List.mapToEntities(semester: Semester) = map {
+ Exam(
+ studentId = semester.studentId,
+ diaryId = semester.diaryId,
+ date = it.date,
+ entryDate = it.entryDate,
+ subject = it.subject,
+ group = "",
+ type = it.type,
+ description = it.description,
+ teacher = it.teacher,
+ teacherSymbol = it.teacherSymbol
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/GradeMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/GradeMapper.kt
new file mode 100644
index 00000000..57322a7a
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/GradeMapper.kt
@@ -0,0 +1,58 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.Grade
+import io.github.wulkanowy.data.db.entities.GradeDescriptive
+import io.github.wulkanowy.data.db.entities.GradeSummary
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.sdk.pojo.Grade as SdkGrade
+import io.github.wulkanowy.sdk.pojo.GradeDescriptive as SdkGradeDescriptive
+import io.github.wulkanowy.sdk.pojo.GradeSummary as SdkGradeSummary
+
+fun List.mapToEntities(semester: Semester) = map {
+ Grade(
+ studentId = semester.studentId,
+ semesterId = semester.semesterId,
+ subject = it.subject,
+ entry = it.entry,
+ value = it.value,
+ modifier = it.modifier,
+ comment = it.comment,
+ color = it.color,
+ gradeSymbol = it.symbol,
+ description = it.description,
+ weight = it.weight,
+ weightValue = it.weightValue,
+ date = it.date,
+ teacher = it.teacher
+ )
+}
+
+@JvmName("mapGradeSummaryToEntities")
+fun List.mapToEntities(semester: Semester) = map {
+ GradeSummary(
+ semesterId = semester.semesterId,
+ studentId = semester.studentId,
+ position = 0,
+ subject = it.name,
+ predictedGrade = it.predicted,
+ finalGrade = it.final,
+ pointsSum = it.pointsSum,
+ pointsSumAllYear = it.pointsSumAllYear,
+ proposedPoints = it.proposedPoints,
+ finalPoints = it.finalPoints,
+ average = it.average,
+ averageAllYear = it.averageAllYear,
+ )
+}
+
+@JvmName("mapGradeDescriptiveToEntities")
+fun List.mapToEntities(semester: Semester) = map {
+ GradeDescriptive(
+ semesterId = semester.semesterId,
+ studentId = semester.studentId,
+ subject = it.subject,
+ description = it.description
+ )
+}
+
+
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/GradeStatisticsMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/GradeStatisticsMapper.kt
new file mode 100644
index 00000000..b25802d2
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/GradeStatisticsMapper.kt
@@ -0,0 +1,79 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.data.db.entities.GradePartialStatistics
+import io.github.wulkanowy.data.db.entities.GradePointsStatistics
+import io.github.wulkanowy.data.db.entities.GradeSemesterStatistics
+import io.github.wulkanowy.data.db.entities.Semester
+import io.github.wulkanowy.data.pojos.GradeStatisticsItem
+import io.github.wulkanowy.sdk.pojo.GradePointsStatistics as SdkGradePointsStatistics
+import io.github.wulkanowy.sdk.pojo.GradeStatisticsSemester as SdkGradeStatisticsSemester
+import io.github.wulkanowy.sdk.pojo.GradeStatisticsSubject as SdkGradeStatisticsSubject
+
+@JvmName("mapToEntitiesSubject")
+fun List.mapToEntities(semester: Semester) = map {
+ GradePartialStatistics(
+ semesterId = semester.semesterId,
+ studentId = semester.studentId,
+ subject = it.subject,
+ classAverage = it.classAverage,
+ studentAverage = it.studentAverage,
+ classAmounts = it.classItems
+ .sortedBy { item -> item.grade }
+ .map { item -> item.amount },
+ studentAmounts = it.studentItems.map { item -> item.amount }
+ )
+}
+
+@JvmName("mapToEntitiesSemester")
+fun List.mapToEntities(semester: Semester) = map {
+ GradeSemesterStatistics(
+ semesterId = semester.semesterId,
+ studentId = semester.studentId,
+ subject = it.subject,
+ amounts = it.items
+ .sortedBy { item -> item.grade }
+ .map { item -> item.amount },
+ studentGrade = it.items.singleOrNull { item -> item.isStudentHere }?.grade ?: 0
+ )
+}
+
+@JvmName("mapToEntitiesPoints")
+fun List.mapToEntities(semester: Semester) = map {
+ GradePointsStatistics(
+ semesterId = semester.semesterId,
+ studentId = semester.studentId,
+ subject = it.subject,
+ others = it.others,
+ student = it.student
+ )
+}
+
+fun List.mapPartialToStatisticItems() = filterNot { it.classAmounts.isEmpty() }.map {
+ GradeStatisticsItem(
+ type = GradeStatisticsItem.DataType.PARTIAL,
+ average = it.classAverage,
+ partial = it,
+ points = null,
+ semester = null
+ )
+}
+
+fun List.mapSemesterToStatisticItems() = filterNot { it.amounts.isEmpty() }.map {
+ GradeStatisticsItem(
+ type = GradeStatisticsItem.DataType.SEMESTER,
+ partial = null,
+ points = null,
+ average = "",
+ semester = it
+ )
+}
+
+fun List.mapPointsToStatisticsItems() = map {
+ GradeStatisticsItem(
+ type = GradeStatisticsItem.DataType.POINTS,
+ partial = null,
+ semester = null,
+ average = "",
+ points = it
+ )
+}
diff --git a/app/src/main/java/io/github/wulkanowy/data/mappers/HomeworkMapper.kt b/app/src/main/java/io/github/wulkanowy/data/mappers/HomeworkMapper.kt
new file mode 100644
index 00000000..880a26d6
--- /dev/null
+++ b/app/src/main/java/io/github/wulkanowy/data/mappers/HomeworkMapper.kt
@@ -0,0 +1,21 @@
+package io.github.wulkanowy.data.mappers
+
+import io.github.wulkanowy.sdk.pojo.Homework as SdkHomework
+import io.github.wulkanowy.data.db.entities.Homework
+import io.github.wulkanowy.data.db.entities.Semester
+
+fun List