[Home] Implement basic timetable card.

This commit is contained in:
Kuba Szczodrzyński 2019-11-24 21:09:49 +01:00
parent 867c8920a8
commit f116c4f1f4
7 changed files with 179 additions and 7 deletions

View File

@ -35,6 +35,7 @@ import kotlinx.coroutines.launch
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
import pl.szczodrzynski.edziennik.utils.models.Time
import pl.szczodrzynski.navlib.R
import pl.szczodrzynski.navlib.getColorFromRes
import java.text.SimpleDateFormat
@ -518,3 +519,17 @@ fun CoroutineScope.startCoroutineTimer(delayMillis: Long = 0, repeatMillis: Long
action()
}
}
operator fun Time?.compareTo(other: Time?): Int {
if (this == null && other == null)
return 0
if (this == null)
return -1
if (other == null)
return 1
return this.compareTo(other)
}
operator fun StringBuilder.plusAssign(str: String?) {
this.append(str)
}

View File

@ -75,6 +75,13 @@ interface TimetableDao {
""")
fun getBetweenDatesNow(dateFrom: Date, dateTo: Date) : List<LessonFull>
@Query("""
$QUERY
WHERE (type != 3 AND date >= :dateFrom AND date <= :dateTo) OR ((type = 3 OR type = 1) AND oldDate >= :dateFrom AND oldDate <= :dateTo)
ORDER BY profileId, id, type
""")
fun getBetweenDates(dateFrom: Date, dateTo: Date) : LiveData<List<LessonFull>>
@Query("""
$QUERY
WHERE timetable.profileId = :profileId AND timetable.id = :lessonId

View File

@ -4,10 +4,13 @@
package pl.szczodrzynski.edziennik.ui.modules.home
import android.os.AsyncTask
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.View.OnClickListener
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.view.AccessibilityDelegateCompat
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat
@ -15,6 +18,8 @@ import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial.Icon
import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@ -22,8 +27,12 @@ import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.databinding.FragmentHomeV2Binding
import pl.szczodrzynski.edziennik.ui.dialogs.home.StudentNumberDialog
import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeLuckyNumberCard
import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeTimetableCard
import pl.szczodrzynski.edziennik.utils.Themes
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem
import kotlin.coroutines.CoroutineContext
class HomeFragmentV2 : Fragment(), CoroutineScope {
@ -62,8 +71,30 @@ class HomeFragmentV2 : Fragment(), CoroutineScope {
if (app.profile == null || !isAdded)
return
activity.bottomSheet.prependItems(
BottomSheetPrimaryItem(true)
.withTitle(R.string.menu_set_student_number)
.withIcon(SzkolnyFont.Icon.szf_clipboard_list_outline)
.withOnClickListener(OnClickListener {
activity.bottomSheet.close()
StudentNumberDialog(activity, app.profile) {
app.profileSaveAsync()
}
}),
BottomSheetSeparatorItem(true),
BottomSheetPrimaryItem(true)
.withTitle(R.string.menu_mark_everything_as_read)
.withIcon(Icon.cmd_eye_check_outline)
.withOnClickListener(OnClickListener {
activity.bottomSheet.close()
AsyncTask.execute { app.db.metadataDao().setAllSeen(App.profileId, true) }
Toast.makeText(activity, R.string.main_menu_mark_as_read_success, Toast.LENGTH_SHORT).show()
})
)
val items = mutableListOf<HomeCard>(
HomeLuckyNumberCard(0, app, activity, this, app.profile),
HomeTimetableCard(0, app, activity, this, app.profile),
HomeDummyCard(1),
HomeDummyCard(2),
HomeDummyCard(3),

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-11-24.
*/
package pl.szczodrzynski.edziennik.ui.modules.home.cards
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.core.view.plusAssign
import androidx.core.view.setMargins
import androidx.lifecycle.Observer
import kotlinx.coroutines.*
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
import pl.szczodrzynski.edziennik.data.db.modules.timetable.LessonFull
import pl.szczodrzynski.edziennik.databinding.CardHomeTimetableBinding
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCard
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCardAdapter
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragmentV2
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
import kotlin.coroutines.CoroutineContext
class HomeTimetableCard(
val id: Int,
val app: App,
val activity: MainActivity,
val fragment: HomeFragmentV2,
val profile: Profile
) : HomeCard, CoroutineScope {
companion object {
private const val TAG = "HomeTimetableCard"
}
private var job: Job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
private lateinit var b: CardHomeTimetableBinding
private val today = Date.getToday()
private val searchEnd = today.clone().stepForward(0, 0, 7)
private var allLessons = listOf<LessonFull>()
private var lessons = listOf<LessonFull>()
private var events = listOf<Event>()
override fun bind(position: Int, holder: HomeCardAdapter.ViewHolder) {
holder.root.removeAllViews()
b = CardHomeTimetableBinding.inflate(LayoutInflater.from(holder.root.context))
b.root.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
setMargins(8.dp)
}
holder.root += b.root
// get all lessons within the search bounds
app.db.timetableDao().getBetweenDates(today, searchEnd).observe(fragment, Observer {
allLessons = it
update()
})
}
private fun update() { launch {
val deferred = async(Dispatchers.Default) {
// get current bell-sync params
var bellSyncDiffMillis: Long = 0
if (app.appConfig.bellSyncDiff != null) {
bellSyncDiffMillis = (app.appConfig.bellSyncDiff.hour * 60 * 60 * 1000 + app.appConfig.bellSyncDiff.minute * 60 * 1000 + app.appConfig.bellSyncDiff.second * 1000).toLong()
bellSyncDiffMillis *= app.appConfig.bellSyncMultiplier.toLong()
bellSyncDiffMillis *= -1
}
// get the current bell-synced time
val now = Time.fromMillis(Time.getNow().inMillis + bellSyncDiffMillis)
// search for lessons to display
val timetableDate = Date.getToday()
var checkedDays = 0
lessons = allLessons.filter { it.profileId == profile.id && it.displayDate == timetableDate && it.displayEndTime > now && it.type != Lesson.TYPE_NO_LESSONS }
while ((lessons.isEmpty() || lessons.none {
it.displayDate != today || (it.displayDate == today && it.displayEndTime != null && it.displayEndTime!! >= now)
}) && checkedDays < 7) {
timetableDate.stepForward(0, 0, 1)
lessons = allLessons.filter { it.profileId == profile.id && it.displayDate == timetableDate && it.type != Lesson.TYPE_NO_LESSONS }
checkedDays++
}
}
deferred.await()
val text = StringBuilder()
for (lesson in lessons) {
text += lesson.displayStartTime?.stringHM+" "+lesson.displaySubjectName+"\n"
}
b.text.text = text.toString()
}}
override fun unbind(position: Int, holder: HomeCardAdapter.ViewHolder) = Unit
}

View File

@ -11,7 +11,4 @@
android:layout_marginRight="16dp"
android:layout_marginBottom="8dp"
android:clickable="true"
android:focusable="true">
<include layout="@layout/card_home_lucky_number" />
</com.google.android.material.card.MaterialCardView>
android:focusable="true" />

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!--
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) Kuba Szczodrzyński 2019-11-24.
-->
@ -30,8 +31,8 @@
android:layout_gravity="center"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:textAppearance="@style/NavView.TextView.Title"
android:text="@string/home_lucky_number_no_info" />
android:text="@string/home_lucky_number_no_info"
android:textAppearance="@style/NavView.TextView.Title" />
</LinearLayout>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) Kuba Szczodrzyński 2019-11-24.
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:layout_margin="8dp">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</layout>