[Grades] Implement showing unseen badges and marking as seen. Change default "hide improved" config value.

This commit is contained in:
Kuba Szczodrzyński 2020-03-09 20:18:11 +01:00
parent 098beb14fe
commit 42ef40439e
16 changed files with 248 additions and 71 deletions

View File

@ -28,7 +28,7 @@ class ProfileConfigGrades(private val config: ProfileConfig) {
private var mHideImproved: Boolean? = null
var hideImproved: Boolean
get() { mHideImproved = mHideImproved ?: config.values.get("hideImproved", true); return mHideImproved ?: true }
get() { mHideImproved = mHideImproved ?: config.values.get("hideImproved", false); return mHideImproved ?: false }
set(value) { config.set("hideImproved", value); mHideImproved = value }
private var mAverageWithoutWeight: Boolean? = null

View File

@ -5,6 +5,7 @@ package pl.szczodrzynski.edziennik.data.db.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.Index
/*public Grade(int profileId, long id, String category, int color, String description, String name, float value, float weight, int semester, long teacherId, long subjectId) {
@ -81,5 +82,11 @@ open class Grade(
*/
@ColumnInfo(name = "gradeIsImprovement")
var isImprovement = false
@Ignore
var showAsUnseen = false
val isImproved
get() = parentId ?: -1L != -1L
}

View File

