From 6c6bc89f579746c9b017fb4a8319ecf4400beed3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Tue, 25 Aug 2020 19:14:11 +0200 Subject: [PATCH] [UI] Improve archive-related UI. Add archived info home card. --- .../pl/szczodrzynski/edziennik/Extensions.kt | 11 ++ .../szczodrzynski/edziennik/MainActivity.kt | 40 ++++++ .../data/api/edziennik/EdziennikTask.kt | 6 +- .../data/api/edziennik/ProfileArchiver.kt | 4 + .../edziennik/data/db/entity/Profile.kt | 3 + .../home/CardItemTouchHelperCallback.kt | 2 +- .../edziennik/ui/modules/home/HomeFragment.kt | 19 +-- .../ui/modules/home/cards/HomeArchiveCard.kt | 79 ++++++++++++ app/src/main/res/drawable/ic_archive.xml | 19 +++ app/src/main/res/layout/card_home_archive.xml | 56 +++++++++ .../main/res/layout/card_home_timetable.xml | 116 +++++++++--------- app/src/main/res/values/strings.xml | 11 ++ 12 files changed, 299 insertions(+), 67 deletions(-) create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeArchiveCard.kt create mode 100644 app/src/main/res/drawable/ic_archive.xml create mode 100644 app/src/main/res/layout/card_home_archive.xml diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt index 2443679b..7306109a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt @@ -42,6 +42,7 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.viewpager.widget.ViewPager import com.google.android.gms.security.ProviderInstaller import com.google.android.material.button.MaterialButton +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.gson.JsonArray import com.google.gson.JsonElement import com.google.gson.JsonObject @@ -672,6 +673,16 @@ fun TextView.setText(@StringRes resid: Int, vararg formatArgs: Any) { text = context.getString(resid, *formatArgs) } +fun MaterialAlertDialogBuilder.setTitle(@StringRes resid: Int, vararg formatArgs: Any): MaterialAlertDialogBuilder { + setTitle(context.getString(resid, *formatArgs)) + return this +} + +fun MaterialAlertDialogBuilder.setMessage(@StringRes resid: Int, vararg formatArgs: Any): MaterialAlertDialogBuilder { + setMessage(context.getString(resid, *formatArgs)) + return this +} + fun JsonObject(vararg properties: Pair): JsonObject { return JsonObject().apply { for (property in properties) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt index 272d8c0d..1ca1dd11 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt @@ -604,6 +604,46 @@ class MainActivity : AppCompatActivity(), CoroutineScope { __/ | |__*/ fun syncCurrentFeature() { + if (app.profile.archived) { + MaterialAlertDialogBuilder(this) + .setTitle(R.string.profile_archived_title) + .setMessage( + R.string.profile_archived_text, + app.profile.studentSchoolYearStart, + app.profile.studentSchoolYearStart + 1 + ) + .setPositiveButton(R.string.ok, null) + .show() + swipeRefreshLayout.isRefreshing = false + return + } + if (app.profile.isBeforeYear()) { + MaterialAlertDialogBuilder(this) + .setTitle(R.string.profile_year_not_started_title) + .setMessage( + R.string.profile_year_not_started_format, + app.profile.dateSemester1Start.formattedString + ) + .setPositiveButton(R.string.ok, null) + .show() + swipeRefreshLayout.isRefreshing = false + return + } + // vulcan hotfix + if (app.profile.dateYearEnd.month > 6) { + app.profile.dateYearEnd.month = 6 + app.profile.dateYearEnd.day = 30 + } + if (app.profile.shouldArchive()) { + MaterialAlertDialogBuilder(this) + .setTitle(R.string.profile_archiving_title) + .setMessage( + R.string.profile_archiving_format, + app.profile.dateYearEnd.formattedString + ) + .setPositiveButton(R.string.ok, null) + .show() + } swipeRefreshLayout.isRefreshing = true Toast.makeText(this, fragmentToSyncName(navTargetId), Toast.LENGTH_SHORT).show() val fragmentParam = when (navTargetId) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/EdziennikTask.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/EdziennikTask.kt index 90780d7b..66a04501 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/EdziennikTask.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/EdziennikTask.kt @@ -26,7 +26,6 @@ import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull import pl.szczodrzynski.edziennik.data.db.full.EventFull import pl.szczodrzynski.edziennik.data.db.full.MessageFull import pl.szczodrzynski.edziennik.utils.Utils.d -import pl.szczodrzynski.edziennik.utils.models.Date open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTask(profileId) { companion object { @@ -74,6 +73,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa internal fun run(app: App, taskCallback: EdziennikCallback) { profile?.let { profile -> + // vulcan hotfix if (profile.dateYearEnd.month > 6) { profile.dateYearEnd.month = 6 profile.dateYearEnd.day = 30 @@ -83,11 +83,11 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa taskCallback.onError(ApiError(TAG, ERROR_PROFILE_ARCHIVED)) return } - else if (Date.getToday() >= profile.dateYearEnd) { + else if (profile.shouldArchive()) { d(TAG, "The profile $profileId's year ended on ${profile.dateYearEnd}, archiving") ProfileArchiver(app, profile) } - if (Date.getToday() < profile.dateSemester1Start) { + if (profile.isBeforeYear()) { d(TAG, "The profile $profileId's school year has not started yet; aborting sync") cancel() taskCallback.onCompleted() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/ProfileArchiver.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/ProfileArchiver.kt index 7c8e9aa9..9e4039bf 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/ProfileArchiver.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/ProfileArchiver.kt @@ -1,3 +1,7 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2020-8-25. + */ + package pl.szczodrzynski.edziennik.data.api.edziennik import android.content.Intent diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Profile.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Profile.kt index f919f7c0..62e4be28 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Profile.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Profile.kt @@ -91,6 +91,9 @@ open class Profile( @delegate:Ignore val currentSemester by lazy { dateToSemester(Date.getToday()) } + fun shouldArchive() = Date.getToday() >= dateYearEnd && Date.getToday().year > studentSchoolYearStart + fun isBeforeYear() = Date.getToday() < dateSemester1Start + var disabledNotifications: List? = null var lastReceiversSync: Long = 0 diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/CardItemTouchHelperCallback.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/CardItemTouchHelperCallback.kt index 66908998..34621474 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/CardItemTouchHelperCallback.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/CardItemTouchHelperCallback.kt @@ -33,7 +33,7 @@ class CardItemTouchHelperCallback(private val cardAdapter: HomeCardAdapter, priv } override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { - removeCard(viewHolder.adapterPosition) + removeCard(viewHolder.adapterPosition, cardAdapter) cardAdapter.items.removeAt(viewHolder.adapterPosition) cardAdapter.notifyItemRemoved(viewHolder.adapterPosition) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt index 181dadc1..8d276a82 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragment.kt @@ -28,10 +28,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.LoginStore import pl.szczodrzynski.edziennik.databinding.FragmentHomeBinding import pl.szczodrzynski.edziennik.onClick import pl.szczodrzynski.edziennik.ui.dialogs.home.StudentNumberDialog -import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeEventsCard -import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeGradesCard -import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeLuckyNumberCard -import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeTimetableCard +import pl.szczodrzynski.edziennik.ui.modules.home.cards.* import pl.szczodrzynski.edziennik.utils.Themes import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem @@ -44,8 +41,8 @@ class HomeFragment : Fragment(), CoroutineScope { fun swapCards(fromPosition: Int, toPosition: Int, cardAdapter: HomeCardAdapter): Boolean { val fromCard = cardAdapter.items[fromPosition] val toCard = cardAdapter.items[toPosition] - if (fromCard.id == 100 || toCard.id == 100) { - // debug card is not swappable + if (fromCard.id >= 100 || toCard.id >= 100) { + // debug & archive cards are not swappable return false } cardAdapter.items[fromPosition] = cardAdapter.items[toPosition] @@ -60,10 +57,16 @@ class HomeFragment : Fragment(), CoroutineScope { return true } - fun removeCard(position: Int) { + fun removeCard(position: Int, cardAdapter: HomeCardAdapter) { val homeCards = App.config.forProfile().ui.homeCards.toMutableList() if (position >= homeCards.size) return + val card = cardAdapter.items[position] + if (card.id >= 100) { + // debug & archive cards are not removable + cardAdapter.notifyDataSetChanged() + return + } homeCards.removeAt(position) App.config.forProfile().ui.homeCards = homeCards } @@ -160,6 +163,8 @@ class HomeFragment : Fragment(), CoroutineScope { } //if (App.devMode) // items += HomeDebugCard(100, app, activity, this, app.profile) + if (app.profile.archived) + items.add(0, HomeArchiveCard(101, app, activity, this, app.profile)) val adapter = HomeCardAdapter(items) val itemTouchHelper = ItemTouchHelper(CardItemTouchHelperCallback(adapter, b.refreshLayout)) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeArchiveCard.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeArchiveCard.kt new file mode 100644 index 00000000..17fc89e4 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeArchiveCard.kt @@ -0,0 +1,79 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2020-8-25. + */ + +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 com.google.android.material.dialog.MaterialAlertDialogBuilder +import kotlinx.coroutines.* +import pl.szczodrzynski.edziennik.* +import pl.szczodrzynski.edziennik.data.db.entity.Profile +import pl.szczodrzynski.edziennik.databinding.CardHomeArchiveBinding +import pl.szczodrzynski.edziennik.ui.modules.home.HomeCard +import pl.szczodrzynski.edziennik.ui.modules.home.HomeCardAdapter +import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment +import kotlin.coroutines.CoroutineContext + +class HomeArchiveCard( + override val id: Int, + val app: App, + val activity: MainActivity, + val fragment: HomeFragment, + val profile: Profile +) : HomeCard, CoroutineScope { + companion object { + private const val TAG = "HomeArchiveCard" + } + + private var job: Job = Job() + override val coroutineContext: CoroutineContext + get() = job + Dispatchers.Main + + override fun bind(position: Int, holder: HomeCardAdapter.ViewHolder) { + holder.root.removeAllViews() + val b = CardHomeArchiveBinding.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 + + b.homeArchiveText.setText( + R.string.home_archive_text, + profile.studentSchoolYearStart, + profile.studentSchoolYearStart + 1 + ) + + b.homeArchiveClose.onClick { + launch { + val profile = profile.archiveId?.let { + withContext(Dispatchers.IO) { + app.db.profileDao().getNotArchivedOf(it) + } + } + if (profile == null) { + MaterialAlertDialogBuilder(activity) + .setTitle(R.string.home_archive_close_no_target_title) + .setMessage(R.string.home_archive_close_no_target_text, this@HomeArchiveCard.profile.name) + .setPositiveButton(R.string.ok) { _, _ -> + activity.drawer.profileSelectionOpen() + activity.drawer.open() + } + .show() + return@launch + } + activity.loadProfile(profile) + } + } + + holder.root.onClick { + activity.loadTarget(MainActivity.DRAWER_ITEM_AGENDA) + } + } + + override fun unbind(position: Int, holder: HomeCardAdapter.ViewHolder) = Unit +} diff --git a/app/src/main/res/drawable/ic_archive.xml b/app/src/main/res/drawable/ic_archive.xml new file mode 100644 index 00000000..a61f71cc --- /dev/null +++ b/app/src/main/res/drawable/ic_archive.xml @@ -0,0 +1,19 @@ + + + + + + + diff --git a/app/src/main/res/layout/card_home_archive.xml b/app/src/main/res/layout/card_home_archive.xml new file mode 100644 index 00000000..ffe979bc --- /dev/null +++ b/app/src/main/res/layout/card_home_archive.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/card_home_timetable.xml b/app/src/main/res/layout/card_home_timetable.xml index 5a1d8514..842e5b51 100644 --- a/app/src/main/res/layout/card_home_timetable.xml +++ b/app/src/main/res/layout/card_home_timetable.xml @@ -17,121 +17,130 @@ android:id="@+id/noTimetableLayout" android:layout_width="match_parent" android:layout_height="wrap_content" + android:gravity="center_vertical" android:orientation="horizontal" android:visibility="gone" tools:visibility="visible"> - - + android:text="@string/home_timetable_no_timetable" + android:textAppearance="@style/NavView.TextView.Title" /> - + android:layout_gravity="center_horizontal" + android:layout_margin="16dp" + android:fontFamily="sans-serif-light" + android:gravity="center_horizontal" + android:text="@string/home_timetable_no_timetable_text" + android:textSize="16sp" /> - + - - + android:text="@string/home_timetable_no_lessons" + android:textAppearance="@style/NavView.TextView.Title" /> - + android:layout_gravity="center_horizontal" + android:layout_margin="16dp" + android:fontFamily="sans-serif-light" + android:gravity="center_horizontal" + android:text="@string/home_timetable_no_lessons_text" + android:textSize="16sp" /> + - - + android:text="@string/home_timetable_not_public" + android:textAppearance="@style/NavView.TextView.Title" /> - + android:layout_gravity="center_horizontal" + android:layout_margin="16dp" + android:fontFamily="sans-serif-light" + android:gravity="center_horizontal" + android:text="@string/home_timetable_not_public_text" + android:textSize="16sp" /> + + tools:layout_marginTop="410dp"> - @@ -181,16 +189,16 @@ android:id="@+id/bellSync" android:layout_width="40dp" android:layout_height="40dp" - android:padding="10dp" android:background="?selectableItemBackgroundBorderless" + android:padding="10dp" tools:src="@sample/settings" /> @@ -234,10 +242,9 @@ android:layout_marginLeft="4dp" android:layout_marginRight="4dp" android:visibility="gone" - tools:visibility="visible" tools:max="2700" - tools:progress="780" /> - + tools:progress="780" + tools:visibility="visible" /> - - - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e06adfef..ad989424 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1356,4 +1356,15 @@ Zaloguj używając tokenu Podaj token aplikacji mobilnej. Logowanie do PPE… + Profil jest archiwalny + Przeglądasz dane ucznia z poprzedniego roku szkolnego (%d/%d). Synchronizacja oraz pobieranie wiadomości i niektórych zadań domowych zostały wyłączone.\n\nAby otworzyć profil ucznia z aktualnego roku, wybierz "Zamknij archiwum" na stronie głównej. + Wakacje ;) + Prawdopodobnie rok szkolny dla tego ucznia jeszcze się nie zaczął (zacznie się %s). Spróbuj wykonać synchronizację później. + Koniec roku szkolnego + Rok szkolny zakończył się %s. Dane ucznia z poprzedniego roku zostaną przeniesione do archiwum, aby można było je później przeglądać. + Profil archiwalny + Przeglądasz dane ucznia z roku szkolnego %d/%d. + Zamknij archiwum + Brak aktualnego profilu + Uczeń %s nie posiada profilu na tym koncie w aktualnym roku szkolnym. Prawdopodobnie ten profil został usunięty lub uczeń nie uczęszcza już do tej klasy.\n\nAby przejść do aktualnego profilu, wybierz ucznia z listy lub zaloguj się na jego konto przyciskiem Dodaj ucznia.