Archived
Converted all bottom sheets to use blank constructors and instead rely on bundles to retrieve data/objects, or custom view models to execute functions
This commit is contained in:
Generated
+17
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="deploymentTargetDropDown">
|
||||
<targetSelectedWithDropDown>
|
||||
<Target>
|
||||
<type value="QUICK_BOOT_TARGET" />
|
||||
<deviceKey>
|
||||
<Key>
|
||||
<type value="VIRTUAL_DEVICE_PATH" />
|
||||
<value value="C:\Users\kduez\.android\avd\Pixel_6_A13_.avd" />
|
||||
</Key>
|
||||
</deviceKey>
|
||||
</Target>
|
||||
</targetSelectedWithDropDown>
|
||||
<timeTargetWasSelectedWithDropDown value="2023-05-02T10:34:36.007714500Z" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -2,12 +2,17 @@ package com.denizk0461.studip.data
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.util.TypedValue
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.AttrRes
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import com.denizk0461.studip.R
|
||||
import com.denizk0461.studip.exception.AcademicQuarterNotApplicableException
|
||||
import com.denizk0461.studip.exception.ParcelNotFoundException
|
||||
import com.denizk0461.studip.sheet.TextSheet
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlin.jvm.Throws
|
||||
|
||||
@@ -54,6 +59,41 @@ fun Resources.Theme.showErrorSnackBar(view: CoordinatorLayout, text: String) {
|
||||
.show()
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a [TextSheet] with text content added as arguments bundle.
|
||||
*
|
||||
* @param header header of the sheet
|
||||
* @param content text content of the sheet
|
||||
* @return sheet with text added
|
||||
*/
|
||||
fun getTextSheet(header: String, content: String): TextSheet = TextSheet().also { sheet ->
|
||||
val bundle = Bundle()
|
||||
bundle.putString("header", header)
|
||||
bundle.putString("content", content)
|
||||
sheet.arguments = bundle
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a Parcelable object from a given instance of [Bundle].
|
||||
*
|
||||
* @param T type of the object to retrieve
|
||||
* @param key string key to retrieve the object from the [Bundle]
|
||||
* @throws ParcelNotFoundException if the Parcel couldn't be retrieved
|
||||
*/
|
||||
@Throws(ParcelNotFoundException::class)
|
||||
inline fun <reified T : Parcelable> Bundle?.getParcelableCompat(key: String): T =
|
||||
/*
|
||||
* Since the old getParcelable() call is deprecated since API 33 (Tiramisu) and replaced with a
|
||||
* type-safe version, and no AppCompat version is available as of now, this API level check is
|
||||
* necessary instead.
|
||||
*/
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
this?.getParcelable(key, T::class.java)
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
this?.getParcelable(key) as? T
|
||||
} ?: throw ParcelNotFoundException()
|
||||
|
||||
/**
|
||||
* Provides a conversion method between a timestamp ending in a full hour, and one with an academic
|
||||
* quarter applied.
|
||||
|
||||
@@ -130,7 +130,7 @@ class StwParser(application: Application) {
|
||||
|
||||
/*
|
||||
* Retrieve the opening hours for the canteen.
|
||||
* TODO this formatting sucks
|
||||
* TODO this formatting sucks and also this doesn't work
|
||||
*/
|
||||
var openingHours = ""
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.denizk0461.studip.exception
|
||||
|
||||
import java.io.IOException
|
||||
|
||||
class ParcelNotFoundException : IOException()
|
||||
@@ -8,10 +8,10 @@ import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.denizk0461.studip.R
|
||||
import com.denizk0461.studip.adapter.CanteenOfferPageAdapter
|
||||
import com.denizk0461.studip.data.getTextSheet
|
||||
import com.denizk0461.studip.data.showErrorSnackBar
|
||||
import com.denizk0461.studip.databinding.FragmentCanteenBinding
|
||||
import com.denizk0461.studip.model.*
|
||||
import com.denizk0461.studip.sheet.TextSheet
|
||||
import com.denizk0461.studip.viewmodel.CanteenViewModel
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
|
||||
@@ -87,7 +87,7 @@ class CanteenFragment : AppFragment() {
|
||||
// Set up button to display info (most likely opening hours)
|
||||
binding.buttonInfo.setOnClickListener {
|
||||
openBottomSheet(
|
||||
TextSheet(
|
||||
getTextSheet(
|
||||
getString(
|
||||
R.string.canteen_opening_hours,
|
||||
getCurrentlySelectedCanteenName()
|
||||
|
||||
@@ -230,7 +230,15 @@ class CanteenPageFragment : AppFragment(), CanteenOfferItemAdapter.OnClickListen
|
||||
* @param offer item that has been clicked
|
||||
*/
|
||||
override fun onClick(offer: CanteenOfferGroupElement, category: String) {
|
||||
openBottomSheet(AllergenSheet(offer, category, viewModel.preferenceColour))
|
||||
openBottomSheet(
|
||||
AllergenSheet().also { sheet ->
|
||||
val bundle = Bundle()
|
||||
bundle.putParcelable("offer", offer)
|
||||
bundle.putString("category", category)
|
||||
bundle.putBoolean("preferenceColour", viewModel.preferenceColour)
|
||||
sheet.arguments = bundle
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -74,7 +74,6 @@ class EventPageFragment : AppFragment(), StudIPEventItemAdapter.OnClickListener
|
||||
|
||||
// Set up LiveData observer to refresh the view on update
|
||||
viewModel.getEventsForDay(currentDay).observe(viewLifecycleOwner) { events ->
|
||||
|
||||
eventAdapter.setNewData(events)
|
||||
}
|
||||
}
|
||||
@@ -85,11 +84,13 @@ class EventPageFragment : AppFragment(), StudIPEventItemAdapter.OnClickListener
|
||||
|
||||
override fun onLongClick(event: StudIPEvent): Boolean {
|
||||
// Open a bottom sheet to edit the event
|
||||
openBottomSheet(ScheduleUpdateSheet(event, onUpdate = { eventToUpdate ->
|
||||
viewModel.update(eventToUpdate)
|
||||
}, onDelete = { eventToDelete ->
|
||||
viewModel.delete(eventToDelete)
|
||||
}))
|
||||
openBottomSheet(
|
||||
ScheduleUpdateSheet().also { sheet ->
|
||||
val bundle = Bundle()
|
||||
bundle.putParcelable("event", event)
|
||||
sheet.arguments = bundle
|
||||
}
|
||||
)
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -12,12 +12,11 @@ import com.denizk0461.studip.BuildConfig
|
||||
import com.denizk0461.studip.R
|
||||
import com.denizk0461.studip.activity.FetcherActivity
|
||||
import com.denizk0461.studip.activity.ImageActivity
|
||||
import com.denizk0461.studip.data.getTextSheet
|
||||
import com.denizk0461.studip.data.showToast
|
||||
import com.denizk0461.studip.databinding.FragmentSettingsBinding
|
||||
import com.denizk0461.studip.model.AllergenPreferences
|
||||
import com.denizk0461.studip.sheet.AllergenConfigSheet
|
||||
import com.denizk0461.studip.sheet.DevCodeSheet
|
||||
import com.denizk0461.studip.sheet.TextSheet
|
||||
import com.denizk0461.studip.viewmodel.SettingsViewModel
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
@@ -67,13 +66,10 @@ class SettingsFragment : AppFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
// Set up button to set allergens
|
||||
binding.buttonAllergensConfig.setOnClickListener {
|
||||
openBottomSheet(
|
||||
AllergenConfigSheet(
|
||||
AllergenPreferences.construct(viewModel.preferenceAllergenConfig)
|
||||
) { obj ->
|
||||
viewModel.preferenceAllergenConfig = obj.deconstruct()
|
||||
}
|
||||
AllergenConfigSheet()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -111,16 +107,18 @@ class SettingsFragment : AppFragment() {
|
||||
|
||||
// Set click listener for the data handling dialogue
|
||||
binding.buttonDataHandling.setOnClickListener {
|
||||
openBottomSheet(TextSheet(
|
||||
openBottomSheet(
|
||||
getTextSheet(
|
||||
getString(R.string.settings_data_sheet_header),
|
||||
getString(R.string.settings_data_sheet_content),
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// Set click listener for showing licences dialogue
|
||||
binding.buttonLicences.setOnClickListener {
|
||||
openBottomSheet(
|
||||
TextSheet(
|
||||
getTextSheet(
|
||||
getString(R.string.sheet_licences_header),
|
||||
getString(R.string.sheet_licences_content),
|
||||
)
|
||||
@@ -129,14 +127,7 @@ class SettingsFragment : AppFragment() {
|
||||
|
||||
// Set long click listener for licences button to open dev code sheet
|
||||
binding.buttonLicences.setOnLongClickListener {
|
||||
openBottomSheet(DevCodeSheet(
|
||||
viewModel::nukeEvents,
|
||||
viewModel::nukeOfferItems,
|
||||
viewModel::nukeOfferCategories,
|
||||
viewModel::nukeOfferCanteens,
|
||||
viewModel::nukeOfferDates,
|
||||
viewModel::nukeEverything,
|
||||
))
|
||||
openBottomSheet(DevCodeSheet())
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.denizk0461.studip.model
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
/**
|
||||
* Stripped version of CanteenOffer.kt that only carries essential info. Assumes that instances of
|
||||
* this are assigned to corresponding date, canteen, and category via an instance of
|
||||
@@ -12,8 +15,39 @@ package com.denizk0461.studip.model
|
||||
* @param allergens allergens and additives that are present in the item
|
||||
*/
|
||||
data class CanteenOfferGroupElement(
|
||||
// parcel
|
||||
val title: String,
|
||||
val price: String,
|
||||
val dietaryPreferences: String,
|
||||
val allergens: String,
|
||||
)
|
||||
) : Parcelable {
|
||||
|
||||
// Generated Parcelable implementation
|
||||
constructor(source: Parcel) : this(
|
||||
source.readString() ?: "",
|
||||
source.readString() ?: "",
|
||||
source.readString() ?: "",
|
||||
source.readString() ?: "",
|
||||
)
|
||||
|
||||
override fun describeContents(): Int = 0
|
||||
|
||||
override fun writeToParcel(dest: Parcel, flags: Int): Unit = with(dest) {
|
||||
writeString(title)
|
||||
writeString(price)
|
||||
writeString(dietaryPreferences)
|
||||
writeString(allergens)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val CREATOR: Parcelable.Creator<CanteenOfferGroupElement> =
|
||||
object : Parcelable.Creator<CanteenOfferGroupElement> {
|
||||
override fun createFromParcel(source: Parcel): CanteenOfferGroupElement =
|
||||
CanteenOfferGroupElement(source)
|
||||
|
||||
override fun newArray(size: Int): Array<CanteenOfferGroupElement?> =
|
||||
arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.denizk0461.studip.model
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@@ -27,8 +29,7 @@ data class StudIPEvent(
|
||||
val timeslotEnd: String,
|
||||
val timeslotId: Int,
|
||||
val colour: Int = 0,
|
||||
) {
|
||||
|
||||
) : Parcelable {
|
||||
/**
|
||||
* Parse timeslotStart and timeslotEnd into an easily readable string in the following format:
|
||||
* 12:15 – 13:45
|
||||
@@ -37,8 +38,6 @@ data class StudIPEvent(
|
||||
*/
|
||||
fun timeslot(): String = "$timeslotStart – $timeslotEnd"
|
||||
|
||||
// Auto-generated methods. Necessary for [AppDiffUtilCallback]
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
@@ -70,4 +69,38 @@ data class StudIPEvent(
|
||||
result = 31 * result + colour
|
||||
return result
|
||||
}
|
||||
|
||||
constructor(source: Parcel) : this(
|
||||
source.readInt(),
|
||||
source.readString() ?: "",
|
||||
source.readString() ?: "",
|
||||
source.readString() ?: "",
|
||||
source.readInt(),
|
||||
source.readString() ?: "",
|
||||
source.readString() ?: "",
|
||||
source.readInt(),
|
||||
source.readInt(),
|
||||
)
|
||||
|
||||
override fun describeContents(): Int = 0
|
||||
|
||||
override fun writeToParcel(dest: Parcel, flags: Int): Unit = with(dest) {
|
||||
writeInt(eventId)
|
||||
writeString(title)
|
||||
writeString(lecturer)
|
||||
writeString(room)
|
||||
writeInt(day)
|
||||
writeString(timeslotStart)
|
||||
writeString(timeslotEnd)
|
||||
writeInt(timeslotId)
|
||||
writeInt(colour)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val CREATOR: Parcelable.Creator<StudIPEvent> = object : Parcelable.Creator<StudIPEvent> {
|
||||
override fun createFromParcel(source: Parcel): StudIPEvent = StudIPEvent(source)
|
||||
override fun newArray(size: Int): Array<StudIPEvent?> = arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,30 +2,34 @@ package com.denizk0461.studip.sheet
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.denizk0461.studip.R
|
||||
import com.denizk0461.studip.data.showToast
|
||||
import com.denizk0461.studip.data.viewBinding
|
||||
import com.denizk0461.studip.databinding.SheetAllergenConfigBinding
|
||||
import com.denizk0461.studip.model.AllergenPreferences
|
||||
import com.denizk0461.studip.viewmodel.AllergenConfigViewModel
|
||||
|
||||
/**
|
||||
* Configuration sheet for the user to pick substances they are allergic against. Offers containing
|
||||
* these allergens will be hidden.
|
||||
*
|
||||
* @param currentAllergenConfig currently set allergen preference
|
||||
* @param onUpdate action to execute to store the allergen preferences
|
||||
*/
|
||||
class AllergenConfigSheet(
|
||||
private val currentAllergenConfig: AllergenPreferences.Object,
|
||||
private val onUpdate: (obj: AllergenPreferences.Object) -> Unit,
|
||||
) : AppSheet(R.layout.sheet_allergen_config) {
|
||||
class AllergenConfigSheet : AppSheet(R.layout.sheet_allergen_config) {
|
||||
|
||||
// View binding
|
||||
private val binding: SheetAllergenConfigBinding by viewBinding(SheetAllergenConfigBinding::bind)
|
||||
|
||||
// View model
|
||||
private val viewModel: AllergenConfigViewModel by viewModels()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
// Retrieve allergens as currently set by the user from view model
|
||||
val currentAllergenConfig = AllergenPreferences.construct(
|
||||
viewModel.preferenceAllergenConfig
|
||||
)
|
||||
|
||||
// Set all check boxes to the currently set values
|
||||
binding.apply {
|
||||
checkWheat.isChecked = currentAllergenConfig.hasWheat
|
||||
@@ -69,36 +73,34 @@ class AllergenConfigSheet(
|
||||
|
||||
binding.apply {
|
||||
// Save the new preferences
|
||||
onUpdate(
|
||||
AllergenPreferences.Object(
|
||||
hasWheat = checkWheat.isChecked,
|
||||
hasRye = checkRye.isChecked,
|
||||
hasBarley = checkBarley.isChecked,
|
||||
hasOats = checkOat.isChecked,
|
||||
hasSpelt = checkSpelt.isChecked,
|
||||
hasKamut = checkKamut.isChecked,
|
||||
hasCrustaceans = checkCrustaceans.isChecked,
|
||||
hasEggs = checkEggs.isChecked,
|
||||
hasFish = checkFish.isChecked,
|
||||
hasPeanuts = checkPeanuts.isChecked,
|
||||
hasSoy = checkSoy.isChecked,
|
||||
hasDairy = checkDairy.isChecked,
|
||||
hasAlmonds = checkAlmonds.isChecked,
|
||||
hasHazelnuts = checkHazelnuts.isChecked,
|
||||
hasWalnuts = checkWalnuts.isChecked,
|
||||
hasCashewNuts = checkCashewNuts.isChecked,
|
||||
hasPecans = checkPecans.isChecked,
|
||||
hasBrazilNuts = checkBrazilNuts.isChecked,
|
||||
hasPistachios = checkPistachios.isChecked,
|
||||
hasMacadamia = checkMacadamia.isChecked,
|
||||
hasCelery = checkCelery.isChecked,
|
||||
hasMustard = checkMustard.isChecked,
|
||||
hasSulphides = checkSulphides.isChecked,
|
||||
hasLupins = checkLupins.isChecked,
|
||||
hasSesame = checkSesame.isChecked,
|
||||
hasMolluscs = checkMolluscs.isChecked,
|
||||
)
|
||||
)
|
||||
viewModel.preferenceAllergenConfig = AllergenPreferences.Object(
|
||||
hasWheat = checkWheat.isChecked,
|
||||
hasRye = checkRye.isChecked,
|
||||
hasBarley = checkBarley.isChecked,
|
||||
hasOats = checkOat.isChecked,
|
||||
hasSpelt = checkSpelt.isChecked,
|
||||
hasKamut = checkKamut.isChecked,
|
||||
hasCrustaceans = checkCrustaceans.isChecked,
|
||||
hasEggs = checkEggs.isChecked,
|
||||
hasFish = checkFish.isChecked,
|
||||
hasPeanuts = checkPeanuts.isChecked,
|
||||
hasSoy = checkSoy.isChecked,
|
||||
hasDairy = checkDairy.isChecked,
|
||||
hasAlmonds = checkAlmonds.isChecked,
|
||||
hasHazelnuts = checkHazelnuts.isChecked,
|
||||
hasWalnuts = checkWalnuts.isChecked,
|
||||
hasCashewNuts = checkCashewNuts.isChecked,
|
||||
hasPecans = checkPecans.isChecked,
|
||||
hasBrazilNuts = checkBrazilNuts.isChecked,
|
||||
hasPistachios = checkPistachios.isChecked,
|
||||
hasMacadamia = checkMacadamia.isChecked,
|
||||
hasCelery = checkCelery.isChecked,
|
||||
hasMustard = checkMustard.isChecked,
|
||||
hasSulphides = checkSulphides.isChecked,
|
||||
hasLupins = checkLupins.isChecked,
|
||||
hasSesame = checkSesame.isChecked,
|
||||
hasMolluscs = checkMolluscs.isChecked,
|
||||
).deconstruct()
|
||||
}
|
||||
|
||||
// Tell the user that saving was successful
|
||||
|
||||
@@ -6,10 +6,13 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.appcompat.content.res.AppCompatResources.getDrawable
|
||||
import com.denizk0461.studip.R
|
||||
import com.denizk0461.studip.data.getParcelableCompat
|
||||
import com.denizk0461.studip.data.getThemedColor
|
||||
import com.denizk0461.studip.data.showToast
|
||||
import com.denizk0461.studip.data.viewBinding
|
||||
import com.denizk0461.studip.databinding.ItemSheetPreferenceBinding
|
||||
import com.denizk0461.studip.databinding.SheetAllergenBinding
|
||||
import com.denizk0461.studip.exception.ParcelNotFoundException
|
||||
import com.denizk0461.studip.model.Allergens
|
||||
import com.denizk0461.studip.model.CanteenOfferGroupElement
|
||||
import com.denizk0461.studip.model.DietaryPreferences
|
||||
@@ -17,16 +20,8 @@ import com.denizk0461.studip.model.DietaryPreferences
|
||||
/**
|
||||
* This class is used to display further information on a canteen offer to the user. Unlike the name
|
||||
* implies, it displays more than just allergens.
|
||||
*
|
||||
* @param offer item to display further information on
|
||||
* @param category category the offer belongs to
|
||||
* @param displayColours whether the user wants dietary preferences to be marked with colours
|
||||
*/
|
||||
class AllergenSheet(
|
||||
private val offer: CanteenOfferGroupElement,
|
||||
private val category: String,
|
||||
private val displayColours: Boolean,
|
||||
) : AppSheet(R.layout.sheet_allergen) {
|
||||
class AllergenSheet : AppSheet(R.layout.sheet_allergen) {
|
||||
|
||||
// View binding
|
||||
private val binding: SheetAllergenBinding by viewBinding(SheetAllergenBinding::bind)
|
||||
@@ -34,60 +29,78 @@ class AllergenSheet(
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.apply {
|
||||
try {
|
||||
// Retrieve offer as Parcelable from arguments bundle
|
||||
val offer: CanteenOfferGroupElement = arguments.getParcelableCompat("offer")
|
||||
|
||||
// Category header
|
||||
textCategory.text = getString(R.string.sheet_category, category)
|
||||
// Retrieve category string
|
||||
val category = arguments?.getString("category") ?: ""
|
||||
|
||||
// Offer text
|
||||
textTitle.text = offer.title
|
||||
// Retrieve preference on whether the user wants preferences to be coloured
|
||||
val displayColours = arguments?.getBoolean("preferenceColour") == true
|
||||
|
||||
// Iterate through all dietary preferences
|
||||
offer.dietaryPreferences.toList().forEachIndexed { index, c ->
|
||||
// If a preference is met, inflate a view to display it
|
||||
if (c == 't') {
|
||||
// Inflate the view
|
||||
val prefLine = ItemSheetPreferenceBinding.inflate(LayoutInflater.from(context))
|
||||
binding.apply {
|
||||
|
||||
val (stringId, drawableId, colourId) = DietaryPreferences.getData(index)
|
||||
// Category header
|
||||
textCategory.text = getString(R.string.sheet_category, category)
|
||||
|
||||
// Add the localised text for the preference
|
||||
prefLine.preferenceText.text = getString(stringId)
|
||||
// Offer text
|
||||
textTitle.text = offer.title
|
||||
|
||||
// Set the appropriate icon
|
||||
prefLine.preferenceImage.setImageDrawable(
|
||||
getDrawable(
|
||||
context,
|
||||
drawableId,
|
||||
// Iterate through all dietary preferences
|
||||
offer.dietaryPreferences.toList().forEachIndexed { index, c ->
|
||||
// If a preference is met, inflate a view to display it
|
||||
if (c == 't') {
|
||||
// Inflate the view
|
||||
val prefLine =
|
||||
ItemSheetPreferenceBinding.inflate(LayoutInflater.from(context))
|
||||
|
||||
val (stringId, drawableId, colourId) = DietaryPreferences.getData(index)
|
||||
|
||||
// Add the localised text for the preference
|
||||
prefLine.preferenceText.text = getString(stringId)
|
||||
|
||||
// Set the appropriate icon
|
||||
prefLine.preferenceImage.setImageDrawable(
|
||||
getDrawable(
|
||||
context,
|
||||
drawableId,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
// Set tint of the icon; themed to the preference, if the user has the option enabled
|
||||
prefLine.preferenceImage.imageTintList = ColorStateList.valueOf(
|
||||
context.theme.getThemedColor(
|
||||
if (displayColours) {
|
||||
colourId
|
||||
} else {
|
||||
R.attr.colorText
|
||||
}
|
||||
// Set tint of the icon; themed to the preference, if the user has the option enabled
|
||||
prefLine.preferenceImage.imageTintList = ColorStateList.valueOf(
|
||||
context.theme.getThemedColor(
|
||||
if (displayColours) {
|
||||
colourId
|
||||
} else {
|
||||
R.attr.colorText
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
// Add the view to the sheet's view container
|
||||
containerPreferences.addView(prefLine.root)
|
||||
// Add the view to the sheet's view container
|
||||
containerPreferences.addView(prefLine.root)
|
||||
}
|
||||
}
|
||||
|
||||
// Allergen and additive notice
|
||||
textContent.text = offer.allergens.compileAllergenString()
|
||||
|
||||
// Show a price, if one is available
|
||||
if (offer.price.isBlank()) {
|
||||
textPrice.visibility = View.GONE
|
||||
} else {
|
||||
textPrice.visibility = View.VISIBLE
|
||||
textPrice.text = offer.price
|
||||
}
|
||||
}
|
||||
} catch (e: ParcelNotFoundException) {
|
||||
// Tell the user that something went wrong when retrieving Parcelable
|
||||
showToast(context, getString(R.string.canteen_page_allergen_sheet_error))
|
||||
|
||||
// Allergen and additive notice
|
||||
textContent.text = offer.allergens.compileAllergenString()
|
||||
|
||||
// Show a price, if one is available
|
||||
if (offer.price.isBlank()) {
|
||||
textPrice.visibility = View.GONE
|
||||
} else {
|
||||
textPrice.visibility = View.VISIBLE
|
||||
textPrice.text = offer.price
|
||||
}
|
||||
// Close the sheet
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,36 +5,27 @@ import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.util.Base64
|
||||
import android.view.View
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.denizk0461.studip.R
|
||||
import com.denizk0461.studip.activity.ImageActivity
|
||||
import com.denizk0461.studip.data.showToast
|
||||
import com.denizk0461.studip.data.viewBinding
|
||||
import com.denizk0461.studip.databinding.SheetDevCodeBinding
|
||||
import com.denizk0461.studip.viewmodel.DevCodeViewModel
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
/**
|
||||
* Sheet that presents the user / developer with a text field to input developer codes / cheat
|
||||
* codes.
|
||||
*
|
||||
* @param nukeEvents deletes all events
|
||||
* @param nukeOfferItems deletes all canteen items
|
||||
* @param nukeOfferCategories deletes all canteen categories
|
||||
* @param nukeOfferCanteens deletes all canteens
|
||||
* @param nukeOfferDates deletes all canteen dates
|
||||
* @param nukeEverything deletes everything
|
||||
*/
|
||||
class DevCodeSheet(
|
||||
private val nukeEvents: () -> Unit,
|
||||
private val nukeOfferItems: () -> Unit,
|
||||
private val nukeOfferCategories: () -> Unit,
|
||||
private val nukeOfferCanteens: () -> Unit,
|
||||
private val nukeOfferDates: () -> Unit,
|
||||
private val nukeEverything: () -> Unit,
|
||||
) : AppSheet(R.layout.sheet_dev_code) {
|
||||
class DevCodeSheet : AppSheet(R.layout.sheet_dev_code) {
|
||||
|
||||
// View binding
|
||||
private val binding: SheetDevCodeBinding by viewBinding(SheetDevCodeBinding::bind)
|
||||
|
||||
// View model
|
||||
private val viewModel: DevCodeViewModel by viewModels()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
@@ -81,27 +72,27 @@ class DevCodeSheet(
|
||||
})
|
||||
}
|
||||
"NEVENT" -> { // nuke events
|
||||
nukeEvents()
|
||||
viewModel.nukeEvents()
|
||||
showToast(context, "Nuked all events")
|
||||
}
|
||||
"NCANTE" -> { // nuke canteens
|
||||
nukeOfferCanteens()
|
||||
viewModel.nukeOfferCanteens()
|
||||
showToast(context, "Nuked all canteens")
|
||||
}
|
||||
"NDATES" -> { // nuke dates
|
||||
nukeOfferDates()
|
||||
viewModel.nukeOfferDates()
|
||||
showToast(context, "Nuked all dates")
|
||||
}
|
||||
"NCATEG" -> { // nuke categories
|
||||
nukeOfferCategories()
|
||||
viewModel.nukeOfferCategories()
|
||||
showToast(context, "Nuked all categories")
|
||||
}
|
||||
"NITEMS" -> { // nuke items
|
||||
nukeOfferItems()
|
||||
viewModel.nukeOfferItems()
|
||||
showToast(context, "Nuked all items")
|
||||
}
|
||||
"NEVERY" -> { // nuke everything
|
||||
nukeEverything()
|
||||
viewModel.nukeEverything()
|
||||
showToast(context, "Nuked everything")
|
||||
}
|
||||
else -> showToast(context, "Code is invalid")
|
||||
|
||||
@@ -4,8 +4,10 @@ import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.transition.TransitionManager
|
||||
import com.denizk0461.studip.R
|
||||
import com.denizk0461.studip.data.getParcelableCompat
|
||||
import com.denizk0461.studip.data.getTimestampAcademicQuarterEnd
|
||||
import com.denizk0461.studip.data.getTimestampAcademicQuarterStart
|
||||
import com.denizk0461.studip.data.parseToMinutes
|
||||
@@ -15,136 +17,152 @@ import com.denizk0461.studip.data.viewBinding
|
||||
import com.denizk0461.studip.databinding.SheetScheduleUpdateBinding
|
||||
import com.denizk0461.studip.dialog.TimePickerFragment
|
||||
import com.denizk0461.studip.exception.AcademicQuarterNotApplicableException
|
||||
import com.denizk0461.studip.exception.ParcelNotFoundException
|
||||
import com.denizk0461.studip.model.StudIPEvent
|
||||
import com.denizk0461.studip.viewmodel.ScheduleUpdateViewModel
|
||||
|
||||
/**
|
||||
* Update sheet to allow the user to edit attributes for a specific schedule event.
|
||||
*
|
||||
* @param event event to be updated
|
||||
* @param onUpdate action to execute to update the event
|
||||
* @param onDelete action to execute to delete the event
|
||||
*/
|
||||
class ScheduleUpdateSheet(
|
||||
private val event: StudIPEvent,
|
||||
private val onUpdate: (event: StudIPEvent) -> Unit,
|
||||
private val onDelete: (event: StudIPEvent) -> Unit,
|
||||
) : AppSheet(R.layout.sheet_schedule_update), TimePickerFragment.OnTimeSetListener {
|
||||
class ScheduleUpdateSheet : AppSheet(R.layout.sheet_schedule_update), TimePickerFragment.OnTimeSetListener {
|
||||
|
||||
// Editable fields
|
||||
private var timeslotStart = event.timeslotStart
|
||||
private var timeslotEnd = event.timeslotEnd
|
||||
private var colour = event.colour
|
||||
private var timeslotStart = ""
|
||||
private var timeslotEnd = ""
|
||||
private var colour = -1
|
||||
|
||||
// View binding
|
||||
private val binding: SheetScheduleUpdateBinding by viewBinding(SheetScheduleUpdateBinding::bind)
|
||||
|
||||
// View model
|
||||
private val viewModel: ScheduleUpdateViewModel by viewModels()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
// Set editable text fields
|
||||
binding.editTextTitle.setText(event.title)
|
||||
binding.editTextLecturers.setText(event.lecturer)
|
||||
binding.editTextRoom.setText(event.room)
|
||||
try {
|
||||
// Retrieve event from arguments bundle
|
||||
val event: StudIPEvent = arguments.getParcelableCompat("event")
|
||||
|
||||
/*
|
||||
* Show academic quarter suggestion if it is applicable. For this to be the case, both the
|
||||
* start timestamp and the end timestamp must match up in a pattern that would make it
|
||||
* likely for the course to use the academic quarter. Example:
|
||||
* 14:00 - 16:00 -> likely 14:15 - 15:45
|
||||
*
|
||||
* 13:00 - 15:30 -> likely no academic quarter intended
|
||||
*/
|
||||
binding.buttonAcademicQuarter.visibility = if (
|
||||
timeslotsAcademicQuarter.contains(timeslotStart) &&
|
||||
timeslotsAcademicQuarter.contains(timeslotEnd)
|
||||
) {
|
||||
binding.buttonAcademicQuarter.setOnClickListener {
|
||||
try {
|
||||
// Retrieve new timestamps with the academic quarter applied, or throw a tantrum
|
||||
val newStart = getTimestampAcademicQuarterStart(timeslotStart)
|
||||
val newEnd = getTimestampAcademicQuarterEnd(timeslotEnd)
|
||||
// Set values of the text field to that of the event
|
||||
timeslotStart = event.timeslotStart
|
||||
timeslotEnd = event.timeslotEnd
|
||||
colour = event.colour
|
||||
|
||||
// Set the buttons to the new timesatmps
|
||||
timeslotStart = newStart
|
||||
binding.buttonTimeStart.text = newStart
|
||||
timeslotEnd = newEnd
|
||||
binding.buttonTimeEnd.text = newEnd
|
||||
// Set editable text fields
|
||||
binding.editTextTitle.setText(event.title)
|
||||
binding.editTextLecturers.setText(event.lecturer)
|
||||
binding.editTextRoom.setText(event.room)
|
||||
|
||||
/*
|
||||
/*
|
||||
* Show academic quarter suggestion if it is applicable. For this to be the case, both the
|
||||
* start timestamp and the end timestamp must match up in a pattern that would make it
|
||||
* likely for the course to use the academic quarter. Example:
|
||||
* 14:00 - 16:00 -> likely 14:15 - 15:45
|
||||
*
|
||||
* 13:00 - 15:30 -> likely no academic quarter intended
|
||||
*/
|
||||
binding.buttonAcademicQuarter.visibility = if (
|
||||
timeslotsAcademicQuarter.contains(timeslotStart) &&
|
||||
timeslotsAcademicQuarter.contains(timeslotEnd)
|
||||
) {
|
||||
binding.buttonAcademicQuarter.setOnClickListener {
|
||||
try {
|
||||
// Retrieve new timestamps with the academic quarter applied, or throw a tantrum
|
||||
val newStart = getTimestampAcademicQuarterStart(timeslotStart)
|
||||
val newEnd = getTimestampAcademicQuarterEnd(timeslotEnd)
|
||||
|
||||
// Set the buttons to the new timesatmps
|
||||
timeslotStart = newStart
|
||||
binding.buttonTimeStart.text = newStart
|
||||
timeslotEnd = newEnd
|
||||
binding.buttonTimeEnd.text = newEnd
|
||||
|
||||
/*
|
||||
* Attempt to fix the issue of the bottom sheet jumping up when hiding the
|
||||
* button.
|
||||
*/
|
||||
TransitionManager.beginDelayedTransition(binding.sheet.parent as ViewGroup)
|
||||
binding.buttonAcademicQuarter.visibility = View.GONE
|
||||
TransitionManager.beginDelayedTransition(binding.sheet.parent as ViewGroup)
|
||||
binding.buttonAcademicQuarter.visibility = View.GONE
|
||||
|
||||
// Catch if a timeslot couldn't be found in the list, and tell the user
|
||||
} catch (e: AcademicQuarterNotApplicableException) {
|
||||
showToast(context, getString(R.string.sheet_schedule_update_hint_quarter_error))
|
||||
// Catch if a timeslot couldn't be found in the list, and tell the user
|
||||
} catch (e: AcademicQuarterNotApplicableException) {
|
||||
showToast(
|
||||
context,
|
||||
getString(R.string.sheet_schedule_update_hint_quarter_error)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// If the pattern applies, show the button to the user
|
||||
View.VISIBLE
|
||||
} else {
|
||||
// Hide the button if the action is not necessary or applicable
|
||||
View.GONE
|
||||
}
|
||||
|
||||
// If the pattern applies, show the button to the user
|
||||
View.VISIBLE
|
||||
} else {
|
||||
// Hide the button if the action is not necessary or applicable
|
||||
View.GONE
|
||||
}
|
||||
// Prepare timestamp buttons
|
||||
binding.buttonTimeStart.text = timeslotStart
|
||||
binding.buttonTimeStart.setOnClickListener {
|
||||
// Launch a time picker dialogue to pick a new start timestamp
|
||||
TimePickerFragment(
|
||||
binding.buttonTimeStart.text.toString(),
|
||||
this,
|
||||
true,
|
||||
).show((context as FragmentActivity).supportFragmentManager, "timePicker")
|
||||
}
|
||||
binding.buttonTimeEnd.text = timeslotEnd
|
||||
binding.buttonTimeEnd.setOnClickListener {
|
||||
// Launch a time picker dialogue to pick a new end timestamp
|
||||
TimePickerFragment(
|
||||
binding.buttonTimeEnd.text.toString(),
|
||||
this,
|
||||
false,
|
||||
).show((context as FragmentActivity).supportFragmentManager, "timePicker")
|
||||
}
|
||||
|
||||
// Prepare timestamp buttons
|
||||
binding.buttonTimeStart.text = timeslotStart
|
||||
binding.buttonTimeStart.setOnClickListener {
|
||||
// Launch a time picker dialogue to pick a new start timestamp
|
||||
TimePickerFragment(
|
||||
binding.buttonTimeStart.text.toString(),
|
||||
this,
|
||||
true,
|
||||
).show((context as FragmentActivity).supportFragmentManager, "timePicker")
|
||||
}
|
||||
binding.buttonTimeEnd.text = timeslotEnd
|
||||
binding.buttonTimeEnd.setOnClickListener {
|
||||
// Launch a time picker dialogue to pick a new end timestamp
|
||||
TimePickerFragment(
|
||||
binding.buttonTimeEnd.text.toString(),
|
||||
this,
|
||||
false,
|
||||
).show((context as FragmentActivity).supportFragmentManager, "timePicker")
|
||||
}
|
||||
/*
|
||||
* TODO implement option to change the colour for the course - single-selection coloured
|
||||
* filter buttons with checkmarks when they're selected maybe?
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO implement option to change the colour for the course - single-selection coloured
|
||||
* filter buttons with checkmarks when they're selected maybe?
|
||||
*/
|
||||
// Prepare cancel button
|
||||
binding.buttonCancel.setOnClickListener {
|
||||
// Do nothing and dismiss the sheet
|
||||
dismiss()
|
||||
}
|
||||
|
||||
// Prepare cancel button
|
||||
binding.buttonCancel.setOnClickListener {
|
||||
// Do nothing and dismiss the sheet
|
||||
dismiss()
|
||||
}
|
||||
// Prepare delete button
|
||||
binding.buttonDelete.setOnClickListener {
|
||||
viewModel.delete(event)
|
||||
// Dismiss the sheet upon deletion
|
||||
dismiss()
|
||||
}
|
||||
|
||||
// Prepare delete button
|
||||
binding.buttonDelete.setOnClickListener {
|
||||
onDelete(event)
|
||||
// Dismiss the sheet upon deletion
|
||||
dismiss()
|
||||
}
|
||||
|
||||
// Prepare update/save button
|
||||
binding.buttonSave.setOnClickListener {
|
||||
onUpdate(
|
||||
// construct new StudIPEvent from the data the user may have edited
|
||||
StudIPEvent(
|
||||
eventId = event.eventId,
|
||||
title = binding.editTextTitle.text.toString(),
|
||||
lecturer = binding.editTextLecturers.text.toString(),
|
||||
room = binding.editTextRoom.text.toString(),
|
||||
day = event.day,
|
||||
timeslotStart = timeslotStart,
|
||||
timeslotEnd = timeslotEnd,
|
||||
timeslotId = timeslotStart.parseToMinutes(),
|
||||
colour = colour,
|
||||
// Prepare update/save button
|
||||
binding.buttonSave.setOnClickListener {
|
||||
viewModel.update(
|
||||
// construct new StudIPEvent from the data the user may have edited
|
||||
StudIPEvent(
|
||||
eventId = event.eventId,
|
||||
title = binding.editTextTitle.text.toString(),
|
||||
lecturer = binding.editTextLecturers.text.toString(),
|
||||
room = binding.editTextRoom.text.toString(),
|
||||
day = event.day,
|
||||
timeslotStart = timeslotStart,
|
||||
timeslotEnd = timeslotEnd,
|
||||
timeslotId = timeslotStart.parseToMinutes(),
|
||||
colour = colour,
|
||||
)
|
||||
)
|
||||
)
|
||||
// Dismiss the sheet upon update
|
||||
// Dismiss the sheet upon update
|
||||
dismiss()
|
||||
}
|
||||
} catch (e: ParcelNotFoundException) {
|
||||
// Tell the user that something went wrong when retrieving Parcelable
|
||||
showToast(context, getString(R.string.event_update_sheet_error))
|
||||
|
||||
// Close the sheet
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,8 @@ import com.denizk0461.studip.databinding.SheetTextBinding
|
||||
|
||||
/**
|
||||
* Bottom sheet used for displaying any sort of text to the user.
|
||||
*
|
||||
* @param header headline for the window
|
||||
* @param content content text for the window
|
||||
*/
|
||||
class TextSheet(
|
||||
private val header: String,
|
||||
private val content: String,
|
||||
) : AppSheet(R.layout.sheet_text) {
|
||||
class TextSheet : AppSheet(R.layout.sheet_text) {
|
||||
|
||||
// View binding
|
||||
private val binding: SheetTextBinding by viewBinding(SheetTextBinding::bind)
|
||||
@@ -23,6 +17,12 @@ class TextSheet(
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
// Retrieve headline for the window
|
||||
val header = arguments?.getString("header") ?: ""
|
||||
|
||||
// Retrieve content for the window
|
||||
val content = arguments?.getString("content") ?: ""
|
||||
|
||||
// Set text values
|
||||
binding.apply {
|
||||
textHeader.text = header
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.denizk0461.studip.viewmodel
|
||||
|
||||
import android.app.Application
|
||||
import com.denizk0461.studip.model.AllergenPreferences
|
||||
import com.denizk0461.studip.model.SettingsPreferences
|
||||
|
||||
class AllergenConfigViewModel(application: Application) : AppViewModel(application) {
|
||||
|
||||
/**
|
||||
* This value determines which allergens the user wants to have displayed or hidden.
|
||||
*/
|
||||
var preferenceAllergenConfig: String
|
||||
get() = repo.getStringPreference(
|
||||
SettingsPreferences.ALLERGEN_CONFIG, defaultValue = AllergenPreferences.TEMPLATE
|
||||
)
|
||||
set(newValue) { repo.setPreference(SettingsPreferences.ALLERGEN_CONFIG, newValue) }
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.denizk0461.studip.viewmodel
|
||||
|
||||
import android.app.Application
|
||||
|
||||
class DevCodeViewModel(application: Application) : AppViewModel(application) {
|
||||
|
||||
/**
|
||||
* Deletes everything from the database.
|
||||
*/
|
||||
fun nukeEverything() {
|
||||
nukeEvents()
|
||||
nukeOfferItems()
|
||||
nukeOfferCategories()
|
||||
nukeOfferCanteens()
|
||||
nukeOfferDates()
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all Stud.IP events from the database.
|
||||
*/
|
||||
fun nukeEvents() { doAsync { repo.nukeEvents() } }
|
||||
|
||||
/**
|
||||
* Deletes all canteen items from the database.
|
||||
*/
|
||||
fun nukeOfferItems() { doAsync { repo.nukeOfferItems() } }
|
||||
|
||||
/**
|
||||
* Deletes all canteen categories from the database.
|
||||
*/
|
||||
fun nukeOfferCategories() { doAsync { repo.nukeOfferCategories() } }
|
||||
|
||||
/**
|
||||
* Deletes all canteens from the database.
|
||||
*/
|
||||
fun nukeOfferCanteens() { doAsync { repo.nukeOfferCanteens() } }
|
||||
|
||||
/**
|
||||
* Deletes all canteen dates from the database.
|
||||
*/
|
||||
fun nukeOfferDates() { doAsync { repo.nukeOfferDates() } }
|
||||
}
|
||||
@@ -17,18 +17,4 @@ class EventPageViewModel(app: Application) : AppViewModel(app) {
|
||||
* @return Stud.IP events for a certain day exposed through a LiveData object
|
||||
*/
|
||||
fun getEventsForDay(day: Int): LiveData<List<StudIPEvent>> = repo.getEventsForDay(day)
|
||||
|
||||
/**
|
||||
* Updates a schedule element.
|
||||
*
|
||||
* @param event the event to update
|
||||
*/
|
||||
fun update(event: StudIPEvent) { doAsync { repo.update(event) } }
|
||||
|
||||
/**
|
||||
* Deletes a schedule element.
|
||||
*
|
||||
* @param event the event to delete
|
||||
*/
|
||||
fun delete(event: StudIPEvent) { doAsync { repo.delete(event) } }
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.denizk0461.studip.viewmodel
|
||||
|
||||
import android.app.Application
|
||||
import com.denizk0461.studip.model.StudIPEvent
|
||||
|
||||
class ScheduleUpdateViewModel(application: Application) : AppViewModel(application) {
|
||||
|
||||
/**
|
||||
* Updates a schedule element.
|
||||
*
|
||||
* @param event the event to update
|
||||
*/
|
||||
fun update(event: StudIPEvent) { doAsync { repo.update(event) } }
|
||||
|
||||
/**
|
||||
* Deletes a schedule element.
|
||||
*
|
||||
* @param event the event to delete
|
||||
*/
|
||||
fun delete(event: StudIPEvent) { doAsync { repo.delete(event) } }
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.denizk0461.studip.viewmodel
|
||||
|
||||
import android.app.Application
|
||||
import com.denizk0461.studip.model.AllergenPreferences
|
||||
import com.denizk0461.studip.model.SettingsPreferences
|
||||
|
||||
/**
|
||||
@@ -11,44 +10,6 @@ import com.denizk0461.studip.model.SettingsPreferences
|
||||
*/
|
||||
class SettingsViewModel(app: Application) : AppViewModel(app) {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Deletes everything from the database.
|
||||
*/
|
||||
fun nukeEverything() {
|
||||
nukeEvents()
|
||||
nukeOfferItems()
|
||||
nukeOfferCategories()
|
||||
nukeOfferCanteens()
|
||||
nukeOfferDates()
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes all Stud.IP events from the database.
|
||||
*/
|
||||
fun nukeEvents() { doAsync { repo.nukeEvents() } }
|
||||
|
||||
/**
|
||||
* Deletes all canteen items from the database.
|
||||
*/
|
||||
fun nukeOfferItems() { doAsync { repo.nukeOfferItems() } }
|
||||
|
||||
/**
|
||||
* Deletes all canteen categories from the database.
|
||||
*/
|
||||
fun nukeOfferCategories() { doAsync { repo.nukeOfferCategories() } }
|
||||
|
||||
/**
|
||||
* Deletes all canteens from the database.
|
||||
*/
|
||||
fun nukeOfferCanteens() { doAsync { repo.nukeOfferCanteens() } }
|
||||
|
||||
/**
|
||||
* Deletes all canteen dates from the database.
|
||||
*/
|
||||
fun nukeOfferDates() { doAsync { repo.nukeOfferDates() } }
|
||||
|
||||
/**
|
||||
* This value determines whether the user wants to have the next course in their schedule
|
||||
* highlighted.
|
||||
@@ -57,15 +18,6 @@ class SettingsViewModel(app: Application) : AppViewModel(app) {
|
||||
get() = repo.getBooleanPreference(SettingsPreferences.COURSE_HIGHLIGHTING)
|
||||
set(newValue) { repo.setPreference(SettingsPreferences.COURSE_HIGHLIGHTING, newValue) }
|
||||
|
||||
/**
|
||||
* This value determines which allergens the user wants to have displayed or hidden.
|
||||
*/
|
||||
var preferenceAllergenConfig: String
|
||||
get() = repo.getStringPreference(
|
||||
SettingsPreferences.ALLERGEN_CONFIG, defaultValue = AllergenPreferences.TEMPLATE
|
||||
)
|
||||
set(newValue) { repo.setPreference(SettingsPreferences.ALLERGEN_CONFIG, newValue) }
|
||||
|
||||
/**
|
||||
* This value determines whether the user wants to have allergens marked.
|
||||
*/
|
||||
|
||||
@@ -58,6 +58,8 @@
|
||||
<string name="cafeteria_bhv">Cafeteria Bremerhaven</string>
|
||||
<string name="mensa_hfk">Interimsmensa HfK</string>
|
||||
|
||||
<string name="event_update_sheet_error">Beim Laden dieses Eintrages ist ein Fehler aufgetreten.</string>
|
||||
|
||||
<!-- dietary preferences -->
|
||||
<string name="pref_fair">Artgerecht</string>
|
||||
<string name="pref_fish">Fisch</string>
|
||||
@@ -115,6 +117,7 @@
|
||||
|
||||
<string name="allergens_none">Enthält weder Allergene noch Zusatzstoffe.</string>
|
||||
<string name="allergens_contains">Enthält: %s.</string>
|
||||
<string name="canteen_page_allergen_sheet_error">Beim Laden dieses Angebots ist ein Fehler aufgetreten.</string>
|
||||
|
||||
<string name="nav_schedule">Stundenplan</string>
|
||||
<string name="nav_food">Mensa</string>
|
||||
@@ -154,7 +157,7 @@
|
||||
<string name="settings_data_title">Was passiert mit meinen Daten?</string>
|
||||
<string name="settings_data_subtitle">Stiehlst du meinen Stud.IP-Login?</string>
|
||||
<string name="settings_data_sheet_header">TL;DR: nein, aber Google könnte mir Bescheid geben, falls die App mal abstürzt.</string>
|
||||
<string name="settings_data_sheet_content">Die App funktioniert standalone, was bedeutet, dass sie sich niemals mit einem Server verbindet, der mir gehört. Sie ist ein Web-Scraper, also ein Programm, welches eine Internetseite öffnet und dann all die Informationen dieser Webseite herunterlädt und analysiert. In diesem Fall sind es die Webseiten der Mensen und Cafeterien des Studierendenwerks Bremen (stw-bremen.de) sowie die Stud.IP-Seite (elearning.uni-bremen.de).\n\nDies funktioniert relativ einfach für die Essenspläne, da diese Pläne öffentlich zugänglich sind. Um jedoch Deinen persönlichen Stud.IP-Stundenplan herunterzuladen, braucht die App Zugriff auf diese Webseite während Dein Account eingeloggt ist. Dies erfolgt, indem die App Dich mit deinem Account einloggen lässt - dies geschieht, wenn Du den Knopf zum Aktualisieren des Plans drückst und die App Dir die Login-Seite zeigt - und Du dann den Knopf klickst, um den Inhalt, den HTML-Quellcode, herunterzuladen. Der HTML-Quellcode beinhält Informationen darüber, was auf einer Webseite angezeigt wird und wie es aussehen soll, aber er kann niemals persönliche Details beinhalten, wie zum Beispiel Passwörter oder andere Daten, die auf Deinem Gerät vorhanden sind.\n\nDer Quellcode wird dann lokal, also auf Deinem Gerät, zu den Karten verarbeitet, die Du dann in der App sehen kannst, ohne, dass jegliche Daten irgendwohin geschickt werden müssten.\n\nEinige Daten könnten jedoch dennoch nach außen geschickt werden. Diese App nutzt \"Crashlytics\" von Google. Dies ist ein Tool, welches Absturzreporte an Google-Server schickt, wenn in der App etwas schief läuft. Diese werden genutzt, um Probleme in der App zu lösen.\n\nDies ist jedoch gemäß europäischer Datenschutz-Grundverordnung Opt-In, was bedeutet, dass Du zustimmen musst, bevor Daten nach außen geschickt werden. Du wurdest danach gefragt, als Du die App zum ersten Mal gestartet hast, und du kannst jederzeit deine Meinung ändern, indem Du den Schalter hierfür in den Einstellungen umstellst. Solltest Du dich entscheiden, keine Daten verschicken zu lassen, wird auch nichts mit Google (und mir) geteilt.\n\nSolltest du dich versichern wollen, dass wirklich keine Daten an irgendwelche Server verschickt wird (abgesehen von den Absturzreports an Google), kannst Du jederzeit das Projekt erkunden, da es Open-Source und auf meinen GitHub-Profil öffentlich zugänglich ist:\nhttps://github.com/denizk0461/studip-timetable/\n\nSchreib mir ansonsten gerne eine E-Mail:\ndenizk0461+kyzil@gmail.com</string>
|
||||
<string name="settings_data_sheet_content">Die App funktioniert standalone, was bedeutet, dass sie sich niemals mit einem Server verbindet, der mir gehört. Sie ist ein Web-Scraper, also ein Programm, welches eine Internetseite öffnet und dann all die Informationen dieser Webseite herunterlädt und analysiert. In diesem Fall sind es die Webseiten der Mensen und Cafeterien des Studierendenwerks Bremen (stw-bremen.de) sowie die Stud.IP-Seite (elearning.uni-bremen.de).\n\nDies funktioniert relativ einfach für die Essenspläne, da diese Pläne öffentlich zugänglich sind. Um jedoch Deinen persönlichen Stud.IP-Stundenplan herunterzuladen, braucht die App Zugriff auf diese Webseite während Dein Account eingeloggt ist. Dies erfolgt, indem die App Dich mit deinem Account einloggen lässt - dies geschieht, wenn Du den Knopf zum Aktualisieren des Plans drückst und die App Dir die Login-Seite zeigt - und Du dann den Knopf klickst, um den Inhalt, den HTML-Quellcode, herunterzuladen. Der HTML-Quellcode beinhält Informationen darüber, was auf einer Webseite angezeigt wird und wie es aussehen soll, aber er kann niemals persönliche Details beinhalten, wie zum Beispiel Passwörter oder andere Daten, die auf Deinem Gerät vorhanden sind.\n\nDer Quellcode wird dann lokal, also auf Deinem Gerät, zu den Karten verarbeitet, die Du dann in der App sehen kannst, ohne, dass jegliche Daten irgendwohin geschickt werden müssten.\n\nEinige Daten könnten jedoch dennoch nach außen geschickt werden. Diese App nutzt \"Crashlytics\" von Google. Dies ist ein Tool, welches Absturzreporte an Google-Server schickt, wenn in der App etwas schief läuft. Diese werden genutzt, um Probleme in der App zu lösen.\n\nDies ist jedoch gemäß europäischer Datenschutz-Grundverordnung Opt-In, was bedeutet, dass Du zustimmen musst, bevor Daten nach außen geschickt werden. Du wurdest danach gefragt, als Du die App zum ersten Mal gestartet hast, und du kannst jederzeit deine Meinung ändern, indem Du den Schalter hierfür in den Einstellungen umstellst. Solltest Du dich entscheiden, keine Daten verschicken zu lassen, wird auch nichts mit Google (und mir) geteilt.\n\nSolltest du dich versichern wollen, dass wirklich keine Daten an irgendwelche Server verschickt wird (abgesehen von den Absturzreports an Google), kannst Du jederzeit das Projekt erkunden, da es Open-Source und auf meinen GitHub-Profil öffentlich zugänglich ist:\nhttps://github.com/denizk0461/studip-timetable/\n\nSchreib mir ansonsten gerne eine E-Mail:\ndenizk0461@gmail.com</string>
|
||||
|
||||
<string name="settings_licences_title">Siehe Lizenzen</string>
|
||||
<string name="settings_licences_subtitle">Ressourcen, die diese App möglich gemacht haben</string>
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
|
||||
<string name="sheet_category" translatable="false">[ %s ]</string>
|
||||
<string name="question_mark" translatable="false">\?</string>
|
||||
<string name="event_update_sheet_error">An error occurred while trying to retrieve this event.</string>
|
||||
|
||||
<!-- dietary preferences -->
|
||||
<string name="pref_fair">Animal Welfare</string> <!-- TODO is this really the best name? what about 'animal welfare'? -->
|
||||
@@ -120,6 +121,7 @@
|
||||
|
||||
<string name="allergens_none">Contains no allergens or additives.</string>
|
||||
<string name="allergens_contains">Contains: %s.</string>
|
||||
<string name="canteen_page_allergen_sheet_error">An error occurred while trying to retrieve this offer.</string>
|
||||
|
||||
<string name="nav_schedule">Schedule</string>
|
||||
<string name="nav_food">Canteens</string>
|
||||
@@ -159,7 +161,7 @@
|
||||
<string name="settings_data_title">What happens with my data?</string>
|
||||
<string name="settings_data_subtitle">Will you steal my Stud.IP login?</string>
|
||||
<string name="settings_data_sheet_header">TL;DR: no, but Google may let me know if the app crashes on your device.</string>
|
||||
<string name="settings_data_sheet_content">This app works standalone, which is to say, it doesn\'t ever connect to a server I own. Instead, it is a web scraper, which means that it opens a website and then downloads and analyses all the data from that website by itself. In this case, those websites are the canteen websites of the Studierendenwerk Bremen (stw-bremen.de) and the Stud.IP page (elearning.uni-bremen.de).\n\nThis works fairly easily for the canteen offers, since the plans are public and anyone can access them. However, to access your personal Stud.IP schedule, the app needs access to that website, with your account logged in. This is done by letting you log into the website by yourself (which happens when you click the button to refresh the schedule and the app opens the login page) and then clicking a button to download the content, the HTML source code, of the website. The HTML source code contains information about which elements are shown on the website and how they look, but it can never contain your personal details such as passwords, or any other sensitive data you may store on your device.\n\nThe HTML source is then processed locally on your device, which means that your device will handle converting the HTML source to the cards you will be shown in the app by itself, without needing to send any data anywhere.\n\nHowever, some data may still be sent outside of your device. This app uses \"Crashlytics\" by Google, which is a tool that sends crash reports to Google servers if something breaks. These are used to fix problems that occur in the app.\n\nThis, in compliance with the European General Data Protection Regulation, is of course opt-in, which means that you need to accept this before any data is sent outside of your device. You have been prompted for this when you first started the app, and you can always change your mind in the app settings by clicking the corresponding switch. Should you choose to not share crash data with Google (and me), no data will be sent outside of your device.\n\nShould you want to reassure yourself that no data is sent to any servers (outside of the crash reports from Google), feel free to explore the project, since it is open-source and documented on my GitHub profile:\nhttps://github.com/denizk0461/studip-timetable/\n\nYou\'re also welcome to send me an email:\ndenizk0461+kyzil@gmail.com</string>
|
||||
<string name="settings_data_sheet_content">This app works standalone, which is to say, it doesn\'t ever connect to a server I own. Instead, it is a web scraper, which means that it opens a website and then downloads and analyses all the data from that website by itself. In this case, those websites are the canteen websites of the Studierendenwerk Bremen (stw-bremen.de) and the Stud.IP page (elearning.uni-bremen.de).\n\nThis works fairly easily for the canteen offers, since the plans are public and anyone can access them. However, to access your personal Stud.IP schedule, the app needs access to that website, with your account logged in. This is done by letting you log into the website by yourself (which happens when you click the button to refresh the schedule and the app opens the login page) and then clicking a button to download the content, the HTML source code, of the website. The HTML source code contains information about which elements are shown on the website and how they look, but it can never contain your personal details such as passwords, or any other sensitive data you may store on your device.\n\nThe HTML source is then processed locally on your device, which means that your device will handle converting the HTML source to the cards you will be shown in the app by itself, without needing to send any data anywhere.\n\nHowever, some data may still be sent outside of your device. This app uses \"Crashlytics\" by Google, which is a tool that sends crash reports to Google servers if something breaks. These are used to fix problems that occur in the app.\n\nThis, in compliance with the European General Data Protection Regulation, is of course opt-in, which means that you need to accept this before any data is sent outside of your device. You have been prompted for this when you first started the app, and you can always change your mind in the app settings by clicking the corresponding switch. Should you choose to not share crash data with Google (and me), no data will be sent outside of your device.\n\nShould you want to reassure yourself that no data is sent to any servers (outside of the crash reports from Google), feel free to explore the project, since it is open-source and documented on my GitHub profile:\nhttps://github.com/denizk0461/studip-timetable/\n\nYou\'re also welcome to send me an email:\ndenizk0461@gmail.com</string>
|
||||
|
||||
<string name="settings_licences_title">View licences</string>
|
||||
<string name="settings_licences_subtitle">Resources that made this app possible</string>
|
||||
|
||||
+2
-1
@@ -22,4 +22,5 @@ kotlin.code.style=official
|
||||
# thereby reducing the size of the R class for that library
|
||||
android.nonTransitiveRClass=true
|
||||
android.defaults.buildfeatures.buildconfig=true
|
||||
android.nonFinalResIds=false
|
||||
android.nonFinalResIds=false
|
||||
org.gradle.unsafe.configuration-cache=true
|
||||
Reference in New Issue
Block a user