From 180987e2d0787e0515f632c10f1cb57d29bd147b Mon Sep 17 00:00:00 2001 From: LagradOst <11805592+LagradOst@users.noreply.github.com> Date: Wed, 2 Aug 2023 05:30:50 +0200 Subject: [PATCH] added local accounts --- .../lagradost/cloudstream3/AcraApplication.kt | 8 + .../cloudstream3/ui/WhoIsWatchingAdapter.kt | 106 +++++++++ .../ui/home/HomeParentItemAdapterPreview.kt | 14 +- .../ui/player/FullScreenPlayer.kt | 4 +- .../cloudstream3/ui/player/GeneratorPlayer.kt | 2 - .../lagradost/cloudstream3/utils/DataStore.kt | 45 +++- .../cloudstream3/utils/DataStoreHelper.kt | 210 +++++++++++++++++- .../lagradost/cloudstream3/utils/UIHelper.kt | 28 ++- .../drawable/ic_outline_account_circle_24.xml | 17 +- app/src/main/res/drawable/outline_card.xml | 11 +- .../main/res/layout/fragment_home_head.xml | 28 ++- .../layout/player_quality_profile_item.xml | 2 +- app/src/main/res/layout/who_is_watching.xml | 35 +++ .../res/layout/who_is_watching_account.xml | 47 ++++ .../layout/who_is_watching_account_add.xml | 29 +++ .../layout/who_is_watching_account_edit.xml | 135 +++++++++++ app/src/main/res/values/strings.xml | 1 + 17 files changed, 693 insertions(+), 29 deletions(-) create mode 100644 app/src/main/java/com/lagradost/cloudstream3/ui/WhoIsWatchingAdapter.kt create mode 100644 app/src/main/res/layout/who_is_watching.xml create mode 100644 app/src/main/res/layout/who_is_watching_account.xml create mode 100644 app/src/main/res/layout/who_is_watching_account_add.xml create mode 100644 app/src/main/res/layout/who_is_watching_account_edit.xml diff --git a/app/src/main/java/com/lagradost/cloudstream3/AcraApplication.kt b/app/src/main/java/com/lagradost/cloudstream3/AcraApplication.kt index 76b2321f..069287b0 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/AcraApplication.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/AcraApplication.kt @@ -148,6 +148,14 @@ class AcraApplication : Application() { _context = WeakReference(value) } + fun getKeyClass(path: String, valueType: Class): T? { + return context?.getKey(path, valueType) + } + + fun setKeyClass(path: String, value: T) { + context?.setKey(path, value) + } + fun removeKeys(folder: String): Int? { return context?.removeKeys(folder) } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/WhoIsWatchingAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/WhoIsWatchingAdapter.kt new file mode 100644 index 00000000..6b3090a9 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/WhoIsWatchingAdapter.kt @@ -0,0 +1,106 @@ +package com.lagradost.cloudstream3.ui + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.view.isVisible +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import androidx.viewbinding.ViewBinding +import com.lagradost.cloudstream3.databinding.WhoIsWatchingAccountAddBinding +import com.lagradost.cloudstream3.databinding.WhoIsWatchingAccountBinding +import com.lagradost.cloudstream3.ui.result.setImage +import com.lagradost.cloudstream3.utils.DataStoreHelper + +class WhoIsWatchingAdapter( + private val selectCallBack: (DataStoreHelper.Account) -> Unit = { }, + private val editCallBack: (DataStoreHelper.Account) -> Unit = { }, + private val addAccountCallback: () -> Unit = {} +) : + ListAdapter(DiffCallback()) { + + companion object { + const val FOOTER = 1 + const val NORMAL = 0 + } + + override fun getItemCount(): Int { + return currentList.size + 1 + } + + override fun getItemViewType(position: Int): Int = when (position) { + currentList.size -> FOOTER + else -> NORMAL + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WhoIsWatchingHolder = + WhoIsWatchingHolder( + binding = when (viewType) { + NORMAL -> WhoIsWatchingAccountBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + + FOOTER -> WhoIsWatchingAccountAddBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + + else -> throw NotImplementedError() + }, + selectCallBack = selectCallBack, + addAccountCallback = addAccountCallback, + editCallBack = editCallBack, + ) + + + override fun onBindViewHolder(holder: WhoIsWatchingHolder, position: Int) = + holder.bind(currentList.getOrNull(position)) + + class WhoIsWatchingHolder( + val binding: ViewBinding, + val selectCallBack: (DataStoreHelper.Account) -> Unit, + val addAccountCallback: () -> Unit, + val editCallBack: (DataStoreHelper.Account) -> Unit + ) : + RecyclerView.ViewHolder(binding.root) { + + fun bind(card: DataStoreHelper.Account?) { + when (binding) { + is WhoIsWatchingAccountBinding -> binding.apply { + if(card == null) return@apply + outline.isVisible = card.keyIndex == DataStoreHelper.selectedKeyIndex + profileText.text = card.name + profileImageBackground.setImage(card.image) + root.setOnClickListener { + selectCallBack(card) + } + root.setOnLongClickListener { + editCallBack(card) + return@setOnLongClickListener true + } + } + + is WhoIsWatchingAccountAddBinding -> binding.apply { + root.setOnClickListener { + addAccountCallback() + } + } + } + } + } + + class DiffCallback : DiffUtil.ItemCallback() { + override fun areItemsTheSame( + oldItem: DataStoreHelper.Account, + newItem: DataStoreHelper.Account + ): Boolean = oldItem.keyIndex == newItem.keyIndex + + override fun areContentsTheSame( + oldItem: DataStoreHelper.Account, + newItem: DataStoreHelper.Account + ): Boolean = oldItem == newItem + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapterPreview.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapterPreview.kt index 84964950..eb7b6f74 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapterPreview.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapterPreview.kt @@ -40,6 +40,7 @@ import com.lagradost.cloudstream3.utils.DataStoreHelper import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showOptionSelectStringRes import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar +import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbarMargin import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbarView import com.lagradost.cloudstream3.utils.UIHelper.setImage @@ -250,6 +251,11 @@ class HomeParentItemAdapterPreview( private var bookmarkRecyclerView: RecyclerView = itemView.findViewById(R.id.home_bookmarked_child_recyclerview) + private var homeAccount: View? = + itemView.findViewById(R.id.home_switch_account) + + private var topPadding : View? = itemView.findViewById(R.id.home_padding) + private val homeNonePadding: View = itemView.findViewById(R.id.home_none_padding) private val previewCallback: ViewPager2.OnPageChangeCallback = @@ -432,6 +438,8 @@ class HomeParentItemAdapterPreview( resumeRecyclerView.setLinearListLayout() bookmarkRecyclerView.setLinearListLayout() + fixPaddingStatusbarMargin(topPadding) + for ((chip, watch) in toggleList) { chip.isChecked = false chip.setOnCheckedChangeListener { _, isChecked -> @@ -445,6 +453,10 @@ class HomeParentItemAdapterPreview( } } + homeAccount?.setOnClickListener { v -> + DataStoreHelper.showWhoIsWatching(v?.context ?: return@setOnClickListener) + } + (binding as? FragmentHomeHeadTvBinding)?.apply { homePreviewChangeApi.setOnClickListener { view -> view.context.selectHomepage(viewModel.repo?.name) { api -> @@ -485,8 +497,6 @@ class HomeParentItemAdapterPreview( } (binding as? FragmentHomeHeadBinding)?.apply { - fixPaddingStatusbar(binding.homeSearch) - homeSearch.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String): Boolean { viewModel.queryTextSubmit(query) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt index 9b72f6c9..9739b627 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt @@ -96,8 +96,8 @@ open class FullScreenPlayer : AbstractPlayerFragment() { // protected var currentPrefQuality = // Qualities.P2160.value // preferred maximum quality, used for ppl w bad internet or on cell protected var fastForwardTime = 10000L - protected var androidTVInterfaceOffSeekTime = 10000L; - protected var androidTVInterfaceOnSeekTime = 30000L; + protected var androidTVInterfaceOffSeekTime = 10000L + protected var androidTVInterfaceOnSeekTime = 30000L protected var swipeHorizontalEnabled = false protected var swipeVerticalEnabled = false protected var playBackSpeedEnabled = false diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt index c280af59..4a807544 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt @@ -1252,7 +1252,6 @@ class GeneratorPlayer : FullScreenPlayer() { private fun displayTimeStamp(show: Boolean) { if (timestampShowState == show) return skipIndex++ - println("displayTimeStamp = $show") timestampShowState = show playerBinding?.skipChapterButton?.apply { val showWidth = 170.toPx @@ -1294,7 +1293,6 @@ class GeneratorPlayer : FullScreenPlayer() { override fun onTimestamp(timestamp: EpisodeSkip.SkipStamp?) { if (timestamp != null) { - println("timestamp: $timestamp") playerBinding?.skipChapterButton?.setText(timestamp.uiText) displayTimeStamp(true) val currentIndex = skipIndex diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt index dd2b40a3..abcef753 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt @@ -6,7 +6,12 @@ import androidx.preference.PreferenceManager import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.json.JsonMapper import com.fasterxml.jackson.module.kotlin.KotlinModule +import com.lagradost.cloudstream3.AcraApplication.Companion.getKeyClass +import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey +import com.lagradost.cloudstream3.AcraApplication.Companion.setKeyClass import com.lagradost.cloudstream3.mvvm.logError +import kotlin.reflect.KClass +import kotlin.reflect.KProperty const val DOWNLOAD_HEADER_CACHE = "download_header_cache" @@ -20,6 +25,31 @@ const val PREFERENCES_NAME = "rebuild_preference" // TODO degelgate by value for get & set +class PreferenceDelegate( + val key: String, val default: T //, private val klass: KClass +) { + private val klass: KClass = default::class + // simple cache to make it not get the key every time it is accessed, however this requires + // that ONLY this changes the key + private var cache: T? = null + + operator fun getValue(self: Any?, property: KProperty<*>) = + cache ?: getKeyClass(key, klass.java).also { newCache -> cache = newCache } ?: default + + operator fun setValue( + self: Any?, + property: KProperty<*>, + t: T? + ) { + cache = t + if (t == null) { + removeKey(key) + } else { + setKeyClass(key, t) + } + } +} + object DataStore { val mapper: JsonMapper = JsonMapper.builder().addModule(KotlinModule()) .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).build() @@ -89,7 +119,7 @@ object DataStore { } fun Context.removeKeys(folder: String): Int { - val keys = getKeys(folder) + val keys = getKeys("$folder/") keys.forEach { value -> removeKey(value) } @@ -106,6 +136,15 @@ object DataStore { } } + fun Context.getKey(path: String, valueType: Class): T? { + try { + val json: String = getSharedPrefs().getString(path, null) ?: return null + return json.toKotlinObject(valueType) + } catch (e: Exception) { + return null + } + } + fun Context.setKey(folder: String, path: String, value: T) { setKey(getFolderName(folder, path), value) } @@ -114,6 +153,10 @@ object DataStore { return mapper.readValue(this, T::class.java) } + fun String.toKotlinObject(valueType: Class): T { + return mapper.readValue(this, valueType) + } + // GET KEY GIVEN PATH AND DEFAULT VALUE, NULL IF ERROR inline fun Context.getKey(path: String, defVal: T?): T? { try { diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/DataStoreHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/DataStoreHelper.kt index 3bdb64e1..137e1457 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/DataStoreHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/DataStoreHelper.kt @@ -1,6 +1,14 @@ package com.lagradost.cloudstream3.utils +import android.content.Context +import android.content.DialogInterface +import android.text.Editable +import android.view.LayoutInflater +import androidx.appcompat.app.AlertDialog +import androidx.core.view.isGone +import androidx.core.widget.doOnTextChanged import com.fasterxml.jackson.annotation.JsonProperty +import com.google.android.material.bottomsheet.BottomSheetDialog import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.APIHolder.unixTimeMS import com.lagradost.cloudstream3.AcraApplication.Companion.getKey @@ -8,10 +16,20 @@ import com.lagradost.cloudstream3.AcraApplication.Companion.getKeys import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey import com.lagradost.cloudstream3.AcraApplication.Companion.removeKeys import com.lagradost.cloudstream3.AcraApplication.Companion.setKey +import com.lagradost.cloudstream3.CommonActivity.showToast +import com.lagradost.cloudstream3.databinding.WhoIsWatchingAccountEditBinding +import com.lagradost.cloudstream3.databinding.WhoIsWatchingBinding +import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.syncproviders.AccountManager import com.lagradost.cloudstream3.syncproviders.SyncAPI import com.lagradost.cloudstream3.ui.WatchType +import com.lagradost.cloudstream3.ui.WhoIsWatchingAdapter +import com.lagradost.cloudstream3.ui.result.UiImage import com.lagradost.cloudstream3.ui.result.VideoWatchState +import com.lagradost.cloudstream3.ui.result.setImage +import com.lagradost.cloudstream3.ui.result.setLinearListLayout +import com.lagradost.cloudstream3.utils.AppUtils.setDefaultFocus +import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe const val VIDEO_POS_DUR = "video_pos_dur" const val VIDEO_WATCH_STATE = "video_watch_state" @@ -26,6 +44,197 @@ const val RESULT_SEASON = "result_season" const val RESULT_DUB = "result_dub" object DataStoreHelper { + // be aware, don't change the index of these as Account uses the index for the art + private val profileImages = arrayOf( + R.drawable.profile_bg_dark_blue, + R.drawable.profile_bg_blue, + R.drawable.profile_bg_orange, + R.drawable.profile_bg_pink, + R.drawable.profile_bg_purple, + R.drawable.profile_bg_red, + R.drawable.profile_bg_teal + ) + + data class Account( + @JsonProperty("keyIndex") + val keyIndex: Int, + @JsonProperty("name") + val name: String, + @JsonProperty("customImage") + val customImage: String? = null, + @JsonProperty("defaultImageIndex") + val defaultImageIndex: Int, + ) { + val image: UiImage + get() = customImage?.let { UiImage.Image(it) } ?: UiImage.Drawable( + profileImages.getOrNull(defaultImageIndex) ?: profileImages.first() + ) + } + + const val TAG = "data_store_helper" + private var accounts by PreferenceDelegate("$TAG/account", arrayOf()) + var selectedKeyIndex by PreferenceDelegate("$TAG/account_key_index", 0) + val currentAccount: String get() = selectedKeyIndex.toString() + + private fun setAccount(account: Account) { + selectedKeyIndex = account.keyIndex + showToast(account.name) + MainActivity.bookmarksUpdatedEvent(true) + } + + private fun editAccount(context: Context, account: Account, isNewAccount: Boolean) { + val binding = + WhoIsWatchingAccountEditBinding.inflate(LayoutInflater.from(context), null, false) + val builder = + AlertDialog.Builder(context, R.style.AlertDialogCustom) + .setView(binding.root) + + var currentEditAccount = account + val dialog = builder.show() + binding.accountName.text = Editable.Factory.getInstance()?.newEditable(account.name) + binding.accountName.doOnTextChanged { text, _, _, _ -> + currentEditAccount = currentEditAccount.copy(name = text?.toString() ?: "") + } + + binding.deleteBtt.isGone = isNewAccount + binding.deleteBtt.setOnClickListener { + val dialogClickListener = + DialogInterface.OnClickListener { _, which -> + when (which) { + DialogInterface.BUTTON_POSITIVE -> { + // remove all keys as well as the account, note that default wont get + // deleted from currentAccounts, as it is not part of "accounts", + // but the watch keys will + removeKeys(account.keyIndex.toString()) + val currentAccounts = accounts.toMutableList() + currentAccounts.removeIf { it.keyIndex == account.keyIndex } + accounts = currentAccounts.toTypedArray() + + // update UI + setAccount(getDefaultAccount(context)) + MainActivity.bookmarksUpdatedEvent(true) + dialog?.dismissSafe() + } + + DialogInterface.BUTTON_NEGATIVE -> {} + } + } + + try { + AlertDialog.Builder(context).setTitle(R.string.delete).setMessage( + context.getString(R.string.delete_message).format( + currentEditAccount.name + ) + ) + .setPositiveButton(R.string.delete, dialogClickListener) + .setNegativeButton(R.string.cancel, dialogClickListener) + .show().setDefaultFocus() + } catch (t: Throwable) { + logError(t) + // ye you somehow fucked up formatting did you? + } + } + + binding.cancelBtt.setOnClickListener { + dialog?.dismissSafe() + } + + binding.profilePic.setImage(account.image) + binding.profilePic.setOnClickListener { + // rolls the image forwards once + currentEditAccount = + currentEditAccount.copy(defaultImageIndex = (currentEditAccount.defaultImageIndex + 1) % profileImages.size) + binding.profilePic.setImage(currentEditAccount.image) + } + + binding.applyBtt.setOnClickListener { + val currentAccounts = accounts.toMutableList() + + val overrideIndex = + currentAccounts.indexOfFirst { it.keyIndex == currentEditAccount.keyIndex } + + // if an account is found that has the same keyIndex then override that one, if not then append it + if (overrideIndex != -1) { + currentAccounts[overrideIndex] = currentEditAccount + } else { + currentAccounts.add(currentEditAccount) + } + + // set the new default account as well as add the key for the new account + setAccount(currentEditAccount) + accounts = currentAccounts.toTypedArray() + + dialog.dismissSafe() + } + } + + private fun getDefaultAccount(context: Context): Account { + return accounts.let { currentAccounts -> + currentAccounts.getOrNull(currentAccounts.indexOfFirst { it.keyIndex == 0 }) ?: Account( + keyIndex = 0, + name = context.getString(R.string.default_account), + defaultImageIndex = 0 + ) + } + } + + fun showWhoIsWatching(context: Context) { + val binding: WhoIsWatchingBinding = WhoIsWatchingBinding.inflate( + LayoutInflater.from(context) + ) + + val showAccount = accounts.toMutableList().apply { + val item = getDefaultAccount(context) + remove(item) + add(0, item) + } + + val builder = + BottomSheetDialog(context) + builder.setContentView(binding.root) + val accountName = context.getString(R.string.account) + + binding.profilesRecyclerview.setLinearListLayout(isHorizontal = true) + binding.profilesRecyclerview.adapter = WhoIsWatchingAdapter( + selectCallBack = { account -> + setAccount(account) + builder.dismissSafe() + }, + addAccountCallback = { + val currentAccounts = accounts + val remainingImages = + profileImages.toSet() - currentAccounts.filter { it.customImage == null } + .mapNotNull { profileImages.getOrNull(it.defaultImageIndex) }.toSet() + val image = + profileImages.indexOf(remainingImages.randomOrNull() ?: profileImages.random()) + val keyIndex = (currentAccounts.maxOfOrNull { it.keyIndex } ?: 0) + 1 + + // create a new dummy account + editAccount( + context, + Account( + keyIndex = keyIndex, + name = "$accountName $keyIndex", + customImage = null, + defaultImageIndex = image + ), isNewAccount = true + ) + builder.dismissSafe() + }, + editCallBack = { account -> + editAccount( + context, account, isNewAccount = false + ) + builder.dismissSafe() + } + ).apply { + submitList(showAccount) + } + + builder.show() + } + + data class PosDur( @JsonProperty("position") val position: Long, @JsonProperty("duration") val duration: Long @@ -117,7 +326,6 @@ object DataStoreHelper { /** * A datastore wide account for future implementations of a multiple account system **/ - var currentAccount: String = "0" //TODO ACCOUNT IMPLEMENTATION fun getAllWatchStateIds(): List? { val folder = "$currentAccount/$RESULT_WATCH_STATE" diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt index eb2067d6..5a393ed5 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt @@ -15,6 +15,7 @@ import android.graphics.drawable.Drawable import android.os.Build import android.os.Bundle import android.view.* +import android.view.ViewGroup.MarginLayoutParams import android.view.inputmethod.InputMethodManager import android.widget.ImageView import android.widget.ListAdapter @@ -33,6 +34,10 @@ import androidx.core.graphics.blue import androidx.core.graphics.drawable.toBitmapOrNull import androidx.core.graphics.green import androidx.core.graphics.red +import androidx.core.view.marginBottom +import androidx.core.view.marginLeft +import androidx.core.view.marginRight +import androidx.core.view.marginTop import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity import androidx.navigation.fragment.NavHostFragment @@ -55,7 +60,6 @@ import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.ui.result.UiImage import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isEmulatorSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings -import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute import jp.wasabeef.glide.transformations.BlurTransformation import kotlin.math.roundToInt @@ -77,8 +81,8 @@ object UIHelper { || Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) } - fun populateChips(view: ChipGroup?, tags : List) { - if(view == null) return + fun populateChips(view: ChipGroup?, tags: List) { + if (view == null) return view.removeAllViews() val context = view.context ?: return @@ -304,7 +308,7 @@ object UIHelper { else req } - if(radius > 0) { + if (radius > 0) { builder = builder.apply(bitmapTransform(BlurTransformation(radius, sample))) } @@ -496,6 +500,22 @@ object UIHelper { ) } + fun fixPaddingStatusbarMargin(v: View?) { + if (v == null) return + val ctx = v.context ?: return + + v.layoutParams = v.layoutParams.apply { + if (this is MarginLayoutParams) { + setMargins( + v.marginLeft, + v.marginTop + ctx.getStatusBarHeight(), + v.marginRight, + v.marginBottom + ) + } + } + } + fun fixPaddingStatusbarView(v: View?) { if (v == null) return val ctx = v.context ?: return diff --git a/app/src/main/res/drawable/ic_outline_account_circle_24.xml b/app/src/main/res/drawable/ic_outline_account_circle_24.xml index cc564471..27c2d574 100644 --- a/app/src/main/res/drawable/ic_outline_account_circle_24.xml +++ b/app/src/main/res/drawable/ic_outline_account_circle_24.xml @@ -1,6 +1,13 @@ - - - + + + diff --git a/app/src/main/res/drawable/outline_card.xml b/app/src/main/res/drawable/outline_card.xml index 02116bb8..5716de45 100644 --- a/app/src/main/res/drawable/outline_card.xml +++ b/app/src/main/res/drawable/outline_card.xml @@ -1,21 +1,20 @@ + android:color="@android:color/white"> - + android:width="2dp" + android:color="@android:color/white" /> + - + - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home_head.xml b/app/src/main/res/layout/fragment_home_head.xml index 603621f7..d8b5dfe5 100644 --- a/app/src/main/res/layout/fragment_home_head.xml +++ b/app/src/main/res/layout/fragment_home_head.xml @@ -38,16 +38,21 @@ + android:layout_height="50dp" + android:gravity="center" + android:orientation="horizontal"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 6a1e9eac..4dd6eadc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -307,6 +307,7 @@ queued No Subtitles Default + @string/default_subtitles Free Used App