[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.profiles.Profile
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team 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.R
import pl.szczodrzynski.navlib.getColorFromRes import pl.szczodrzynski.navlib.getColorFromRes
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
@ -518,3 +519,17 @@ fun CoroutineScope.startCoroutineTimer(delayMillis: Long = 0, repeatMillis: Long
action() 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> 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("""
$QUERY $QUERY
WHERE timetable.profileId = :profileId AND timetable.id = :lessonId WHERE timetable.profileId = :profileId AND timetable.id = :lessonId

View File

@ -4,10 +4,13 @@
package pl.szczodrzynski.edziennik.ui.modules.home package pl.szczodrzynski.edziennik.ui.modules.home
import android.os.AsyncTask
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.View.OnClickListener
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast
import androidx.core.view.AccessibilityDelegateCompat import androidx.core.view.AccessibilityDelegateCompat
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat 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.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate 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.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -22,8 +27,12 @@ import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.databinding.FragmentHomeV2Binding 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.HomeLuckyNumberCard
import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeTimetableCard
import pl.szczodrzynski.edziennik.utils.Themes import pl.szczodrzynski.edziennik.utils.Themes
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
class HomeFragmentV2 : Fragment(), CoroutineScope { class HomeFragmentV2 : Fragment(), CoroutineScope {
@ -62,8 +71,30 @@ class HomeFragmentV2 : Fragment(), CoroutineScope {
if (app.profile == null || !isAdded) if (app.profile == null || !isAdded)
return 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>( val items = mutableListOf<HomeCard>(
HomeLuckyNumberCard(0, app, activity, this, app.profile), HomeLuckyNumberCard(0, app, activity, this, app.profile),
HomeTimetableCard(0, app, activity, this, app.profile),
HomeDummyCard(1), HomeDummyCard(1),
HomeDummyCard(2), HomeDummyCard(2),
HomeDummyCard(3), 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_marginRight="16dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:clickable="true" android:clickable="true"
android:focusable="true"> android:focusable="true" />
<include layout="@layout/card_home_lucky_number" />
</com.google.android.material.card.MaterialCardView>

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. ~ Copyright (c) Kuba Szczodrzyński 2019-11-24.
--> -->
@ -30,8 +31,8 @@
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginLeft="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> </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>