From e17a81e604750952e0f443b82ac1dbaf8432788d Mon Sep 17 00:00:00 2001 From: denizk0461 Date: Thu, 4 May 2023 15:09:10 +0200 Subject: [PATCH] CanteenFragment.kt: replaced buttons for opening hours and canteen switch embedded in the app bar with floating action buttons; implemented a possible fix for the app crashing after refreshing the canteen plan. This may have been caused by accessing the view/context of the fragment to let the user know that the refresh succeeded or encountered an error. Reference will be null by the time the fragment is inactive, causing a NullPointerException --- .../studip/adapter/StudIPEventItemAdapter.kt | 1 - .../com/denizk0461/studip/data/StwParser.kt | 10 +- .../studip/fragment/CanteenFragment.kt | 130 ++++++++++-------- .../studip/model/AllergenPreferences.kt | 13 +- app/src/main/res/drawable/arrow_down.xml | 5 + app/src/main/res/drawable/clock.xml | 6 + app/src/main/res/drawable/switch_arrows.xml | 6 + app/src/main/res/layout/fragment_canteen.xml | 96 +++++++------ app/src/main/res/layout/fragment_event.xml | 2 +- app/src/main/res/layout/fragment_settings.xml | 2 +- app/src/main/res/values-de/strings.xml | 3 + app/src/main/res/values-night/themes.xml | 15 -- app/src/main/res/values/strings.xml | 3 + app/src/main/res/values/themes.xml | 15 -- 14 files changed, 165 insertions(+), 142 deletions(-) create mode 100644 app/src/main/res/drawable/arrow_down.xml create mode 100644 app/src/main/res/drawable/clock.xml create mode 100644 app/src/main/res/drawable/switch_arrows.xml diff --git a/app/src/main/java/com/denizk0461/studip/adapter/StudIPEventItemAdapter.kt b/app/src/main/java/com/denizk0461/studip/adapter/StudIPEventItemAdapter.kt index 7247e80..7101ed0 100644 --- a/app/src/main/java/com/denizk0461/studip/adapter/StudIPEventItemAdapter.kt +++ b/app/src/main/java/com/denizk0461/studip/adapter/StudIPEventItemAdapter.kt @@ -35,7 +35,6 @@ class StudIPEventItemAdapter( /** * Retrieve an instance of Calendar to check whether the adapter's day matches the current day. - * TODO this can be optimised by checking in EventPageFragment.kt and delivering a boolean */ private val currentCalendar = Calendar.getInstance() diff --git a/app/src/main/java/com/denizk0461/studip/data/StwParser.kt b/app/src/main/java/com/denizk0461/studip/data/StwParser.kt index 1c3a8b4..99fb963 100644 --- a/app/src/main/java/com/denizk0461/studip/data/StwParser.kt +++ b/app/src/main/java/com/denizk0461/studip/data/StwParser.kt @@ -128,10 +128,7 @@ class StwParser(application: Application) { // Parse the HTML using Jsoup to traverse the document val doc = Jsoup.connect(url).get() - /* - * Retrieve the opening hours for the canteen. - * TODO this formatting sucks and also this doesn't work - */ + // Retrieve the opening hours for the canteen var openingHours = "" // Iterate through all wrappers that could contain opening hours @@ -139,10 +136,7 @@ class StwParser(application: Application) { // Element is not for providing contact details if (it.getElementsByClass("contact-person-name").size == 0) { - /* - * Retrieve all opening hours. - * TODO this slows down the fetch SIGNIFICANTLY, but why? - */ + // Retrieve all opening hours. it.children().forEach { element -> if (element.tag().toString() == "p") { openingHours += element.textWithBreaks().trim() + "\n" // Uni-Mensa is not parsed properly diff --git a/app/src/main/java/com/denizk0461/studip/fragment/CanteenFragment.kt b/app/src/main/java/com/denizk0461/studip/fragment/CanteenFragment.kt index 209f22b..52264a6 100644 --- a/app/src/main/java/com/denizk0461/studip/fragment/CanteenFragment.kt +++ b/app/src/main/java/com/denizk0461/studip/fragment/CanteenFragment.kt @@ -53,53 +53,18 @@ class CanteenFragment : AppFragment() { // Set progress circle colours binding.swipeRefreshLayout.setRainbowProgressCircle() - // Open the menu for the canteen picker button - binding.buttonCanteenPicker.setOnClickListener { - PopupMenu(binding.root.context, binding.buttonCanteenPicker).apply { - setOnMenuItemClickListener { item -> - viewModel.preferenceCanteen = when (item?.itemId) { - R.id.mensa_uni -> 0 - R.id.cafe_central -> 1 - R.id.mensa_nw1 -> 2 - R.id.cafeteria_gw2 -> 3 - R.id.mensa_neustadt -> 4 - R.id.mensa_werder -> 5 - R.id.mensa_airport -> 6 - R.id.mensa_bhv -> 7 - R.id.cafeteria_bhv -> 8 - R.id.mensa_hfk -> 9 - else -> 0 - } - // Set newly selected canteen to the button - binding.buttonCanteenPicker.text = getCurrentlySelectedCanteenName() - - // Display to the user that the canteen plan will be refreshed - binding.swipeRefreshLayout.isRefreshing = true - - // Refresh the canteen menu for the newly selected canteen - refresh() - true - } - inflate(R.menu.menu_canteens) - show() - } - } - // Set currently selected canteen to the button - binding.buttonCanteenPicker.text = getCurrentlySelectedCanteenName() +// binding.buttonCanteenPicker.text = getCurrentlySelectedCanteenName() + binding.appTitleBar.text = getString( + R.string.title_canteen_template, + getCurrentlySelectedCanteenName(), + ) + binding.appTitleBar.isSelected = true // Set up button to display info (most likely opening hours) - binding.buttonInfo.setOnClickListener { - openBottomSheet( - getTextSheet( - getString( - R.string.canteen_opening_hours, - getCurrentlySelectedCanteenName() - ), - openingHours - ) - ) - } +// binding.buttonInfo.setOnClickListener { +// +// } // Assign a preference value to every button to filter for dietary preferences val chipMap = mapOf( @@ -127,6 +92,55 @@ class CanteenFragment : AppFragment() { } } + // Set up floating action button for viewing the opening hours + binding.fabOpeningHours.setOnClickListener { + openBottomSheet( + getTextSheet( + getString( + R.string.canteen_opening_hours, + getCurrentlySelectedCanteenName() + ), + openingHours + ) + ) + } + + // Set up floating action button for switching the canteen + binding.fabSwitchCanteen.setOnClickListener { + PopupMenu(binding.root.context, binding.fabSwitchCanteen).apply { + setOnMenuItemClickListener { item -> + viewModel.preferenceCanteen = when (item?.itemId) { + R.id.mensa_uni -> 0 + R.id.cafe_central -> 1 + R.id.mensa_nw1 -> 2 + R.id.cafeteria_gw2 -> 3 + R.id.mensa_neustadt -> 4 + R.id.mensa_werder -> 5 + R.id.mensa_airport -> 6 + R.id.mensa_bhv -> 7 + R.id.cafeteria_bhv -> 8 + R.id.mensa_hfk -> 9 + else -> 0 + } + // Set newly selected canteen to the button +// binding.buttonCanteenPicker.text = getCurrentlySelectedCanteenName() + binding.appTitleBar.text = getString( + R.string.title_canteen_template, + getCurrentlySelectedCanteenName(), + ) + + // Display to the user that the canteen plan will be refreshed + binding.swipeRefreshLayout.isRefreshing = true + + // Refresh the canteen menu for the newly selected canteen + refresh() + true + } + inflate(R.menu.menu_canteens) + show() + } + } + // Set up floating action button for refreshing the canteen offers binding.fabRefreshOffers.setOnClickListener { // Display to the user that a refresh is in progress @@ -224,21 +238,27 @@ class CanteenFragment : AppFragment() { private fun refresh() { // Retrieve new offers from the website(s) viewModel.fetchOffers(viewModel.preferenceCanteen, onFinish = { - /* - * Tell the swipe refresh layout to stop refreshing. - */ - binding.swipeRefreshLayout.isRefreshing = false + // Check if the fragment is still active + if (_binding != null) { + /* + * Tell the swipe refresh layout to stop refreshing. + */ + binding.swipeRefreshLayout.isRefreshing = false + } }, onError = { - // Tell the user that an error occurred - context.theme?.showErrorSnackBar( - binding.snackbarContainer, - getString(R.string.canteen_fetch_error) - ) - /* + // Check if the fragment is still active + if (_binding != null) { + // Tell the user that an error occurred + context.theme?.showErrorSnackBar( + binding.snackbarContainer, + getString(R.string.canteen_fetch_error) + ) + /* * Tell the swipe refresh layout to stop refreshing. */ - binding.swipeRefreshLayout.isRefreshing = false + binding.swipeRefreshLayout.isRefreshing = false + } }) } } \ No newline at end of file diff --git a/app/src/main/java/com/denizk0461/studip/model/AllergenPreferences.kt b/app/src/main/java/com/denizk0461/studip/model/AllergenPreferences.kt index b1f0ead..04c46a1 100644 --- a/app/src/main/java/com/denizk0461/studip/model/AllergenPreferences.kt +++ b/app/src/main/java/com/denizk0461/studip/model/AllergenPreferences.kt @@ -1,6 +1,10 @@ package com.denizk0461.studip.model -// TODO KDoc +/** + * Class for managing allergen preferences. The user can tell the app which substances they are + * allergic against, and the functions in this class can be used to filter out offers containing + * allergens that could kill them. + */ class AllergenPreferences { /** @@ -69,8 +73,13 @@ class AllergenPreferences { * @return string with preferences inserted */ fun deconstruct(): String { + // Create an empty list val array = arrayListOf() + /* + * Add the symbols for the allergens to the list. Allergen symbols derived from the + * allergen list at stw-bremen.de + */ if (hasWheat) array.add("a1") if (hasRye) array.add("a2") if (hasBarley) array.add("a3") @@ -98,6 +107,7 @@ class AllergenPreferences { if (hasSesame) array.add("m") if (hasMolluscs) array.add("n") + // Join the individual symbols to a single string return array.joinToString(",") } } @@ -116,6 +126,7 @@ class AllergenPreferences { * @return instance of AllergenPreferences.Object with preferences inserted */ fun construct(input: String): Object { + // Split the string into its individual components val elements = input.split(",") return Object( elements.contains("a1"), diff --git a/app/src/main/res/drawable/arrow_down.xml b/app/src/main/res/drawable/arrow_down.xml new file mode 100644 index 0000000..9e345b8 --- /dev/null +++ b/app/src/main/res/drawable/arrow_down.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/clock.xml b/app/src/main/res/drawable/clock.xml new file mode 100644 index 0000000..bdf91f9 --- /dev/null +++ b/app/src/main/res/drawable/clock.xml @@ -0,0 +1,6 @@ + + + + diff --git a/app/src/main/res/drawable/switch_arrows.xml b/app/src/main/res/drawable/switch_arrows.xml new file mode 100644 index 0000000..ebd68d9 --- /dev/null +++ b/app/src/main/res/drawable/switch_arrows.xml @@ -0,0 +1,6 @@ + + + + diff --git a/app/src/main/res/layout/fragment_canteen.xml b/app/src/main/res/layout/fragment_canteen.xml index 8db101b..7e82a7a 100644 --- a/app/src/main/res/layout/fragment_canteen.xml +++ b/app/src/main/res/layout/fragment_canteen.xml @@ -1,6 +1,7 @@ @@ -17,48 +18,21 @@ android:orientation="vertical" app:layout_scrollFlags="scroll|exitUntilCollapsed"> - - - - - - - - - + android:text="@string/title_food" + android:textSize="28sp" + android:fontFamily="@font/lato_bolditalic" + android:layout_marginTop="16dp" + android:layout_marginHorizontal="16dp" + android:singleLine="true" + android:ellipsize="marquee" + android:marqueeRepeatLimit="marquee_forever" + android:focusable="true" + android:focusableInTouchMode="true" + android:scrollHorizontally="true"/> - + app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"> + + + + + + + + diff --git a/app/src/main/res/layout/fragment_event.xml b/app/src/main/res/layout/fragment_event.xml index 76a0378..4f88b7b 100644 --- a/app/src/main/res/layout/fragment_event.xml +++ b/app/src/main/res/layout/fragment_event.xml @@ -17,7 +17,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/title_schedule" - android:textSize="32sp" + android:textSize="28sp" android:fontFamily="@font/lato_bolditalic" android:layout_marginTop="16dp" android:layout_marginHorizontal="16dp" diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml index bc41a69..8851b23 100644 --- a/app/src/main/res/layout/fragment_settings.xml +++ b/app/src/main/res/layout/fragment_settings.xml @@ -22,7 +22,7 @@ android:fontFamily="@font/lato_bolditalic" android:text="@string/title_settings" app:layout_scrollFlags="scroll|exitUntilCollapsed" - android:textSize="32sp"/> + android:textSize="28sp"/> diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 3a3e924..124441d 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -58,12 +58,15 @@ Kein Angebot Für diesen Tag sind keine Angebote vorhanden + Zeige Öffnungszeiten + Wechsle Mensa Aktualisiere Angebote Lizenzen Dein Stundenplan Mensenangebote + %s – Angebote App-Einstellungen %s – Öffnungszeiten diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml index 0580aa6..147a69e 100644 --- a/app/src/main/res/values-night/themes.xml +++ b/app/src/main/res/values-night/themes.xml @@ -80,24 +80,9 @@ @color/game_dark_onPrimary @color/game_dark_container @color/game_dark_onContainer - - @style/TimeDialogTheme - - - - \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c4f3478..da27b0c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -59,6 +59,8 @@ No offers There are no offers available for this day + Show opening hours + Switch canteen Refresh offers Licences @@ -66,6 +68,7 @@ Your Schedule Canteen Offers + %s – Offers App Settings %s – Opening Hours diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 16a3722..e4cda17 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -80,8 +80,6 @@ @color/game_light_onPrimary @color/game_light_container @color/game_light_onContainer - - @style/TimeDialogTheme - - - - \ No newline at end of file