forked from github/szkolny
[Grades] Implement showing unseen badges and marking as seen. Change default "hide improved" config value.
This commit is contained in:
parent
098beb14fe
commit
42ef40439e
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user