Archived
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:
@@ -1,12 +1,15 @@
|
|||||||
package com.denizk0461.weserplaner.fragment
|
package com.denizk0461.weserplaner.fragment
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Base64
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.view.inputmethod.InputMethodManager
|
||||||
import androidx.fragment.app.setFragmentResultListener
|
import androidx.fragment.app.setFragmentResultListener
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import com.denizk0461.weserplaner.BuildConfig
|
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.FetcherActivity
|
||||||
import com.denizk0461.weserplaner.activity.ImageActivity
|
import com.denizk0461.weserplaner.activity.ImageActivity
|
||||||
import com.denizk0461.weserplaner.data.getTextSheet
|
import com.denizk0461.weserplaner.data.getTextSheet
|
||||||
|
import com.denizk0461.weserplaner.data.showSnackBar
|
||||||
import com.denizk0461.weserplaner.data.showToast
|
import com.denizk0461.weserplaner.data.showToast
|
||||||
import com.denizk0461.weserplaner.databinding.FragmentSettingsBinding
|
import com.denizk0461.weserplaner.databinding.FragmentSettingsBinding
|
||||||
import com.denizk0461.weserplaner.sheet.AllergenConfigSheet
|
import com.denizk0461.weserplaner.sheet.AllergenConfigSheet
|
||||||
import com.denizk0461.weserplaner.sheet.DevCodeSheet
|
|
||||||
import com.denizk0461.weserplaner.viewmodel.SettingsViewModel
|
import com.denizk0461.weserplaner.viewmodel.SettingsViewModel
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -45,6 +49,9 @@ class SettingsFragment : AppFragment() {
|
|||||||
// Click counter on the app version button
|
// Click counter on the app version button
|
||||||
private var appVersionClick = 1
|
private var appVersionClick = 1
|
||||||
|
|
||||||
|
// Whether the user has set the text of the allergen setting to its alt text
|
||||||
|
private var hasSetAllergensAltText = false
|
||||||
|
|
||||||
// 222
|
// 222
|
||||||
private val mysteryLink = "https://www.youtube.com/watch?v=nhIQMCXJzLI"
|
private val mysteryLink = "https://www.youtube.com/watch?v=nhIQMCXJzLI"
|
||||||
|
|
||||||
@@ -57,6 +64,8 @@ class SettingsFragment : AppFragment() {
|
|||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
// --- schedule settings --- //
|
||||||
|
|
||||||
// Launch the Stud.IP schedule fetcher activity
|
// Launch the Stud.IP schedule fetcher activity
|
||||||
binding.buttonRefreshSchedule.setOnClickListener {
|
binding.buttonRefreshSchedule.setOnClickListener {
|
||||||
launchWebView()
|
launchWebView()
|
||||||
@@ -78,6 +87,8 @@ class SettingsFragment : AppFragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- canteen offer settings --- //
|
||||||
|
|
||||||
// Set up button to set allergens
|
// Set up button to set allergens
|
||||||
binding.buttonAllergensConfig.setOnClickListener {
|
binding.buttonAllergensConfig.setOnClickListener {
|
||||||
openBottomSheet(
|
openBottomSheet(
|
||||||
@@ -95,6 +106,7 @@ class SettingsFragment : AppFragment() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set text according to how many allergens the user has set
|
||||||
binding.allergensConfigSubtitle.text = getAllergensConfigCountText()
|
binding.allergensConfigSubtitle.text = getAllergensConfigCountText()
|
||||||
|
|
||||||
// Set up switch for displaying allergens
|
// Set up switch for displaying allergens
|
||||||
@@ -105,13 +117,19 @@ class SettingsFragment : AppFragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up switch for launching the app with a specific view
|
// Change text on allergens setting
|
||||||
// binding.switchLaunchCanteen.apply {
|
binding.settingsAllergensSubtitleView.setOnLongClickListener {
|
||||||
// isChecked = viewModel.preferenceLaunchCanteen
|
if (hasSetAllergensAltText) {
|
||||||
// setOnCheckedChangeListener { _, newValue ->
|
binding.settingsAllergensTitleView.text = getString(R.string.settings_allergens_title)
|
||||||
// viewModel.preferenceLaunchCanteen = newValue
|
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
|
// Set up button toggle group for changing prices displayed for the canteen offers
|
||||||
binding.togglePricingGroup.apply {
|
binding.togglePricingGroup.apply {
|
||||||
@@ -139,6 +157,8 @@ class SettingsFragment : AppFragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- miscellaneous settings --- //
|
||||||
|
|
||||||
// Set up button toggle group for changing default fragment
|
// Set up button toggle group for changing default fragment
|
||||||
binding.toggleLaunchFragmentGroup.apply {
|
binding.toggleLaunchFragmentGroup.apply {
|
||||||
// Check the fragment that is currently selected
|
// 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 {
|
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) {
|
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 {
|
} else {
|
||||||
licencesLongClick += 1
|
licencesLongClick += 1
|
||||||
}
|
}
|
||||||
@@ -273,15 +304,130 @@ class SettingsFragment : AppFragment() {
|
|||||||
*/
|
*/
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
binding.appVersionText.text =
|
binding.appVersionText.text =
|
||||||
"${BuildConfig.VERSION_NAME}-${
|
"${BuildConfig.VERSION_NAME}-${if (BuildConfig.DEBUG) "dev" else "release"}"
|
||||||
if (BuildConfig.DEBUG)
|
|
||||||
"dev-[${SimpleDateFormat("yyyy-MM-dd, HH:mm:ss.SSS", Locale.GERMANY)
|
// --- experimental settings --- //
|
||||||
.format(Date(BuildConfig.BUILD_TIME_MILLIS))}]"
|
|
||||||
else
|
// Set visibility of experimental settings depending on whether they have been unlocked
|
||||||
"release"
|
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
|
// Invalidate the view binding
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
|||||||
@@ -63,5 +63,10 @@ enum class SettingsPreferences(val key: String) {
|
|||||||
* Whether the user has opened the canteen fragment before.
|
* Whether the user has opened the canteen fragment before.
|
||||||
*/
|
*/
|
||||||
HAS_OPENED_CANTEEN("has_opened_canteen"),
|
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
|
var preferenceDataHandling: Boolean
|
||||||
get() = repo.getBooleanPreference(SettingsPreferences.DATA_HANDLING)
|
get() = repo.getBooleanPreference(SettingsPreferences.DATA_HANDLING)
|
||||||
set(newValue) { repo.setPreference(SettingsPreferences.DATA_HANDLING, newValue) }
|
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>
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:context=".fragment.SettingsFragment"
|
tools:context=".fragment.SettingsFragment"
|
||||||
|
android:id="@+id/coordinator_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
@@ -37,7 +38,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingBottom="8dp">
|
android:paddingBottom="8dp"
|
||||||
|
android:animateLayoutChanges="true">
|
||||||
|
|
||||||
<!-- Stud.IP schedule settings -->
|
<!-- Stud.IP schedule settings -->
|
||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.card.MaterialCardView
|
||||||
@@ -262,6 +264,7 @@
|
|||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/settings_allergens_title_view"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fontFamily="@font/lato_bolditalic"
|
android:fontFamily="@font/lato_bolditalic"
|
||||||
@@ -269,6 +272,7 @@
|
|||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
android:id="@+id/settings_allergens_subtitle_view"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/settings_allergens_subtitle"
|
android:text="@string/settings_allergens_subtitle"
|
||||||
@@ -595,6 +599,154 @@
|
|||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</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.appcompat.widget.LinearLayoutCompat>
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|||||||
@@ -169,6 +169,7 @@
|
|||||||
<string name="settings_schedule">Stud.IP-Stundenplan</string>
|
<string name="settings_schedule">Stud.IP-Stundenplan</string>
|
||||||
<string name="settings_canteen">Mensenangebote</string>
|
<string name="settings_canteen">Mensenangebote</string>
|
||||||
<string name="settings_misc">Sonstiges</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_title">Aktualisiere deinen Stud.IP-Stundenplan</string>
|
||||||
<string name="refresh_schedule_subtitle">Dies wird alle Anpassungen löschen!</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_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_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>
|
<string name="settings_launch_canteen_title">Wähle, mit welchem Bildschirm die App startet</string>
|
||||||
|
|
||||||
|
|||||||
@@ -173,6 +173,7 @@
|
|||||||
<string name="settings_schedule">Stud.IP Schedule</string>
|
<string name="settings_schedule">Stud.IP Schedule</string>
|
||||||
<string name="settings_canteen">Canteen Offers</string>
|
<string name="settings_canteen">Canteen Offers</string>
|
||||||
<string name="settings_misc">Miscellaneous</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_title">Refresh your Stud.IP schedule</string>
|
||||||
<string name="refresh_schedule_subtitle">This will clear any customisations!</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_title">Mark offers with allergens with a star*</string>
|
||||||
<string name="settings_allergens_subtitle">Also applies to additives</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_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_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_title">View licences</string>
|
||||||
<string name="settings_licences_subtitle">Resources that made this app possible</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="sheet_cheat_header" translatable="false">Cheat Codes</string>
|
||||||
|
|
||||||
<string name="settings_app_version">App Version</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 & 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_15">keep clicking</string>
|
||||||
<string name="settings_app_version_20" translatable="false">^_^</string>
|
<string name="settings_app_version_20" translatable="false">^_^</string>
|
||||||
<string name="settings_app_version_30" translatable="false">^_____^</string>
|
<string name="settings_app_version_30" translatable="false">^_____^</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user