From 9637d8a85ec4de6344a6fd7c315de07be90e452d Mon Sep 17 00:00:00 2001 From: deniscerri <64997243+deniscerri@users.noreply.github.com> Date: Thu, 1 Jan 2026 19:36:04 +0100 Subject: [PATCH] Add Icon Picker --- .../ytdl/ui/adapter/IconsSheetAdapter.kt | 58 +++++++++++ .../more/settings/GeneralSettingsFragment.kt | 33 +++++++ .../com/deniscerri/ytdl/util/ThemeUtil.kt | 98 ++++++++++--------- app/src/main/res/drawable/ic_frame.xml | 10 ++ app/src/main/res/drawable/rounded_ripple.xml | 10 ++ app/src/main/res/layout/app_icon_item.xml | 31 ++++++ app/src/main/res/values/strings.xml | 1 + app/src/main/res/values/styles.xml | 5 + app/src/main/res/xml/general_preferences.xml | 7 ++ 9 files changed, 209 insertions(+), 44 deletions(-) create mode 100644 app/src/main/java/com/deniscerri/ytdl/ui/adapter/IconsSheetAdapter.kt create mode 100644 app/src/main/res/drawable/ic_frame.xml create mode 100644 app/src/main/res/drawable/rounded_ripple.xml create mode 100644 app/src/main/res/layout/app_icon_item.xml diff --git a/app/src/main/java/com/deniscerri/ytdl/ui/adapter/IconsSheetAdapter.kt b/app/src/main/java/com/deniscerri/ytdl/ui/adapter/IconsSheetAdapter.kt new file mode 100644 index 00000000..e1b18536 --- /dev/null +++ b/app/src/main/java/com/deniscerri/ytdl/ui/adapter/IconsSheetAdapter.kt @@ -0,0 +1,58 @@ +package com.deniscerri.ytdl.ui.adapter + +import android.app.Activity +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import androidx.recyclerview.widget.RecyclerView +import com.deniscerri.ytdl.R +import com.deniscerri.ytdl.databinding.AppIconItemBinding +import com.deniscerri.ytdl.util.ThemeUtil + +class IconsSheetAdapter(val activity: Activity) : RecyclerView.Adapter() { + + class IconsSheetViewHolder( + val binding: AppIconItemBinding + ) : RecyclerView.ViewHolder(binding.root) + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): IconsSheetViewHolder { + val binding = AppIconItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) + return IconsSheetViewHolder(binding) + } + + override fun getItemCount() = availableIcons.size + + override fun onBindViewHolder(holder: IconsSheetViewHolder, position: Int) { + val appIcon = availableIcons[position] + holder.binding.apply { + iconIV.setImageResource(appIcon.iconResource) + iconName.text = root.context.getString(appIcon.nameResource) + root.setOnClickListener { + val preferences = androidx.preference.PreferenceManager.getDefaultSharedPreferences(activity) + preferences.edit().putString("ytdlnis_icon", appIcon.activityAlias).apply() + val theme = preferences.getString("ytdlnis_theme", "System")!! + ThemeUtil.updateAppIcon(activity, theme,appIcon.activityAlias) + activity.recreate() + } + } + } + + companion object { + sealed class AppIcon( + @StringRes val nameResource: Int, + @DrawableRes val iconResource: Int, + val activityAlias: String + ) { + object Default : AppIcon(R.string.auto, R.mipmap.ic_launcher, "default") + object DefaultLight : AppIcon(R.string.light, R.mipmap.ic_launcher_light, "Light") + object DefaultDark : AppIcon(R.string.dark, R.mipmap.ic_launcher_dark, "Dark") + } + + val availableIcons = listOf( + AppIcon.Default, + AppIcon.DefaultLight, + AppIcon.DefaultDark + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdl/ui/more/settings/GeneralSettingsFragment.kt b/app/src/main/java/com/deniscerri/ytdl/ui/more/settings/GeneralSettingsFragment.kt index b2de49a3..9d0fab18 100644 --- a/app/src/main/java/com/deniscerri/ytdl/ui/more/settings/GeneralSettingsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdl/ui/more/settings/GeneralSettingsFragment.kt @@ -12,6 +12,9 @@ import android.net.Uri import android.os.Bundle import android.os.PowerManager import android.provider.Settings +import android.util.DisplayMetrics +import android.view.ViewGroup +import android.view.Window import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatDelegate import androidx.core.os.LocaleListCompat @@ -24,6 +27,7 @@ import androidx.preference.MultiSelectListPreference import androidx.preference.Preference import androidx.preference.PreferenceManager import androidx.preference.SwitchPreferenceCompat +import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -32,11 +36,13 @@ import androidx.work.WorkManager import com.deniscerri.ytdl.R import com.deniscerri.ytdl.database.viewmodel.ResultViewModel import com.deniscerri.ytdl.databinding.NavOptionsItemBinding +import com.deniscerri.ytdl.ui.adapter.IconsSheetAdapter import com.deniscerri.ytdl.ui.adapter.NavBarOptionsAdapter import com.deniscerri.ytdl.util.NavbarUtil import com.deniscerri.ytdl.util.ThemeUtil import com.deniscerri.ytdl.util.UiUtil import com.deniscerri.ytdl.util.UpdateUtil +import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -202,6 +208,33 @@ class GeneralSettingsFragment : BaseSettingsFragment() { } } + findPreference("ytdlnis_icon")?.apply { + val currentValue = preferences.getString("ytdlnis_icon", "default") + IconsSheetAdapter.availableIcons.firstOrNull { it.activityAlias == currentValue }?.let { + summary = getString(it.nameResource) + } + + setOnPreferenceClickListener { + val bottomSheet = BottomSheetDialog(context) + bottomSheet.requestWindowFeature(Window.FEATURE_NO_TITLE) + bottomSheet.setContentView(R.layout.generic_list) + + val recycler = bottomSheet.findViewById(R.id.download_recyclerview)!! + recycler.layoutManager = GridLayoutManager(context, 3) + recycler.adapter = IconsSheetAdapter(requireActivity()) + + bottomSheet.show() + val displayMetrics = DisplayMetrics() + requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics) + bottomSheet.behavior.peekHeight = displayMetrics.heightPixels + bottomSheet.window!!.setLayout( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + ) + false + } + } + findPreference("theme_accent")?.apply { summary = entry setOnPreferenceChangeListener { _, _ -> diff --git a/app/src/main/java/com/deniscerri/ytdl/util/ThemeUtil.kt b/app/src/main/java/com/deniscerri/ytdl/util/ThemeUtil.kt index 6c37fc24..c497728d 100644 --- a/app/src/main/java/com/deniscerri/ytdl/util/ThemeUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdl/util/ThemeUtil.kt @@ -113,61 +113,23 @@ object ThemeUtil { activity.theme.applyStyle(R.style.Pure, true) } - //disable old icons - for (appIcon in availableIcons) { - val activityClass = "com.deniscerri.ytdl." + appIcon.activityAlias - - // remove old icons - activity.packageManager.setComponentEnabledSetting( - ComponentName(activity.packageName, activityClass), - PackageManager.COMPONENT_ENABLED_STATE_DISABLED, - PackageManager.DONT_KILL_APP - ) - } - - when (sharedPreferences.getString("ytdlnis_theme", "System")!!) { - "System" -> { - //set dynamic icon - activity.packageManager.setComponentEnabledSetting( - ComponentName(activity.packageName, "com.deniscerri.ytdl.Default"), - PackageManager.COMPONENT_ENABLED_STATE_ENABLED, - PackageManager.DONT_KILL_APP - ) - - AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) - } + val theme = sharedPreferences.getString("ytdlnis_theme", "System")!! + when (theme) { "Light" -> { - //set light icon - activity.packageManager.setComponentEnabledSetting( - ComponentName(activity.packageName, "com.deniscerri.ytdl.LightIcon"), - PackageManager.COMPONENT_ENABLED_STATE_ENABLED, - PackageManager.DONT_KILL_APP - ) - AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) } "Dark" -> { - //set dark icon - activity.packageManager.setComponentEnabledSetting( - ComponentName(activity.packageName, "com.deniscerri.ytdl.DarkIcon"), - PackageManager.COMPONENT_ENABLED_STATE_ENABLED, - PackageManager.DONT_KILL_APP - ) - AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) } + // or "System" else -> { - //set dynamic icon - activity.packageManager.setComponentEnabledSetting( - ComponentName(activity.packageName, "com.deniscerri.ytdl.Default"), - PackageManager.COMPONENT_ENABLED_STATE_ENABLED, - PackageManager.DONT_KILL_APP - ) - AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) } } + + val iconMode = sharedPreferences.getString("ytdlnis_icon", "default")!! + updateAppIcon(activity,theme, iconMode) } fun getThemeColor(context: Context, colorCode: Int): Int { @@ -192,4 +154,52 @@ object ThemeUtil { return "YTDLnis" .parseAsHtml(HtmlCompat.FROM_HTML_MODE_COMPACT) } + + + fun updateAppIcon(activity: Activity, theme: String, appIconMode: String) { + //disable old icons + for (appIcon in availableIcons) { + val activityClass = "com.deniscerri.ytdl." + appIcon.activityAlias + + // remove old icons + activity.packageManager.setComponentEnabledSetting( + ComponentName(activity.packageName, activityClass), + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP + ) + } + + var iconMode = appIconMode + if (appIconMode == "default") { + iconMode = theme + } + + when (iconMode) { + "Light" -> { + //set light icon + activity.packageManager.setComponentEnabledSetting( + ComponentName(activity.packageName, "com.deniscerri.ytdl.LightIcon"), + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP + ) + } + "Dark" -> { + //set dark icon + activity.packageManager.setComponentEnabledSetting( + ComponentName(activity.packageName, "com.deniscerri.ytdl.DarkIcon"), + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP + ) + } + // or "System" + else -> { + //set dynamic icon + activity.packageManager.setComponentEnabledSetting( + ComponentName(activity.packageName, "com.deniscerri.ytdl.Default"), + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP + ) + } + } + } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_frame.xml b/app/src/main/res/drawable/ic_frame.xml new file mode 100644 index 00000000..a2164edc --- /dev/null +++ b/app/src/main/res/drawable/ic_frame.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/rounded_ripple.xml b/app/src/main/res/drawable/rounded_ripple.xml new file mode 100644 index 00000000..59a9bc04 --- /dev/null +++ b/app/src/main/res/drawable/rounded_ripple.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/app_icon_item.xml b/app/src/main/res/layout/app_icon_item.xml new file mode 100644 index 00000000..1628d103 --- /dev/null +++ b/app/src/main/res/layout/app_icon_item.xml @@ -0,0 +1,31 @@ + + + + + + + + \ 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 2ae655c8..38251b9d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -506,4 +506,5 @@ Auth\n-----------------------\n1. Click \'Auth\' to open the sign in page in WebView.\n2. Sign in to your Google Account.\n3. Play any video that supports auto-translated subtitles.\n4. Turn on auto-translated subtitles and see if it works.\n\t4.1 If auto-translated subtitles don\'t work, switch to another video that supports auto-translated subtitles and try step 4 again.\n5. Click OK.\n\nNo Auth\n-----------------------\n1. Click \'No Auth\'.\n2. Write any youtube video url\n3. Wait for the video to load and play the video for at least 3 seconds.\n4. Click OK. No Auth Auth + App Icon diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index c4e550f5..edaadb45 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -33,6 +33,11 @@ 5dp + +