Moved development codes from DevCodeSheet.kt to a (by default) hidden section of SettingsFragment.kt; added further information about the build in that section

This commit is contained in:
denizk0461
2023-05-13 19:31:27 +02:00
parent 7ed230b4b9
commit 2798e0ecbb
9 changed files with 390 additions and 199 deletions
@@ -1,12 +1,15 @@
package com.denizk0461.weserplaner.fragment
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Base64
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import androidx.fragment.app.setFragmentResultListener
import androidx.fragment.app.viewModels
import com.denizk0461.weserplaner.BuildConfig
@@ -14,11 +17,12 @@ import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.activity.FetcherActivity
import com.denizk0461.weserplaner.activity.ImageActivity
import com.denizk0461.weserplaner.data.getTextSheet
import com.denizk0461.weserplaner.data.showSnackBar
import com.denizk0461.weserplaner.data.showToast
import com.denizk0461.weserplaner.databinding.FragmentSettingsBinding
import com.denizk0461.weserplaner.sheet.AllergenConfigSheet
import com.denizk0461.weserplaner.sheet.DevCodeSheet
import com.denizk0461.weserplaner.viewmodel.SettingsViewModel
import java.nio.charset.StandardCharsets
import java.text.SimpleDateFormat
import java.util.*
@@ -45,6 +49,9 @@ class SettingsFragment : AppFragment() {
// Click counter on the app version button
private var appVersionClick = 1
// Whether the user has set the text of the allergen setting to its alt text
private var hasSetAllergensAltText = false
// 222
private val mysteryLink = "https://www.youtube.com/watch?v=nhIQMCXJzLI"
@@ -57,6 +64,8 @@ class SettingsFragment : AppFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// --- schedule settings --- //
// Launch the Stud.IP schedule fetcher activity
binding.buttonRefreshSchedule.setOnClickListener {
launchWebView()
@@ -78,6 +87,8 @@ class SettingsFragment : AppFragment() {
}
}
// --- canteen offer settings --- //
// Set up button to set allergens
binding.buttonAllergensConfig.setOnClickListener {
openBottomSheet(
@@ -95,6 +106,7 @@ class SettingsFragment : AppFragment() {
)
}
// Set text according to how many allergens the user has set
binding.allergensConfigSubtitle.text = getAllergensConfigCountText()
// Set up switch for displaying allergens
@@ -105,13 +117,19 @@ 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
// }
// }
// Change text on allergens setting
binding.settingsAllergensSubtitleView.setOnLongClickListener {
if (hasSetAllergensAltText) {
binding.settingsAllergensTitleView.text = getString(R.string.settings_allergens_title)
binding.settingsAllergensSubtitleView.text = getString(R.string.settings_allergens_subtitle)
hasSetAllergensAltText = false
} else {
binding.settingsAllergensTitleView.text = getString(R.string.settings_allergens_title_alt)
binding.settingsAllergensSubtitleView.text = getString(R.string.settings_allergens_subtitle_alt)
hasSetAllergensAltText = true
}
true
}
// Set up button toggle group for changing prices displayed for the canteen offers
binding.togglePricingGroup.apply {
@@ -139,6 +157,8 @@ class SettingsFragment : AppFragment() {
}
}
// --- miscellaneous settings --- //
// Set up button toggle group for changing default fragment
binding.toggleLaunchFragmentGroup.apply {
// Check the fragment that is currently selected
@@ -207,10 +227,21 @@ class SettingsFragment : AppFragment() {
)
}
// Set long click listener for licences button to open dev code sheet
// Set long click listener for licences button to unlock experimental settings
binding.buttonLicences.setOnLongClickListener {
// Return false if the experimental settings are already enabled
if (viewModel.preferenceExperimentalSettingsEnabled) return@setOnLongClickListener false
// Unlock experimental settings after 3 long presses
if (licencesLongClick > 3) {
openBottomSheet(DevCodeSheet())
// openBottomSheet(DevCodeSheet())
licencesLongClick = 0
viewModel.preferenceExperimentalSettingsEnabled = true
binding.cardExperimentalSettings.visibility = View.VISIBLE
context.theme.showSnackBar(
binding.coordinatorLayout,
getString(R.string.settings_unlocked_experiments),
)
} else {
licencesLongClick += 1
}
@@ -273,15 +304,130 @@ class SettingsFragment : AppFragment() {
*/
@SuppressLint("SetTextI18n")
binding.appVersionText.text =
"${BuildConfig.VERSION_NAME}-${
if (BuildConfig.DEBUG)
"dev-[${SimpleDateFormat("yyyy-MM-dd, HH:mm:ss.SSS", Locale.GERMANY)
.format(Date(BuildConfig.BUILD_TIME_MILLIS))}]"
else
"release"
}"
"${BuildConfig.VERSION_NAME}-${if (BuildConfig.DEBUG) "dev" else "release"}"
// --- experimental settings --- //
// Set visibility of experimental settings depending on whether they have been unlocked
binding.cardExperimentalSettings.visibility = if (
viewModel.preferenceExperimentalSettingsEnabled
) {
View.VISIBLE
} else {
View.GONE
}
binding.buttonHideExperiments.setOnClickListener {
viewModel.preferenceExperimentalSettingsEnabled = false
binding.cardExperimentalSettings.visibility = View.GONE
context.theme.showSnackBar(
binding.coordinatorLayout,
getString(R.string.settings_hide_experiments),
)
}
// Set build version code and time text
@SuppressLint("SetTextI18n")
binding.buildTimeText.text = "v${BuildConfig.VERSION_CODE} | ${
SimpleDateFormat("yyyy-MM-dd, HH:mm:ss.SSS", Locale.GERMANY)
.format(Date(BuildConfig.BUILD_TIME_MILLIS))
}"
binding.buttonDevCodes.setOnClickListener {
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(view.windowToken, 0)
when (binding.inputDevCode.text.toString().uppercase()) {
"U1RST0JF".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS90S2k5Wi1mNnFYNA==".d64)
"U1BJUklU".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9XN25lMzlEU05TZw==".d64)
"Q0xPVURT".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9rbUJ6YTRhNTB2dw==".d64)
"NjQxODJL".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9EbTFyZ285UHBUcw==".d64)
"U0FJTE9S".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9QUHlDYXZ6OG5NWQ==".d64)
"SE9ORVNU".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9DSEg0OE5LUEFraw==".d64)
"QkJVT0s/".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS90Rm1PMm1TY0tHNA==".d64)
"SUhUU0Mq".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS85bXZ4SVdhWHZuWQ==".d64)
"SU5TQU5F".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS90NE9kYTlUZFYwbw==".d64)
"SE9SSVpO".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9SUVpUUy1CWjhtcw==".d64)
"TUFSR0Uh".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS8tbHFxRHZXRjQ1dw==".d64)
"UE9XRUxM".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9XUGMtVkVxQlBISQ==".d64)
"Q0FMTE1F".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS8xbTV1WnJNMnktMA==".d64)
"SkFNSVJP".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9fMVZoT2c0N3ozNA==".d64)
"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()
bundle.putString("img", "Qk9KQUNL".d64.lowercase())
intent.putExtras(bundle)
})
}
"QkNFTExT".d64 -> {
startActivity(Intent(context, ImageActivity::class.java).also { intent ->
val bundle = Bundle()
bundle.putString("img", "QkNFTExT".d64.lowercase())
intent.putExtras(bundle)
})
}
"NEVENT" -> { // nuke events
viewModel.nukeEvents()
showToast(context, "Nuked all events")
}
"NCANTE" -> { // nuke canteens
viewModel.nukeOfferCanteens()
showToast(context, "Nuked all canteens")
}
"NDATES" -> { // nuke dates
viewModel.nukeOfferDates()
showToast(context, "Nuked all dates")
}
"NCATEG" -> { // nuke categories
viewModel.nukeOfferCategories()
showToast(context, "Nuked all categories")
}
"NITEMS" -> { // nuke items
viewModel.nukeOfferItems()
showToast(context, "Nuked all items")
}
"NEVERY" -> { // nuke everything
viewModel.nukeEverything()
showToast(context, "Nuked everything")
}
else -> context.theme.showSnackBar(
binding.coordinatorLayout,
getString(R.string.settings_dev_codes_invalid)
)
}
}
}
/**
* Launches a web link.
*
* @param link link to open
*/
private fun launchLink(link: String) {
// Let the user know they accomplished something with their life
showToast(context, "")
// Give the user a slight dopamine boost
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(link)))
}
/**
* Decodes Base64 to a regular string.
*
* @return the decoded string
*/
private val String.d64: String get() = String(
Base64.decode(this, Base64.DEFAULT),
StandardCharsets.UTF_8
)
// Invalidate the view binding
override fun onDestroyView() {
super.onDestroyView()
@@ -63,5 +63,10 @@ enum class SettingsPreferences(val key: String) {
* Whether the user has opened the canteen fragment before.
*/
HAS_OPENED_CANTEEN("has_opened_canteen"),
/**
* Whether the user has enabled experimental settings.
*/
EXPERIMENTAL_ENABLED("experimental_enabled"),
;
}
@@ -1,139 +0,0 @@
package com.denizk0461.weserplaner.sheet
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Base64
import android.view.View
import androidx.fragment.app.viewModels
import com.denizk0461.weserplaner.R
import com.denizk0461.weserplaner.activity.ImageActivity
import com.denizk0461.weserplaner.data.showToast
import com.denizk0461.weserplaner.data.viewBinding
import com.denizk0461.weserplaner.databinding.SheetDevCodeBinding
import com.denizk0461.weserplaner.viewmodel.DevCodeViewModel
import java.nio.charset.StandardCharsets
/**
* Sheet that presents the user / developer with a text field to input developer codes / cheat
* codes.
*/
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)
// Execute an action based on the input
binding.buttonConfirm.setOnClickListener {
/*
* Codes are implemented here.
*
* About the inks; they are safe (which is suspicious of me to say), just encoded so
* people can't just look at the file and figure out all the codes! Of course, they're
* easily decoded, but who would go for that? You would have to have a lot of time to
* waste to do that. Then again, I was the one who encoded all of these links in the
* first place, so I suppose the joke's on me...
*
* If you're reading this, I ask you why?
*/
when (binding.input.text.toString().uppercase()) {
"U1RST0JF".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS90S2k5Wi1mNnFYNA==".d64)
"U1BJUklU".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9XN25lMzlEU05TZw==".d64)
"Q0xPVURT".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9rbUJ6YTRhNTB2dw==".d64)
"NjQxODJL".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9EbTFyZ285UHBUcw==".d64)
"U0FJTE9S".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9QUHlDYXZ6OG5NWQ==".d64)
"SE9ORVNU".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9DSEg0OE5LUEFraw==".d64)
"QkJVT0s/".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS90Rm1PMm1TY0tHNA==".d64)
"SUhUU0Mq".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS85bXZ4SVdhWHZuWQ==".d64)
"SU5TQU5F".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS90NE9kYTlUZFYwbw==".d64)
"SE9SSVpO".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9SUVpUUy1CWjhtcw==".d64)
"TUFSR0Uh".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS8tbHFxRHZXRjQ1dw==".d64)
"UE9XRUxM".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9XUGMtVkVxQlBISQ==".d64)
"Q0FMTE1F".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS8xbTV1WnJNMnktMA==".d64)
"SkFNSVJP".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9fMVZoT2c0N3ozNA==".d64)
"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()
bundle.putString("img", "Qk9KQUNL".d64.lowercase())
intent.putExtras(bundle)
})
}
"QkNFTExT".d64 -> {
startActivity(Intent(context, ImageActivity::class.java).also { intent ->
val bundle = Bundle()
bundle.putString("img", "QkNFTExT".d64.lowercase())
intent.putExtras(bundle)
})
}
"NEVENT" -> { // nuke events
viewModel.nukeEvents()
showToast(context, "Nuked all events")
}
"NCANTE" -> { // nuke canteens
viewModel.nukeOfferCanteens()
showToast(context, "Nuked all canteens")
}
"NDATES" -> { // nuke dates
viewModel.nukeOfferDates()
showToast(context, "Nuked all dates")
}
"NCATEG" -> { // nuke categories
viewModel.nukeOfferCategories()
showToast(context, "Nuked all categories")
}
"NITEMS" -> { // nuke items
viewModel.nukeOfferItems()
showToast(context, "Nuked all items")
}
"NEVERY" -> { // nuke everything
viewModel.nukeEverything()
showToast(context, "Nuked everything")
}
else -> showToast(context, "Code is invalid")
}
dismiss()
}
// Set up close button
binding.buttonCancel.setOnClickListener {
// Do nothing and dismiss the sheet
dismiss()
}
}
/**
* Launches a web link.
*
* @param link link to open
*/
private fun launchLink(link: String) {
// Let the user know they accomplished something with their life
showToast(context, "")
// Give the user a slight dopamine boost
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(link)))
}
/**
* Decodes Base64 to a regular string.
*
* @return the decoded string
*/
private val String.d64: String get() = String(
Base64.decode(this, Base64.DEFAULT),
StandardCharsets.UTF_8
)
}
@@ -1,42 +0,0 @@
package com.denizk0461.weserplaner.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() } }
}
@@ -78,4 +78,49 @@ class SettingsViewModel(app: Application) : AppViewModel(app) {
var preferenceDataHandling: Boolean
get() = repo.getBooleanPreference(SettingsPreferences.DATA_HANDLING)
set(newValue) { repo.setPreference(SettingsPreferences.DATA_HANDLING, newValue) }
/**
* This value determines whether the user has enabled experimental settings.
*/
var preferenceExperimentalSettingsEnabled: Boolean
get() = repo.getBooleanPreference(SettingsPreferences.EXPERIMENTAL_ENABLED)
set(newValue) { repo.setPreference(SettingsPreferences.EXPERIMENTAL_ENABLED, newValue) }
// --- functions for dev codes --- //
/**
* 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() } }
}
@@ -0,0 +1,6 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M6.41,6l-1.41,1.41l4.58,4.59l-4.58,4.59l1.41,1.41l6,-6z"/>
<path android:fillColor="@android:color/white" android:pathData="M13,6l-1.41,1.41l4.58,4.59l-4.58,4.59l1.41,1.41l6,-6z"/>
</vector>
+153 -1
View File
@@ -3,6 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".fragment.SettingsFragment"
android:id="@+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
@@ -37,7 +38,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="8dp">
android:paddingBottom="8dp"
android:animateLayoutChanges="true">
<!-- Stud.IP schedule settings -->
<com.google.android.material.card.MaterialCardView
@@ -262,6 +264,7 @@
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/settings_allergens_title_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/lato_bolditalic"
@@ -269,6 +272,7 @@
android:textSize="16sp" />
<TextView
android:id="@+id/settings_allergens_subtitle_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings_allergens_subtitle"
@@ -595,6 +599,154 @@
</com.google.android.material.card.MaterialCardView>
<!-- development settings -->
<com.google.android.material.card.MaterialCardView
android:id="@+id/card_experimental_settings"
style="@style/Widget.Material3.CardView.Outlined"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="8dp"
android:layout_marginVertical="4dp">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:fontFamily="@font/lato_bolditalic"
android:text="@string/settings_experimental"
android:textSize="22sp" />
<com.google.android.material.divider.MaterialDivider
style="@style/DividerTheme"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"/>
<!-- Hide experiments -->
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/button_hide_experiments"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/selectable_item_background"
android:clickable="true"
android:focusable="true"
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_hide_experiments_title"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings_hide_experiments_subtitle"
android:textSize="16sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- Build time -->
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/button_build_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/selectable_item_background"
android:clickable="true"
android:focusable="true"
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_build_time"
android:textSize="16sp" />
<TextView
android:id="@+id/build_time_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<!-- Dev codes -->
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/selectable_item_background"
android:clickable="true"
android:focusable="true"
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_dev_codes_title"
android:textSize="16sp" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.Material3.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="4"
android:layout_marginEnd="8dp"
android:hint="@string/settings_dev_codes_hint">
<com.google.android.material.textfield.TextInputEditText
style="@style/Widget.Material3.TextInputEditText.OutlinedBox"
android:maxLines="1"
android:maxLength="6"
android:id="@+id/input_dev_code"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:fontFamily="@font/ibm_regular"
android:inputType="textNoSuggestions"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
style="@style/Widget.Material3.Button.IconButton.Outlined"
android:id="@+id/button_dev_codes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="0dp"
app:icon="@drawable/double_arrow_right"
app:iconPadding="0dp"
app:strokeColor="?attr/colorOutlineVariant"
app:iconTint="?attr/colorOnSurfaceVariant"/>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</com.google.android.material.card.MaterialCardView>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.core.widget.NestedScrollView>
+3
View File
@@ -169,6 +169,7 @@
<string name="settings_schedule">Stud.IP-Stundenplan</string>
<string name="settings_canteen">Mensenangebote</string>
<string name="settings_misc">Sonstiges</string>
<string name="settings_experimental">Experimentelles</string>
<string name="refresh_schedule_title">Aktualisiere deinen Stud.IP-Stundenplan</string>
<string name="refresh_schedule_subtitle">Dies wird alle Anpassungen löschen!</string>
@@ -194,6 +195,8 @@
<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_allergens_title_alt">App entwickelt von denizk0461</string>
<string name="settings_allergens_subtitle_alt">Danke, dass du meine App nutzt ☺︎♡</string>
<string name="settings_launch_canteen_title">Wähle, mit welchem Bildschirm die App startet</string>
+15
View File
@@ -173,6 +173,7 @@
<string name="settings_schedule">Stud.IP Schedule</string>
<string name="settings_canteen">Canteen Offers</string>
<string name="settings_misc">Miscellaneous</string>
<string name="settings_experimental">Experimental</string>
<string name="refresh_schedule_title">Refresh your Stud.IP schedule</string>
<string name="refresh_schedule_subtitle">This will clear any customisations!</string>
@@ -198,6 +199,8 @@
<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_allergens_title_alt">App developed by denizk0461</string>
<string name="settings_allergens_subtitle_alt">Thank you for using my app ☺︎♡</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 -->
@@ -215,11 +218,23 @@
<string name="settings_licences_title">View licences</string>
<string name="settings_licences_subtitle">Resources that made this app possible</string>
<string name="settings_unlocked_experiments" translatable="false">Experimental settings have been unlocked.</string>
<string name="settings_hide_experiments" translatable="false">Experimental settings have been hidden.</string>
<string name="sheet_cheat_header" translatable="false">Cheat Codes</string>
<string name="settings_app_version">App Version</string>
<string name="settings_hide_experiments_title" translatable="false">Hide experimental settings</string>
<string name="settings_hide_experiments_subtitle" translatable="false">Show them again via licences button</string>
<string name="settings_build_time" translatable="false">Gradle build code &amp; time</string>
<string name="settings_dev_codes_title" translatable="false">Development codes</string>
<string name="settings_dev_codes_hint" translatable="false">6 chars</string>
<string name="settings_dev_codes_button" translatable="false"></string>
<string name="settings_dev_codes_invalid" translatable="false">This code could not be found.</string>
<string name="settings_app_version_15">keep clicking</string>
<string name="settings_app_version_20" translatable="false">^_^</string>
<string name="settings_app_version_30" translatable="false">^_____^</string>