WeserPlaner 1.0.1: pricing can now be adjusted - users can pick whether they want to see pricing for students or for employees; fragment launch settings has been changed to use a MaterialButtonGroup to support adding more options down the line

This commit is contained in:
denizk0461
2023-05-10 21:14:17 +02:00
parent 9ada2ca462
commit e33414b7e9
12 changed files with 228 additions and 79 deletions
@@ -47,17 +47,21 @@ class MainActivity : FragmentActivity() {
* Sets the navigation graph for the fragments. Also sets the start destination.
*/
private fun setNavigationGraph() {
// Get nav host
val navHostFragment = supportFragmentManager
.findFragmentById(R.id.nav_host_fragment_content_main) as NavHostFragment
val navController = navHostFragment.navController
val navGraph = navController.navInflater.inflate(R.navigation.main_nav_graph)
navGraph.setStartDestination(if (viewModel.preferenceLaunchCanteen) {
R.id.canteen
} else {
R.id.schedule
// Inflate new nav graph
val navGraph = navHostFragment
.navController.navInflater.inflate(R.navigation.main_nav_graph)
// Set the starting fragment for the app
navGraph.setStartDestination(when (viewModel.preferenceLaunchFragment) {
1 -> R.id.canteen
else -> R.id.schedule // 0
})
navController.graph = navGraph
// Set the newly defined nav graph
navHostFragment.navController.graph = navGraph
}
}
@@ -252,7 +252,18 @@ class StwParser(application: Application) {
itemId,
categoryId,
title = filteredText.first,
price = tableRows.getTextOrEmpty(2),
price = tableRows.getTextOrEmpty(
/*
* ID stored for student: 0
* Index required to fetch student price: 2
*
* ID stored for employee: 1
* Index required to fetch employee price: 3
*
* Hence, getIntPreference() + 2
*/
repo.getIntPreference(SettingsPreferences.PRICING) + 2
),
dietaryPreferences = prefs.deconstruct(),
allergens = filteredText.second,
)
@@ -14,8 +14,6 @@ import com.denizk0461.weserplaner.data.showErrorSnackBar
import com.denizk0461.weserplaner.databinding.FragmentCanteenBinding
import com.denizk0461.weserplaner.model.*
import com.denizk0461.weserplaner.viewmodel.CanteenViewModel
import com.google.android.material.badge.BadgeDrawable
import com.google.android.material.badge.BadgeUtils
import com.google.android.material.tabs.TabLayoutMediator
/**
@@ -72,10 +70,12 @@ class CanteenFragment : AppFragment() {
}
// Create badge
val badge = BadgeDrawable.create(context)
badge.isVisible = true
// Attach badge to button
BadgeUtils.attachBadgeDrawable(badge, binding.buttonNotifications)
// val badge = BadgeDrawable.create(context)
//// badge.isVisible = true
// badge.number = 1
// badge.badgeGravity = BadgeDrawable.TOP_END
// // Attach badge to button
// BadgeUtils.attachBadgeDrawable(badge, binding.buttonNotifications, binding.buttonNotificationsBadgeContainer)
// Assign a preference value to every button to filter for dietary preferences
val chipMap = mapOf(
@@ -106,10 +106,62 @@ class SettingsFragment : AppFragment() {
}
// Set up switch for launching the app with a specific view
binding.switchLaunchCanteen.apply {
isChecked = viewModel.preferenceLaunchCanteen
setOnCheckedChangeListener { _, newValue ->
viewModel.preferenceLaunchCanteen = newValue
// binding.switchLaunchCanteen.apply {
// isChecked = viewModel.preferenceLaunchCanteen
// setOnCheckedChangeListener { _, newValue ->
// viewModel.preferenceLaunchCanteen = newValue
// }
// }
// Set up button toggle group for changing prices displayed for the canteen offers
binding.togglePricingGroup.apply {
// Check the pricing that is currently selected
check(when (viewModel.preferencePricing) {
1 -> R.id.toggle_pricing_employee
else -> R.id.toggle_pricing_student // 0
})
// Set up checked listener for toggle group
addOnButtonCheckedListener { _, checkedId, isChecked ->
/*
* Check if the button that is changed is the checked button. If this is not checked
* for, the listener will simply loop through this when-statement with all buttons
* that had their state changed somehow, and save the ID of the last one that had
* its state changed.
*/
if (isChecked) {
// Save new preference
viewModel.preferencePricing = when (checkedId) {
R.id.toggle_pricing_employee -> 1
else -> 0 // R.id.toggle_pricing_student
}
}
}
}
// Set up button toggle group for changing default fragment
binding.toggleLaunchFragmentGroup.apply {
// Check the fragment that is currently selected
check(when (viewModel.preferenceLaunchFragment) {
1 -> R.id.toggle_launch_fragment_canteen
else -> R.id.toggle_launch_fragment_schedule // 0
})
// Set up checked listener for toggle group
addOnButtonCheckedListener { _, checkedId, isChecked ->
/*
* Check if the button that is changed is the checked button. If this is not checked
* for, the listener will simply loop through this when-statement with all buttons
* that had their state changed somehow, and save the ID of the last one that had
* its state changed.
*/
if (isChecked) {
// Save new preference
viewModel.preferenceLaunchFragment = when (checkedId) {
R.id.toggle_launch_fragment_canteen -> 1
else -> 0 // R.id.toggle_launch_fragment_schedule
}
}
}
}
@@ -3,6 +3,7 @@ package com.denizk0461.weserplaner.model
/**
* Enumeration class for user-set preferences that will be saved in persistent storage via
* SharedPreferences.
* TODO mark which data types should be used for which preferences (boolean, string, int)
*
* @param key key for the SharedPreferences transaction
*/
@@ -34,9 +35,14 @@ enum class SettingsPreferences(val key: String) {
COURSE_HIGHLIGHTING("setting_highlight"),
/**
* Whether the user wants the app to launch with the canteen fragment.
* Which prices the user wants to have displayed for the canteen offers.
*/
LAUNCH_CANTEEN_ON_START("settings_launch_canteen"),
PRICING("settings_pricing"),
/**
* Which fragment the user wants the app to start with.
*/
LAUNCH_FRAGMENT_ON_START("settings_launch_fragment"),
/**
* Whether the user wants dietary preferences to be coloured.
@@ -60,6 +60,10 @@ class DevCodeSheet : AppSheet(R.layout.sheet_dev_code) {
"TE9ORUxZ".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9uLURFNHNfc3d5Zw==".d64)
"QkVBVVRZ".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9vbVQ1ckttVTVfaw==".d64)
"Uk9NQ09N".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9HUW1nUG5uZjE4WQ==".d64)
"Tk9DQVNI".d64 -> launchLink(listOf(
"aHR0cHM6Ly95b3V0dS5iZS9lRzh3bkx2NTlPbw==",
"aHR0cHM6Ly95b3V0dS5iZS9RSzBZLUQ1bVpaaw==",
).random().d64)
"Qk9KQUNL".d64 -> {
startActivity(Intent(context, ImageActivity::class.java).also { intent ->
val bundle = Bundle()
@@ -11,8 +11,9 @@ import com.denizk0461.weserplaner.model.SettingsPreferences
class MainViewModel(application: Application) : AppViewModel(application) {
/**
* This value determines whether the user wants the app to launch with the canteen view.
* This value determines which fragment the user wants the app to start with. Order is equal to
* the order that the items are arranged in in the bottom nav bar.
*/
val preferenceLaunchCanteen: Boolean
get() = repo.getBooleanPreference(SettingsPreferences.LAUNCH_CANTEEN_ON_START)
val preferenceLaunchFragment: Int
get() = repo.getIntPreference(SettingsPreferences.LAUNCH_FRAGMENT_ON_START)
}
@@ -50,11 +50,20 @@ class SettingsViewModel(app: Application) : AppViewModel(app) {
}
/**
* This value determines whether the user wants the app to launch with the canteen view.
* This value determines which fragment the user wants the app to start with. Order is equal to
* the order that the items are arranged in in the bottom nav bar.
*/
var preferenceLaunchCanteen: Boolean
get() = repo.getBooleanPreference(SettingsPreferences.LAUNCH_CANTEEN_ON_START)
set(newValue) { repo.setPreference(SettingsPreferences.LAUNCH_CANTEEN_ON_START, newValue) }
var preferencePricing: Int
get() = repo.getIntPreference(SettingsPreferences.PRICING)
set(newValue) { repo.setPreference(SettingsPreferences.PRICING, newValue) }
/**
* This value determines which fragment the user wants the app to start with. Order is equal to
* the order that the items are arranged in in the bottom nav bar.
*/
var preferenceLaunchFragment: Int
get() = repo.getIntPreference(SettingsPreferences.LAUNCH_FRAGMENT_ON_START)
set(newValue) { repo.setPreference(SettingsPreferences.LAUNCH_FRAGMENT_ON_START, newValue) }
/**
* This value determines which canteen the user has selected.
+11 -12
View File
@@ -21,16 +21,16 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp">
android:layout_marginHorizontal="16dp">
<TextView
android:id="@+id/app_title_bar"
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/title_food"
android:text="@string/title_canteen"
android:textSize="28sp"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:fontFamily="@font/lato_blackitalic"
android:singleLine="true"
android:ellipsize="marquee"
@@ -49,12 +49,11 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="0dp"
android:layout_marginStart="8dp"
app:icon="@drawable/notification"
app:iconPadding="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintTop_toTopOf="@id/app_title_bar"
app:layout_constraintBottom_toBottomOf="@id/app_title_bar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:iconTint="?attr/colorOnSurfaceVariant"/>
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -229,10 +228,10 @@
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TEST TEST TEST TEST ABC 123 !!!"/>
<!-- <TextView-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="TEST TEST TEST TEST ABC 123 !!!"/>-->
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
+85 -34
View File
@@ -329,6 +329,56 @@
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- Pricing -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/lato_bolditalic"
android:text="@string/settings_pricing_title"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings_pricing_subtitle"
android:textSize="16sp" />
<com.google.android.material.button.MaterialButtonToggleGroup
android:id="@+id/toggle_pricing_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
app:singleSelection="true"
app:selectionRequired="true">
<com.google.android.material.button.MaterialButton
android:id="@+id/toggle_pricing_student"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/settings_pricing_student"
style="?attr/materialButtonOutlinedStyle"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/toggle_pricing_employee"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/settings_pricing_employee"
style="?attr/materialButtonOutlinedStyle"/>
</com.google.android.material.button.MaterialButtonToggleGroup>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</com.google.android.material.card.MaterialCardView>
@@ -363,48 +413,49 @@
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp" />
<!-- show canteen plan on app launch -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout_launch_canteen"
<!-- Launch fragment -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/switch_launch_canteen"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/lato_bolditalic"
android:text="@string/settings_launch_canteen_title"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings_launch_canteen_subtitle"
android:textSize="16sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/switch_launch_canteen"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
android:fontFamily="@font/lato_bolditalic"
android:text="@string/settings_launch_canteen_title"
android:textSize="16sp" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.button.MaterialButtonToggleGroup
android:id="@+id/toggle_launch_fragment_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
app:singleSelection="true"
app:selectionRequired="true">
<com.google.android.material.button.MaterialButton
android:id="@+id/toggle_launch_fragment_schedule"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/title_schedule_short"
style="?attr/materialButtonOutlinedStyle"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/toggle_launch_fragment_canteen"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/title_canteen_short"
style="?attr/materialButtonOutlinedStyle"/>
</com.google.android.material.button.MaterialButtonToggleGroup>
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- crashlytics opt-in - unused. use for possible future implementation of Crashlytics -->
<androidx.constraintlayout.widget.ConstraintLayout
+9 -3
View File
@@ -76,7 +76,9 @@
<string name="sheet_licences_header">Lizenzen</string>
<string name="title_schedule">Dein Stundenplan</string>
<string name="title_food">Mensenangebote</string>
<string name="title_schedule_short">Stundenplan</string>
<string name="title_canteen">Mensenangebote</string>
<string name="title_canteen_short">Mensa</string>
<string name="title_canteen_template">%s Angebote</string>
<string name="title_settings">App-Einstellungen</string>
@@ -178,11 +180,15 @@
<string name="allergens_config_content">Achtung: bitte verlasse Dich nicht vollständig auf diese Funktion. Stelle immer in der Mensa, die Du besuchst, sicher, dass die Stoffe, auf die Du allergisch reagierst, nicht in deren Angeboten vorhanden sind. Die Allergen-Hinweise einiger Mensen sind online leider unvollständig.</string>
<string name="allergens_config_confirmation">Deine Allergene wurden gespeichert.</string>
<string name="settings_pricing_title">Siehe Preise für</string>
<string name="settings_pricing_subtitle">Wird nach einer Aktualisierung der Angebote wirksam</string>
<string name="settings_pricing_student">Studierende</string>
<string name="settings_pricing_employee">Bedienstete</string>
<string name="settings_allergens_title">Markiere Angebote mit Allergenen mit einem Stern*</string>
<string name="settings_allergens_subtitle">Wird auch für Zusatzstoffe genutzt</string>
<string name="settings_launch_canteen_title">Starte die App mit dem Mensaplan</string>
<string name="settings_launch_canteen_subtitle">Sonst wird Dein Stundenplan beim Start gezeigt</string>
<string name="settings_launch_canteen_title">Wähle, mit welchem Bildschirm die App startet</string>
<string name="settings_pref_colour_title">Färbe Diätpreferenzen</string>
<string name="settings_pref_colour_subtitle">Dies färbt die kleinen Symbole ähnlich wie auf der Webseite</string>
+9 -3
View File
@@ -78,7 +78,9 @@
<string name="sheet_licences_content" translatable="false">Android developer resources by Google.\nhttps://developer.android.com/\nandroidx.appcompat:appcompat:1.6.1\nandroidx.constraintlayout:constraintlayout:2.1.4\nandroidx.core:core-ktx:1.10.0\nandroidx.fragment:fragment-ktx:1.6.0-beta01\nandroidx.navigation:navigation-fragment-ktx:2.5.3\nandroidx.navigation:navigation-ui-ktx:2.5.3\nandroidx.preference:preference-ktx:1.2.0\nandroidx.room:room-runtime:2.5.1\nandroidx.room:room-compiler:2.5.1\nandroidx.swiperefreshlayout:swiperefreshlayout:1.2.0-alpha01\n\nDesign guidelines, icons, and colour palette by Google.\nhttps://m3.material.io/\ncom.google.android.material:material:1.9.0\n\nAdditional icons by Flaticon.\nhttps://www.flaticon.com/\n\nWeb scraping functionality by Jonathan Hedley.\nhttps://jhy.io/\nhttps://jsoup.org/\norg.jsoup:jsoup:1.15.4\n\nApp developed by Deniz Düzgören.\ndenizk0461@gmail.com\ndeniz7@uni-bremen.de</string>
<string name="title_schedule">Your Schedule</string>
<string name="title_food">Canteen Offers</string>
<string name="title_schedule_short">Schedule</string>
<string name="title_canteen">Canteen Offers</string>
<string name="title_canteen_short">Canteen</string>
<string name="title_canteen_template">%s Offers</string>
<string name="title_settings">App Settings</string>
@@ -182,14 +184,18 @@
<string name="allergens_config_content">Note: please don\'t entirely rely on this. Always check the notices displayed at the canteen you\'re visiting to confirm substances you may be allergic against are not present in their offerings. Some canteens unfortunately don\'t provide full allergen information online.</string>
<string name="allergens_config_confirmation">Your allergen settings have been saved.</string>
<string name="settings_pricing_title">View prices for</string>
<string name="settings_pricing_subtitle">Takes effect after refreshing the offers</string>
<string name="settings_pricing_student">Students</string>
<string name="settings_pricing_employee">Employees</string>
<string name="settings_allergens_title">Mark offers with allergens with a star*</string>
<string name="settings_allergens_subtitle">Also applies to additives</string>
<string name="settings_pref_colour_title">Colour dietary preferences</string>
<string name="settings_pref_colour_subtitle">Icons will be coloured similarly to how they look the website</string> <!-- TODO this text sucks, DE too -->
<string name="settings_launch_canteen_title">Show canteen plan on app launch</string>
<string name="settings_launch_canteen_subtitle">Otherwise your schedule will be shown at launch</string>
<string name="settings_launch_canteen_title">Select which screen to start the app with</string>
<!-- unused - use for possible future implementation of Crashlytics -->
<string name="settings_crashlytics_title">Opt-in to sharing crash data</string>