@ -10,19 +10,24 @@ import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.db.entity.Grade
import pl.szczodrzynski.edziennik.data.db.full.GradeFull
import pl.szczodrzynski.edziennik.onClick
import pl.szczodrzynski.edziennik.startCoroutineTimer
import pl.szczodrzynski.edziennik.ui.modules.grades.models.*
import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.*
import kotlin.coroutines.CoroutineContext
class GradesAdapter(
val activity: AppCompatActivity,
var onGradeClick: ((item: GradeFull) -> Unit)? = null,
var onGradesEditorClick: ((subject: GradesSubject, semester: GradesSemester) -> Unit)? = null
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
) : RecyclerView.Adapter<RecyclerView.ViewHolder>(), CoroutineScope {
companion object {
private const val TAG = "GradesAdapter"
private const val ITEM_TYPE_SUBJECT = 0
@ -34,6 +39,13 @@ class GradesAdapter(
const val STATE_OPENED = 1
}
private val app = activity.applicationContext as App
private val manager = app.gradesManager
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
var items = mutableListOf<Any>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
@ -67,56 +79,63 @@ class GradesAdapter(
}
if (model !is ExpandableItemModel<*>)
return@OnClickListener
expandModel(model, view)
}
fun expandModel(model: ExpandableItemModel<*>?, view: View?, notifyAdapter: Boolean = true) {
model ?: return
val position = items.indexOf(model)
if (position == -1)
return@OnClickListener
//val position = it.getTag(R.string.tag_key_position) as? Int ?: return@OnClickListener
return
if (model is GradesSubject || model is GradesSemester) {
view.findViewById<View>(R.id.dropdownIcon)?.let { dropdownIcon ->
view?.findViewById<View>(R.id.dropdownIcon)?.let { dropdownIcon ->
ObjectAnimator.ofFloat(
dropdownIcon,
View.ROTATION,
if (model.state == STATE_CLOSED) 0f else 180f,
if (model.state == STATE_CLOSED) 180f else 0f
dropdownIcon,
View.ROTATION,
if (model.state == STATE_CLOSED) 0f else 180f,
if (model.state == STATE_CLOSED) 180f else 0f
).setDuration(200).start();
}
}
if (model is GradesSubject) {
val preview = view.findViewById<View>(R.id.previewContainer)
val summary = view.findViewById<View>(R.id.yearSummary)
val preview = view?.findViewById<View>(R.id.previewContainer)
val summary = view?.findViewById<View>(R.id.yearSummary)
preview?.visibility = if (model.state == STATE_CLOSED) View.INVISIBLE else View.VISIBLE
summary?.visibility = if (model.state == STATE_CLOSED) View.VISIBLE else View.INVISIBLE
}
if (model.state == STATE_CLOSED) {
val subItems = if (model is GradesSemester && model.grades.isEmpty())
listOf(GradesEmpty())
else
model.items
val subItems = when {
model is GradesSemester && model.grades.isEmpty() ->
listOf(GradesEmpty())
model is GradesSemester && manager.hideImproved ->
model.items.filter { !it.seen || !it.isImproved }
else -> model.items
}
model.state = STATE_OPENED
items.addAll(position + 1, subItems.filterNotNull())
notifyItemRangeInserted(position + 1, subItems.size)
/*notifyItemRangeChanged(
position + subItems.size,
items.size - (position + subItems.size)
)*/
//notifyItemRangeChanged(position, items.size - position)
if (notifyAdapter) notifyItemRangeInserted(position + 1, subItems.size)
if (model is GradesSubject) {
// auto expand first semester
if (model.semesters.isNotEmpty()) {
val semester = model.semesters.firstOrNull { it.grades.isNotEmpty() } ?: model.semesters.first()
val semesterIndex = model.semesters.indexOf(semester)
val grades = if (semester.grades.isEmpty())
listOf(GradesEmpty())
else
semester.grades
val grades = when {
semester.grades.isEmpty() ->
listOf(GradesEmpty())
manager.hideImproved ->
semester.grades.filter { !it.seen || !it.isImproved }
else -> semester.grades
}
semester.state = STATE_OPENED
items.addAll(position + 2 + semesterIndex, grades)
notifyItemRangeInserted(position + 2 + semesterIndex, grades.size)
if (notifyAdapter) notifyItemRangeInserted(position + 2 + semesterIndex, grades.size)
}
}
}
@ -138,9 +157,7 @@ class GradesAdapter(
if (end != -1) {
items.subList(start, end).clear()
notifyItemRangeRemoved(start, end - start)
//notifyItemRangeChanged(start, end - start)
//notifyItemRangeChanged(position, items.size - position)
if (notifyAdapter) notifyItemRangeRemoved(start, end - start)
}
model.state = STATE_CLOSED
@ -152,8 +169,6 @@ class GradesAdapter(
if (holder !is BindableViewHolder<*>)
return
val app = activity.applicationContext as App
val viewType = when (holder) {
is SubjectViewHolder -> ITEM_TYPE_SUBJECT
is SemesterViewHolder -> ITEM_TYPE_SEMESTER
@ -167,11 +182,11 @@ class GradesAdapter(
holder.itemView.setTag(R.string.tag_key_model, item)
when {
holder is SubjectViewHolder && item is GradesSubject -> holder.onBind(activity, app, item, position)
holder is SemesterViewHolder && item is GradesSemester -> holder.onBind(activity, app, item, position)
holder is EmptyViewHolder && item is GradesEmpty -> holder.onBind(activity, app, item, position)
holder is GradeViewHolder && item is GradeFull -> holder.onBind(activity, app, item, position)
holder is StatsViewHolder && item is GradesStats -> holder.onBind(activity, app, item, position)
holder is SubjectViewHolder && item is GradesSubject -> holder.onBind(activity, app, item, position, this)
holder is SemesterViewHolder && item is GradesSemester -> holder.onBind(activity, app, item, position, this)
holder is EmptyViewHolder && item is GradesEmpty -> holder.onBind(activity, app, item, position, this)
holder is GradeViewHolder && item is GradeFull -> holder.onBind(activity, app, item, position, this)
holder is StatsViewHolder && item is GradesStats -> holder.onBind(activity, app, item, position, this)
}
if (holder is SemesterViewHolder && item is GradesSemester) {
@ -184,5 +199,23 @@ class GradesAdapter(
holder.itemView.setOnClickListener(onClickListener)
}
fun notifyItemChanged(model: Any) {
startCoroutineTimer(1000L, 0L) {
val index = items.indexOf(model)
if (index != -1)
notifyItemChanged(index)
}
}
fun removeItem(model: Any) {
startCoroutineTimer(2000L, 0L) {
val index = items.indexOf(model)
if (index != -1) {
items.removeAt(index)
notifyItemRemoved(index)
}
}
}
override fun getItemCount() = items.size
}

View File

@ -12,11 +12,8 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.coroutines.*
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.Bundle
import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.MainActivity.Companion.TARGET_GRADES_EDITOR
import pl.szczodrzynski.edziennik.averageOrNull
import pl.szczodrzynski.edziennik.data.db.entity.Grade
import pl.szczodrzynski.edziennik.data.db.full.GradeFull
import pl.szczodrzynski.edziennik.databinding.GradesFragmentBinding
@ -48,6 +45,7 @@ class GradesFragment : Fragment(), CoroutineScope {
}
private val manager by lazy { app.gradesManager }
private val dontCountGrades by lazy { manager.dontCountGrades }
private var expandSubjectId = 0L
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
activity = (getActivity() as MainActivity?) ?: return null
@ -62,6 +60,8 @@ class GradesFragment : Fragment(), CoroutineScope {
if (!isAdded)
return
expandSubjectId = arguments?.getLong("gradesSubjectId") ?: 0L
app.db.gradeDao()
.getAllOrderBy(App.profileId, app.gradesManager.getOrderByString())
.observe(this, Observer { grades ->
@ -113,6 +113,7 @@ class GradesFragment : Fragment(), CoroutineScope {
}
}
@Suppress("SuspendFunctionOnCoroutineScope")
private suspend fun processGrades(grades: List<GradeFull>) {
val items = mutableListOf<GradesSubject>()
@ -146,6 +147,11 @@ class GradesFragment : Fragment(), CoroutineScope {
?: GradesSemester(subject.subjectId, grade.semester).also { subject.semesters += it }
}
grade.showAsUnseen = !grade.seen
if (!grade.seen) {
semester.hasUnseen = true
}
when (grade.type) {
Grade.TYPE_SEMESTER1_PROPOSED,
Grade.TYPE_SEMESTER2_PROPOSED -> semester.proposedGrade = grade
@ -154,10 +160,7 @@ class GradesFragment : Fragment(), CoroutineScope {
Grade.TYPE_YEAR_PROPOSED -> subject.proposedGrade = grade
Grade.TYPE_YEAR_FINAL -> subject.finalGrade = grade
else -> {
if (!hideImproved || grade.parentId ?: -1L == -1L) {
// hide improved grades if parent(new grade) ID is not set
semester.grades += grade
}
semester.grades += grade
countGrade(grade, subject.averages)
countGrade(grade, semester.averages)
}
@ -242,9 +245,27 @@ class GradesFragment : Fragment(), CoroutineScope {
adapter.items = items.toMutableList()
adapter.items.add(stats)
var expandSubjectModel: GradesSubject? = null
if (expandSubjectId != 0L) {
expandSubjectModel = items.firstOrNull { it.subjectId == expandSubjectId }
adapter.expandModel(
model = expandSubjectModel,
view = null,
notifyAdapter = false
)
}
withContext(Dispatchers.Main) {
adapter.notifyDataSetChanged()
}
startCoroutineTimer(500L, 0L) {
if (expandSubjectModel != null) {
b.gradesRecyclerView.smoothScrollToPosition(
items.indexOf(expandSubjectModel) + expandSubjectModel.semesters.size + (expandSubjectModel.semesters.firstOrNull()?.grades?.size ?: 0)
)
}
}
}
private fun countGrade(grade: Grade, averages: GradesAverages) {

View File

@ -4,16 +4,17 @@
package pl.szczodrzynski.edziennik.ui.modules.grades.models
import pl.szczodrzynski.edziennik.data.db.entity.Grade
import pl.szczodrzynski.edziennik.data.db.full.GradeFull
data class GradesSemester(
val subjectId: Long,
val number: Int,
val grades: MutableList<Grade> = mutableListOf()
) : ExpandableItemModel<Grade>(grades) {
val grades: MutableList<GradeFull> = mutableListOf()
) : ExpandableItemModel<GradeFull>(grades) {
override var level = 2
var hasUnseen = false
val averages = GradesAverages()
var proposedGrade: GradeFull? = null
var finalGrade: GradeFull? = null

View File

@ -16,6 +16,9 @@ data class GradesSubject(
var lastAddedDate = 0L
var semester: Int = 1
val hasUnseen
get() = semesters.any { it.hasUnseen }
val averages = GradesAverages()
var proposedGrade: GradeFull? = null
var finalGrade: GradeFull? = null

View File

@ -6,7 +6,8 @@ package pl.szczodrzynski.edziennik.ui.modules.grades.viewholder
import androidx.appcompat.app.AppCompatActivity
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.ui.modules.grades.GradesAdapter
interface BindableViewHolder<T> {
fun onBind(activity: AppCompatActivity, app: App, item: T, position: Int)
fun onBind(activity: AppCompatActivity, app: App, item: T, position: Int, adapter: GradesAdapter)
}

View File

@ -10,6 +10,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.databinding.GradesItemEmptyBinding
import pl.szczodrzynski.edziennik.ui.modules.grades.GradesAdapter
import pl.szczodrzynski.edziennik.ui.modules.grades.models.GradesEmpty
class EmptyViewHolder(
@ -21,7 +22,7 @@ class EmptyViewHolder(
private const val TAG = "EmptyViewHolder"
}
override fun onBind(activity: AppCompatActivity, app: App, item: GradesEmpty, position: Int) {
override fun onBind(activity: AppCompatActivity, app: App, item: GradesEmpty, position: Int, adapter: GradesAdapter) {
}
}

View File

@ -7,11 +7,14 @@ package pl.szczodrzynski.edziennik.ui.modules.grades.viewholder
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.db.full.GradeFull
import pl.szczodrzynski.edziennik.databinding.GradesItemGradeBinding
import pl.szczodrzynski.edziennik.ui.modules.grades.GradesAdapter
import pl.szczodrzynski.edziennik.ui.modules.grades.models.GradesSubject
import pl.szczodrzynski.edziennik.utils.models.Date
class GradeViewHolder(
@ -24,7 +27,7 @@ class GradeViewHolder(
}
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
override fun onBind(activity: AppCompatActivity, app: App, grade: GradeFull, position: Int) {
override fun onBind(activity: AppCompatActivity, app: App, grade: GradeFull, position: Int, adapter: GradesAdapter) {
val manager = app.gradesManager
b.gradeName.setGrade(grade, manager, bigView = true)
@ -45,19 +48,35 @@ class GradeViewHolder(
grade.category
}
b.gradeWeight.text = manager.getWeightString(activity, grade, showClassAverage = true)
val weightText = manager.getWeightString(activity, grade, showClassAverage = true)
b.gradeWeight.text = weightText
b.gradeWeight.isVisible = weightText != null
b.gradeTeacherName.text = grade.teacherFullName
b.gradeAddedDate.text = Date.fromMillis(grade.addedDate).let {
it.getRelativeString(app, 5) ?: it.formattedStringShort
}
/*if (!grade.seen) {
b.gradeDescription.setBackground(mContext.getResources().getDrawable(R.drawable.bg_rounded_4dp))
b.gradeDescription.getBackground()
.setColorFilter(PorterDuffColorFilter(0x692196f3, PorterDuff.Mode.MULTIPLY))
} else {
b.gradeDescription.setBackground(null)
}*/
b.unread.isVisible = grade.showAsUnseen
if (!grade.seen) {
manager.markAsSeen(grade)
val subject = adapter.items.firstOrNull {
it is GradesSubject && it.subjectId == grade.subjectId
} as? GradesSubject ?: return
val semester = subject.semesters.firstOrNull { it.number == grade.semester } ?: return
semester.hasUnseen = semester.grades.any { !it.seen }
// check if the unseen status has changed
if (!semester.hasUnseen) {
adapter.notifyItemChanged(semester)
}
if (!subject.hasUnseen) {
adapter.notifyItemChanged(subject)
}
if (manager.hideImproved && grade.isImproved) {
adapter.removeItem(grade)
}
}
}
}

View File

@ -7,6 +7,7 @@ package pl.szczodrzynski.edziennik.ui.modules.grades.viewholder
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R
@ -14,6 +15,7 @@ import pl.szczodrzynski.edziennik.databinding.GradesItemSemesterBinding
import pl.szczodrzynski.edziennik.setText
import pl.szczodrzynski.edziennik.ui.modules.grades.GradesAdapter
import pl.szczodrzynski.edziennik.ui.modules.grades.models.GradesSemester
import pl.szczodrzynski.edziennik.ui.modules.grades.models.GradesSubject
class SemesterViewHolder(
inflater: LayoutInflater,
@ -24,7 +26,7 @@ class SemesterViewHolder(
private const val TAG = "SemesterViewHolder"
}
override fun onBind(activity: AppCompatActivity, app: App, item: GradesSemester, position: Int) {
override fun onBind(activity: AppCompatActivity, app: App, item: GradesSemester, position: Int, adapter: GradesAdapter) {
val manager = app.gradesManager
b.semesterName.setText(R.string.grades_semester_format, item.number)
b.dropdownIcon.rotation = when (item.state) {
@ -32,6 +34,33 @@ class SemesterViewHolder(
else -> 180f
}
b.unread.isVisible = item.hasUnseen
var unseenChanged = false
if (item.proposedGrade?.seen == false) {
manager.markAsSeen(item.proposedGrade!!)
unseenChanged = true
}
if (item.finalGrade?.seen == false) {
manager.markAsSeen(item.finalGrade!!)
unseenChanged = true
}
if (unseenChanged) {
val subject = adapter.items.firstOrNull {
it is GradesSubject && it.subjectId == item.subjectId
} as? GradesSubject ?: return
item.hasUnseen = item.grades.any { !it.seen }
// check if the unseen status has changed
if (!item.hasUnseen) {
adapter.notifyItemChanged(item)
}
if (!subject.hasUnseen) {
adapter.notifyItemChanged(subject)
}
}
b.average.text = manager.getAverageString(app, item.averages)
b.proposedGrade.setGrade(item.proposedGrade, manager)
b.finalGrade.setGrade(item.finalGrade, manager)

View File

@ -16,6 +16,7 @@ import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.databinding.GradesItemStatsBinding
import pl.szczodrzynski.edziennik.onClick
import pl.szczodrzynski.edziennik.ui.dialogs.settings.GradesConfigDialog
import pl.szczodrzynski.edziennik.ui.modules.grades.GradesAdapter
import pl.szczodrzynski.edziennik.ui.modules.grades.models.GradesStats
import java.text.DecimalFormat
@ -28,7 +29,7 @@ class StatsViewHolder(
private const val TAG = "StatsViewHolder"
}
override fun onBind(activity: AppCompatActivity, app: App, item: GradesStats, position: Int) {
override fun onBind(activity: AppCompatActivity, app: App, item: GradesStats, position: Int, adapter: GradesAdapter) {
val manager = app.gradesManager
val showAverages = mutableListOf<Int>()
val showPoint = mutableListOf<Int>()
@ -109,7 +110,7 @@ class StatsViewHolder(
}
private fun getSemesterString(context: Context, expected: Float, proposed: Float, final: Float, notAllFinal: Boolean) : Pair<String?, String?> {
val format = DecimalFormat("#.##")
val format = DecimalFormat("#.00")
val average = when {
final != 0f -> final

View File

@ -14,6 +14,7 @@ import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.view.get
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R
@ -21,6 +22,7 @@ import pl.szczodrzynski.edziennik.databinding.GradesItemSubjectBinding
import pl.szczodrzynski.edziennik.dp
import pl.szczodrzynski.edziennik.setText
import pl.szczodrzynski.edziennik.ui.modules.grades.GradeView
import pl.szczodrzynski.edziennik.ui.modules.grades.GradesAdapter
import pl.szczodrzynski.edziennik.ui.modules.grades.GradesAdapter.Companion.STATE_CLOSED
import pl.szczodrzynski.edziennik.ui.modules.grades.models.GradesSubject
import pl.szczodrzynski.edziennik.utils.Themes
@ -34,7 +36,7 @@ class SubjectViewHolder(
private const val TAG = "SubjectViewHolder"
}
override fun onBind(activity: AppCompatActivity, app: App, item: GradesSubject, position: Int) {
override fun onBind(activity: AppCompatActivity, app: App, item: GradesSubject, position: Int, adapter: GradesAdapter) {
val manager = app.gradesManager
val contextWrapper = ContextThemeWrapper(activity, Themes.themeInt)
@ -44,6 +46,8 @@ class SubjectViewHolder(
else -> 180f
}
b.unread.isVisible = item.hasUnseen
b.previewContainer.visibility = if (item.state == STATE_CLOSED) View.VISIBLE else View.INVISIBLE
b.yearSummary.visibility = if (item.state == STATE_CLOSED) View.INVISIBLE else View.VISIBLE
@ -71,7 +75,10 @@ class SubjectViewHolder(
})
}*/
val hideImproved = manager.hideImproved
for (grade in firstSemester.grades) {
if (hideImproved && grade.isImproved)
continue
b.gradesContainer.addView(GradeView(
contextWrapper,
grade,

View File

@ -5,18 +5,23 @@
package pl.szczodrzynski.edziennik.utils.managers
import android.content.Context
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.db.entity.Grade
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_NORMAL
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_POINT_AVG
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_POINT_SUM
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_YEAR_FINAL
import pl.szczodrzynski.edziennik.data.db.full.GradeFull
import pl.szczodrzynski.edziennik.ui.modules.grades.models.GradesAverages
import pl.szczodrzynski.edziennik.ui.modules.grades.models.GradesSemester
import java.text.DecimalFormat
import kotlin.coroutines.CoroutineContext
import kotlin.math.floor
class GradesManager(val app: App) {
class GradesManager(val app: App) : CoroutineScope {
companion object {
const val ORDER_BY_DATE_DESC = 0
const val ORDER_BY_SUBJECT_ASC = 1
@ -31,6 +36,10 @@ class GradesManager(val app: App) {
const val COLOR_MODE_WEIGHTED = 1
}
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Default
private val gradeRegex by lazy { """([0-6])([+-])?""".toRegex() }
private val format = DecimalFormat("#.##")
@ -144,6 +153,13 @@ class GradesManager(val app: App) {
return color or 0xff000000.toInt()
}
fun markAsSeen(grade: GradeFull) {
grade.seen = true
startCoroutineTimer(500L, 0L) {
app.db.metadataDao().setSeen(grade.profileId, grade, true)
}
}
fun calculateAverages(averages: GradesAverages, semesters: List<GradesSemester>? = null) {
if (averages.pointAvgMax != 0f)
averages.pointAvgPercent = averages.pointAvgSum / averages.pointAvgMax * 100f

View File

@ -20,6 +20,10 @@
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
tools:background="@drawable/bg_rounded_8dp"
tools:backgroundTint="#4caf50"
tools:textSize="24sp"
tools:gravity="center"
tools:text="5+" />
<LinearLayout
@ -30,6 +34,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
@ -38,12 +43,22 @@
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginEnd="4dp"
android:layout_marginRight="4dp"
android:layout_weight="1"
android:ellipsize="end"
android:singleLine="true"
tools:text="kraje hehe no jak zwykle jedynka z geografii. to jest baaardzo długi tekst ale szkoda że się nie scrolluje." />
tools:text="kraje" />
<View
android:id="@+id/unread"
android:layout_width="12dp"
android:layout_height="12dp"
android:layout_marginEnd="4dp"
android:layout_marginRight="4dp"
android:visibility="gone"
android:background="@drawable/unread_red_circle"
tools:visibility="visible"/>
<TextView
android:id="@+id/gradeAddedDate"
@ -82,7 +97,7 @@
android:maxWidth="200dp"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:text="Kartkówki - K1 123456789 12345678" />
tools:text="Kartkówki - K1" />
<TextView
android:id="@+id/gradeTeacherName"
@ -95,7 +110,7 @@
android:gravity="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
tools:text="Anna Jakaśtam-Cośtam" />
tools:text="Jan Kowalski" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -37,6 +37,17 @@
android:textSize="18sp"
tools:text="Semestr 1" />
<View
android:id="@+id/unread"
android:layout_width="12dp"
android:layout_height="12dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:visibility="gone"
android:background="@drawable/unread_red_circle"
tools:visibility="visible"/>
<TextView
android:id="@+id/average"
android:layout_width="wrap_content"

View File

@ -20,7 +20,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/subjectName"
@ -33,7 +34,18 @@
android:maxLines="2"
android:textColor="?android:textColorPrimary"
android:textSize="20sp"
tools:text="systemy operacyjne\n1234" />
tools:text="systemy operacyjne" />
<View
android:id="@+id/unread"
android:layout_width="12dp"
android:layout_height="12dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:visibility="gone"
android:background="@drawable/unread_red_circle"
tools:visibility="visible"/>
<com.mikepenz.iconics.view.IconicsImageView
android:id="@+id/dropdownIcon"
@ -85,7 +97,7 @@
tools:text1="Cały rok: 3 oceny • suma: 320 pkt"
tools:text2="Cały rok: 15 ocen • średnia: 2,62"
tools:text="Cały rok: 6 ocen • punkty: 34.20/40 (87.5%)"
tools:visibility="gone"/>
tools:visibility="visible"/>
</FrameLayout>
</LinearLayout>
</layout>