diff --git a/app/src/main/java/com/lagradost/cloudstream3/AcraApplication.kt b/app/src/main/java/com/lagradost/cloudstream3/AcraApplication.kt index 85f031b3..f343bb0c 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/AcraApplication.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/AcraApplication.kt @@ -18,6 +18,7 @@ import com.lagradost.cloudstream3.utils.DataStore.getKeys import com.lagradost.cloudstream3.utils.DataStore.removeKey import com.lagradost.cloudstream3.utils.DataStore.removeKeys import com.lagradost.cloudstream3.utils.DataStore.setKey +import com.lagradost.cloudstream3.utils.resources.ResourcePackManager import kotlinx.coroutines.runBlocking import org.acra.ACRA import org.acra.ReportField @@ -79,6 +80,7 @@ class ExceptionHandler(val errorFile: File, val onError: (() -> Unit)): Thread.U ACRA.errorReporter.handleException(error) try { PrintStream(errorFile).use { ps -> + ps.println(String.format("Enabled resource pack: ${ResourcePackManager.activePackId ?: "none"}")) ps.println(String.format("Currently loading extension: ${PluginManager.currentlyLoading ?: "none"}")) ps.println(String.format("Fatal exception on thread %s (%d)", thread.name, thread.id)) error.printStackTrace(ps) diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index 6c9fadd8..9bc36847 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -4,13 +4,13 @@ import android.content.ComponentName import android.content.Intent import android.content.res.ColorStateList import android.content.res.Configuration +import android.content.res.Resources import android.os.Bundle import android.util.Log import android.view.KeyEvent import android.view.Menu import android.view.MenuItem import android.view.WindowManager -import android.widget.Toast import androidx.annotation.IdRes import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity @@ -59,6 +59,9 @@ import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSet import com.lagradost.cloudstream3.ui.settings.SettingsGeneral import com.lagradost.cloudstream3.ui.setup.HAS_DONE_SETUP_KEY import com.lagradost.cloudstream3.ui.setup.SetupFragmentExtensions +import com.lagradost.cloudstream3.utils.Event +import com.lagradost.cloudstream3.utils.IOnBackPressed +import com.lagradost.cloudstream3.utils.resources.ResourcePatch import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable import com.lagradost.cloudstream3.utils.AppUtils.loadCache import com.lagradost.cloudstream3.utils.AppUtils.loadRepository @@ -70,8 +73,6 @@ import com.lagradost.cloudstream3.utils.DataStore.removeKey import com.lagradost.cloudstream3.utils.DataStore.setKey import com.lagradost.cloudstream3.utils.DataStoreHelper.migrateResumeWatching import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos -import com.lagradost.cloudstream3.utils.Event -import com.lagradost.cloudstream3.utils.IOnBackPressed import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate import com.lagradost.cloudstream3.utils.UIHelper.changeStatusBarState import com.lagradost.cloudstream3.utils.UIHelper.checkWrite @@ -82,6 +83,8 @@ import com.lagradost.cloudstream3.utils.UIHelper.navigate import com.lagradost.cloudstream3.utils.UIHelper.requestRW import com.lagradost.cloudstream3.utils.USER_PROVIDER_API import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API +import com.lagradost.cloudstream3.utils.resources.ResourcePackManager +import com.lagradost.cloudstream3.utils.resources.ResourcePatchActivity import com.lagradost.nicehttp.Requests import com.lagradost.nicehttp.ResponseParser import kotlinx.android.synthetic.main.activity_main.* @@ -133,7 +136,18 @@ var app = Requests(responseParser = object : ResponseParser { defaultHeaders = mapOf("user-agent" to USER_AGENT) } -class MainActivity : AppCompatActivity(), ColorPickerDialogListener { +class MainActivity : AppCompatActivity(), ColorPickerDialogListener, ResourcePatchActivity { + private var resourcePatch: ResourcePatch? = null + + override fun getResources(): Resources = resourcePatch ?: super.getResources() + override fun reloadResourcePatch() { + resourcePatch = try { + ResourcePackManager.activePack?.invoke(super.getResources()) + } catch (e: Throwable) { + null + } + } + companion object { const val TAG = "MAINACT" diff --git a/app/src/main/java/com/lagradost/cloudstream3/plugins/Plugin.kt b/app/src/main/java/com/lagradost/cloudstream3/plugins/Plugin.kt index 242baf59..ec845d2c 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/plugins/Plugin.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/plugins/Plugin.kt @@ -9,6 +9,8 @@ import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.extractorApis import android.util.Log import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.utils.resources.ResourcePackManager +import com.lagradost.cloudstream3.utils.resources.ResourcePatch const val PLUGIN_TAG = "PluginInstance" @@ -50,6 +52,16 @@ abstract class Plugin { extractorApis.add(element) } + /** + * Used to register a new resource pack + * @param factory The function that provided the original resources will generate a ResourcePatch instance + * You should probably use MapResourcePatch + * @see com.lagradost.cloudstream3.utils.resources.MapResourcePatch + */ + fun registerResourcePack(name: String, factory: (Resources) -> ResourcePatch) { + ResourcePackManager.registerPack(name, factory, this.__filename) + } + class Manifest { @JsonProperty("name") var name: String? = null @JsonProperty("pluginClassName") var pluginClassName: String? = null diff --git a/app/src/main/java/com/lagradost/cloudstream3/plugins/PluginManager.kt b/app/src/main/java/com/lagradost/cloudstream3/plugins/PluginManager.kt index b5441b94..29603a5f 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/plugins/PluginManager.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/plugins/PluginManager.kt @@ -27,6 +27,7 @@ import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIE import com.lagradost.cloudstream3.utils.Coroutines.ioSafe import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.extractorApis +import com.lagradost.cloudstream3.utils.resources.ResourcePackManager import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import org.acra.log.debug @@ -376,6 +377,7 @@ object PluginManager { } APIHolder.allProviders.removeIf { provider: MainAPI -> provider.sourcePlugin == plugin.__filename } extractorApis.removeIf { provider: ExtractorApi -> provider.sourcePlugin == plugin.__filename } + ResourcePackManager.unregisterPlugin(plugin.__filename) classLoaders.values.removeIf { v -> v == plugin } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt index dc1bbba3..0d9c819c 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt @@ -1,6 +1,7 @@ package com.lagradost.cloudstream3.ui.player import android.content.Intent +import android.content.res.Resources import android.net.Uri import android.os.Bundle import android.util.Log @@ -11,10 +12,13 @@ import com.lagradost.cloudstream3.CommonActivity import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.utils.ExtractorUri import com.lagradost.cloudstream3.utils.UIHelper.navigate +import com.lagradost.cloudstream3.utils.resources.ResourcePackManager +import com.lagradost.cloudstream3.utils.resources.ResourcePatch +import com.lagradost.cloudstream3.utils.resources.ResourcePatchActivity const val DTAG = "PlayerActivity" -class DownloadedPlayerActivity : AppCompatActivity() { +class DownloadedPlayerActivity : AppCompatActivity(), ResourcePatchActivity { override fun dispatchKeyEvent(event: KeyEvent?): Boolean { CommonActivity.dispatchKeyEvent(this, event)?.let { return it @@ -106,4 +110,14 @@ class DownloadedPlayerActivity : AppCompatActivity() { return } } + + private var resourcePatch: ResourcePatch? = null + override fun getResources(): Resources = resourcePatch ?: super.getResources() + override fun reloadResourcePatch() { + resourcePatch = try { + ResourcePackManager.activePack?.invoke(super.getResources()) + } catch (e: Throwable) { + null + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsUI.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsUI.kt index 9ad3ee8f..b01d900e 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsUI.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsUI.kt @@ -4,6 +4,7 @@ import android.os.Bundle import android.view.View import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceManager +import com.lagradost.cloudstream3.MainActivity import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.SearchQuality import com.lagradost.cloudstream3.mvvm.logError @@ -16,6 +17,8 @@ import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showMultiDialog import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard +import com.lagradost.cloudstream3.utils.resources.ResourcePackManager +import kotlin.streams.toList class SettingsUI : PreferenceFragmentCompat() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -130,6 +133,27 @@ class SettingsUI : PreferenceFragmentCompat() { } return@setOnPreferenceClickListener true } + getPref(R.string.active_resource_pack_key)?.setOnPreferenceClickListener { + val prefNames = ResourcePackManager.packs.keys.toMutableList() + prefNames.add(0, getString(R.string.none)) + val prefValues: MutableList = ResourcePackManager.packs.keys.toMutableList() + prefValues.add(0, null) + + activity?.showDialog( + prefNames.toList(), + prefValues.indexOf(ResourcePackManager.activePackId), + getString(R.string.resource_pack), + true, + {}) { + try { + ResourcePackManager.selectPack(prefValues[it], activity as MainActivity) + activity?.recreate() + } catch (e: Exception) { + logError(e) + } + } + return@setOnPreferenceClickListener true + } getPref(R.string.pref_filter_search_quality_key)?.setOnPreferenceClickListener { val names = enumValues().sorted().map { it.name } diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/resources/MapResourcePatch.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/resources/MapResourcePatch.kt new file mode 100644 index 00000000..732a95cc --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/resources/MapResourcePatch.kt @@ -0,0 +1,47 @@ +package com.lagradost.cloudstream3.utils.resources + +import android.content.res.ColorStateList +import android.content.res.Resources +import android.content.res.XmlResourceParser +import android.graphics.drawable.Drawable +import android.os.Build +import android.util.Log +import androidx.annotation.RequiresApi + +typealias Generator = () -> T? +typealias GeneratorWithTheme = (Resources.Theme?) -> T? + +open class MapResourcePatch(private val original: Resources): ResourcePatch(original) { + val mapping: HashMap = hashMapOf() + val idMapping: HashMap = hashMapOf() + + override fun mapId(id: Int): Int = + idMapping[id] ?: super.mapId(id) + + override fun getLayout(id: Int): XmlResourceParser = + mapping.getMappingKA(id, null) ?: super.getLayout(id) + + override fun getDrawable(id: Int, theme: Theme?): Drawable = + mapping.getMappingKA(id, theme) ?: super.getDrawable(id, theme) + + @RequiresApi(Build.VERSION_CODES.M) + override fun getColorStateList(id: Int, theme: Theme?): ColorStateList = + mapping.getMappingKA(id, theme) ?: super.getColorStateList(id, theme) + + override fun getXml(id: Int): XmlResourceParser = + mapping.getMappingKA(id, null) ?: super.getXml(id) + + @RequiresApi(Build.VERSION_CODES.M) + override fun getColor(id: Int, theme: Theme?): Int = + mapping.getMappingKA(id, theme) ?: super.getColor(id, theme) +} + +private inline fun HashMap.getMappingKA(id: K?, theme: Resources.Theme?): V? { + return when (val res = this[id]) { + equals(null) -> null + is V -> res + is Function0<*> -> (res as? Generator)?.invoke() + is Function1<*, *> -> (res as? GeneratorWithTheme)?.invoke(theme) + else -> null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/resources/ResourcePackManager.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/resources/ResourcePackManager.kt new file mode 100644 index 00000000..f9d8c31c --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/resources/ResourcePackManager.kt @@ -0,0 +1,66 @@ +package com.lagradost.cloudstream3.utils.resources + +import android.content.res.Resources +import android.util.Log +import com.lagradost.cloudstream3.AcraApplication +import com.lagradost.cloudstream3.AcraApplication.Companion.getActivity +import com.lagradost.cloudstream3.AcraApplication.Companion.getKey +import com.lagradost.cloudstream3.AcraApplication.Companion.setKey +import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent +import com.lagradost.cloudstream3.R + +typealias PatchFactory = (Resources) -> ResourcePatch + +object ResourcePackManager { + private const val KEY = "ResourcePackManager" + const val SETTINGS_KEY = "active_resource_pack_key" // TODO + val packs: HashMap = hashMapOf() + private val pluginMapping: HashMap> = hashMapOf() + var activePackId: String? = null + internal set + val activePack: PatchFactory? + get() = if (activePackId == null) null else packs[activePackId] + + init { + afterPluginsLoadedEvent += ::onExtensionsLoaded + } + + fun registerPack(name: String, factory: PatchFactory, pluginId: String?) { + packs[name] = factory + if (pluginId != null) { + if (!pluginMapping.containsKey(pluginId)) + pluginMapping[pluginId] = arrayListOf() + pluginMapping[pluginId]?.add(name) + } + } + + fun unregisterPlugin(pluginId: String?) { + pluginMapping[pluginId]?.forEach { + packs.remove(it) + if (activePackId == it) // if pack is being removed make sure its not set + selectPack(null, AcraApplication.context?.getActivity() as? ResourcePatchActivity) + } + pluginMapping.remove(pluginId) + } + + fun selectPack(packId: String?, activity: ResourcePatchActivity?) { + if (packId == null) activePackId = null + else if (packs.containsKey(packId)) activePackId = packId + else activePackId = null + + Log.d(KEY, "Selecting: ${activePackId ?: "none"}") + setKey(SETTINGS_KEY, activePackId) + + activity?.reloadResourcePatch() + } + + + private fun onExtensionsLoaded(successful: Boolean = false) { + if (!successful) return + activePackId = getKey(SETTINGS_KEY) + Log.d(KEY, "Selecting saved: ${activePackId ?: "none"}") + val activity = AcraApplication.context?.getActivity() as? ResourcePatchActivity + activity?.reloadResourcePatch() + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/resources/ResourcePatch.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/resources/ResourcePatch.kt new file mode 100644 index 00000000..71bcbb2c --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/resources/ResourcePatch.kt @@ -0,0 +1,80 @@ +package com.lagradost.cloudstream3.utils.resources + +import android.annotation.SuppressLint +import android.content.res.* +import android.content.res.loader.ResourcesLoader +import android.graphics.Typeface +import android.graphics.drawable.Drawable +import android.os.Build +import android.os.Bundle +import android.util.AttributeSet +import android.util.DisplayMetrics +import android.util.TypedValue +import androidx.annotation.RequiresApi +import java.io.InputStream + +open class ResourcePatch(private val original: Resources) : + Resources(original.assets, original.displayMetrics, original.configuration) { + + open fun mapId(id: Int): Int = id + + @RequiresApi(Build.VERSION_CODES.R) + override fun addLoaders(vararg loaders: ResourcesLoader?) = original.addLoaders(*loaders) + override fun getAnimation(id: Int): XmlResourceParser = original.getAnimation(mapId(id)) + override fun getBoolean(id: Int): Boolean = original.getBoolean(mapId(id)) + @RequiresApi(Build.VERSION_CODES.M) + override fun getColor(id: Int, theme: Theme?): Int = original.getColor(mapId(id), theme) + override fun getConfiguration(): Configuration = original.configuration + override fun getDisplayMetrics(): DisplayMetrics = original.displayMetrics + @RequiresApi(Build.VERSION_CODES.M) + override fun getColorStateList(id: Int, theme: Theme?): ColorStateList = original.getColorStateList(mapId(id), theme) + override fun getLayout(id: Int): XmlResourceParser = original.getLayout(mapId(id)) + override fun getDimension(id: Int): Float = original.getDimension(mapId(id)) + override fun getIdentifier(name: String?, defType: String?, defPackage: String?): Int = original.getIdentifier(name, defType, defPackage) + override fun getDimensionPixelOffset(id: Int): Int = original.getDimensionPixelOffset(mapId(id)) + override fun getDimensionPixelSize(id: Int): Int = original.getDimensionPixelSize(mapId(id)) + @SuppressLint("UseCompatLoadingForDrawables") + override fun getDrawable(id: Int, theme: Theme?): Drawable = original.getDrawable(mapId(id), theme) + override fun getDrawableForDensity(id: Int, density: Int, theme: Theme?): Drawable? = original.getDrawableForDensity(mapId(id), density, theme) + @RequiresApi(Build.VERSION_CODES.Q) + override fun getFloat(id: Int): Float = original.getFloat(mapId(id)) + @RequiresApi(Build.VERSION_CODES.O) + override fun getFont(id: Int): Typeface = original.getFont(mapId(id)) + override fun getIntArray(id: Int): IntArray = original.getIntArray(mapId(id)) + override fun getFraction(id: Int, base: Int, pbase: Int): Float = original.getFraction(mapId(id), base, pbase) + override fun getInteger(id: Int): Int = original.getInteger(mapId(id)) + override fun getQuantityString(id: Int, quantity: Int): String = original.getQuantityString(mapId(id), quantity) + override fun getQuantityString(id: Int, quantity: Int, vararg formatArgs: Any?): String = original.getQuantityString(mapId(id), quantity, *formatArgs) + override fun getQuantityText(id: Int, quantity: Int): CharSequence = original.getQuantityText(mapId(id), quantity) + override fun getResourceEntryName(id: Int): String = original.getResourceEntryName(mapId(id)) + override fun getResourceName(id: Int): String = original.getResourceName(mapId(id)) + override fun getResourcePackageName(id: Int): String = original.getResourcePackageName(mapId(id)) + override fun getResourceTypeName(id: Int): String = original.getResourceTypeName(mapId(id)) + override fun getString(id: Int): String = original.getString(mapId(id)) + override fun getString(id: Int, vararg formatArgs: Any?): String = original.getString(mapId(id), *formatArgs) + override fun getStringArray(id: Int): Array = original.getStringArray(mapId(id)) + override fun getText(id: Int): CharSequence = original.getText(mapId(id)) + override fun getText(id: Int, def: CharSequence?): CharSequence = original.getText(mapId(id), def) + override fun getTextArray(id: Int): Array = original.getTextArray(mapId(id)) + override fun getValue(id: Int, outValue: TypedValue?, resolveRefs: Boolean) = original.getValue(mapId(id), outValue, resolveRefs) + override fun getValue(name: String?, outValue: TypedValue?, resolveRefs: Boolean) = original.getValue(name, outValue, resolveRefs) + override fun getValueForDensity(id: Int, density: Int, outValue: TypedValue?, resolveRefs: Boolean) = original.getValueForDensity(mapId(id), density, outValue, resolveRefs) + override fun getXml(id: Int): XmlResourceParser = original.getXml(mapId(id)) + override fun obtainTypedArray(id: Int): TypedArray = original.obtainTypedArray(mapId(id)) + override fun openRawResource(id: Int): InputStream = original.openRawResource(mapId(id)) + override fun openRawResource(id: Int, value: TypedValue?): InputStream = original.openRawResource(mapId(id), value) + override fun openRawResourceFd(id: Int): AssetFileDescriptor = original.openRawResourceFd(mapId(id)) + override fun obtainAttributes(set: AttributeSet?, attrs: IntArray?): TypedArray = original.obtainAttributes(set, attrs) + override fun parseBundleExtra(tagName: String?, attrs: AttributeSet?, outBundle: Bundle?) = original.parseBundleExtra(tagName, attrs, outBundle) + override fun parseBundleExtras(parser: XmlResourceParser?, outBundle: Bundle?) = original.parseBundleExtras(parser, outBundle) + @RequiresApi(Build.VERSION_CODES.R) + override fun removeLoaders(vararg loaders: ResourcesLoader?) = original.removeLoaders(*loaders) + override fun equals(other: Any?): Boolean = original == other + override fun hashCode(): Int = original.hashCode() + + override fun getColor(id: Int): Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) getColor(mapId(id), null) else original.getColor(mapId(id)) + @SuppressLint("UseCompatLoadingForColorStateLists") + override fun getColorStateList(id: Int): ColorStateList = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) getColorStateList(mapId(id), null) else original.getColorStateList(mapId(id)) + @SuppressLint("UseCompatLoadingForDrawables") + override fun getDrawable(id: Int): Drawable = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) getDrawable(mapId(id), null) else original.getDrawable(mapId(id)) +} diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/resources/ResourcePatchActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/resources/ResourcePatchActivity.kt new file mode 100644 index 00000000..dc1200d5 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/resources/ResourcePatchActivity.kt @@ -0,0 +1,5 @@ +package com.lagradost.cloudstream3.utils.resources + +interface ResourcePatchActivity { + fun reloadResourcePatch() +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8e6dadcf..c0008cd1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -41,6 +41,7 @@ Cloudstream app_layout_key primary_color_key + active_resource_pack_key restore_key backup_key prefer_media_type_key_2 @@ -457,6 +458,7 @@ Primary color App theme + Resource pack Poster title location Put the title under the poster diff --git a/app/src/main/res/xml/settins_ui.xml b/app/src/main/res/xml/settins_ui.xml index 071df918..bf92a17d 100644 --- a/app/src/main/res/xml/settins_ui.xml +++ b/app/src/main/res/xml/settins_ui.xml @@ -9,6 +9,10 @@ android:icon="@drawable/ic_baseline_color_lens_24" android:key="@string/app_theme_key" android:title="@string/app_theme_settings" /> +