diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a5e3a03..639819f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,6 +17,7 @@ diff --git a/app/src/main/java/com/denizk0461/studip/activity/FetcherActivity.kt b/app/src/main/java/com/denizk0461/studip/activity/FetcherActivity.kt index 9e17573..3b9a353 100644 --- a/app/src/main/java/com/denizk0461/studip/activity/FetcherActivity.kt +++ b/app/src/main/java/com/denizk0461/studip/activity/FetcherActivity.kt @@ -6,6 +6,7 @@ import android.os.Bundle import android.webkit.WebResourceRequest import android.webkit.WebView import android.webkit.WebViewClient +import android.widget.Toast import androidx.lifecycle.ViewModelProvider import com.denizk0461.studip.R import com.denizk0461.studip.data.showErrorSnackBar @@ -60,38 +61,37 @@ class FetcherActivity : Activity() { binding.webview.loadUrl("https://elearning.uni-bremen.de/index.php?again=yes") binding.fab.setOnClickListener { view -> - /* - * Retrieve encoded HTML via JavaScript function. Encoding is done as otherwise not all - * symbols will be accurately fetched. - */ - binding.webview.evaluateJavascript( - "(function(){return encodeURI(document.getElementsByTagName('html')[0].innerHTML)})();" - ) { p0 -> - try { - // Decode HTML and parse it into a list of StudIPEvent.kt - // TODO this exception handling and finish() is broken - viewModel.parse(URLDecoder.decode(p0, "UTF-8")) -// StudIPParser(application).parse(URLDecoder.decode(p0, "UTF-8")) { events -> -// -// // Delete all previously fetched elements -//// viewModel.nukeEvents() -//// viewModel.replaceEvents(events) -// -// // Insert the list into the database -//// viewModel.insertEvents(events) -// -// // Notify the user that the fetch was successful -// Toast.makeText( -// this, R.string.toast_fetch_finished, Toast.LENGTH_SHORT -// ).show() -// -// // Close the activity -// finish() -// } - } catch (e: IOException) { - // Let the user know that an error occurred - theme.showErrorSnackBar(binding.rootView, getString(R.string.fetch_error_snack)) + + if (binding.webview.url?.contains( + "https://elearning.uni-bremen.de/dispatch.php/calendar/schedule" + ) == true) { + /* + * Retrieve encoded HTML via JavaScript function. Encoding is done as otherwise not all + * symbols will be accurately fetched. + */ + binding.webview.evaluateJavascript( + "(function(){return encodeURI(document.getElementsByTagName('html')[0].innerHTML)})();" + ) { p0 -> + try { + // Decode HTML and parse it into a list of StudIPEvent.kt + // TODO add a tutorial for the user to know what to do + viewModel.parse(URLDecoder.decode(p0, "UTF-8")) + + // Notify the user that the fetch was successful + Toast.makeText( + this, R.string.toast_fetch_finished, Toast.LENGTH_SHORT + ).show() + + // Close the activity + finish() + + } catch (e: IOException) { + // Let the user know that an error occurred + theme.showErrorSnackBar(binding.rootView, getString(R.string.fetch_error_snack)) + } } + } else { + theme.showErrorSnackBar(binding.rootView, getString(R.string.fetch_error_webpage_snack)) } } } diff --git a/app/src/main/java/com/denizk0461/studip/adapter/CanteenOfferItemAdapter.kt b/app/src/main/java/com/denizk0461/studip/adapter/CanteenOfferItemAdapter.kt index 360ec5c..6d4ce94 100644 --- a/app/src/main/java/com/denizk0461/studip/adapter/CanteenOfferItemAdapter.kt +++ b/app/src/main/java/com/denizk0461/studip/adapter/CanteenOfferItemAdapter.kt @@ -1,5 +1,6 @@ package com.denizk0461.studip.adapter +import android.content.res.ColorStateList import android.view.LayoutInflater import android.view.ViewGroup import androidx.appcompat.content.res.AppCompatResources @@ -7,6 +8,7 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.denizk0461.studip.R import com.denizk0461.studip.data.AppDiffUtilCallback +import com.denizk0461.studip.data.getThemedColor import com.denizk0461.studip.databinding.ItemCanteenBinding import com.denizk0461.studip.databinding.ItemCanteenLineBinding import com.denizk0461.studip.databinding.ItemIconBinding @@ -19,10 +21,12 @@ import com.denizk0461.studip.model.DietaryPreferences * * @param onClickListener used for listening to clicks and long presses * @param displayAllergens whether the user wants allergens to be marked + * @param displayColours whether the user wants dietary preferences to be marked with colours */ class CanteenOfferItemAdapter( private val onClickListener: OnClickListener, private val displayAllergens: Boolean, + private val displayColours: Boolean, ) : RecyclerView.Adapter() { private val offers: MutableList = mutableListOf() @@ -79,7 +83,8 @@ class CanteenOfferItemAdapter( // Inflate a new icon holder val img = ItemIconBinding.inflate(LayoutInflater.from(holder.binding.root.context)) - val (_, drawableId) = DietaryPreferences.getData(DietaryPreferences.ERROR.ordinal) + // Retrieve data for the dietary preference + val (_, drawableId, colourId) = DietaryPreferences.getData(DietaryPreferences.ERROR.ordinal) // Set a cross icon img.imageView.setImageDrawable( @@ -89,6 +94,17 @@ class CanteenOfferItemAdapter( ) ) + // Set tint of the icon; themed to the preference, if the user has the option enabled + img.imageView.imageTintList = ColorStateList.valueOf( + holder.binding.root.context.theme.getThemedColor( + if (displayColours) { + colourId + } else { + R.attr.colorText + } + ) + ) + // Bind the new icon to the line view line.imageViewContainer.addView(img.root) @@ -130,7 +146,8 @@ class CanteenOfferItemAdapter( // Inflate a new icon holder val img = ItemIconBinding.inflate(LayoutInflater.from(holder.binding.root.context)) - val (_, drawableId) = DietaryPreferences.getData(index) + // Retrieve data for the dietary preference + val (_, drawableId, colourId) = DietaryPreferences.getData(index) // Set the appropriate icon img.imageView.setImageDrawable( @@ -140,6 +157,17 @@ class CanteenOfferItemAdapter( ) ) + // Set tint of the icon + img.imageView.imageTintList = ColorStateList.valueOf( + holder.binding.root.context.theme.getThemedColor( + if (displayColours) { + colourId + } else { + R.attr.colorText + } + ) + ) + // Bind the new icon to the line view line.imageViewContainer.addView(img.root) } diff --git a/app/src/main/java/com/denizk0461/studip/data/StudIPParser.kt b/app/src/main/java/com/denizk0461/studip/data/StudIPParser.kt index caef527..978a9e3 100644 --- a/app/src/main/java/com/denizk0461/studip/data/StudIPParser.kt +++ b/app/src/main/java/com/denizk0461/studip/data/StudIPParser.kt @@ -5,6 +5,7 @@ import com.denizk0461.studip.db.AppRepository import com.denizk0461.studip.model.StudIPEvent import org.jsoup.Jsoup import java.io.IOException +import kotlin.jvm.Throws /** * Parser class used for fetching and collecting scheduled events from a Stud.IP timetable. @@ -17,11 +18,10 @@ class StudIPParser(application: Application) { * Parse a given HTML string. HTML must be of a Stud.IP timetable. * * @param html website content of the Stud.IP timetable - * @param insert action call to save the contents to persistent storage * @throws IOException when an error in fetching or the database transaction occurs */ - @kotlin.jvm.Throws(IOException::class) - fun parse(html: String, insert: (events: List) -> Unit) { + @Throws(IOException::class) + fun parse(html: String) { // Primary key value to uniquely identify entries in the database var id = 0 diff --git a/app/src/main/java/com/denizk0461/studip/fragment/CanteenFragment.kt b/app/src/main/java/com/denizk0461/studip/fragment/CanteenFragment.kt index 0381efa..34008df 100644 --- a/app/src/main/java/com/denizk0461/studip/fragment/CanteenFragment.kt +++ b/app/src/main/java/com/denizk0461/studip/fragment/CanteenFragment.kt @@ -72,7 +72,7 @@ class CanteenFragment : AppFragment() { binding.buttonCanteenPicker.text = getCurrentlySelectedCanteenName() // Display to the user that the canteen plan will be refreshed -// binding.swipeRefreshLayout.isRefreshing = true + binding.swipeRefreshLayout.isRefreshing = true // Refresh the canteen menu for the newly selected canteen refresh() diff --git a/app/src/main/java/com/denizk0461/studip/fragment/CanteenPageFragment.kt b/app/src/main/java/com/denizk0461/studip/fragment/CanteenPageFragment.kt index 583b948..e9d5d7e 100644 --- a/app/src/main/java/com/denizk0461/studip/fragment/CanteenPageFragment.kt +++ b/app/src/main/java/com/denizk0461/studip/fragment/CanteenPageFragment.kt @@ -54,6 +54,7 @@ class CanteenPageFragment( recyclerViewAdapter = CanteenOfferItemAdapter( this, viewModel.preferenceAllergen, + viewModel.preferenceColour, ) binding.recyclerView.apply { @@ -62,13 +63,6 @@ class CanteenPageFragment( context, LinearLayoutManager.VERTICAL, false ) - /* - * Create new adapter for every page. Attribute position denotes day that will be set up - * by the newly created adapter (0 = Monday, 4 = Friday) - * TODO check if the filtered list is empty, and tell the user if it is - */ -// val o = offers.filter { it.dateId == currentDay } - adapter = recyclerViewAdapter // Animate creation of new page @@ -78,7 +72,6 @@ class CanteenPageFragment( offerList.clear() offerList.addAll(offers) recyclerViewAdapter.setNewData(offers.filterElements().groupElements().distinct()) -// filterList() } } @@ -192,7 +185,7 @@ class CanteenPageFragment( * @param offer item that has been clicked */ override fun onClick(offer: CanteenOfferGroupElement, category: String) { - openBottomSheet(AllergenSheet(offer, category)) + openBottomSheet(AllergenSheet(offer, category, viewModel.preferenceColour)) } /** diff --git a/app/src/main/java/com/denizk0461/studip/fragment/SettingsFragment.kt b/app/src/main/java/com/denizk0461/studip/fragment/SettingsFragment.kt index 63d7812..245c376 100644 --- a/app/src/main/java/com/denizk0461/studip/fragment/SettingsFragment.kt +++ b/app/src/main/java/com/denizk0461/studip/fragment/SettingsFragment.kt @@ -79,6 +79,14 @@ class SettingsFragment : AppFragment() { } } + // Set up switch for colouring dietary preferences + binding.switchPrefColour.apply { + isChecked = viewModel.preferenceColour + setOnCheckedChangeListener { _, newValue -> + viewModel.preferenceColour = newValue + } + } + // Set up switch for crash report opt-in binding.switchCrashlytics.apply { isChecked = viewModel.preferenceDataHandling diff --git a/app/src/main/java/com/denizk0461/studip/model/DietaryPreferences.kt b/app/src/main/java/com/denizk0461/studip/model/DietaryPreferences.kt index 4d34e1a..b3c9389 100644 --- a/app/src/main/java/com/denizk0461/studip/model/DietaryPreferences.kt +++ b/app/src/main/java/com/denizk0461/studip/model/DietaryPreferences.kt @@ -167,21 +167,21 @@ enum class DietaryPreferences(val value: String) { * string and drawable values. * * @param index ordinal of the enum item - * @return string resource ID and drawable resource ID as a pair + * @return string resource ID, drawable resource ID, colour attribute ID */ - fun getData(index: Int): Pair = when (index) { - WELFARE.ordinal -> Pair(R.string.pref_fair, R.drawable.handshake) - FISH.ordinal -> Pair(R.string.pref_fish, R.drawable.fish) - POULTRY.ordinal -> Pair(R.string.pref_poultry, R.drawable.chicken) - LAMB.ordinal -> Pair(R.string.pref_lamb, R.drawable.sheep) - VITAL.ordinal -> Pair(R.string.pref_vital, R.drawable.yoga) - BEEF.ordinal -> Pair(R.string.pref_beef, R.drawable.cow) - PORK.ordinal -> Pair(R.string.pref_pork, R.drawable.pig) - VEGAN.ordinal -> Pair(R.string.pref_vegan, R.drawable.leaf) - VEGETARIAN.ordinal -> Pair(R.string.pref_vegetarian, R.drawable.carrot) - GAME.ordinal -> Pair(R.string.pref_game, R.drawable.deer) - NONE.ordinal -> Pair(R.string.question_mark, R.drawable.circle) - else -> Pair(R.string.question_mark, R.drawable.cross) // ERROR.ordinal + fun getData(index: Int): Triple = when (index) { + WELFARE.ordinal -> Triple(R.string.pref_fair, R.drawable.handshake, R.attr.colorPrimaryFair) + FISH.ordinal -> Triple(R.string.pref_fish, R.drawable.fish, R.attr.colorPrimaryFish) + POULTRY.ordinal -> Triple(R.string.pref_poultry, R.drawable.chicken, R.attr.colorPrimaryPoultry) + LAMB.ordinal -> Triple(R.string.pref_lamb, R.drawable.sheep, R.attr.colorPrimaryLamb) + VITAL.ordinal -> Triple(R.string.pref_vital, R.drawable.yoga, R.attr.colorPrimaryVital) + BEEF.ordinal -> Triple(R.string.pref_beef, R.drawable.cow, R.attr.colorPrimaryBeef) + PORK.ordinal -> Triple(R.string.pref_pork, R.drawable.pig, R.attr.colorPrimaryPork) + VEGAN.ordinal -> Triple(R.string.pref_vegan, R.drawable.leaf, R.attr.colorPrimaryVegan) + VEGETARIAN.ordinal -> Triple(R.string.pref_vegetarian, R.drawable.carrot, R.attr.colorPrimaryVegetarian) + GAME.ordinal -> Triple(R.string.pref_game, R.drawable.deer, R.attr.colorPrimaryGame) + NONE.ordinal -> Triple(R.string.question_mark, R.drawable.circle, R.attr.colorText) + else -> Triple(R.string.question_mark, R.drawable.cross, R.attr.colorErrorText) // ERROR.ordinal } } } \ No newline at end of file diff --git a/app/src/main/java/com/denizk0461/studip/model/SettingsPreferences.kt b/app/src/main/java/com/denizk0461/studip/model/SettingsPreferences.kt index 20a136f..0110a98 100644 --- a/app/src/main/java/com/denizk0461/studip/model/SettingsPreferences.kt +++ b/app/src/main/java/com/denizk0461/studip/model/SettingsPreferences.kt @@ -17,11 +17,17 @@ enum class SettingsPreferences(val key: String) { * Whether the user wants the next course in his schedule to be highlighted. */ COURSE_HIGHLIGHTING("setting_highlight"), + /** * Whether the user wants the app to launch with the canteen fragment. */ LAUNCH_CANTEEN_ON_START("settings_launch_canteen"), + /** + * Whether the user wants dietary preferences to be coloured. + */ + COLOUR_PREFS("settings_prefs_colour"), + /** * Whether the user opts into sending crash report. */ diff --git a/app/src/main/java/com/denizk0461/studip/sheet/AllergenSheet.kt b/app/src/main/java/com/denizk0461/studip/sheet/AllergenSheet.kt index b45b46b..b748279 100644 --- a/app/src/main/java/com/denizk0461/studip/sheet/AllergenSheet.kt +++ b/app/src/main/java/com/denizk0461/studip/sheet/AllergenSheet.kt @@ -1,10 +1,12 @@ package com.denizk0461.studip.sheet +import android.content.res.ColorStateList import android.os.Bundle 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.getThemedColor import com.denizk0461.studip.data.viewBinding import com.denizk0461.studip.databinding.ItemSheetPreferenceBinding import com.denizk0461.studip.databinding.SheetAllergenBinding @@ -18,10 +20,12 @@ import com.denizk0461.studip.model.DietaryPreferences * * @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) { // View binding @@ -45,7 +49,7 @@ class AllergenSheet( // Inflate the view val prefLine = ItemSheetPreferenceBinding.inflate(LayoutInflater.from(context)) - val (stringId, drawableId) = DietaryPreferences.getData(index) + val (stringId, drawableId, colourId) = DietaryPreferences.getData(index) // Add the localised text for the preference prefLine.preferenceText.text = getString(stringId) @@ -58,6 +62,17 @@ class AllergenSheet( ) ) + // 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) } diff --git a/app/src/main/java/com/denizk0461/studip/sheet/DevCodeSheet.kt b/app/src/main/java/com/denizk0461/studip/sheet/DevCodeSheet.kt index 7d9c917..1b7427a 100644 --- a/app/src/main/java/com/denizk0461/studip/sheet/DevCodeSheet.kt +++ b/app/src/main/java/com/denizk0461/studip/sheet/DevCodeSheet.kt @@ -62,6 +62,7 @@ class DevCodeSheet( "SU5TQU5F".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS90NE9kYTlUZFYwbw==".d64) "X0RSV05f".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9SUVpUUy1CWjhtcw==".d64) "TUFSR0Uh".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS8tbHFxRHZXRjQ1dw==".d64) + "UE9XRUxM".d64 -> launchLink("aHR0cHM6Ly95b3V0dS5iZS9XUGMtVkVxQlBISQ==".d64) "NEVENT" -> { // nuke events nukeEvents() showToast(context, "Nuked all events") @@ -86,7 +87,8 @@ class DevCodeSheet( nukeEverything() showToast(context, "Nuked everything") } - else -> showToast(context, "code is invalid") + "HACK()" -> showToast(context, "Hack attempt unsuccessful") + else -> showToast(context, "Code is invalid") } dismiss() } diff --git a/app/src/main/java/com/denizk0461/studip/viewmodel/CanteenPageViewModel.kt b/app/src/main/java/com/denizk0461/studip/viewmodel/CanteenPageViewModel.kt index 403e7d1..8755f3a 100644 --- a/app/src/main/java/com/denizk0461/studip/viewmodel/CanteenPageViewModel.kt +++ b/app/src/main/java/com/denizk0461/studip/viewmodel/CanteenPageViewModel.kt @@ -30,4 +30,11 @@ class CanteenPageViewModel(app: Application) : AppViewModel(app) { */ val preferenceAllergen: Boolean get() = repo.getBooleanPreference(SettingsPreferences.ALLERGEN, defaultValue = true) + + /** + * This value determines which canteen the user has selected. + */ + var preferenceColour: Boolean + get() = repo.getBooleanPreference(SettingsPreferences.COLOUR_PREFS) + set(newValue) { repo.setPreference(SettingsPreferences.COLOUR_PREFS, newValue) } } \ No newline at end of file diff --git a/app/src/main/java/com/denizk0461/studip/viewmodel/FetcherViewModel.kt b/app/src/main/java/com/denizk0461/studip/viewmodel/FetcherViewModel.kt index 47f189b..340801f 100644 --- a/app/src/main/java/com/denizk0461/studip/viewmodel/FetcherViewModel.kt +++ b/app/src/main/java/com/denizk0461/studip/viewmodel/FetcherViewModel.kt @@ -2,6 +2,8 @@ package com.denizk0461.studip.viewmodel import android.app.Application import com.denizk0461.studip.data.StudIPParser +import java.io.IOException +import kotlin.jvm.Throws /** * View model for [com.denizk0461.studip.activity.FetcherActivity] @@ -10,7 +12,20 @@ import com.denizk0461.studip.data.StudIPParser */ class FetcherViewModel(app: Application) : AppViewModel(app) { + /** + * Instance of the parser used to fetch and parse the user's Stud.IP schedule. + */ private val parser: StudIPParser = StudIPParser(app) - fun parse(html: String) { doAsync { parser.parse(html, {}) }} + /** + * Fetches and parses the user's Stud.IP schedule. + * + * @param html source code of the schedule website + */ + @Throws(IOException::class) + fun parse(html: String) { + doAsync { + parser.parse(html) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/denizk0461/studip/viewmodel/SettingsViewModel.kt b/app/src/main/java/com/denizk0461/studip/viewmodel/SettingsViewModel.kt index e47779a..6a7f353 100644 --- a/app/src/main/java/com/denizk0461/studip/viewmodel/SettingsViewModel.kt +++ b/app/src/main/java/com/denizk0461/studip/viewmodel/SettingsViewModel.kt @@ -70,6 +70,13 @@ class SettingsViewModel(app: Application) : AppViewModel(app) { get() = repo.getBooleanPreference(SettingsPreferences.LAUNCH_CANTEEN_ON_START) set(newValue) { repo.setPreference(SettingsPreferences.LAUNCH_CANTEEN_ON_START, newValue) } + /** + * This value determines which canteen the user has selected. + */ + var preferenceColour: Boolean + get() = repo.getBooleanPreference(SettingsPreferences.COLOUR_PREFS) + set(newValue) { repo.setPreference(SettingsPreferences.COLOUR_PREFS, newValue) } + /** * This value determines whether the user opts into submitting crash reports. */ diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml index 91ed85e..cadce76 100644 --- a/app/src/main/res/layout/fragment_settings.xml +++ b/app/src/main/res/layout/fragment_settings.xml @@ -206,6 +206,49 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 4fb9f32..36d467d 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -20,6 +20,7 @@ Ein Fehler ist aufgetreten! + Du musst deinen Stundenplan öffnen! Mensaplan konnte nicht heruntergeladen werden! Speichern @@ -138,6 +139,9 @@ Starte die App mit dem Mensaplan Sonst wird Dein Stundenplan beim Start gezeigt + Färbe Diätpreferenzen + Dies färbt die kleinen Symbole ähnlich wie auf der Webseite + Stimme Sammlung von Absturzreporten zu Daten werden anonymisiert übertragen diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml index 7e94765..5a71dc6 100644 --- a/app/src/main/res/values-night/themes.xml +++ b/app/src/main/res/values-night/themes.xml @@ -28,6 +28,8 @@ @color/md_theme_dark_inverseSurface @color/md_theme_dark_inversePrimary + @color/md_theme_dark_error + @color/md_theme_dark_onSurfaceVariant @color/md_theme_dark_onSurfaceVariant @color/md_theme_dark_onSurfaceVariant @@ -35,6 +37,48 @@ @color/md_theme_light_background + + + @color/fair_dark_primary + @color/fair_dark_onPrimary + @color/fair_dark_container + @color/fair_dark_onContainer + @color/fish_dark_primary + @color/fish_dark_onPrimary + @color/fish_dark_container + @color/fish_dark_onContainer + @color/poultry_dark_primary + @color/poultry_dark_onPrimary + @color/poultry_dark_container + @color/poultry_dark_onContainer + @color/vital_dark_primary + @color/vital_dark_onPrimary + @color/vital_dark_container + @color/vital_dark_onContainer + @color/lamb_dark_primary + @color/lamb_dark_onPrimary + @color/lamb_dark_container + @color/lamb_dark_onContainer + @color/beef_dark_primary + @color/beef_dark_onPrimary + @color/beef_dark_container + @color/beef_dark_onContainer + @color/pork_dark_primary + @color/pork_dark_onPrimary + @color/pork_dark_container + @color/pork_dark_onContainer + @color/vegan_dark_primary + @color/vegan_dark_onPrimary + @color/vegan_dark_container + @color/vegan_dark_onContainer + @color/vegetarian_dark_primary + @color/vegetarian_dark_onPrimary + @color/vegetarian_dark_container + @color/vegetarian_dark_onContainer + @color/game_dark_primary + @color/game_dark_onPrimary + @color/game_dark_container + @color/game_dark_onContainer