diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebAttendance.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebAttendance.kt index e6f75694..7fe18171 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebAttendance.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebAttendance.kt @@ -96,8 +96,8 @@ class EdudziennikWebAttendance(override val data: DataEdudziennik, profileId, Metadata.TYPE_ATTENDANCE, id, - profile.empty, - profile.empty + profile.empty || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN, + profile.empty || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN )) } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebAttendance.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebAttendance.kt index d67acbdf..e77c9eac 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebAttendance.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebAttendance.kt @@ -148,8 +148,8 @@ class IdziennikWebAttendance(override val data: DataIdziennik, profileId, Metadata.TYPE_ATTENDANCE, attendanceObject.id, - profile?.empty ?: false, - profile?.empty ?: false + profile?.empty ?: false || baseType == TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN, + profile?.empty ?: false || baseType == TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN )) } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendances.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendances.kt index cf9d7729..7857dc2a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendances.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/api/LibrusApiAttendances.kt @@ -77,8 +77,8 @@ class LibrusApiAttendances(override val data: DataLibrus, profileId, Metadata.TYPE_ATTENDANCE, id, - profile?.empty ?: false, - profile?.empty ?: false + profile?.empty ?: false || type?.baseType == Attendance.TYPE_PRESENT_CUSTOM || type?.baseType == Attendance.TYPE_UNKNOWN, + profile?.empty ?: false || type?.baseType == Attendance.TYPE_PRESENT_CUSTOM || type?.baseType == Attendance.TYPE_UNKNOWN )) } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiAttendance.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiAttendance.kt index d9d7abb7..473b3691 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiAttendance.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiAttendance.kt @@ -72,8 +72,8 @@ class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List) data.profileId, Metadata.TYPE_ATTENDANCE, id, - data.profile?.empty ?: false, - data.profile?.empty ?: false + data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN, + data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN )) } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebAttendance.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebAttendance.kt index 57fef0a8..9dd4638d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebAttendance.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebAttendance.kt @@ -175,8 +175,8 @@ class MobidziennikWebAttendance(override val data: DataMobidziennik, data.profileId, Metadata.TYPE_ATTENDANCE, id, - data.profile?.empty ?: false, - data.profile?.empty ?: false + data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN, + data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN )) } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiAttendance.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiAttendance.kt index 2fc816ee..b75da00f 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiAttendance.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiAttendance.kt @@ -73,8 +73,8 @@ class VulcanApiAttendance(override val data: DataVulcan, profileId, Metadata.TYPE_ATTENDANCE, attendanceObject.id, - profile.empty, - profile.empty + profile.empty || type.baseType == Attendance.TYPE_PRESENT_CUSTOM || type.baseType == Attendance.TYPE_UNKNOWN, + profile.empty || type.baseType == Attendance.TYPE_PRESENT_CUSTOM || type.baseType == Attendance.TYPE_UNKNOWN )) } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Attendance.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Attendance.kt index 99953548..525c2b39 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Attendance.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Attendance.kt @@ -68,4 +68,9 @@ open class Attendance( @Ignore var showAsUnseen: Boolean? = null + + @delegate:Ignore + val typeObject by lazy { + AttendanceType(profileId, baseType.toLong(), baseType, typeName, typeShort, typeSymbol, typeColor) + } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/AttendanceType.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/AttendanceType.kt index f70c7bc6..904c06c6 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/AttendanceType.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/AttendanceType.kt @@ -21,4 +21,35 @@ data class AttendanceType ( val typeSymbol: String, /** A color that the e-register would display, null falls back to app's default */ val typeColor: Int? -) +) : Comparable { + + // attendance bar order: + // day_free, present, present_custom, unknown, belated_excused, belated, released, absent_excused, absent, + override fun compareTo(other: AttendanceType): Int { + val type1 = when (baseType) { + Attendance.TYPE_DAY_FREE -> 0 + Attendance.TYPE_PRESENT -> 1 + Attendance.TYPE_PRESENT_CUSTOM -> 2 + Attendance.TYPE_UNKNOWN -> 3 + Attendance.TYPE_BELATED_EXCUSED -> 4 + Attendance.TYPE_BELATED -> 5 + Attendance.TYPE_RELEASED -> 6 + Attendance.TYPE_ABSENT_EXCUSED -> 7 + Attendance.TYPE_ABSENT -> 8 + else -> 9 + } + val type2 = when (other.baseType) { + Attendance.TYPE_DAY_FREE -> 0 + Attendance.TYPE_PRESENT -> 1 + Attendance.TYPE_PRESENT_CUSTOM -> 2 + Attendance.TYPE_UNKNOWN -> 3 + Attendance.TYPE_BELATED_EXCUSED -> 4 + Attendance.TYPE_BELATED -> 5 + Attendance.TYPE_RELEASED -> 6 + Attendance.TYPE_ABSENT_EXCUSED -> 7 + Attendance.TYPE_ABSENT -> 8 + else -> 9 + } + return type1 - type2 + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/full/AttendanceFull.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/full/AttendanceFull.kt index 223ceb38..f235fafd 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/full/AttendanceFull.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/full/AttendanceFull.kt @@ -24,5 +24,6 @@ class AttendanceFull( // metadata var seen = false + get() = field || baseType == TYPE_PRESENT var notified = false } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceBar.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceBar.kt index 5fcdc8e0..bfe49a41 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceBar.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceBar.kt @@ -93,7 +93,7 @@ class AttendanceBar : View { val textBounds = Rect() textPaint.getTextBounds(e.count.toString(), 0, e.count.toString().length, textBounds) - if (width > textBounds.width() + 8.dp) { + if (width > textBounds.width() + 8.dp && height > textBounds.height() + 2.dp) { textPaint.color = Colors.legibleTextColor(e.color) canvas.drawText(e.count.toString(), left + width / 2, bottom - height / 2 + textBounds.height()/2, textPaint) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceListFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceListFragment.kt index 5f5da8ed..2f800bb0 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceListFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceListFragment.kt @@ -49,7 +49,6 @@ class AttendanceListFragment : LazyFragment(), CoroutineScope { context ?: return null app = activity.application as App b = AttendanceListFragmentBinding.inflate(inflater) - b.refreshLayout.setParent(activity.swipeRefreshLayout) return b.root } @@ -67,7 +66,7 @@ class AttendanceListFragment : LazyFragment(), CoroutineScope { // load & configure the adapter adapter.items = withContext(Dispatchers.Default) { processAttendance(items) } - if (items.isNotNullNorEmpty() && b.list.adapter == null) { + if (adapter.items.isNotNullNorEmpty() && b.list.adapter == null) { b.list.adapter = adapter b.list.apply { setHasFixedSize(true) @@ -76,6 +75,7 @@ class AttendanceListFragment : LazyFragment(), CoroutineScope { } } adapter.notifyDataSetChanged() + setSwipeToRefresh(adapter.items.isNullOrEmpty()) if (firstRun) { expandSubject(adapter) @@ -84,7 +84,7 @@ class AttendanceListFragment : LazyFragment(), CoroutineScope { // show/hide relevant views b.progressBar.isVisible = false - if (items.isNullOrEmpty()) { + if (adapter.items.isNullOrEmpty()) { b.list.isVisible = false b.noData.isVisible = true } else { @@ -141,6 +141,8 @@ class AttendanceListFragment : LazyFragment(), CoroutineScope { items.sortByDescending { it.rangeStart } val iterator = items.listIterator() + if (!iterator.hasNext()) + return items.toMutableList() var element = iterator.next() while (iterator.hasNext()) { var nextElement = iterator.next() @@ -170,14 +172,19 @@ class AttendanceListFragment : LazyFragment(), CoroutineScope { items.forEach { month -> month.typeCountMap = month.items - .groupBy { it.baseType } + .groupBy { it.typeObject } .map { it.key to it.value.size } .sortedBy { it.first } .toMap() - val totalCount = month.typeCountMap.entries.sumBy { it.value } + val totalCount = month.typeCountMap.entries.sumBy { + when (it.key.baseType) { + Attendance.TYPE_UNKNOWN -> 0 + else -> it.value + } + } val presenceCount = month.typeCountMap.entries.sumBy { - when (it.key) { + when (it.key.baseType) { Attendance.TYPE_PRESENT, Attendance.TYPE_PRESENT_CUSTOM, Attendance.TYPE_BELATED, diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceSummaryFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceSummaryFragment.kt index 829f03a0..2e4378c8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceSummaryFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/AttendanceSummaryFragment.kt @@ -4,35 +4,43 @@ package pl.szczodrzynski.edziennik.ui.modules.attendance +import android.graphics.Color import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.view.animation.AccelerateDecelerateInterpolator +import android.view.animation.Animation +import android.view.animation.Transformation +import android.widget.LinearLayout +import android.widget.TextView +import androidx.core.graphics.ColorUtils +import androidx.core.view.isInvisible import androidx.core.view.isVisible import androidx.lifecycle.Observer import androidx.recyclerview.widget.LinearLayoutManager import kotlinx.coroutines.* -import pl.szczodrzynski.edziennik.App -import pl.szczodrzynski.edziennik.MainActivity +import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.db.entity.Attendance import pl.szczodrzynski.edziennik.data.db.full.AttendanceFull -import pl.szczodrzynski.edziennik.databinding.AttendanceListFragmentBinding -import pl.szczodrzynski.edziennik.isNotNullNorEmpty -import pl.szczodrzynski.edziennik.startCoroutineTimer +import pl.szczodrzynski.edziennik.databinding.AttendanceSummaryFragmentBinding import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceFragment.Companion.VIEW_SUMMARY import pl.szczodrzynski.edziennik.ui.modules.attendance.models.AttendanceSubject import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyFragment import pl.szczodrzynski.edziennik.ui.modules.grades.models.GradesSubject +import pl.szczodrzynski.edziennik.utils.models.Date +import java.text.DecimalFormat import kotlin.coroutines.CoroutineContext class AttendanceSummaryFragment : LazyFragment(), CoroutineScope { companion object { private const val TAG = "AttendanceSummaryFragment" + private var periodSelection = 0 } private lateinit var app: App private lateinit var activity: MainActivity - private lateinit var b: AttendanceListFragmentBinding + private lateinit var b: AttendanceSummaryFragmentBinding private val job: Job = Job() override val coroutineContext: CoroutineContext @@ -41,13 +49,13 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope { // local/private variables go here private val manager by lazy { app.attendanceManager } private var expandSubjectId = 0L + private var attendance = listOf() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { activity = (getActivity() as MainActivity?) ?: return null context ?: return null app = activity.application as App - b = AttendanceListFragmentBinding.inflate(inflater) - b.refreshLayout.setParent(activity.swipeRefreshLayout) + b = AttendanceSummaryFragmentBinding.inflate(inflater) return b.root } @@ -63,16 +71,17 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope { if (!isAdded) return@launch // load & configure the adapter - adapter.items = withContext(Dispatchers.Default) { processAttendance(items) } - if (items.isNotNullNorEmpty() && b.list.adapter == null) { + attendance = items + adapter.items = withContext(Dispatchers.Default) { processAttendance() } + if (adapter.items.isNotNullNorEmpty() && b.list.adapter == null) { b.list.adapter = adapter b.list.apply { setHasFixedSize(true) layoutManager = LinearLayoutManager(context) - addOnScrollListener(onScrollListener) } } adapter.notifyDataSetChanged() + setSwipeToRefresh(adapter.items.isNullOrEmpty()) if (firstRun) { expandSubject(adapter) @@ -81,10 +90,12 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope { // show/hide relevant views b.progressBar.isVisible = false - if (items.isNullOrEmpty()) { + if (adapter.items.isNullOrEmpty()) { + b.statsLayout.isVisible = false b.list.isVisible = false b.noData.isVisible = true } else { + b.statsLayout.isVisible = true b.list.isVisible = true b.noData.isVisible = false } @@ -93,6 +104,36 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope { adapter.onAttendanceClick = { //GradeDetailsDialog(activity, it) } + + b.toggleGroup.check(when (periodSelection) { + 0 -> R.id.allYear + 1 -> R.id.semester1 + 2 -> R.id.semester2 + else -> R.id.allYear + }) + b.toggleGroup.addOnButtonCheckedListener { _, checkedId, isChecked -> + if (!isChecked) + return@addOnButtonCheckedListener + periodSelection = when (checkedId) { + R.id.allYear -> 0 + R.id.semester1 -> 1 + R.id.semester2 -> 2 + else -> 0 + } + this@AttendanceSummaryFragment.launch { + adapter.items = withContext(Dispatchers.Default) { processAttendance() } + if (adapter.items.isNullOrEmpty()) { + b.statsLayout.isVisible = false + b.list.isVisible = false + b.noData.isVisible = true + } else { + b.statsLayout.isVisible = true + b.list.isVisible = true + b.noData.isVisible = false + } + adapter.notifyDataSetChanged() + } + } }; return true} private fun expandSubject(adapter: AttendanceAdapter) { @@ -116,7 +157,14 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope { } @Suppress("SuspendFunctionOnCoroutineScope") - private fun processAttendance(attendance: List): MutableList { + private fun processAttendance(): MutableList { + val attendance = when (periodSelection) { + 0 -> attendance + 1 -> attendance.filter { it.semester == 1 } + 2 -> attendance.filter { it.semester == 2 } + else -> attendance + } + if (attendance.isEmpty()) return mutableListOf() @@ -129,16 +177,24 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope { ) } .sortedBy { it.subjectName.toLowerCase() } + var totalCountSum = 0 + var presenceCountSum = 0 + items.forEach { subject -> subject.typeCountMap = subject.items - .groupBy { it.baseType } + .groupBy { it.typeObject } .map { it.key to it.value.size } .sortedBy { it.first } .toMap() - val totalCount = subject.typeCountMap.entries.sumBy { it.value } + val totalCount = subject.typeCountMap.entries.sumBy { + when (it.key.baseType) { + Attendance.TYPE_UNKNOWN -> 0 + else -> it.value + } + } val presenceCount = subject.typeCountMap.entries.sumBy { - when (it.key) { + when (it.key.baseType) { Attendance.TYPE_PRESENT, Attendance.TYPE_PRESENT_CUSTOM, Attendance.TYPE_BELATED, @@ -147,6 +203,8 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope { else -> 0 } } + totalCountSum += totalCount + presenceCountSum += presenceCount subject.percentage = if (totalCount == 0) 0f @@ -157,6 +215,91 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope { subject.items.removeAll { it.baseType == Attendance.TYPE_PRESENT } } + val typeCountMap = attendance + .groupBy { it.typeObject } + .map { it.key to it.value.size } + .sortedBy { it.first } + .toMap() + + val percentage = if (totalCountSum == 0) + 0f + else + presenceCountSum.toFloat() / totalCountSum.toFloat() * 100f + + launch { + b.attendanceBar.setAttendanceData(typeCountMap.mapKeys { manager.getAttendanceColor(it.key) }) + b.attendanceBar.isInvisible = typeCountMap.isEmpty() + + b.previewContainer.removeAllViews() + val sum = typeCountMap.entries.sumBy { it.value }.toFloat() + typeCountMap.forEach { (type, count) -> + val layout = LinearLayout(activity) + val attendanceObject = Attendance( + profileId = 0, + id = 0, + baseType = type.baseType, + typeName = "", + typeShort = type.typeShort, + typeSymbol = type.typeSymbol, + typeColor = type.typeColor, + date = Date(0, 0, 0), + startTime = null, + semester = 0, + teacherId = 0, + subjectId = 0, + addedDate = 0 + ) + layout.addView(AttendanceView(activity, attendanceObject, manager)) + layout.addView(TextView(activity).also { + it.setText(R.string.attendance_percentage_format, count/sum*100f) + it.setPadding(0, 0, 5.dp, 0) + }) + layout.setPadding(0, 8.dp, 0, 8.dp) + b.previewContainer.addView(layout) + } + + if (percentage == 0f) { + b.percentage.isInvisible = true + b.percentageCircle.isInvisible = true + } + else { + b.percentage.isVisible = true + b.percentageCircle.isVisible = true + b.percentage.setText(R.string.attendance_period_summary_format, percentage) + + val df = DecimalFormat("0.##") + b.percentageCircle.setProgressTextAdapter { value -> + df.format(value) + "%" + } + b.percentageCircle.maxProgress = 100.0 + animatePercentageIndicator(percentage.toDouble()) + } + } + return items.toMutableList() } + + private fun animatePercentageIndicator(targetProgress: Double) { + val startingProgress = b.percentageCircle.progress + val progressChange = targetProgress - startingProgress + + val a: Animation = object : Animation() { + override fun applyTransformation(interpolatedTime: Float, t: Transformation) { + val progress = startingProgress + (progressChange * interpolatedTime) + //if (interpolatedTime == 1f) + // progress = startingProgress + progressChange + + val color = ColorUtils.blendARGB(Color.RED, Color.GREEN, progress.toFloat() / 100.0f) + b.percentageCircle.progressColor = color + b.percentageCircle.setProgress(progress, 100.0) + } + + override fun willChangeBounds(): Boolean { + return false + } + } + a.duration = 1300 + a.interpolator = AccelerateDecelerateInterpolator() + b.percentageCircle.startAnimation(a) + } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/models/AttendanceMonth.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/models/AttendanceMonth.kt index e1fde3f2..c6d14914 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/models/AttendanceMonth.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/models/AttendanceMonth.kt @@ -5,6 +5,7 @@ package pl.szczodrzynski.edziennik.ui.modules.attendance.models import pl.szczodrzynski.edziennik.data.db.entity.Attendance +import pl.szczodrzynski.edziennik.data.db.entity.AttendanceType import pl.szczodrzynski.edziennik.data.db.full.AttendanceFull import pl.szczodrzynski.edziennik.ui.modules.grades.models.ExpandableItemModel @@ -20,6 +21,6 @@ data class AttendanceMonth( var hasUnseen: Boolean = false get() = field || items.any { it.baseType != Attendance.TYPE_PRESENT && !it.seen } - var typeCountMap: Map = mapOf() + var typeCountMap: Map = mapOf() var percentage: Float = 0f } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/models/AttendanceSubject.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/models/AttendanceSubject.kt index 67332fc9..b56cd62a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/models/AttendanceSubject.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/models/AttendanceSubject.kt @@ -5,6 +5,7 @@ package pl.szczodrzynski.edziennik.ui.modules.attendance.models import pl.szczodrzynski.edziennik.data.db.entity.Attendance +import pl.szczodrzynski.edziennik.data.db.entity.AttendanceType import pl.szczodrzynski.edziennik.data.db.full.AttendanceFull import pl.szczodrzynski.edziennik.ui.modules.grades.models.ExpandableItemModel @@ -20,6 +21,6 @@ data class AttendanceSubject( var hasUnseen: Boolean = false get() = field || items.any { it.baseType != Attendance.TYPE_PRESENT && !it.seen } - var typeCountMap: Map = mapOf() + var typeCountMap: Map = mapOf() var percentage: Float = 0f } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/viewholder/MonthViewHolder.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/viewholder/MonthViewHolder.kt index 0c46cdab..8c010f81 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/viewholder/MonthViewHolder.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/viewholder/MonthViewHolder.kt @@ -63,11 +63,11 @@ class MonthViewHolder( val attendance = Attendance( profileId = 0, id = 0, - baseType = type, + baseType = type.baseType, typeName = "", - typeShort = manager.getTypeShort(type), - typeSymbol = manager.getTypeShort(type), - typeColor = manager.getAttendanceColor(type), + typeShort = type.typeShort, + typeSymbol = type.typeSymbol, + typeColor = type.typeColor, date = Date(0, 0, 0), startTime = null, semester = 0, @@ -80,7 +80,7 @@ class MonthViewHolder( it.setText(R.string.attendance_percentage_format, count/sum*100f) it.setPadding(0, 0, 5.dp, 0) }) - layout.setPadding(0, 8.dp, 0, 0) + layout.setPadding(0, 8.dp, 0, 8.dp) b.previewContainer.addView(layout) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/viewholder/SubjectViewHolder.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/viewholder/SubjectViewHolder.kt index d079a3a1..bea33ed4 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/viewholder/SubjectViewHolder.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/attendance/viewholder/SubjectViewHolder.kt @@ -6,31 +6,24 @@ package pl.szczodrzynski.edziennik.ui.modules.attendance.viewholder import android.view.LayoutInflater import android.view.ViewGroup -import android.widget.LinearLayout -import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ContextThemeWrapper -import androidx.core.view.isInvisible 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.entity.Attendance -import pl.szczodrzynski.edziennik.databinding.AttendanceItemContainerBarBinding -import pl.szczodrzynski.edziennik.dp +import pl.szczodrzynski.edziennik.databinding.AttendanceItemContainerSubjectBinding import pl.szczodrzynski.edziennik.setText import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceAdapter import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceAdapter.Companion.STATE_CLOSED -import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceView import pl.szczodrzynski.edziennik.ui.modules.attendance.models.AttendanceSubject import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.BindableViewHolder import pl.szczodrzynski.edziennik.utils.Themes -import pl.szczodrzynski.edziennik.utils.models.Date class SubjectViewHolder( inflater: LayoutInflater, parent: ViewGroup, - val b: AttendanceItemContainerBarBinding = AttendanceItemContainerBarBinding.inflate(inflater, parent, false) + val b: AttendanceItemContainerSubjectBinding = AttendanceItemContainerSubjectBinding.inflate(inflater, parent, false) ) : RecyclerView.ViewHolder(b.root), BindableViewHolder { companion object { private const val TAG = "SubjectViewHolder" @@ -51,48 +44,14 @@ class SubjectViewHolder( b.attendanceBar.setAttendanceData(item.typeCountMap.mapKeys { manager.getAttendanceColor(it.key) }) - b.previewContainer.isInvisible = item.state != STATE_CLOSED - b.summaryContainer.isInvisible = item.state == STATE_CLOSED - b.percentage.isVisible = item.state == STATE_CLOSED - - b.previewContainer.removeAllViews() - - val sum = item.typeCountMap.entries.sumBy { it.value }.toFloat() - item.typeCountMap.forEach { (type, count) -> - val layout = LinearLayout(contextWrapper) - val attendance = Attendance( - profileId = 0, - id = 0, - baseType = type, - typeName = "", - typeShort = manager.getTypeShort(type), - typeSymbol = manager.getTypeShort(type), - typeColor = manager.getAttendanceColor(type), - date = Date(0, 0, 0), - startTime = null, - semester = 0, - teacherId = 0, - subjectId = 0, - addedDate = 0 - ) - layout.addView(AttendanceView(contextWrapper, attendance, manager)) - layout.addView(TextView(contextWrapper).also { - it.setText(R.string.attendance_percentage_format, count/sum*100f) - it.setPadding(0, 0, 5.dp, 0) - }) - layout.setPadding(0, 8.dp, 0, 0) - b.previewContainer.addView(layout) - } + b.percentage.isVisible = true if (item.percentage == 0f) { b.percentage.isVisible = false b.percentage.text = null - b.summaryContainer.isVisible = false - b.summaryContainer.text = null } else { b.percentage.setText(R.string.attendance_percentage_format, item.percentage) - b.summaryContainer.setText(R.string.attendance_period_summary_format, item.percentage) } } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/AttendanceManager.kt b/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/AttendanceManager.kt index e77e5fbd..922831fd 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/AttendanceManager.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/AttendanceManager.kt @@ -9,6 +9,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.data.db.entity.Attendance +import pl.szczodrzynski.edziennik.data.db.entity.AttendanceType import pl.szczodrzynski.edziennik.data.db.full.AttendanceFull import pl.szczodrzynski.edziennik.startCoroutineTimer import kotlin.coroutines.CoroutineContext @@ -49,6 +50,12 @@ class AttendanceManager(val app: App) : CoroutineScope { else -> 0xff64b5f6.toInt() } } + fun getAttendanceColor(typeObject: AttendanceType): Int { + return (if (useSymbols) typeObject.typeColor else null) ?: when (typeObject.baseType) { + Attendance.TYPE_PRESENT_CUSTOM -> typeObject.typeColor ?: 0xff64b5f6.toInt() + else -> getAttendanceColor(typeObject.baseType) + } + } fun getAttendanceColor(attendance: Attendance): Int { return (if (useSymbols) attendance.typeColor else null) ?: when (attendance.baseType) { Attendance.TYPE_PRESENT_CUSTOM -> attendance.typeColor ?: 0xff64b5f6.toInt() diff --git a/app/src/main/res/layout/attendance_config_dialog.xml b/app/src/main/res/layout/attendance_config_dialog.xml index b31edc72..5d7db447 100644 --- a/app/src/main/res/layout/attendance_config_dialog.xml +++ b/app/src/main/res/layout/attendance_config_dialog.xml @@ -52,8 +52,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="32dp" - android:text="@string/attendance_config_show_presence_in_month" - android:visibility="gone" /> + android:text="@string/attendance_config_show_presence_in_month" /> diff --git a/app/src/main/res/layout/attendance_item_container_subject.xml b/app/src/main/res/layout/attendance_item_container_subject.xml new file mode 100644 index 00000000..bcf95152 --- /dev/null +++ b/app/src/main/res/layout/attendance_item_container_subject.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/attendance_list_fragment.xml b/app/src/main/res/layout/attendance_list_fragment.xml index 0d6e2abe..36f54733 100644 --- a/app/src/main/res/layout/attendance_list_fragment.xml +++ b/app/src/main/res/layout/attendance_list_fragment.xml @@ -7,41 +7,35 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> - - + + + + - - - - - - - - + android:layout_height="match_parent" + android:visibility="gone" + tools:listitem="@layout/attendance_item_attendance" + tools:visibility="visible" /> + diff --git a/app/src/main/res/layout/attendance_summary_fragment.xml b/app/src/main/res/layout/attendance_summary_fragment.xml index d3b1404e..e4d96e80 100644 --- a/app/src/main/res/layout/attendance_summary_fragment.xml +++ b/app/src/main/res/layout/attendance_summary_fragment.xml @@ -7,41 +7,165 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> - + android:layout_height="match_parent" + android:orientation="vertical"> - + android:layout_height="wrap_content" + android:layout_margin="8dp" + app:singleSelection="true" + app:selectionRequired="true" + android:gravity="center_horizontal"> - + android:text="Semestr 1" /> - + android:text="Semestr 2" /> - + + + + + - - + android:layout_height="wrap_content" + android:orientation="vertical"> + + + + + + + + + + + + + + + + + + + + + + + + + + + +