[UI] Add showing unseen events. Add Lab fragment.

This commit is contained in:
Kuba Szczodrzyński 2020-04-03 20:58:51 +02:00
parent fcb627aac6
commit c0aeb0d2f3
15 changed files with 206 additions and 15 deletions

View File

@ -43,10 +43,7 @@ import pl.szczodrzynski.edziennik.sync.SyncWorker
import pl.szczodrzynski.edziennik.sync.UpdateWorker
import pl.szczodrzynski.edziennik.ui.modules.base.CrashActivity
import pl.szczodrzynski.edziennik.utils.*
import pl.szczodrzynski.edziennik.utils.managers.GradesManager
import pl.szczodrzynski.edziennik.utils.managers.NotificationChannelsManager
import pl.szczodrzynski.edziennik.utils.managers.TimetableManager
import pl.szczodrzynski.edziennik.utils.managers.UserActionManager
import pl.szczodrzynski.edziennik.utils.managers.*
import java.util.concurrent.TimeUnit
import kotlin.coroutines.CoroutineContext
@ -67,6 +64,7 @@ class App : MultiDexApplication(), Configuration.Provider, CoroutineScope {
val userActionManager by lazy { UserActionManager(this) }
val gradesManager by lazy { GradesManager(this) }
val timetableManager by lazy { TimetableManager(this) }
val eventManager by lazy { EventManager(this) }
val db
get() = App.db

View File

@ -55,9 +55,10 @@ import pl.szczodrzynski.edziennik.ui.dialogs.sync.SyncViewListDialog
import pl.szczodrzynski.edziennik.ui.modules.agenda.AgendaFragment
import pl.szczodrzynski.edziennik.ui.modules.announcements.AnnouncementsFragment
import pl.szczodrzynski.edziennik.ui.modules.attendance.AttendanceFragment
import pl.szczodrzynski.edziennik.ui.modules.base.DebugFragment
import pl.szczodrzynski.edziennik.ui.modules.base.MainSnackbar
import pl.szczodrzynski.edziennik.ui.modules.behaviour.BehaviourFragment
import pl.szczodrzynski.edziennik.ui.modules.debug.DebugFragment
import pl.szczodrzynski.edziennik.ui.modules.debug.LabFragment
import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar
import pl.szczodrzynski.edziennik.ui.modules.feedback.FeedbackFragment
import pl.szczodrzynski.edziennik.ui.modules.feedback.HelpFragment
@ -73,7 +74,6 @@ import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesListFragment
import pl.szczodrzynski.edziennik.ui.modules.notifications.NotificationsListFragment
import pl.szczodrzynski.edziennik.ui.modules.settings.ProfileManagerFragment
import pl.szczodrzynski.edziennik.ui.modules.settings.SettingsNewFragment
import pl.szczodrzynski.edziennik.ui.modules.template.TemplateFragment
import pl.szczodrzynski.edziennik.ui.modules.timetable.TimetableFragment
import pl.szczodrzynski.edziennik.ui.modules.webpush.WebPushFragment
import pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoTouch
@ -130,7 +130,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
const val TARGET_MESSAGES_DETAILS = 503
const val TARGET_MESSAGES_COMPOSE = 504
const val TARGET_WEB_PUSH = 140
const val TARGET_TEMPLATE = 1000
const val TARGET_LAB = 1000
const val HOME_ID = DRAWER_ITEM_HOME
@ -230,8 +230,8 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
list += NavTarget(TARGET_WEB_PUSH, R.string.menu_web_push, WebPushFragment::class)
list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class)
if (App.devMode) {
list += NavTarget(TARGET_TEMPLATE, R.string.menu_template, TemplateFragment::class)
.withIcon(CommunityMaterial.Icon2.cmd_test_tube_empty)
list += NavTarget(TARGET_LAB, R.string.menu_lab, LabFragment::class)
.withIcon(CommunityMaterial.Icon.cmd_flask_outline)
.isInDrawer(true)
.isBelowSeparator(true)
.isStatic(true)

View File

@ -93,7 +93,7 @@ open class Event(
var attachmentNames: MutableList<String>? = null
@Ignore
var showAsUnseen = false
var showAsUnseen: Boolean? = null
val startTimeCalendar: Calendar
get() = Calendar.getInstance().also { it.set(

View File

@ -151,6 +151,7 @@ class DayDialog(
showType = true,
showTime = true,
showSubject = true,
markAsSeen = true,
onItemClick = {
EventDetailsDialog(
activity,

View File

@ -9,11 +9,15 @@ import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.databinding.EventListItemBinding
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Week
import kotlin.coroutines.CoroutineContext
class EventListAdapter(
val context: Context,
@ -23,11 +27,17 @@ class EventListAdapter(
val showType: Boolean = true,
val showTime: Boolean = true,
val showSubject: Boolean = true,
val markAsSeen: Boolean = true,
val onItemClick: ((event: EventFull) -> Unit)? = null,
val onEventEditClick: ((event: EventFull) -> Unit)? = null
) : RecyclerView.Adapter<EventListAdapter.ViewHolder>() {
) : RecyclerView.Adapter<EventListAdapter.ViewHolder>(), CoroutineScope {
private val app by lazy { context.applicationContext as App }
private val app = context.applicationContext as App
private val manager = app.eventManager
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
var items = listOf<EventFull>()
@ -40,9 +50,17 @@ class EventListAdapter(
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val event = items[position]
val b = holder.b
val manager = app.eventManager
b.root.onClick {
onItemClick?.invoke(event)
if (!event.seen) {
manager.markAsSeen(event)
}
if (event.showAsUnseen == true) {
event.showAsUnseen = false
notifyItemChanged(event)
}
}
val bullet = ""
@ -85,6 +103,22 @@ class EventListAdapter(
b.editButton.attachToastHint(R.string.hint_edit_event)
b.isDone.isVisible = event.isDone
if (event.showAsUnseen == null)
event.showAsUnseen = !event.seen
b.unread.isVisible = event.showAsUnseen == true
if (markAsSeen && !event.seen) {
manager.markAsSeen(event)
}
}
private fun notifyItemChanged(model: Any) {
startCoroutineTimer(1000L, 0L) {
val index = items.indexOf(model)
if (index != -1)
notifyItemChanged(index)
}
}
override fun getItemCount() = items.size

View File

@ -175,6 +175,7 @@ class LessonDetailsDialog(
showType = true,
showTime = true,
showSubject = true,
markAsSeen = true,
onItemClick = {
EventDetailsDialog(
activity,

View File

@ -1,4 +1,8 @@
package pl.szczodrzynski.edziennik.ui.modules.base;
/*
* Copyright (c) Kuba Szczodrzyński 2020-4-3.
*/
package pl.szczodrzynski.edziennik.ui.modules.debug;
import android.os.Bundle;
import android.util.Log;

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-4-3.
*/
package pl.szczodrzynski.edziennik.ui.modules.debug
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.data.db.entity.Event
import pl.szczodrzynski.edziennik.databinding.LabFragmentBinding
import pl.szczodrzynski.edziennik.onClick
import kotlin.coroutines.CoroutineContext
class LabFragment : Fragment(), CoroutineScope {
companion object {
private const val TAG = "LabFragment"
}
private lateinit var app: App
private lateinit var activity: MainActivity
private lateinit var b: LabFragmentBinding
private val job: Job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
// local/private variables go here
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 = LabFragmentBinding.inflate(inflater)
return b.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
if (!isAdded) return
b.last10unseen.onClick {
launch(Dispatchers.Default) {
val events = app.db.eventDao().getAllNow(App.profileId)
val ids = events.sortedBy { it.date }.filter { it.type == Event.TYPE_HOMEWORK }.takeLast(10)
ids.forEach {
app.db.metadataDao().setSeen(App.profileId, it, false)
}
}
}
}
}

View File

@ -65,6 +65,7 @@ class HomeEventsCard(
showType = true,
showTime = false,
showSubject = false,
markAsSeen = false,
onItemClick = {
EventDetailsDialog(
activity,

View File

@ -60,6 +60,7 @@ class HomeworkListFragment : LazyFragment(), CoroutineScope {
showType = false,
showTime = true,
showSubject = true,
markAsSeen = true,
onItemClick = {
EventDetailsDialog(
activity,

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-4-3.
*/
package pl.szczodrzynski.edziennik.utils.managers
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.startCoroutineTimer
import kotlin.coroutines.CoroutineContext
class EventManager(val app: App) : CoroutineScope {
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Default
/* _ _ _____ _____ _ __ _
| | | |_ _| / ____| (_)/ _(_)
| | | | | | | (___ _ __ ___ ___ _| |_ _ ___
| | | | | | \___ \| '_ \ / _ \/ __| | _| |/ __|
| |__| |_| |_ ____) | |_) | __/ (__| | | | | (__
\____/|_____| |_____/| .__/ \___|\___|_|_| |_|\___|
| |
|*/
fun markAsSeen(event: EventFull) {
event.seen = true
startCoroutineTimer(500L, 0L) {
app.db.metadataDao().setSeen(event.profileId, event, true)
}
}
}

View File

@ -36,13 +36,23 @@
<TextView
android:id="@+id/details"
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textAppearance="@style/NavView.TextView.Helper"
android:textSize="16sp"
android:maxLines="2"
tools:text="sprawdzian • 9:05 • historia i społeczeństwo" />
<View
android:id="@+id/unread"
android:layout_width="12dp"
android:layout_height="12dp"
android:layout_marginHorizontal="4dp"
android:visibility="gone"
android:background="@drawable/unread_red_circle"
tools:visibility="visible"/>
</LinearLayout>
<LinearLayout
@ -81,6 +91,7 @@
android:layout_gravity="top"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:visibility="gone"
app:iiv_color="@color/md_green_500"
app:iiv_icon="cmd-check"
tools:background="@sample/check" />

View File

@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.modules.base.DebugFragment">
tools:context=".ui.modules.debug.DebugFragment">
<!-- TODO: Update blank fragment layout -->
<com.google.android.material.textfield.TextInputLayout

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) Kuba Szczodrzyński 2020-4-3.
-->
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
tools:ignore="HardcodedText">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="8dp"
android:layout_marginVertical="8dp"
android:orientation="vertical">
<!--<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorSurface_6dp"
app:tabIndicatorColor="?colorPrimary"
app:tabMode="auto"
app:tabSelectedTextColor="?colorPrimary"
app:tabTextColor="?android:textColorPrimary" />-->
<!--<pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />-->
<Button
android:id="@+id/last10unseen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Set last 10 as unseen"
android:textAllCaps="false" />
</LinearLayout>
</ScrollView>
</layout>

View File

@ -1286,4 +1286,5 @@
<string name="dialog_event_details_body">Treść</string>
<string name="dialog_event_details_attachments">Załączniki</string>
<string name="hint_download_again">Pobierz ponownie</string>
<string name="menu_lab">Laboratorium</string>
</resources>