forked from github/wulkanowy-mirror
Add predicted and final grade notifications (#872)
This commit is contained in:
parent
a529836937
commit
a6682c9b73
@ -1741,4 +1741,4 @@
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd101f5a26a024f62e6fee161e421b882')"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1768
app/schemas/io.github.wulkanowy.data.db.AppDatabase/26.json
Normal file
1768
app/schemas/io.github.wulkanowy.data.db.AppDatabase/26.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -68,6 +68,7 @@ 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.Migration3
|
||||
import io.github.wulkanowy.data.db.migrations.Migration4
|
||||
import io.github.wulkanowy.data.db.migrations.Migration5
|
||||
@ -110,7 +111,7 @@ import javax.inject.Singleton
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
companion object {
|
||||
const val VERSION_SCHEMA = 25
|
||||
const val VERSION_SCHEMA = 26
|
||||
|
||||
fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array<Migration> {
|
||||
return arrayOf(
|
||||
@ -137,7 +138,8 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
Migration22(),
|
||||
Migration23(),
|
||||
Migration24(),
|
||||
Migration25()
|
||||
Migration25(),
|
||||
Migration26()
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package io.github.wulkanowy.data.db.entities
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import org.threeten.bp.LocalDateTime
|
||||
|
||||
@Entity(tableName = "GradesSummary")
|
||||
data class GradeSummary(
|
||||
@ -36,4 +37,16 @@ data class GradeSummary(
|
||||
) {
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
var id: Long = 0
|
||||
|
||||
@ColumnInfo(name = "is_predicted_grade_notified")
|
||||
var isPredictedGradeNotified: Boolean = true
|
||||
|
||||
@ColumnInfo(name = "is_final_grade_notified")
|
||||
var isFinalGradeNotified: Boolean = true
|
||||
|
||||
@ColumnInfo(name = "predicted_grade_last_change")
|
||||
var predictedGradeLastChange: LocalDateTime = LocalDateTime.now()
|
||||
|
||||
@ColumnInfo(name = "final_grade_last_change")
|
||||
var finalGradeLastChange: LocalDateTime = LocalDateTime.now()
|
||||
}
|
||||
|
@ -0,0 +1,14 @@
|
||||
package io.github.wulkanowy.data.db.migrations
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration26 : Migration(25, 26) {
|
||||
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("ALTER TABLE GradesSummary ADD COLUMN is_predicted_grade_notified INTEGER NOT NULL DEFAULT 1")
|
||||
database.execSQL("ALTER TABLE GradesSummary ADD COLUMN is_final_grade_notified INTEGER NOT NULL DEFAULT 1")
|
||||
database.execSQL("ALTER TABLE GradesSummary ADD COLUMN predicted_grade_last_change INTEGER NOT NULL DEFAULT 0")
|
||||
database.execSQL("ALTER TABLE GradesSummary ADD COLUMN final_grade_last_change INTEGER NOT NULL DEFAULT 0")
|
||||
}
|
||||
}
|
@ -27,6 +27,10 @@ class GradeLocal @Inject constructor(
|
||||
gradeDb.updateAll(grades)
|
||||
}
|
||||
|
||||
fun updateGradesSummary(gradesSummary: List<GradeSummary>) {
|
||||
gradeSummaryDb.updateAll(gradesSummary)
|
||||
}
|
||||
|
||||
fun getGradesDetails(semester: Semester): Maybe<List<Grade>> {
|
||||
return gradeDb.loadAll(semester.semesterId, semester.studentId).filter { it.isNotEmpty() }
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.utils.uniqueSubtract
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Single
|
||||
import org.threeten.bp.LocalDateTime
|
||||
import java.net.UnknownHostException
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@ -43,7 +44,31 @@ class GradeRepository @Inject constructor(
|
||||
local.getGradesSummary(semester).toSingle(emptyList())
|
||||
.doOnSuccess { old ->
|
||||
local.deleteGradesSummary(old.uniqueSubtract(newSummary))
|
||||
local.saveGradesSummary(newSummary.uniqueSubtract(old))
|
||||
local.saveGradesSummary(newSummary.uniqueSubtract(old)
|
||||
.onEach { summary ->
|
||||
val oldSummary = old.find { oldSummary -> oldSummary.subject == summary.subject }
|
||||
summary.isPredictedGradeNotified = when {
|
||||
summary.predictedGrade.isEmpty() -> true
|
||||
notify && oldSummary?.predictedGrade != summary.predictedGrade -> false
|
||||
else -> true
|
||||
}
|
||||
summary.isFinalGradeNotified = when {
|
||||
summary.finalGrade.isEmpty() -> true
|
||||
notify && oldSummary?.finalGrade != summary.finalGrade -> false
|
||||
else -> true
|
||||
}
|
||||
|
||||
summary.predictedGradeLastChange = when {
|
||||
oldSummary == null -> LocalDateTime.now()
|
||||
summary.predictedGrade != oldSummary.predictedGrade -> LocalDateTime.now()
|
||||
else -> oldSummary.predictedGradeLastChange
|
||||
}
|
||||
summary.finalGradeLastChange = when {
|
||||
oldSummary == null -> LocalDateTime.now()
|
||||
summary.finalGrade != oldSummary.finalGrade -> LocalDateTime.now()
|
||||
else -> oldSummary.finalGradeLastChange
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}.flatMap {
|
||||
@ -63,6 +88,14 @@ class GradeRepository @Inject constructor(
|
||||
return local.getGradesDetails(semester).map { it.filter { grade -> !grade.isNotified } }.toSingle(emptyList())
|
||||
}
|
||||
|
||||
fun getNotNotifiedPredictedGrades(semester: Semester): Single<List<GradeSummary>> {
|
||||
return local.getGradesSummary(semester).map { it.filter { gradeSummary -> !gradeSummary.isPredictedGradeNotified } }.toSingle(emptyList())
|
||||
}
|
||||
|
||||
fun getNotNotifiedFinalGrades(semester: Semester): Single<List<GradeSummary>> {
|
||||
return local.getGradesSummary(semester).map { it.filter { gradeSummary -> !gradeSummary.isFinalGradeNotified } }.toSingle(emptyList())
|
||||
}
|
||||
|
||||
fun updateGrade(grade: Grade): Completable {
|
||||
return Completable.fromCallable { local.updateGrades(listOf(grade)) }
|
||||
}
|
||||
@ -70,4 +103,8 @@ class GradeRepository @Inject constructor(
|
||||
fun updateGrades(grades: List<Grade>): Completable {
|
||||
return Completable.fromCallable { local.updateGrades(grades) }
|
||||
}
|
||||
|
||||
fun updateGradesSummary(gradesSummary: List<GradeSummary>): Completable {
|
||||
return Completable.fromCallable { local.updateGradesSummary(gradesSummary) }
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import androidx.core.app.NotificationCompat.PRIORITY_HIGH
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import io.github.wulkanowy.R
|
||||
import io.github.wulkanowy.data.db.entities.Grade
|
||||
import io.github.wulkanowy.data.db.entities.GradeSummary
|
||||
import io.github.wulkanowy.data.db.entities.Semester
|
||||
import io.github.wulkanowy.data.db.entities.Student
|
||||
import io.github.wulkanowy.data.repositories.grade.GradeRepository
|
||||
@ -30,17 +31,21 @@ class GradeWork @Inject constructor(
|
||||
|
||||
override fun create(student: Student, semester: Semester): Completable {
|
||||
return gradeRepository.getGrades(student, semester, true, preferencesRepository.isNotificationsEnable)
|
||||
.flatMap { gradeRepository.getNotNotifiedGrades(semester) }
|
||||
.flatMapCompletable {
|
||||
if (it.isNotEmpty()) notify(it)
|
||||
.ignoreElement()
|
||||
.concatWith(Completable.concatArray(gradeRepository.getNotNotifiedGrades(semester).flatMapCompletable {
|
||||
if (it.isNotEmpty()) notifyDetails(it)
|
||||
gradeRepository.updateGrades(it.onEach { grade -> grade.isNotified = true })
|
||||
}
|
||||
}, gradeRepository.getNotNotifiedPredictedGrades(semester).flatMapCompletable {
|
||||
if (it.isNotEmpty()) notifyPredicted(it)
|
||||
gradeRepository.updateGradesSummary(it.onEach { grade -> grade.isPredictedGradeNotified = true })
|
||||
}, gradeRepository.getNotNotifiedFinalGrades(semester).flatMapCompletable {
|
||||
if (it.isNotEmpty()) notifyFinal(it)
|
||||
gradeRepository.updateGradesSummary(it.onEach { grade -> grade.isFinalGradeNotified = true })
|
||||
}))
|
||||
}
|
||||
|
||||
private fun notify(grades: List<Grade>) {
|
||||
notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(context, NewGradesChannel.CHANNEL_ID)
|
||||
.setContentTitle(context.resources.getQuantityString(R.plurals.grade_new_items, grades.size, grades.size))
|
||||
.setContentText(context.resources.getQuantityString(R.plurals.grade_notify_new_items, grades.size, grades.size))
|
||||
private fun getNotificationBuilder(): NotificationCompat.Builder {
|
||||
return NotificationCompat.Builder(context, NewGradesChannel.CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_stat_grade)
|
||||
.setAutoCancel(true)
|
||||
.setPriority(PRIORITY_HIGH)
|
||||
@ -49,6 +54,12 @@ class GradeWork @Inject constructor(
|
||||
.setContentIntent(
|
||||
PendingIntent.getActivity(context, MainView.Section.GRADE.id,
|
||||
MainActivity.getStartIntent(context, MainView.Section.GRADE, true), FLAG_UPDATE_CURRENT))
|
||||
}
|
||||
|
||||
private fun notifyDetails(grades: List<Grade>) {
|
||||
notificationManager.notify(Random.nextInt(Int.MAX_VALUE), getNotificationBuilder()
|
||||
.setContentTitle(context.resources.getQuantityString(R.plurals.grade_new_items, grades.size, grades.size))
|
||||
.setContentText(context.resources.getQuantityString(R.plurals.grade_notify_new_items, grades.size, grades.size))
|
||||
.setStyle(NotificationCompat.InboxStyle().run {
|
||||
setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, grades.size, grades.size))
|
||||
grades.forEach { addLine("${it.subject}: ${it.entry}") }
|
||||
@ -57,4 +68,30 @@ class GradeWork @Inject constructor(
|
||||
.build()
|
||||
)
|
||||
}
|
||||
|
||||
private fun notifyPredicted(gradesSummary: List<GradeSummary>) {
|
||||
notificationManager.notify(Random.nextInt(Int.MAX_VALUE), getNotificationBuilder()
|
||||
.setContentTitle(context.resources.getQuantityString(R.plurals.grade_new_items_predicted, gradesSummary.size, gradesSummary.size))
|
||||
.setContentText(context.resources.getQuantityString(R.plurals.grade_notify_new_items_predicted, gradesSummary.size, gradesSummary.size))
|
||||
.setStyle(NotificationCompat.InboxStyle().run {
|
||||
setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, gradesSummary.size, gradesSummary.size))
|
||||
gradesSummary.forEach { addLine("${it.subject}: ${it.predictedGrade}") }
|
||||
this
|
||||
})
|
||||
.build()
|
||||
)
|
||||
}
|
||||
|
||||
private fun notifyFinal(gradesSummary: List<GradeSummary>) {
|
||||
notificationManager.notify(Random.nextInt(Int.MAX_VALUE), getNotificationBuilder()
|
||||
.setContentTitle(context.resources.getQuantityString(R.plurals.grade_new_items_final, gradesSummary.size, gradesSummary.size))
|
||||
.setContentText(context.resources.getQuantityString(R.plurals.grade_notify_new_items_final, gradesSummary.size, gradesSummary.size))
|
||||
.setStyle(NotificationCompat.InboxStyle().run {
|
||||
setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, gradesSummary.size, gradesSummary.size))
|
||||
gradesSummary.forEach { addLine("${it.subject}: ${it.finalGrade}") }
|
||||
this
|
||||
})
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -107,12 +107,36 @@
|
||||
<item quantity="many">Nowe oceny</item>
|
||||
<item quantity="other">Nowe oceny</item>
|
||||
</plurals>
|
||||
<plurals name="grade_new_items_predicted">
|
||||
<item quantity="one">Nowa ocena przewidywana</item>
|
||||
<item quantity="few">Nowe oceny przewidywane</item>
|
||||
<item quantity="many">Nowe oceny przewidywane</item>
|
||||
<item quantity="other">Nowe oceny przewidywane</item>
|
||||
</plurals>
|
||||
<plurals name="grade_new_items_final">
|
||||
<item quantity="one">Nowa ocena końcowa</item>
|
||||
<item quantity="few">Nowe oceny końcowe</item>
|
||||
<item quantity="many">Nowe oceny końcowe</item>
|
||||
<item quantity="other">Nowe oceny końcowe</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items">
|
||||
<item quantity="one">Masz %1$d nową ocenę</item>
|
||||
<item quantity="few">Masz %1$d nowe oceny</item>
|
||||
<item quantity="many">Masz %1$d nowych ocen</item>
|
||||
<item quantity="other">Masz %1$d nowych ocen</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items_predicted">
|
||||
<item quantity="one">Masz %1$d nową przewidywaną ocenę</item>
|
||||
<item quantity="few">Masz %1$d nowe przewidywane oceny</item>
|
||||
<item quantity="many">Masz %1$d nowych przewidywanych ocen</item>
|
||||
<item quantity="other">Masz %1$d nowych przewidywanych ocen</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items_final">
|
||||
<item quantity="one">Masz %1$d nową końcową ocenę</item>
|
||||
<item quantity="few">Masz %1$d nowe końcowe oceny</item>
|
||||
<item quantity="many">Masz %1$d nowych końcowych ocen</item>
|
||||
<item quantity="other">Masz %1$d nowych końcowych ocen</item>
|
||||
</plurals>
|
||||
<!--Timetable-->
|
||||
<string name="timetable_lesson">Lekcja</string>
|
||||
<string name="timetable_room">Sala</string>
|
||||
|
@ -113,10 +113,26 @@
|
||||
<item quantity="one">New grade</item>
|
||||
<item quantity="other">New grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_new_items_predicted">
|
||||
<item quantity="one">New predicted grade</item>
|
||||
<item quantity="other">New predicted grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_new_items_final">
|
||||
<item quantity="one">New final grade</item>
|
||||
<item quantity="other">New final grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items">
|
||||
<item quantity="one">You received %1$d grade</item>
|
||||
<item quantity="other">You received %1$d grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items_predicted">
|
||||
<item quantity="one">You received %1$d predicted grade</item>
|
||||
<item quantity="other">You received %1$d predicted grades</item>
|
||||
</plurals>
|
||||
<plurals name="grade_notify_new_items_final">
|
||||
<item quantity="one">You received %1$d final grade</item>
|
||||
<item quantity="other">You received %1$d final grades</item>
|
||||
</plurals>
|
||||
|
||||
|
||||
<!--Timetable-->
|
||||
|
Loading…
x
Reference in New Issue
Block a user