mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-01-18 12:56:45 -06:00
[UI] Add attendance summary page. Disable presence notifications.
This commit is contained in:
parent
97412a3736
commit
e068f1944f
@ -96,8 +96,8 @@ class EdudziennikWebAttendance(override val data: DataEdudziennik,
|
|||||||
profileId,
|
profileId,
|
||||||
Metadata.TYPE_ATTENDANCE,
|
Metadata.TYPE_ATTENDANCE,
|
||||||
id,
|
id,
|
||||||
profile.empty,
|
profile.empty || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN,
|
||||||
profile.empty
|
profile.empty || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,8 +148,8 @@ class IdziennikWebAttendance(override val data: DataIdziennik,
|
|||||||
profileId,
|
profileId,
|
||||||
Metadata.TYPE_ATTENDANCE,
|
Metadata.TYPE_ATTENDANCE,
|
||||||
attendanceObject.id,
|
attendanceObject.id,
|
||||||
profile?.empty ?: false,
|
profile?.empty ?: false || baseType == TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN,
|
||||||
profile?.empty ?: false
|
profile?.empty ?: false || baseType == TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,8 +77,8 @@ class LibrusApiAttendances(override val data: DataLibrus,
|
|||||||
profileId,
|
profileId,
|
||||||
Metadata.TYPE_ATTENDANCE,
|
Metadata.TYPE_ATTENDANCE,
|
||||||
id,
|
id,
|
||||||
profile?.empty ?: false,
|
profile?.empty ?: false || type?.baseType == Attendance.TYPE_PRESENT_CUSTOM || type?.baseType == Attendance.TYPE_UNKNOWN,
|
||||||
profile?.empty ?: false
|
profile?.empty ?: false || type?.baseType == Attendance.TYPE_PRESENT_CUSTOM || type?.baseType == Attendance.TYPE_UNKNOWN
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,8 +72,8 @@ class MobidziennikApiAttendance(val data: DataMobidziennik, rows: List<String>)
|
|||||||
data.profileId,
|
data.profileId,
|
||||||
Metadata.TYPE_ATTENDANCE,
|
Metadata.TYPE_ATTENDANCE,
|
||||||
id,
|
id,
|
||||||
data.profile?.empty ?: false,
|
data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN,
|
||||||
data.profile?.empty ?: false
|
data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,8 +175,8 @@ class MobidziennikWebAttendance(override val data: DataMobidziennik,
|
|||||||
data.profileId,
|
data.profileId,
|
||||||
Metadata.TYPE_ATTENDANCE,
|
Metadata.TYPE_ATTENDANCE,
|
||||||
id,
|
id,
|
||||||
data.profile?.empty ?: false,
|
data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN,
|
||||||
data.profile?.empty ?: false
|
data.profile?.empty ?: false || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,8 +73,8 @@ class VulcanApiAttendance(override val data: DataVulcan,
|
|||||||
profileId,
|
profileId,
|
||||||
Metadata.TYPE_ATTENDANCE,
|
Metadata.TYPE_ATTENDANCE,
|
||||||
attendanceObject.id,
|
attendanceObject.id,
|
||||||
profile.empty,
|
profile.empty || type.baseType == Attendance.TYPE_PRESENT_CUSTOM || type.baseType == Attendance.TYPE_UNKNOWN,
|
||||||
profile.empty
|
profile.empty || type.baseType == Attendance.TYPE_PRESENT_CUSTOM || type.baseType == Attendance.TYPE_UNKNOWN
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,4 +68,9 @@ open class Attendance(
|
|||||||
|
|
||||||
@Ignore
|
@Ignore
|
||||||
var showAsUnseen: Boolean? = null
|
var showAsUnseen: Boolean? = null
|
||||||
|
|
||||||
|
@delegate:Ignore
|
||||||
|
val typeObject by lazy {
|
||||||
|
AttendanceType(profileId, baseType.toLong(), baseType, typeName, typeShort, typeSymbol, typeColor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,4 +21,35 @@ data class AttendanceType (
|
|||||||
val typeSymbol: String,
|
val typeSymbol: String,
|
||||||
/** A color that the e-register would display, null falls back to app's default */
|
/** A color that the e-register would display, null falls back to app's default */
|
||||||
val typeColor: Int?
|
val typeColor: Int?
|
||||||
)
|
) : Comparable<AttendanceType> {
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -24,5 +24,6 @@ class AttendanceFull(
|
|||||||
|
|
||||||
// metadata
|
// metadata
|
||||||
var seen = false
|
var seen = false
|
||||||
|
get() = field || baseType == TYPE_PRESENT
|
||||||
var notified = false
|
var notified = false
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ class AttendanceBar : View {
|
|||||||
|
|
||||||
val textBounds = Rect()
|
val textBounds = Rect()
|
||||||
textPaint.getTextBounds(e.count.toString(), 0, e.count.toString().length, textBounds)
|
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)
|
textPaint.color = Colors.legibleTextColor(e.color)
|
||||||
canvas.drawText(e.count.toString(), left + width / 2, bottom - height / 2 + textBounds.height()/2, textPaint)
|
canvas.drawText(e.count.toString(), left + width / 2, bottom - height / 2 + textBounds.height()/2, textPaint)
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,6 @@ class AttendanceListFragment : LazyFragment(), CoroutineScope {
|
|||||||
context ?: return null
|
context ?: return null
|
||||||
app = activity.application as App
|
app = activity.application as App
|
||||||
b = AttendanceListFragmentBinding.inflate(inflater)
|
b = AttendanceListFragmentBinding.inflate(inflater)
|
||||||
b.refreshLayout.setParent(activity.swipeRefreshLayout)
|
|
||||||
return b.root
|
return b.root
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +66,7 @@ class AttendanceListFragment : LazyFragment(), CoroutineScope {
|
|||||||
|
|
||||||
// load & configure the adapter
|
// load & configure the adapter
|
||||||
adapter.items = withContext(Dispatchers.Default) { processAttendance(items) }
|
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.adapter = adapter
|
||||||
b.list.apply {
|
b.list.apply {
|
||||||
setHasFixedSize(true)
|
setHasFixedSize(true)
|
||||||
@ -76,6 +75,7 @@ class AttendanceListFragment : LazyFragment(), CoroutineScope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
adapter.notifyDataSetChanged()
|
adapter.notifyDataSetChanged()
|
||||||
|
setSwipeToRefresh(adapter.items.isNullOrEmpty())
|
||||||
|
|
||||||
if (firstRun) {
|
if (firstRun) {
|
||||||
expandSubject(adapter)
|
expandSubject(adapter)
|
||||||
@ -84,7 +84,7 @@ class AttendanceListFragment : LazyFragment(), CoroutineScope {
|
|||||||
|
|
||||||
// show/hide relevant views
|
// show/hide relevant views
|
||||||
b.progressBar.isVisible = false
|
b.progressBar.isVisible = false
|
||||||
if (items.isNullOrEmpty()) {
|
if (adapter.items.isNullOrEmpty()) {
|
||||||
b.list.isVisible = false
|
b.list.isVisible = false
|
||||||
b.noData.isVisible = true
|
b.noData.isVisible = true
|
||||||
} else {
|
} else {
|
||||||
@ -141,6 +141,8 @@ class AttendanceListFragment : LazyFragment(), CoroutineScope {
|
|||||||
items.sortByDescending { it.rangeStart }
|
items.sortByDescending { it.rangeStart }
|
||||||
val iterator = items.listIterator()
|
val iterator = items.listIterator()
|
||||||
|
|
||||||
|
if (!iterator.hasNext())
|
||||||
|
return items.toMutableList()
|
||||||
var element = iterator.next()
|
var element = iterator.next()
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
var nextElement = iterator.next()
|
var nextElement = iterator.next()
|
||||||
@ -170,14 +172,19 @@ class AttendanceListFragment : LazyFragment(), CoroutineScope {
|
|||||||
|
|
||||||
items.forEach { month ->
|
items.forEach { month ->
|
||||||
month.typeCountMap = month.items
|
month.typeCountMap = month.items
|
||||||
.groupBy { it.baseType }
|
.groupBy { it.typeObject }
|
||||||
.map { it.key to it.value.size }
|
.map { it.key to it.value.size }
|
||||||
.sortedBy { it.first }
|
.sortedBy { it.first }
|
||||||
.toMap()
|
.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 {
|
val presenceCount = month.typeCountMap.entries.sumBy {
|
||||||
when (it.key) {
|
when (it.key.baseType) {
|
||||||
Attendance.TYPE_PRESENT,
|
Attendance.TYPE_PRESENT,
|
||||||
Attendance.TYPE_PRESENT_CUSTOM,
|
Attendance.TYPE_PRESENT_CUSTOM,
|
||||||
Attendance.TYPE_BELATED,
|
Attendance.TYPE_BELATED,
|
||||||
|
@ -4,35 +4,43 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.ui.modules.attendance
|
package pl.szczodrzynski.edziennik.ui.modules.attendance
|
||||||
|
|
||||||
|
import android.graphics.Color
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
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.core.view.isVisible
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.*
|
||||||
import pl.szczodrzynski.edziennik.MainActivity
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
|
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
|
||||||
import pl.szczodrzynski.edziennik.data.db.full.AttendanceFull
|
import pl.szczodrzynski.edziennik.data.db.full.AttendanceFull
|
||||||
import pl.szczodrzynski.edziennik.databinding.AttendanceListFragmentBinding
|
import pl.szczodrzynski.edziennik.databinding.AttendanceSummaryFragmentBinding
|
||||||
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
|
||||||
import pl.szczodrzynski.edziennik.startCoroutineTimer
|
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceFragment.Companion.VIEW_SUMMARY
|
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.attendance.models.AttendanceSubject
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyFragment
|
import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.grades.models.GradesSubject
|
import pl.szczodrzynski.edziennik.ui.modules.grades.models.GradesSubject
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
import java.text.DecimalFormat
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
class AttendanceSummaryFragment : LazyFragment(), CoroutineScope {
|
class AttendanceSummaryFragment : LazyFragment(), CoroutineScope {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "AttendanceSummaryFragment"
|
private const val TAG = "AttendanceSummaryFragment"
|
||||||
|
private var periodSelection = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var app: App
|
private lateinit var app: App
|
||||||
private lateinit var activity: MainActivity
|
private lateinit var activity: MainActivity
|
||||||
private lateinit var b: AttendanceListFragmentBinding
|
private lateinit var b: AttendanceSummaryFragmentBinding
|
||||||
|
|
||||||
private val job: Job = Job()
|
private val job: Job = Job()
|
||||||
override val coroutineContext: CoroutineContext
|
override val coroutineContext: CoroutineContext
|
||||||
@ -41,13 +49,13 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope {
|
|||||||
// local/private variables go here
|
// local/private variables go here
|
||||||
private val manager by lazy { app.attendanceManager }
|
private val manager by lazy { app.attendanceManager }
|
||||||
private var expandSubjectId = 0L
|
private var expandSubjectId = 0L
|
||||||
|
private var attendance = listOf<AttendanceFull>()
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
activity = (getActivity() as MainActivity?) ?: return null
|
activity = (getActivity() as MainActivity?) ?: return null
|
||||||
context ?: return null
|
context ?: return null
|
||||||
app = activity.application as App
|
app = activity.application as App
|
||||||
b = AttendanceListFragmentBinding.inflate(inflater)
|
b = AttendanceSummaryFragmentBinding.inflate(inflater)
|
||||||
b.refreshLayout.setParent(activity.swipeRefreshLayout)
|
|
||||||
return b.root
|
return b.root
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,16 +71,17 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope {
|
|||||||
if (!isAdded) return@launch
|
if (!isAdded) return@launch
|
||||||
|
|
||||||
// load & configure the adapter
|
// load & configure the adapter
|
||||||
adapter.items = withContext(Dispatchers.Default) { processAttendance(items) }
|
attendance = items
|
||||||
if (items.isNotNullNorEmpty() && b.list.adapter == null) {
|
adapter.items = withContext(Dispatchers.Default) { processAttendance() }
|
||||||
|
if (adapter.items.isNotNullNorEmpty() && b.list.adapter == null) {
|
||||||
b.list.adapter = adapter
|
b.list.adapter = adapter
|
||||||
b.list.apply {
|
b.list.apply {
|
||||||
setHasFixedSize(true)
|
setHasFixedSize(true)
|
||||||
layoutManager = LinearLayoutManager(context)
|
layoutManager = LinearLayoutManager(context)
|
||||||
addOnScrollListener(onScrollListener)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
adapter.notifyDataSetChanged()
|
adapter.notifyDataSetChanged()
|
||||||
|
setSwipeToRefresh(adapter.items.isNullOrEmpty())
|
||||||
|
|
||||||
if (firstRun) {
|
if (firstRun) {
|
||||||
expandSubject(adapter)
|
expandSubject(adapter)
|
||||||
@ -81,10 +90,12 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope {
|
|||||||
|
|
||||||
// show/hide relevant views
|
// show/hide relevant views
|
||||||
b.progressBar.isVisible = false
|
b.progressBar.isVisible = false
|
||||||
if (items.isNullOrEmpty()) {
|
if (adapter.items.isNullOrEmpty()) {
|
||||||
|
b.statsLayout.isVisible = false
|
||||||
b.list.isVisible = false
|
b.list.isVisible = false
|
||||||
b.noData.isVisible = true
|
b.noData.isVisible = true
|
||||||
} else {
|
} else {
|
||||||
|
b.statsLayout.isVisible = true
|
||||||
b.list.isVisible = true
|
b.list.isVisible = true
|
||||||
b.noData.isVisible = false
|
b.noData.isVisible = false
|
||||||
}
|
}
|
||||||
@ -93,6 +104,36 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope {
|
|||||||
adapter.onAttendanceClick = {
|
adapter.onAttendanceClick = {
|
||||||
//GradeDetailsDialog(activity, it)
|
//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}
|
}; return true}
|
||||||
|
|
||||||
private fun expandSubject(adapter: AttendanceAdapter) {
|
private fun expandSubject(adapter: AttendanceAdapter) {
|
||||||
@ -116,7 +157,14 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("SuspendFunctionOnCoroutineScope")
|
@Suppress("SuspendFunctionOnCoroutineScope")
|
||||||
private fun processAttendance(attendance: List<AttendanceFull>): MutableList<Any> {
|
private fun processAttendance(): MutableList<Any> {
|
||||||
|
val attendance = when (periodSelection) {
|
||||||
|
0 -> attendance
|
||||||
|
1 -> attendance.filter { it.semester == 1 }
|
||||||
|
2 -> attendance.filter { it.semester == 2 }
|
||||||
|
else -> attendance
|
||||||
|
}
|
||||||
|
|
||||||
if (attendance.isEmpty())
|
if (attendance.isEmpty())
|
||||||
return mutableListOf()
|
return mutableListOf()
|
||||||
|
|
||||||
@ -129,16 +177,24 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope {
|
|||||||
) }
|
) }
|
||||||
.sortedBy { it.subjectName.toLowerCase() }
|
.sortedBy { it.subjectName.toLowerCase() }
|
||||||
|
|
||||||
|
var totalCountSum = 0
|
||||||
|
var presenceCountSum = 0
|
||||||
|
|
||||||
items.forEach { subject ->
|
items.forEach { subject ->
|
||||||
subject.typeCountMap = subject.items
|
subject.typeCountMap = subject.items
|
||||||
.groupBy { it.baseType }
|
.groupBy { it.typeObject }
|
||||||
.map { it.key to it.value.size }
|
.map { it.key to it.value.size }
|
||||||
.sortedBy { it.first }
|
.sortedBy { it.first }
|
||||||
.toMap()
|
.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 {
|
val presenceCount = subject.typeCountMap.entries.sumBy {
|
||||||
when (it.key) {
|
when (it.key.baseType) {
|
||||||
Attendance.TYPE_PRESENT,
|
Attendance.TYPE_PRESENT,
|
||||||
Attendance.TYPE_PRESENT_CUSTOM,
|
Attendance.TYPE_PRESENT_CUSTOM,
|
||||||
Attendance.TYPE_BELATED,
|
Attendance.TYPE_BELATED,
|
||||||
@ -147,6 +203,8 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope {
|
|||||||
else -> 0
|
else -> 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
totalCountSum += totalCount
|
||||||
|
presenceCountSum += presenceCount
|
||||||
|
|
||||||
subject.percentage = if (totalCount == 0)
|
subject.percentage = if (totalCount == 0)
|
||||||
0f
|
0f
|
||||||
@ -157,6 +215,91 @@ class AttendanceSummaryFragment : LazyFragment(), CoroutineScope {
|
|||||||
subject.items.removeAll { it.baseType == Attendance.TYPE_PRESENT }
|
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()
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
package pl.szczodrzynski.edziennik.ui.modules.attendance.models
|
package pl.szczodrzynski.edziennik.ui.modules.attendance.models
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
|
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.data.db.full.AttendanceFull
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.grades.models.ExpandableItemModel
|
import pl.szczodrzynski.edziennik.ui.modules.grades.models.ExpandableItemModel
|
||||||
|
|
||||||
@ -20,6 +21,6 @@ data class AttendanceMonth(
|
|||||||
var hasUnseen: Boolean = false
|
var hasUnseen: Boolean = false
|
||||||
get() = field || items.any { it.baseType != Attendance.TYPE_PRESENT && !it.seen }
|
get() = field || items.any { it.baseType != Attendance.TYPE_PRESENT && !it.seen }
|
||||||
|
|
||||||
var typeCountMap: Map<Int, Int> = mapOf()
|
var typeCountMap: Map<AttendanceType, Int> = mapOf()
|
||||||
var percentage: Float = 0f
|
var percentage: Float = 0f
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
package pl.szczodrzynski.edziennik.ui.modules.attendance.models
|
package pl.szczodrzynski.edziennik.ui.modules.attendance.models
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
|
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.data.db.full.AttendanceFull
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.grades.models.ExpandableItemModel
|
import pl.szczodrzynski.edziennik.ui.modules.grades.models.ExpandableItemModel
|
||||||
|
|
||||||
@ -20,6 +21,6 @@ data class AttendanceSubject(
|
|||||||
var hasUnseen: Boolean = false
|
var hasUnseen: Boolean = false
|
||||||
get() = field || items.any { it.baseType != Attendance.TYPE_PRESENT && !it.seen }
|
get() = field || items.any { it.baseType != Attendance.TYPE_PRESENT && !it.seen }
|
||||||
|
|
||||||
var typeCountMap: Map<Int, Int> = mapOf()
|
var typeCountMap: Map<AttendanceType, Int> = mapOf()
|
||||||
var percentage: Float = 0f
|
var percentage: Float = 0f
|
||||||
}
|
}
|
||||||
|
@ -63,11 +63,11 @@ class MonthViewHolder(
|
|||||||
val attendance = Attendance(
|
val attendance = Attendance(
|
||||||
profileId = 0,
|
profileId = 0,
|
||||||
id = 0,
|
id = 0,
|
||||||
baseType = type,
|
baseType = type.baseType,
|
||||||
typeName = "",
|
typeName = "",
|
||||||
typeShort = manager.getTypeShort(type),
|
typeShort = type.typeShort,
|
||||||
typeSymbol = manager.getTypeShort(type),
|
typeSymbol = type.typeSymbol,
|
||||||
typeColor = manager.getAttendanceColor(type),
|
typeColor = type.typeColor,
|
||||||
date = Date(0, 0, 0),
|
date = Date(0, 0, 0),
|
||||||
startTime = null,
|
startTime = null,
|
||||||
semester = 0,
|
semester = 0,
|
||||||
@ -80,7 +80,7 @@ class MonthViewHolder(
|
|||||||
it.setText(R.string.attendance_percentage_format, count/sum*100f)
|
it.setText(R.string.attendance_percentage_format, count/sum*100f)
|
||||||
it.setPadding(0, 0, 5.dp, 0)
|
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)
|
b.previewContainer.addView(layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,31 +6,24 @@ package pl.szczodrzynski.edziennik.ui.modules.attendance.viewholder
|
|||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.view.ContextThemeWrapper
|
import androidx.appcompat.view.ContextThemeWrapper
|
||||||
import androidx.core.view.isInvisible
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
|
import pl.szczodrzynski.edziennik.databinding.AttendanceItemContainerSubjectBinding
|
||||||
import pl.szczodrzynski.edziennik.databinding.AttendanceItemContainerBarBinding
|
|
||||||
import pl.szczodrzynski.edziennik.dp
|
|
||||||
import pl.szczodrzynski.edziennik.setText
|
import pl.szczodrzynski.edziennik.setText
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceAdapter
|
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.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.attendance.models.AttendanceSubject
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.BindableViewHolder
|
import pl.szczodrzynski.edziennik.ui.modules.grades.viewholder.BindableViewHolder
|
||||||
import pl.szczodrzynski.edziennik.utils.Themes
|
import pl.szczodrzynski.edziennik.utils.Themes
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
|
|
||||||
class SubjectViewHolder(
|
class SubjectViewHolder(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
parent: ViewGroup,
|
parent: ViewGroup,
|
||||||
val b: AttendanceItemContainerBarBinding = AttendanceItemContainerBarBinding.inflate(inflater, parent, false)
|
val b: AttendanceItemContainerSubjectBinding = AttendanceItemContainerSubjectBinding.inflate(inflater, parent, false)
|
||||||
) : RecyclerView.ViewHolder(b.root), BindableViewHolder<AttendanceSubject, AttendanceAdapter> {
|
) : RecyclerView.ViewHolder(b.root), BindableViewHolder<AttendanceSubject, AttendanceAdapter> {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "SubjectViewHolder"
|
private const val TAG = "SubjectViewHolder"
|
||||||
@ -51,48 +44,14 @@ class SubjectViewHolder(
|
|||||||
|
|
||||||
b.attendanceBar.setAttendanceData(item.typeCountMap.mapKeys { manager.getAttendanceColor(it.key) })
|
b.attendanceBar.setAttendanceData(item.typeCountMap.mapKeys { manager.getAttendanceColor(it.key) })
|
||||||
|
|
||||||
b.previewContainer.isInvisible = item.state != STATE_CLOSED
|
b.percentage.isVisible = true
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.percentage == 0f) {
|
if (item.percentage == 0f) {
|
||||||
b.percentage.isVisible = false
|
b.percentage.isVisible = false
|
||||||
b.percentage.text = null
|
b.percentage.text = null
|
||||||
b.summaryContainer.isVisible = false
|
|
||||||
b.summaryContainer.text = null
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
b.percentage.setText(R.string.attendance_percentage_format, item.percentage)
|
b.percentage.setText(R.string.attendance_percentage_format, item.percentage)
|
||||||
b.summaryContainer.setText(R.string.attendance_period_summary_format, item.percentage)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
|
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.data.db.full.AttendanceFull
|
||||||
import pl.szczodrzynski.edziennik.startCoroutineTimer
|
import pl.szczodrzynski.edziennik.startCoroutineTimer
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
@ -49,6 +50,12 @@ class AttendanceManager(val app: App) : CoroutineScope {
|
|||||||
else -> 0xff64b5f6.toInt()
|
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 {
|
fun getAttendanceColor(attendance: Attendance): Int {
|
||||||
return (if (useSymbols) attendance.typeColor else null) ?: when (attendance.baseType) {
|
return (if (useSymbols) attendance.typeColor else null) ?: when (attendance.baseType) {
|
||||||
Attendance.TYPE_PRESENT_CUSTOM -> attendance.typeColor ?: 0xff64b5f6.toInt()
|
Attendance.TYPE_PRESENT_CUSTOM -> attendance.typeColor ?: 0xff64b5f6.toInt()
|
||||||
|
@ -52,8 +52,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minHeight="32dp"
|
android:minHeight="32dp"
|
||||||
android:text="@string/attendance_config_show_presence_in_month"
|
android:text="@string/attendance_config_show_presence_in_month" />
|
||||||
android:visibility="gone" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -0,0 +1,80 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) Kuba Szczodrzyński 2020-5-5.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:background="?selectableItemBackground">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="@drawable/divider"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:textColor="?android:textColorPrimary"
|
||||||
|
android:textSize="20sp"
|
||||||
|
tools:text="historia i społeczeństwo" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/unread"
|
||||||
|
android:layout_width="12dp"
|
||||||
|
android:layout_height="12dp"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_marginEnd="4dp"
|
||||||
|
android:layout_marginRight="4dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:background="@drawable/unread_red_circle"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/percentage"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_marginEnd="4dp"
|
||||||
|
android:layout_marginRight="4dp"
|
||||||
|
tools:text="6,5%" />
|
||||||
|
|
||||||
|
<com.mikepenz.iconics.view.IconicsImageView
|
||||||
|
android:id="@+id/dropdownIcon"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="36dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:scaleType="centerInside"
|
||||||
|
app:iiv_color="?android:textColorSecondary"
|
||||||
|
app:iiv_icon="cmd-chevron-down"
|
||||||
|
app:iiv_size="18dp"
|
||||||
|
tools:src="@android:drawable/ic_menu_more" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceBar
|
||||||
|
android:id="@+id/attendanceBar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="12dp"
|
||||||
|
android:layout_marginHorizontal="8dp"
|
||||||
|
android:layout_marginBottom="8dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
</layout>
|
@ -7,41 +7,35 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator
|
<FrameLayout
|
||||||
android:id="@+id/refreshLayout"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<FrameLayout
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/noData"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:drawablePadding="16dp"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
android:text="@string/attendances_no_data"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:drawableTopCompat="@drawable/ic_no_grades"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/list"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:visibility="gone"
|
||||||
<ProgressBar
|
tools:listitem="@layout/attendance_item_attendance"
|
||||||
android:id="@+id/progressBar"
|
tools:visibility="visible" />
|
||||||
android:layout_width="wrap_content"
|
</FrameLayout>
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
|
||||||
android:id="@+id/noData"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:drawablePadding="16dp"
|
|
||||||
android:fontFamily="sans-serif-light"
|
|
||||||
android:text="@string/attendances_no_data"
|
|
||||||
android:textSize="24sp"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:drawableTopCompat="@drawable/ic_no_grades"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/list"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:listitem="@layout/attendance_item_attendance"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
</FrameLayout>
|
|
||||||
</pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator>
|
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -7,41 +7,165 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator
|
<LinearLayout
|
||||||
android:id="@+id/refreshLayout"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
<FrameLayout
|
<com.google.android.material.button.MaterialButtonToggleGroup
|
||||||
|
android:id="@+id/toggleGroup"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
app:singleSelection="true"
|
||||||
|
app:selectionRequired="true"
|
||||||
|
android:gravity="center_horizontal">
|
||||||
|
|
||||||
<ProgressBar
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/progressBar"
|
android:id="@+id/semester1"
|
||||||
|
style="?materialButtonOutlinedStyle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center" />
|
android:text="Semestr 1" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/noData"
|
android:id="@+id/semester2"
|
||||||
|
style="?materialButtonOutlinedStyle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:text="Semestr 2" />
|
||||||
android:drawablePadding="16dp"
|
|
||||||
android:fontFamily="sans-serif-light"
|
|
||||||
android:text="@string/attendances_no_data"
|
|
||||||
android:textSize="24sp"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:drawableTopCompat="@drawable/ic_no_grades"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/list"
|
android:id="@+id/allYear"
|
||||||
|
style="?materialButtonOutlinedStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Cały rok" />
|
||||||
|
</com.google.android.material.button.MaterialButtonToggleGroup>
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:id="@+id/scrollView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:visibility="gone"
|
android:orientation="vertical">
|
||||||
tools:listitem="@layout/attendance_item_attendance"
|
|
||||||
tools:visibility="visible" />
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
</FrameLayout>
|
android:id="@+id/statsLayout"
|
||||||
</pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator>
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/percentage"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="8dp"
|
||||||
|
android:textAppearance="@style/NavView.TextView.Subtitle"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="Obecność w tym okresie: 99,7%" />
|
||||||
|
|
||||||
|
<antonkozyriatskyi.circularprogressindicator.CircularProgressIndicator
|
||||||
|
android:id="@+id/percentageCircle"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:layout_marginHorizontal="8dp"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
app:direction="clockwise"
|
||||||
|
app:drawDot="false"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:progressBackgroundStrokeWidth="9dp"
|
||||||
|
app:progressStrokeWidth="10dp"
|
||||||
|
app:progressCap="butt"
|
||||||
|
app:textSize="0sp"
|
||||||
|
android:visibility="invisible"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceBar
|
||||||
|
android:id="@+id/attendanceBar"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="20dp"
|
||||||
|
android:layout_marginHorizontal="8dp"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/percentageCircle"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/percentage"
|
||||||
|
android:visibility="invisible"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
|
android:id="@+id/previewContainer"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
app:flexWrap="wrap"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/percentageCircle"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/attendanceBar">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingBottom="8dp">
|
||||||
|
|
||||||
|
<pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:background="@drawable/bg_rounded_4dp"
|
||||||
|
tools:backgroundTint="#43a047"
|
||||||
|
tools:layout_marginEnd="5dp"
|
||||||
|
tools:layout_marginRight="5dp"
|
||||||
|
tools:paddingHorizontal="5dp"
|
||||||
|
tools:singleLine="true"
|
||||||
|
tools:text="w"
|
||||||
|
tools:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:layout_marginEnd="5dp"
|
||||||
|
tools:layout_marginRight="5dp"
|
||||||
|
tools:text="6,8%" />
|
||||||
|
</LinearLayout>
|
||||||
|
</com.google.android.flexbox.FlexboxLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginVertical="64dp"
|
||||||
|
tools:visibility="gone" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/noData"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:drawablePadding="16dp"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
android:text="@string/attendances_no_data"
|
||||||
|
android:textSize="24sp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:drawableTopCompat="@drawable/ic_no_grades"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:listitem="@layout/attendance_item_attendance"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
</LinearLayout>
|
||||||
</layout>
|
</layout>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user