From 8f612d3c31505eb7f4ef6cef2875ceacb0bccf7a Mon Sep 17 00:00:00 2001 From: denizk0461 Date: Sun, 4 Jun 2023 17:42:30 +0200 Subject: [PATCH] Added back buttons on all user-facing fragments that show when compact layout is used --- .../weserplaner/activity/MainActivity.kt | 67 +++++++++++++------ .../weserplaner/db/AppRepository.kt | 8 ++- .../weserplaner/fragment/CanteenFragment.kt | 15 +++++ .../fragment/CompactOverviewFragment.kt | 18 +++++ .../weserplaner/fragment/EventFragment.kt | 15 +++++ .../weserplaner/fragment/SettingsFragment.kt | 23 +++++++ .../weserplaner/values/AppLayout.kt | 13 ++++ .../weserplaner/values/SettingsPreferences.kt | 2 +- .../weserplaner/viewmodel/CanteenViewModel.kt | 7 ++ .../weserplaner/viewmodel/EventViewModel.kt | 7 ++ .../weserplaner/viewmodel/MainViewModel.kt | 7 ++ .../viewmodel/SettingsViewModel.kt | 10 ++- app/src/main/res/layout/fragment_canteen.xml | 22 +++++- .../res/layout/fragment_compact_overview.xml | 64 +++++++++++++++++- app/src/main/res/layout/fragment_event.xml | 22 +++++- app/src/main/res/layout/fragment_settings.xml | 48 ++++++++++--- .../main/res/navigation/nav_graph_compact.xml | 20 ++++-- ...aph_detailed.xml => nav_graph_default.xml} | 2 +- app/src/main/res/values-de/strings.xml | 3 + app/src/main/res/values/strings.xml | 3 + 20 files changed, 328 insertions(+), 48 deletions(-) create mode 100644 app/src/main/java/com/denizk0461/weserplaner/values/AppLayout.kt rename app/src/main/res/navigation/{nav_graph_detailed.xml => nav_graph_default.xml} (97%) diff --git a/app/src/main/java/com/denizk0461/weserplaner/activity/MainActivity.kt b/app/src/main/java/com/denizk0461/weserplaner/activity/MainActivity.kt index 7511812..e5eff5c 100644 --- a/app/src/main/java/com/denizk0461/weserplaner/activity/MainActivity.kt +++ b/app/src/main/java/com/denizk0461/weserplaner/activity/MainActivity.kt @@ -2,6 +2,7 @@ package com.denizk0461.weserplaner.activity import android.content.Intent import android.os.Bundle +import android.view.View import androidx.core.view.WindowCompat import androidx.fragment.app.FragmentActivity import androidx.lifecycle.ViewModelProvider @@ -10,6 +11,7 @@ import androidx.navigation.fragment.findNavController import androidx.navigation.ui.setupWithNavController import com.denizk0461.weserplaner.R import com.denizk0461.weserplaner.databinding.ActivityMainBinding +import com.denizk0461.weserplaner.values.AppLayout import com.denizk0461.weserplaner.viewmodel.MainViewModel /** @@ -51,33 +53,47 @@ class MainActivity : FragmentActivity() { startActivity(Intent(this, IntroductionActivity::class.java)) } - // Set up bottom navigation view to navigate between fragments - binding.navView.setupWithNavController( - binding.navHostFragmentContentMain.getFragment().findNavController() - ) + when (viewModel.preferenceAppLayout) { + AppLayout.DEFAULT -> { + // Ensure that the navigation bar is visible + binding.navView.visibility = View.VISIBLE - // Check whether the user has enabled beta screens - val showBetaScreens = viewModel.preferenceBetaScreensEnabled + // Set up bottom navigation view to navigate between fragments + binding.navView.setupWithNavController( + binding.navHostFragmentContentMain.getFragment().findNavController() + ) - // Set the visibility for the navigation bar items for beta screens accordingly - binding.navView.menu.findItem(R.id.exam_overview).isVisible = showBetaScreens - binding.navView.menu.findItem(R.id.room_finder).isVisible = showBetaScreens + // Check whether the user has enabled beta screens + val showBetaScreens = viewModel.preferenceBetaScreensEnabled - // Set up navigation component - setNavigationGraph() + // Set the visibility for the navigation bar items for beta screens accordingly + binding.navView.menu.findItem(R.id.exam_overview).isVisible = showBetaScreens + binding.navView.menu.findItem(R.id.room_finder).isVisible = showBetaScreens + + // Set up navigation graph for the default layout + (supportFragmentManager + .findFragmentById(R.id.nav_host_fragment_content_main) as NavHostFragment) + .setupDefaultNavigationGraph() + } + AppLayout.COMPACT -> { + // Hide the navigation bar, as it is unnecessary in the compact layout + binding.navView.visibility = View.GONE + + // Set up navigation graph for the compact layout + (supportFragmentManager + .findFragmentById(R.id.nav_host_fragment_content_main) as NavHostFragment) + .setupCompactNavigationGraph() + } + } } /** - * Sets the navigation graph for the fragments. Also sets the start destination. + * Sets the default navigation graph for the fragments. Also sets the start destination, as + * specified by the user. */ - private fun setNavigationGraph() { - // Get nav host - val navHostFragment = supportFragmentManager - .findFragmentById(R.id.nav_host_fragment_content_main) as NavHostFragment - + private fun NavHostFragment.setupDefaultNavigationGraph() { // Inflate new nav graph - val navGraph = navHostFragment - .navController.navInflater.inflate(R.navigation.nav_graph_detailed) + val navGraph = this.navController.navInflater.inflate(R.navigation.nav_graph_default) // Set the starting fragment for the app navGraph.setStartDestination(when (viewModel.preferenceLaunchFragment) { @@ -86,6 +102,17 @@ class MainActivity : FragmentActivity() { }) // Set the newly defined nav graph - navHostFragment.navController.graph = navGraph + this.navController.graph = navGraph + } + + /** + * Sets the compact navigation graph for the fragments. + */ + private fun NavHostFragment.setupCompactNavigationGraph() { + // Inflate new nav graph + val navGraph = this.navController.navInflater.inflate(R.navigation.nav_graph_compact) + + // Set the newly defined nav graph + this.navController.graph = navGraph } } \ No newline at end of file diff --git a/app/src/main/java/com/denizk0461/weserplaner/db/AppRepository.kt b/app/src/main/java/com/denizk0461/weserplaner/db/AppRepository.kt index 0aee72e..d72281a 100644 --- a/app/src/main/java/com/denizk0461/weserplaner/db/AppRepository.kt +++ b/app/src/main/java/com/denizk0461/weserplaner/db/AppRepository.kt @@ -9,6 +9,7 @@ import com.denizk0461.weserplaner.values.SettingsPreferences import com.denizk0461.weserplaner.values.TaskOrder import com.denizk0461.weserplaner.model.* import com.denizk0461.weserplaner.values.AllergenPreferences +import com.denizk0461.weserplaner.values.AppLayout /** * Repository objects that acts as a mediator between view models and the database to retrieve data @@ -396,12 +397,15 @@ class AppRepository(app: Application) { /** * This value determines which navigation graph will be used for app navigation. */ - fun getAppLayout(): Int = getIntPreference( + fun getAppLayout(): AppLayout = AppLayout.values()[getIntPreference( SettingsPreferences.APP_LAYOUT, - ) + )] fun setAppLayout(newValue: Int) { setPreference(SettingsPreferences.APP_LAYOUT, newValue) } + fun setAppLayout(newValue: AppLayout) { + setPreference(SettingsPreferences.APP_LAYOUT, newValue.ordinal) + } /** * This value determines whether the user opts into submitting crash reports. diff --git a/app/src/main/java/com/denizk0461/weserplaner/fragment/CanteenFragment.kt b/app/src/main/java/com/denizk0461/weserplaner/fragment/CanteenFragment.kt index 13a8904..0588ea9 100644 --- a/app/src/main/java/com/denizk0461/weserplaner/fragment/CanteenFragment.kt +++ b/app/src/main/java/com/denizk0461/weserplaner/fragment/CanteenFragment.kt @@ -8,6 +8,7 @@ import android.view.ViewGroup import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.widget.PopupMenu import androidx.fragment.app.viewModels +import androidx.navigation.fragment.findNavController import androidx.viewpager2.widget.ViewPager2 import com.denizk0461.weserplaner.R import com.denizk0461.weserplaner.adapter.CanteenOfferPageAdapter @@ -19,6 +20,7 @@ import com.denizk0461.weserplaner.data.showSnackBar import com.denizk0461.weserplaner.databinding.FragmentCanteenBinding import com.denizk0461.weserplaner.values.DietaryPreferences import com.denizk0461.weserplaner.model.* +import com.denizk0461.weserplaner.values.AppLayout import com.denizk0461.weserplaner.values.TextSheetContentId import com.denizk0461.weserplaner.viewmodel.CanteenViewModel import com.google.android.material.tabs.TabLayoutMediator @@ -50,6 +52,19 @@ class CanteenFragment : AppFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + // Set up back button, if required by the selected layout + when (viewModel.preferenceAppLayout) { + AppLayout.DEFAULT -> { + binding.buttonNavigateBack.visibility = View.GONE + } + AppLayout.COMPACT -> { + binding.buttonNavigateBack.visibility = View.VISIBLE + binding.buttonNavigateBack.setOnClickListener { + findNavController().navigate(R.id.action_canteen_to_compact_overview) + } + } + } + // Set progress circle colours binding.swipeRefreshLayout.setRainbowProgressCircle() diff --git a/app/src/main/java/com/denizk0461/weserplaner/fragment/CompactOverviewFragment.kt b/app/src/main/java/com/denizk0461/weserplaner/fragment/CompactOverviewFragment.kt index fad453f..a191210 100644 --- a/app/src/main/java/com/denizk0461/weserplaner/fragment/CompactOverviewFragment.kt +++ b/app/src/main/java/com/denizk0461/weserplaner/fragment/CompactOverviewFragment.kt @@ -1,8 +1,26 @@ package com.denizk0461.weserplaner.fragment +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.navigation.fragment.findNavController +import com.denizk0461.weserplaner.R import com.denizk0461.weserplaner.databinding.FragmentCompactOverviewBinding class CompactOverviewFragment : AppFragment() { + // Instantiate the view binding + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + _binding = FragmentCompactOverviewBinding.inflate(inflater, container, false) + return binding.root + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.buttonSettings.setOnClickListener { + findNavController().navigate(R.id.action_compact_overview_to_settings) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/denizk0461/weserplaner/fragment/EventFragment.kt b/app/src/main/java/com/denizk0461/weserplaner/fragment/EventFragment.kt index c9d3b8f..aa03b63 100644 --- a/app/src/main/java/com/denizk0461/weserplaner/fragment/EventFragment.kt +++ b/app/src/main/java/com/denizk0461/weserplaner/fragment/EventFragment.kt @@ -6,6 +6,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.viewModels +import androidx.navigation.fragment.findNavController import androidx.viewpager2.widget.ViewPager2 import com.denizk0461.weserplaner.R import com.denizk0461.weserplaner.activity.FetcherActivity @@ -14,6 +15,7 @@ import com.denizk0461.weserplaner.adapter.StudIPEventPageAdapter import com.denizk0461.weserplaner.data.showSnackBar import com.denizk0461.weserplaner.databinding.FragmentEventBinding import com.denizk0461.weserplaner.sheet.ScheduleUpdateSheet +import com.denizk0461.weserplaner.values.AppLayout import com.denizk0461.weserplaner.viewmodel.EventViewModel import com.google.android.material.tabs.TabLayoutMediator import java.util.* @@ -41,6 +43,19 @@ class EventFragment : AppFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + // Set up back button, if required by the selected layout + when (viewModel.preferenceAppLayout) { + AppLayout.DEFAULT -> { + binding.buttonNavigateBack.visibility = View.GONE + } + AppLayout.COMPACT -> { + binding.buttonNavigateBack.visibility = View.VISIBLE + binding.buttonNavigateBack.setOnClickListener { + findNavController().navigate(R.id.action_schedule_to_compact_overview) + } + } + } + // Get localised weekday names weekdays = context.resources?.getStringArray(R.array.weekdays) ?: arrayOf() diff --git a/app/src/main/java/com/denizk0461/weserplaner/fragment/SettingsFragment.kt b/app/src/main/java/com/denizk0461/weserplaner/fragment/SettingsFragment.kt index 5568b8c..1f23ab5 100644 --- a/app/src/main/java/com/denizk0461/weserplaner/fragment/SettingsFragment.kt +++ b/app/src/main/java/com/denizk0461/weserplaner/fragment/SettingsFragment.kt @@ -13,6 +13,7 @@ import android.view.ViewGroup import android.view.inputmethod.InputMethodManager import androidx.fragment.app.setFragmentResultListener import androidx.fragment.app.viewModels +import androidx.navigation.fragment.findNavController import com.denizk0461.weserplaner.BuildConfig import com.denizk0461.weserplaner.R import com.denizk0461.weserplaner.activity.FetcherActivity @@ -23,6 +24,7 @@ import com.denizk0461.weserplaner.data.showToast import com.denizk0461.weserplaner.databinding.FragmentSettingsBinding import com.denizk0461.weserplaner.model.FormattedDate import com.denizk0461.weserplaner.sheet.AllergenConfigSheet +import com.denizk0461.weserplaner.values.AppLayout import com.denizk0461.weserplaner.viewmodel.SettingsViewModel import java.nio.charset.StandardCharsets import java.util.* @@ -56,6 +58,19 @@ class SettingsFragment : AppFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + // Set up back button, if required by the selected layout + when (viewModel.preferenceAppLayout) { + AppLayout.DEFAULT -> { + binding.buttonNavigateBack.visibility = View.GONE + } + AppLayout.COMPACT -> { + binding.buttonNavigateBack.visibility = View.VISIBLE + binding.buttonNavigateBack.setOnClickListener { + findNavController().navigate(R.id.action_settings_to_compact_overview) + } + } + } + // --- schedule settings --- // // Launch the Stud.IP schedule fetcher activity @@ -419,6 +434,14 @@ class SettingsFragment : AppFragment() { viewModel.preferenceFirstLaunch = true showToast(context, "First launch flag cleared") } + "LAYDEF" -> { + viewModel.preferenceAppLayout = AppLayout.DEFAULT + showToast(context, "App will use default layout") + } + "LAYCOM" -> { + viewModel.preferenceAppLayout = AppLayout.COMPACT + showToast(context, "App will use compact layout") + } else -> showSnackBar( getString(R.string.settings_dev_codes_invalid) ) diff --git a/app/src/main/java/com/denizk0461/weserplaner/values/AppLayout.kt b/app/src/main/java/com/denizk0461/weserplaner/values/AppLayout.kt new file mode 100644 index 0000000..934433a --- /dev/null +++ b/app/src/main/java/com/denizk0461/weserplaner/values/AppLayout.kt @@ -0,0 +1,13 @@ +package com.denizk0461.weserplaner.values + +/** + * This enum class represents the different layouts the app has to offer. + */ +enum class AppLayout { + // Default app layout. + DEFAULT, + + // More compact app layout that attempts to prioritise relevant information. + COMPACT, + ; +} \ No newline at end of file diff --git a/app/src/main/java/com/denizk0461/weserplaner/values/SettingsPreferences.kt b/app/src/main/java/com/denizk0461/weserplaner/values/SettingsPreferences.kt index 7c90cf9..2b89d59 100644 --- a/app/src/main/java/com/denizk0461/weserplaner/values/SettingsPreferences.kt +++ b/app/src/main/java/com/denizk0461/weserplaner/values/SettingsPreferences.kt @@ -75,7 +75,7 @@ enum class SettingsPreferences(val key: String) { BETA_SCREENS_ENABLED("beta_screens"), /** - * The user's app layout preference. + * The user's app layout preference. Also see [com.denizk0461.weserplaner.values.AppLayout]. */ APP_LAYOUT("app_layout"), ; diff --git a/app/src/main/java/com/denizk0461/weserplaner/viewmodel/CanteenViewModel.kt b/app/src/main/java/com/denizk0461/weserplaner/viewmodel/CanteenViewModel.kt index abb87bb..6557d67 100644 --- a/app/src/main/java/com/denizk0461/weserplaner/viewmodel/CanteenViewModel.kt +++ b/app/src/main/java/com/denizk0461/weserplaner/viewmodel/CanteenViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.viewModelScope import com.denizk0461.weserplaner.data.StwParser import com.denizk0461.weserplaner.values.DietaryPreferences import com.denizk0461.weserplaner.model.* +import com.denizk0461.weserplaner.values.AppLayout import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -88,4 +89,10 @@ class CanteenViewModel(app: Application) : AppViewModel(app) { var preferenceHasOpenedCanteen: Boolean get() = repo.getPreferenceHasOpenedCanteen() set(newValue) { repo.setPreferenceHasOpenedCanteen(newValue) } + + /** + * Determines which layout the user wants the app to use. + */ + val preferenceAppLayout: AppLayout + get() = repo.getAppLayout() } \ No newline at end of file diff --git a/app/src/main/java/com/denizk0461/weserplaner/viewmodel/EventViewModel.kt b/app/src/main/java/com/denizk0461/weserplaner/viewmodel/EventViewModel.kt index 3dcdf8a..153f53e 100644 --- a/app/src/main/java/com/denizk0461/weserplaner/viewmodel/EventViewModel.kt +++ b/app/src/main/java/com/denizk0461/weserplaner/viewmodel/EventViewModel.kt @@ -2,6 +2,7 @@ package com.denizk0461.weserplaner.viewmodel import android.app.Application import androidx.lifecycle.LiveData +import com.denizk0461.weserplaner.values.AppLayout /** * View model for [com.denizk0461.weserplaner.fragment.EventFragment] @@ -22,4 +23,10 @@ class EventViewModel(app: Application) : AppViewModel(app) { */ val preferenceCurrentDay: Boolean get() = repo.getPreferenceCurrentDay() + + /** + * Determines which layout the user wants the app to use. + */ + val preferenceAppLayout: AppLayout + get() = repo.getAppLayout() } \ No newline at end of file diff --git a/app/src/main/java/com/denizk0461/weserplaner/viewmodel/MainViewModel.kt b/app/src/main/java/com/denizk0461/weserplaner/viewmodel/MainViewModel.kt index 98de732..bc9d165 100644 --- a/app/src/main/java/com/denizk0461/weserplaner/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/denizk0461/weserplaner/viewmodel/MainViewModel.kt @@ -1,6 +1,7 @@ package com.denizk0461.weserplaner.viewmodel import android.app.Application +import com.denizk0461.weserplaner.values.AppLayout /** * View model for [com.denizk0461.weserplaner.activity.MainActivity] @@ -27,4 +28,10 @@ class MainViewModel(application: Application) : AppViewModel(application) { */ val preferenceFirstLaunch: Boolean get() = repo.getPreferenceFirstLaunch() + + /** + * Determines which layout the user wants the app to use. + */ + val preferenceAppLayout: AppLayout + get() = repo.getAppLayout() } \ No newline at end of file diff --git a/app/src/main/java/com/denizk0461/weserplaner/viewmodel/SettingsViewModel.kt b/app/src/main/java/com/denizk0461/weserplaner/viewmodel/SettingsViewModel.kt index 5f57546..d162161 100644 --- a/app/src/main/java/com/denizk0461/weserplaner/viewmodel/SettingsViewModel.kt +++ b/app/src/main/java/com/denizk0461/weserplaner/viewmodel/SettingsViewModel.kt @@ -1,6 +1,7 @@ package com.denizk0461.weserplaner.viewmodel import android.app.Application +import com.denizk0461.weserplaner.values.AppLayout /** * View model for [com.denizk0461.weserplaner.fragment.SettingsFragment] @@ -86,7 +87,14 @@ class SettingsViewModel(app: Application) : AppViewModel(app) { */ var preferenceFirstLaunch: Boolean get() = repo.getPreferenceFirstLaunch() - set(value) { repo.setPreferenceFirstLaunch(value) } + set(newValue) { repo.setPreferenceFirstLaunch(newValue) } + + /** + * Determines which layout the user wants the app to use. + */ + var preferenceAppLayout: AppLayout + get() = repo.getAppLayout() + set(newValue) { repo.setAppLayout(newValue) } // --- functions for dev codes --- // diff --git a/app/src/main/res/layout/fragment_canteen.xml b/app/src/main/res/layout/fragment_canteen.xml index 64b3693..0e43c59 100644 --- a/app/src/main/res/layout/fragment_canteen.xml +++ b/app/src/main/res/layout/fragment_canteen.xml @@ -21,8 +21,23 @@ + android:layout_marginHorizontal="8dp"> + + - + android:layout_height="match_parent" + tools:context=".fragment.EventFragment"> - \ No newline at end of file + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_event.xml b/app/src/main/res/layout/fragment_event.xml index a49b119..d2e48e0 100644 --- a/app/src/main/res/layout/fragment_event.xml +++ b/app/src/main/res/layout/fragment_event.xml @@ -16,10 +16,25 @@ + + - + android:layout_marginHorizontal="8dp" + app:layout_scrollFlags="scroll"> + + + + + + diff --git a/app/src/main/res/navigation/nav_graph_compact.xml b/app/src/main/res/navigation/nav_graph_compact.xml index 62a6960..6f02495 100644 --- a/app/src/main/res/navigation/nav_graph_compact.xml +++ b/app/src/main/res/navigation/nav_graph_compact.xml @@ -3,7 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/nav_graph_compact" - app:startDestination="@id/schedule"> + app:startDestination="@id/compact_overview"> + tools:layout="@layout/fragment_event"> + + + tools:layout="@layout/fragment_canteen"> + + + tools:layout="@layout/fragment_settings"> + + \ No newline at end of file diff --git a/app/src/main/res/navigation/nav_graph_detailed.xml b/app/src/main/res/navigation/nav_graph_default.xml similarity index 97% rename from app/src/main/res/navigation/nav_graph_detailed.xml rename to app/src/main/res/navigation/nav_graph_default.xml index 0e5f742..719cb41 100644 --- a/app/src/main/res/navigation/nav_graph_detailed.xml +++ b/app/src/main/res/navigation/nav_graph_default.xml @@ -2,7 +2,7 @@ – oder – Gehe direkt zur App + App-Einstellungen + Zurück zur Übersicht + Ein Fehler ist aufgetreten! Du musst deinen Stundenplan öffnen! Du musst dich zuerst einloggen! diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5ecad6b..b50b1e8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -31,6 +31,9 @@ – or – Continue to the app + App settings + Back to overview + Something went wrong! You must navigate to your schedule! You must log in first!