From ad7b8bd866d2a3aee533765422bb678801929a87 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Sat, 14 Jan 2023 15:18:27 +0530 Subject: [PATCH 01/50] Simplify country detection methods. --- .../com/github/libretube/util/LocaleHelper.kt | 66 ++++++------------- 1 file changed, 19 insertions(+), 47 deletions(-) diff --git a/app/src/main/java/com/github/libretube/util/LocaleHelper.kt b/app/src/main/java/com/github/libretube/util/LocaleHelper.kt index 017a96022..9c1f5c769 100644 --- a/app/src/main/java/com/github/libretube/util/LocaleHelper.kt +++ b/app/src/main/java/com/github/libretube/util/LocaleHelper.kt @@ -5,6 +5,8 @@ import android.content.res.Configuration import android.content.res.Resources import android.os.Build import android.telephony.TelephonyManager +import androidx.core.content.getSystemService +import androidx.core.os.ConfigurationCompat import com.github.libretube.constants.PreferenceKeys import com.github.libretube.obj.Country import java.util.* @@ -44,53 +46,24 @@ object LocaleHelper { resources.updateConfiguration(configuration, resources.getDisplayMetrics()) } - fun getDetectedCountry(context: Context, defaultCountryIsoCode: String): String { - detectSIMCountry(context)?.let { - if (it != "") return it - } - - detectNetworkCountry(context)?.let { - if (it != "") return it - } - - detectLocaleCountry(context)?.let { - if (it != "") return it - } - - return defaultCountryIsoCode - } - - private fun detectSIMCountry(context: Context): String? { - try { - val telephonyManager = - context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager - return telephonyManager.simCountryIso - } catch (e: Exception) { - e.printStackTrace() - } - return null - } - - private fun detectNetworkCountry(context: Context): String? { - try { - val telephonyManager = - context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager - return telephonyManager.networkCountryIso - } catch (e: Exception) { - e.printStackTrace() - } - return null - } - - private fun detectLocaleCountry(context: Context): String? { - try { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - return context.resources.configuration.locales[0].country + private fun getDetectedCountry(context: Context): String { + return detectSIMCountry(context).ifEmpty { + detectNetworkCountry(context).ifEmpty { + detectLocaleCountry(context).ifEmpty { "UK" } } - } catch (e: Exception) { - e.printStackTrace() } - return null + } + + private fun detectSIMCountry(context: Context): String { + return context.getSystemService()?.simCountryIso.orEmpty() + } + + private fun detectNetworkCountry(context: Context): String { + return context.getSystemService()?.networkCountryIso.orEmpty() + } + + private fun detectLocaleCountry(context: Context): String { + return ConfigurationCompat.getLocales(context.resources.configuration)[0]!!.country } fun getAvailableCountries(): List { @@ -132,8 +105,7 @@ object LocaleHelper { // get the system default country if auto region selected return if (regionPref == "sys") { - getDetectedCountry(context, "UK") - .uppercase() + getDetectedCountry(context).uppercase() } else { regionPref } From 030cc80c71a737a8938dd98f65e8529203b395e0 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Sat, 14 Jan 2023 15:26:38 +0530 Subject: [PATCH 02/50] Simplify some expressions. --- app/src/main/java/com/github/libretube/util/LocaleHelper.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/github/libretube/util/LocaleHelper.kt b/app/src/main/java/com/github/libretube/util/LocaleHelper.kt index 9c1f5c769..6ad980f08 100644 --- a/app/src/main/java/com/github/libretube/util/LocaleHelper.kt +++ b/app/src/main/java/com/github/libretube/util/LocaleHelper.kt @@ -17,7 +17,7 @@ object LocaleHelper { val languageName = PreferenceHelper.getString(PreferenceKeys.LANGUAGE, "sys") val locale = when { languageName == "sys" -> Locale.getDefault() - languageName.contains("-") == true -> { + languageName.contains("-") -> { val languageParts = languageName.split("-") Locale( languageParts[0], @@ -41,9 +41,9 @@ object LocaleHelper { private fun updateResourcesLegacy(context: Context, locale: Locale) { Locale.setDefault(locale) val resources: Resources = context.resources - val configuration: Configuration = resources.getConfiguration() + val configuration = resources.configuration configuration.locale = locale - resources.updateConfiguration(configuration, resources.getDisplayMetrics()) + resources.updateConfiguration(configuration, resources.displayMetrics) } private fun getDetectedCountry(context: Context): String { From e68677ab6dfc9308b2a8d75a09731ccc1deb751e Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Sat, 14 Jan 2023 15:35:32 +0530 Subject: [PATCH 03/50] Use array extensions. --- .../ui/preferences/PlayerSettings.kt | 2 +- .../com/github/libretube/util/LocaleHelper.kt | 35 ++++--------------- 2 files changed, 8 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/com/github/libretube/ui/preferences/PlayerSettings.kt b/app/src/main/java/com/github/libretube/ui/preferences/PlayerSettings.kt index ac228defc..f77cb80a7 100644 --- a/app/src/main/java/com/github/libretube/ui/preferences/PlayerSettings.kt +++ b/app/src/main/java/com/github/libretube/ui/preferences/PlayerSettings.kt @@ -73,7 +73,7 @@ class PlayerSettings : BasePreferenceFragment() { } private fun setupSubtitlePref(preference: ListPreference) { - val locales = LocaleHelper.getAvailableLocales().sortedBy { it.name } + val locales = LocaleHelper.getAvailableLocales() val localeNames = locales.map { it.name } .toMutableList() localeNames.add(0, requireContext().getString(R.string.none)) diff --git a/app/src/main/java/com/github/libretube/util/LocaleHelper.kt b/app/src/main/java/com/github/libretube/util/LocaleHelper.kt index 6ad980f08..f2c377c02 100644 --- a/app/src/main/java/com/github/libretube/util/LocaleHelper.kt +++ b/app/src/main/java/com/github/libretube/util/LocaleHelper.kt @@ -67,37 +67,16 @@ object LocaleHelper { } fun getAvailableCountries(): List { - val isoCountries = Locale.getISOCountries() - val countries = mutableListOf() - isoCountries.forEach { countryCode -> - val locale = Locale("", countryCode) - val countryName = locale.displayCountry - countries.add( - Country( - countryName, - countryCode - ) - ) - } - countries.sortBy { it.name } - return countries + return Locale.getISOCountries() + .map { Country(Locale("", it).displayCountry, it) } + .sortedBy { it.name } } fun getAvailableLocales(): List { - val availableLocales: Array = Locale.getAvailableLocales() - val locales = mutableListOf() - - availableLocales.forEach { locale -> - if (locales.filter { it.code == locale.language }.isEmpty()) { - locales.add( - Country( - locale.displayLanguage, - locale.language - ) - ) - } - } - return locales + return Locale.getAvailableLocales() + .distinctBy { it.language } + .map { Country(it.displayLanguage, it.language) } + .sortedBy { it.name } } fun getTrendingRegion(context: Context): String { From a52bd6247c3a8bcfe2f911717b8b1494b9ca8124 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Sun, 15 Jan 2023 13:20:33 +0100 Subject: [PATCH 04/50] Move the bitmap scaling logic to the `ImageHelper` --- .../com/github/libretube/util/ImageHelper.kt | 16 ++++++++++++++++ .../libretube/util/NowPlayingNotification.kt | 16 +++------------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/github/libretube/util/ImageHelper.kt b/app/src/main/java/com/github/libretube/util/ImageHelper.kt index f5aaca9b6..ca07d5865 100644 --- a/app/src/main/java/com/github/libretube/util/ImageHelper.kt +++ b/app/src/main/java/com/github/libretube/util/ImageHelper.kt @@ -88,4 +88,20 @@ object ImageHelper { } return null } + + /** + * Get a squared bitmap with the same width and height from a bitmap + * @param bitmap The bitmap to resize + */ + fun getSquareBitmap(bitmap: Bitmap?): Bitmap? { + bitmap ?: return null + val newSize = minOf(bitmap.width, bitmap.height) + return Bitmap.createBitmap( + bitmap, + (bitmap.width - newSize) / 2, + (bitmap.height - newSize) / 2, + newSize, + newSize + ) + } } diff --git a/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt b/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt index 471addf10..7b077b814 100644 --- a/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt +++ b/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt @@ -118,22 +118,12 @@ class NowPlayingNotification( ImageHelper.imageLoader.enqueue(request) // returns the bitmap on Android 13+, for everything below scaled down to a square - return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) getSquareBitmap(bitmap) else bitmap + return if ( + Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU + ) ImageHelper.getSquareBitmap(bitmap) else bitmap } } - private fun getSquareBitmap(bitmap: Bitmap?): Bitmap? { - bitmap ?: return null - val newSize = minOf(bitmap.width, bitmap.height) - return Bitmap.createBitmap( - bitmap, - (bitmap.width - newSize) / 2, - (bitmap.height - newSize) / 2, - newSize, - newSize - ) - } - /** * Creates a [MediaSessionCompat] amd a [MediaSessionConnector] for the player */ From 12d4ee9e8ed0a3b7507c476c9ce5e4c316aa2711 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Sun, 15 Jan 2023 13:26:16 +0100 Subject: [PATCH 05/50] Cleanup the PiP window controls --- .../libretube/util/NowPlayingNotification.kt | 25 +++--- .../com/github/libretube/util/PlayerHelper.kt | 77 +++++++++---------- 2 files changed, 49 insertions(+), 53 deletions(-) diff --git a/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt b/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt index 7b077b814..8107eca1c 100644 --- a/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt +++ b/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt @@ -17,6 +17,7 @@ import android.support.v4.media.session.MediaSessionCompat import coil.request.ImageRequest import com.github.libretube.R import com.github.libretube.api.obj.Streams +import com.github.libretube.compat.PendingIntentCompat import com.github.libretube.constants.BACKGROUND_CHANNEL_ID import com.github.libretube.constants.IntentData import com.github.libretube.constants.PLAYER_NOTIFICATION_ID @@ -71,23 +72,19 @@ class NowPlayingNotification( // starts a new MainActivity Intent when the player notification is clicked // it doesn't start a completely new MainActivity because the MainActivity's launchMode // is set to "singleTop" in the AndroidManifest (important!!!) - // that's the only way to launch back into the previous activity (e.g. the player view + // that's the only way to launch back into the previous activity (e.g. the player view val intent = Intent(context, MainActivity::class.java).apply { if (isBackgroundPlayerNotification) { putExtra(IntentData.openAudioPlayer, true) addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) } } - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - PendingIntent.getActivity( - context, - 0, - intent, - PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT - ) - } else { - PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) - } + return PendingIntent.getActivity( + context, + 0, + intent, + PendingIntentCompat.updateCurrentFlags + ) } /** @@ -120,7 +117,11 @@ class NowPlayingNotification( // returns the bitmap on Android 13+, for everything below scaled down to a square return if ( Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU - ) ImageHelper.getSquareBitmap(bitmap) else bitmap + ) { + ImageHelper.getSquareBitmap(bitmap) + } else { + bitmap + } } } diff --git a/app/src/main/java/com/github/libretube/util/PlayerHelper.kt b/app/src/main/java/com/github/libretube/util/PlayerHelper.kt index 560021075..008e92963 100644 --- a/app/src/main/java/com/github/libretube/util/PlayerHelper.kt +++ b/app/src/main/java/com/github/libretube/util/PlayerHelper.kt @@ -397,52 +397,47 @@ object PlayerHelper { */ @RequiresApi(Build.VERSION_CODES.O) fun getPiPModeActions(activity: Activity, isPlaying: Boolean, isOfflinePlayer: Boolean = false): ArrayList { - val actions: ArrayList = ArrayList() - actions.add( - if (!isOfflinePlayer && alternativePiPControls) { - getRemoteAction( - activity, - R.drawable.ic_headphones, - R.string.background_mode, - PlayerEvent.Background - ) - } else { - getRemoteAction( - activity, - R.drawable.ic_rewind, - R.string.rewind, - PlayerEvent.Rewind - ) - } + val audioModeAction = getRemoteAction( + activity, + R.drawable.ic_headphones, + R.string.background_mode, + PlayerEvent.Background ) - actions.add( - getRemoteAction( - activity, - if (isPlaying) R.drawable.ic_pause else R.drawable.ic_play, - R.string.pause, - if (isPlaying) PlayerEvent.Pause else PlayerEvent.Play - ) + val rewindAction = getRemoteAction( + activity, + R.drawable.ic_rewind, + R.string.rewind, + PlayerEvent.Rewind ) - actions.add( - if (!isOfflinePlayer && alternativePiPControls) { - getRemoteAction( - activity, - R.drawable.ic_next, - R.string.play_next, - PlayerEvent.Next - ) - } else { - getRemoteAction( - activity, - R.drawable.ic_forward, - R.string.forward, - PlayerEvent.Forward - ) - } + val playPauseAction = getRemoteAction( + activity, + if (isPlaying) R.drawable.ic_pause else R.drawable.ic_play, + R.string.pause, + if (isPlaying) PlayerEvent.Pause else PlayerEvent.Play ) - return actions + + val skipNextAction = getRemoteAction( + activity, + R.drawable.ic_next, + R.string.play_next, + PlayerEvent.Next + ) + + val forwardAction = getRemoteAction( + activity, + R.drawable.ic_forward, + R.string.forward, + PlayerEvent.Forward + ) + return if ( + !isOfflinePlayer && alternativePiPControls + ) { + arrayListOf(audioModeAction, playPauseAction, skipNextAction) + } else { + arrayListOf(rewindAction, playPauseAction, forwardAction) + } } /** From 90e87c596e7e6c2cf5d9225fdb48fdd76e3c0d45 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Sun, 15 Jan 2023 14:26:55 +0100 Subject: [PATCH 06/50] Add custom notification actions --- .../libretube/util/NowPlayingNotification.kt | 128 ++++++++++++++---- 1 file changed, 104 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt b/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt index 8107eca1c..61da6273d 100644 --- a/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt +++ b/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt @@ -5,7 +5,6 @@ import android.app.NotificationManager import android.app.PendingIntent import android.content.Context import android.content.Intent -import android.content.res.Resources import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.drawable.BitmapDrawable @@ -14,6 +13,10 @@ import android.os.Bundle import android.support.v4.media.MediaDescriptionCompat import android.support.v4.media.MediaMetadataCompat import android.support.v4.media.session.MediaSessionCompat +import android.support.v4.media.session.PlaybackStateCompat +import android.util.Log +import androidx.annotation.DrawableRes +import androidx.core.app.NotificationCompat import coil.request.ImageRequest import com.github.libretube.R import com.github.libretube.api.obj.Streams @@ -27,6 +30,7 @@ import com.google.android.exoplayer2.Player import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator import com.google.android.exoplayer2.ui.PlayerNotificationManager +import com.google.android.exoplayer2.ui.PlayerNotificationManager.CustomActionReceiver class NowPlayingNotification( private val context: Context, @@ -52,11 +56,10 @@ class NowPlayingNotification( private var playerNotification: PlayerNotificationManager? = null /** - * The [DescriptionAdapter] is used to show title, uploaderName and thumbnail of the video in the notification + * The [descriptionAdapter] is used to show title, uploaderName and thumbnail of the video in the notification * Basic example [here](https://github.com/AnthonyMarkD/AudioPlayerSampleTest) */ - inner class DescriptionAdapter : - PlayerNotificationManager.MediaDescriptionAdapter { + private val descriptionAdapter = object : PlayerNotificationManager.MediaDescriptionAdapter { /** * sets the title of the notification */ @@ -125,6 +128,51 @@ class NowPlayingNotification( } } + private val customActionReceiver = object : CustomActionReceiver { + override fun createCustomActions( + context: Context, + instanceId: Int + ): MutableMap { + return mutableMapOf( + PREV to createNotificationAction(R.drawable.ic_prev, PREV, instanceId), + NEXT to createNotificationAction(R.drawable.ic_next, NEXT, instanceId), + REWIND to createNotificationAction(R.drawable.ic_rewind, REWIND, instanceId), + FORWARD to createNotificationAction(R.drawable.ic_forward, FORWARD, instanceId) + ) + } + + override fun getCustomActions(player: Player): MutableList { + return mutableListOf(PREV, NEXT, REWIND, FORWARD) + } + + override fun onCustomAction(player: Player, action: String, intent: Intent) { + handlePlayerAction(action) + } + } + + private fun createNotificationAction(drawableRes: Int, actionName: String, instanceId: Int): NotificationCompat.Action { + val intent: Intent = Intent(actionName).setPackage(context.packageName) + val pendingIntent = PendingIntent.getBroadcast( + context, + instanceId, + intent, + PendingIntentCompat.cancelCurrentFlags + ) + return NotificationCompat.Action.Builder(drawableRes, actionName, pendingIntent).build() + } + + private fun createMediaSessionAction(@DrawableRes drawableRes: Int, actionName: String): MediaSessionConnector.CustomActionProvider { + return object : MediaSessionConnector.CustomActionProvider { + override fun getCustomAction(player: Player): PlaybackStateCompat.CustomAction? { + return PlaybackStateCompat.CustomAction.Builder(actionName, actionName, drawableRes).build() + } + + override fun onCustomAction(player: Player, action: String, extras: Bundle?) { + handlePlayerAction(action) + } + } + } + /** * Creates a [MediaSessionCompat] amd a [MediaSessionConnector] for the player */ @@ -142,22 +190,50 @@ class NowPlayingNotification( return MediaDescriptionCompat.Builder().apply { setTitle(streams?.title!!) setSubtitle(streams?.uploader) - val extras = Bundle() val appIcon = BitmapFactory.decodeResource( - Resources.getSystem(), + context.resources, R.drawable.ic_launcher_monochrome ) - extras.putParcelable(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, appIcon) - extras.putString(MediaMetadataCompat.METADATA_KEY_TITLE, streams?.title!!) - extras.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, streams?.uploader) + val extras = Bundle().apply { + putParcelable(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, appIcon) + putString(MediaMetadataCompat.METADATA_KEY_TITLE, streams?.title!!) + putString(MediaMetadataCompat.METADATA_KEY_ARTIST, streams?.uploader) + } setIconBitmap(appIcon) setExtras(extras) }.build() } }) + mediaSessionConnector.setCustomActionProviders( + createMediaSessionAction(R.drawable.ic_prev, PREV), + createMediaSessionAction(R.drawable.ic_next, NEXT), + createMediaSessionAction(R.drawable.ic_rewind, REWIND), + createMediaSessionAction(R.drawable.ic_forward, FORWARD) + ) mediaSessionConnector.setPlayer(player) } + private fun handlePlayerAction(action: String) { + when (action) { + NEXT -> { + if (PlayingQueue.hasNext()) PlayingQueue.onQueueItemSelected( + PlayingQueue.currentIndex() + 1 + ) + } + PREV -> { + if (PlayingQueue.hasPrev()) PlayingQueue.onQueueItemSelected( + PlayingQueue.currentIndex() - 1 + ) + } + REWIND -> { + player.seekTo(player.currentPosition - PlayerHelper.seekIncrement) + } + FORWARD -> { + player.seekTo(player.currentPosition + PlayerHelper.seekIncrement) + } + } + } + /** * Updates or creates the [playerNotification] */ @@ -181,21 +257,18 @@ class NowPlayingNotification( playerNotification = PlayerNotificationManager .Builder(context, PLAYER_NOTIFICATION_ID, BACKGROUND_CHANNEL_ID) // set the description of the notification - .setMediaDescriptionAdapter( - DescriptionAdapter() - ) - .build() - playerNotification?.apply { - setPlayer(player) - setUseNextAction(false) - setUsePreviousAction(false) - setUseStopAction(true) - setColorized(true) - setMediaSessionToken(mediaSession.sessionToken) - setSmallIcon(R.drawable.ic_launcher_lockscreen) - setUseFastForwardActionInCompactView(true) - setUseRewindActionInCompactView(true) - } + .setMediaDescriptionAdapter(descriptionAdapter) + // register the receiver for custom actions, doesn't seem to change anything + .setCustomActionReceiver(customActionReceiver) + .build().apply { + setPlayer(player) + setColorized(true) + setMediaSessionToken(mediaSession.sessionToken) + setSmallIcon(R.drawable.ic_launcher_lockscreen) + setUseNextAction(false) + setUsePreviousAction(false) + setUseStopAction(true) + } } /** @@ -215,4 +288,11 @@ class NowPlayingNotification( ) as NotificationManager notificationManager.cancel(PLAYER_NOTIFICATION_ID) } + + companion object { + private const val PREV = "prev" + private const val NEXT = "next" + private const val REWIND = "rewind" + private const val FORWARD = "forward" + } } From 8ccc91024e370058b5890cb7d55f373723683801 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Mon, 16 Jan 2023 12:14:30 +0530 Subject: [PATCH 07/50] Simplify country detection further. --- .../com/github/libretube/util/LocaleHelper.kt | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/github/libretube/util/LocaleHelper.kt b/app/src/main/java/com/github/libretube/util/LocaleHelper.kt index f2c377c02..9f28e1915 100644 --- a/app/src/main/java/com/github/libretube/util/LocaleHelper.kt +++ b/app/src/main/java/com/github/libretube/util/LocaleHelper.kt @@ -2,7 +2,6 @@ package com.github.libretube.util import android.content.Context import android.content.res.Configuration -import android.content.res.Resources import android.os.Build import android.telephony.TelephonyManager import androidx.core.content.getSystemService @@ -40,30 +39,30 @@ object LocaleHelper { @Suppress("DEPRECATION") private fun updateResourcesLegacy(context: Context, locale: Locale) { Locale.setDefault(locale) - val resources: Resources = context.resources + val resources = context.resources val configuration = resources.configuration configuration.locale = locale resources.updateConfiguration(configuration, resources.displayMetrics) } private fun getDetectedCountry(context: Context): String { - return detectSIMCountry(context).ifEmpty { - detectNetworkCountry(context).ifEmpty { - detectLocaleCountry(context).ifEmpty { "UK" } - } - } + return detectSIMCountry(context) + ?: detectNetworkCountry(context) + ?: detectLocaleCountry(context) + ?: "UK" } - private fun detectSIMCountry(context: Context): String { - return context.getSystemService()?.simCountryIso.orEmpty() + private fun detectSIMCountry(context: Context): String? { + return context.getSystemService()?.simCountryIso?.ifEmpty { null } } - private fun detectNetworkCountry(context: Context): String { - return context.getSystemService()?.networkCountryIso.orEmpty() + private fun detectNetworkCountry(context: Context): String? { + return context.getSystemService()?.networkCountryIso?.ifEmpty { null } } - private fun detectLocaleCountry(context: Context): String { + private fun detectLocaleCountry(context: Context): String? { return ConfigurationCompat.getLocales(context.resources.configuration)[0]!!.country + .ifEmpty { null } } fun getAvailableCountries(): List { From 812278834911bfe543dfdff6819e99f3ebd3cf53 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Mon, 16 Jan 2023 17:09:16 +0530 Subject: [PATCH 08/50] Use ConfigurationCompat.getLocales(). --- .../com/github/libretube/ui/fragments/PlayerFragment.kt | 8 +++----- app/src/main/java/com/github/libretube/util/TextUtils.kt | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt index 2e0e9d0ed..f6f8456ee 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt @@ -27,6 +27,7 @@ import android.widget.Toast import androidx.annotation.RequiresApi import androidx.constraintlayout.motion.widget.MotionLayout import androidx.core.net.toUri +import androidx.core.os.ConfigurationCompat import androidx.core.os.bundleOf import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels @@ -842,11 +843,8 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions { } private fun localizedDate(date: String?): String? { - return if (SDK_INT >= Build.VERSION_CODES.N) { - TextUtils.localizeDate(date, resources.configuration.locales[0]) - } else { - TextUtils.localizeDate(date) - } + val locale = ConfigurationCompat.getLocales(resources.configuration)[0]!! + return TextUtils.localizeDate(date, locale) } private fun handleLiveVideo() { diff --git a/app/src/main/java/com/github/libretube/util/TextUtils.kt b/app/src/main/java/com/github/libretube/util/TextUtils.kt index e3b774b17..1fe22eeb1 100644 --- a/app/src/main/java/com/github/libretube/util/TextUtils.kt +++ b/app/src/main/java/com/github/libretube/util/TextUtils.kt @@ -40,7 +40,7 @@ object TextUtils { * @param locale The locale to use, otherwise uses system default * return Localized date string */ - fun localizeDate(date: String?, locale: Locale? = null): String? { + fun localizeDate(date: String?, locale: Locale): String? { date ?: return null // relative time span From 6c750b51fa0d19e5fae6c0d694f1bf7d6235efed Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 16 Jan 2023 14:23:36 +0100 Subject: [PATCH 09/50] Better icons in the now playing notification --- .../libretube/util/NowPlayingNotification.kt | 91 ++++++++++--------- .../main/res/drawable/ic_next_outlined.xml | 10 ++ .../main/res/drawable/ic_prev_outlined.xml | 10 ++ 3 files changed, 70 insertions(+), 41 deletions(-) create mode 100644 app/src/main/res/drawable/ic_next_outlined.xml create mode 100644 app/src/main/res/drawable/ic_prev_outlined.xml diff --git a/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt b/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt index 61da6273d..4012a3e9e 100644 --- a/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt +++ b/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt @@ -14,7 +14,6 @@ import android.support.v4.media.MediaDescriptionCompat import android.support.v4.media.MediaMetadataCompat import android.support.v4.media.session.MediaSessionCompat import android.support.v4.media.session.PlaybackStateCompat -import android.util.Log import androidx.annotation.DrawableRes import androidx.core.app.NotificationCompat import coil.request.ImageRequest @@ -134,8 +133,8 @@ class NowPlayingNotification( instanceId: Int ): MutableMap { return mutableMapOf( - PREV to createNotificationAction(R.drawable.ic_prev, PREV, instanceId), - NEXT to createNotificationAction(R.drawable.ic_next, NEXT, instanceId), + PREV to createNotificationAction(R.drawable.ic_prev_outlined, PREV, instanceId), + NEXT to createNotificationAction(R.drawable.ic_next_outlined, NEXT, instanceId), REWIND to createNotificationAction(R.drawable.ic_rewind, REWIND, instanceId), FORWARD to createNotificationAction(R.drawable.ic_forward, FORWARD, instanceId) ) @@ -178,52 +177,62 @@ class NowPlayingNotification( */ private fun createMediaSession() { if (this::mediaSession.isInitialized) return - mediaSession = MediaSessionCompat(context, this.javaClass.name) - mediaSession.isActive = true + mediaSession = MediaSessionCompat(context, this.javaClass.name).apply { + isActive = true + } - mediaSessionConnector = MediaSessionConnector(mediaSession) - mediaSessionConnector.setQueueNavigator(object : TimelineQueueNavigator(mediaSession) { - override fun getMediaDescription( - player: Player, - windowIndex: Int - ): MediaDescriptionCompat { - return MediaDescriptionCompat.Builder().apply { - setTitle(streams?.title!!) - setSubtitle(streams?.uploader) - val appIcon = BitmapFactory.decodeResource( - context.resources, - R.drawable.ic_launcher_monochrome - ) - val extras = Bundle().apply { - putParcelable(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, appIcon) - putString(MediaMetadataCompat.METADATA_KEY_TITLE, streams?.title!!) - putString(MediaMetadataCompat.METADATA_KEY_ARTIST, streams?.uploader) - } - setIconBitmap(appIcon) - setExtras(extras) - }.build() - } - }) - mediaSessionConnector.setCustomActionProviders( - createMediaSessionAction(R.drawable.ic_prev, PREV), - createMediaSessionAction(R.drawable.ic_next, NEXT), - createMediaSessionAction(R.drawable.ic_rewind, REWIND), - createMediaSessionAction(R.drawable.ic_forward, FORWARD) - ) - mediaSessionConnector.setPlayer(player) + mediaSessionConnector = MediaSessionConnector(mediaSession).apply { + setPlayer(player) + setQueueNavigator(object : TimelineQueueNavigator(mediaSession) { + override fun getMediaDescription( + player: Player, + windowIndex: Int + ): MediaDescriptionCompat { + return MediaDescriptionCompat.Builder().apply { + setTitle(streams?.title!!) + setSubtitle(streams?.uploader) + val appIcon = BitmapFactory.decodeResource( + context.resources, + R.drawable.ic_launcher_monochrome + ) + val extras = Bundle().apply { + putParcelable(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, appIcon) + putString(MediaMetadataCompat.METADATA_KEY_TITLE, streams?.title!!) + putString(MediaMetadataCompat.METADATA_KEY_ARTIST, streams?.uploader) + } + setIconBitmap(appIcon) + setExtras(extras) + }.build() + } + + override fun getSupportedQueueNavigatorActions(player: Player): Long { + return PlaybackStateCompat.ACTION_PLAY_PAUSE + } + }) + setCustomActionProviders( + createMediaSessionAction(R.drawable.ic_prev_outlined, PREV), + createMediaSessionAction(R.drawable.ic_next_outlined, NEXT), + createMediaSessionAction(R.drawable.ic_rewind, REWIND), + createMediaSessionAction(R.drawable.ic_forward, FORWARD) + ) + } } private fun handlePlayerAction(action: String) { when (action) { NEXT -> { - if (PlayingQueue.hasNext()) PlayingQueue.onQueueItemSelected( - PlayingQueue.currentIndex() + 1 - ) + if (PlayingQueue.hasNext()) { + PlayingQueue.onQueueItemSelected( + PlayingQueue.currentIndex() + 1 + ) + } } PREV -> { - if (PlayingQueue.hasPrev()) PlayingQueue.onQueueItemSelected( - PlayingQueue.currentIndex() - 1 - ) + if (PlayingQueue.hasPrev()) { + PlayingQueue.onQueueItemSelected( + PlayingQueue.currentIndex() - 1 + ) + } } REWIND -> { player.seekTo(player.currentPosition - PlayerHelper.seekIncrement) diff --git a/app/src/main/res/drawable/ic_next_outlined.xml b/app/src/main/res/drawable/ic_next_outlined.xml new file mode 100644 index 000000000..1a8af1d37 --- /dev/null +++ b/app/src/main/res/drawable/ic_next_outlined.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_prev_outlined.xml b/app/src/main/res/drawable/ic_prev_outlined.xml new file mode 100644 index 000000000..9152dd34c --- /dev/null +++ b/app/src/main/res/drawable/ic_prev_outlined.xml @@ -0,0 +1,10 @@ + + + From cf17c0dfee33b95fb394e408ee5a64db31785fca Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 16 Jan 2023 14:30:48 +0100 Subject: [PATCH 10/50] Use MD icons for the notification seek controls --- .../github/libretube/util/NowPlayingNotification.kt | 8 ++++---- app/src/main/res/drawable/ic_forward_md.xml | 10 ++++++++++ app/src/main/res/drawable/ic_rewind_md.xml | 10 ++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 app/src/main/res/drawable/ic_forward_md.xml create mode 100644 app/src/main/res/drawable/ic_rewind_md.xml diff --git a/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt b/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt index 4012a3e9e..e53f8d0fb 100644 --- a/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt +++ b/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt @@ -135,8 +135,8 @@ class NowPlayingNotification( return mutableMapOf( PREV to createNotificationAction(R.drawable.ic_prev_outlined, PREV, instanceId), NEXT to createNotificationAction(R.drawable.ic_next_outlined, NEXT, instanceId), - REWIND to createNotificationAction(R.drawable.ic_rewind, REWIND, instanceId), - FORWARD to createNotificationAction(R.drawable.ic_forward, FORWARD, instanceId) + REWIND to createNotificationAction(R.drawable.ic_rewind_md, REWIND, instanceId), + FORWARD to createNotificationAction(R.drawable.ic_forward_md, FORWARD, instanceId) ) } @@ -212,8 +212,8 @@ class NowPlayingNotification( setCustomActionProviders( createMediaSessionAction(R.drawable.ic_prev_outlined, PREV), createMediaSessionAction(R.drawable.ic_next_outlined, NEXT), - createMediaSessionAction(R.drawable.ic_rewind, REWIND), - createMediaSessionAction(R.drawable.ic_forward, FORWARD) + createMediaSessionAction(R.drawable.ic_rewind_md, REWIND), + createMediaSessionAction(R.drawable.ic_forward_md, FORWARD) ) } } diff --git a/app/src/main/res/drawable/ic_forward_md.xml b/app/src/main/res/drawable/ic_forward_md.xml new file mode 100644 index 000000000..bf1528a53 --- /dev/null +++ b/app/src/main/res/drawable/ic_forward_md.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_rewind_md.xml b/app/src/main/res/drawable/ic_rewind_md.xml new file mode 100644 index 000000000..1e3b79b2c --- /dev/null +++ b/app/src/main/res/drawable/ic_rewind_md.xml @@ -0,0 +1,10 @@ + + + From 930df73efaa8edb416c5005e84459a7c17da4435 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 16 Jan 2023 14:33:38 +0100 Subject: [PATCH 11/50] Display the uploader in the notification --- .../java/com/github/libretube/util/NowPlayingNotification.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt b/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt index e53f8d0fb..b2b660ec3 100644 --- a/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt +++ b/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt @@ -125,6 +125,10 @@ class NowPlayingNotification( bitmap } } + + override fun getCurrentSubText(player: Player): CharSequence? { + return streams?.uploader + } } private val customActionReceiver = object : CustomActionReceiver { From 1641c751463e75ce8e27aa30be572bc4f39a070c Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 16 Jan 2023 14:44:37 +0100 Subject: [PATCH 12/50] Fix that the notification thumbnail doesn't load sometimes --- .../libretube/util/NowPlayingNotification.kt | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt b/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt index b2b660ec3..f9925d507 100644 --- a/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt +++ b/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt @@ -110,20 +110,19 @@ class NowPlayingNotification( val request = ImageRequest.Builder(context) .data(streams?.thumbnailUrl) .target { result -> - bitmap = (result as BitmapDrawable).bitmap + val bm = (result as BitmapDrawable).bitmap + // returns the bitmap on Android 13+, for everything below scaled down to a square + bitmap = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { + ImageHelper.getSquareBitmap(bm) + } else bm + callback.onBitmap(bitmap!!) } .build() + // enqueue the thumbnail loading request ImageHelper.imageLoader.enqueue(request) - // returns the bitmap on Android 13+, for everything below scaled down to a square - return if ( - Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU - ) { - ImageHelper.getSquareBitmap(bitmap) - } else { - bitmap - } + return bitmap } override fun getCurrentSubText(player: Player): CharSequence? { From ec49d3e61eb6769f1bfa6730d20812b1229627cc Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 16 Jan 2023 14:58:53 +0100 Subject: [PATCH 13/50] fix ktlint --- .../java/com/github/libretube/util/NowPlayingNotification.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt b/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt index f9925d507..c9295f314 100644 --- a/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt +++ b/app/src/main/java/com/github/libretube/util/NowPlayingNotification.kt @@ -114,7 +114,9 @@ class NowPlayingNotification( // returns the bitmap on Android 13+, for everything below scaled down to a square bitmap = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { ImageHelper.getSquareBitmap(bm) - } else bm + } else { + bm + } callback.onBitmap(bitmap!!) } .build() From 905a0e9ac2d2ff58edf18840783aadccab09bf89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C4=B1la?= <121803062+Ilhamiii@users.noreply.github.com> Date: Mon, 16 Jan 2023 18:04:53 +0400 Subject: [PATCH 14/50] Impove the translation of "Azerbaijan" (#2709) --- app/src/main/res/values/array.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/array.xml b/app/src/main/res/values/array.xml index 9e8bbd4fa..ce2c0f36f 100644 --- a/app/src/main/res/values/array.xml +++ b/app/src/main/res/values/array.xml @@ -28,7 +28,7 @@ @string/systemLanguage العربية - Azərbaycan dili + Azərbaycanca Euskara বাংলা Català From 2ce5c797287b1c583c39c53b1348d32d5e3b100e Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 16 Jan 2023 15:09:35 +0100 Subject: [PATCH 15/50] Fix that queue doesn't regenerate --- .../java/com/github/libretube/ui/fragments/PlayerFragment.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt index 02837a246..40078965f 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt @@ -250,8 +250,11 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions { super.onViewCreated(view, savedInstanceState) context?.hideKeyboard(view) + // reset the callbacks of the playing queue + PlayingQueue.resetToDefaults() + // clear the playing queue - if (!keepQueue) PlayingQueue.resetToDefaults() + if (!keepQueue) PlayingQueue.clear() changeOrientationMode() From 7af4f20e53e64c8ca5d769f6dcf6e626361ce96d Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 16 Jan 2023 15:14:22 +0100 Subject: [PATCH 16/50] Fix the visibility of the 'add to queue' btn --- .../github/libretube/ui/fragments/PlayerFragment.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt index 40078965f..6408708d1 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt @@ -343,15 +343,13 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions { // actions that don't depend on video information private fun initializeOnClickActions() { binding.closeImageView.setOnClickListener { - viewModel.isMiniPlayerVisible.value = false - binding.playerMotionLayout.transitionToEnd() - val mainActivity = activity as MainActivity - mainActivity.supportFragmentManager.beginTransaction() - .remove(this) - .commit() + PlayingQueue.clear() BackgroundHelper.stopBackgroundPlay(requireContext()) + killPlayerFragment() } playerBinding.closeImageButton.setOnClickListener { + PlayingQueue.clear() + BackgroundHelper.stopBackgroundPlay(requireContext()) killPlayerFragment() } playerBinding.autoPlay.visibility = View.VISIBLE @@ -1526,6 +1524,8 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions { mainActivity.supportFragmentManager.beginTransaction() .remove(this) .commit() + + onDestroy() } override fun onConfigurationChanged(newConfig: Configuration) { From 88ecef18dd56b98b8ee8892fc4d7fd4d4ca11f2e Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 16 Jan 2023 15:18:32 +0100 Subject: [PATCH 17/50] Minor cleanup to the `PlayerFragment` --- .../com/github/libretube/ui/fragments/PlayerFragment.kt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt index 6408708d1..894f0b111 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt @@ -1209,8 +1209,7 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions { }.flatten() .filter { it > 0 } .sortedDescending() - .toSet() - .toList() + .distinct() return resolutions.map { VideoResolution( @@ -1359,8 +1358,7 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions { override fun onCaptionsClicked() { if (!this@PlayerFragment::streams.isInitialized || - streams.subtitles == null || - streams.subtitles!!.isEmpty() + streams.subtitles.isNullOrEmpty() ) { Toast.makeText(context, R.string.no_subtitles_available, Toast.LENGTH_SHORT).show() return @@ -1375,7 +1373,7 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions { BaseBottomSheet() .setSimpleItems(subtitlesNamesList) { index -> - val language = if (index > 0) subtitleCodesList[index] else null + val language = subtitleCodesList.getOrNull(index) updateCaptionsLanguage(language) this.captionLanguage = language } From cf3d396efdc54bbf49c9a838da698d8182a6e50e Mon Sep 17 00:00:00 2001 From: Andrey Date: Sun, 15 Jan 2023 12:24:02 +0000 Subject: [PATCH 18/50] Translated using Weblate (Russian) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/ru/ --- app/src/main/res/values-ru/strings.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 36b391fb1..2820776f4 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -436,4 +436,14 @@ Пауза Добавить в закладки Удалить закладку + Аудиоплеер + Без субтитров + Загрузка приостановлена + Загрузка завершена + Максимальное количество одновременных загрузок + Достигнут максимальный предел одновременных загрузок. + Неизвестно + Продолжить + Режим только аудио + Превратите LibreTube в музыкальный проигрыватель. \ No newline at end of file From 401a1bc4bdbbe28079b3a7930a3ee581f6653ccb Mon Sep 17 00:00:00 2001 From: Ettore Atalan Date: Sun, 15 Jan 2023 03:08:51 +0000 Subject: [PATCH 19/50] Translated using Weblate (German) Currently translated at 98.8% (441 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/de/ --- app/src/main/res/values-de/strings.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 538b6a70e..16fd501e5 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -435,4 +435,10 @@ Vorspulen Pause Alternative BiB-Steuerungen + Nur-Audio-Modus + Kein Untertitel + Herunterladen pausiert + Herunterladen abgeschlossen + Unbekannt + Fortsetzen \ No newline at end of file From 2f5412abb63e5fce1a55c34c7f9c83102eb13b01 Mon Sep 17 00:00:00 2001 From: random r Date: Sat, 14 Jan 2023 18:43:39 +0000 Subject: [PATCH 20/50] Translated using Weblate (Italian) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/it/ --- app/src/main/res/values-it/strings.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 50aaa4283..9062c2193 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -436,4 +436,14 @@ Pausa Controlli PiP alternativi Mostra solo l\'audio e salta i controlli nel PiP, invece di avanti e riavvolgi + Riproduttore audio + Nessun sottotitolo + Scaricamento in pausa + Scaricamento completato + Max download simultanei + Limite massimo di download simultanei raggiunto. + Sconosciuto + Riprendi + Modalità solo audio + Trasforma LibreTube in un riproduttore musicale. \ No newline at end of file From 7101fde55904af30748ce250ce63c1368d49a7bc Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Sat, 14 Jan 2023 19:42:05 +0000 Subject: [PATCH 21/50] Translated using Weblate (Spanish) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/es/ --- app/src/main/res/values-es/strings.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 47c0bf47c..316d57b91 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -437,4 +437,13 @@ Rebobinar Controles alternativos de imagen en imagen Reproductor de audio + Convierte LibreTube en un reproductor de música. + Sin subtítulos + Descarga pausada + Descarga completa + Número máximo de descargas simultáneas + Límite máximo de descargas simultáneas alcanzado. + Reanudar + Sólo audio + Desconocido \ No newline at end of file From a72eb47e9eed1af4ea61ffba1ba04ae92fc99ef2 Mon Sep 17 00:00:00 2001 From: RSoulwin Date: Sat, 14 Jan 2023 23:38:38 +0000 Subject: [PATCH 22/50] Translated using Weblate (Hindi) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/hi/ --- app/src/main/res/values-hi/strings.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index fe2d579e3..da6a3c30e 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -439,4 +439,11 @@ ऑडियो प्लेयर ऑडियो केवल मोड LibreTube को म्यूजिक प्लेयर में बदलें। + कोई उपशीर्षक नहीं + डाउनलोड रोका गया + डाउनलोड पूरा हुआ + अधिकतम समवर्ती डाउनलोड + अनजान + अधिकतम समवर्ती डाउनलोड सीमा पूरी हो गई है। + फिर शुरू करें \ No newline at end of file From c912e3312ad8a3196f73632d602778291364f5ac Mon Sep 17 00:00:00 2001 From: Fjuro Date: Sat, 14 Jan 2023 18:44:06 +0000 Subject: [PATCH 23/50] Translated using Weblate (Czech) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/cs/ --- app/src/main/res/values-cs/strings.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index e3adf5813..504d160a7 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -437,4 +437,13 @@ Vpřed Alternativní ovládací prvky PiP Přehrávač zvuku + Bez titulků + Stahování pozastaveno + Stahování dokončeno + Maximální počet souběžných stahování + Dosažen limit maximálního počtu souběžných stahování. + Neznámý + Pokračovat + Režim pouze zvuku + Proměňte LibreTube v hudební přehrávač. \ No newline at end of file From f1183e4f796b9451ed4348b03440488985371a47 Mon Sep 17 00:00:00 2001 From: Sergio Marques Date: Sun, 15 Jan 2023 01:07:58 +0000 Subject: [PATCH 24/50] Translated using Weblate (Portuguese) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/pt/ --- app/src/main/res/values-pt/strings.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 2da1c80e3..091a7fd4a 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -437,4 +437,13 @@ Controlos PiP alternativos Mostrar apenas áudio e saltar controlos em PiP em vez de avançar e rebobinar Reprodutor de áudio + Sem legendas + Descarga em pausa + Apenas áudio + Transforme LibreTube num reprodutor de músicas. + Número de transferências simultâneas + Desconhecido + Continuar + Descarga terminada + Atingiu o limite máximo de descargas em simultâneo. \ No newline at end of file From 3367780a8a03077258a3336e63d78f41a90d952f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81cs=20Zolt=C3=A1n?= Date: Sat, 14 Jan 2023 17:39:17 +0000 Subject: [PATCH 25/50] Translated using Weblate (Hungarian) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/hu/ --- app/src/main/res/values-hu/strings.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 1e4992beb..532b151c2 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -436,4 +436,14 @@ Visszatekerés Alternatív PiP irányítás Csak hang és átlépés gombok megjelenítése a PiP-ben az előretekerés és a visszatekerés helyett + Hanglejátszó + Nincs felirat + Letöltés szüneteltetve + Letöltés befejezve + Maximális egyidejű letöltések + Ismeretlen + Folytatás + Az egyidejű letöltések maximális száma elérve. + Csak hang mód + Változtassa a LibreTube-ot zenelejátszóvá. \ No newline at end of file From d4340e7ddc9100c9fbbdc0d732ea392afa87d5cd Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Sun, 15 Jan 2023 16:10:38 +0000 Subject: [PATCH 26/50] Translated using Weblate (Polish) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/pl/ --- app/src/main/res/values-pl/strings.xml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index a59513cca..71437027e 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -435,6 +435,15 @@ Do przodu Wstrzymaj Alternatywne sterowanie PiP - Zastąp przyciski „przewiń do tyłu” i „przwiń do przodu” na „tylko dźwięk” i „pomiń film”. + Wyświetl sterowanie odtwarzaniem dźwięku w tle i pomijania filmu zamiast przycisków przewijania do tyłu i przodu. Odtwarzacz dźwięku + Pobieranie wstrzymane + Pobieranie ukończone + Maks. równoczesnych pobierań + Osiągnięto limit maksymalnego jednoczesnego pobierania. + Nieznane + Wznów + Bez napisów + Zmień LibreTube w odtwarzacz muzyczny. + Tryb „tylko dźwięk” \ No newline at end of file From 9c8b55489a0c1fc7cc0752e1a0d4929c95700348 Mon Sep 17 00:00:00 2001 From: Ricardo Date: Sat, 14 Jan 2023 17:24:57 +0000 Subject: [PATCH 27/50] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/pt_BR/ --- app/src/main/res/values-pt-rBR/strings.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 17614cd78..0692385ef 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -437,4 +437,13 @@ Controles PiP alternativos Mostrar controles de apenas áudio e pular no PiP em vez de avançar e retroceder Player de Áudio + Sem legenda + Download pausado + Download concluído + Máximo de downloads simultâneos + Limite máximo de downloads simultâneos atingido. + Desconhecido + Retomar + Transforme o LibreTube em um reprodutor de música. + Modo somente áudio \ No newline at end of file From 982f26c6ea4fefe9a49a9a667e0ea002fcbae10c Mon Sep 17 00:00:00 2001 From: Nidi Date: Sat, 14 Jan 2023 17:50:29 +0000 Subject: [PATCH 28/50] Translated using Weblate (Azerbaijani) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/az/ --- app/src/main/res/values-az/strings.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index 24a0777dd..854178d4c 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -439,4 +439,11 @@ Səs oynadıcı Yalnız səs rejimi LibreTube-u musiqi oynadıcıya dəyiş. + Altyazı yoxdur + Endirməyə fasilə verildi + Endirmə tamamlandı + Maksimal paralel endirmələr + Maksimal paralel endirmə limitinə çatıldı. + Naməlum + Davam et \ No newline at end of file From 72b8fc0bbef7d92d8739cd46b97230369d631907 Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Sat, 14 Jan 2023 17:44:13 +0000 Subject: [PATCH 29/50] Translated using Weblate (Ukrainian) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/uk/ --- app/src/main/res/values-uk/strings.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index fa6d3d3dc..ae9e58a4d 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -437,4 +437,13 @@ Альтернативні елементи керування PiP Показувати лише аудіо та пропускати елементи керування в PiP замість перемотування вперед та назад Аудіопрогравач + Режим лише аудіо + Перетворіть LibreTube на музичний програвач. + Субтитрів немає + Завантаження призупинено + Максимальна кількість одночасних завантажень + Досягнуто максимальної кількості одночасних завантажень. + Невідомо + Завантаження завершено + Продовжити \ No newline at end of file From 1471899876cc05b14b093ec030c42fbf698423f7 Mon Sep 17 00:00:00 2001 From: Yaron Shahrabani Date: Sun, 15 Jan 2023 11:27:44 +0000 Subject: [PATCH 30/50] Translated using Weblate (Hebrew) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/he/ --- app/src/main/res/values-iw/strings.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index d258e575c..3e7afee8b 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -436,4 +436,14 @@ השהיה בקרים חלופיים לתמונה בתוך תמונה להציג בקרי שמע בלבד ודילוג בתמונה בתוך תמונה במקום קדימה ואחורה + נגן שמע + ההורדה הושלמה + כמות ההורדות המרבית במקביל + אין כתובית + ההורדה מושהית + הגעת למגבלת ההורדות במקביל. + לא ידוע + המשך + מצב שמע בלבד + הפיכת LibreTube לנגן מוזיקה. \ No newline at end of file From 9eb2f5de3223a5a239e562e325fca6ce201a3f80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Veseli=20Kraji=C5=A1nik?= Date: Sun, 15 Jan 2023 08:41:10 +0000 Subject: [PATCH 31/50] Translated using Weblate (Serbian) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/sr/ --- app/src/main/res/values-sr/strings.xml | 57 ++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 5d8bc415f..39329ad9b 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -389,4 +389,61 @@ Шта је сада у тренду Обележивачи Обележивач + Локалне листе + Свестрана љубичаста + Ставка менија није омогућена! + Прво изаберите другу почетну картицу! + Осветлење екрана + Јачина звука + Аутоматски + Брзо превлачење контрола + Користите покрет брзог превлачења да бисте подесили светлину екрана и јачину звука. + Подразумевано + Искачући + Величина натписа + Пауза + Премотај уназад + Додирните двапут да бисте тражили + Додирните двапут са леве или десне стране да бисте премотали или проследили позицију плејера. + Није могуће добити доступне инстанце. + Не приказуј видео записе који се гледају више од 90% на картици са праћењима. + Ништа изабрано! + Штипање + Извези листе + Прављење резервне копије апликације + Репродукуј најновије видео записе + Аудио плејер + URL листе + Нема превода + Преузимање је паузирано + Преузимање је завршено + Максимално истовремених преузимања + Овај видео нема доступних коментара. + Минималистички монохром + Видели сте све нове снимке + Све прегледано + Увези листе + Увоз & извоз праћења, листа,… + Извезено. + Упозорење о приватности + Желите ли да наставите са е-адресом која се не препоручује\? + Настави + Сакриј гледане видео записе са фида + Премотај унапред + Алтернативне PiP контроле + Приказивање само звука и прескакање контрола у PiP-у уместо унапред и уназад + Режим само звука + Претвори LibreTube у музички плејер. + Максимално истовремених преузимања је достигнуто. + Користите покрет штипања за увећавање/умањивање. + Непознато + Настави + Отпремилац је онемогућио коментаре. + Пауза приликом изласка + Уметање сродних видео записа + Брисање обележивача + Нема обележивача! + Насумично + Обриши обележивач + Додај у обележиваче \ No newline at end of file From 9eae83903674c58c23805b5ab3701e8bc2ab55ef Mon Sep 17 00:00:00 2001 From: GET100PERCENT Date: Sat, 14 Jan 2023 18:00:05 +0000 Subject: [PATCH 32/50] Translated using Weblate (Odia) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/or/ --- app/src/main/res/values-or/strings.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/src/main/res/values-or/strings.xml b/app/src/main/res/values-or/strings.xml index 3daae90e2..204cffe04 100644 --- a/app/src/main/res/values-or/strings.xml +++ b/app/src/main/res/values-or/strings.xml @@ -437,4 +437,13 @@ ବିକଳ୍ପ PIP ନିୟନ୍ତ୍ରଣ କେବଳ ଅଡିଓ ଦେଖାନ୍ତୁ ଏବଂ ଆଗକୁ ଏବଂ ପଛକୁ ନେବା ପରିବର୍ତ୍ତେ PiP ରେ କଣ୍ଟ୍ରୋଲ୍ ଛାଡିଦିଅ ଅଡିଓ ପ୍ଲେୟାର + କୌଣସି ଉପ-ଆଖ୍ୟା ନାହିଁ + ଡାଉନଲୋଡ୍ ବିରତ ହୋଇଛି + ଡାଉନଲୋଡ୍ ସମାପ୍ତ ହୋଇଛି + ସର୍ବାଧିକ ଏକକାଳୀନ ଡାଉନଲୋଡ୍ + ସର୍ବାଧିକ ଏକକାଳୀନ ଡାଉନଲୋଡ୍ ସୀମା ପହଞ୍ଚିଲା । + ଅଜ୍ଞାତ + ପୁଣି ଆରମ୍ଭ କରନ୍ତୁ + କେବଳ ଅଡିଓ ମୋଡ୍ + LibreTube କୁ ଏକ ମ୍ୟୁଜିକ୍ ପ୍ଲେୟାରରେ ପରିଣତ କର । \ No newline at end of file From 38baeb92f3e1dd8bfc64c1f4a8f8d5ea42f7277b Mon Sep 17 00:00:00 2001 From: RSoulwin Date: Sat, 14 Jan 2023 23:41:51 +0000 Subject: [PATCH 33/50] Translated using Weblate (Punjabi) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/pa/ --- app/src/main/res/values-pa/strings.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index ee84c03c8..da813dbdb 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -439,4 +439,11 @@ ਆਡੀਓ ਪਲੇਅਰ ਸਿਰਫ ਆਡੀਓ ਮੋਡ LibreTube ਨੂੰ ਇੱਕ ਸੰਗੀਤ ਪਲੇਅਰ ਵਿੱਚ ਬਦਲੋ। + ਕੋਈ ਉਪਸਿਰਲੇਖ ਨਹੀਂ + ਅਗਿਆਤ + ਡਾਊਨਲੋਡ ਰੋਕਿਆ ਗਿਆ + ਡਾਊਨਲੋਡ ਪੂਰਾ ਹੋਇਆ + ਮੁੜ ਸ਼ੁਰੂ ਕਰੋ + ਅਧਿਕਤਮ ਸਮਕਾਲੀ ਡਾਊਨਲੋਡ + ਅਧਿਕਤਮ ਸਮਕਾਲੀ ਡਾਊਨਲੋਡ ਸੀਮਾ ਪੂਰੀ ਹੋ ਗਈ ਹੈ। \ No newline at end of file From 384a26d6de7ccfdaf28231648c6c9a339f635f42 Mon Sep 17 00:00:00 2001 From: Lam Lam Chi Date: Sun, 15 Jan 2023 11:32:02 +0000 Subject: [PATCH 34/50] Translated using Weblate (Yue) Currently translated at 18.8% (84 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/yue/ --- app/src/main/res/values-yue/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-yue/strings.xml b/app/src/main/res/values-yue/strings.xml index 6b6a972dd..9c65b68bb 100644 --- a/app/src/main/res/values-yue/strings.xml +++ b/app/src/main/res/values-yue/strings.xml @@ -83,4 +83,5 @@ YT Music 歌 Sponsor + 較嘢 \ No newline at end of file From 2f10b7ba2324af45d29c939b30417c960bb98834 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 16 Jan 2023 18:25:12 +0100 Subject: [PATCH 35/50] Option to add newly opened links to queue --- app/src/main/AndroidManifest.xml | 17 +++++++- .../ui/activities/AddToQueueActivity.kt | 39 +++++++++++++++++++ .../libretube/ui/activities/RouterActivity.kt | 6 +-- .../com/github/libretube/util/PlayingQueue.kt | 23 +++++++---- 4 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 app/src/main/java/com/github/libretube/ui/activities/AddToQueueActivity.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 06d4a6c8f..279de389d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -47,6 +47,21 @@ android:name=".ui.activities.CommunityActivity" android:label="@string/settings" /> + + + + + + + + + + - + diff --git a/app/src/main/java/com/github/libretube/ui/activities/AddToQueueActivity.kt b/app/src/main/java/com/github/libretube/ui/activities/AddToQueueActivity.kt new file mode 100644 index 000000000..e1f1ca436 --- /dev/null +++ b/app/src/main/java/com/github/libretube/ui/activities/AddToQueueActivity.kt @@ -0,0 +1,39 @@ +package com.github.libretube.ui.activities + +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import com.github.libretube.ui.base.BaseActivity +import com.github.libretube.util.PlayingQueue + +/** + * Receives a text by the intent and attempts to add it to the playing queue + * If no video is playing currently, the queue will be left unchanged and the the main activity is being resumed + */ +class AddToQueueActivity : BaseActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + val uri = Uri.parse(intent.getStringExtra(Intent.EXTRA_TEXT)!!) + var videoId: String? = null + listOf("/shorts/", "/v/", "/embed/").forEach { + if (uri.path!!.contains(it)) { + videoId = uri.path!!.replace(it, "") + } + } + if ( + uri.path!!.contains("/watch") && uri.query != null + ) { + videoId = uri.getQueryParameter("v") + } + + if (videoId == null) videoId = uri.path!!.replace("/", "") + + // if playing a video currently, the playing queue is not empty + if (PlayingQueue.isNotEmpty()) PlayingQueue.insertByVideoId(videoId!!) + + val intent = packageManager.getLaunchIntentForPackage(packageName) + startActivity(intent) + finishAndRemoveTask() + } +} diff --git a/app/src/main/java/com/github/libretube/ui/activities/RouterActivity.kt b/app/src/main/java/com/github/libretube/ui/activities/RouterActivity.kt index a0ff62adf..898e35557 100644 --- a/app/src/main/java/com/github/libretube/ui/activities/RouterActivity.kt +++ b/app/src/main/java/com/github/libretube/ui/activities/RouterActivity.kt @@ -84,10 +84,8 @@ class RouterActivity : BaseActivity() { val pm: PackageManager = this.packageManager val intent = pm.getLaunchIntentForPackage(this.packageName) intent?.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK - this.startActivity( - resolveType(intent!!, uri) - ) - this.finishAndRemoveTask() + startActivity(resolveType(intent!!, uri)) + finishAndRemoveTask() } private fun parseTimestamp(t: String): Long? { diff --git a/app/src/main/java/com/github/libretube/util/PlayingQueue.kt b/app/src/main/java/com/github/libretube/util/PlayingQueue.kt index 995f45bfd..35f3c3436 100644 --- a/app/src/main/java/com/github/libretube/util/PlayingQueue.kt +++ b/app/src/main/java/com/github/libretube/util/PlayingQueue.kt @@ -6,6 +6,7 @@ import com.github.libretube.api.RetrofitInstance import com.github.libretube.api.obj.StreamItem import com.github.libretube.extensions.move import com.github.libretube.extensions.toID +import com.github.libretube.extensions.toStreamItem import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -13,6 +14,7 @@ import kotlinx.coroutines.launch object PlayingQueue { private val queue = mutableListOf() private var currentStream: StreamItem? = null + private val scope = CoroutineScope(Dispatchers.IO) /** * Listener that gets called when the user selects an item from the queue @@ -111,7 +113,7 @@ object PlayingQueue { private fun fetchMoreFromPlaylist(playlistId: String, nextPage: String?) { var playlistNextPage: String? = nextPage - CoroutineScope(Dispatchers.IO).launch { + scope.launch { while (playlistNextPage != null) { RetrofitInstance.authApi.getPlaylistNextPage( playlistId, @@ -127,7 +129,7 @@ object PlayingQueue { } fun insertPlaylist(playlistId: String, newCurrentStream: StreamItem) { - CoroutineScope(Dispatchers.IO).launch { + scope.launch { try { val playlist = PlaylistsHelper.getPlaylist(playlistId) add(*playlist.relatedStreams.orEmpty().toTypedArray()) @@ -142,7 +144,7 @@ object PlayingQueue { private fun fetchMoreFromChannel(channelId: String, nextPage: String?) { var channelNextPage: String? = nextPage - CoroutineScope(Dispatchers.IO).launch { + scope.launch { while (channelNextPage != null) { RetrofitInstance.api.getChannelNextPage(channelId, nextPage!!).apply { add(*relatedStreams.orEmpty().toTypedArray()) @@ -153,15 +155,22 @@ object PlayingQueue { } fun insertChannel(channelId: String, newCurrentStream: StreamItem) { - CoroutineScope(Dispatchers.IO).launch { - try { + scope.launch { + runCatching { val channel = RetrofitInstance.api.getChannel(channelId) add(*channel.relatedStreams.orEmpty().toTypedArray()) updateCurrent(newCurrentStream) if (channel.nextpage == null) return@launch fetchMoreFromChannel(channelId, channel.nextpage) - } catch (e: Exception) { - e.printStackTrace() + } + } + } + + fun insertByVideoId(videoId: String) { + scope.launch { + runCatching { + val streams = RetrofitInstance.api.getStreams(videoId.toID()) + add(streams.toStreamItem(videoId)) } } } From 4e978faea33cbebb0e77c1a6ddab148350ab8e0a Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 16 Jan 2023 18:33:11 +0100 Subject: [PATCH 36/50] Fix unexpected audio queue behavior --- .../java/com/github/libretube/services/BackgroundMode.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/github/libretube/services/BackgroundMode.kt b/app/src/main/java/com/github/libretube/services/BackgroundMode.kt index 7ad013a21..dd9e0dbb8 100644 --- a/app/src/main/java/com/github/libretube/services/BackgroundMode.kt +++ b/app/src/main/java/com/github/libretube/services/BackgroundMode.kt @@ -169,6 +169,9 @@ class BackgroundMode : Service() { /** * Gets the video data and prepares the [player]. + * @param videoId The id of the video to play + * @param seekToPosition The position of the video to seek to + * @param keepQueue Whether to keep the queue or clear it instead */ private fun loadAudio( videoId: String, @@ -298,7 +301,7 @@ class BackgroundMode : Service() { this.videoId = nextVideo this.streams = null this.segmentData = null - loadAudio(videoId) + loadAudio(videoId, keepQueue = true) } /** From aa3aee0b277216fc26333bdb24150e948f5ea724 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 16 Jan 2023 18:36:30 +0100 Subject: [PATCH 37/50] Fix the color of notification badges --- .../main/java/com/github/libretube/ui/activities/MainActivity.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt b/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt index 66d3a6174..650d807a6 100644 --- a/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt +++ b/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt @@ -247,6 +247,7 @@ class MainActivity : BaseActivity() { binding.bottomNav.getOrCreateBadge(R.id.subscriptionsFragment).apply { number = lastSeenVideoIndex backgroundColor = ThemeHelper.getThemeColor(this@MainActivity, R.attr.colorPrimary) + badgeTextColor = ThemeHelper.getThemeColor(this@MainActivity, R.attr.colorOnPrimary) } } } From bda610d99ce5e4289f64902ce2bf6a23d7c5082a Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 16 Jan 2023 20:02:07 +0100 Subject: [PATCH 38/50] Fix duplicated videos in the playing queue --- .../java/com/github/libretube/util/PlayingQueue.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/github/libretube/util/PlayingQueue.kt b/app/src/main/java/com/github/libretube/util/PlayingQueue.kt index 35f3c3436..31769d384 100644 --- a/app/src/main/java/com/github/libretube/util/PlayingQueue.kt +++ b/app/src/main/java/com/github/libretube/util/PlayingQueue.kt @@ -30,11 +30,11 @@ object PlayingQueue { fun clear() = queue.clear() fun add(vararg streamItem: StreamItem) { - streamItem.forEach { - if (currentStream != it) { - if (queue.contains(it)) queue.remove(it) - queue.add(it) - } + for (stream in streamItem) { + if (currentStream?.url?.toID() == stream.url?.toID()) continue + // remove if already present + queue.remove(stream) + queue.add(stream) } } From f6473cfa9694323dc25625494cf74e7c6c46e6b5 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Mon, 16 Jan 2023 22:08:08 +0100 Subject: [PATCH 39/50] Use compats for setting fullscreen --- .../libretube/ui/activities/MainActivity.kt | 72 ++----------------- .../ui/activities/OfflinePlayerActivity.kt | 34 +-------- .../libretube/ui/views/CustomExoPlayerView.kt | 2 +- .../com/github/libretube/util/WindowHelper.kt | 49 +++++++++++++ 4 files changed, 56 insertions(+), 101 deletions(-) create mode 100644 app/src/main/java/com/github/libretube/util/WindowHelper.kt diff --git a/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt b/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt index 650d807a6..e5059634d 100644 --- a/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt +++ b/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt @@ -6,15 +6,10 @@ import android.content.pm.ActivityInfo import android.content.res.Configuration import android.os.Build import android.os.Bundle -import android.os.Handler -import android.os.Looper import android.view.Menu import android.view.MenuItem import android.view.View import android.view.ViewGroup -import android.view.WindowInsets -import android.view.WindowInsetsController -import android.view.WindowManager import android.widget.ScrollView import androidx.activity.OnBackPressedCallback import androidx.appcompat.widget.SearchView @@ -46,6 +41,7 @@ import com.github.libretube.util.NavigationHelper import com.github.libretube.util.NetworkHelper import com.github.libretube.util.PreferenceHelper import com.github.libretube.util.ThemeHelper +import com.github.libretube.util.WindowHelper import com.google.android.material.elevation.SurfaceColors class MainActivity : BaseActivity() { @@ -60,7 +56,7 @@ class MainActivity : BaseActivity() { lateinit var searchView: SearchView private lateinit var searchItem: MenuItem - private val handler = Handler(Looper.getMainLooper()) + val windowHelper = WindowHelper(this) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -468,68 +464,8 @@ class MainActivity : BaseActivity() { super.onConfigurationChanged(newConfig) when (newConfig.orientation) { - Configuration.ORIENTATION_PORTRAIT -> unsetFullscreen() - Configuration.ORIENTATION_LANDSCAPE -> setFullscreen() - } - } - - fun setFullscreen() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - window.attributes.layoutInDisplayCutoutMode = - WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - window.setDecorFitsSystemWindows(false) - window.insetsController?.apply { - hide(WindowInsets.Type.statusBars() or WindowInsets.Type.navigationBars()) - systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - } - } else { - @Suppress("DEPRECATION") - window.decorView.systemUiVisibility = ( - View.SYSTEM_UI_FLAG_FULLSCREEN - or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - or View.SYSTEM_UI_FLAG_IMMERSIVE - or View.SYSTEM_UI_FLAG_LAYOUT_STABLE - or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - ) - } - - window.setFlags( - WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, - WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS - ) - } - - private fun unsetFullscreen() { - window.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { - @Suppress("DEPRECATION") - window.clearFlags( - WindowManager.LayoutParams.FLAG_FULLSCREEN - ) - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - window.attributes.layoutInDisplayCutoutMode = - WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - window.setDecorFitsSystemWindows(true) - window.insetsController?.apply { - show(WindowInsets.Type.statusBars() or WindowInsets.Type.navigationBars()) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - systemBarsBehavior = WindowInsetsController.BEHAVIOR_DEFAULT - } - } - } else { - @Suppress("DEPRECATION") - window.decorView.systemUiVisibility = - (View.SYSTEM_UI_FLAG_VISIBLE or View.SYSTEM_UI_FLAG_LAYOUT_STABLE) + Configuration.ORIENTATION_PORTRAIT -> windowHelper.unsetFullscreen() + Configuration.ORIENTATION_LANDSCAPE -> windowHelper.setFullscreen() } } diff --git a/app/src/main/java/com/github/libretube/ui/activities/OfflinePlayerActivity.kt b/app/src/main/java/com/github/libretube/ui/activities/OfflinePlayerActivity.kt index 4a4762fb8..253e6a662 100644 --- a/app/src/main/java/com/github/libretube/ui/activities/OfflinePlayerActivity.kt +++ b/app/src/main/java/com/github/libretube/ui/activities/OfflinePlayerActivity.kt @@ -2,18 +2,13 @@ package com.github.libretube.ui.activities import android.app.PictureInPictureParams import android.content.pm.ActivityInfo -import android.graphics.Color import android.media.session.PlaybackState import android.net.Uri import android.os.Build import android.os.Bundle import android.text.format.DateUtils import android.view.View -import android.view.WindowManager import androidx.activity.viewModels -import androidx.core.view.WindowCompat -import androidx.core.view.WindowInsetsCompat -import androidx.core.view.WindowInsetsControllerCompat import com.github.libretube.constants.IntentData import com.github.libretube.databinding.ActivityOfflinePlayerBinding import com.github.libretube.databinding.ExoStyledPlayerControlViewBinding @@ -25,6 +20,7 @@ import com.github.libretube.ui.base.BaseActivity import com.github.libretube.ui.extensions.setAspectRatio import com.github.libretube.ui.models.PlayerViewModel import com.github.libretube.util.PlayerHelper +import com.github.libretube.util.WindowHelper import com.google.android.exoplayer2.C import com.google.android.exoplayer2.ExoPlayer import com.google.android.exoplayer2.MediaItem @@ -49,7 +45,7 @@ class OfflinePlayerActivity : BaseActivity() { private val playerViewModel: PlayerViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { - hideSystemBars() + WindowHelper(this).setFullscreen() requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE @@ -179,32 +175,6 @@ class OfflinePlayerActivity : BaseActivity() { } } - @Suppress("DEPRECATION") - private fun hideSystemBars() { - window?.decorView?.systemUiVisibility = ( - View.SYSTEM_UI_FLAG_LAYOUT_STABLE - or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - ) - window.statusBarColor = Color.TRANSPARENT - - window.setFlags( - WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, - WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN - ) - - val windowInsetsController = - WindowCompat.getInsetsController(window, window.decorView) - windowInsetsController.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - windowInsetsController.hide(WindowInsetsCompat.Type.statusBars()) - - supportActionBar?.hide() - - windowInsetsController.systemBarsBehavior = - WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()) - } - override fun onResume() { playerViewModel.isFullscreen.value = true super.onResume() diff --git a/app/src/main/java/com/github/libretube/ui/views/CustomExoPlayerView.kt b/app/src/main/java/com/github/libretube/ui/views/CustomExoPlayerView.kt index 9b33f4354..05f9a1bd8 100644 --- a/app/src/main/java/com/github/libretube/ui/views/CustomExoPlayerView.kt +++ b/app/src/main/java/com/github/libretube/ui/views/CustomExoPlayerView.kt @@ -189,7 +189,7 @@ internal class CustomExoPlayerView( override fun hideController() { if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) { // hide all the navigation bars that potentially could have been reopened manually ba the user - (context as? MainActivity)?.setFullscreen() + (context as? MainActivity)?.windowHelper?.setFullscreen() } super.hideController() } diff --git a/app/src/main/java/com/github/libretube/util/WindowHelper.kt b/app/src/main/java/com/github/libretube/util/WindowHelper.kt new file mode 100644 index 000000000..e75c6855d --- /dev/null +++ b/app/src/main/java/com/github/libretube/util/WindowHelper.kt @@ -0,0 +1,49 @@ +package com.github.libretube.util + +import android.os.Build +import android.view.WindowManager +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.WindowInsetsControllerCompat +import com.github.libretube.ui.base.BaseActivity + +class WindowHelper(private val activity: BaseActivity) { + fun setFullscreen() = activity.apply { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + window.attributes.layoutInDisplayCutoutMode = + WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES + } + + WindowCompat.setDecorFitsSystemWindows(window, false) + WindowInsetsControllerCompat(window, window.decorView).let { controller -> + controller.hide( + WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.navigationBars() + ) + controller.systemBarsBehavior = + WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + } + + window.setFlags( + WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, + WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS + ) + } + + fun unsetFullscreen() = activity.apply { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + window.attributes.layoutInDisplayCutoutMode = + WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT + } + + WindowCompat.setDecorFitsSystemWindows(window, true) + WindowInsetsControllerCompat(window, window.decorView).let { controller -> + controller.show( + WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.navigationBars() + ) + controller.systemBarsBehavior = + WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_TOUCH + } + + window.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) + } +} From 345f34f67670f8f2c521f4417b9c9048c89dcf38 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Tue, 17 Jan 2023 06:48:07 +0530 Subject: [PATCH 40/50] Simplify TimePickerPreference implementation. --- .../ui/views/TimePickerPreference.kt | 39 +++++-------------- .../com/github/libretube/util/TextUtils.kt | 4 -- 2 files changed, 9 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/com/github/libretube/ui/views/TimePickerPreference.kt b/app/src/main/java/com/github/libretube/ui/views/TimePickerPreference.kt index 3bb1830a2..f319b2ac5 100644 --- a/app/src/main/java/com/github/libretube/ui/views/TimePickerPreference.kt +++ b/app/src/main/java/com/github/libretube/ui/views/TimePickerPreference.kt @@ -6,60 +6,39 @@ import android.util.AttributeSet import androidx.appcompat.app.AppCompatActivity import androidx.preference.Preference import com.github.libretube.util.PreferenceHelper -import com.github.libretube.util.TextUtils import com.google.android.material.timepicker.MaterialTimePicker import com.google.android.material.timepicker.TimeFormat +import java.time.LocalTime class TimePickerPreference( context: Context, attributeSet: AttributeSet ) : Preference(context, attributeSet) { override fun getSummary(): CharSequence { - val prefStr = PreferenceHelper.getString(key, "") - return if (prefStr != "") prefStr else DEFAULT_VALUE + return PreferenceHelper.getString(key, DEFAULT_VALUE) } override fun onClick() { + val prefTime = LocalTime.parse(PreferenceHelper.getString(key, DEFAULT_VALUE)) val picker = MaterialTimePicker.Builder() .setInputMode(MaterialTimePicker.INPUT_MODE_CLOCK) - .setTimeFormat(getTimeFormat()) - .setHour(getHour()) - .setMinute(getMinutes()) + .setTimeFormat(timeFormat) + .setHour(prefTime.hour) + .setMinute(prefTime.minute) .build() picker.addOnPositiveButtonClickListener { - val timeStr = getTimeStr(picker) + val timeStr = LocalTime.of(picker.hour, picker.minute).toString() PreferenceHelper.putString(key, timeStr) summary = timeStr } picker.show((context as AppCompatActivity).supportFragmentManager, null) } - private fun getTimeFormat(): Int { - return if (is24HourFormat(context)) TimeFormat.CLOCK_24H else TimeFormat.CLOCK_12H - } - - private fun getPrefStringPart(index: Int): String? { - val prefStr = PreferenceHelper.getString(key, "").split(SEPARATOR).getOrNull(index) - return if (prefStr != "") prefStr else null - } - - private fun getHour(): Int { - return getPrefStringPart(0)?.toInt() ?: 0 - } - - private fun getMinutes(): Int { - return getPrefStringPart(1)?.toInt() ?: 0 - } - - private fun getTimeStr(picker: MaterialTimePicker): String { - val hour = TextUtils.toTwoDecimalsString(picker.hour) - val minute = TextUtils.toTwoDecimalsString(picker.minute) - return "$hour$SEPARATOR$minute" - } + private val timeFormat: Int + get() = if (is24HourFormat(context)) TimeFormat.CLOCK_24H else TimeFormat.CLOCK_12H companion object { - const val SEPARATOR = ":" const val DEFAULT_VALUE = "12:00" } } diff --git a/app/src/main/java/com/github/libretube/util/TextUtils.kt b/app/src/main/java/com/github/libretube/util/TextUtils.kt index b9633ff12..6d100523d 100644 --- a/app/src/main/java/com/github/libretube/util/TextUtils.kt +++ b/app/src/main/java/com/github/libretube/util/TextUtils.kt @@ -22,10 +22,6 @@ object TextUtils { */ const val RESERVED_CHARS = "?:\"*|/\\<>\u0000" - fun toTwoDecimalsString(num: Int): String { - return if (num >= 10) num.toString() else "0$num" - } - /** * Check whether an Url is valid * @param url The url to test From 18ba225e7748ec970f44325f0b1b82ad2f3574b4 Mon Sep 17 00:00:00 2001 From: Mohamed Aashif Date: Tue, 17 Jan 2023 03:51:17 +0100 Subject: [PATCH 41/50] Added translation using Weblate (Sinhala) --- app/src/main/res/values-si/strings.xml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 app/src/main/res/values-si/strings.xml diff --git a/app/src/main/res/values-si/strings.xml b/app/src/main/res/values-si/strings.xml new file mode 100644 index 000000000..a6b3daec9 --- /dev/null +++ b/app/src/main/res/values-si/strings.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file From 2bf5b6e6f768178b5c4edd51ad005fc88a1c4409 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Tue, 17 Jan 2023 18:21:59 +0100 Subject: [PATCH 42/50] Replace the break reminder with a sleep timer --- .../libretube/constants/PreferenceKeys.kt | 4 +- .../libretube/ui/activities/MainActivity.kt | 17 +++-- .../ui/preferences/GeneralSettings.kt | 15 +++-- .../libretube/ui/tools/BreakReminder.kt | 55 ---------------- .../github/libretube/ui/tools/SleepTimer.kt | 62 +++++++++++++++++++ app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/general_settings.xml | 6 +- 7 files changed, 85 insertions(+), 75 deletions(-) delete mode 100644 app/src/main/java/com/github/libretube/ui/tools/BreakReminder.kt create mode 100644 app/src/main/java/com/github/libretube/ui/tools/SleepTimer.kt diff --git a/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt b/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt index 56d9070d4..f460c9f94 100644 --- a/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt +++ b/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt @@ -18,8 +18,8 @@ object PreferenceKeys { const val LANGUAGE = "language" const val REGION = "region" const val AUTO_ROTATION = "auto_rotation" - const val BREAK_REMINDER_TOGGLE = "break_reminder_toggle" - const val BREAK_REMINDER = "break_reminder" + const val SLEEP_TIMER = "sleep_timer_toggle" + const val SLEEP_TIMER_DELAY = "sleep_timer_delay" const val SAVE_FEED = "save_feed" const val NAVBAR_ITEMS = "navbar_items" const val START_FRAGMENT = "start_fragment" diff --git a/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt b/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt index e5059634d..cbd3d7239 100644 --- a/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt +++ b/app/src/main/java/com/github/libretube/ui/activities/MainActivity.kt @@ -35,7 +35,7 @@ import com.github.libretube.ui.fragments.PlayerFragment import com.github.libretube.ui.models.PlayerViewModel import com.github.libretube.ui.models.SearchViewModel import com.github.libretube.ui.models.SubscriptionsViewModel -import com.github.libretube.ui.tools.BreakReminder +import com.github.libretube.ui.tools.SleepTimer import com.github.libretube.util.NavBarHelper import com.github.libretube.util.NavigationHelper import com.github.libretube.util.NetworkHelper @@ -132,13 +132,12 @@ class MainActivity : BaseActivity() { binding.toolbar.title = ThemeHelper.getStyledAppName(this) - /** - * handle error logs - */ - val log = PreferenceHelper.getErrorLog() - if (log != "") ErrorDialog().show(supportFragmentManager, null) + // handle error logs + PreferenceHelper.getErrorLog().ifBlank { null }?.let { + ErrorDialog().show(supportFragmentManager, null) + } - BreakReminder.setupBreakReminder(applicationContext) + SleepTimer.setup(this) setupSubscriptionsBadge() @@ -157,11 +156,9 @@ class MainActivity : BaseActivity() { } if (binding.mainMotionLayout.progress == 0F) { - try { + runCatching { minimizePlayer() return - } catch (e: Exception) { - // current fragment isn't the player fragment } } diff --git a/app/src/main/java/com/github/libretube/ui/preferences/GeneralSettings.kt b/app/src/main/java/com/github/libretube/ui/preferences/GeneralSettings.kt index 4c4b58e3f..5d28cf875 100644 --- a/app/src/main/java/com/github/libretube/ui/preferences/GeneralSettings.kt +++ b/app/src/main/java/com/github/libretube/ui/preferences/GeneralSettings.kt @@ -30,21 +30,26 @@ class GeneralSettings : BasePreferenceFragment() { val autoRotation = findPreference(PreferenceKeys.AUTO_ROTATION) autoRotation?.setOnPreferenceChangeListener { _, _ -> - val restartDialog = RequireRestartDialog() - restartDialog.show(childFragmentManager, RequireRestartDialog::class.java.name) + RequireRestartDialog().show(childFragmentManager, RequireRestartDialog::class.java.name) true } val breakReminder = - findPreference(PreferenceKeys.BREAK_REMINDER_TOGGLE) - val breakReminderTime = findPreference(PreferenceKeys.BREAK_REMINDER) + findPreference(PreferenceKeys.SLEEP_TIMER) + val breakReminderTime = findPreference(PreferenceKeys.SLEEP_TIMER_DELAY) breakReminderTime?.isEnabled = PreferenceHelper.getBoolean( - PreferenceKeys.BREAK_REMINDER_TOGGLE, + PreferenceKeys.SLEEP_TIMER, false ) breakReminder?.setOnPreferenceChangeListener { _, newValue -> breakReminderTime?.isEnabled = newValue as Boolean + RequireRestartDialog().show(childFragmentManager, RequireRestartDialog::class.java.name) + true + } + + breakReminderTime?.setOnPreferenceChangeListener { _, _ -> + RequireRestartDialog().show(childFragmentManager, RequireRestartDialog::class.java.name) true } } diff --git a/app/src/main/java/com/github/libretube/ui/tools/BreakReminder.kt b/app/src/main/java/com/github/libretube/ui/tools/BreakReminder.kt deleted file mode 100644 index 7e38e059f..000000000 --- a/app/src/main/java/com/github/libretube/ui/tools/BreakReminder.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.github.libretube.ui.tools - -import android.content.Context -import android.os.Handler -import android.os.Looper -import android.widget.Toast -import com.github.libretube.R -import com.github.libretube.constants.PreferenceKeys -import com.github.libretube.util.PreferenceHelper -import com.google.android.material.dialog.MaterialAlertDialogBuilder - -object BreakReminder { - /** - * Show a break reminder when watched too long - */ - fun setupBreakReminder(context: Context) { - if (!PreferenceHelper.getBoolean( - PreferenceKeys.BREAK_REMINDER_TOGGLE, - false - ) - ) { - return - } - val breakReminderPref = PreferenceHelper.getString( - PreferenceKeys.BREAK_REMINDER, - "0" - ) - if (!breakReminderPref.all { Character.isDigit(it) } || - breakReminderPref == "" || breakReminderPref == "0" - ) { - return - } - Handler(Looper.getMainLooper()).postDelayed( - { - try { - MaterialAlertDialogBuilder(context) - .setTitle(R.string.take_a_break) - .setMessage( - context.getString( - R.string.already_spent_time, - breakReminderPref - ) - ) - .setPositiveButton(R.string.okay, null) - .show() - } catch (e: Exception) { - runCatching { - Toast.makeText(context, R.string.take_a_break, Toast.LENGTH_LONG).show() - } - } - }, - breakReminderPref.toLong() * 60 * 1000 - ) - } -} diff --git a/app/src/main/java/com/github/libretube/ui/tools/SleepTimer.kt b/app/src/main/java/com/github/libretube/ui/tools/SleepTimer.kt new file mode 100644 index 000000000..5fe8c2b74 --- /dev/null +++ b/app/src/main/java/com/github/libretube/ui/tools/SleepTimer.kt @@ -0,0 +1,62 @@ +package com.github.libretube.ui.tools + +import android.content.Context +import android.os.Handler +import android.os.Looper +import com.github.libretube.R +import com.github.libretube.constants.PreferenceKeys +import com.github.libretube.ui.activities.MainActivity +import com.github.libretube.util.PreferenceHelper +import com.google.android.material.snackbar.Snackbar + +object SleepTimer { + private val handler = Handler(Looper.getMainLooper()) + private const val REACTION_INTERVAL = 5L + + /** + * Kill the app after showing a warning after a certain amount of time + * @param context This must not be the applicationContext! + */ + fun setup(context: Context) { + if (!PreferenceHelper.getBoolean(PreferenceKeys.SLEEP_TIMER, false)) return + + val breakReminderPref = PreferenceHelper.getString( + PreferenceKeys.SLEEP_TIMER_DELAY, + "" + ).ifEmpty { return } + + handler.postDelayed( + { + var killApp = true + val mainActivity = context as? MainActivity ?: return@postDelayed + val snackBar = Snackbar.make( + mainActivity.binding.root, + R.string.take_a_break, + Snackbar.LENGTH_INDEFINITE + ) + .setAction(R.string.cancel) { + killApp = false + } + snackBar.show() + (0..REACTION_INTERVAL).forEach { + handler.postDelayed({ + val remainingTime = " (${REACTION_INTERVAL - it})" + snackBar.setText(context.getString(R.string.take_a_break) + remainingTime) + }, it * 1000) + } + handler.postDelayed( + killApp@{ + if (!killApp) return@killApp + + // kill the application + mainActivity.finishAffinity() + mainActivity.finish() + android.os.Process.killProcess(android.os.Process.myPid()) + }, + REACTION_INTERVAL * 1000 + ) + }, + breakReminderPref.toLong() * 60 * 1000 + ) + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2d656d3c3..2146b817b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -440,6 +440,7 @@ Audio player Audio only mode Turn LibreTube into a music player. + Sleep timer Download Service diff --git a/app/src/main/res/xml/general_settings.xml b/app/src/main/res/xml/general_settings.xml index 67b585be7..e98d056ff 100644 --- a/app/src/main/res/xml/general_settings.xml +++ b/app/src/main/res/xml/general_settings.xml @@ -50,14 +50,14 @@ + app:key="sleep_timer_toggle" + app:title="@string/sleep_timer" /> From 82903819e9554e9ee42483e19d179577f5a12edc Mon Sep 17 00:00:00 2001 From: Nidi Date: Mon, 16 Jan 2023 22:51:28 +0000 Subject: [PATCH 43/50] Translated using Weblate (Azerbaijani) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/az/ --- app/src/main/res/values-az/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index 854178d4c..0921627cc 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -434,7 +434,7 @@ İrəli Fasilə ver Alternativ PiP nəzarətləri - Yalnız səsi göstər və irəli və geri çevirmək əvəzinə PiP-də idarəetmələri ötür + Yalnız səsi göstər və irəli və geri çevirmək əvəzində PiP-də idarəetmələri ötür Geri sar Səs oynadıcı Yalnız səs rejimi From d30002abcdf72bb0c94e4e78dacb08ea86b0586b Mon Sep 17 00:00:00 2001 From: MkQtS Date: Tue, 17 Jan 2023 07:22:06 +0000 Subject: [PATCH 44/50] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/zh_Hans/ --- app/src/main/res/values-zh-rCN/strings.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index df7f8d650..7b53dd164 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -437,4 +437,13 @@ 备选 PiP (画中画)操控 仅显示音频并跳过画中画操控而非前进和后退 音频播放器 + 将 LibreTube 作为音乐播放器。 + 无字幕 + 下载已暂停 + 下载已完成 + 最大并发下载 + 已达到最大并发下载限制。 + 未知 + 恢复 + 仅音频模式 \ No newline at end of file From 7c7b46f53924bd059fbb98099af3ea0414127bc5 Mon Sep 17 00:00:00 2001 From: Mohamed Aashif Date: Tue, 17 Jan 2023 02:55:07 +0000 Subject: [PATCH 45/50] Translated using Weblate (Sinhala) Currently translated at 100.0% (446 of 446 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/si/ --- app/src/main/res/values-si/strings.xml | 449 ++++++++++++++++++++++++- 1 file changed, 448 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-si/strings.xml b/app/src/main/res/values-si/strings.xml index a6b3daec9..06ad6fef3 100644 --- a/app/src/main/res/values-si/strings.xml +++ b/app/src/main/res/values-si/strings.xml @@ -1,2 +1,449 @@ - \ No newline at end of file + + ලේඛනාලය + ඔව් + ගුණත්වය + සොයන්න + වීඩියෝ + දායකවන්න + බෙදාගන්න + බාගත කරන්න + සුරකින්න + පරිශීලක නාමය + ඇතුළු වන්න + ලියාපදිංචි වන්න + වරනය වන්න + අවලංගු කරන්න + වරනය වුනා. + දැනටමත් පුරනය වී ඇත. ඔබට ඔබගේ ගිණුමෙන් වරනය විය හැක. + කරුණාකර පුරනය වී නැවත උත්සාහ කරන්න. + අභිරුචිය පරිදි + කලාපය + කරුණාකර පළමුව පුරනය වන්න හෝ සැකසීම් තුළ ලියාපදිංචි වන්න. + දායක විය + මෙම ප්‍රවාහය බාගත කළ නොහැක. + බාගත කිරීම සම්පූර්ණයි. + බාගත කිරීම අසමත් විය. + VLC හි විවෘත කරන්න + දායකත්වයන් ආනයනය කරන්න + YouTube හෝ NewPipe වෙතින් + පෙනුම + ජාල දෝෂයකි. + මොකක්හරි වැරැද්දක් වෙලා. + ජාලකයේ තීරු ගණන + මෙහි කිසිවක් නැහැ. + කළා. + අසාර්ථකයි :( + වාදන ලැයිස්තුව මකන්න + වාදන ලැයිස්තුව සාදන්න + ගැන + භාෂාව + පද්ධතිය + පද්ධතිය + එළිය + අඳුරු + %1$s දායක වන්නන් + සැකසුම් + ස්ථානය + සේවාදායකය + ගැලපීම් + වෙබ් අඩවිය + %1$s වීඩියෝ + මුලින්ම අන්තර්ජාලයට සම්බන්ධ වෙන්න. + නැවත උත්සාහ කරන්න + අදහස් + සෙවුම් පෙරහන තෝරන්න + නාලිකා + සියලුම + හරි + සෙවුම් ඉතිහාසය + ඉතිහාසය හිස් කරන්න + YT Music ගීත + YT Music වීඩියෝ + YT Music ඇල්බම + පෙරනිමි පිම්ම + කොටස මඟ හැරිය + සක්‍රිය + අනුග්‍රාහකයා + නොගෙවූ/ස්වයං ප්‍රවර්ධන + අන්තර්ක්‍රියා මතක් කිරීම (කැමති සහ දායක වන්න) + විරාම/හඳුන්වාදීමේ සජීවිකරණය + අවසන් කාඩ්පත් සහ දායක ලැයිස්තුව + අවසානයට පසුව තොරතුරු. තොරතුරු සහිත නිගමන සඳහා නොවේ. + අදාළ නොවන කොටස්/විහිළු + SponsorBlock + වාදන ලැයිස්තු + YT Music වාදන ලැයිස්තු + නොගෙවූ හෝ ස්වයං ප්‍රවර්ධනය හැර \"අනුග්‍රාහකයා\" හා සමානයි. මෙයට වෙළඳ භාණ්ඩ, පරිත්‍යාග, හෝ ඔවුන් සහයෝගීව කටයුතු කළ අය පිළිබඳ තොරතුරු පිළිබඳ කොටස් ඇතුළත් වේ. + පෙරදසුන/සාරාංශය + බලපත්රය + Material You + දැනුම්දීම් + නිරූපකය + සක්‍රිය + අක්‍රිය + Piped + YouTube + නිකුතු අංකය %1$s ඇත + එය බාගත කිරීමට GitHub හි නිකුතු වෙත යන්නද\? + පෙනුම + බාගත කිරීම් + වීඩියෝ ආකෘතිය + බාගත කරන ස්ථානය + බාගත කළ මාධ්‍ය ගබඩා කරන තැන. + දායක වන්න + නව අනුවාදයක් සොයන්න + යාවත්කාලීන කිරීමට ඹබන්න + නවතම අනුවාදය ධාවනය කරමින් සිටියි. + උසස් + වාදකය + ඔබගේ අභිමතය පරිදි යෙදුම සකසන්න. + බාගැනීම්, සහ යළි පිහිටුවන්න + සජීවි + කතුවරුන් + බාගත කළ මාධ්‍ය ගබඩා කර ඇති ෆෝල්ඩරයේ නම. + අභ්යන්තර ගබඩාව + ෆෝල්ඩරය බාගත කරන්න + SD කාඩ් + URL එක බෙදාගන්න + බැලීම් + %1$s බැලීම් + පෙරනිමිය + අවධාරණ + කහ පාට + කොළ පාට + දම් පාට + කළු පාට + නිල් පාට + රතු පාට + වාදන වේගය + විලාසිතාමය ගින්න + නවීන පන්දම + පියාඹන දැල්ල + Piped, පුරනය සහ දායකත්ව + සේවාදායකයේ නම + සේවාදායක API වෙත URL + සේවාදායකයක් එකතු කරන්න + එකතු කිරීම් මකන්න + අනුවාදය %1$s + LibreTube කණ්ඩායම සහ ඒ සියල්ල සිදුවන්නේ කෙසේදැයි දැන ගන්න. + අදාළ අන්තර්ගත + පරිච්ඡේද පෙන්වන්න + පරිච්ඡේද සඟවන්න + Glib ශ්‍රේණියේ වර්ණය + පියාඹන කුරුල්ලා + පූර්ව ප්‍රෙව්ශය වෙමින් + වාදකය සඳහා වීඩියෝ ආකෘතිය + ශ්‍රව්‍ය නැත + උපසිරැසි නැත + ශ්‍රව්‍ය + බාගත වෙමින්… + බාගත කිරීම නවතා ඇත + උපරිම සමකාලීන බාගත කිරීම් + උපරිම සමකාලීන බාගත කිරීම් සීමාව ළඟා විය. + නවත්වන්න + අරඹන්න + නැගී එන පිටුව සඟවන්න + සේවාදායක ඉදිරිපස URL + ගුණත්වය + පෙරනිමි සහ හැසිරීම + වර්ධක අන්වේෂණය කරන්න + ස්වයංක්‍රීය වාදනය + පෙරනිමි ප්‍රත්‍යර්පණය කරන්න + ගිණුම මකන්න + ඔබගේ Piped ගිණුම මකන්න + ගිණුම + ප්‍රත්‍යර්පණය කරන්න + නැරඹුම් ඉතිහාසය + සත්‍යතාව තහවුරු කිරීමේ සේවාදායකය + සත්‍යතාව තහවුරු කිරීමට සේවාදායකයක් තෝරන්න + HLS + GitHub + ශ්රව්ය සහ වීඩියෝ + සම්පූර්ණ තිර නැඹුරුව + භූ දර්ශනය + ප්‍රජාව + Discord + Matrix + Telegram + Reddit + Twitter + කරුණාකර අන්තර්ජාලයට සම්බන්ධ වීමට Wi-Fi හෝ ජංගම දත්ත ක්‍රියාත්මක කරන්න. + විවෘත කරන්න… + පරිච්ඡේද + යෙදුම නැවත පටන් ගැනීම අවශ්‍යයි + ලේබල් දෘශ්‍යතාව + තෝරා ගන්නා ලදී + කවදාවත් නැහැ + ස්වයං-පූර්ණ තිරය + තනි පෙනුම + තනි සුදු/කළු පෙනුම + දත්ත සුරැකීමේ ප්‍රකාරය + සිඟිති රූ සහ අනෙකුත් පින්තූර මඟ හරින්න. + නැරඹූ වීඩියෝ දේශීයව මතක තබා ගන්න + නැරඹුම් සහ සෙවුම් ඉතිහාසය + ප්‍රත්‍යාරම්භ කරන්න + වාදන වේගය + උපාංගය හැරවූ විට සම්පූර්ණ තිර වාදනය. + මතක වාදන ස්ථාන + නව LibreTube අනුවාදය දැන් පිහිටු වන්නද\? + භාෂාව සහ ප්‍රදේශය + සිරස්තල + වාදකය සඳහා ශ්‍රව්‍ය ආකෘතිය + ශ්‍රව්‍ය ගුණත්වය + විශිෂ්ට + නරකම + නව ප්‍රවාහ සඳහා දැනුම්දීම් + බලන වාර ගණන… + %1$s නව ප්‍රවාහ තිබේ + %1$s විසින් නව ප්‍රවාහ… + ඔබට විශ්වාසද\? මෙය පසුගමනය කළ නොහැක! + අලුත්ම + පැරණිම + බොහෝ බැලීම් + අඩුම බැලීම් + නාලිකාවේ නම (A-Z) + නාලිකාවේ නම (Z-A) + තේරීම + සියලුම + සීමිත + Wi-Fi මත පමණි + පරිවර්තනය + ප්‍රතිපල නැත. + දෝෂයකි + පිටපත් කර ඇත + කාල කේතය සමඟ බෙදා ගන්න + දායකත්වයන් අපනයනය කරන්න + ඊළඟ හෝ පෙර වීඩියෝවට යාමට බොත්තම් පෙන්වන්න. + උපරිම ඉතිහාස ප්‍රමාණය + පසුබිම් ප්‍රකාරය + වෙනත් + විවේක මතක් කිරීම + විවේකයක් ගැනීමට කාලයයි + කෙටි වීඩියෝ + උපසිරැසි නොමැත + නැවත ධාවනය කිරීම් ප්‍රකාරය + සුදුසු + පුරවන්න + පසුබිමේ වාදනය වෙමින්… + දැන් + උපස්ථ සහ ප්‍රත‍්‍යර්පණ කිරීම + උපස්ථ කිරීම + පින්තූරයේ පින්තූරය + උපරිම පින්තූර නිහිත ප්‍රමාණය + විවෘත කරන්න + මතක් කිරීමට පෙර මිනිත්තු ගණන + උපාංග තොරතුරු + ගුණත්වය සහ ආකෘතිය + බාගත කිරීම් වලින් මකන්න + විකල්ප නැගී එන පිරිසැලසුම + Wi-Fi + ජංගම දත්ත + අලුත් වීඩියෝ තිබේ නම් ප්‍රමාණය සමඟ ලාංඡනයක් පෙන්වන්න. + කොටස මඟ හරින්න + අතින් මඟ හරින්න + දේශීයව ගබඩා කර ඇති දායකත්වයන් + සැකසුම් + වෙනත් සේවාදායකයක් + පසුබිමේ නවතම වීඩියෝ පූරණය කරන්න + මං සෙවුම් තීරුව + කරුණාකර අවම වශයෙන් එක් අයිතමයක් තෝරන්න + ප්‍රගතිශීලීව ප්‍රවේශනය වීමේ විරාම ප්‍රමාණය + අඩු අගයක් මුල් වීඩියෝ ප්‍රවේශනය වේගවත් කළ හැක. + ස්වරය + ගොනු නාමය + වලංගු නොවන ගොනු නාමයකි! + මෑතකදී යාවත්කාලීන කරන ලද + මෑතකදී යාවත්කාලීන කරන ලද (ප්‍රතිලෝම) + තව පෙන්වන්න + ඊළඟ වීඩියෝව වාදනය කරන්න + වාදන ලැයිස්තුවට එක් කරන ලදී + පෝලිම + සජීවී ප්‍රවාහ + විකල්ප වීඩියෝ පිරිසැලසුම + පෙරනිමි එළිය + ඔබට %1$s ගෙ දායකත්වයෙන් ඉවත් වීමට අවශ්‍ය බව විශ්වාසද\? + දායකත්වයෙන් ඉවත් වීම තහවුරු කරන්න + කාලය + දැනුම්දීමේ කාලය + දැනුම්දීම් පෙන්වීමට අවසර දී ඇති කාල පරාසය. + විකල්ප නැගී එන පිරිසැලසුම + පිළිවෙල + පිරිසැලසුම + ශ්‍රව්‍ය පථය + පෙරනිමිය + සහාය නොදක්වන ගොනු ආකෘතියකි! + HLS භාවිතා කරන්න + ස්වයං + ධාවන කාලයට සීමා කරන්න + දැනුම්දීමෙන් පෝලිම විවෘත කරන්න + ප්‍රවණතා + විශේෂාංගගත + දැන් නැගී එන්නේ කුමක්ද + පොත් සලකුණු + පොත් සලකුණු හිස් කරන්න + තවමත් පොත් සලකුණු නොමැත! + කරුණාකර පළමුව වෙනත් ආරම්භක පිම්මක් තෝරන්න! + දීප්තිය + ශබ්ද හඩ + ස්වයං + ස්වයිප් පාලන + දීප්තිය සහ ශබ්ද හඩ සීරුමාරු කිරීමට ස්වයිප් අභිනය භාවිත කරන්න. + කෙනිත්තීම අභිනය පාලනය + විශාලනය කිරීමට/පිටතට කිරීමට කෙනිත්තීම අභිනය භාවිත කරන්න. + පෙරනිමි + උත්පතන + අවම ඒකවර්ණ + සිරස්තල ප්‍රමාණය + සියල්ල වාදනය කරන්න + ඔබ නව වීඩියෝ සියල්ලම දැක ඇත + යෙදුම් උපස්ථ + අපනයනය කරන ලදී. + ඇවිරීම් ඇඟවීම + නිර්දේශ නොකළ විද්‍යුත් තැපැල් ලිපිනයක් සමඟ ඉදිරියට යන්නද\? + ඉදිරියට යන්න + නවතම වීඩියෝ වාදනය කරන්න + කිසිවක් තෝරා නැත! + ජම්බූල පාට + වාදන ලැයිස්තු ආනයනය කරන්න + වාදන ලැයිස්තු URL + ශ්‍රව්‍ය වාදකය + LibreTube සංගීත වාදකයක් බවට පත් කරන්න. + දායකත්ව පිම්මෙහි 90%කට වඩා නරඹන වීඩියෝ නොපෙන්වන්න. + ඉවත් වීමේදී නවත්වන්න + කලවම් කරන්න + පොත් සලකුණු වලට එකතු කරන්න + ආපස්සට යන්න + ඉදිරියට යන්න + විකල්ප PiP පාලන + ශ්‍රව්‍ය පමණක් ප්‍රකාරය + මාධ්‍ය බාගත කිරීමේදී දැනුම්දීමක් පෙන්වයි. + පසුබිම් ප්‍රකාරය + නව ප්‍රවාහ පවතින විට දැනුම්දීමක් පෙන්වයි. + ඹබ සියල්ල බලා ඇත + මුල් + මුරපදය + දායකත්ව + දායක නොවන්න + පුරනය වී ඇත. + ලියාපදිංචි. දැන් ඔබට නාලිකා වලට දායක විය හැක. + තෝරන්න… + පුරනය වන්න / ලියාපදිංචි වන්න + මුලින්ම නාලිකා කිහිපයකට දායක වෙන්න. + තවත් බාගත කිරීමක් දැනටමත් සිදු වෙමින් පවතී, කරුණාකර එය අවසන් වන තෙක් රැඳී සිටින්න. + VLC හි විවෘත කළ නොහැක. එය පිහිටුවා නැති විය හැකිය. + ඔබ පරිශීලක නාමයක් සහ මුරපදයක් ඇතුළත් කළ යුතුය. + සේවාදායකයේ ගැටලුවක් තිබේ. වෙනත් සේවාදායකයක් උත්සාහ කරන්නද\? + මෙය Piped ගිණුමක් සඳහා ය. + වීඩියෝ විභේදනය + වාදන ලැයිස්තුවේ නම + ඉතිහාසය + https://sponsor.ajay.app API භාවිත කරයි + කොටස් + අතරතුර කැමති වීමට, දායක වීමට හෝ අනුගමනය කිරීමට කෙටි මතක් කිරීමක් ඇති විට. දිගු හෝ විශේෂිත දෙයක් ගැන නම්, ඒ වෙනුවට එය ස්වයං ප්‍රවර්ධනයකි. + සැබෑ අන්තර්ගතයක් නොමැති විරාමයක්. නැවතීමක්, ස්ථිතික රාමුවක්, පුනරාවර්තන සජීවිකරණයක් විය හැකිය. තොරතුරු අඩංගු සංක්‍රාන්ති සඳහා භාවිතා නොකළ යුතුය. + සංගීත වීඩියෝවල භාවිතය සඳහා පමණි. එය නිල මිශ්‍රණවල කොටසක් නොව වීඩියෝවේ කොටස් ආවරණය කළ යුතුය. අවසානයේදී, වීඩියෝව Spotify හෝ වෙනත් ඕනෑම මිශ්‍ර අනුවාදයක් හැකිතාක් සමීපව සමාන විය යුතුය, නැතහොත් කතා කිරීම හෝ වෙනත් අවධානය වෙනතකට යොමු කිරීම අඩු කළ යුතුය. + වීඩියෝවේ ප්‍රධාන අන්තර්ගතය තේරුම් ගැනීමට අවශ්‍ය නොවන ෆිලර් හෝ හාස්‍යය සඳහා පමණක් එක් කළ කොටස් සඳහා. + ගීත: ගීතය නොවන කොටස + හැසිරීම + අහිමි වූ උරුමය + මෝඩ හැඩැති + එකතු කරන්න… + නම සහ API URL එක පුරවන්න. + පසුබිමේ වාදනය කරන්න + ශ්‍රව්‍ය සහ දෘශ්‍ය යන දෙකම බාගත කර ඇත්නම් ගොනු පරිවර්තනය කිරීම. + ඔබ නවතම අනුවාදය ධාවනය කරමින් සිටියි. + මෙම අදහසට පිළිතුරු නොමැත. + සංගීත ෆෝල්ඩරය + පරිත්‍යාග කරන්න + නම + චිත්‍රපට ෆෝල්ඩරය + කරුණාකර වැඩ කරන URL එකක් ඇතුළු කරන්න + ඔබ නරඹන දේ හා සමාන ප්‍රවාහ පෙන්වන්න. + සලකුණු + වීඩියෝ + වීඩියෝව බෆර කිරීමට දෙන උපරිම තත්පර ගණන. + වීඩියෝ නැත + බාගත කිරීම සම්පූර්ණයි + නොදන්නා + හැසිරීම + ස්වයං නැවැත්වීම + වාදන ලැයිස්තුව ක්ලෝනය කරන්න + වත්මන් වීඩියෝවෙන් පසුව ඊළඟ වීඩියෝව ස්වයංක්‍රීයව වාදනය කරන්න. + සියලු සැකසුම් යළි සකසා වරනය වන්නද\? + නව වෙනස්කම් භාවිතා කිරීමට යෙදුම නැවත පටන් ගන්න. + අවසාන වාදන ස්ථානයෙන් ඉදිරියට යන්න + ස්ථානය මතක තබා ගන්න + සත්‍යතාව තහවුරු කිරීම සඳහා වෙනත් සේවාදායකයක් භාවිතා කරන්න. + වීඩියෝ දර්ශන අනුපාතය + ස්වයංක්‍රීය භ්‍රමණය + සිරස් + සැමවිටම + අසීමිත + බාහිර වාදකයක් හමු නොවීය. කරුණාකර ඔබ එකක් පිහිටුවා ඇති බවට වග බලා ගන්න. + වීඩියෝ පෙරදසුන + පොදු + සෙවුම් මතක තබා ගන්න + සිරස්තල + කිසිවක් නැත + පද්ධති සිරස්තල විලාසය + APK බාගත කරමින්… + දැනුම්දීම් + උපසිරැසි භාෂාව + ඔබ අනුගමනය කරන නිර්මාණකරුවන්ගෙන් නැවුම් අන්තර්ගත පිළිබඳ දැනුම්දීම්. + තවමත් ඉතිහාසයක් නැත. + ඔබ දැනටමත් යෙදුම තුළ මිනිත්තු %1$s ගත කර ඇත, විවේකයක් ගැනීමට කාලයයි. + සම්බන්ධතාවයක් අවශ්‍ය + බාගත කිරීම සාර්ථක විය + මඟ හරින බොත්තම් + නව වීඩියෝ සඳහා දර්ශකය + නව දායකත්ව වීඩියෝ පසුබිමේ පූරණය කර එය ස්වයංක්‍රීයව නැවුම් වීම වළක්වන්න. + විශාලනය කරන්න + කිසිවක් නැත + පෝලිමට එකතු කරන්න + වත්මන් ප්‍රදේශය සඳහා නැගී එන වීඩියෝ නොමැති බව පෙනේ. කරුණාකර සැකසීම් තුළ වෙනත් එකක් තෝරන්න. + ප්‍රමාණය වෙනස් කිරීමේ ප්‍රකාරය + පසුරු පුවරුවට පිටපත් කර ඇත + HLS 1080p දක්වා සීමා කරන්න + උරුම දායකත්ව දසුන + වාදන ලැයිස්තුව නැවත නම් කරන්න + කොටස් ස්වයංක්‍රීයව මඟ නොහරින්න, සෑම විටම පෙර විමසන්න. + පෙරනිමිය + වාදන ලැයිස්තු අනුපිළිවෙල + කාල කේතය (තත්පර) + කාල තීරුවේ කොටස් සලකුණු කරන්න. + වාදනය කරන පෝලිම + දායකත්වයෙන් ඉවත් වීමට පෙර තහවුරු කිරීමේ සංවාදයක් පෙන්වන්න. + වාදන ලැයිස්තුව ක්ලෝන කරන ලදී + විකල්ප වාදක පිරිසැලසුම + අවසන් කාලය + ආරම්භක කාලය + අදාළ වීඩියෝ පහතින් වෙනුවට අදහස්වලට ඉහළින් පේළියක් ලෙස පෙන්වන්න. + DASH වෙනුවට HLS භාවිතා කරන්න (මන්දගාමී වනු ඇත, නිර්දේශ නොකරයි) + පොත් සලකුණ + මෙනු අයිතමය සබල කර නැත! + දේශීය වාදන ලැයිස්තු + අදාළ වීඩියෝ ඇතුළු කරන්න + මෙම වීඩියෝවට අදහස් නොමැත. + උඩුගත කරන්නා විසින් අදහස් අබල කර ඇත. + අන්වේෂණයට දෙවරක් තට්ටු කරන්න + වාදකයේ ස්ථානය රිවයින්ඩ් කිරීමට හෝ ඉදිරියට යාමට වමේ හෝ දකුණේ දෙවරක් තට්ටු කරන්න. + වාදන ලැයිස්තු අපනයනය කරන්න + දායකත්වයන්, වාදන ලැයිස්තු,… ආනයනය සහ අපනයනය කරන්න + පවතින සේවාදායකයන් ලබා ගැනීමට නොහැකි විය. + නවතම කොටසෙහි නැරඹූ වීඩියෝ සඟවන්න + මෙම වාදන ලැයිස්තුව මකන්නද\? + වාදන ලැයිස්තුවේ නම හිස් විය නොහැක + තිරය ක්‍රියාවිරහිත වූ විට වාදනය නවත්වන්න. + වාදන දර්ශකය ඇදගෙන යන විට සැණරුවක් පෙන්වන්න. + වාදන ලැයිස්තුවේ නම (ප්‍රතිලෝම) + වාදන ලැයිස්තුව සාදන ලදී. + වාදන ලැයිස්තුවට එක් කරන්න + ශ්‍රව්‍ය ධාවකය පාලනය කිරීමට බොත්තම් සහිත දැනුම්දීමක් පෙන්වයි. + පොත් සලකුණ ඉවත් කරන්න + බාගත කිරීමේ සේවාව + දැනුම්දීම් සේවකයා + ගෙවුම් ප්‍රවර්ධනය, ගෙවුම් යොමු කිරීම් සහ සෘජු දැන්වීම්. ස්වයං ප්‍රවර්ධනය හෝ නොමිලේ නිර්මාණකරුවන්, වෙබ් අඩවි සහ නිෂ්පාදන සඳහා සත්‍ය ප්‍රචාරක කටයුතු, සඳහා නොවේ. + මෙම හෝ එහි මාලාවේ අනාගත වීඩියෝවල ඉදිරියට එන අන්තර්ගතය විස්තර කරන කොටස් සඳහා, නමුත් අමතර තොරතුරු ලබා නොදේ. මෙහි පමණක් පෙනෙන ක්ලිප් ඇතුළත් නම්, මෙය බොහෝ දුරට වැරදි කාණ්ඩයකි. + ඉදිරියට සහ පසුපසට යැවීම වෙනුවට PiP හි ශබ්ද පමණක් සහ මඟහරින පාලක පෙන්වන්න + \ No newline at end of file From fe6506179c4592c79bcfd16cabd0b9e74dbdaa6d Mon Sep 17 00:00:00 2001 From: Bnyro Date: Tue, 17 Jan 2023 18:38:39 +0100 Subject: [PATCH 46/50] Ability to skip silence when playing videos --- .../libretube/constants/PreferenceKeys.kt | 1 + .../libretube/ui/sheets/PlaybackSpeedSheet.kt | 14 +++++++++-- .../libretube/ui/views/CustomExoPlayerView.kt | 10 +++++++- .../main/res/layout/playback_bottom_sheet.xml | 23 +++++++++++++++++++ app/src/main/res/values/strings.xml | 1 + 5 files changed, 46 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt b/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt index f460c9f94..486a858d7 100644 --- a/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt +++ b/app/src/main/java/com/github/libretube/constants/PreferenceKeys.kt @@ -88,6 +88,7 @@ object PreferenceKeys { const val DOUBLE_TAP_TO_SEEK = "double_tap_seek" const val PAUSE_ON_QUIT = "pause_on_quit" const val ALTERNATIVE_PIP_CONTROLS = "alternative_pip_controls" + const val SKIP_SILENCE = "skip_silence" /** * Background mode diff --git a/app/src/main/java/com/github/libretube/ui/sheets/PlaybackSpeedSheet.kt b/app/src/main/java/com/github/libretube/ui/sheets/PlaybackSpeedSheet.kt index dc0d670b3..4bf141c9e 100644 --- a/app/src/main/java/com/github/libretube/ui/sheets/PlaybackSpeedSheet.kt +++ b/app/src/main/java/com/github/libretube/ui/sheets/PlaybackSpeedSheet.kt @@ -4,13 +4,15 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import com.github.libretube.constants.PreferenceKeys import com.github.libretube.databinding.PlaybackBottomSheetBinding import com.github.libretube.extensions.round +import com.github.libretube.util.PreferenceHelper +import com.google.android.exoplayer2.ExoPlayer import com.google.android.exoplayer2.PlaybackParameters -import com.google.android.exoplayer2.Player class PlaybackSpeedSheet( - private val player: Player + private val player: ExoPlayer ) : ExpandedBottomSheet() { private lateinit var binding: PlaybackBottomSheetBinding @@ -28,6 +30,9 @@ class PlaybackSpeedSheet( binding.speed.value = player.playbackParameters.speed binding.pitch.value = player.playbackParameters.pitch + PreferenceHelper.getBoolean(PreferenceKeys.SKIP_SILENCE, false).let { + binding.skipSilence.isChecked = it + } binding.speed.addOnChangeListener { _, _, _ -> onChange() @@ -46,6 +51,11 @@ class PlaybackSpeedSheet( binding.pitch.value = 1f onChange() } + + binding.skipSilence.setOnCheckedChangeListener { _, isChecked -> + player.skipSilenceEnabled = isChecked + PreferenceHelper.putBoolean(PreferenceKeys.SKIP_SILENCE, isChecked) + } } private fun onChange() { diff --git a/app/src/main/java/com/github/libretube/ui/views/CustomExoPlayerView.kt b/app/src/main/java/com/github/libretube/ui/views/CustomExoPlayerView.kt index 05f9a1bd8..0ab60b343 100644 --- a/app/src/main/java/com/github/libretube/ui/views/CustomExoPlayerView.kt +++ b/app/src/main/java/com/github/libretube/ui/views/CustomExoPlayerView.kt @@ -15,6 +15,7 @@ import android.widget.ImageView import android.widget.TextView import androidx.core.content.ContextCompat import com.github.libretube.R +import com.github.libretube.constants.PreferenceKeys import com.github.libretube.databinding.DoubleTapOverlayBinding import com.github.libretube.databinding.ExoStyledPlayerControlViewBinding import com.github.libretube.databinding.PlayerGestureControlsViewBinding @@ -33,6 +34,8 @@ import com.github.libretube.util.BrightnessHelper import com.github.libretube.util.PlayerGestureController import com.github.libretube.util.PlayerHelper import com.github.libretube.util.PlayingQueue +import com.github.libretube.util.PreferenceHelper +import com.google.android.exoplayer2.ExoPlayer import com.google.android.exoplayer2.PlaybackParameters import com.google.android.exoplayer2.Player import com.google.android.exoplayer2.trackselection.TrackSelector @@ -111,6 +114,9 @@ internal class CustomExoPlayerView( PlayerHelper.playbackSpeed.toFloat(), 1.0f ) + PreferenceHelper.getBoolean(PreferenceKeys.SKIP_SILENCE, false).let { + (player as ExoPlayer).skipSilenceEnabled = true + } playbackPrefSet = true } @@ -484,7 +490,9 @@ internal class CustomExoPlayerView( } override fun onPlaybackSpeedClicked() { - player?.let { PlaybackSpeedSheet(it).show(supportFragmentManager) } + player?.let { + PlaybackSpeedSheet(it as ExoPlayer).show(supportFragmentManager) + } } override fun onResizeModeClicked() { diff --git a/app/src/main/res/layout/playback_bottom_sheet.xml b/app/src/main/res/layout/playback_bottom_sheet.xml index ab34782c3..b99366ce8 100644 --- a/app/src/main/res/layout/playback_bottom_sheet.xml +++ b/app/src/main/res/layout/playback_bottom_sheet.xml @@ -92,6 +92,29 @@ + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2146b817b..f97725a59 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -441,6 +441,7 @@ Audio only mode Turn LibreTube into a music player. Sleep timer + Skip silence Download Service From 26e2c38f60b8d801326b44075ea47694efcfa730 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Tue, 17 Jan 2023 19:05:22 +0100 Subject: [PATCH 47/50] Create shortcuts dynamically --- app/src/main/AndroidManifest.xml | 27 ---------- .../java/com/github/libretube/LibreTubeApp.kt | 6 +++ .../github/libretube/constants/IntentData.kt | 1 + .../com/github/libretube/obj/AppShortcut.kt | 10 ++++ .../github/libretube/util/ShortcutHelper.kt | 45 ++++++++++++++++ app/src/main/res/xml/shortcuts.xml | 53 ------------------- 6 files changed, 62 insertions(+), 80 deletions(-) create mode 100644 app/src/main/java/com/github/libretube/obj/AppShortcut.kt create mode 100644 app/src/main/java/com/github/libretube/util/ShortcutHelper.kt delete mode 100644 app/src/main/res/xml/shortcuts.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 279de389d..0843a522c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -82,9 +82,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 8fe7bda851f743004e2c8579bbaef288f9684fd7 Mon Sep 17 00:00:00 2001 From: Yaron Shahrabani Date: Tue, 17 Jan 2023 17:24:45 +0000 Subject: [PATCH 48/50] Translated using Weblate (Hebrew) Currently translated at 100.0% (447 of 447 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/he/ --- app/src/main/res/values-iw/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 3e7afee8b..99c367f59 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -446,4 +446,5 @@ המשך מצב שמע בלבד הפיכת LibreTube לנגן מוזיקה. + מתזמן שינה \ No newline at end of file From 4191b5eadaa8c5b86082b75cb67c322e4f41c0ba Mon Sep 17 00:00:00 2001 From: Ricardo Date: Tue, 17 Jan 2023 17:56:06 +0000 Subject: [PATCH 49/50] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (448 of 448 strings) Translation: LibreTube/LibreTube Translate-URL: https://hosted.weblate.org/projects/libretube/libretube/pt_BR/ --- app/src/main/res/values-pt-rBR/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 0692385ef..035698ccc 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -446,4 +446,6 @@ Retomar Transforme o LibreTube em um reprodutor de música. Modo somente áudio + Temporizador + Pular silêncio \ No newline at end of file From 1433578cb02589cedb11e7bfc6843213212eacfa Mon Sep 17 00:00:00 2001 From: Bnyro Date: Tue, 17 Jan 2023 19:19:42 +0100 Subject: [PATCH 50/50] Use a dark blue color for app shortcuts instead of black --- app/src/main/res/drawable/ic_home.xml | 2 +- app/src/main/res/drawable/ic_library.xml | 2 +- app/src/main/res/drawable/ic_subscriptions.xml | 2 +- app/src/main/res/drawable/ic_trending.xml | 3 ++- app/src/main/res/values/colors.xml | 1 + 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/src/main/res/drawable/ic_home.xml b/app/src/main/res/drawable/ic_home.xml index 20c5ae8c5..68e02a616 100644 --- a/app/src/main/res/drawable/ic_home.xml +++ b/app/src/main/res/drawable/ic_home.xml @@ -6,6 +6,6 @@ android:viewportHeight="48"> diff --git a/app/src/main/res/drawable/ic_library.xml b/app/src/main/res/drawable/ic_library.xml index e623e5d3c..8588f8bb2 100644 --- a/app/src/main/res/drawable/ic_library.xml +++ b/app/src/main/res/drawable/ic_library.xml @@ -6,6 +6,6 @@ android:viewportHeight="48"> diff --git a/app/src/main/res/drawable/ic_subscriptions.xml b/app/src/main/res/drawable/ic_subscriptions.xml index 10574772e..72d819812 100644 --- a/app/src/main/res/drawable/ic_subscriptions.xml +++ b/app/src/main/res/drawable/ic_subscriptions.xml @@ -6,6 +6,6 @@ android:viewportHeight="48"> diff --git a/app/src/main/res/drawable/ic_trending.xml b/app/src/main/res/drawable/ic_trending.xml index 233823167..b69f9c14c 100644 --- a/app/src/main/res/drawable/ic_trending.xml +++ b/app/src/main/res/drawable/ic_trending.xml @@ -4,7 +4,8 @@ android:tint="?attr/colorControlNormal" android:viewportWidth="52" android:viewportHeight="52"> + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index dc758a619..4886b7498 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -2,6 +2,7 @@ #AA000000 #EEFFFFFF + #0061A6 #0058CB #FFFFFF