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')"
|
"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.Migration23
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration24
|
import io.github.wulkanowy.data.db.migrations.Migration24
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration25
|
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.Migration3
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration4
|
import io.github.wulkanowy.data.db.migrations.Migration4
|
||||||
import io.github.wulkanowy.data.db.migrations.Migration5
|
import io.github.wulkanowy.data.db.migrations.Migration5
|
||||||
@ -110,7 +111,7 @@ import javax.inject.Singleton
|
|||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val VERSION_SCHEMA = 25
|
const val VERSION_SCHEMA = 26
|
||||||
|
|
||||||
fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array<Migration> {
|
fun getMigrations(sharedPrefProvider: SharedPrefProvider): Array<Migration> {
|
||||||
return arrayOf(
|
return arrayOf(
|
||||||
@ -137,7 +138,8 @@ abstract class AppDatabase : RoomDatabase() {
|
|||||||
Migration22(),
|
Migration22(),
|
||||||
Migration23(),
|
Migration23(),
|
||||||
Migration24(),
|
Migration24(),
|
||||||
Migration25()
|
Migration25(),
|
||||||
|
Migration26()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +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 org.threeten.bp.LocalDateTime
|
||||||
|
|
||||||
@Entity(tableName = "GradesSummary")
|
@Entity(tableName = "GradesSummary")
|
||||||
data class GradeSummary(
|
data class GradeSummary(
|
||||||
@ -36,4 +37,16 @@ data class GradeSummary(
|
|||||||
) {
|
) {
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
var id: Long = 0
|
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)
|
gradeDb.updateAll(grades)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateGradesSummary(gradesSummary: List<GradeSummary>) {
|
||||||
|
gradeSummaryDb.updateAll(gradesSummary)
|
||||||
|
}
|
||||||
|
|
||||||
fun getGradesDetails(semester: Semester): Maybe<List<Grade>> {
|
fun getGradesDetails(semester: Semester): Maybe<List<Grade>> {
|
||||||
return gradeDb.loadAll(semester.semesterId, semester.studentId).filter { it.isNotEmpty() }
|
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.github.wulkanowy.utils.uniqueSubtract
|
||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
|
import org.threeten.bp.LocalDateTime
|
||||||
import java.net.UnknownHostException
|
import java.net.UnknownHostException
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@ -43,7 +44,31 @@ class GradeRepository @Inject constructor(
|
|||||||
local.getGradesSummary(semester).toSingle(emptyList())
|
local.getGradesSummary(semester).toSingle(emptyList())
|
||||||
.doOnSuccess { old ->
|
.doOnSuccess { old ->
|
||||||
local.deleteGradesSummary(old.uniqueSubtract(newSummary))
|
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 {
|
}.flatMap {
|
||||||
@ -63,6 +88,14 @@ class GradeRepository @Inject constructor(
|
|||||||
return local.getGradesDetails(semester).map { it.filter { grade -> !grade.isNotified } }.toSingle(emptyList())
|
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 {
|
fun updateGrade(grade: Grade): Completable {
|
||||||
return Completable.fromCallable { local.updateGrades(listOf(grade)) }
|
return Completable.fromCallable { local.updateGrades(listOf(grade)) }
|
||||||
}
|
}
|
||||||
@ -70,4 +103,8 @@ class GradeRepository @Inject constructor(
|
|||||||
fun updateGrades(grades: List<Grade>): Completable {
|
fun updateGrades(grades: List<Grade>): Completable {
|
||||||
return Completable.fromCallable { local.updateGrades(grades) }
|
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 androidx.core.app.NotificationManagerCompat
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.data.db.entities.Grade
|
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.Semester
|
||||||
import io.github.wulkanowy.data.db.entities.Student
|
import io.github.wulkanowy.data.db.entities.Student
|
||||||
import io.github.wulkanowy.data.repositories.grade.GradeRepository
|
import io.github.wulkanowy.data.repositories.grade.GradeRepository
|
||||||
@ -30,17 +31,21 @@ class GradeWork @Inject constructor(
|
|||||||
|
|
||||||
override fun create(student: Student, semester: Semester): Completable {
|
override fun create(student: Student, semester: Semester): Completable {
|
||||||
return gradeRepository.getGrades(student, semester, true, preferencesRepository.isNotificationsEnable)
|
return gradeRepository.getGrades(student, semester, true, preferencesRepository.isNotificationsEnable)
|
||||||
.flatMap { gradeRepository.getNotNotifiedGrades(semester) }
|
.ignoreElement()
|
||||||
.flatMapCompletable {
|
.concatWith(Completable.concatArray(gradeRepository.getNotNotifiedGrades(semester).flatMapCompletable {
|
||||||
if (it.isNotEmpty()) notify(it)
|
if (it.isNotEmpty()) notifyDetails(it)
|
||||||
gradeRepository.updateGrades(it.onEach { grade -> grade.isNotified = true })
|
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>) {
|
private fun getNotificationBuilder(): NotificationCompat.Builder {
|
||||||
notificationManager.notify(Random.nextInt(Int.MAX_VALUE), NotificationCompat.Builder(context, NewGradesChannel.CHANNEL_ID)
|
return 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))
|
|
||||||
.setSmallIcon(R.drawable.ic_stat_grade)
|
.setSmallIcon(R.drawable.ic_stat_grade)
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
.setPriority(PRIORITY_HIGH)
|
.setPriority(PRIORITY_HIGH)
|
||||||
@ -49,6 +54,12 @@ class GradeWork @Inject constructor(
|
|||||||
.setContentIntent(
|
.setContentIntent(
|
||||||
PendingIntent.getActivity(context, MainView.Section.GRADE.id,
|
PendingIntent.getActivity(context, MainView.Section.GRADE.id,
|
||||||
MainActivity.getStartIntent(context, MainView.Section.GRADE, true), FLAG_UPDATE_CURRENT))
|
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 {
|
.setStyle(NotificationCompat.InboxStyle().run {
|
||||||
setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, grades.size, grades.size))
|
setSummaryText(context.resources.getQuantityString(R.plurals.grade_number_item, grades.size, grades.size))
|
||||||
grades.forEach { addLine("${it.subject}: ${it.entry}") }
|
grades.forEach { addLine("${it.subject}: ${it.entry}") }
|
||||||
@ -57,4 +68,30 @@ class GradeWork @Inject constructor(
|
|||||||
.build()
|
.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="many">Nowe oceny</item>
|
||||||
<item quantity="other">Nowe oceny</item>
|
<item quantity="other">Nowe oceny</item>
|
||||||
</plurals>
|
</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">
|
<plurals name="grade_notify_new_items">
|
||||||
<item quantity="one">Masz %1$d nową ocenę</item>
|
<item quantity="one">Masz %1$d nową ocenę</item>
|
||||||
<item quantity="few">Masz %1$d nowe oceny</item>
|
<item quantity="few">Masz %1$d nowe oceny</item>
|
||||||
<item quantity="many">Masz %1$d nowych ocen</item>
|
<item quantity="many">Masz %1$d nowych ocen</item>
|
||||||
<item quantity="other">Masz %1$d nowych ocen</item>
|
<item quantity="other">Masz %1$d nowych ocen</item>
|
||||||
</plurals>
|
</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-->
|
<!--Timetable-->
|
||||||
<string name="timetable_lesson">Lekcja</string>
|
<string name="timetable_lesson">Lekcja</string>
|
||||||
<string name="timetable_room">Sala</string>
|
<string name="timetable_room">Sala</string>
|
||||||
|
@ -113,10 +113,26 @@
|
|||||||
<item quantity="one">New grade</item>
|
<item quantity="one">New grade</item>
|
||||||
<item quantity="other">New grades</item>
|
<item quantity="other">New grades</item>
|
||||||
</plurals>
|
</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">
|
<plurals name="grade_notify_new_items">
|
||||||
<item quantity="one">You received %1$d grade</item>
|
<item quantity="one">You received %1$d grade</item>
|
||||||
<item quantity="other">You received %1$d grades</item>
|
<item quantity="other">You received %1$d grades</item>
|
||||||
</plurals>
|
</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-->
|
<!--Timetable-->
|
||||||
|
Loading…
x
Reference in New Issue
Block a user