From f116c4f1f49bacd0671a2df6477e8139c651095b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sun, 24 Nov 2019 21:09:49 +0100 Subject: [PATCH] [Home] Implement basic timetable card. --- .../pl/szczodrzynski/edziennik/Extensions.kt | 15 +++ .../data/db/modules/timetable/TimetableDao.kt | 7 ++ .../ui/modules/home/HomeFragmentV2.kt | 31 ++++++ .../modules/home/cards/HomeTimetableCard.kt | 100 ++++++++++++++++++ app/src/main/res/layout/card_home.xml | 5 +- .../res/layout/card_home_lucky_number.xml | 7 +- .../main/res/layout/card_home_timetable.xml | 21 ++++ 7 files changed, 179 insertions(+), 7 deletions(-) create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeTimetableCard.kt create mode 100644 app/src/main/res/layout/card_home_timetable.xml diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt index 8dfc5099..761f0dd6 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt @@ -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) +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/timetable/TimetableDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/timetable/TimetableDao.kt index 9170a20b..251e65c8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/timetable/TimetableDao.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/timetable/TimetableDao.kt @@ -75,6 +75,13 @@ interface TimetableDao { """) fun getBetweenDatesNow(dateFrom: Date, dateTo: Date) : List + @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> + @Query(""" $QUERY WHERE timetable.profileId = :profileId AND timetable.id = :lessonId diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragmentV2.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragmentV2.kt index e47108af..061dd7ef 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragmentV2.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragmentV2.kt @@ -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( HomeLuckyNumberCard(0, app, activity, this, app.profile), + HomeTimetableCard(0, app, activity, this, app.profile), HomeDummyCard(1), HomeDummyCard(2), HomeDummyCard(3), diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeTimetableCard.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeTimetableCard.kt new file mode 100644 index 00000000..4255f9da --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeTimetableCard.kt @@ -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() + private var lessons = listOf() + private var events = listOf() + + 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 +} \ No newline at end of file diff --git a/app/src/main/res/layout/card_home.xml b/app/src/main/res/layout/card_home.xml index 0db20325..60e58ec3 100644 --- a/app/src/main/res/layout/card_home.xml +++ b/app/src/main/res/layout/card_home.xml @@ -11,7 +11,4 @@ android:layout_marginRight="16dp" android:layout_marginBottom="8dp" android:clickable="true" - android:focusable="true"> - - - + android:focusable="true" /> diff --git a/app/src/main/res/layout/card_home_lucky_number.xml b/app/src/main/res/layout/card_home_lucky_number.xml index 8853ff68..40069c32 100644 --- a/app/src/main/res/layout/card_home_lucky_number.xml +++ b/app/src/main/res/layout/card_home_lucky_number.xml @@ -1,4 +1,5 @@ - @@ -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" /> diff --git a/app/src/main/res/layout/card_home_timetable.xml b/app/src/main/res/layout/card_home_timetable.xml new file mode 100644 index 00000000..7a9aad11 --- /dev/null +++ b/app/src/main/res/layout/card_home_timetable.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + \ No newline at end of file