diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index 0e52baff6..604695859 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -701,23 +701,6 @@ class HomeFragment : BaseFragment( homeViewModel.queryTextSubmit("") } - // Load value for toggling Tv layout real time clock. Hide by default at startup - // set visibility first, to apply a scroll effect later - context?.let { - if (isLayout(TV)) { - val settingsManager = PreferenceManager.getDefaultSharedPreferences(it) - val toggleClock = - settingsManager.getBoolean( - getString(R.string.tv_layout_clock_key), - false - ) - binding.homeClock.isVisible = toggleClock - } else { - binding.homeClock.isVisible = false - } - } - - homeMasterRecycler.addOnScrollListener(object : RecyclerView.OnScrollListener() { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { if (isLayout(PHONE)) { @@ -757,17 +740,6 @@ class HomeFragment : BaseFragment( view.getLocationInWindow(rect) scrollParent.isVisible = true scrollParent.translationY = rect[1].toFloat() - 60.toPx - - // Move the TV layout real time clock out of the way too - // We check if we have the correct layout and if the clock is enabled - if(isLayout(TV) && binding.homeClock.isVisible) { - val scrollParent = binding.homeClock - - val rect = IntArray(2) - view.getLocationInWindow(rect) - scrollParent.isVisible = true - scrollParent.translationY = rect[1].toFloat() - 60.toPx - } } } super.onScrolled(recyclerView, dx, dy) 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 d90b6043f..20c37dcf4 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 @@ -307,7 +307,6 @@ open class FullScreenPlayer : AbstractPlayerFragment( playerVideoTitleRez, playerVideoInfo, playerGoBackHolder, - playerVideoClock, ).forEach { it.animateY(titleMove) } @@ -773,7 +772,7 @@ open class FullScreenPlayer : AbstractPlayerFragment( val showPlayerEpisodes = !isGone && isThereEpisodes() playerEpisodesButtonRoot.isVisible = showPlayerEpisodes playerEpisodesButton.isVisible = showPlayerEpisodes - playerVideoTitleHolder.isGone = togglePlayerTitleGone || playerVideoTitle.text.isBlank() + playerVideoTitleHolder.isGone = togglePlayerTitleGone playerVideoTitleRez.isGone = isGone || playerVideoTitleRez.text.isBlank() playerEpisodeFiller.isGone = isGone playerCenterMenu.isGone = isGone 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 4495a5602..91e3ff970 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 @@ -8,7 +8,6 @@ import android.content.Context import android.content.Intent import android.content.res.ColorStateList import android.graphics.Bitmap -import android.graphics.Typeface import android.os.Build import android.os.Bundle import android.text.Spanned @@ -80,7 +79,6 @@ import com.lagradost.cloudstream3.ui.player.CS3IPlayer.Companion.preferredAudioT import com.lagradost.cloudstream3.ui.player.CustomDecoder.Companion.updateForcedEncoding import com.lagradost.cloudstream3.ui.player.PlayerSubtitleHelper.Companion.toSubtitleMimeType import com.lagradost.cloudstream3.ui.player.source_priority.LinkSource -import com.lagradost.cloudstream3.ui.player.source_priority.ProfileSettings import com.lagradost.cloudstream3.ui.player.source_priority.QualityDataHelper import com.lagradost.cloudstream3.ui.player.source_priority.QualityDataHelper.getLinkPriority import com.lagradost.cloudstream3.ui.player.source_priority.QualityProfileDialog @@ -134,7 +132,6 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import java.io.Serializable -import java.lang.ref.WeakReference import java.util.Calendar import java.util.UUID import java.util.concurrent.ConcurrentHashMap @@ -513,7 +510,7 @@ class GeneratorPlayer : FullScreenPlayer() { showDownloadProgress(DownloadEvent(0, 0, 0, null)) // uiReset() // Removed due to UX - + currentSelectedLink = link // setEpisodes(viewModel.getAllMeta() ?: emptyList()) setPlayerDimen(null) @@ -1115,29 +1112,21 @@ class GeneratorPlayer : FullScreenPlayer() { var sourceIndex = 0 var startSource = 0 - // Filtered and sorted links - var currentHiddenFooter: View? = null - var filteredLinks: List = emptyList() + var sortedUrls = emptyList>() fun refreshLinks(qualityProfile: Int) { - val currentLinkUsed = currentSelectedLink - // Always display current linkFooter - val sortedLinks = viewModel.state.sortLinks(qualityProfile) - - filteredLinks = sortedLinks.filter { it.shouldUseLink || it.link == currentLinkUsed } - - if (sortedLinks.isEmpty()) { + sortedUrls = viewModel.state.sortLinks(qualityProfile) + if (sortedUrls.isEmpty()) { sourceDialog.findViewById(R.id.sort_sources_holder)?.isGone = true } else { - startSource = filteredLinks.indexOfFirst { it.link == currentLinkUsed } + startSource = sortedUrls.indexOf(currentSelectedLink) sourceIndex = startSource val sourcesArrayAdapter = ArrayAdapter(ctx, R.layout.sort_bottom_single_choice) - sourcesArrayAdapter.addAll(filteredLinks.map { displayLink -> - val (link, uri) = displayLink.link + sourcesArrayAdapter.addAll(sortedUrls.map { (link, uri) -> val name = link?.name ?: uri?.name ?: "NULL" "$name ${Qualities.getStringByInt(link?.quality)}" }) @@ -1153,7 +1142,7 @@ class GeneratorPlayer : FullScreenPlayer() { } providerList.setOnItemLongClickListener { _, _, position, _ -> - sortedLinks.getOrNull(position)?.link?.first?.url?.let { + sortedUrls.getOrNull(position)?.first?.url?.let { clipboardHelper( txt(R.string.video_source), it @@ -1161,25 +1150,6 @@ class GeneratorPlayer : FullScreenPlayer() { } true } - - val hiddenLinks = sortedLinks.size - filteredLinks.size - providerList.removeFooterView(currentHiddenFooter) - - if (hiddenLinks > 0) { - val hiddenLinksFooter: TextView = layoutInflater.inflate( - R.layout.sort_bottom_footer_add_choice, null - ) as TextView - - providerList.addFooterView(hiddenLinksFooter, null, false) - currentHiddenFooter = hiddenLinksFooter - - val hiddenLinksText = - ctx.resources.getQuantityString(R.plurals.links_hidden, hiddenLinks) - .format(hiddenLinks) - hiddenLinksFooter.text = hiddenLinksText - hiddenLinksFooter.setCompoundDrawables(null, null, null, null) - hiddenLinksFooter.setTypeface(null, Typeface.ITALIC) - } } } @@ -1393,8 +1363,8 @@ class GeneratorPlayer : FullScreenPlayer() { } } if (init) { - filteredLinks.getOrNull(sourceIndex)?.let { - loadLink(it.link, true) + sortedUrls.getOrNull(sourceIndex)?.let { + loadLink(it, true) } } sourceDialog.dismissSafe(activity) @@ -1562,10 +1532,6 @@ class GeneratorPlayer : FullScreenPlayer() { } override fun playerError(exception: Throwable) { - currentSelectedLink?.let { link -> - viewModel.modifyState { this.addError(link) } - } - val currentUrl = currentSelectedLink?.let { it.first?.url ?: it.second?.uri?.toString() } ?: "unknown" val headers = currentSelectedLink?.first?.headers?.toString() ?: "none" @@ -1588,22 +1554,8 @@ class GeneratorPlayer : FullScreenPlayer() { private fun noLinksFound() { viewModel.forceClearCache = true - val hiddenLinks = viewModel.state.sortLinks(currentQualityProfile).count { !it.shouldUseLink } - - context?.let { ctx -> - // Display that there are hidden links to the user. - if (hiddenLinks > 0) { - val noLinksString = ctx.getString(R.string.no_links_found_toast) - val hiddenString = - ctx.resources.getQuantityString(R.plurals.links_hidden, hiddenLinks) - .format(hiddenLinks) - val toastText = "$noLinksString\n($hiddenString)" - showToast(toastText, Toast.LENGTH_SHORT) - } else { - showToast(R.string.no_links_found_toast, Toast.LENGTH_SHORT) - } - } + showToast(R.string.no_links_found_toast, Toast.LENGTH_SHORT) activity?.popCurrentPage() } @@ -1614,9 +1566,7 @@ class GeneratorPlayer : FullScreenPlayer() { } val links = viewModel.state.sortLinks(currentQualityProfile) - - val firstAvailableLink = links.firstOrNull { it.shouldUseLink }?.link - if (firstAvailableLink == null) { + if (links.isEmpty()) { noLinksFound() return } @@ -1624,7 +1574,7 @@ class GeneratorPlayer : FullScreenPlayer() { if (!isPlayerActive.compareAndSet(false, true)) { return } - loadLink(firstAvailableLink, false) + loadLink(links.first(), false) showPlayerMetadata() } @@ -1691,26 +1641,25 @@ class GeneratorPlayer : FullScreenPlayer() { } } - private fun getNextLink(): DisplayLink? { - val links = viewModel.state.sortLinks(currentQualityProfile) - val currentIndex = links.indexOfFirst { it.link == currentSelectedLink } - val nextPotentialLink = - links.withIndex().firstOrNull { it.index > currentIndex && it.value.shouldUseLink } - return nextPotentialLink?.value - } - override fun hasNextMirror(): Boolean { - return getNextLink() != null + val links = viewModel.state.sortLinks(currentQualityProfile) + return links.isNotEmpty() && links.indexOf(currentSelectedLink) + 1 < links.size } override fun nextMirror() { - val nextLink = getNextLink() - if (nextLink == null) { + val links = viewModel.state.sortLinks(currentQualityProfile) + if (links.isEmpty()) { noLinksFound() return } - loadLink(nextLink.link, true) + val newIndex = links.indexOf(currentSelectedLink) + 1 + if (newIndex >= links.size) { + noLinksFound() + return + } + + loadLink(links[newIndex], true) } override fun onDestroy() { @@ -2217,7 +2166,6 @@ class GeneratorPlayer : FullScreenPlayer() { isPlayerActive.set(false) binding?.overlayLoadingSkipButton?.isVisible = false binding?.playerLoadingOverlay?.isVisible = true - viewModel.modifyState { setError(emptyList()) } uiReset() } @@ -2271,14 +2219,6 @@ class GeneratorPlayer : FullScreenPlayer() { fromTagToEnglishLanguageName(it)?.lowercase() ?: return@mapNotNull null } ?: listOf() } - - // Set up TV clock visibility - if (isLayout(TV)) { - val showTvClock = settingsManager.getBoolean(ctx.getString(R.string.tv_layout_clock_key), false) - playerBinding?.playerVideoClock?.isVisible = showTvClock - } else { - playerBinding?.playerVideoClock?.isVisible = false - } } unwrapBundle(savedInstanceState) @@ -2357,23 +2297,19 @@ class GeneratorPlayer : FullScreenPlayer() { } } - observe(viewModel.currentLinks) { (_, instance) -> + observe(viewModel.currentLinks) { (links, instance) -> if (instance != viewModel.state.instance) return@observe // Outdated observe - val sortedLinks = viewModel.state.sortLinks(currentQualityProfile) - val usableLinks = sortedLinks.count { link -> link.shouldUseLink } - - val turnVisible = usableLinks > 0 && viewModel.generator?.canSkipLoading == true + val turnVisible = links.isNotEmpty() && viewModel.generator?.canSkipLoading == true val wasGone = binding.overlayLoadingSkipButton.isGone binding.overlayLoadingSkipButton.apply { isVisible = turnVisible - - if (usableLinks == 0) { + if (links.isEmpty()) { setText(R.string.skip_loading) } else { @SuppressLint("SetTextI18n") - text = "${context.getString(R.string.skip_loading)} (${usableLinks})" + text = "${context.getString(R.string.skip_loading)} (${links.size})" } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerGeneratorViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerGeneratorViewModel.kt index cb8cf8bff..e3c390d50 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerGeneratorViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerGeneratorViewModel.kt @@ -10,8 +10,6 @@ import com.lagradost.cloudstream3.mvvm.Resource import com.lagradost.cloudstream3.mvvm.launchSafe import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.safeApiCall -import com.lagradost.cloudstream3.ui.player.source_priority.ProfileSettings -import com.lagradost.cloudstream3.ui.player.source_priority.QualityDataHelper import com.lagradost.cloudstream3.ui.player.source_priority.QualityDataHelper.getLinkPriority import com.lagradost.cloudstream3.ui.result.ResultEpisode import com.lagradost.cloudstream3.utils.Coroutines.ioSafe @@ -42,20 +40,12 @@ data class GeneratorState( val id: Int?, ) -data class DisplayLink( - val link: VideoLink, - // If the link should be displayed and used by the player - val shouldUseLink: Boolean, - val priority: Int -) - /** Immutable state of all current links relevant to displaying the video */ // @MustUseReturnValues // @Immutable data class VideoState( val subtitles: PersistentSet = persistentSetOf(), val links: PersistentSet = persistentSetOf(), - val erroredLinks: PersistentSet = persistentSetOf(), val stamps: PersistentList = persistentListOf(), val loading: Resource = Resource.Loading(), val generatorState: GeneratorState? = null, @@ -66,52 +56,19 @@ data class VideoState( * * sortedBy is not exactly expensive, but each hasNextMirror does it again, so this alleviates unnecessary recomputation * */ - private val sortedLinks: ConcurrentHashMap> = ConcurrentHashMap() + private val sortedLinks: ConcurrentHashMap> = ConcurrentHashMap() - /** - * The cache is guaranteed to be up to date link-wise due to the immutable links. - * However, hideNegativeSources and hideErrorSources could be updated, which requires clearing the cache. - */ fun clearSortedLinksCache() = sortedLinks.clear() - private fun hasLinkErrored(link: VideoLink): Boolean { - return erroredLinks.any { it == link } - } - - private fun VideoLink.toDisplayLink( - qualityProfile: Int, - hideNegativeSources: Boolean, - hideErrorSources: Boolean - ): DisplayLink { - val priority = getLinkPriority(qualityProfile, this.first) - val shouldHideLink = - (hideNegativeSources && priority < 0) || (hideErrorSources && hasLinkErrored(this)) - val displayLink = DisplayLink(this, !shouldHideLink, priority) - - return displayLink - } - // Modifying sortedLinks is not considered a "visible" side effect, and rerunning it does not change the result // It is by all standards, idempotent and by extension also pure as it has no "visible" side effect /** Returns .links in the sorted order according to the qualityProfile. * Use .links if order is not needed */ @Contract(pure = true) - fun sortLinks(qualityProfile: Int): List { - sortedLinks[qualityProfile]?.let { - return it - } - - val hideNegativeSources = - QualityDataHelper.getProfileSetting(qualityProfile, ProfileSettings.HideNegativeSources) - val hideErrorSources = - QualityDataHelper.getProfileSetting(qualityProfile, ProfileSettings.HideErrorSources) - - return links.map { link -> + fun sortLinks(qualityProfile: Int): List { + return sortedLinks[qualityProfile] ?: links.sortedBy { link -> // negative because we want to sort highest quality first - link.toDisplayLink(qualityProfile, hideNegativeSources, hideErrorSources) - }.sortedBy { - // negative because we want to sort highest quality first - -it.priority + -getLinkPriority(qualityProfile, link.first) }.also { value -> sortedLinks[qualityProfile] = value } } @@ -156,12 +113,6 @@ data class VideoState( @JvmName("setVideoSkipStamp") @Contract(pure = true) fun set(items: Collection): VideoState = copy(stamps = items.toPersistentList()) - - @Contract(pure = true) - fun addError(item: VideoLink): VideoState = copy(erroredLinks = erroredLinks.add(item)) - - @Contract(pure = true) - fun setError(items: Collection): VideoState = copy(erroredLinks = items.toPersistentSet()) } data class VideoLive( @@ -190,8 +141,9 @@ class PlayerGeneratorViewModel : ViewModel() { var state = VideoState(instance = 0) private set - private val _currentLinks = MutableLiveData>>(null) - val currentLinks: LiveData>> = _currentLinks + private val _currentLinks = + MutableLiveData>>>(null) + val currentLinks: LiveData>>> = _currentLinks private val _currentSubtitles = MutableLiveData>>(null) val currentSubtitles: LiveData>> = _currentSubtitles diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/QualityDataHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/QualityDataHelper.kt index d8d47bd10..15d25148c 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/QualityDataHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/QualityDataHelper.kt @@ -12,16 +12,12 @@ import com.lagradost.cloudstream3.utils.txt import com.lagradost.cloudstream3.utils.DataStoreHelper.currentAccount import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.Qualities -import java.util.EnumMap -import java.util.concurrent.ConcurrentHashMap -import kotlin.also import kotlin.math.abs object QualityDataHelper { private const val VIDEO_SOURCE_PRIORITY = "video_source_priority" private const val VIDEO_PROFILE_NAME = "video_profile_name" private const val VIDEO_QUALITY_PRIORITY = "video_quality_priority" - const val VIDEO_PROFILE_SETTINGS = "video_profile_settings" // Old key only supporting one type per profile @Deprecated("Changed to support multiple types per profile") @@ -57,21 +53,13 @@ object QualityDataHelper { val types: Set ) - - // Map profile and name to priority - val sourcePriorityCache: ConcurrentHashMap> = ConcurrentHashMap() - fun getSourcePriority(profile: Int, name: String?): Int { if (name == null) return DEFAULT_SOURCE_PRIORITY - - return sourcePriorityCache[profile]?.get(name) ?: (getKey( + return getKey( "$currentAccount/$VIDEO_SOURCE_PRIORITY/$profile", name, DEFAULT_SOURCE_PRIORITY - ) ?: DEFAULT_SOURCE_PRIORITY).also { - sourcePriorityCache.getOrPut(profile) { hashMapOf() } - sourcePriorityCache[profile]?.set(name, it) - } + ) ?: DEFAULT_SOURCE_PRIORITY } fun getAllSourcePriorityNames(profile: Int): List { @@ -89,8 +77,6 @@ object QualityDataHelper { } else { setKey(folder, name, priority) } - - sourcePriorityCache[profile]?.set(name, priority) } fun setProfileName(profile: Int, name: String?) { @@ -107,17 +93,12 @@ object QualityDataHelper { ?: txt(R.string.profile_number, profile) } - // Map profile and quality to priority - val qualityPriorityCache: ConcurrentHashMap> = ConcurrentHashMap() fun getQualityPriority(profile: Int, quality: Qualities): Int { - return qualityPriorityCache[profile]?.get(quality) ?: (getKey( + return getKey( "$currentAccount/$VIDEO_QUALITY_PRIORITY/$profile", quality.value.toString(), quality.defaultPriority - )?.also { - qualityPriorityCache.getOrPut(profile) { EnumMap(Qualities::class.java) } - qualityPriorityCache[profile]?.set(quality, it) - }) ?: quality.defaultPriority + ) ?: quality.defaultPriority } fun setQualityPriority(profile: Int, quality: Qualities, priority: Int) { @@ -126,24 +107,8 @@ object QualityDataHelper { quality.value.toString(), priority ) - qualityPriorityCache[profile]?.set(quality, priority) } - fun setProfileSetting(profile: Int, setting: ProfileSettings, value: T) { - val folder = "$currentAccount/$VIDEO_PROFILE_SETTINGS/$profile" - // Prevent unnecessary keys - if (value == setting.defaultValue) { - removeKey(folder, setting.key) - } else { - setKey(folder, setting.key, value) - } - } - - inline fun getProfileSetting(profile: Int, setting: ProfileSettings): T { - val folder = "$currentAccount/$VIDEO_PROFILE_SETTINGS/$profile" - val value = getKey(folder, setting.key) - return value ?: setting.defaultValue - } @Suppress("DEPRECATION") fun getQualityProfileTypes(profile: Int): Set { @@ -259,8 +224,3 @@ object QualityDataHelper { return Qualities.entries.minBy { abs(it.value - target) } } } - -sealed class ProfileSettings(val key: String, val defaultValue: T) { - object HideErrorSources : ProfileSettings("hide_error_sources", false) - object HideNegativeSources : ProfileSettings("hide_negative_sources", false) -} diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/SourcePriorityDialog.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/SourcePriorityDialog.kt index 604ec3149..c8ac96ebb 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/SourcePriorityDialog.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/SourcePriorityDialog.kt @@ -14,7 +14,7 @@ import com.lagradost.cloudstream3.utils.UIHelper.fixSystemBarsPadding class SourcePriorityDialog( val ctx: Context, - @StyleRes val themeRes: Int, + @StyleRes themeRes: Int, val links: List, private val profile: QualityDataHelper.QualityProfile, /** @@ -28,79 +28,76 @@ class SourcePriorityDialog( PlayerSelectSourcePriorityBinding.inflate(LayoutInflater.from(ctx), null, false) setContentView(binding.root) fixSystemBarsPadding(binding.root) + val sourcesRecyclerView = binding.sortSources + val qualitiesRecyclerView = binding.sortQualities + val profileText = binding.profileTextEditable + val saveBtt = binding.saveBtt + val exitBtt = binding.closeBtt + val helpBtt = binding.helpBtt - binding.apply { - profileTextEditable.setText( - QualityDataHelper.getProfileName(profile.id).asString(context) - ) - profileTextEditable.hint = txt(R.string.profile_number, profile.id).asString(context) + profileText.setText(QualityDataHelper.getProfileName(profile.id).asString(context)) + profileText.hint = txt(R.string.profile_number, profile.id).asString(context) - sortSources.adapter = PriorityAdapter( - ).apply { - val sortedLinks = links.map { link -> - SourcePriority( - null, - link.source, - QualityDataHelper.getSourcePriority(profile.id, link.source) - ) - }.distinctBy { it.name }.sortedBy { -it.priority } - - submitList(sortedLinks) - } - - sortQualities.adapter = PriorityAdapter( - ).apply { - submitList(Qualities.entries.mapNotNull { - SourcePriority( - it, - Qualities.getStringByIntFull(it.value).ifBlank { return@mapNotNull null }, - QualityDataHelper.getQualityPriority(profile.id, it) - ) - }.sortedBy { -it.priority }) - } - - @Suppress("UNCHECKED_CAST") // We know the types - saveBtt.setOnClickListener { - val qualityAdapter = sortQualities.adapter as? PriorityAdapter - val sourcesAdapter = sortSources.adapter as? PriorityAdapter - - val qualities = qualityAdapter?.immutableCurrentList ?: emptyList() - val sources = sourcesAdapter?.immutableCurrentList ?: emptyList() - - qualities.forEach { - QualityDataHelper.setQualityPriority(profile.id, it.data, it.priority) - } - - sources.forEach { - QualityDataHelper.setSourcePriority(profile.id, it.name, it.priority) - } - - qualityAdapter?.submitList(qualities.sortedBy { -it.priority }) - sourcesAdapter?.submitList(sources.sortedBy { -it.priority }) - - val savedProfileName = profileTextEditable.text.toString() - if (savedProfileName.isBlank()) { - QualityDataHelper.setProfileName(profile.id, null) - } else { - QualityDataHelper.setProfileName(profile.id, savedProfileName) - } - updatedCallback.invoke() - } - - closeBtt.setOnClickListener { - dismissSafe() - } - - helpBtt.setOnClickListener { - AlertDialog.Builder(context, R.style.AlertDialogCustom).apply { - setMessage(R.string.quality_profile_help) - }.show() - } - - settingsBtt.setOnClickListener { - SourceProfileSettingsDialog(ctx, themeRes, profile.id).show() - } + sourcesRecyclerView.adapter = PriorityAdapter( + ).apply { + submitList(links.map { link -> + SourcePriority( + null, + link.source, + QualityDataHelper.getSourcePriority(profile.id, link.source) + ) + }.distinctBy { it.name }.sortedBy { -it.priority }) } + + qualitiesRecyclerView.adapter = PriorityAdapter( + ).apply { + submitList(Qualities.entries.mapNotNull { + SourcePriority( + it, + Qualities.getStringByIntFull(it.value).ifBlank { return@mapNotNull null }, + QualityDataHelper.getQualityPriority(profile.id, it) + ) + }.sortedBy { -it.priority }) + } + + @Suppress("UNCHECKED_CAST") // We know the types + saveBtt.setOnClickListener { + val qualityAdapter = qualitiesRecyclerView.adapter as? PriorityAdapter + val sourcesAdapter = sourcesRecyclerView.adapter as? PriorityAdapter + + val qualities = qualityAdapter?.immutableCurrentList ?: emptyList() + val sources = sourcesAdapter?.immutableCurrentList ?: emptyList() + + qualities.forEach { + QualityDataHelper.setQualityPriority(profile.id, it.data, it.priority) + } + + sources.forEach { + QualityDataHelper.setSourcePriority(profile.id, it.name, it.priority) + } + + qualityAdapter?.submitList(qualities.sortedBy { -it.priority }) + sourcesAdapter?.submitList(sources.sortedBy { -it.priority }) + + val savedProfileName = profileText.text.toString() + if (savedProfileName.isBlank()) { + QualityDataHelper.setProfileName(profile.id, null) + } else { + QualityDataHelper.setProfileName(profile.id, savedProfileName) + } + updatedCallback.invoke() + } + + exitBtt.setOnClickListener { + this.dismissSafe() + } + + helpBtt.setOnClickListener { + AlertDialog.Builder(context, R.style.AlertDialogCustom).apply { + setMessage(R.string.quality_profile_help) + }.show() + } + super.show() } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/SourceProfileSettingsDialog.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/SourceProfileSettingsDialog.kt deleted file mode 100644 index c26955b5e..000000000 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/SourceProfileSettingsDialog.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.lagradost.cloudstream3.ui.player.source_priority - -import android.app.Dialog -import android.content.Context -import android.view.LayoutInflater -import androidx.annotation.StyleRes -import com.lagradost.cloudstream3.databinding.SourceProfileSettingsDialogBinding -import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe -import com.lagradost.cloudstream3.utils.UIHelper.fixSystemBarsPadding - -class SourceProfileSettingsDialog( - val ctx: Context, - @StyleRes themeRes: Int, - val profile: Int -) : Dialog(ctx, themeRes) { - override fun show() { - val binding = - SourceProfileSettingsDialogBinding.inflate(LayoutInflater.from(ctx), null, false) - setContentView(binding.root) - fixSystemBarsPadding(binding.root) - - binding.apply { - var hideErrorSources = QualityDataHelper.getProfileSetting(profile, ProfileSettings.HideErrorSources) - var hideNegativeSources = QualityDataHelper.getProfileSetting(profile, ProfileSettings.HideNegativeSources) - - profileHideErrorSources.isChecked = hideErrorSources - profileHideErrorSources.setOnCheckedChangeListener { _, bool -> - hideErrorSources = bool - } - - profileHideNegativeSources.isChecked = hideNegativeSources - profileHideNegativeSources.setOnCheckedChangeListener { _, bool -> - hideNegativeSources = bool - } - - applyBtt.setOnClickListener { - QualityDataHelper.setProfileSetting(profile, ProfileSettings.HideErrorSources, hideErrorSources) - QualityDataHelper.setProfileSetting(profile, ProfileSettings.HideNegativeSources, hideNegativeSources) - dismissSafe() - } - - cancelBtt.setOnClickListener { - dismissSafe() - } - } - super.show() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt index b04f9a4a2..354424978 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt @@ -77,7 +77,6 @@ val appLanguages = arrayListOf( Pair("Azərbaycan dili", "az"), Pair("Bahasa Indonesia", "in"), Pair("Bahasa Melayu", "ms"), - Pair("català", "ca"), Pair("Deutsch", "de"), Pair("English", "en"), Pair("Español", "es"), @@ -98,7 +97,6 @@ val appLanguages = arrayListOf( Pair("Português", "pt"), Pair("Português (Brasil)", "pt-BR"), Pair("Română", "ro"), - Pair("Shqip мова", "sq"), Pair("Slovenčina", "sk"), Pair("Soomaaliga", "so"), Pair("Svenska", "sv"), @@ -108,7 +106,6 @@ val appLanguages = arrayListOf( Pair("Wikang Filipino", "fil"), Pair("Čeština", "cs"), Pair("Ελληνικά", "el"), - Pair("беларуская мова", "be"), Pair("български", "bg"), Pair("македонски", "mk"), Pair("русский", "ru"), 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 5f86a3a5a..f4c522bf9 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 @@ -228,8 +228,6 @@ class SettingsUI : BasePreferenceFragmentCompat() { return@setOnPreferenceClickListener true } - getPref(R.string.tv_layout_clock_key)?.hideOn(PHONE or EMULATOR) - getPref(R.string.confirm_exit_key)?.setOnPreferenceClickListener { val prefNames = resources.getStringArray(R.array.confirm_exit) val prefValues = resources.getIntArray(R.array.confirm_exit_values) 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 68f262d8d..02ee69791 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/DataStore.kt @@ -181,11 +181,11 @@ object DataStore { } fun Context.getKey(path: String, valueType: Class): T? { - return try { + try { val json: String = getSharedPrefs().getString(path, null) ?: return null - parseJson(json, valueType.kotlin) - } catch (_: Exception) { - null + return parseJson(json, valueType.kotlin) + } catch (e: Exception) { + return null } } @@ -193,37 +193,21 @@ object DataStore { setKey(getFolderName(folder, path), value) } - @Deprecated( - message = "Use parseJson(this) directly instead.", - level = DeprecationLevel.WARNING, - replaceWith = ReplaceWith( - expression = "parseJson(this)", - imports = ["com.lagradost.cloudstream3.utils.AppUtils.parseJson"], - ), - ) inline fun String.toKotlinObject(): T { return parseJson(this) } - @Deprecated( - message = "Use parseJson(this) directly instead.", - level = DeprecationLevel.WARNING, - replaceWith = ReplaceWith( - expression = "parseJson(this)", - imports = ["com.lagradost.cloudstream3.utils.AppUtils.parseJson"], - ), - ) fun String.toKotlinObject(valueType: Class): T { return parseJson(this, valueType.kotlin) } // GET KEY GIVEN PATH AND DEFAULT VALUE, NULL IF ERROR inline fun Context.getKey(path: String, defVal: T?): T? { - return try { + try { val json: String = getSharedPrefs().getString(path, null) ?: return defVal - parseJson(json) - } catch (_: Exception) { - null + return json.toKotlinObject() + } catch (e: Exception) { + return null } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/TvChannelUtils.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/TvChannelUtils.kt index b5b367262..4c0717b3f 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/TvChannelUtils.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/TvChannelUtils.kt @@ -149,12 +149,10 @@ object TvChannelUtils { .setInputId(inputId) .build() - val channelUri = runCatching { - context.contentResolver.insert( - TvContractCompat.Channels.CONTENT_URI, - channel.toContentValues() - ) - }.getOrNull() + val channelUri = context.contentResolver.insert( + TvContractCompat.Channels.CONTENT_URI, + channel.toContentValues() + ) channelUri?.let { val channelId = ContentUris.parseId(it) diff --git a/app/src/main/res/drawable/ic_baseline_clock_24.xml b/app/src/main/res/drawable/ic_baseline_clock_24.xml deleted file mode 100644 index 3436c6208..000000000 --- a/app/src/main/res/drawable/ic_baseline_clock_24.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/layout-port/player_select_source_priority.xml b/app/src/main/res/layout-port/player_select_source_priority.xml index 926227c58..2cba9c869 100644 --- a/app/src/main/res/layout-port/player_select_source_priority.xml +++ b/app/src/main/res/layout-port/player_select_source_priority.xml @@ -1,5 +1,6 @@ - - + @@ -32,21 +33,14 @@ android:textSize="20sp" android:textStyle="bold" /> - - + android:src="@drawable/baseline_help_outline_24" + android:contentDescription="@string/help" /> - + + tools:text="@string/profile_number" + tools:ignore="LabelFor" /> + android:text="@string/sort_save" + style="@style/WhiteButton" /> + android:text="@string/sort_close" + style="@style/BlackButton" /> diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 8d78c01b3..99a764dee 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -227,12 +227,6 @@ tools:listitem="@layout/homepage_parent" tools:visibility="gone" /> - - - - - - - diff --git a/app/src/main/res/layout/player_custom_layout_tv.xml b/app/src/main/res/layout/player_custom_layout_tv.xml index c6445d80f..88e4cd984 100644 --- a/app/src/main/res/layout/player_custom_layout_tv.xml +++ b/app/src/main/res/layout/player_custom_layout_tv.xml @@ -352,22 +352,6 @@ android:layout_marginEnd="32dp" android:orientation="vertical"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/trailer_custom_layout.xml b/app/src/main/res/layout/trailer_custom_layout.xml index b1dc96479..ddaa53464 100644 --- a/app/src/main/res/layout/trailer_custom_layout.xml +++ b/app/src/main/res/layout/trailer_custom_layout.xml @@ -171,12 +171,6 @@ android:layout_marginEnd="32dp" android:orientation="vertical"> - - পোস্টার ক্লাউডস্ট্রিম দিয়ে চালান হোম - অভিনয়ে: %s + অভিনয়েঃ %s %1$dদিন %2$dঘন্টা %3$dমিনিট %1$dঘন্টা %2$dমিনিট %d মিনিট @@ -22,7 +22,7 @@ খুঁজুন ডাউনলোডসমূহ সেটিংস - %1$s পর্ব %2$d + %1$s এপি %2$d পর্ব %d মুক্তির তারিখ শেয়ার ব্রাউজারে খুলুন @@ -131,8 +131,8 @@ স্টোরেজ এর অনুমতি অনুপস্থিত। দয়া করে আবার চেষ্টা করুন। তথ্য ট্রেইলার প্রদর্শন করুন - Kitsu থেকে পোস্টারসমূহ প্রদর্শন করুন - স্বয়ংক্রিয় প্লাগইন আপডেট + কিটসু হতে পোস্টারসমূহ প্রদর্শন করুন + স্বয়ংক্রিয়ভাবে প্লাগিন এর হালনাগাদ স্বয়ংক্রিয়ভাবে প্লাগিনসমুহের ডাউনলোড হালনাগাদ ও ব্যাকআপ অ্যাপ এর হালনাগাদ দেখান @@ -148,9 +148,9 @@ সামনে বা পিছনের দিকে যেতে ডান বা বাম দিকে দুবার আলতো চাপুন ফাইল ডিলিট মান ডিফল্ট এ রিসেট করুন - স্টার্টআপে নতুন আপডেটের জন্য স্বয়ংক্রিয়ভাবে অনুসন্ধান করুন যোগ। + স্টার্টআপে নতুন আপডেটের জন্য স্বয়ংক্রিয়ভাবে অনুসন্ধান করুন সিনেমা - অ্যানিমে ফিলার পর্ব প্রদর্শন + এনিমে এর ফিলার পর্ব দেখায় টিভি সিরিজ লিংক পাওয়া যায়নি চা খাওয়ানো হয়েছে @@ -174,7 +174,7 @@ ডিলিট শুরু কার্টুন - Some devices do not support the new package installer. Try the legacy option if updates do not install। + কিছু ফোন নতুন প্যাকেজ ইনস্টলার সাপোর্ট করে না। যদি আপডেটগুলি ইনস্টল না হয় তবে পুরোনো পদ্ধতি ব্যবহার করে দেখুন। সাবটাইটেল নেই এই প্রোভাইডার ক্রোমকাস্ট সাপোর্ট করে না উন্নত অনুসন্ধান @@ -204,7 +204,7 @@ আমাদের তৈরি Anime দেখার অ্যাপ্লিকেশন 18+ এনিমে - অনুসন্ধানের ফলে নির্বাচিত ভিডিওর মান লুকান + অনুসন্ধান ফলাফলে নির্বাচিত ভিডিও কুয়ালিটি লুকান অ্যাপ লাইভস্ট্রিম APK ইনস্টলার @@ -354,37 +354,4 @@ স্পিচ রিকগনিশন উপলব্ধ নেই কথা বলা শুরু করুন… ডাউনলোড তালিকা - সম্পূর্ণ সিরিজ প্লে করুন - এই ভিডিওটি একটি টরেন্ট, অর্থাৎ আপনার ভিডিও অ্যাক্টিভিটি ট্র্যাক করা সম্ভব।\nএগোনোর আগে টরেন্টিং সম্পর্কে ভালোভাবে বুঝে নিন। - ডিলিট করার জন্য আইটেম সিলেক্ট করুন - বর্তমানে কোনো ডাউনলোড নেই। - বর্তমানে কোনো ডাউনলোড কিউতে নেই। - অফলাইনে দেখার জন্য উপলব্ধ - সব সিলেক্ট করুন - সব ডিসিলেক্ট করুন - লোকাল ভিডিও খুলুন - অতিরিক্ত ব্রাইটনেস - ডিসপ্লে ব্রাইটনেস ১০০% ছাড়িয়ে গেলে ব্রাইটনেস ফিল্টার চালু করুন - সার্চ সাজেশন - টাইপ করার সময় সার্চ সাজেশন দেখান - সাজেশন মুছে ফেলুন - প্লেয়ার মেটাডেটা ওভারলে প্রদর্শন - কাস্ট প্যানেল প্রদর্শন - প্রাক-মুক্তি সংস্করণ ইনস্টলেশন - প্রাক-মুক্তি সংস্করণ ইতোমধ্যে ইনস্টল রয়েছে। - প্রাক-মুক্তি সংস্করণ ইনস্টল করতে সমস্যা হয়েছে। - (%1$d | %2$s) মুছুন - সাবধান - আপনি কি নিম্নলিখিত আইটেমগুলো স্থায়ীভাবে মুছতে চান?\n\n%s - ফাইল মুছুন - আপনি কি নিশ্চিত যে আপনি %1$s-এ নিচের এপিসোডগুলো স্থায়ীভাবে মুছে ফেলতে চান?\n\n%2$s - আপনি নিচের সিরিজগুলোর সব এপিসোডও স্থায়ীভাবে মুছে ফেলবেন:\n\n%s - আপনি কি নিশ্চিত যে আপনি নিচের সিরিজটির সব এপিসোড স্থায়ীভাবে মুছে ফেলতে চান?\n\n%s - সঙ্গীত - অডিও বই - মিডিয়া - অডিও - পডকাস্ট - ভিডিও - এনকোডিং ত্রুটি diff --git a/app/src/main/res/values-b+nl/strings.xml b/app/src/main/res/values-b+nl/strings.xml index feec84263..8a2424326 100644 --- a/app/src/main/res/values-b+nl/strings.xml +++ b/app/src/main/res/values-b+nl/strings.xml @@ -682,17 +682,4 @@ Zet torrent aan in Instellingen/Providers/Media voorkeur Herstart de app en accepteer de Stream Torrent pop-up om verder te gaan. Handmatige Update Knop - Open de app met Vingerafdruk, Face ID, PIN, Pattern en Wachtwoord. - Seekbar preview - Zet preview thumbnail aan op seekbar - Software decodering - Software decodering staat de mogelijkheid toe om de speler videobestanden af te laten spelen op jouw apparaat, maar het kan een haperige of onstabiele kijkervaring zorgen op hoge resolutie. - Volume heeft de 100% overschreden - Update Plugins - Geen plugins zijn geupdate. - Speler meldingen - De speler melding om de kijkervaring van de achtergrond de besturen - Online - Hoeveel verschillende items kunnen in parallel gedownload worden - Parallel downloads diff --git a/app/src/main/res/values-b+pl/strings.xml b/app/src/main/res/values-b+pl/strings.xml index b69146c92..35367a1b2 100644 --- a/app/src/main/res/values-b+pl/strings.xml +++ b/app/src/main/res/values-b+pl/strings.xml @@ -742,13 +742,4 @@ Wideo Zapowiedź Na żywo - Ustawienia profilu - Ukryj źródła z negatywnym priorytetem - Ukryj źródła z błędami - - %d ukryty odnośnik - %d ukryte odnośniki - %d ukrytych odnośników - %d ukrytych odnośników - diff --git a/app/src/main/res/values-b+vi/strings.xml b/app/src/main/res/values-b+vi/strings.xml index 53679c05c..3b2b3876f 100644 --- a/app/src/main/res/values-b+vi/strings.xml +++ b/app/src/main/res/values-b+vi/strings.xml @@ -36,7 +36,7 @@ Tập tiếp theo Thể loại Chia sẻ - Phát bằng Trình duyệt + Mở bằng trình duyệt Bỏ tải Đang tải… Đang xem @@ -255,13 +255,13 @@ Chất lượng xem ưu tiên (WiFi) Số ký tự tối đa tiêu đề trình phát Hiển thị thông tin trình phát - Kích thước bộ đệm video - Thời lượng bộ đệm video + Kích thước bộ nhớ đệm video + Thời lượng bộ nhớ đệm Bộ nhớ đệm video trên thiết bị Xoá bộ nhớ đệm hình ảnh và video Sẽ gây lỗi nếu đặt quá cao trên thiết bị có bộ nhớ thấp như Android TV. - Sẽ gây lỗi nếu đặt quá cao trên thiết bị có dung lượng lưu trữ thấp như Android TV. - DNS qua HTTPS + Sẽ gây lỗi nếu đặt quá cao trên máy có dung lượng lưu trữ thấp như Android TV. + DNS over HTTPS Rất hữu ích để bỏ chặn ISP Bản sao trang web Xoá trang web diff --git a/app/src/main/res/values-b+be/strings.xml b/app/src/main/res/values-be/strings.xml similarity index 99% rename from app/src/main/res/values-b+be/strings.xml rename to app/src/main/res/values-be/strings.xml index 9fbf8a8d5..3d9200faf 100644 --- a/app/src/main/res/values-b+be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -125,7 +125,7 @@ Працягнуць прагляд Выдаліць Больш інфармацыі - @string/home_play + \@string/home_play Для карэктнай працы гэтага пастаўшчыка можа спатрэбіцца VPN Гэты пастаўшчык — Torrent, рэкамендуецца VPN Вэб-сайт не пастаўляе метададзеных, загрузіць відэа не ўдасца, калі на сайце яго няма. diff --git a/app/src/main/res/values-b+ca/strings.xml b/app/src/main/res/values-ca/strings.xml similarity index 99% rename from app/src/main/res/values-b+ca/strings.xml rename to app/src/main/res/values-ca/strings.xml index 621243c78..495eb5e3c 100644 --- a/app/src/main/res/values-b+ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -123,7 +123,7 @@ Continua mirant Eliminar Més info - @string/home_play + \@string/home_play Potser necessiteu una VPN per que aquest proveïdor funcioni correctament Aquest proveïdor és un Torrent, es recomana fer servir una VPN El lloc no proveeix metadades, la càrrega del video fallarà si no existeix al lloc. diff --git a/app/src/main/res/values-b+sq/strings.xml b/app/src/main/res/values-sq/strings.xml similarity index 99% rename from app/src/main/res/values-b+sq/strings.xml rename to app/src/main/res/values-sq/strings.xml index c33ea0447..a13f87bfa 100644 --- a/app/src/main/res/values-b+sq/strings.xml +++ b/app/src/main/res/values-sq/strings.xml @@ -127,7 +127,7 @@ Vazhdo shikimin Hiq Më shumë informacion - @string/home_play + \@string/home_play Një VPN mund të nevojitet që ky ofrues të funksionojë në rregull Ky ofrues është Torrent, rekomandohet një VPN Metadata nuk ofrohet nga kjo faqe, ngarkimi i videos do të dështojë nëse nuk ekziston në këtë faqe. @@ -735,11 +735,4 @@ %d shkarkime në radhë Live - Cilësimet e profil-it - Fshih burimet me prioritet negativ - Fshih burimet me error-e - - %d link i fshehur - %d linqe të fshehura - diff --git a/app/src/main/res/values/donottranslate-strings.xml b/app/src/main/res/values/donottranslate-strings.xml index bb222918c..6a4c82713 100644 --- a/app/src/main/res/values/donottranslate-strings.xml +++ b/app/src/main/res/values/donottranslate-strings.xml @@ -101,7 +101,6 @@ opensubtitles_key subdl_key animeskip_key - tv_layout_clock_key pref_category_security_key pref_category_gestures_key diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index eed41ce81..31cf951cf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -374,8 +374,6 @@ Looks Features General - Show real time clock - Show a real time clock at the top of the screen. Applies to the homepage and player Random Button Show random button on Homepage and Library Extension languages @@ -624,14 +622,6 @@ Subscribe Unsubscribe Profile %d - Profile settings - Hide sources with a negative priority - Hide sources with errors - - %d hidden link - %d hidden links - - Wi-Fi Mobile data Set default @@ -793,4 +783,5 @@ %d downloads queued Live + diff --git a/app/src/main/res/xml/settings_ui.xml b/app/src/main/res/xml/settings_ui.xml index 774724f99..1b516ffa3 100644 --- a/app/src/main/res/xml/settings_ui.xml +++ b/app/src/main/res/xml/settings_ui.xml @@ -89,12 +89,6 @@ android:icon="@drawable/metadata_overlay_icon" android:key="@string/show_player_metadata_key" android:title="@string/show_player_metadata_overlay" /> -