forked from github/wulkanowy-mirror
Merge branch 'release/1.5.0'
This commit is contained in:
commit
6dc16b288d
15
.idea/codeStyles/Project.xml
generated
15
.idea/codeStyles/Project.xml
generated
@ -2,14 +2,6 @@
|
|||||||
<code_scheme name="Project" version="173">
|
<code_scheme name="Project" version="173">
|
||||||
<option name="LINE_SEPARATOR" value=" " />
|
<option name="LINE_SEPARATOR" value=" " />
|
||||||
<JetCodeStyleSettings>
|
<JetCodeStyleSettings>
|
||||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
|
||||||
<value>
|
|
||||||
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
|
|
||||||
</value>
|
|
||||||
</option>
|
|
||||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
|
|
||||||
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
|
|
||||||
<option name="WRAP_ELVIS_EXPRESSIONS" value="0" />
|
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
</JetCodeStyleSettings>
|
</JetCodeStyleSettings>
|
||||||
<codeStyleSettings language="XML">
|
<codeStyleSettings language="XML">
|
||||||
@ -126,13 +118,6 @@
|
|||||||
</codeStyleSettings>
|
</codeStyleSettings>
|
||||||
<codeStyleSettings language="kotlin">
|
<codeStyleSettings language="kotlin">
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
|
|
||||||
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
|
|
||||||
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" />
|
|
||||||
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
|
|
||||||
<indentOptions>
|
|
||||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
|
||||||
</indentOptions>
|
|
||||||
</codeStyleSettings>
|
</codeStyleSettings>
|
||||||
</code_scheme>
|
</code_scheme>
|
||||||
</component>
|
</component>
|
@ -22,8 +22,8 @@ android {
|
|||||||
testApplicationId "io.github.tests.wulkanowy"
|
testApplicationId "io.github.tests.wulkanowy"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 31
|
targetSdkVersion 31
|
||||||
versionCode 102
|
versionCode 103
|
||||||
versionName "1.4.4"
|
versionName "1.5.0"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
resValue "string", "app_name", "Wulkanowy"
|
resValue "string", "app_name", "Wulkanowy"
|
||||||
@ -149,8 +149,10 @@ kapt {
|
|||||||
|
|
||||||
play {
|
play {
|
||||||
defaultToAppBundles = false
|
defaultToAppBundles = false
|
||||||
track = 'beta'
|
track = 'production'
|
||||||
updatePriority = 4
|
releaseStatus = com.github.triplet.gradle.androidpublisher.ReleaseStatus.IN_PROGRESS
|
||||||
|
userFraction = 0.25d
|
||||||
|
updatePriority = 1
|
||||||
enabled.set(false)
|
enabled.set(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,18 +169,18 @@ huaweiPublish {
|
|||||||
ext {
|
ext {
|
||||||
work_manager = "2.7.1"
|
work_manager = "2.7.1"
|
||||||
android_hilt = "1.0.0"
|
android_hilt = "1.0.0"
|
||||||
room = "2.3.0"
|
room = "2.4.0"
|
||||||
chucker = "3.5.2"
|
chucker = "3.5.2"
|
||||||
mockk = "1.12.1"
|
mockk = "1.12.1"
|
||||||
coroutines = "1.5.2"
|
coroutines = "1.6.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "io.github.wulkanowy:sdk:1.4.4"
|
implementation "io.github.wulkanowy:sdk:1.5.0"
|
||||||
|
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.1"
|
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"
|
||||||
|
|
||||||
implementation "androidx.core:core-ktx:1.7.0"
|
implementation "androidx.core:core-ktx:1.7.0"
|
||||||
@ -229,7 +231,7 @@ dependencies {
|
|||||||
implementation 'me.xdrop:fuzzywuzzy:1.3.1'
|
implementation 'me.xdrop:fuzzywuzzy:1.3.1'
|
||||||
implementation 'com.fredporciuncula:flow-preferences:1.6.0'
|
implementation 'com.fredporciuncula:flow-preferences:1.6.0'
|
||||||
|
|
||||||
playImplementation platform('com.google.firebase:firebase-bom:29.0.2')
|
playImplementation platform('com.google.firebase:firebase-bom:29.0.3')
|
||||||
playImplementation 'com.google.firebase:firebase-analytics-ktx'
|
playImplementation 'com.google.firebase:firebase-analytics-ktx'
|
||||||
playImplementation 'com.google.firebase:firebase-messaging:'
|
playImplementation 'com.google.firebase:firebase-messaging:'
|
||||||
playImplementation 'com.google.firebase:firebase-crashlytics:'
|
playImplementation 'com.google.firebase:firebase-crashlytics:'
|
||||||
@ -238,7 +240,7 @@ dependencies {
|
|||||||
playImplementation 'com.google.android.gms:play-services-ads:20.5.0'
|
playImplementation 'com.google.android.gms:play-services-ads:20.5.0'
|
||||||
|
|
||||||
hmsImplementation 'com.huawei.hms:hianalytics:6.3.2.300'
|
hmsImplementation 'com.huawei.hms:hianalytics:6.3.2.300'
|
||||||
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.6.2.300'
|
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.6.3.200'
|
||||||
|
|
||||||
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
|
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
|
||||||
|
|
||||||
|
2430
app/schemas/io.github.wulkanowy.data.db.AppDatabase/45.json
Normal file
2430
app/schemas/io.github.wulkanowy.data.db.AppDatabase/45.json
Normal file
File diff suppressed because it is too large
Load Diff
2430
app/schemas/io.github.wulkanowy.data.db.AppDatabase/46.json
Normal file
2430
app/schemas/io.github.wulkanowy.data.db.AppDatabase/46.json
Normal file
File diff suppressed because it is too large
Load Diff
2438
app/schemas/io.github.wulkanowy.data.db.AppDatabase/47.json
Normal file
2438
app/schemas/io.github.wulkanowy.data.db.AppDatabase/47.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -114,7 +114,6 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".ui.modules.timetablewidget.TimetableWidgetProvider"
|
android:name=".ui.modules.timetablewidget.TimetableWidgetProvider"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
package io.github.wulkanowy
|
package io.github.wulkanowy
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.util.Log.DEBUG
|
import android.util.Log.*
|
||||||
import android.util.Log.INFO
|
|
||||||
import android.util.Log.VERBOSE
|
|
||||||
import android.webkit.WebView
|
|
||||||
import androidx.hilt.work.HiltWorkerFactory
|
import androidx.hilt.work.HiltWorkerFactory
|
||||||
import androidx.work.Configuration
|
import androidx.work.Configuration
|
||||||
import com.yariksoffice.lingver.Lingver
|
import com.yariksoffice.lingver.Lingver
|
||||||
@ -12,12 +9,7 @@ import dagger.hilt.android.HiltAndroidApp
|
|||||||
import fr.bipi.tressence.file.FileLoggerTree
|
import fr.bipi.tressence.file.FileLoggerTree
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||||
import io.github.wulkanowy.ui.base.ThemeManager
|
import io.github.wulkanowy.ui.base.ThemeManager
|
||||||
import io.github.wulkanowy.utils.ActivityLifecycleLogger
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
|
||||||
import io.github.wulkanowy.utils.CrashLogExceptionTree
|
|
||||||
import io.github.wulkanowy.utils.CrashLogTree
|
|
||||||
import io.github.wulkanowy.utils.DebugLogTree
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -44,7 +36,6 @@ class WulkanowyApp : Application(), Configuration.Provider {
|
|||||||
initializeAppLanguage()
|
initializeAppLanguage()
|
||||||
themeManager.applyDefaultTheme()
|
themeManager.applyDefaultTheme()
|
||||||
initLogging()
|
initLogging()
|
||||||
fixWebViewLocale()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initLogging() {
|
private fun initLogging() {
|
||||||
@ -76,15 +67,6 @@ class WulkanowyApp : Application(), Configuration.Provider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fixWebViewLocale() {
|
|
||||||
//https://stackoverflow.com/questions/40398528/android-webview-language-changes-abruptly-on-android-7-0-and-above
|
|
||||||
try {
|
|
||||||
WebView(this).destroy()
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
//Ignore exceptions
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getWorkManagerConfiguration() = Configuration.Builder()
|
override fun getWorkManagerConfiguration() = Configuration.Builder()
|
||||||
.setWorkerFactory(workerFactory)
|
.setWorkerFactory(workerFactory)
|
||||||
.setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO)
|
.setMinimumLoggingLevel(if (appInfo.isDebug) VERBOSE else INFO)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package io.github.wulkanowy.data.db
|
package io.github.wulkanowy.data.db
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import androidx.room.AutoMigration
|
||||||
import androidx.room.Database
|
import androidx.room.Database
|
||||||
import androidx.room.Room
|
import androidx.room.Room
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
@ -66,49 +67,7 @@ import io.github.wulkanowy.data.db.entities.Teacher
|
|||||||
import io.github.wulkanowy.data.db.entities.Timetable
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
import io.github.wulkanowy.data.db.entities.TimetableAdditional
|
import io.github.wulkanowy.data.db.entities.TimetableAdditional
|
||||||
import io.github.wulkanowy.data.db.entities.TimetableHeader
|
import io.github.wulkanowy.data.db.entities.TimetableHeader
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration10
|
import io.github.wulkanowy.data.db.migrations.*
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration11
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration12
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration13
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration14
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration15
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration16
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration17
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration18
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration19
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration2
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration20
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration21
|
|
||||||
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.Migration5
|
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration6
|
|
||||||
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 io.github.wulkanowy.utils.AppInfo
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -146,6 +105,10 @@ import javax.inject.Singleton
|
|||||||
Notification::class,
|
Notification::class,
|
||||||
AdminMessage::class
|
AdminMessage::class
|
||||||
],
|
],
|
||||||
|
autoMigrations = [
|
||||||
|
AutoMigration(from = 44, to = 45),
|
||||||
|
AutoMigration(from = 46, to = 47),
|
||||||
|
],
|
||||||
version = AppDatabase.VERSION_SCHEMA,
|
version = AppDatabase.VERSION_SCHEMA,
|
||||||
exportSchema = true
|
exportSchema = true
|
||||||
)
|
)
|
||||||
@ -153,7 +116,7 @@ import javax.inject.Singleton
|
|||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val VERSION_SCHEMA = 44
|
const val VERSION_SCHEMA = 47
|
||||||
|
|
||||||
fun getMigrations(sharedPrefProvider: SharedPrefProvider, appInfo: AppInfo) = arrayOf(
|
fun getMigrations(sharedPrefProvider: SharedPrefProvider, appInfo: AppInfo) = arrayOf(
|
||||||
Migration2(),
|
Migration2(),
|
||||||
@ -198,7 +161,8 @@ abstract class AppDatabase : RoomDatabase() {
|
|||||||
Migration41(sharedPrefProvider),
|
Migration41(sharedPrefProvider),
|
||||||
Migration42(),
|
Migration42(),
|
||||||
Migration43(),
|
Migration43(),
|
||||||
Migration44()
|
Migration44(),
|
||||||
|
Migration46(),
|
||||||
)
|
)
|
||||||
|
|
||||||
fun newInstance(
|
fun newInstance(
|
||||||
|
@ -1,40 +1,33 @@
|
|||||||
package io.github.wulkanowy.data.db
|
package io.github.wulkanowy.data.db
|
||||||
|
|
||||||
import androidx.room.TypeConverter
|
import androidx.room.TypeConverter
|
||||||
|
import io.github.wulkanowy.utils.toTimestamp
|
||||||
import kotlinx.serialization.SerializationException
|
import kotlinx.serialization.SerializationException
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
|
||||||
import java.time.Month
|
import java.time.Month
|
||||||
import java.time.ZoneOffset
|
import java.time.ZoneOffset
|
||||||
import java.util.Date
|
import java.util.*
|
||||||
|
|
||||||
class Converters {
|
class Converters {
|
||||||
|
|
||||||
private val json = Json
|
private val json = Json
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun timestampToDate(value: Long?): LocalDate? = value?.run {
|
fun timestampToLocalDate(value: Long?): LocalDate? =
|
||||||
Date(value).toInstant().atZone(ZoneOffset.UTC).toLocalDate()
|
value?.let(::Date)?.toInstant()?.atZone(ZoneOffset.UTC)?.toLocalDate()
|
||||||
}
|
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun dateToTimestamp(date: LocalDate?): Long? {
|
fun dateToTimestamp(date: LocalDate?): Long? = date?.toTimestamp()
|
||||||
return date?.atStartOfDay()?.toInstant(ZoneOffset.UTC)?.toEpochMilli()
|
|
||||||
}
|
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun timestampToTime(value: Long?): LocalDateTime? = value?.let {
|
fun instantToTimestamp(instant: Instant?): Long? = instant?.toEpochMilli()
|
||||||
LocalDateTime.ofInstant(Instant.ofEpochMilli(value), ZoneOffset.UTC)
|
|
||||||
}
|
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun timeToTimestamp(date: LocalDateTime?): Long? {
|
fun timestampToInstant(timestamp: Long?): Instant? = timestamp?.let(Instant::ofEpochMilli)
|
||||||
return date?.atZone(ZoneOffset.UTC)?.toInstant()?.toEpochMilli()
|
|
||||||
}
|
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun monthToInt(month: Month?) = month?.value
|
fun monthToInt(month: Month?) = month?.value
|
||||||
|
@ -4,7 +4,7 @@ import androidx.room.Dao
|
|||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import io.github.wulkanowy.data.db.entities.Conference
|
import io.github.wulkanowy.data.db.entities.Conference
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import java.time.LocalDateTime
|
import java.time.Instant
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
@ -12,5 +12,5 @@ import javax.inject.Singleton
|
|||||||
interface ConferenceDao : BaseDao<Conference> {
|
interface ConferenceDao : BaseDao<Conference> {
|
||||||
|
|
||||||
@Query("SELECT * FROM Conferences WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :startDate")
|
@Query("SELECT * FROM Conferences WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :startDate")
|
||||||
fun loadAll(diaryId: Int, studentId: Int, startDate: LocalDateTime): Flow<List<Conference>>
|
fun loadAll(diaryId: Int, studentId: Int, startDate: Instant): Flow<List<Conference>>
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,7 @@
|
|||||||
package io.github.wulkanowy.data.db.dao
|
package io.github.wulkanowy.data.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.*
|
||||||
import androidx.room.Delete
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.OnConflictStrategy.ABORT
|
import androidx.room.OnConflictStrategy.ABORT
|
||||||
import androidx.room.Query
|
|
||||||
import androidx.room.Transaction
|
|
||||||
import androidx.room.Update
|
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar
|
import io.github.wulkanowy.data.db.entities.StudentNickAndAvatar
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||||
|
@ -5,6 +5,7 @@ import androidx.room.Query
|
|||||||
import io.github.wulkanowy.data.db.entities.TimetableAdditional
|
import io.github.wulkanowy.data.db.entities.TimetableAdditional
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
|
import java.util.UUID
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
@ -12,5 +13,13 @@ import javax.inject.Singleton
|
|||||||
interface TimetableAdditionalDao : BaseDao<TimetableAdditional> {
|
interface TimetableAdditionalDao : BaseDao<TimetableAdditional> {
|
||||||
|
|
||||||
@Query("SELECT * FROM TimetableAdditional WHERE diary_id = :diaryId AND student_id = :studentId AND date >= :from AND date <= :end")
|
@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<List<TimetableAdditional>>
|
fun loadAll(
|
||||||
|
diaryId: Int,
|
||||||
|
studentId: Int,
|
||||||
|
from: LocalDate,
|
||||||
|
end: LocalDate
|
||||||
|
): Flow<List<TimetableAdditional>>
|
||||||
|
|
||||||
|
@Query("DELETE FROM TimetableAdditional WHERE repeat_id = :repeatId")
|
||||||
|
suspend fun deleteAllByRepeatId(repeatId: UUID)
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import androidx.room.ColumnInfo
|
|||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.time.LocalDateTime
|
import java.time.Instant
|
||||||
|
|
||||||
@Entity(tableName = "Conferences")
|
@Entity(tableName = "Conferences")
|
||||||
data class Conference(
|
data class Conference(
|
||||||
@ -27,7 +27,7 @@ data class Conference(
|
|||||||
@ColumnInfo(name = "conference_id")
|
@ColumnInfo(name = "conference_id")
|
||||||
val conferenceId: Int,
|
val conferenceId: Int,
|
||||||
|
|
||||||
val date: LocalDateTime
|
val date: Instant,
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
@ -3,7 +3,7 @@ package io.github.wulkanowy.data.db.entities
|
|||||||
import androidx.room.ColumnInfo
|
import androidx.room.ColumnInfo
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import java.time.LocalDateTime
|
import java.time.Instant
|
||||||
|
|
||||||
@Entity(tableName = "GradesSummary")
|
@Entity(tableName = "GradesSummary")
|
||||||
data class GradeSummary(
|
data class GradeSummary(
|
||||||
@ -45,8 +45,8 @@ data class GradeSummary(
|
|||||||
var isFinalGradeNotified: Boolean = true
|
var isFinalGradeNotified: Boolean = true
|
||||||
|
|
||||||
@ColumnInfo(name = "predicted_grade_last_change")
|
@ColumnInfo(name = "predicted_grade_last_change")
|
||||||
var predictedGradeLastChange: LocalDateTime = LocalDateTime.now()
|
var predictedGradeLastChange: Instant = Instant.now()
|
||||||
|
|
||||||
@ColumnInfo(name = "final_grade_last_change")
|
@ColumnInfo(name = "final_grade_last_change")
|
||||||
var finalGradeLastChange: LocalDateTime = LocalDateTime.now()
|
var finalGradeLastChange: Instant = Instant.now()
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import androidx.room.ColumnInfo
|
|||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.time.LocalDateTime
|
import java.time.Instant
|
||||||
|
|
||||||
@Entity(tableName = "Messages")
|
@Entity(tableName = "Messages")
|
||||||
data class Message(
|
data class Message(
|
||||||
@ -29,7 +29,7 @@ data class Message(
|
|||||||
|
|
||||||
val subject: String,
|
val subject: String,
|
||||||
|
|
||||||
val date: LocalDateTime,
|
val date: Instant,
|
||||||
|
|
||||||
@ColumnInfo(name = "folder_id")
|
@ColumnInfo(name = "folder_id")
|
||||||
val folderId: Int,
|
val folderId: Int,
|
||||||
|
@ -4,7 +4,7 @@ import androidx.room.ColumnInfo
|
|||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.time.LocalDateTime
|
import java.time.Instant
|
||||||
|
|
||||||
@Entity(tableName = "MobileDevices")
|
@Entity(tableName = "MobileDevices")
|
||||||
data class MobileDevice(
|
data class MobileDevice(
|
||||||
@ -17,7 +17,7 @@ data class MobileDevice(
|
|||||||
|
|
||||||
val name: String,
|
val name: String,
|
||||||
|
|
||||||
val date: LocalDateTime
|
val date: Instant,
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
@ -4,7 +4,7 @@ import androidx.room.ColumnInfo
|
|||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import io.github.wulkanowy.services.sync.notifications.NotificationType
|
import io.github.wulkanowy.services.sync.notifications.NotificationType
|
||||||
import java.time.LocalDateTime
|
import java.time.Instant
|
||||||
|
|
||||||
@Entity(tableName = "Notifications")
|
@Entity(tableName = "Notifications")
|
||||||
data class Notification(
|
data class Notification(
|
||||||
@ -18,7 +18,7 @@ data class Notification(
|
|||||||
|
|
||||||
val type: NotificationType,
|
val type: NotificationType,
|
||||||
|
|
||||||
val date: LocalDateTime,
|
val date: Instant,
|
||||||
|
|
||||||
val data: String? = null
|
val data: String? = null
|
||||||
) {
|
) {
|
||||||
|
@ -7,7 +7,12 @@ import androidx.room.PrimaryKey
|
|||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.time.LocalDate
|
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(
|
data class Semester(
|
||||||
|
|
||||||
@ColumnInfo(name = "student_id")
|
@ColumnInfo(name = "student_id")
|
||||||
@ -16,6 +21,9 @@ data class Semester(
|
|||||||
@ColumnInfo(name = "diary_id")
|
@ColumnInfo(name = "diary_id")
|
||||||
val diaryId: Int,
|
val diaryId: Int,
|
||||||
|
|
||||||
|
@ColumnInfo(name = "kindergarten_diary_id", defaultValue = "0")
|
||||||
|
val kindergartenDiaryId: Int,
|
||||||
|
|
||||||
@ColumnInfo(name = "diary_name")
|
@ColumnInfo(name = "diary_name")
|
||||||
val diaryName: String,
|
val diaryName: String,
|
||||||
|
|
||||||
@ -42,7 +50,6 @@ data class Semester(
|
|||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
var id: Long = 0
|
var id: Long = 0
|
||||||
|
|
||||||
|
|
||||||
@ColumnInfo(name = "is_current")
|
@ColumnInfo(name = "is_current")
|
||||||
var current: Boolean = false
|
var current: Boolean = false
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import androidx.room.Entity
|
|||||||
import androidx.room.Index
|
import androidx.room.Index
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.time.LocalDateTime
|
import java.time.Instant
|
||||||
|
|
||||||
@Entity(
|
@Entity(
|
||||||
tableName = "Students",
|
tableName = "Students",
|
||||||
@ -74,7 +74,7 @@ data class Student(
|
|||||||
val isCurrent: Boolean,
|
val isCurrent: Boolean,
|
||||||
|
|
||||||
@ColumnInfo(name = "registration_date")
|
@ColumnInfo(name = "registration_date")
|
||||||
val registrationDate: LocalDateTime
|
val registrationDate: Instant,
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
@ -4,8 +4,8 @@ import androidx.room.ColumnInfo
|
|||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
import java.time.Instant
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
|
||||||
|
|
||||||
@Entity(tableName = "Timetable")
|
@Entity(tableName = "Timetable")
|
||||||
data class Timetable(
|
data class Timetable(
|
||||||
@ -18,9 +18,9 @@ data class Timetable(
|
|||||||
|
|
||||||
val number: Int,
|
val number: Int,
|
||||||
|
|
||||||
val start: LocalDateTime,
|
val start: Instant,
|
||||||
|
|
||||||
val end: LocalDateTime,
|
val end: Instant,
|
||||||
|
|
||||||
val date: LocalDate,
|
val date: LocalDate,
|
||||||
|
|
||||||
|
@ -4,8 +4,9 @@ import androidx.room.ColumnInfo
|
|||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
import java.time.Instant
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
import java.util.*
|
||||||
|
|
||||||
@Entity(tableName = "TimetableAdditional")
|
@Entity(tableName = "TimetableAdditional")
|
||||||
data class TimetableAdditional(
|
data class TimetableAdditional(
|
||||||
@ -16,9 +17,9 @@ data class TimetableAdditional(
|
|||||||
@ColumnInfo(name = "diary_id")
|
@ColumnInfo(name = "diary_id")
|
||||||
val diaryId: Int,
|
val diaryId: Int,
|
||||||
|
|
||||||
val start: LocalDateTime,
|
val start: Instant,
|
||||||
|
|
||||||
val end: LocalDateTime,
|
val end: Instant,
|
||||||
|
|
||||||
val date: LocalDate,
|
val date: LocalDate,
|
||||||
|
|
||||||
@ -27,4 +28,10 @@ data class TimetableAdditional(
|
|||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
var id: Long = 0
|
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
|
||||||
}
|
}
|
||||||
|
@ -43,12 +43,14 @@ class Migration12 : Migration(11, 12) {
|
|||||||
|
|
||||||
private fun getStudentsIds(database: SupportSQLiteDatabase): List<Int> {
|
private fun getStudentsIds(database: SupportSQLiteDatabase): List<Int> {
|
||||||
val students = mutableListOf<Int>()
|
val students = mutableListOf<Int>()
|
||||||
val studentsCursor = database.query("SELECT student_id FROM Students")
|
database.query("SELECT student_id FROM Students").use {
|
||||||
if (studentsCursor.moveToFirst()) {
|
if (it.moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
students.add(studentsCursor.getInt(0))
|
students.add(it.getInt(0))
|
||||||
} while (studentsCursor.moveToNext())
|
} while (it.moveToNext())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return students
|
return students
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,12 +25,14 @@ class Migration13 : Migration(12, 13) {
|
|||||||
|
|
||||||
private fun getStudentsIds(database: SupportSQLiteDatabase): MutableList<Pair<Int, String>> {
|
private fun getStudentsIds(database: SupportSQLiteDatabase): MutableList<Pair<Int, String>> {
|
||||||
val students = mutableListOf<Pair<Int, String>>()
|
val students = mutableListOf<Pair<Int, String>>()
|
||||||
val studentsCursor = database.query("SELECT id, school_name FROM Students")
|
database.query("SELECT id, school_name FROM Students").use {
|
||||||
if (studentsCursor.moveToFirst()) {
|
if (it.moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
students.add(studentsCursor.getInt(0) to studentsCursor.getString(1))
|
students.add(it.getInt(0) to it.getString(1))
|
||||||
} while (studentsCursor.moveToNext())
|
} while (it.moveToNext())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return students
|
return students
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,12 +44,14 @@ class Migration13 : Migration(12, 13) {
|
|||||||
|
|
||||||
private fun getStudentsAndClassIds(database: SupportSQLiteDatabase): List<Pair<Int, Int>> {
|
private fun getStudentsAndClassIds(database: SupportSQLiteDatabase): List<Pair<Int, Int>> {
|
||||||
val students = mutableListOf<Pair<Int, Int>>()
|
val students = mutableListOf<Pair<Int, Int>>()
|
||||||
val studentsCursor = database.query("SELECT student_id, class_id FROM Students")
|
database.query("SELECT student_id, class_id FROM Students").use {
|
||||||
if (studentsCursor.moveToFirst()) {
|
if (it.moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
students.add(studentsCursor.getInt(0) to studentsCursor.getInt(1))
|
students.add(it.getInt(0) to it.getInt(1))
|
||||||
} while (studentsCursor.moveToNext())
|
} while (it.moveToNext())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return students
|
return students
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,23 +22,27 @@ class Migration27 : Migration(26, 27) {
|
|||||||
|
|
||||||
private fun getStudentsIdsAndNames(database: SupportSQLiteDatabase): MutableList<Triple<Long, Int, String>> {
|
private fun getStudentsIdsAndNames(database: SupportSQLiteDatabase): MutableList<Triple<Long, Int, String>> {
|
||||||
val students = mutableListOf<Triple<Long, Int, String>>()
|
val students = mutableListOf<Triple<Long, Int, String>>()
|
||||||
val studentsCursor = database.query("SELECT id, user_login_id, student_name FROM Students")
|
database.query("SELECT id, user_login_id, student_name FROM Students").use {
|
||||||
if (studentsCursor.moveToFirst()) {
|
if (it.moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
students.add(Triple(studentsCursor.getLong(0), studentsCursor.getInt(1), studentsCursor.getString(2)))
|
students.add(Triple(it.getLong(0), it.getInt(1), it.getString(2)))
|
||||||
} while (studentsCursor.moveToNext())
|
} while (it.moveToNext())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return students
|
return students
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getReportingUnits(database: SupportSQLiteDatabase): MutableList<Pair<Int, String>> {
|
private fun getReportingUnits(database: SupportSQLiteDatabase): MutableList<Pair<Int, String>> {
|
||||||
val units = mutableListOf<Pair<Int, String>>()
|
val units = mutableListOf<Pair<Int, String>>()
|
||||||
val unitsCursor = database.query("SELECT sender_id, sender_name FROM ReportingUnits")
|
database.query("SELECT sender_id, sender_name FROM ReportingUnits").use {
|
||||||
if (unitsCursor.moveToFirst()) {
|
if (it.moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
units.add(unitsCursor.getInt(0) to unitsCursor.getString(1))
|
units.add(it.getInt(0) to it.getString(1))
|
||||||
} while (unitsCursor.moveToNext())
|
} while (it.moveToNext())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return units
|
return units
|
||||||
}
|
}
|
||||||
|
@ -10,15 +10,17 @@ class Migration35(private val appInfo: AppInfo) : Migration(34, 35) {
|
|||||||
override fun migrate(database: SupportSQLiteDatabase) {
|
override fun migrate(database: SupportSQLiteDatabase) {
|
||||||
database.execSQL("ALTER TABLE Students ADD COLUMN `avatar_color` INTEGER NOT NULL DEFAULT 0")
|
database.execSQL("ALTER TABLE Students ADD COLUMN `avatar_color` INTEGER NOT NULL DEFAULT 0")
|
||||||
|
|
||||||
val studentsCursor = database.query("SELECT * FROM Students")
|
database.query("SELECT * FROM Students").use {
|
||||||
|
while (it.moveToNext()) {
|
||||||
while (studentsCursor.moveToNext()) {
|
val studentId = it.getLongOrNull(0)
|
||||||
val studentId = studentsCursor.getLongOrNull(0)
|
|
||||||
database.execSQL(
|
database.execSQL(
|
||||||
"""UPDATE Students
|
"""
|
||||||
|
UPDATE Students
|
||||||
SET avatar_color = ${appInfo.defaultColorsForAvatar.random()}
|
SET avatar_color = ${appInfo.defaultColorsForAvatar.random()}
|
||||||
WHERE id = $studentId"""
|
WHERE id = $studentId
|
||||||
|
"""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -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(database: SupportSQLiteDatabase) {
|
||||||
|
migrateConferences(database)
|
||||||
|
migrateMessages(database)
|
||||||
|
migrateMobileDevices(database)
|
||||||
|
migrateNotifications(database)
|
||||||
|
migrateTimetable(database)
|
||||||
|
migrateTimetableAdditional(database)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun migrateConferences(database: SupportSQLiteDatabase) {
|
||||||
|
database.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()
|
||||||
|
|
||||||
|
database.execSQL("UPDATE Conferences SET date = $timestampUtc WHERE id = $id")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun migrateMessages(database: SupportSQLiteDatabase) {
|
||||||
|
database.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()
|
||||||
|
|
||||||
|
database.execSQL("UPDATE Messages SET date = $timestampUtc WHERE id = $id")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun migrateMobileDevices(database: SupportSQLiteDatabase) {
|
||||||
|
database.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()
|
||||||
|
|
||||||
|
database.execSQL("UPDATE MobileDevices SET date = $timestampUtc WHERE id = $id")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun migrateNotifications(database: SupportSQLiteDatabase) {
|
||||||
|
database.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()
|
||||||
|
|
||||||
|
database.execSQL("UPDATE Notifications SET date = $timestampUtc WHERE id = $id")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun migrateTimetable(database: SupportSQLiteDatabase) {
|
||||||
|
database.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()
|
||||||
|
|
||||||
|
database.execSQL("UPDATE Timetable SET start = $timestampUtcStart, end = $timestampUtcEnd WHERE id = $id")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun migrateTimetableAdditional(database: SupportSQLiteDatabase) {
|
||||||
|
database.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()
|
||||||
|
|
||||||
|
database.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()
|
||||||
|
}
|
@ -10,7 +10,7 @@ fun List<SdkConference>.mapToEntities(semester: Semester) = map {
|
|||||||
diaryId = semester.diaryId,
|
diaryId = semester.diaryId,
|
||||||
agenda = it.agenda,
|
agenda = it.agenda,
|
||||||
conferenceId = it.id,
|
conferenceId = it.id,
|
||||||
date = it.date,
|
date = it.dateZoned.toInstant(),
|
||||||
presentOnConference = it.presentOnConference,
|
presentOnConference = it.presentOnConference,
|
||||||
subject = it.subject,
|
subject = it.subject,
|
||||||
title = it.title
|
title = it.title
|
||||||
|
@ -6,7 +6,7 @@ import io.github.wulkanowy.sdk.pojo.DirectorInformation as SdkDirectorInformatio
|
|||||||
|
|
||||||
fun List<SdkDirectorInformation>.mapToEntities(student: Student) = map {
|
fun List<SdkDirectorInformation>.mapToEntities(student: Student) = map {
|
||||||
SchoolAnnouncement(
|
SchoolAnnouncement(
|
||||||
studentId = student.studentId,
|
studentId = student.userLoginId,
|
||||||
date = it.date,
|
date = it.date,
|
||||||
subject = it.subject,
|
subject = it.subject,
|
||||||
content = it.content,
|
content = it.content,
|
||||||
|
@ -4,7 +4,7 @@ import io.github.wulkanowy.data.db.entities.Message
|
|||||||
import io.github.wulkanowy.data.db.entities.MessageAttachment
|
import io.github.wulkanowy.data.db.entities.MessageAttachment
|
||||||
import io.github.wulkanowy.data.db.entities.Recipient
|
import io.github.wulkanowy.data.db.entities.Recipient
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import java.time.LocalDateTime
|
import java.time.Instant
|
||||||
import io.github.wulkanowy.sdk.pojo.Message as SdkMessage
|
import io.github.wulkanowy.sdk.pojo.Message as SdkMessage
|
||||||
import io.github.wulkanowy.sdk.pojo.MessageAttachment as SdkMessageAttachment
|
import io.github.wulkanowy.sdk.pojo.MessageAttachment as SdkMessageAttachment
|
||||||
import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
|
import io.github.wulkanowy.sdk.pojo.Recipient as SdkRecipient
|
||||||
@ -18,7 +18,7 @@ fun List<SdkMessage>.mapToEntities(student: Student) = map {
|
|||||||
senderId = it.sender?.loginId ?: 0,
|
senderId = it.sender?.loginId ?: 0,
|
||||||
recipient = it.recipients.singleOrNull()?.name ?: "Wielu adresatów",
|
recipient = it.recipients.singleOrNull()?.name ?: "Wielu adresatów",
|
||||||
subject = it.subject.trim(),
|
subject = it.subject.trim(),
|
||||||
date = it.date ?: LocalDateTime.now(),
|
date = it.dateZoned?.toInstant() ?: Instant.now(),
|
||||||
folderId = it.folderId,
|
folderId = it.folderId,
|
||||||
unread = it.unread ?: false,
|
unread = it.unread ?: false,
|
||||||
removed = it.removed,
|
removed = it.removed,
|
||||||
|
@ -3,13 +3,13 @@ package io.github.wulkanowy.data.mappers
|
|||||||
import io.github.wulkanowy.data.db.entities.MobileDevice
|
import io.github.wulkanowy.data.db.entities.MobileDevice
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.pojos.MobileDeviceToken
|
import io.github.wulkanowy.data.pojos.MobileDeviceToken
|
||||||
import io.github.wulkanowy.sdk.pojo.Token as SdkToken
|
|
||||||
import io.github.wulkanowy.sdk.pojo.Device as SdkDevice
|
import io.github.wulkanowy.sdk.pojo.Device as SdkDevice
|
||||||
|
import io.github.wulkanowy.sdk.pojo.Token as SdkToken
|
||||||
|
|
||||||
fun List<SdkDevice>.mapToEntities(semester: Semester) = map {
|
fun List<SdkDevice>.mapToEntities(semester: Semester) = map {
|
||||||
MobileDevice(
|
MobileDevice(
|
||||||
userLoginId = semester.studentId,
|
userLoginId = semester.studentId,
|
||||||
date = it.createDate,
|
date = it.createDateZoned.toInstant(),
|
||||||
deviceId = it.id,
|
deviceId = it.id,
|
||||||
name = it.name
|
name = it.name
|
||||||
)
|
)
|
||||||
|
@ -7,6 +7,7 @@ fun List<SdkSemester>.mapToEntities(studentId: Int) = map {
|
|||||||
Semester(
|
Semester(
|
||||||
studentId = studentId,
|
studentId = studentId,
|
||||||
diaryId = it.diaryId,
|
diaryId = it.diaryId,
|
||||||
|
kindergartenDiaryId = it.kindergartenDiaryId,
|
||||||
diaryName = it.diaryName,
|
diaryName = it.diaryName,
|
||||||
schoolYear = it.schoolYear,
|
schoolYear = it.schoolYear,
|
||||||
semesterId = it.semesterId,
|
semesterId = it.semesterId,
|
||||||
|
@ -2,7 +2,7 @@ package io.github.wulkanowy.data.mappers
|
|||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||||
import java.time.LocalDateTime
|
import java.time.Instant
|
||||||
import io.github.wulkanowy.sdk.pojo.Student as SdkStudent
|
import io.github.wulkanowy.sdk.pojo.Student as SdkStudent
|
||||||
|
|
||||||
fun List<SdkStudent>.mapToEntities(password: String = "", colors: List<Long>) = map {
|
fun List<SdkStudent>.mapToEntities(password: String = "", colors: List<Long>) = map {
|
||||||
@ -24,7 +24,7 @@ fun List<SdkStudent>.mapToEntities(password: String = "", colors: List<Long>) =
|
|||||||
scrapperBaseUrl = it.scrapperBaseUrl,
|
scrapperBaseUrl = it.scrapperBaseUrl,
|
||||||
loginType = it.loginType.name,
|
loginType = it.loginType.name,
|
||||||
isCurrent = false,
|
isCurrent = false,
|
||||||
registrationDate = LocalDateTime.now(),
|
registrationDate = Instant.now(),
|
||||||
mobileBaseUrl = it.mobileBaseUrl,
|
mobileBaseUrl = it.mobileBaseUrl,
|
||||||
privateKey = it.privateKey,
|
privateKey = it.privateKey,
|
||||||
certificateKey = it.certificateKey,
|
certificateKey = it.certificateKey,
|
||||||
|
@ -21,8 +21,8 @@ fun List<SdkTimetable>.mapToEntities(semester: Semester) = map {
|
|||||||
studentId = semester.studentId,
|
studentId = semester.studentId,
|
||||||
diaryId = semester.diaryId,
|
diaryId = semester.diaryId,
|
||||||
number = it.number,
|
number = it.number,
|
||||||
start = it.start,
|
start = it.startZoned.toInstant(),
|
||||||
end = it.end,
|
end = it.endZoned.toInstant(),
|
||||||
date = it.date,
|
date = it.date,
|
||||||
subject = it.subject,
|
subject = it.subject,
|
||||||
subjectOld = it.subjectOld,
|
subjectOld = it.subjectOld,
|
||||||
@ -45,8 +45,8 @@ fun List<SdkTimetableAdditional>.mapToEntities(semester: Semester) = map {
|
|||||||
diaryId = semester.diaryId,
|
diaryId = semester.diaryId,
|
||||||
subject = it.subject,
|
subject = it.subject,
|
||||||
date = it.date,
|
date = it.date,
|
||||||
start = it.start,
|
start = it.startZoned.toInstant(),
|
||||||
end = it.end
|
end = it.endZoned.toInstant(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import io.github.wulkanowy.data.api.AdminMessageService
|
|||||||
import io.github.wulkanowy.data.db.dao.AdminMessageDao
|
import io.github.wulkanowy.data.db.dao.AdminMessageDao
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
import io.github.wulkanowy.utils.AppInfo
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
|
||||||
import io.github.wulkanowy.utils.networkBoundResource
|
import io.github.wulkanowy.utils.networkBoundResource
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -14,23 +13,17 @@ import javax.inject.Singleton
|
|||||||
class AdminMessageRepository @Inject constructor(
|
class AdminMessageRepository @Inject constructor(
|
||||||
private val adminMessageService: AdminMessageService,
|
private val adminMessageService: AdminMessageService,
|
||||||
private val adminMessageDao: AdminMessageDao,
|
private val adminMessageDao: AdminMessageDao,
|
||||||
private val appInfo: AppInfo,
|
private val appInfo: AppInfo
|
||||||
private val refreshHelper: AutoRefreshHelper,
|
|
||||||
) {
|
) {
|
||||||
private val saveFetchResultMutex = Mutex()
|
private val saveFetchResultMutex = Mutex()
|
||||||
|
|
||||||
private val cacheKey = "admin_messages"
|
suspend fun getAdminMessages(student: Student) = networkBoundResource(
|
||||||
|
|
||||||
suspend fun getAdminMessages(student: Student, forceRefresh: Boolean) = networkBoundResource(
|
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
query = { adminMessageDao.loadAll() },
|
query = { adminMessageDao.loadAll() },
|
||||||
fetch = { adminMessageService.getAdminMessages() },
|
fetch = { adminMessageService.getAdminMessages() },
|
||||||
shouldFetch = {
|
shouldFetch = { true },
|
||||||
refreshHelper.shouldBeRefreshed(cacheKey) || forceRefresh
|
|
||||||
},
|
|
||||||
saveFetchResult = { oldItems, newItems ->
|
saveFetchResult = { oldItems, newItems ->
|
||||||
adminMessageDao.removeOldAndSaveNew(oldItems, newItems)
|
adminMessageDao.removeOldAndSaveNew(oldItems, newItems)
|
||||||
refreshHelper.updateLastRefreshTimestamp(cacheKey)
|
|
||||||
},
|
},
|
||||||
showSavedOnLoading = false,
|
showSavedOnLoading = false,
|
||||||
mapResult = { adminMessages ->
|
mapResult = { adminMessages ->
|
||||||
|
@ -7,13 +7,7 @@ import io.github.wulkanowy.data.db.entities.Student
|
|||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.sdk.pojo.Absent
|
import io.github.wulkanowy.sdk.pojo.Absent
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.monday
|
|
||||||
import io.github.wulkanowy.utils.networkBoundResource
|
|
||||||
import io.github.wulkanowy.utils.sunday
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
@ -52,7 +46,8 @@ class AttendanceRepository @Inject constructor(
|
|||||||
attendanceDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday)
|
attendanceDb.loadAll(semester.diaryId, semester.studentId, start.monday, end.sunday)
|
||||||
},
|
},
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getAttendance(start.monday, end.sunday, semester.semesterId)
|
.getAttendance(start.monday, end.sunday, semester.semesterId)
|
||||||
.mapToEntities(semester)
|
.mapToEntities(semester)
|
||||||
},
|
},
|
||||||
@ -90,7 +85,8 @@ class AttendanceRepository @Inject constructor(
|
|||||||
timeId = attendance.timeId
|
timeId = attendance.timeId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.excuseForAbsence(items, reason)
|
.excuseForAbsence(items, reason)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,7 @@ import io.github.wulkanowy.data.db.entities.Semester
|
|||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.networkBoundResource
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -38,7 +34,8 @@ class AttendanceSummaryRepository @Inject constructor(
|
|||||||
},
|
},
|
||||||
query = { attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId) },
|
query = { attendanceDb.loadAll(semester.diaryId, semester.studentId, subjectId) },
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getAttendanceSummary(subjectId)
|
.getAttendanceSummary(subjectId)
|
||||||
.mapToEntities(semester, subjectId)
|
.mapToEntities(semester, subjectId)
|
||||||
},
|
},
|
||||||
|
@ -5,13 +5,7 @@ import io.github.wulkanowy.data.db.entities.Semester
|
|||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.monday
|
|
||||||
import io.github.wulkanowy.utils.networkBoundResource
|
|
||||||
import io.github.wulkanowy.utils.sunday
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -51,7 +45,8 @@ class CompletedLessonsRepository @Inject constructor(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getCompletedLessons(start.monday, end.sunday)
|
.getCompletedLessons(start.monday, end.sunday)
|
||||||
.mapToEntities(semester)
|
.mapToEntities(semester)
|
||||||
},
|
},
|
||||||
|
@ -6,16 +6,10 @@ import io.github.wulkanowy.data.db.entities.Semester
|
|||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.networkBoundResource
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.LocalDateTime
|
|
||||||
import java.time.ZoneOffset
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -35,7 +29,7 @@ class ConferenceRepository @Inject constructor(
|
|||||||
semester: Semester,
|
semester: Semester,
|
||||||
forceRefresh: Boolean,
|
forceRefresh: Boolean,
|
||||||
notify: Boolean = false,
|
notify: Boolean = false,
|
||||||
startDate: LocalDateTime = LocalDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC),
|
startDate: Instant = Instant.EPOCH,
|
||||||
) = networkBoundResource(
|
) = networkBoundResource(
|
||||||
mutex = saveFetchResultMutex,
|
mutex = saveFetchResultMutex,
|
||||||
shouldFetch = {
|
shouldFetch = {
|
||||||
@ -46,7 +40,8 @@ class ConferenceRepository @Inject constructor(
|
|||||||
conferenceDb.loadAll(semester.diaryId, student.studentId, startDate)
|
conferenceDb.loadAll(semester.diaryId, student.studentId, startDate)
|
||||||
},
|
},
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getConferences()
|
.getConferences()
|
||||||
.mapToEntities(semester)
|
.mapToEntities(semester)
|
||||||
.filter { it.date >= startDate }
|
.filter { it.date >= startDate }
|
||||||
@ -66,7 +61,7 @@ class ConferenceRepository @Inject constructor(
|
|||||||
conferenceDb.loadAll(
|
conferenceDb.loadAll(
|
||||||
diaryId = semester.diaryId,
|
diaryId = semester.diaryId,
|
||||||
studentId = semester.studentId,
|
studentId = semester.studentId,
|
||||||
startDate = LocalDateTime.ofInstant(Instant.EPOCH, ZoneOffset.UTC)
|
startDate = Instant.EPOCH,
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun updateConference(conference: List<Conference>) = conferenceDb.updateAll(conference)
|
suspend fun updateConference(conference: List<Conference>) = conferenceDb.updateAll(conference)
|
||||||
|
@ -6,13 +6,7 @@ import io.github.wulkanowy.data.db.entities.Semester
|
|||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.endExamsDay
|
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.networkBoundResource
|
|
||||||
import io.github.wulkanowy.utils.startExamsDay
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
@ -54,7 +48,8 @@ class ExamRepository @Inject constructor(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getExams(start.startExamsDay, start.endExamsDay, semester.semesterId)
|
.getExams(start.startExamsDay, start.endExamsDay, semester.semesterId)
|
||||||
.mapToEntities(semester)
|
.mapToEntities(semester)
|
||||||
},
|
},
|
||||||
|
@ -8,16 +8,12 @@ import io.github.wulkanowy.data.db.entities.Semester
|
|||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.networkBoundResource
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import java.time.LocalDateTime
|
import java.time.Instant
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -51,7 +47,7 @@ class GradeRepository @Inject constructor(
|
|||||||
},
|
},
|
||||||
fetch = {
|
fetch = {
|
||||||
val (details, summary) = sdk.init(student)
|
val (details, summary) = sdk.init(student)
|
||||||
.switchDiary(semester.diaryId, semester.schoolYear)
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getGrades(semester.semesterId)
|
.getGrades(semester.semesterId)
|
||||||
|
|
||||||
details.mapToEntities(semester) to summary.mapToEntities(semester)
|
details.mapToEntities(semester) to summary.mapToEntities(semester)
|
||||||
@ -70,8 +66,8 @@ class GradeRepository @Inject constructor(
|
|||||||
newDetails: List<Grade>,
|
newDetails: List<Grade>,
|
||||||
notify: Boolean
|
notify: Boolean
|
||||||
) {
|
) {
|
||||||
val notifyBreakDate = oldGrades.maxByOrNull {it.date }
|
val notifyBreakDate = oldGrades.maxByOrNull { it.date }?.date
|
||||||
?.date ?: student.registrationDate.toLocalDate()
|
?: student.registrationDate.toLocalDate()
|
||||||
gradeDb.deleteAll(oldGrades uniqueSubtract newDetails)
|
gradeDb.deleteAll(oldGrades uniqueSubtract newDetails)
|
||||||
gradeDb.insertAll((newDetails uniqueSubtract oldGrades).onEach {
|
gradeDb.insertAll((newDetails uniqueSubtract oldGrades).onEach {
|
||||||
if (it.date >= notifyBreakDate) it.apply {
|
if (it.date >= notifyBreakDate) it.apply {
|
||||||
@ -101,13 +97,13 @@ class GradeRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
summary.predictedGradeLastChange = when {
|
summary.predictedGradeLastChange = when {
|
||||||
oldSummary == null -> LocalDateTime.now()
|
oldSummary == null -> Instant.now()
|
||||||
summary.predictedGrade != oldSummary.predictedGrade -> LocalDateTime.now()
|
summary.predictedGrade != oldSummary.predictedGrade -> Instant.now()
|
||||||
else -> oldSummary.predictedGradeLastChange
|
else -> oldSummary.predictedGradeLastChange
|
||||||
}
|
}
|
||||||
summary.finalGradeLastChange = when {
|
summary.finalGradeLastChange = when {
|
||||||
oldSummary == null -> LocalDateTime.now()
|
oldSummary == null -> Instant.now()
|
||||||
summary.finalGrade != oldSummary.finalGrade -> LocalDateTime.now()
|
summary.finalGrade != oldSummary.finalGrade -> Instant.now()
|
||||||
else -> oldSummary.finalGradeLastChange
|
else -> oldSummary.finalGradeLastChange
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -12,13 +12,9 @@ import io.github.wulkanowy.data.mappers.mapPointsToStatisticsItems
|
|||||||
import io.github.wulkanowy.data.mappers.mapSemesterToStatisticItems
|
import io.github.wulkanowy.data.mappers.mapSemesterToStatisticItems
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.networkBoundResource
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import java.util.Locale
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -54,7 +50,8 @@ class GradeStatisticsRepository @Inject constructor(
|
|||||||
},
|
},
|
||||||
query = { gradePartialStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
|
query = { gradePartialStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getGradesPartialStatistics(semester.semesterId)
|
.getGradesPartialStatistics(semester.semesterId)
|
||||||
.mapToEntities(semester)
|
.mapToEntities(semester)
|
||||||
},
|
},
|
||||||
@ -101,7 +98,8 @@ class GradeStatisticsRepository @Inject constructor(
|
|||||||
},
|
},
|
||||||
query = { gradeSemesterStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
|
query = { gradeSemesterStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getGradesSemesterStatistics(semester.semesterId)
|
.getGradesSemesterStatistics(semester.semesterId)
|
||||||
.mapToEntities(semester)
|
.mapToEntities(semester)
|
||||||
},
|
},
|
||||||
@ -155,7 +153,8 @@ class GradeStatisticsRepository @Inject constructor(
|
|||||||
},
|
},
|
||||||
query = { gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
|
query = { gradePointsStatisticsDb.loadAll(semester.semesterId, semester.studentId) },
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getGradesPointsStatistics(semester.semesterId)
|
.getGradesPointsStatistics(semester.semesterId)
|
||||||
.mapToEntities(semester)
|
.mapToEntities(semester)
|
||||||
},
|
},
|
||||||
|
@ -6,13 +6,7 @@ import io.github.wulkanowy.data.db.entities.Semester
|
|||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.monday
|
|
||||||
import io.github.wulkanowy.utils.networkBoundResource
|
|
||||||
import io.github.wulkanowy.utils.sunday
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -53,7 +47,8 @@ class HomeworkRepository @Inject constructor(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getHomework(start.monday, end.sunday)
|
.getHomework(start.monday, end.sunday)
|
||||||
.mapToEntities(semester)
|
.mapToEntities(semester)
|
||||||
},
|
},
|
||||||
|
@ -8,11 +8,7 @@ import io.github.wulkanowy.data.mappers.mapToEntities
|
|||||||
import io.github.wulkanowy.data.mappers.mapToMobileDeviceToken
|
import io.github.wulkanowy.data.mappers.mapToMobileDeviceToken
|
||||||
import io.github.wulkanowy.data.pojos.MobileDeviceToken
|
import io.github.wulkanowy.data.pojos.MobileDeviceToken
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.networkBoundResource
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -40,7 +36,8 @@ class MobileDeviceRepository @Inject constructor(
|
|||||||
},
|
},
|
||||||
query = { mobileDb.loadAll(student.userLoginId.takeIf { it != 0 } ?: student.studentId) },
|
query = { mobileDb.loadAll(student.userLoginId.takeIf { it != 0 } ?: student.studentId) },
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getRegisteredDevices()
|
.getRegisteredDevices()
|
||||||
.mapToEntities(semester)
|
.mapToEntities(semester)
|
||||||
},
|
},
|
||||||
@ -53,14 +50,16 @@ class MobileDeviceRepository @Inject constructor(
|
|||||||
)
|
)
|
||||||
|
|
||||||
suspend fun unregisterDevice(student: Student, semester: Semester, device: MobileDevice) {
|
suspend fun unregisterDevice(student: Student, semester: Semester, device: MobileDevice) {
|
||||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.unregisterDevice(device.deviceId)
|
.unregisterDevice(device.deviceId)
|
||||||
|
|
||||||
mobileDb.deleteAll(listOf(device))
|
mobileDb.deleteAll(listOf(device))
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getToken(student: Student, semester: Semester): MobileDeviceToken {
|
suspend fun getToken(student: Student, semester: Semester): MobileDeviceToken {
|
||||||
return sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
return sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getToken()
|
.getToken()
|
||||||
.mapToMobileDeviceToken()
|
.mapToMobileDeviceToken()
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,7 @@ import io.github.wulkanowy.data.db.entities.Semester
|
|||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.networkBoundResource
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -42,7 +38,8 @@ class NoteRepository @Inject constructor(
|
|||||||
},
|
},
|
||||||
query = { noteDb.loadAll(student.studentId) },
|
query = { noteDb.loadAll(student.studentId) },
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getNotes(semester.semesterId)
|
.getNotes(semester.semesterId)
|
||||||
.mapToEntities(semester)
|
.mapToEntities(semester)
|
||||||
},
|
},
|
||||||
|
@ -7,24 +7,16 @@ import com.fredporciuncula.flow.preferences.FlowSharedPreferences
|
|||||||
import com.fredporciuncula.flow.preferences.Preference
|
import com.fredporciuncula.flow.preferences.Preference
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.enums.AppTheme
|
import io.github.wulkanowy.data.enums.*
|
||||||
import io.github.wulkanowy.data.enums.GradeColorTheme
|
|
||||||
import io.github.wulkanowy.data.enums.GradeExpandMode
|
|
||||||
import io.github.wulkanowy.data.enums.GradeSortingMode
|
|
||||||
import io.github.wulkanowy.data.enums.TimetableMode
|
|
||||||
import io.github.wulkanowy.sdk.toLocalDate
|
|
||||||
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
|
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
|
||||||
import io.github.wulkanowy.ui.modules.grade.GradeAverageMode
|
import io.github.wulkanowy.ui.modules.grade.GradeAverageMode
|
||||||
import io.github.wulkanowy.utils.toLocalDateTime
|
|
||||||
import io.github.wulkanowy.utils.toTimestamp
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import java.time.LocalDate
|
import java.time.Instant
|
||||||
import java.time.LocalDateTime
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@ -133,6 +125,12 @@ class PreferencesRepository @Inject constructor(
|
|||||||
R.bool.pref_default_notification_piggyback
|
R.bool.pref_default_notification_piggyback
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val isNotificationPiggybackRemoveOriginalEnabled: Boolean
|
||||||
|
get() = getBoolean(
|
||||||
|
R.string.pref_key_notifications_piggyback_cancel_original,
|
||||||
|
R.bool.pref_default_notification_piggyback_cancel_original
|
||||||
|
)
|
||||||
|
|
||||||
val isDebugNotificationEnableKey = context.getString(R.string.pref_key_notification_debug)
|
val isDebugNotificationEnableKey = context.getString(R.string.pref_key_notification_debug)
|
||||||
val isDebugNotificationEnable: Boolean
|
val isDebugNotificationEnable: Boolean
|
||||||
get() = getBoolean(isDebugNotificationEnableKey, R.bool.pref_default_notification_debug)
|
get() = getBoolean(isDebugNotificationEnableKey, R.bool.pref_default_notification_debug)
|
||||||
@ -202,10 +200,10 @@ class PreferencesRepository @Inject constructor(
|
|||||||
R.bool.pref_default_optional_arithmetic_average
|
R.bool.pref_default_optional_arithmetic_average
|
||||||
)
|
)
|
||||||
|
|
||||||
var lasSyncDate: LocalDateTime
|
var lasSyncDate: Instant?
|
||||||
get() = getLong(R.string.pref_key_last_sync_date, R.string.pref_default_last_sync_date)
|
get() = getLong(R.string.pref_key_last_sync_date, R.string.pref_default_last_sync_date)
|
||||||
.toLocalDateTime()
|
.takeIf { it != 0L }?.let(Instant::ofEpochMilli)
|
||||||
set(value) = sharedPref.edit().putLong("last_sync_date", value.toTimestamp()).apply()
|
set(value) = sharedPref.edit().putLong("last_sync_date", value?.toEpochMilli() ?: 0).apply()
|
||||||
|
|
||||||
var dashboardItemsPosition: Map<DashboardItem.Type, Int>?
|
var dashboardItemsPosition: Map<DashboardItem.Type, Int>?
|
||||||
get() {
|
get() {
|
||||||
@ -264,11 +262,12 @@ class PreferencesRepository @Inject constructor(
|
|||||||
get() = sharedPref.getInt(PREF_KEY_IN_APP_REVIEW_COUNT, 0)
|
get() = sharedPref.getInt(PREF_KEY_IN_APP_REVIEW_COUNT, 0)
|
||||||
set(value) = sharedPref.edit().putInt(PREF_KEY_IN_APP_REVIEW_COUNT, value).apply()
|
set(value) = sharedPref.edit().putInt(PREF_KEY_IN_APP_REVIEW_COUNT, value).apply()
|
||||||
|
|
||||||
var inAppReviewDate: LocalDate?
|
var inAppReviewDate: Instant?
|
||||||
get() = sharedPref.getLong(PREF_KEY_IN_APP_REVIEW_DATE, 0).takeIf { it != 0L }
|
get() = sharedPref.getLong(PREF_KEY_IN_APP_REVIEW_DATE, 0).takeIf { it != 0L }
|
||||||
?.toLocalDate()
|
?.let(Instant::ofEpochMilli)
|
||||||
set(value) = sharedPref.edit().putLong(PREF_KEY_IN_APP_REVIEW_DATE, value!!.toTimestamp())
|
set(value) = sharedPref.edit {
|
||||||
.apply()
|
putLong(PREF_KEY_IN_APP_REVIEW_DATE, value?.toEpochMilli() ?: 0)
|
||||||
|
}
|
||||||
|
|
||||||
var isAppReviewDone: Boolean
|
var isAppReviewDone: Boolean
|
||||||
get() = sharedPref.getBoolean(PREF_KEY_IN_APP_REVIEW_DONE, false)
|
get() = sharedPref.getBoolean(PREF_KEY_IN_APP_REVIEW_DONE, false)
|
||||||
|
@ -38,7 +38,9 @@ class SchoolRepository @Inject constructor(
|
|||||||
},
|
},
|
||||||
query = { schoolDb.load(semester.studentId, semester.classId) },
|
query = { schoolDb.load(semester.studentId, semester.classId) },
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear).getSchool()
|
sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
|
.getSchool()
|
||||||
.mapToEntity(semester)
|
.mapToEntity(semester)
|
||||||
},
|
},
|
||||||
saveFetchResult = { old, new ->
|
saveFetchResult = { old, new ->
|
||||||
|
@ -5,11 +5,7 @@ import io.github.wulkanowy.data.db.entities.Semester
|
|||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.DispatchersProvider
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getCurrentOrLast
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.isCurrent
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -43,10 +39,14 @@ class SemesterRepository @Inject constructor(
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
val isNoSemesters = semesters.isEmpty()
|
val isNoSemesters = semesters.isEmpty()
|
||||||
|
|
||||||
val isRefreshOnModeChangeRequired =
|
val isRefreshOnModeChangeRequired = when {
|
||||||
if (Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API) {
|
Sdk.Mode.valueOf(student.loginMode) != Sdk.Mode.API -> {
|
||||||
semesters.firstOrNull { it.isCurrent }?.diaryId == 0
|
semesters.firstOrNull { it.isCurrent }?.let {
|
||||||
} else false
|
0 == it.diaryId && 0 == it.kindergartenDiaryId
|
||||||
|
} == true
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
val isRefreshOnNoCurrentAppropriate =
|
val isRefreshOnNoCurrentAppropriate =
|
||||||
refreshOnNoCurrent && !semesters.any { semester -> semester.isCurrent }
|
refreshOnNoCurrent && !semesters.any { semester -> semester.isCurrent }
|
||||||
|
@ -28,7 +28,8 @@ class StudentInfoRepository @Inject constructor(
|
|||||||
shouldFetch = { it == null || forceRefresh },
|
shouldFetch = { it == null || forceRefresh },
|
||||||
query = { studentInfoDao.loadStudentInfo(student.studentId) },
|
query = { studentInfoDao.loadStudentInfo(student.studentId) },
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getStudentInfo().mapToEntity(semester)
|
.getStudentInfo().mapToEntity(semester)
|
||||||
},
|
},
|
||||||
saveFetchResult = { old, new ->
|
saveFetchResult = { old, new ->
|
||||||
|
@ -128,4 +128,7 @@ class StudentRepository @Inject constructor(
|
|||||||
|
|
||||||
suspend fun updateStudentNickAndAvatar(studentNickAndAvatar: StudentNickAndAvatar) =
|
suspend fun updateStudentNickAndAvatar(studentNickAndAvatar: StudentNickAndAvatar) =
|
||||||
studentDb.update(studentNickAndAvatar)
|
studentDb.update(studentNickAndAvatar)
|
||||||
|
|
||||||
|
suspend fun isOneUniqueStudent() = getSavedStudents(false)
|
||||||
|
.distinctBy { it.student.studentName }.size == 1
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,7 @@ import io.github.wulkanowy.data.db.entities.Semester
|
|||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.networkBoundResource
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -37,7 +33,8 @@ class SubjectRepository @Inject constructor(
|
|||||||
},
|
},
|
||||||
query = { subjectDao.loadAll(semester.diaryId, semester.studentId) },
|
query = { subjectDao.loadAll(semester.diaryId, semester.studentId) },
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getSubjects().mapToEntities(semester)
|
.getSubjects().mapToEntities(semester)
|
||||||
},
|
},
|
||||||
saveFetchResult = { old, new ->
|
saveFetchResult = { old, new ->
|
||||||
|
@ -5,11 +5,7 @@ import io.github.wulkanowy.data.db.entities.Semester
|
|||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.networkBoundResource
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -37,7 +33,8 @@ class TeacherRepository @Inject constructor(
|
|||||||
},
|
},
|
||||||
query = { teacherDb.loadAll(semester.studentId, semester.classId) },
|
query = { teacherDb.loadAll(semester.studentId, semester.classId) },
|
||||||
fetch = {
|
fetch = {
|
||||||
sdk.init(student).switchDiary(semester.diaryId, semester.schoolYear)
|
sdk.init(student)
|
||||||
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getTeachers(semester.semesterId)
|
.getTeachers(semester.semesterId)
|
||||||
.mapToEntities(semester)
|
.mapToEntities(semester)
|
||||||
},
|
},
|
||||||
|
@ -3,22 +3,12 @@ package io.github.wulkanowy.data.repositories
|
|||||||
import io.github.wulkanowy.data.db.dao.TimetableAdditionalDao
|
import io.github.wulkanowy.data.db.dao.TimetableAdditionalDao
|
||||||
import io.github.wulkanowy.data.db.dao.TimetableDao
|
import io.github.wulkanowy.data.db.dao.TimetableDao
|
||||||
import io.github.wulkanowy.data.db.dao.TimetableHeaderDao
|
import io.github.wulkanowy.data.db.dao.TimetableHeaderDao
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.*
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
|
||||||
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.mappers.mapToEntities
|
import io.github.wulkanowy.data.mappers.mapToEntities
|
||||||
import io.github.wulkanowy.data.pojos.TimetableFull
|
import io.github.wulkanowy.data.pojos.TimetableFull
|
||||||
import io.github.wulkanowy.sdk.Sdk
|
import io.github.wulkanowy.sdk.Sdk
|
||||||
import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
|
import io.github.wulkanowy.services.alarm.TimetableNotificationSchedulerHelper
|
||||||
import io.github.wulkanowy.utils.AutoRefreshHelper
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getRefreshKey
|
|
||||||
import io.github.wulkanowy.utils.init
|
|
||||||
import io.github.wulkanowy.utils.monday
|
|
||||||
import io.github.wulkanowy.utils.networkBoundResource
|
|
||||||
import io.github.wulkanowy.utils.sunday
|
|
||||||
import io.github.wulkanowy.utils.uniqueSubtract
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
@ -62,7 +52,7 @@ class TimetableRepository @Inject constructor(
|
|||||||
query = { getFullTimetableFromDatabase(student, semester, start, end) },
|
query = { getFullTimetableFromDatabase(student, semester, start, end) },
|
||||||
fetch = {
|
fetch = {
|
||||||
val timetableFull = sdk.init(student)
|
val timetableFull = sdk.init(student)
|
||||||
.switchDiary(semester.diaryId, semester.schoolYear)
|
.switchDiary(semester.diaryId, semester.kindergartenDiaryId, semester.schoolYear)
|
||||||
.getTimetableFull(start.monday, end.sunday)
|
.getTimetableFull(start.monday, end.sunday)
|
||||||
|
|
||||||
timetableFull.mapToEntities(semester)
|
timetableFull.mapToEntities(semester)
|
||||||
@ -152,7 +142,8 @@ class TimetableRepository @Inject constructor(
|
|||||||
old: List<TimetableAdditional>,
|
old: List<TimetableAdditional>,
|
||||||
new: List<TimetableAdditional>
|
new: List<TimetableAdditional>
|
||||||
) {
|
) {
|
||||||
timetableAdditionalDb.deleteAll(old uniqueSubtract new)
|
val oldFiltered = old.filter { !it.isAddedByUser }
|
||||||
|
timetableAdditionalDb.deleteAll(oldFiltered uniqueSubtract new)
|
||||||
timetableAdditionalDb.insertAll(new uniqueSubtract old)
|
timetableAdditionalDb.insertAll(new uniqueSubtract old)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,4 +151,14 @@ class TimetableRepository @Inject constructor(
|
|||||||
timetableHeaderDb.deleteAll(old uniqueSubtract new)
|
timetableHeaderDb.deleteAll(old uniqueSubtract new)
|
||||||
timetableHeaderDb.insertAll(new uniqueSubtract old)
|
timetableHeaderDb.insertAll(new uniqueSubtract old)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun saveAdditionalList(additionalList: List<TimetableAdditional>) =
|
||||||
|
timetableAdditionalDb.insertAll(additionalList)
|
||||||
|
|
||||||
|
suspend fun deleteAdditional(additional: TimetableAdditional, deleteSeries: Boolean) =
|
||||||
|
if (deleteSeries) {
|
||||||
|
timetableAdditionalDb.deleteAllByRepeatId(additional.repeatId!!)
|
||||||
|
} else {
|
||||||
|
timetableAdditionalDb.deleteAll(listOf(additional))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
package io.github.wulkanowy.services
|
|
||||||
|
|
||||||
import android.content.BroadcastReceiver
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
|
|
||||||
abstract class HiltBroadcastReceiver : BroadcastReceiver() {
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {}
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
package io.github.wulkanowy.services.alarm
|
package io.github.wulkanowy.services.alarm
|
||||||
|
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
@ -12,14 +13,12 @@ import io.github.wulkanowy.R
|
|||||||
import io.github.wulkanowy.data.Status
|
import io.github.wulkanowy.data.Status
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
import io.github.wulkanowy.data.repositories.StudentRepository
|
||||||
import io.github.wulkanowy.services.HiltBroadcastReceiver
|
|
||||||
import io.github.wulkanowy.services.sync.channels.UpcomingLessonsChannel.Companion.CHANNEL_ID
|
import io.github.wulkanowy.services.sync.channels.UpcomingLessonsChannel.Companion.CHANNEL_ID
|
||||||
import io.github.wulkanowy.ui.modules.Destination
|
import io.github.wulkanowy.ui.modules.Destination
|
||||||
import io.github.wulkanowy.ui.modules.splash.SplashActivity
|
import io.github.wulkanowy.ui.modules.splash.SplashActivity
|
||||||
import io.github.wulkanowy.utils.PendingIntentCompat
|
import io.github.wulkanowy.utils.PendingIntentCompat
|
||||||
import io.github.wulkanowy.utils.flowWithResource
|
import io.github.wulkanowy.utils.flowWithResource
|
||||||
import io.github.wulkanowy.utils.getCompatColor
|
import io.github.wulkanowy.utils.getCompatColor
|
||||||
import io.github.wulkanowy.utils.toLocalDateTime
|
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
@ -28,7 +27,7 @@ import timber.log.Timber
|
|||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class TimetableNotificationReceiver : HiltBroadcastReceiver() {
|
class TimetableNotificationReceiver : BroadcastReceiver() {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var studentRepository: StudentRepository
|
lateinit var studentRepository: StudentRepository
|
||||||
@ -41,6 +40,8 @@ class TimetableNotificationReceiver : HiltBroadcastReceiver() {
|
|||||||
const val NOTIFICATION_TYPE_UPCOMING = 2
|
const val NOTIFICATION_TYPE_UPCOMING = 2
|
||||||
const val NOTIFICATION_TYPE_LAST_LESSON_CANCELLATION = 3
|
const val NOTIFICATION_TYPE_LAST_LESSON_CANCELLATION = 3
|
||||||
|
|
||||||
|
// FIXME only shows one notification even if there are multiple students.
|
||||||
|
// Probably want to fix after #721 is merged.
|
||||||
const val NOTIFICATION_ID = 2137
|
const val NOTIFICATION_ID = 2137
|
||||||
|
|
||||||
const val STUDENT_NAME = "student_name"
|
const val STUDENT_NAME = "student_name"
|
||||||
@ -56,20 +57,24 @@ class TimetableNotificationReceiver : HiltBroadcastReceiver() {
|
|||||||
|
|
||||||
@OptIn(DelicateCoroutinesApi::class)
|
@OptIn(DelicateCoroutinesApi::class)
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
super.onReceive(context, intent)
|
|
||||||
Timber.d("Receiving intent... ${intent.toUri(0)}")
|
Timber.d("Receiving intent... ${intent.toUri(0)}")
|
||||||
|
|
||||||
flowWithResource {
|
flowWithResource {
|
||||||
|
val showStudentName = !studentRepository.isOneUniqueStudent()
|
||||||
val student = studentRepository.getCurrentStudent(false)
|
val student = studentRepository.getCurrentStudent(false)
|
||||||
val studentId = intent.getIntExtra(STUDENT_ID, 0)
|
val studentId = intent.getIntExtra(STUDENT_ID, 0)
|
||||||
if (student.studentId == studentId) prepareNotification(context, intent)
|
|
||||||
else Timber.d("Notification studentId($studentId) differs from current(${student.studentId})")
|
if (student.studentId == studentId) {
|
||||||
|
prepareNotification(context, intent, showStudentName)
|
||||||
|
} else {
|
||||||
|
Timber.d("Notification studentId($studentId) differs from current(${student.studentId})")
|
||||||
|
}
|
||||||
}.onEach {
|
}.onEach {
|
||||||
if (it.status == Status.ERROR) Timber.e(it.error!!)
|
if (it.status == Status.ERROR) Timber.e(it.error!!)
|
||||||
}.launchIn(GlobalScope)
|
}.launchIn(GlobalScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun prepareNotification(context: Context, intent: Intent) {
|
private fun prepareNotification(context: Context, intent: Intent, showStudentName: Boolean) {
|
||||||
val type = intent.getIntExtra(LESSON_TYPE, 0)
|
val type = intent.getIntExtra(LESSON_TYPE, 0)
|
||||||
val isPersistent = preferencesRepository.isUpcomingLessonsNotificationsPersistent
|
val isPersistent = preferencesRepository.isUpcomingLessonsNotificationsPersistent
|
||||||
|
|
||||||
@ -78,7 +83,7 @@ class TimetableNotificationReceiver : HiltBroadcastReceiver() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val studentId = intent.getIntExtra(STUDENT_ID, 0)
|
val studentId = intent.getIntExtra(STUDENT_ID, 0)
|
||||||
val studentName = intent.getStringExtra(STUDENT_NAME)
|
val studentName = intent.getStringExtra(STUDENT_NAME).takeIf { showStudentName }
|
||||||
|
|
||||||
val subject = intent.getStringExtra(LESSON_TITLE)
|
val subject = intent.getStringExtra(LESSON_TITLE)
|
||||||
val room = intent.getStringExtra(LESSON_ROOM)
|
val room = intent.getStringExtra(LESSON_ROOM)
|
||||||
@ -89,21 +94,28 @@ class TimetableNotificationReceiver : HiltBroadcastReceiver() {
|
|||||||
val nextSubject = intent.getStringExtra(LESSON_NEXT_TITLE)
|
val nextSubject = intent.getStringExtra(LESSON_NEXT_TITLE)
|
||||||
val nextRoom = intent.getStringExtra(LESSON_NEXT_ROOM)
|
val nextRoom = intent.getStringExtra(LESSON_NEXT_ROOM)
|
||||||
|
|
||||||
Timber.d("TimetableNotification receive: type: $type, subject: $subject, start: ${start.toLocalDateTime()}, student: $studentId")
|
Timber.d("TimetableNotification receive: type: $type, subject: $subject, start: $start, student: $studentId")
|
||||||
|
|
||||||
showNotification(
|
val notificationTitleResId =
|
||||||
context, isPersistent, studentName,
|
if (type == NOTIFICATION_TYPE_CURRENT) R.string.timetable_now else R.string.timetable_next
|
||||||
if (type == NOTIFICATION_TYPE_CURRENT) end else start, end - start,
|
val notificationTitle =
|
||||||
context.getString(
|
context.getString(notificationTitleResId, "($room) $subject".removePrefix("()"))
|
||||||
if (type == NOTIFICATION_TYPE_CURRENT) R.string.timetable_now else R.string.timetable_next,
|
|
||||||
"($room) $subject".removePrefix("()")
|
val nextLessonText = nextSubject?.let {
|
||||||
),
|
|
||||||
nextSubject?.let {
|
|
||||||
context.getString(
|
context.getString(
|
||||||
R.string.timetable_later,
|
R.string.timetable_later,
|
||||||
"($nextRoom) $nextSubject".removePrefix("()")
|
"($nextRoom) $nextSubject".removePrefix("()")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showNotification(
|
||||||
|
context = context,
|
||||||
|
isPersistent = isPersistent,
|
||||||
|
studentName = studentName,
|
||||||
|
countDown = if (type == NOTIFICATION_TYPE_CURRENT) end else start,
|
||||||
|
timeout = end - start,
|
||||||
|
title = notificationTitle,
|
||||||
|
next = nextLessonText
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,9 +142,10 @@ class TimetableNotificationReceiver : HiltBroadcastReceiver() {
|
|||||||
.setTimeoutAfter(timeout)
|
.setTimeoutAfter(timeout)
|
||||||
.setSmallIcon(R.drawable.ic_stat_timetable)
|
.setSmallIcon(R.drawable.ic_stat_timetable)
|
||||||
.setColor(context.getCompatColor(R.color.colorPrimary))
|
.setColor(context.getCompatColor(R.color.colorPrimary))
|
||||||
.setStyle(NotificationCompat.InboxStyle().also {
|
.setStyle(NotificationCompat.InboxStyle()
|
||||||
it.setSummaryText(studentName)
|
.addLine(next)
|
||||||
it.addLine(next)
|
.also { inboxStyle ->
|
||||||
|
studentName?.let { inboxStyle.setSummaryText(it) }
|
||||||
})
|
})
|
||||||
.setContentIntent(
|
.setContentIntent(
|
||||||
PendingIntent.getActivity(
|
PendingIntent.getActivity(
|
||||||
|
@ -28,12 +28,12 @@ import io.github.wulkanowy.services.alarm.TimetableNotificationReceiver.Companio
|
|||||||
import io.github.wulkanowy.utils.DispatchersProvider
|
import io.github.wulkanowy.utils.DispatchersProvider
|
||||||
import io.github.wulkanowy.utils.PendingIntentCompat
|
import io.github.wulkanowy.utils.PendingIntentCompat
|
||||||
import io.github.wulkanowy.utils.nickOrName
|
import io.github.wulkanowy.utils.nickOrName
|
||||||
import io.github.wulkanowy.utils.toTimestamp
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import java.time.Duration.ofMinutes
|
||||||
|
import java.time.Instant
|
||||||
|
import java.time.Instant.now
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
|
||||||
import java.time.LocalDateTime.now
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class TimetableNotificationSchedulerHelper @Inject constructor(
|
class TimetableNotificationSchedulerHelper @Inject constructor(
|
||||||
@ -43,14 +43,14 @@ class TimetableNotificationSchedulerHelper @Inject constructor(
|
|||||||
private val dispatchersProvider: DispatchersProvider,
|
private val dispatchersProvider: DispatchersProvider,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private fun getRequestCode(time: LocalDateTime, studentId: Int) =
|
private fun getRequestCode(time: Instant, studentId: Int): Int =
|
||||||
(time.toTimestamp() * studentId).toInt()
|
(time.toEpochMilli() * studentId).toInt()
|
||||||
|
|
||||||
private fun getUpcomingLessonTime(
|
private fun getUpcomingLessonTime(
|
||||||
index: Int,
|
index: Int,
|
||||||
day: List<Timetable>,
|
day: List<Timetable>,
|
||||||
lesson: Timetable
|
lesson: Timetable
|
||||||
) = day.getOrNull(index - 1)?.end ?: lesson.start.minusMinutes(30)
|
): Instant = day.getOrNull(index - 1)?.end ?: lesson.start.minus(ofMinutes(30))
|
||||||
|
|
||||||
suspend fun cancelScheduled(lessons: List<Timetable>, student: Student) {
|
suspend fun cancelScheduled(lessons: List<Timetable>, student: Student) {
|
||||||
val studentId = student.studentId
|
val studentId = student.studentId
|
||||||
@ -71,7 +71,7 @@ class TimetableNotificationSchedulerHelper @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cancelScheduledTo(range: ClosedRange<LocalDateTime>, requestCode: Int) {
|
private fun cancelScheduledTo(range: ClosedRange<Instant>, requestCode: Int) {
|
||||||
if (now() in range) cancelNotification()
|
if (now() in range) cancelNotification()
|
||||||
|
|
||||||
alarmManager.cancel(
|
alarmManager.cancel(
|
||||||
@ -150,8 +150,8 @@ class TimetableNotificationSchedulerHelper @Inject constructor(
|
|||||||
putExtra(STUDENT_ID, student.studentId)
|
putExtra(STUDENT_ID, student.studentId)
|
||||||
putExtra(STUDENT_NAME, student.nickOrName)
|
putExtra(STUDENT_NAME, student.nickOrName)
|
||||||
putExtra(LESSON_ROOM, lesson.room)
|
putExtra(LESSON_ROOM, lesson.room)
|
||||||
putExtra(LESSON_START, lesson.start.toTimestamp())
|
putExtra(LESSON_START, lesson.start.toEpochMilli())
|
||||||
putExtra(LESSON_END, lesson.end.toTimestamp())
|
putExtra(LESSON_END, lesson.end.toEpochMilli())
|
||||||
putExtra(LESSON_TITLE, lesson.subject)
|
putExtra(LESSON_TITLE, lesson.subject)
|
||||||
putExtra(LESSON_NEXT_TITLE, nextLesson?.subject)
|
putExtra(LESSON_NEXT_TITLE, nextLesson?.subject)
|
||||||
putExtra(LESSON_NEXT_ROOM, nextLesson?.room)
|
putExtra(LESSON_NEXT_ROOM, nextLesson?.room)
|
||||||
@ -162,11 +162,11 @@ class TimetableNotificationSchedulerHelper @Inject constructor(
|
|||||||
intent: Intent,
|
intent: Intent,
|
||||||
studentId: Int,
|
studentId: Int,
|
||||||
notificationType: Int,
|
notificationType: Int,
|
||||||
time: LocalDateTime
|
time: Instant
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
AlarmManagerCompat.setExactAndAllowWhileIdle(
|
AlarmManagerCompat.setExactAndAllowWhileIdle(
|
||||||
alarmManager, RTC_WAKEUP, time.toTimestamp(),
|
alarmManager, RTC_WAKEUP, time.toEpochMilli(),
|
||||||
PendingIntent.getBroadcast(context, getRequestCode(time, studentId), intent.also {
|
PendingIntent.getBroadcast(context, getRequestCode(time, studentId), intent.also {
|
||||||
it.putExtra(LESSON_TYPE, notificationType)
|
it.putExtra(LESSON_TYPE, notificationType)
|
||||||
}, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE)
|
}, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE)
|
||||||
|
@ -19,6 +19,9 @@ class VulcanNotificationListenerService : NotificationListenerService() {
|
|||||||
override fun onNotificationPosted(statusBarNotification: StatusBarNotification?) {
|
override fun onNotificationPosted(statusBarNotification: StatusBarNotification?) {
|
||||||
if (statusBarNotification?.packageName == "pl.edu.vulcan.hebe" && preferenceRepository.isNotificationPiggybackEnabled) {
|
if (statusBarNotification?.packageName == "pl.edu.vulcan.hebe" && preferenceRepository.isNotificationPiggybackEnabled) {
|
||||||
syncManager.startOneTimeSyncWorker()
|
syncManager.startOneTimeSyncWorker()
|
||||||
|
if (preferenceRepository.isNotificationPiggybackRemoveOriginalEnabled) {
|
||||||
|
cancelNotification(statusBarNotification.key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -74,10 +74,12 @@ class SyncManager @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startOneTimeSyncWorker(): Flow<WorkInfo?> {
|
// if quiet, no notifications will be sent
|
||||||
|
fun startOneTimeSyncWorker(quiet: Boolean = false): Flow<WorkInfo?> {
|
||||||
val work = OneTimeWorkRequestBuilder<SyncWorker>()
|
val work = OneTimeWorkRequestBuilder<SyncWorker>()
|
||||||
.setInputData(
|
.setInputData(
|
||||||
Data.Builder()
|
Data.Builder()
|
||||||
|
.putBoolean("quiet", quiet)
|
||||||
.putBoolean("one_time", true)
|
.putBoolean("one_time", true)
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
|
@ -23,7 +23,7 @@ import io.github.wulkanowy.utils.DispatchersProvider
|
|||||||
import io.github.wulkanowy.utils.getCompatColor
|
import io.github.wulkanowy.utils.getCompatColor
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.time.LocalDateTime
|
import java.time.Instant
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@HiltWorker
|
@HiltWorker
|
||||||
@ -38,18 +38,23 @@ class SyncWorker @AssistedInject constructor(
|
|||||||
private val dispatchersProvider: DispatchersProvider
|
private val dispatchersProvider: DispatchersProvider
|
||||||
) : CoroutineWorker(appContext, workerParameters) {
|
) : CoroutineWorker(appContext, workerParameters) {
|
||||||
|
|
||||||
override suspend fun doWork() = withContext(dispatchersProvider.io) {
|
override suspend fun doWork(): Result = withContext(dispatchersProvider.io) {
|
||||||
Timber.i("SyncWorker is starting")
|
Timber.i("SyncWorker is starting")
|
||||||
|
|
||||||
if (!studentRepository.isCurrentStudentSet()) return@withContext Result.failure()
|
if (!studentRepository.isCurrentStudentSet()) return@withContext Result.failure()
|
||||||
|
|
||||||
|
val (student, semester) = try {
|
||||||
val student = studentRepository.getCurrentStudent()
|
val student = studentRepository.getCurrentStudent()
|
||||||
val semester = semesterRepository.getCurrentSemester(student, true)
|
val semester = semesterRepository.getCurrentSemester(student, true)
|
||||||
|
student to semester
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
return@withContext getResultFromErrors(listOf(e))
|
||||||
|
}
|
||||||
|
|
||||||
val exceptions = works.mapNotNull { work ->
|
val exceptions = works.mapNotNull { work ->
|
||||||
try {
|
try {
|
||||||
Timber.i("${work::class.java.simpleName} is starting")
|
Timber.i("${work::class.java.simpleName} is starting")
|
||||||
work.doWork(student, semester)
|
work.doWork(student, semester, isNotificationsEnabled())
|
||||||
Timber.i("${work::class.java.simpleName} result: Success")
|
Timber.i("${work::class.java.simpleName} result: Success")
|
||||||
null
|
null
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
@ -62,20 +67,7 @@ class SyncWorker @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val result = when {
|
val result = getResultFromErrors(exceptions)
|
||||||
exceptions.isNotEmpty() && inputData.getBoolean("one_time", false) -> {
|
|
||||||
Result.failure(
|
|
||||||
Data.Builder()
|
|
||||||
.putString("error", exceptions.map { it.stackTraceToString() }.toString())
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
exceptions.isNotEmpty() -> Result.retry()
|
|
||||||
else -> {
|
|
||||||
preferencesRepository.lasSyncDate = LocalDateTime.now()
|
|
||||||
Result.success()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preferencesRepository.isDebugNotificationEnable) notify(result)
|
if (preferencesRepository.isDebugNotificationEnable) notify(result)
|
||||||
Timber.i("SyncWorker result: $result")
|
Timber.i("SyncWorker result: $result")
|
||||||
@ -83,6 +75,27 @@ class SyncWorker @AssistedInject constructor(
|
|||||||
return@withContext result
|
return@withContext result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isNotificationsEnabled(): Boolean {
|
||||||
|
val quiet = inputData.getBoolean("quiet", false)
|
||||||
|
return preferencesRepository.isNotificationsEnable && !quiet
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getResultFromErrors(errors: List<Throwable>): Result = when {
|
||||||
|
errors.isNotEmpty() && inputData.getBoolean("one_time", false) -> {
|
||||||
|
Result.failure(
|
||||||
|
Data.Builder()
|
||||||
|
.putString("error_message", errors.joinToString { it.message.toString() })
|
||||||
|
.putString("error_stack", errors.map { it.stackTraceToString() }.toString())
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
errors.isNotEmpty() -> Result.retry()
|
||||||
|
else -> {
|
||||||
|
preferencesRepository.lasSyncDate = Instant.now()
|
||||||
|
Result.success()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun notify(result: Result) {
|
private fun notify(result: Result) {
|
||||||
notificationManager.notify(
|
notificationManager.notify(
|
||||||
Random.nextInt(Int.MAX_VALUE),
|
Random.nextInt(Int.MAX_VALUE),
|
||||||
|
@ -18,7 +18,7 @@ import io.github.wulkanowy.utils.PendingIntentCompat
|
|||||||
import io.github.wulkanowy.utils.getCompatBitmap
|
import io.github.wulkanowy.utils.getCompatBitmap
|
||||||
import io.github.wulkanowy.utils.getCompatColor
|
import io.github.wulkanowy.utils.getCompatColor
|
||||||
import io.github.wulkanowy.utils.nickOrName
|
import io.github.wulkanowy.utils.nickOrName
|
||||||
import java.time.LocalDateTime
|
import java.time.Instant
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ class AppNotificationManager @Inject constructor(
|
|||||||
NotificationCompat.BigTextStyle()
|
NotificationCompat.BigTextStyle()
|
||||||
.bigText(notificationData.content)
|
.bigText(notificationData.content)
|
||||||
.also { builder ->
|
.also { builder ->
|
||||||
if (shouldShowStudentName()) {
|
if (!studentRepository.isOneUniqueStudent()) {
|
||||||
builder.setSummaryText(student.nickOrName)
|
builder.setSummaryText(student.nickOrName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ class AppNotificationManager @Inject constructor(
|
|||||||
NotificationCompat.BigTextStyle()
|
NotificationCompat.BigTextStyle()
|
||||||
.bigText(notificationData.content)
|
.bigText(notificationData.content)
|
||||||
.also { builder ->
|
.also { builder ->
|
||||||
if (shouldShowStudentName()) {
|
if (!studentRepository.isOneUniqueStudent()) {
|
||||||
builder.setSummaryText(student.nickOrName)
|
builder.setSummaryText(student.nickOrName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,7 +134,7 @@ class AppNotificationManager @Inject constructor(
|
|||||||
.setStyle(
|
.setStyle(
|
||||||
NotificationCompat.InboxStyle()
|
NotificationCompat.InboxStyle()
|
||||||
.also { builder ->
|
.also { builder ->
|
||||||
if (shouldShowStudentName()) {
|
if (!studentRepository.isOneUniqueStudent()) {
|
||||||
builder.setSummaryText(student.nickOrName)
|
builder.setSummaryText(student.nickOrName)
|
||||||
}
|
}
|
||||||
groupNotificationData.notificationDataList.forEach {
|
groupNotificationData.notificationDataList.forEach {
|
||||||
@ -169,12 +169,9 @@ class AppNotificationManager @Inject constructor(
|
|||||||
title = notificationData.title,
|
title = notificationData.title,
|
||||||
content = notificationData.content,
|
content = notificationData.content,
|
||||||
type = notificationType,
|
type = notificationType,
|
||||||
date = LocalDateTime.now()
|
date = Instant.now(),
|
||||||
)
|
)
|
||||||
|
|
||||||
notificationRepository.saveNotification(notificationEntity)
|
notificationRepository.saveNotification(notificationEntity)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun shouldShowStudentName(): Boolean =
|
|
||||||
studentRepository.getSavedStudents(decryptPass = false).size > 1
|
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,8 @@ import io.github.wulkanowy.ui.modules.Destination
|
|||||||
import io.github.wulkanowy.ui.modules.splash.SplashActivity
|
import io.github.wulkanowy.ui.modules.splash.SplashActivity
|
||||||
import io.github.wulkanowy.utils.getPlural
|
import io.github.wulkanowy.utils.getPlural
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
|
import java.time.Instant
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class ChangeTimetableNotification @Inject constructor(
|
class ChangeTimetableNotification @Inject constructor(
|
||||||
@ -21,7 +21,7 @@ class ChangeTimetableNotification @Inject constructor(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun notify(items: List<Timetable>, student: Student) {
|
suspend fun notify(items: List<Timetable>, student: Student) {
|
||||||
val currentTime = LocalDateTime.now()
|
val currentTime = Instant.now()
|
||||||
val changedLessons = items.filter { (it.canceled || it.changes) && it.start > currentTime }
|
val changedLessons = items.filter { (it.canceled || it.changes) && it.start > currentTime }
|
||||||
val notificationDataList = changedLessons.groupBy { it.date }
|
val notificationDataList = changedLessons.groupBy { it.date }
|
||||||
.map { (date, lessons) ->
|
.map { (date, lessons) ->
|
||||||
|
@ -11,7 +11,7 @@ import io.github.wulkanowy.ui.modules.Destination
|
|||||||
import io.github.wulkanowy.ui.modules.splash.SplashActivity
|
import io.github.wulkanowy.ui.modules.splash.SplashActivity
|
||||||
import io.github.wulkanowy.utils.getPlural
|
import io.github.wulkanowy.utils.getPlural
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
import java.time.LocalDateTime
|
import java.time.Instant
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class NewConferenceNotification @Inject constructor(
|
class NewConferenceNotification @Inject constructor(
|
||||||
@ -20,7 +20,7 @@ class NewConferenceNotification @Inject constructor(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun notify(items: List<Conference>, student: Student) {
|
suspend fun notify(items: List<Conference>, student: Student) {
|
||||||
val today = LocalDateTime.now()
|
val today = Instant.now()
|
||||||
val lines = items.filter { !it.date.isBefore(today) }
|
val lines = items.filter { !it.date.isBefore(today) }
|
||||||
.map {
|
.map {
|
||||||
"${it.date.toFormattedString("dd.MM")} - ${it.title}: ${it.subject}"
|
"${it.date.toFormattedString("dd.MM")} - ${it.title}: ${it.subject}"
|
||||||
|
@ -22,7 +22,10 @@ class NewGradeNotification @Inject constructor(
|
|||||||
val notificationDataList = items.map {
|
val notificationDataList = items.map {
|
||||||
NotificationData(
|
NotificationData(
|
||||||
title = context.getPlural(R.plurals.grade_new_items, 1),
|
title = context.getPlural(R.plurals.grade_new_items, 1),
|
||||||
content = "${it.subject}: ${it.entry}",
|
content = buildString {
|
||||||
|
append("${it.subject}: ${it.entry}")
|
||||||
|
if (it.comment.isNotBlank()) append(" (${it.comment})")
|
||||||
|
},
|
||||||
intentToStart = SplashActivity.getStartIntent(context, Destination.Grade),
|
intentToStart = SplashActivity.getStartIntent(context, Destination.Grade),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package io.github.wulkanowy.services.sync.notifications
|
package io.github.wulkanowy.services.sync.notifications
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import androidx.core.text.parseAsHtml
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
|
import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
|
||||||
@ -28,7 +29,7 @@ class NewSchoolAnnouncementNotification @Inject constructor(
|
|||||||
R.plurals.school_announcement_notify_new_item_title,
|
R.plurals.school_announcement_notify_new_item_title,
|
||||||
1
|
1
|
||||||
),
|
),
|
||||||
content = "${it.subject}: ${it.content}"
|
content = "${it.subject}: ${it.content.parseAsHtml()}"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val groupNotificationData = GroupNotificationData(
|
val groupNotificationData = GroupNotificationData(
|
||||||
|
@ -10,7 +10,12 @@ class AttendanceSummaryWork @Inject constructor(
|
|||||||
private val attendanceSummaryRepository: AttendanceSummaryRepository
|
private val attendanceSummaryRepository: AttendanceSummaryRepository
|
||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override suspend fun doWork(student: Student, semester: Semester) {
|
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||||
attendanceSummaryRepository.getAttendanceSummary(student, semester, -1, true).waitForResult()
|
attendanceSummaryRepository.getAttendanceSummary(
|
||||||
|
student = student,
|
||||||
|
semester = semester,
|
||||||
|
subjectId = -1,
|
||||||
|
forceRefresh = true,
|
||||||
|
).waitForResult()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package io.github.wulkanowy.services.sync.works
|
|||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.AttendanceRepository
|
import io.github.wulkanowy.data.repositories.AttendanceRepository
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
|
||||||
import io.github.wulkanowy.services.sync.notifications.NewAttendanceNotification
|
import io.github.wulkanowy.services.sync.notifications.NewAttendanceNotification
|
||||||
import io.github.wulkanowy.utils.previousOrSameSchoolDay
|
import io.github.wulkanowy.utils.previousOrSameSchoolDay
|
||||||
import io.github.wulkanowy.utils.waitForResult
|
import io.github.wulkanowy.utils.waitForResult
|
||||||
@ -14,17 +13,16 @@ import javax.inject.Inject
|
|||||||
class AttendanceWork @Inject constructor(
|
class AttendanceWork @Inject constructor(
|
||||||
private val attendanceRepository: AttendanceRepository,
|
private val attendanceRepository: AttendanceRepository,
|
||||||
private val newAttendanceNotification: NewAttendanceNotification,
|
private val newAttendanceNotification: NewAttendanceNotification,
|
||||||
private val preferencesRepository: PreferencesRepository
|
|
||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override suspend fun doWork(student: Student, semester: Semester) {
|
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||||
attendanceRepository.getAttendance(
|
attendanceRepository.getAttendance(
|
||||||
student = student,
|
student = student,
|
||||||
semester = semester,
|
semester = semester,
|
||||||
start = now().previousOrSameSchoolDay,
|
start = now().previousOrSameSchoolDay,
|
||||||
end = now().previousOrSameSchoolDay,
|
end = now().previousOrSameSchoolDay,
|
||||||
forceRefresh = true,
|
forceRefresh = true,
|
||||||
notify = preferencesRepository.isNotificationsEnable
|
notify = notify,
|
||||||
)
|
)
|
||||||
.waitForResult()
|
.waitForResult()
|
||||||
|
|
||||||
|
@ -13,7 +13,13 @@ class CompletedLessonWork @Inject constructor(
|
|||||||
private val completedLessonsRepository: CompletedLessonsRepository
|
private val completedLessonsRepository: CompletedLessonsRepository
|
||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override suspend fun doWork(student: Student, semester: Semester) {
|
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||||
completedLessonsRepository.getCompletedLessons(student, semester, now().monday, now().sunday, true).waitForResult()
|
completedLessonsRepository.getCompletedLessons(
|
||||||
|
student = student,
|
||||||
|
semester = semester,
|
||||||
|
start = now().monday,
|
||||||
|
end = now().sunday,
|
||||||
|
forceRefresh = true,
|
||||||
|
).waitForResult()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package io.github.wulkanowy.services.sync.works
|
|||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.ConferenceRepository
|
import io.github.wulkanowy.data.repositories.ConferenceRepository
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
|
||||||
import io.github.wulkanowy.services.sync.notifications.NewConferenceNotification
|
import io.github.wulkanowy.services.sync.notifications.NewConferenceNotification
|
||||||
import io.github.wulkanowy.utils.waitForResult
|
import io.github.wulkanowy.utils.waitForResult
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
@ -11,16 +10,15 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
class ConferenceWork @Inject constructor(
|
class ConferenceWork @Inject constructor(
|
||||||
private val conferenceRepository: ConferenceRepository,
|
private val conferenceRepository: ConferenceRepository,
|
||||||
private val preferencesRepository: PreferencesRepository,
|
|
||||||
private val newConferenceNotification: NewConferenceNotification,
|
private val newConferenceNotification: NewConferenceNotification,
|
||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override suspend fun doWork(student: Student, semester: Semester) {
|
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||||
conferenceRepository.getConferences(
|
conferenceRepository.getConferences(
|
||||||
student = student,
|
student = student,
|
||||||
semester = semester,
|
semester = semester,
|
||||||
forceRefresh = true,
|
forceRefresh = true,
|
||||||
notify = preferencesRepository.isNotificationsEnable
|
notify = notify
|
||||||
).waitForResult()
|
).waitForResult()
|
||||||
|
|
||||||
conferenceRepository.getConferenceFromDatabase(semester).first()
|
conferenceRepository.getConferenceFromDatabase(semester).first()
|
||||||
|
@ -3,7 +3,6 @@ package io.github.wulkanowy.services.sync.works
|
|||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.ExamRepository
|
import io.github.wulkanowy.data.repositories.ExamRepository
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
|
||||||
import io.github.wulkanowy.services.sync.notifications.NewExamNotification
|
import io.github.wulkanowy.services.sync.notifications.NewExamNotification
|
||||||
import io.github.wulkanowy.utils.waitForResult
|
import io.github.wulkanowy.utils.waitForResult
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
@ -12,18 +11,17 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
class ExamWork @Inject constructor(
|
class ExamWork @Inject constructor(
|
||||||
private val examRepository: ExamRepository,
|
private val examRepository: ExamRepository,
|
||||||
private val preferencesRepository: PreferencesRepository,
|
|
||||||
private val newExamNotification: NewExamNotification,
|
private val newExamNotification: NewExamNotification,
|
||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override suspend fun doWork(student: Student, semester: Semester) {
|
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||||
examRepository.getExams(
|
examRepository.getExams(
|
||||||
student = student,
|
student = student,
|
||||||
semester = semester,
|
semester = semester,
|
||||||
start = now(),
|
start = now(),
|
||||||
end = now(),
|
end = now(),
|
||||||
forceRefresh = true,
|
forceRefresh = true,
|
||||||
notify = preferencesRepository.isNotificationsEnable
|
notify = notify,
|
||||||
).waitForResult()
|
).waitForResult()
|
||||||
|
|
||||||
examRepository.getExamsFromDatabase(semester, now()).first()
|
examRepository.getExamsFromDatabase(semester, now()).first()
|
||||||
|
@ -10,7 +10,7 @@ class GradeStatisticsWork @Inject constructor(
|
|||||||
private val gradeStatisticsRepository: GradeStatisticsRepository
|
private val gradeStatisticsRepository: GradeStatisticsRepository
|
||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override suspend fun doWork(student: Student, semester: Semester) {
|
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||||
with(gradeStatisticsRepository) {
|
with(gradeStatisticsRepository) {
|
||||||
getGradesPartialStatistics(student, semester, "Wszystkie", forceRefresh = true).waitForResult()
|
getGradesPartialStatistics(student, semester, "Wszystkie", forceRefresh = true).waitForResult()
|
||||||
getGradesSemesterStatistics(student, semester, "Wszystkie", forceRefresh = true).waitForResult()
|
getGradesSemesterStatistics(student, semester, "Wszystkie", forceRefresh = true).waitForResult()
|
||||||
|
@ -3,7 +3,6 @@ package io.github.wulkanowy.services.sync.works
|
|||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.GradeRepository
|
import io.github.wulkanowy.data.repositories.GradeRepository
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
|
||||||
import io.github.wulkanowy.services.sync.notifications.NewGradeNotification
|
import io.github.wulkanowy.services.sync.notifications.NewGradeNotification
|
||||||
import io.github.wulkanowy.utils.waitForResult
|
import io.github.wulkanowy.utils.waitForResult
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
@ -11,16 +10,15 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
class GradeWork @Inject constructor(
|
class GradeWork @Inject constructor(
|
||||||
private val gradeRepository: GradeRepository,
|
private val gradeRepository: GradeRepository,
|
||||||
private val preferencesRepository: PreferencesRepository,
|
|
||||||
private val newGradeNotification: NewGradeNotification,
|
private val newGradeNotification: NewGradeNotification,
|
||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override suspend fun doWork(student: Student, semester: Semester) {
|
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||||
gradeRepository.getGrades(
|
gradeRepository.getGrades(
|
||||||
student = student,
|
student = student,
|
||||||
semester = semester,
|
semester = semester,
|
||||||
forceRefresh = true,
|
forceRefresh = true,
|
||||||
notify = preferencesRepository.isNotificationsEnable
|
notify = notify,
|
||||||
).waitForResult()
|
).waitForResult()
|
||||||
|
|
||||||
gradeRepository.getGradesFromDatabase(semester).first()
|
gradeRepository.getGradesFromDatabase(semester).first()
|
||||||
|
@ -3,7 +3,6 @@ package io.github.wulkanowy.services.sync.works
|
|||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.HomeworkRepository
|
import io.github.wulkanowy.data.repositories.HomeworkRepository
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
|
||||||
import io.github.wulkanowy.services.sync.notifications.NewHomeworkNotification
|
import io.github.wulkanowy.services.sync.notifications.NewHomeworkNotification
|
||||||
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
||||||
import io.github.wulkanowy.utils.waitForResult
|
import io.github.wulkanowy.utils.waitForResult
|
||||||
@ -13,18 +12,17 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
class HomeworkWork @Inject constructor(
|
class HomeworkWork @Inject constructor(
|
||||||
private val homeworkRepository: HomeworkRepository,
|
private val homeworkRepository: HomeworkRepository,
|
||||||
private val preferencesRepository: PreferencesRepository,
|
|
||||||
private val newHomeworkNotification: NewHomeworkNotification,
|
private val newHomeworkNotification: NewHomeworkNotification,
|
||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override suspend fun doWork(student: Student, semester: Semester) {
|
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||||
homeworkRepository.getHomework(
|
homeworkRepository.getHomework(
|
||||||
student = student,
|
student = student,
|
||||||
semester = semester,
|
semester = semester,
|
||||||
start = now().nextOrSameSchoolDay,
|
start = now().nextOrSameSchoolDay,
|
||||||
end = now().nextOrSameSchoolDay,
|
end = now().nextOrSameSchoolDay,
|
||||||
forceRefresh = true,
|
forceRefresh = true,
|
||||||
notify = preferencesRepository.isNotificationsEnable
|
notify = notify,
|
||||||
).waitForResult()
|
).waitForResult()
|
||||||
|
|
||||||
homeworkRepository.getHomeworkFromDatabase(semester, now(), now().plusDays(7)).first()
|
homeworkRepository.getHomeworkFromDatabase(semester, now(), now().plusDays(7)).first()
|
||||||
|
@ -3,22 +3,20 @@ package io.github.wulkanowy.services.sync.works
|
|||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.LuckyNumberRepository
|
import io.github.wulkanowy.data.repositories.LuckyNumberRepository
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
|
||||||
import io.github.wulkanowy.services.sync.notifications.NewLuckyNumberNotification
|
import io.github.wulkanowy.services.sync.notifications.NewLuckyNumberNotification
|
||||||
import io.github.wulkanowy.utils.waitForResult
|
import io.github.wulkanowy.utils.waitForResult
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class LuckyNumberWork @Inject constructor(
|
class LuckyNumberWork @Inject constructor(
|
||||||
private val luckyNumberRepository: LuckyNumberRepository,
|
private val luckyNumberRepository: LuckyNumberRepository,
|
||||||
private val preferencesRepository: PreferencesRepository,
|
|
||||||
private val newLuckyNumberNotification: NewLuckyNumberNotification,
|
private val newLuckyNumberNotification: NewLuckyNumberNotification,
|
||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override suspend fun doWork(student: Student, semester: Semester) {
|
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||||
luckyNumberRepository.getLuckyNumber(
|
luckyNumberRepository.getLuckyNumber(
|
||||||
student = student,
|
student = student,
|
||||||
forceRefresh = true,
|
forceRefresh = true,
|
||||||
notify = preferencesRepository.isNotificationsEnable
|
notify = notify,
|
||||||
).waitForResult()
|
).waitForResult()
|
||||||
|
|
||||||
luckyNumberRepository.getNotNotifiedLuckyNumber(student)?.let {
|
luckyNumberRepository.getNotNotifiedLuckyNumber(student)?.let {
|
||||||
|
@ -4,7 +4,6 @@ import io.github.wulkanowy.data.db.entities.Semester
|
|||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.enums.MessageFolder.RECEIVED
|
import io.github.wulkanowy.data.enums.MessageFolder.RECEIVED
|
||||||
import io.github.wulkanowy.data.repositories.MessageRepository
|
import io.github.wulkanowy.data.repositories.MessageRepository
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
|
||||||
import io.github.wulkanowy.services.sync.notifications.NewMessageNotification
|
import io.github.wulkanowy.services.sync.notifications.NewMessageNotification
|
||||||
import io.github.wulkanowy.utils.waitForResult
|
import io.github.wulkanowy.utils.waitForResult
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
@ -12,17 +11,16 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
class MessageWork @Inject constructor(
|
class MessageWork @Inject constructor(
|
||||||
private val messageRepository: MessageRepository,
|
private val messageRepository: MessageRepository,
|
||||||
private val preferencesRepository: PreferencesRepository,
|
|
||||||
private val newMessageNotification: NewMessageNotification,
|
private val newMessageNotification: NewMessageNotification,
|
||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override suspend fun doWork(student: Student, semester: Semester) {
|
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||||
messageRepository.getMessages(
|
messageRepository.getMessages(
|
||||||
student = student,
|
student = student,
|
||||||
semester = semester,
|
semester = semester,
|
||||||
folder = RECEIVED,
|
folder = RECEIVED,
|
||||||
forceRefresh = true,
|
forceRefresh = true,
|
||||||
notify = preferencesRepository.isNotificationsEnable
|
notify = notify
|
||||||
).waitForResult()
|
).waitForResult()
|
||||||
|
|
||||||
messageRepository.getMessagesFromDatabase(student).first()
|
messageRepository.getMessagesFromDatabase(student).first()
|
||||||
|
@ -3,7 +3,6 @@ package io.github.wulkanowy.services.sync.works
|
|||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.NoteRepository
|
import io.github.wulkanowy.data.repositories.NoteRepository
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
|
||||||
import io.github.wulkanowy.services.sync.notifications.NewNoteNotification
|
import io.github.wulkanowy.services.sync.notifications.NewNoteNotification
|
||||||
import io.github.wulkanowy.utils.waitForResult
|
import io.github.wulkanowy.utils.waitForResult
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
@ -11,16 +10,15 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
class NoteWork @Inject constructor(
|
class NoteWork @Inject constructor(
|
||||||
private val noteRepository: NoteRepository,
|
private val noteRepository: NoteRepository,
|
||||||
private val preferencesRepository: PreferencesRepository,
|
|
||||||
private val newNoteNotification: NewNoteNotification,
|
private val newNoteNotification: NewNoteNotification,
|
||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override suspend fun doWork(student: Student, semester: Semester) {
|
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||||
noteRepository.getNotes(
|
noteRepository.getNotes(
|
||||||
student = student,
|
student = student,
|
||||||
semester = semester,
|
semester = semester,
|
||||||
forceRefresh = true,
|
forceRefresh = true,
|
||||||
notify = preferencesRepository.isNotificationsEnable
|
notify = notify,
|
||||||
).waitForResult()
|
).waitForResult()
|
||||||
|
|
||||||
noteRepository.getNotesFromDatabase(student).first()
|
noteRepository.getNotesFromDatabase(student).first()
|
||||||
|
@ -11,7 +11,7 @@ class RecipientWork @Inject constructor(
|
|||||||
private val recipientRepository: RecipientRepository
|
private val recipientRepository: RecipientRepository
|
||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override suspend fun doWork(student: Student, semester: Semester) {
|
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||||
reportingUnitRepository.refreshReportingUnits(student)
|
reportingUnitRepository.refreshReportingUnits(student)
|
||||||
|
|
||||||
reportingUnitRepository.getReportingUnits(student).let { units ->
|
reportingUnitRepository.getReportingUnits(student).let { units ->
|
||||||
|
@ -2,7 +2,6 @@ package io.github.wulkanowy.services.sync.works
|
|||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
|
||||||
import io.github.wulkanowy.data.repositories.SchoolAnnouncementRepository
|
import io.github.wulkanowy.data.repositories.SchoolAnnouncementRepository
|
||||||
import io.github.wulkanowy.services.sync.notifications.NewSchoolAnnouncementNotification
|
import io.github.wulkanowy.services.sync.notifications.NewSchoolAnnouncementNotification
|
||||||
import io.github.wulkanowy.utils.waitForResult
|
import io.github.wulkanowy.utils.waitForResult
|
||||||
@ -11,15 +10,14 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
class SchoolAnnouncementWork @Inject constructor(
|
class SchoolAnnouncementWork @Inject constructor(
|
||||||
private val schoolAnnouncementRepository: SchoolAnnouncementRepository,
|
private val schoolAnnouncementRepository: SchoolAnnouncementRepository,
|
||||||
private val preferencesRepository: PreferencesRepository,
|
|
||||||
private val newSchoolAnnouncementNotification: NewSchoolAnnouncementNotification,
|
private val newSchoolAnnouncementNotification: NewSchoolAnnouncementNotification,
|
||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override suspend fun doWork(student: Student, semester: Semester) {
|
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||||
schoolAnnouncementRepository.getSchoolAnnouncements(
|
schoolAnnouncementRepository.getSchoolAnnouncements(
|
||||||
student = student,
|
student = student,
|
||||||
forceRefresh = true,
|
forceRefresh = true,
|
||||||
notify = preferencesRepository.isNotificationsEnable
|
notify = notify,
|
||||||
).waitForResult()
|
).waitForResult()
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
class TeacherWork @Inject constructor(private val teacherRepository: TeacherRepository) : Work {
|
class TeacherWork @Inject constructor(private val teacherRepository: TeacherRepository) : Work {
|
||||||
|
|
||||||
override suspend fun doWork(student: Student, semester: Semester) {
|
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||||
teacherRepository.getTeachers(student, semester, true).waitForResult()
|
teacherRepository.getTeachers(student, semester, true).waitForResult()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package io.github.wulkanowy.services.sync.works
|
|||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Semester
|
import io.github.wulkanowy.data.db.entities.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
|
||||||
import io.github.wulkanowy.data.repositories.TimetableRepository
|
import io.github.wulkanowy.data.repositories.TimetableRepository
|
||||||
import io.github.wulkanowy.services.sync.notifications.ChangeTimetableNotification
|
import io.github.wulkanowy.services.sync.notifications.ChangeTimetableNotification
|
||||||
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
||||||
@ -14,17 +13,16 @@ import javax.inject.Inject
|
|||||||
class TimetableWork @Inject constructor(
|
class TimetableWork @Inject constructor(
|
||||||
private val timetableRepository: TimetableRepository,
|
private val timetableRepository: TimetableRepository,
|
||||||
private val changeTimetableNotification: ChangeTimetableNotification,
|
private val changeTimetableNotification: ChangeTimetableNotification,
|
||||||
private val preferencesRepository: PreferencesRepository
|
|
||||||
) : Work {
|
) : Work {
|
||||||
|
|
||||||
override suspend fun doWork(student: Student, semester: Semester) {
|
override suspend fun doWork(student: Student, semester: Semester, notify: Boolean) {
|
||||||
timetableRepository.getTimetable(
|
timetableRepository.getTimetable(
|
||||||
student = student,
|
student = student,
|
||||||
semester = semester,
|
semester = semester,
|
||||||
start = now().nextOrSameSchoolDay,
|
start = now().nextOrSameSchoolDay,
|
||||||
end = now().nextOrSameSchoolDay,
|
end = now().nextOrSameSchoolDay,
|
||||||
forceRefresh = true,
|
forceRefresh = true,
|
||||||
notify = preferencesRepository.isNotificationsEnable
|
notify = notify,
|
||||||
)
|
)
|
||||||
.waitForResult()
|
.waitForResult()
|
||||||
|
|
||||||
|
@ -5,5 +5,5 @@ import io.github.wulkanowy.data.db.entities.Student
|
|||||||
|
|
||||||
interface Work {
|
interface Work {
|
||||||
|
|
||||||
suspend fun doWork(student: Student, semester: Semester)
|
suspend fun doWork(student: Student, semester: Semester, notify: Boolean)
|
||||||
}
|
}
|
||||||
|
@ -1,100 +1,82 @@
|
|||||||
package io.github.wulkanowy.ui.base
|
package io.github.wulkanowy.ui.base
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
import android.content.ClipData
|
import android.content.ClipData
|
||||||
import android.content.ClipboardManager
|
import android.content.ClipboardManager
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.HorizontalScrollView
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import android.widget.Toast.LENGTH_LONG
|
import android.widget.Toast.LENGTH_LONG
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.databinding.DialogErrorBinding
|
import io.github.wulkanowy.databinding.DialogErrorBinding
|
||||||
import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException
|
|
||||||
import io.github.wulkanowy.sdk.scrapper.exception.ServiceUnavailableException
|
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
|
||||||
import io.github.wulkanowy.utils.getString
|
|
||||||
import io.github.wulkanowy.utils.openAppInMarket
|
|
||||||
import io.github.wulkanowy.utils.openEmailClient
|
|
||||||
import io.github.wulkanowy.utils.openInternetBrowser
|
|
||||||
import okhttp3.internal.http2.StreamResetException
|
|
||||||
import java.io.InterruptedIOException
|
|
||||||
import java.net.ConnectException
|
|
||||||
import java.net.SocketTimeoutException
|
|
||||||
import java.net.UnknownHostException
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class ErrorDialog : BaseDialogFragment<DialogErrorBinding>() {
|
class ErrorDialog : DialogFragment() {
|
||||||
|
|
||||||
private lateinit var error: Throwable
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var appInfo: AppInfo
|
lateinit var appInfo: AppInfo
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val ARGUMENT_KEY = "Data"
|
private const val ARGUMENT_KEY = "error"
|
||||||
|
|
||||||
fun newInstance(error: Throwable) = ErrorDialog().apply {
|
fun newInstance(error: Throwable) = ErrorDialog().apply {
|
||||||
arguments = Bundle().apply { putSerializable(ARGUMENT_KEY, error) }
|
arguments = bundleOf(ARGUMENT_KEY to error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
super.onCreate(savedInstanceState)
|
val error = requireArguments().getSerializable(ARGUMENT_KEY) as Throwable
|
||||||
setStyle(STYLE_NO_TITLE, 0)
|
|
||||||
arguments?.run {
|
val binding = DialogErrorBinding.inflate(LayoutInflater.from(context))
|
||||||
error = getSerializable(ARGUMENT_KEY) as Throwable
|
binding.bindErrorDetails(error)
|
||||||
|
|
||||||
|
return getAlertDialog(binding, error).apply {
|
||||||
|
enableReportButtonIfErrorIsReportable(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
private fun getAlertDialog(binding: DialogErrorBinding, error: Throwable): AlertDialog {
|
||||||
inflater: LayoutInflater,
|
return MaterialAlertDialogBuilder(requireContext()).apply {
|
||||||
container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
) = DialogErrorBinding.inflate(inflater).apply { binding = this }.root
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
|
|
||||||
val errorStacktrace = error.stackTraceToString()
|
val errorStacktrace = error.stackTraceToString()
|
||||||
|
setTitle(R.string.all_details)
|
||||||
with(binding) {
|
setView(binding.root)
|
||||||
errorDialogContent.text = errorStacktrace.replace(": ${error.localizedMessage}", "")
|
setNeutralButton(R.string.about_feedback) { _, _ ->
|
||||||
with(errorDialogHorizontalScroll) {
|
|
||||||
post { fullScroll(HorizontalScrollView.FOCUS_LEFT) }
|
|
||||||
}
|
|
||||||
errorDialogCopy.setOnClickListener {
|
|
||||||
val clip = ClipData.newPlainText("Error details", errorStacktrace)
|
|
||||||
activity?.getSystemService<ClipboardManager>()?.setPrimaryClip(clip)
|
|
||||||
|
|
||||||
Toast.makeText(context, R.string.all_copied, LENGTH_LONG).show()
|
|
||||||
}
|
|
||||||
errorDialogCancel.setOnClickListener { dismiss() }
|
|
||||||
errorDialogReport.setOnClickListener {
|
|
||||||
openConfirmDialog { openEmailClient(errorStacktrace) }
|
openConfirmDialog { openEmailClient(errorStacktrace) }
|
||||||
}
|
}
|
||||||
errorDialogHumanizedMessage.text = resources.getString(error)
|
setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||||
|
setPositiveButton(android.R.string.copy) { _, _ -> copyErrorToClipboard(errorStacktrace) }
|
||||||
|
}.create()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun DialogErrorBinding.bindErrorDetails(error: Throwable) {
|
||||||
|
return with(this) {
|
||||||
|
errorDialogHumanizedMessage.text = resources.getErrorString(error)
|
||||||
errorDialogErrorMessage.text = error.localizedMessage
|
errorDialogErrorMessage.text = error.localizedMessage
|
||||||
errorDialogErrorMessage.isGone = error.localizedMessage.isNullOrBlank()
|
errorDialogErrorMessage.isGone = error.localizedMessage.isNullOrBlank()
|
||||||
errorDialogReport.isEnabled = when (error) {
|
errorDialogContent.text = error.stackTraceToString()
|
||||||
is UnknownHostException,
|
.replace(": ${error.localizedMessage}", "")
|
||||||
is InterruptedIOException,
|
|
||||||
is ConnectException,
|
|
||||||
is StreamResetException,
|
|
||||||
is SocketTimeoutException,
|
|
||||||
is ServiceUnavailableException,
|
|
||||||
is FeatureDisabledException,
|
|
||||||
is FeatureNotAvailableException -> false
|
|
||||||
else -> true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun AlertDialog.enableReportButtonIfErrorIsReportable(error: Throwable) {
|
||||||
|
setOnShowListener {
|
||||||
|
getButton(AlertDialog.BUTTON_NEUTRAL).isEnabled = error.isShouldBeReported()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun copyErrorToClipboard(errorStacktrace: String) {
|
||||||
|
val clip = ClipData.newPlainText("Error details", errorStacktrace)
|
||||||
|
requireActivity().getSystemService<ClipboardManager>()?.setPrimaryClip(clip)
|
||||||
|
Toast.makeText(requireContext(), R.string.all_copied, LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun openConfirmDialog(callback: () -> Unit) {
|
private fun openConfirmDialog(callback: () -> Unit) {
|
||||||
@ -127,4 +109,8 @@ class ErrorDialog : BaseDialogFragment<DialogErrorBinding>() {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showMessage(text: String) {
|
||||||
|
Toast.makeText(requireContext(), text, LENGTH_LONG).show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext
|
|||||||
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
|
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
|
||||||
import io.github.wulkanowy.sdk.scrapper.login.BadCredentialsException
|
import io.github.wulkanowy.sdk.scrapper.login.BadCredentialsException
|
||||||
import io.github.wulkanowy.sdk.scrapper.login.PasswordChangeRequiredException
|
import io.github.wulkanowy.sdk.scrapper.login.PasswordChangeRequiredException
|
||||||
import io.github.wulkanowy.utils.getString
|
import io.github.wulkanowy.utils.getErrorString
|
||||||
import io.github.wulkanowy.utils.security.ScramblerException
|
import io.github.wulkanowy.utils.security.ScramblerException
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -26,7 +26,7 @@ open class ErrorHandler @Inject constructor(@ApplicationContext protected val co
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected open fun proceed(error: Throwable) {
|
protected open fun proceed(error: Throwable) {
|
||||||
showErrorMessage(context.resources.getString(error), error)
|
showErrorMessage(context.resources.getErrorString(error), error)
|
||||||
when (error) {
|
when (error) {
|
||||||
is PasswordChangeRequiredException -> onPasswordChangeRequired(error.redirectUrl)
|
is PasswordChangeRequiredException -> onPasswordChangeRequired(error.redirectUrl)
|
||||||
is ScramblerException, is BadCredentialsException -> onSessionExpired()
|
is ScramblerException, is BadCredentialsException -> onSessionExpired()
|
||||||
|
@ -13,13 +13,8 @@ import io.github.wulkanowy.ui.modules.about.license.LicenseFragment
|
|||||||
import io.github.wulkanowy.ui.modules.debug.DebugFragment
|
import io.github.wulkanowy.ui.modules.debug.DebugFragment
|
||||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||||
import io.github.wulkanowy.ui.modules.main.MainView
|
import io.github.wulkanowy.ui.modules.main.MainView
|
||||||
import io.github.wulkanowy.utils.AppInfo
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getCompatDrawable
|
import java.time.Instant
|
||||||
import io.github.wulkanowy.utils.openAppInMarket
|
|
||||||
import io.github.wulkanowy.utils.openEmailClient
|
|
||||||
import io.github.wulkanowy.utils.openInternetBrowser
|
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
|
||||||
import io.github.wulkanowy.utils.toLocalDateTime
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -38,7 +33,7 @@ class AboutFragment : BaseFragment<FragmentAboutBinding>(R.layout.fragment_about
|
|||||||
override val versionRes: Triple<String, String, Drawable?>?
|
override val versionRes: Triple<String, String, Drawable?>?
|
||||||
get() = context?.run {
|
get() = context?.run {
|
||||||
val buildTimestamp =
|
val buildTimestamp =
|
||||||
appInfo.buildTimestamp.toLocalDateTime().toFormattedString("yyyy-MM-dd")
|
Instant.ofEpochMilli(appInfo.buildTimestamp).toFormattedString("yyyy-MM-dd")
|
||||||
val versionSignature =
|
val versionSignature =
|
||||||
"${appInfo.versionName}-${appInfo.buildFlavor} (${appInfo.versionCode}), $buildTimestamp"
|
"${appInfo.versionName}-${appInfo.buildFlavor} (${appInfo.versionCode}), $buildTimestamp"
|
||||||
Triple(
|
Triple(
|
||||||
|
@ -14,8 +14,6 @@ import androidx.appcompat.app.AlertDialog
|
|||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.google.android.material.datepicker.CalendarConstraints
|
|
||||||
import com.google.android.material.datepicker.MaterialDatePicker
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Attendance
|
import io.github.wulkanowy.data.db.entities.Attendance
|
||||||
@ -27,12 +25,10 @@ import io.github.wulkanowy.ui.modules.main.MainActivity
|
|||||||
import io.github.wulkanowy.ui.modules.main.MainView
|
import io.github.wulkanowy.ui.modules.main.MainView
|
||||||
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
|
import io.github.wulkanowy.ui.modules.message.send.SendMessageActivity
|
||||||
import io.github.wulkanowy.ui.widgets.DividerItemDecoration
|
import io.github.wulkanowy.ui.widgets.DividerItemDecoration
|
||||||
import io.github.wulkanowy.utils.SchoolDaysValidator
|
|
||||||
import io.github.wulkanowy.utils.dpToPx
|
import io.github.wulkanowy.utils.dpToPx
|
||||||
|
import io.github.wulkanowy.utils.firstSchoolDayInSchoolYear
|
||||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
import io.github.wulkanowy.utils.getThemeAttrColor
|
||||||
import io.github.wulkanowy.utils.schoolYearStart
|
import io.github.wulkanowy.utils.openMaterialDatePicker
|
||||||
import io.github.wulkanowy.utils.toLocalDateTime
|
|
||||||
import io.github.wulkanowy.utils.toTimestamp
|
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -224,29 +220,15 @@ class AttendanceFragment : BaseFragment<FragmentAttendanceBinding>(R.layout.frag
|
|||||||
(activity as? MainActivity)?.showDialogFragment(AttendanceDialog.newInstance(lesson))
|
(activity as? MainActivity)?.showDialogFragment(AttendanceDialog.newInstance(lesson))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showDatePickerDialog(currentDate: LocalDate) {
|
override fun showDatePickerDialog(selectedDate: LocalDate) {
|
||||||
val baseDate = currentDate.schoolYearStart
|
openMaterialDatePicker(
|
||||||
val rangeStart = baseDate.toTimestamp()
|
selected = selectedDate,
|
||||||
val rangeEnd = LocalDate.now().plusWeeks(1).toTimestamp()
|
rangeStart = selectedDate.firstSchoolDayInSchoolYear,
|
||||||
|
rangeEnd = LocalDate.now().plusWeeks(1),
|
||||||
val constraintsBuilder = CalendarConstraints.Builder().apply {
|
onDateSelected = {
|
||||||
setValidator(SchoolDaysValidator(rangeStart, rangeEnd))
|
presenter.onDateSet(it.year, it.monthValue, it.dayOfMonth)
|
||||||
setStart(rangeStart)
|
|
||||||
setEnd(rangeEnd)
|
|
||||||
}
|
|
||||||
val datePicker = MaterialDatePicker.Builder.datePicker()
|
|
||||||
.setCalendarConstraints(constraintsBuilder.build())
|
|
||||||
.setSelection(currentDate.toTimestamp())
|
|
||||||
.build()
|
|
||||||
|
|
||||||
datePicker.addOnPositiveButtonClickListener {
|
|
||||||
val date = it.toLocalDateTime()
|
|
||||||
presenter.onDateSet(date.year, date.monthValue, date.dayOfMonth)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!parentFragmentManager.isStateSaved) {
|
|
||||||
datePicker.show(parentFragmentManager, null)
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showExcuseDialog() {
|
override fun showExcuseDialog() {
|
||||||
|
@ -48,7 +48,7 @@ interface AttendanceView : BaseView {
|
|||||||
|
|
||||||
fun showAttendanceDialog(lesson: Attendance)
|
fun showAttendanceDialog(lesson: Attendance)
|
||||||
|
|
||||||
fun showDatePickerDialog(currentDate: LocalDate)
|
fun showDatePickerDialog(selectedDate: LocalDate)
|
||||||
|
|
||||||
fun showExcuseDialog()
|
fun showExcuseDialog()
|
||||||
|
|
||||||
|
@ -37,9 +37,7 @@ import io.github.wulkanowy.utils.left
|
|||||||
import io.github.wulkanowy.utils.nickOrName
|
import io.github.wulkanowy.utils.nickOrName
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.time.Duration
|
import java.time.*
|
||||||
import java.time.LocalDate
|
|
||||||
import java.time.LocalDateTime
|
|
||||||
import java.util.Timer
|
import java.util.Timer
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.concurrent.timer
|
import kotlin.concurrent.timer
|
||||||
@ -291,7 +289,7 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
|
|||||||
var dateToNavigate = LocalDate.now()
|
var dateToNavigate = LocalDate.now()
|
||||||
|
|
||||||
fun updateLessonState() {
|
fun updateLessonState() {
|
||||||
val currentDateTime = LocalDateTime.now()
|
val currentDateTime = Instant.now()
|
||||||
val currentDate = LocalDate.now()
|
val currentDate = LocalDate.now()
|
||||||
val tomorrowDate = currentDate.plusDays(1)
|
val tomorrowDate = currentDate.plusDays(1)
|
||||||
|
|
||||||
@ -361,7 +359,7 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
|
|||||||
binding: ItemDashboardLessonsBinding,
|
binding: ItemDashboardLessonsBinding,
|
||||||
header: TimetableHeader? = null,
|
header: TimetableHeader? = null,
|
||||||
) {
|
) {
|
||||||
val currentDateTime = LocalDateTime.now()
|
val currentDateTime = Instant.now()
|
||||||
val nextLessons = timetableToShow.filter { it.end.isAfter(currentDateTime) }
|
val nextLessons = timetableToShow.filter { it.end.isAfter(currentDateTime) }
|
||||||
.sortedBy { it.start }
|
.sortedBy { it.start }
|
||||||
|
|
||||||
@ -386,7 +384,7 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
|
|||||||
private fun updateFirstLessonView(
|
private fun updateFirstLessonView(
|
||||||
binding: ItemDashboardLessonsBinding,
|
binding: ItemDashboardLessonsBinding,
|
||||||
firstLesson: Timetable?,
|
firstLesson: Timetable?,
|
||||||
currentDateTime: LocalDateTime
|
currentDateTime: Instant
|
||||||
) {
|
) {
|
||||||
val context = binding.root.context
|
val context = binding.root.context
|
||||||
val sansSerifFont = Typeface.create("sans-serif", Typeface.NORMAL)
|
val sansSerifFont = Typeface.create("sans-serif", Typeface.NORMAL)
|
||||||
|
@ -28,10 +28,7 @@ import io.github.wulkanowy.ui.modules.message.MessageFragment
|
|||||||
import io.github.wulkanowy.ui.modules.notificationscenter.NotificationsCenterFragment
|
import io.github.wulkanowy.ui.modules.notificationscenter.NotificationsCenterFragment
|
||||||
import io.github.wulkanowy.ui.modules.schoolannouncement.SchoolAnnouncementFragment
|
import io.github.wulkanowy.ui.modules.schoolannouncement.SchoolAnnouncementFragment
|
||||||
import io.github.wulkanowy.ui.modules.timetable.TimetableFragment
|
import io.github.wulkanowy.ui.modules.timetable.TimetableFragment
|
||||||
import io.github.wulkanowy.utils.capitalise
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
|
||||||
import io.github.wulkanowy.utils.openInternetBrowser
|
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -178,8 +175,8 @@ class DashboardFragment : BaseFragment<FragmentDashboardBinding>(R.layout.fragme
|
|||||||
binding.dashboardErrorContainer.isVisible = show
|
binding.dashboardErrorContainer.isVisible = show
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setErrorDetails(message: String) {
|
override fun setErrorDetails(error: Throwable) {
|
||||||
binding.dashboardErrorMessage.text = message
|
binding.dashboardErrorMessage.text = requireContext().resources.getErrorString(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun resetView() {
|
override fun resetView() {
|
||||||
|
@ -6,37 +6,17 @@ import io.github.wulkanowy.data.db.entities.AdminMessage
|
|||||||
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
import io.github.wulkanowy.data.db.entities.LuckyNumber
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.enums.MessageFolder
|
import io.github.wulkanowy.data.enums.MessageFolder
|
||||||
import io.github.wulkanowy.data.repositories.AdminMessageRepository
|
import io.github.wulkanowy.data.repositories.*
|
||||||
import io.github.wulkanowy.data.repositories.AttendanceSummaryRepository
|
|
||||||
import io.github.wulkanowy.data.repositories.ConferenceRepository
|
|
||||||
import io.github.wulkanowy.data.repositories.ExamRepository
|
|
||||||
import io.github.wulkanowy.data.repositories.GradeRepository
|
|
||||||
import io.github.wulkanowy.data.repositories.HomeworkRepository
|
|
||||||
import io.github.wulkanowy.data.repositories.LuckyNumberRepository
|
|
||||||
import io.github.wulkanowy.data.repositories.MessageRepository
|
|
||||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
|
||||||
import io.github.wulkanowy.data.repositories.SchoolAnnouncementRepository
|
|
||||||
import io.github.wulkanowy.data.repositories.SemesterRepository
|
|
||||||
import io.github.wulkanowy.data.repositories.StudentRepository
|
|
||||||
import io.github.wulkanowy.data.repositories.TimetableRepository
|
|
||||||
import io.github.wulkanowy.ui.base.BasePresenter
|
import io.github.wulkanowy.ui.base.BasePresenter
|
||||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||||
import io.github.wulkanowy.utils.calculatePercentage
|
import io.github.wulkanowy.utils.calculatePercentage
|
||||||
import io.github.wulkanowy.utils.flowWithResourceIn
|
import io.github.wulkanowy.utils.flowWithResourceIn
|
||||||
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
import io.github.wulkanowy.utils.nextOrSameSchoolDay
|
||||||
import kotlinx.coroutines.flow.catch
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.flow.combine
|
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
|
||||||
import kotlinx.coroutines.flow.emitAll
|
|
||||||
import kotlinx.coroutines.flow.filterNot
|
|
||||||
import kotlinx.coroutines.flow.flow
|
|
||||||
import kotlinx.coroutines.flow.flowOf
|
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
import kotlinx.coroutines.flow.onEach
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import java.time.Instant
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class DashboardPresenter @Inject constructor(
|
class DashboardPresenter @Inject constructor(
|
||||||
@ -552,7 +532,7 @@ class DashboardPresenter @Inject constructor(
|
|||||||
student = student,
|
student = student,
|
||||||
semester = semester,
|
semester = semester,
|
||||||
forceRefresh = forceRefresh,
|
forceRefresh = forceRefresh,
|
||||||
startDate = LocalDateTime.now()
|
startDate = Instant.now(),
|
||||||
)
|
)
|
||||||
}.onEach {
|
}.onEach {
|
||||||
when (it.status) {
|
when (it.status) {
|
||||||
@ -582,7 +562,7 @@ class DashboardPresenter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun loadAdminMessage(student: Student, forceRefresh: Boolean) {
|
private fun loadAdminMessage(student: Student, forceRefresh: Boolean) {
|
||||||
flowWithResourceIn { adminMessageRepository.getAdminMessages(student, forceRefresh) }
|
flowWithResourceIn { adminMessageRepository.getAdminMessages(student) }
|
||||||
.map {
|
.map {
|
||||||
val isDismissed = it.data?.id in preferencesRepository.dismissedAdminMessageIds
|
val isDismissed = it.data?.id in preferencesRepository.dismissedAdminMessageIds
|
||||||
it.copy(data = it.data.takeUnless { isDismissed })
|
it.copy(data = it.data.takeUnless { isDismissed })
|
||||||
@ -716,7 +696,7 @@ class DashboardPresenter @Inject constructor(
|
|||||||
itemsLoadedList.find { it.type == DashboardItem.Type.ACCOUNT }?.error != null
|
itemsLoadedList.find { it.type == DashboardItem.Type.ACCOUNT }?.error != null
|
||||||
val isGeneralError =
|
val isGeneralError =
|
||||||
filteredItems.none { it.error == null } && filteredItems.isNotEmpty() || isAccountItemError
|
filteredItems.none { it.error == null } && filteredItems.isNotEmpty() || isAccountItemError
|
||||||
val errorMessage = itemsLoadedList.map { it.error?.stackTraceToString() }.toString()
|
val firstError = itemsLoadedList.mapNotNull { it.error }.firstOrNull()
|
||||||
|
|
||||||
val filteredOriginalLoadedList =
|
val filteredOriginalLoadedList =
|
||||||
dashboardItemLoadedList.filterNot { it.type == DashboardItem.Type.ACCOUNT }
|
dashboardItemLoadedList.filterNot { it.type == DashboardItem.Type.ACCOUNT }
|
||||||
@ -726,7 +706,7 @@ class DashboardPresenter @Inject constructor(
|
|||||||
filteredOriginalLoadedList.none { it.error == null } && filteredOriginalLoadedList.isNotEmpty() || wasAccountItemError
|
filteredOriginalLoadedList.none { it.error == null } && filteredOriginalLoadedList.isNotEmpty() || wasAccountItemError
|
||||||
|
|
||||||
if (isGeneralError && isItemsLoaded) {
|
if (isGeneralError && isItemsLoaded) {
|
||||||
lastError = Exception(errorMessage)
|
lastError = requireNotNull(firstError)
|
||||||
|
|
||||||
view?.run {
|
view?.run {
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
@ -734,6 +714,7 @@ class DashboardPresenter @Inject constructor(
|
|||||||
if ((forceRefresh && wasGeneralError) || !forceRefresh) {
|
if ((forceRefresh && wasGeneralError) || !forceRefresh) {
|
||||||
showContent(false)
|
showContent(false)
|
||||||
showErrorView(true)
|
showErrorView(true)
|
||||||
|
setErrorDetails(lastError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ interface DashboardView : BaseView {
|
|||||||
|
|
||||||
fun showErrorView(show: Boolean)
|
fun showErrorView(show: Boolean)
|
||||||
|
|
||||||
fun setErrorDetails(message: String)
|
fun setErrorDetails(error: Throwable)
|
||||||
|
|
||||||
fun resetView()
|
fun resetView()
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
package io.github.wulkanowy.ui.modules.debug.notification.mock
|
package io.github.wulkanowy.ui.modules.debug.notification.mock
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Conference
|
import io.github.wulkanowy.data.db.entities.Conference
|
||||||
import java.time.LocalDateTime
|
import java.time.Duration
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
val debugConferenceItems = listOf(
|
val debugConferenceItems = listOf(
|
||||||
generateConference(
|
generateConference(
|
||||||
@ -53,6 +54,6 @@ private fun generateConference(title: String, subject: String) = Conference(
|
|||||||
diaryId = 0,
|
diaryId = 0,
|
||||||
agenda = "",
|
agenda = "",
|
||||||
conferenceId = 0,
|
conferenceId = 0,
|
||||||
date = LocalDateTime.now().plusMinutes(10),
|
date = Instant.now().plus(Duration.ofMinutes(10)),
|
||||||
presentOnConference = "",
|
presentOnConference = "",
|
||||||
)
|
)
|
||||||
|
@ -5,7 +5,7 @@ import java.time.LocalDate
|
|||||||
|
|
||||||
val debugGradeDetailsItems = listOf(
|
val debugGradeDetailsItems = listOf(
|
||||||
generateGrade("Matematyka", "+"),
|
generateGrade("Matematyka", "+"),
|
||||||
generateGrade("Matematyka", "2="),
|
generateGrade("Matematyka", "120", comment = "%"),
|
||||||
generateGrade("Fizyka", "-"),
|
generateGrade("Fizyka", "-"),
|
||||||
generateGrade("Geografia", "4+"),
|
generateGrade("Geografia", "4+"),
|
||||||
generateGrade("Sieci komputerowe", "1"),
|
generateGrade("Sieci komputerowe", "1"),
|
||||||
@ -17,14 +17,14 @@ val debugGradeDetailsItems = listOf(
|
|||||||
generateGrade("Wychowanie fizyczne", "5"),
|
generateGrade("Wychowanie fizyczne", "5"),
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun generateGrade(subject: String, entry: String) = Grade(
|
private fun generateGrade(subject: String, entry: String, comment: String = "") = Grade(
|
||||||
subject = subject,
|
subject = subject,
|
||||||
entry = entry,
|
entry = entry,
|
||||||
semesterId = 0,
|
semesterId = 0,
|
||||||
studentId = 0,
|
studentId = 0,
|
||||||
value = 0.0,
|
value = 0.0,
|
||||||
modifier = 0.0,
|
modifier = 0.0,
|
||||||
comment = "",
|
comment = comment,
|
||||||
color = "",
|
color = "",
|
||||||
gradeSymbol = "",
|
gradeSymbol = "",
|
||||||
description = "",
|
description = "",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package io.github.wulkanowy.ui.modules.debug.notification.mock
|
package io.github.wulkanowy.ui.modules.debug.notification.mock
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Message
|
import io.github.wulkanowy.data.db.entities.Message
|
||||||
import java.time.LocalDateTime
|
import java.time.Instant
|
||||||
|
|
||||||
val debugMessageItems = listOf(
|
val debugMessageItems = listOf(
|
||||||
generateMessage("Kowalski Jan", "Tytuł"),
|
generateMessage("Kowalski Jan", "Tytuł"),
|
||||||
@ -24,7 +24,7 @@ private fun generateMessage(sender: String, subject: String) = Message(
|
|||||||
messageId = 0,
|
messageId = 0,
|
||||||
senderId = 0,
|
senderId = 0,
|
||||||
recipient = "",
|
recipient = "",
|
||||||
date = LocalDateTime.now(),
|
date = Instant.now(),
|
||||||
folderId = 0,
|
folderId = 0,
|
||||||
unread = true,
|
unread = true,
|
||||||
removed = false,
|
removed = false,
|
||||||
|
@ -4,13 +4,13 @@ import io.github.wulkanowy.data.db.entities.SchoolAnnouncement
|
|||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
|
|
||||||
val debugSchoolAnnouncementItems = listOf(
|
val debugSchoolAnnouncementItems = listOf(
|
||||||
generateAnnouncement("Dzień wolny od zajęć dydaktycznych", "Dzień wolny od zajęć dydaktycznych\n03.05.2021 - poniedziałek"),
|
generateAnnouncement("Dzień wolny od zajęć dydaktycznych", "Dzień wolny od zajęć dydaktycznych<br />03.05.2021 – poniedziałek"),
|
||||||
generateAnnouncement("Zasady bezpieczeństwa", "Wszyscy uczniowie są zobowiązani do noszenia maseczek"),
|
generateAnnouncement("Zasady bezpieczeństwa", "Wszyscy uczniowie są zobowiązani do noszenia maseczek"),
|
||||||
generateAnnouncement("Święto szkoły", "W najbliższych dniach obchodzimy święto szkoły, podczas którego..."),
|
generateAnnouncement("Święto szkoły", "W najbliższych dniach obchodzimy święto szkoły, podczas którego..."),
|
||||||
generateAnnouncement("Rocznica odzyskania przez szkołę sztandaru", "Juz niedługo, bo za tydzień, a dokładnie za 8 dni..."),
|
generateAnnouncement("Rocznica odzyskania przez szkołę sztandaru", "Juz niedługo, bo za tydzień, a dokładnie za 8 dni..."),
|
||||||
generateAnnouncement("Ogłoszenie w sprawie otwarcia stołówki", "Wszyscy uczniowie zainteresowani obiadami w szkole..."),
|
generateAnnouncement("Ogłoszenie w sprawie otwarcia stołówki", "Wszyscy uczniowie zainteresowani obiadami w szkole..."),
|
||||||
generateAnnouncement("Uczniowie proszeni do sekretariatu", "Kuba i Jacek z klasy czwartej proszeni do dyrektora w trybie pilnym"),
|
generateAnnouncement("Uczniowie proszeni do sekretariatu", "Kuba i Jacek z klasy czwartej proszeni do dyrektora w trybie pilnym"),
|
||||||
generateAnnouncement("Dzień wolny od zajęć dydaktycznych", "Dzień wolny od zajęć dydaktycznych\n21.06.2021 - poniedziałek"),
|
generateAnnouncement("Dzień wolny od zajęć dydaktycznych", "Dzień wolny od zajęć dydaktycznych<br />21.06.2021 – poniedziałek"),
|
||||||
generateAnnouncement("Zasady bezpieczeństwa", "Wszyscy uczniowie są zobowiązani do zdjęcia maseczek"),
|
generateAnnouncement("Zasady bezpieczeństwa", "Wszyscy uczniowie są zobowiązani do zdjęcia maseczek"),
|
||||||
generateAnnouncement("Święto państwowe", "W najbliższych dniach obchodzimy święto państwowe, podczas którego..."),
|
generateAnnouncement("Święto państwowe", "W najbliższych dniach obchodzimy święto państwowe, podczas którego..."),
|
||||||
generateAnnouncement("Uczniowie proszeni do sekretariatu", "Kuba i Jacek z klasy czwartej proszeni do dyrektora w trybie wolnym"),
|
generateAnnouncement("Uczniowie proszeni do sekretariatu", "Kuba i Jacek z klasy czwartej proszeni do dyrektora w trybie wolnym"),
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
package io.github.wulkanowy.ui.modules.debug.notification.mock
|
package io.github.wulkanowy.ui.modules.debug.notification.mock
|
||||||
|
|
||||||
import io.github.wulkanowy.data.db.entities.Timetable
|
import io.github.wulkanowy.data.db.entities.Timetable
|
||||||
|
import java.time.Duration
|
||||||
|
import java.time.Instant
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
val debugTimetableItems = listOf(
|
val debugTimetableItems = listOf(
|
||||||
@ -24,8 +25,8 @@ private fun generateTimetable(subject: String, room: String, roomOld: String) =
|
|||||||
diaryId = 0,
|
diaryId = 0,
|
||||||
date = LocalDate.now().minusDays(Random.nextLong(0, 8)),
|
date = LocalDate.now().minusDays(Random.nextLong(0, 8)),
|
||||||
number = 1,
|
number = 1,
|
||||||
start = LocalDateTime.now().plusHours(1),
|
start = Instant.now(),
|
||||||
end = LocalDateTime.now(),
|
end = Instant.now().plus(Duration.ofHours(1)),
|
||||||
subjectOld = "",
|
subjectOld = "",
|
||||||
group = "",
|
group = "",
|
||||||
room = room,
|
room = room,
|
||||||
|
@ -33,6 +33,7 @@ class GradeStatisticsFragment :
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val SAVED_CHART_TYPE = "CURRENT_TYPE"
|
private const val SAVED_CHART_TYPE = "CURRENT_TYPE"
|
||||||
|
private const val SAVED_SUBJECT_NAME = "SUBJECT_NAME"
|
||||||
|
|
||||||
fun newInstance() = GradeStatisticsFragment()
|
fun newInstance() = GradeStatisticsFragment()
|
||||||
}
|
}
|
||||||
@ -46,8 +47,9 @@ class GradeStatisticsFragment :
|
|||||||
binding = FragmentGradeStatisticsBinding.bind(view)
|
binding = FragmentGradeStatisticsBinding.bind(view)
|
||||||
messageContainer = binding.gradeStatisticsRecycler
|
messageContainer = binding.gradeStatisticsRecycler
|
||||||
presenter.onAttachView(
|
presenter.onAttachView(
|
||||||
this,
|
view = this,
|
||||||
savedInstanceState?.getSerializable(SAVED_CHART_TYPE) as? GradeStatisticsItem.DataType
|
type = savedInstanceState?.getSerializable(SAVED_CHART_TYPE) as? GradeStatisticsItem.DataType,
|
||||||
|
subjectName = savedInstanceState?.getSerializable(SAVED_SUBJECT_NAME) as? String,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +58,7 @@ class GradeStatisticsFragment :
|
|||||||
|
|
||||||
with(binding.gradeStatisticsRecycler) {
|
with(binding.gradeStatisticsRecycler) {
|
||||||
layoutManager = LinearLayoutManager(requireContext())
|
layoutManager = LinearLayoutManager(requireContext())
|
||||||
|
statisticsAdapter.currentDataType = presenter.currentType
|
||||||
adapter = statisticsAdapter
|
adapter = statisticsAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +84,8 @@ class GradeStatisticsFragment :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateSubjects(data: ArrayList<String>) {
|
override fun updateSubjects(data: List<String>, selectedIndex: Int) {
|
||||||
|
binding.gradeStatisticsSubjects.setSelection(selectedIndex)
|
||||||
with(subjectsAdapter) {
|
with(subjectsAdapter) {
|
||||||
clear()
|
clear()
|
||||||
addAll(data)
|
addAll(data)
|
||||||
@ -161,6 +165,7 @@ class GradeStatisticsFragment :
|
|||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
super.onSaveInstanceState(outState)
|
super.onSaveInstanceState(outState)
|
||||||
outState.putSerializable(SAVED_CHART_TYPE, presenter.currentType)
|
outState.putSerializable(SAVED_CHART_TYPE, presenter.currentType)
|
||||||
|
outState.putSerializable(SAVED_SUBJECT_NAME, presenter.currentSubjectName)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -31,16 +31,22 @@ class GradeStatisticsPresenter @Inject constructor(
|
|||||||
|
|
||||||
private var currentSemesterId = 0
|
private var currentSemesterId = 0
|
||||||
|
|
||||||
private var currentSubjectName: String = "Wszystkie"
|
var currentSubjectName: String = "Wszystkie"
|
||||||
|
private set
|
||||||
|
|
||||||
private lateinit var lastError: Throwable
|
private lateinit var lastError: Throwable
|
||||||
|
|
||||||
var currentType: GradeStatisticsItem.DataType = GradeStatisticsItem.DataType.PARTIAL
|
var currentType: GradeStatisticsItem.DataType = GradeStatisticsItem.DataType.PARTIAL
|
||||||
private set
|
private set
|
||||||
|
|
||||||
fun onAttachView(view: GradeStatisticsView, type: GradeStatisticsItem.DataType?) {
|
fun onAttachView(
|
||||||
|
view: GradeStatisticsView,
|
||||||
|
type: GradeStatisticsItem.DataType?,
|
||||||
|
subjectName: String?
|
||||||
|
) {
|
||||||
super.onAttachView(view)
|
super.onAttachView(view)
|
||||||
currentType = type ?: GradeStatisticsItem.DataType.PARTIAL
|
currentType = type ?: GradeStatisticsItem.DataType.PARTIAL
|
||||||
|
currentSubjectName = subjectName ?: currentSubjectName
|
||||||
view.initView()
|
view.initView()
|
||||||
errorHandler.showErrorMessage = ::showErrorViewOnError
|
errorHandler.showErrorMessage = ::showErrorViewOnError
|
||||||
}
|
}
|
||||||
@ -127,12 +133,17 @@ class GradeStatisticsPresenter @Inject constructor(
|
|||||||
when (it.status) {
|
when (it.status) {
|
||||||
Status.LOADING -> Timber.i("Loading grade stats subjects started")
|
Status.LOADING -> Timber.i("Loading grade stats subjects started")
|
||||||
Status.SUCCESS -> {
|
Status.SUCCESS -> {
|
||||||
subjects = it.data!!
|
subjects = requireNotNull(it.data)
|
||||||
|
|
||||||
Timber.i("Loading grade stats subjects result: Success")
|
Timber.i("Loading grade stats subjects result: Success")
|
||||||
|
|
||||||
view?.run {
|
view?.run {
|
||||||
view?.updateSubjects(ArrayList(it.data.map { subject -> subject.name }))
|
|
||||||
showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList)
|
showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList)
|
||||||
|
updateSubjects(
|
||||||
|
data = it.data.map { subject -> subject.name },
|
||||||
|
selectedIndex = it.data.indexOfFirst { subject ->
|
||||||
|
subject.name == currentSubjectName
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Status.ERROR -> {
|
Status.ERROR -> {
|
||||||
@ -151,9 +162,11 @@ class GradeStatisticsPresenter @Inject constructor(
|
|||||||
) {
|
) {
|
||||||
Timber.i("Loading grade stats data started")
|
Timber.i("Loading grade stats data started")
|
||||||
|
|
||||||
currentSubjectName =
|
|
||||||
if (preferencesRepository.showAllSubjectsOnStatisticsList) "Wszystkie" else subjectName
|
|
||||||
currentType = type
|
currentType = type
|
||||||
|
currentSubjectName = when {
|
||||||
|
preferencesRepository.showAllSubjectsOnStatisticsList -> "Wszystkie"
|
||||||
|
else -> subjectName
|
||||||
|
}
|
||||||
|
|
||||||
flowWithResourceIn {
|
flowWithResourceIn {
|
||||||
val student = studentRepository.getCurrentStudent()
|
val student = studentRepository.getCurrentStudent()
|
||||||
@ -200,9 +213,9 @@ class GradeStatisticsPresenter @Inject constructor(
|
|||||||
showRefresh(true)
|
showRefresh(true)
|
||||||
showProgress(false)
|
showProgress(false)
|
||||||
updateData(
|
updateData(
|
||||||
if (isNoContent) emptyList() else it.data!!,
|
newItems = if (isNoContent) emptyList() else it.data!!,
|
||||||
preferencesRepository.gradeColorTheme,
|
newTheme = preferencesRepository.gradeColorTheme,
|
||||||
preferencesRepository.showAllSubjectsOnStatisticsList
|
showAllSubjectsOnStatisticsList = preferencesRepository.showAllSubjectsOnStatisticsList,
|
||||||
)
|
)
|
||||||
showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList)
|
showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList)
|
||||||
}
|
}
|
||||||
@ -215,9 +228,9 @@ class GradeStatisticsPresenter @Inject constructor(
|
|||||||
showEmpty(isNoContent)
|
showEmpty(isNoContent)
|
||||||
showErrorView(false)
|
showErrorView(false)
|
||||||
updateData(
|
updateData(
|
||||||
if (isNoContent) emptyList() else it.data,
|
newItems = if (isNoContent) emptyList() else it.data,
|
||||||
preferencesRepository.gradeColorTheme,
|
newTheme = preferencesRepository.gradeColorTheme,
|
||||||
preferencesRepository.showAllSubjectsOnStatisticsList
|
showAllSubjectsOnStatisticsList = preferencesRepository.showAllSubjectsOnStatisticsList,
|
||||||
)
|
)
|
||||||
showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList)
|
showSubjects(!preferencesRepository.showAllSubjectsOnStatisticsList)
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ interface GradeStatisticsView : BaseView {
|
|||||||
|
|
||||||
fun initView()
|
fun initView()
|
||||||
|
|
||||||
fun updateSubjects(data: ArrayList<String>)
|
fun updateSubjects(data: List<String>, selectedIndex: Int)
|
||||||
|
|
||||||
fun updateData(
|
fun updateData(
|
||||||
newItems: List<GradeStatisticsItem>,
|
newItems: List<GradeStatisticsItem>,
|
||||||
|
@ -5,15 +5,13 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.widget.doOnTextChanged
|
import androidx.core.widget.doOnTextChanged
|
||||||
import com.google.android.material.datepicker.CalendarConstraints
|
|
||||||
import com.google.android.material.datepicker.MaterialDatePicker
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.databinding.DialogHomeworkAddBinding
|
import io.github.wulkanowy.databinding.DialogHomeworkAddBinding
|
||||||
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
import io.github.wulkanowy.ui.base.BaseDialogFragment
|
||||||
|
import io.github.wulkanowy.utils.lastSchoolDayInSchoolYear
|
||||||
|
import io.github.wulkanowy.utils.openMaterialDatePicker
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
import io.github.wulkanowy.utils.toFormattedString
|
||||||
import io.github.wulkanowy.utils.toLocalDateTime
|
|
||||||
import io.github.wulkanowy.utils.toTimestamp
|
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -23,6 +21,7 @@ class HomeworkAddDialog : BaseDialogFragment<DialogHomeworkAddBinding>(), Homewo
|
|||||||
@Inject
|
@Inject
|
||||||
lateinit var presenter: HomeworkAddPresenter
|
lateinit var presenter: HomeworkAddPresenter
|
||||||
|
|
||||||
|
// todo: move it to presenter
|
||||||
private var date: LocalDate? = null
|
private var date: LocalDate? = null
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@ -97,24 +96,16 @@ class HomeworkAddDialog : BaseDialogFragment<DialogHomeworkAddBinding>(), Homewo
|
|||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showDatePickerDialog(currentDate: LocalDate) {
|
override fun showDatePickerDialog(selectedDate: LocalDate) {
|
||||||
val constraintsBuilder = CalendarConstraints.Builder().apply {
|
openMaterialDatePicker(
|
||||||
setStart(LocalDate.now().toEpochDay())
|
selected = selectedDate,
|
||||||
}
|
rangeStart = LocalDate.now(),
|
||||||
val datePicker =
|
rangeEnd = LocalDate.now().lastSchoolDayInSchoolYear,
|
||||||
MaterialDatePicker.Builder.datePicker()
|
onDateSelected = {
|
||||||
.setCalendarConstraints(constraintsBuilder.build())
|
date = it
|
||||||
.setSelection(currentDate.toTimestamp())
|
|
||||||
.build()
|
|
||||||
|
|
||||||
datePicker.addOnPositiveButtonClickListener {
|
|
||||||
date = it.toLocalDateTime().toLocalDate()
|
|
||||||
binding.homeworkDialogDate.editText?.setText(date!!.toFormattedString())
|
binding.homeworkDialogDate.editText?.setText(date!!.toFormattedString())
|
||||||
}
|
}
|
||||||
|
)
|
||||||
if (!parentFragmentManager.isStateSaved) {
|
|
||||||
datePicker.show(this.parentFragmentManager, null)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -17,5 +17,5 @@ interface HomeworkAddView : BaseView {
|
|||||||
|
|
||||||
fun closeDialog()
|
fun closeDialog()
|
||||||
|
|
||||||
fun showDatePickerDialog(currentDate: LocalDate)
|
fun showDatePickerDialog(selectedDate: LocalDate)
|
||||||
}
|
}
|
||||||
|
@ -4,18 +4,19 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.commit
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
import io.github.wulkanowy.data.db.entities.StudentWithSemesters
|
||||||
import io.github.wulkanowy.databinding.ActivityLoginBinding
|
import io.github.wulkanowy.databinding.ActivityLoginBinding
|
||||||
import io.github.wulkanowy.ui.base.BaseActivity
|
import io.github.wulkanowy.ui.base.BaseActivity
|
||||||
import io.github.wulkanowy.ui.base.BaseFragmentPagerAdapter
|
|
||||||
import io.github.wulkanowy.ui.modules.login.advanced.LoginAdvancedFragment
|
import io.github.wulkanowy.ui.modules.login.advanced.LoginAdvancedFragment
|
||||||
import io.github.wulkanowy.ui.modules.login.form.LoginFormFragment
|
import io.github.wulkanowy.ui.modules.login.form.LoginFormFragment
|
||||||
import io.github.wulkanowy.ui.modules.login.recover.LoginRecoverFragment
|
import io.github.wulkanowy.ui.modules.login.recover.LoginRecoverFragment
|
||||||
import io.github.wulkanowy.ui.modules.login.studentselect.LoginStudentSelectFragment
|
import io.github.wulkanowy.ui.modules.login.studentselect.LoginStudentSelectFragment
|
||||||
import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment
|
import io.github.wulkanowy.ui.modules.login.symbol.LoginSymbolFragment
|
||||||
import io.github.wulkanowy.utils.UpdateHelper
|
import io.github.wulkanowy.utils.UpdateHelper
|
||||||
import io.github.wulkanowy.utils.setOnSelectPageListener
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -24,21 +25,10 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
|
|||||||
@Inject
|
@Inject
|
||||||
override lateinit var presenter: LoginPresenter
|
override lateinit var presenter: LoginPresenter
|
||||||
|
|
||||||
private val pagerAdapter by lazy {
|
|
||||||
BaseFragmentPagerAdapter(
|
|
||||||
fragmentManager = supportFragmentManager,
|
|
||||||
pagesCount = 5,
|
|
||||||
lifecycle = lifecycle,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var updateHelper: UpdateHelper
|
lateinit var updateHelper: UpdateHelper
|
||||||
|
|
||||||
override val currentViewIndex get() = binding.loginViewpager.currentItem
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun getStartIntent(context: Context) = Intent(context, LoginActivity::class.java)
|
fun getStartIntent(context: Context) = Intent(context, LoginActivity::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,6 +41,50 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
|
|||||||
|
|
||||||
presenter.onAttachView(this)
|
presenter.onAttachView(this)
|
||||||
updateHelper.checkAndInstallUpdates(this)
|
updateHelper.checkAndInstallUpdates(this)
|
||||||
|
|
||||||
|
if (savedInstanceState == null) {
|
||||||
|
openFragment(LoginFormFragment.newInstance(), clearBackStack = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initView() {
|
||||||
|
with(requireNotNull(supportActionBar)) {
|
||||||
|
setDisplayHomeAsUpEnabled(true)
|
||||||
|
setDisplayShowTitleEnabled(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
if (item.itemId == android.R.id.home) onBackPressed()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showActionBar(show: Boolean) {
|
||||||
|
supportActionBar?.run { if (show) show() else hide() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun navigateToSymbolFragment(loginData: LoginData) {
|
||||||
|
openFragment(LoginSymbolFragment.newInstance(loginData))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun navigateToStudentSelect(studentsWithSemesters: List<StudentWithSemesters>) {
|
||||||
|
openFragment(LoginStudentSelectFragment.newInstance(studentsWithSemesters))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onAdvancedLoginClick() {
|
||||||
|
openFragment(LoginAdvancedFragment.newInstance())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onRecoverClick() {
|
||||||
|
openFragment(LoginRecoverFragment.newInstance())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openFragment(fragment: Fragment, clearBackStack: Boolean = false) {
|
||||||
|
supportFragmentManager.commit {
|
||||||
|
replace(R.id.loginContainer, fragment)
|
||||||
|
setReorderingAllowed(true)
|
||||||
|
if (!clearBackStack) addToBackStack(fragment::class.java.name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
@ -64,78 +98,4 @@ class LoginActivity : BaseActivity<LoginPresenter, ActivityLoginBinding>(), Logi
|
|||||||
super.onActivityResult(requestCode, resultCode, data)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
updateHelper.onActivityResult(requestCode, resultCode)
|
updateHelper.onActivityResult(requestCode, resultCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initView() {
|
|
||||||
with(requireNotNull(supportActionBar)) {
|
|
||||||
setDisplayHomeAsUpEnabled(true)
|
|
||||||
setDisplayShowTitleEnabled(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
with(binding.loginViewpager) {
|
|
||||||
adapter = pagerAdapter
|
|
||||||
isUserInputEnabled = false
|
|
||||||
offscreenPageLimit = 2
|
|
||||||
setOnSelectPageListener(presenter::onViewSelected)
|
|
||||||
}
|
|
||||||
|
|
||||||
with(pagerAdapter) {
|
|
||||||
containerId = binding.loginViewpager.id
|
|
||||||
itemFactory = {
|
|
||||||
when (it) {
|
|
||||||
0 -> LoginFormFragment.newInstance()
|
|
||||||
1 -> LoginSymbolFragment.newInstance()
|
|
||||||
2 -> LoginStudentSelectFragment.newInstance()
|
|
||||||
3 -> LoginAdvancedFragment.newInstance()
|
|
||||||
4 -> LoginRecoverFragment.newInstance()
|
|
||||||
else -> throw IllegalStateException()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
if (item.itemId == android.R.id.home) onBackPressed()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun switchView(index: Int) {
|
|
||||||
binding.loginViewpager.setCurrentItem(index, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showActionBar(show: Boolean) {
|
|
||||||
supportActionBar?.run { if (show) show() else hide() }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed() {
|
|
||||||
presenter.onBackPressed { super.onBackPressed() }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun notifyInitSymbolFragment(loginData: Triple<String, String, String>) {
|
|
||||||
(pagerAdapter.getFragmentInstance(1) as? LoginSymbolFragment)
|
|
||||||
?.onParentInitSymbolFragment(loginData)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun notifyInitStudentSelectFragment(studentsWithSemesters: List<StudentWithSemesters>) {
|
|
||||||
(pagerAdapter.getFragmentInstance(2) as? LoginStudentSelectFragment)
|
|
||||||
?.onParentInitStudentSelectFragment(studentsWithSemesters)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onFormFragmentAccountLogged(
|
|
||||||
studentsWithSemesters: List<StudentWithSemesters>,
|
|
||||||
loginData: Triple<String, String, String>
|
|
||||||
) {
|
|
||||||
presenter.onFormViewAccountLogged(studentsWithSemesters, loginData)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onSymbolFragmentAccountLogged(studentsWithSemesters: List<StudentWithSemesters>) {
|
|
||||||
presenter.onSymbolViewAccountLogged(studentsWithSemesters)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onAdvancedLoginClick() {
|
|
||||||
presenter.onAdvancedLoginClick()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onRecoverClick() {
|
|
||||||
presenter.onRecoverClick()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
package io.github.wulkanowy.ui.modules.login
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
data class LoginData(
|
||||||
|
val login: String,
|
||||||
|
val password: String,
|
||||||
|
val baseUrl: String,
|
||||||
|
) : Serializable
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user