diff --git a/.github/downloads.jpg b/.github/downloads.jpg new file mode 100644 index 00000000..ca14a664 Binary files /dev/null and b/.github/downloads.jpg differ diff --git a/.github/home.jpg b/.github/home.jpg new file mode 100644 index 00000000..72370d3c Binary files /dev/null and b/.github/home.jpg differ diff --git a/.github/locales.py b/.github/locales.py index 7d6d6b90..1c79c093 100644 --- a/.github/locales.py +++ b/.github/locales.py @@ -1,7 +1,6 @@ import re import glob import requests -import lxml.etree as ET # builtin library doesn't preserve comments SETTINGS_PATH = "app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt" @@ -46,18 +45,4 @@ open(SETTINGS_PATH, "w+",encoding='utf-8').write( "\n" + END_MARKER + after_src -) - -# Go through each values.xml file and fix escaped \@string -for file in glob.glob(f"{XML_NAME}*/strings.xml"): - try: - tree = ET.parse(file) - for child in tree.getroot(): - if child.text.startswith("\\@string/"): - print(f"[{file}] fixing {child.attrib['name']}") - child.text = child.text.replace("\\@string/", "@string/") - with open(file, 'wb') as fp: - fp.write(b'\n') - tree.write(fp, encoding="utf-8", method="xml", pretty_print=True, xml_declaration=False) - except ET.ParseError as ex: - print(f"[{file}] {ex}") +) \ No newline at end of file diff --git a/.github/player.jpg b/.github/player.jpg new file mode 100644 index 00000000..f6959cf3 Binary files /dev/null and b/.github/player.jpg differ diff --git a/.github/results.jpg b/.github/results.jpg new file mode 100644 index 00000000..4dbc9b8d Binary files /dev/null and b/.github/results.jpg differ diff --git a/.github/search.jpg b/.github/search.jpg new file mode 100644 index 00000000..784bec89 Binary files /dev/null and b/.github/search.jpg differ diff --git a/.github/workflows/update_locales.yml b/.github/workflows/update_locales.yml index 628e9bc9..93cdca44 100644 --- a/.github/workflows/update_locales.yml +++ b/.github/workflows/update_locales.yml @@ -1,4 +1,4 @@ -name: Fix locale issues +name: Update locale lists on: workflow_dispatch: @@ -9,7 +9,7 @@ on: - master concurrency: - group: "locale" + group: "locale-list" cancel-in-progress: true jobs: @@ -26,9 +26,6 @@ jobs: - uses: actions/checkout@v2 with: token: ${{ steps.generate_token.outputs.token }} - - name: Install dependencies - run: | - pip3 install lxml - name: Edit files run: | python3 .github/locales.py @@ -38,5 +35,5 @@ jobs: git config --local user.name "recloudstream[bot]" git add . # "echo" returns true so the build succeeds, even if no changed files - git commit -m 'chore(locales): fix locale issues' || echo + git commit -m 'update list of locales' || echo git push diff --git a/README.md b/README.md index e3d033ba..3430d626 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,12 @@ + Download and stream movies, tv-shows and anime + Chromecast +### Screenshots: + + + + ### Supported languages: Translation status - + \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0bd56fe7..9cbccbe5 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -159,8 +159,6 @@ dependencies { implementation("com.google.android.exoplayer:extension-cast:2.18.2") implementation("com.google.android.exoplayer:extension-mediasession:2.18.2") implementation("com.google.android.exoplayer:extension-okhttp:2.18.2") - // Use the Jellyfin ffmpeg extension for easy ffmpeg audio decoding in exoplayer. Thank you Jellyfin <3 -// implementation("org.jellyfin.exoplayer:exoplayer-ffmpeg-extension:2.18.2+1") //implementation("com.google.android.exoplayer:extension-leanback:2.14.0") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 563c82f8..871c4f69 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -98,16 +98,6 @@ - - - - - - - - - - diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index d054f504..a7449255 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -5,8 +5,6 @@ import android.content.Context import android.content.Intent import android.content.res.ColorStateList import android.content.res.Configuration -import android.net.Uri -import android.os.Build import android.os.Bundle import android.util.AttributeSet import android.util.Log @@ -36,6 +34,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.navigationrail.NavigationRailView import com.google.android.material.snackbar.Snackbar import com.jaredrummler.android.colorpicker.ColorPickerDialogListener +import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.APIHolder.allProviders import com.lagradost.cloudstream3.APIHolder.apis import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings @@ -58,7 +57,6 @@ import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.OAuth2Apis import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.accountManagers import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appString -import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringPlayer import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringRepo import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringResumeWatching import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringSearch @@ -67,9 +65,6 @@ import com.lagradost.cloudstream3.ui.APIRepository import com.lagradost.cloudstream3.ui.WatchType import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO import com.lagradost.cloudstream3.ui.home.HomeViewModel -import com.lagradost.cloudstream3.ui.player.BasicLink -import com.lagradost.cloudstream3.ui.player.GeneratorPlayer -import com.lagradost.cloudstream3.ui.player.LinkGenerator import com.lagradost.cloudstream3.ui.result.ResultViewModel2 import com.lagradost.cloudstream3.ui.result.START_ACTION_RESUME_LATEST import com.lagradost.cloudstream3.ui.result.setImage @@ -175,12 +170,7 @@ open class ResultResume( val VLC = object : ResultResume( VLC_PACKAGE, - // Android 13 intent restrictions fucks up specifically launching the VLC player - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { - "org.videolan.vlc.player.result" - } else { - Intent.ACTION_VIEW - }, + "org.videolan.vlc.player.result", "extra_position", "extra_duration", ) { @@ -279,8 +269,6 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { isWebview: Boolean ): Boolean = with(activity) { - // TODO MUCH BETTER HANDLING - // Invalid URIs can crash fun safeURI(uri: String) = normalSafeApiCall { URI(uri) } @@ -336,20 +324,6 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { // It might be better to use the QuickSearch. nav_view?.selectedItemId = R.id.navigation_search nav_rail_view?.selectedItemId = R.id.navigation_search - } else if (safeURI(str)?.scheme == appStringPlayer) { - val uri = Uri.parse(str) - val name = uri.getQueryParameter("name") - val url = URLDecoder.decode(uri.authority, "UTF-8") - - navigate( - R.id.global_to_navigation_player, - GeneratorPlayer.newInstance( - LinkGenerator( - listOf(BasicLink(url, name)), - extract = true, - ) - ) - ) } else if (safeURI(str)?.scheme == appStringResumeWatching) { val id = str.substringAfter("$appStringResumeWatching://").toIntOrNull() @@ -759,16 +733,15 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { } else { this.setKey(getString(R.string.jsdelivr_proxy_key), true) val parentView: View = findViewById(android.R.id.content) - Snackbar.make(parentView, R.string.jsdelivr_enabled, Snackbar.LENGTH_LONG) - .let { snackbar -> - snackbar.setAction(R.string.revert) { - setKey(getString(R.string.jsdelivr_proxy_key), false) - } - snackbar.setBackgroundTint(colorFromAttribute(R.attr.primaryGrayBackground)) - snackbar.setTextColor(colorFromAttribute(R.attr.textColor)) - snackbar.setActionTextColor(colorFromAttribute(R.attr.colorPrimary)) - snackbar.show() + Snackbar.make(parentView, R.string.jsdelivr_enabled, Snackbar.LENGTH_LONG).let { snackbar -> + snackbar.setAction(R.string.revert) { + setKey(getString(R.string.jsdelivr_proxy_key), false) } + snackbar.setBackgroundTint(colorFromAttribute(R.attr.primaryGrayBackground)) + snackbar.setTextColor(colorFromAttribute(R.attr.textColor)) + snackbar.setActionTextColor(colorFromAttribute(R.attr.colorPrimary)) + snackbar.show() + } } } @@ -1150,10 +1123,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { suspend fun checkGithubConnectivity(): Boolean { return try { - app.get( - "https://raw.githubusercontent.com/recloudstream/.github/master/connectivitycheck", - timeout = 5 - ).text.trim() == "ok" + app.get("https://raw.githubusercontent.com/recloudstream/.github/master/connectivitycheck", timeout = 5).text.trim() == "ok" } catch (t: Throwable) { false } diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/StreamSB.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/StreamSB.kt index cac31328..b7477242 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/StreamSB.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/StreamSB.kt @@ -134,7 +134,7 @@ open class StreamSB : ExtractorApi() { it.value.replace(Regex("(embed-|/e/)"), "") }.first() // val master = "$mainUrl/sources48/6d6144797752744a454267617c7c${bytesToHex.lowercase()}7c7c4e61755a56456f34385243727c7c73747265616d7362/6b4a33767968506e4e71374f7c7c343837323439333133333462353935333633373836643638376337633462333634663539343137373761333635313533333835333763376333393636363133393635366136323733343435323332376137633763373337343732363536313664373336327c7c504d754478413835306633797c7c73747265616d7362" - val master = "$mainUrl/sources15/" + bytesToHex("||$id||||streamsb".toByteArray()) + "/" + val master = "$mainUrl/sources51/" + bytesToHex("||$id||||streamsb".toByteArray()) + "/" val headers = mapOf( "watchsb" to "sbstream", ) diff --git a/app/src/main/java/com/lagradost/cloudstream3/syncproviders/AccountManager.kt b/app/src/main/java/com/lagradost/cloudstream3/syncproviders/AccountManager.kt index 8ce6bae2..f17086c1 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/syncproviders/AccountManager.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/syncproviders/AccountManager.kt @@ -45,7 +45,6 @@ abstract class AccountManager(private val defIndex: Int) : AuthAPI { const val appString = "cloudstreamapp" const val appStringRepo = "cloudstreamrepo" - const val appStringPlayer = "cloudstreamplayer" // Instantly start the search given a query const val appStringSearch = "cloudstreamsearch" diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadFragment.kt index e80a8fa5..f0340845 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadFragment.kt @@ -24,6 +24,7 @@ import com.lagradost.cloudstream3.mvvm.observe import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick import com.lagradost.cloudstream3.ui.player.GeneratorPlayer import com.lagradost.cloudstream3.ui.player.LinkGenerator +import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings import com.lagradost.cloudstream3.utils.AppUtils.loadResult import com.lagradost.cloudstream3.utils.Coroutines.main import com.lagradost.cloudstream3.utils.DOWNLOAD_EPISODE_CACHE @@ -39,7 +40,6 @@ import kotlinx.android.synthetic.main.stream_input.* import android.text.format.Formatter.formatShortFileSize import androidx.core.widget.doOnTextChanged import com.lagradost.cloudstream3.mvvm.normalSafeApiCall -import com.lagradost.cloudstream3.ui.player.BasicLink import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings import java.net.URI @@ -225,7 +225,7 @@ class DownloadFragment : Fragment() { R.id.global_to_navigation_player, GeneratorPlayer.newInstance( LinkGenerator( - listOf(BasicLink(url)), + listOf(url), extract = true, referer = referer, isM3u8 = dialog.hls_switch?.isChecked diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapter.kt index 58c6dbe0..e6999c9e 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapter.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapter.kt @@ -185,7 +185,7 @@ open class ParentItemAdapter( ) : RecyclerView.ViewHolder(itemView) { val title: TextView = itemView.home_child_more_info - private val recyclerView: RecyclerView = itemView.home_child_recyclerview + val recyclerView: RecyclerView = itemView.home_child_recyclerview fun update(expand: HomeViewModel.ExpandableHomepageList) { val info = expand.list diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt index e0885671..782e3fa4 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt @@ -9,11 +9,8 @@ import android.widget.FrameLayout import androidx.preference.PreferenceManager import com.google.android.exoplayer2.* import com.google.android.exoplayer2.C.* -import com.google.android.exoplayer2.DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON -import com.google.android.exoplayer2.DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER import com.google.android.exoplayer2.database.StandaloneDatabaseProvider import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSource -import com.google.android.exoplayer2.mediacodec.MediaCodecSelector import com.google.android.exoplayer2.source.* import com.google.android.exoplayer2.text.TextRenderer import com.google.android.exoplayer2.trackselection.DefaultTrackSelector @@ -541,8 +538,7 @@ class CS3IPlayer : IPlayer { } // Do no include empty referer, if the provider wants those they can use the header map. - val refererMap = - if (link.referer.isBlank()) emptyMap() else mapOf("referer" to link.referer) + val refererMap = if (link.referer.isBlank()) emptyMap() else mapOf("referer" to link.referer) val headers = mapOf( "accept" to "*/*", "sec-ch-ua" to "\"Chromium\";v=\"91\", \" Not;A Brand\";v=\"99\"", @@ -673,27 +669,23 @@ class CS3IPlayer : IPlayer { val exoPlayerBuilder = ExoPlayer.Builder(context) .setRenderersFactory { eventHandler, videoRendererEventListener, audioRendererEventListener, textRendererOutput, metadataRendererOutput -> - DefaultRenderersFactory(context).apply { -// setEnableDecoderFallback(true) - // Enable Ffmpeg extension -// setExtensionRendererMode(EXTENSION_RENDERER_MODE_ON) - }.createRenderers( - eventHandler, - videoRendererEventListener, - audioRendererEventListener, - textRendererOutput, - metadataRendererOutput - ).map { - if (it is TextRenderer) { - currentTextRenderer = CustomTextRenderer( - subtitleOffset, - textRendererOutput, - eventHandler.looper, - CustomSubtitleDecoderFactory() - ) - currentTextRenderer!! - } else it - }.toTypedArray() + DefaultRenderersFactory(context).createRenderers( + eventHandler, + videoRendererEventListener, + audioRendererEventListener, + textRendererOutput, + metadataRendererOutput + ).map { + if (it is TextRenderer) { + currentTextRenderer = CustomTextRenderer( + subtitleOffset, + textRendererOutput, + eventHandler.looper, + CustomSubtitleDecoderFactory() + ) + currentTextRenderer!! + } else it + }.toTypedArray() } .setTrackSelector( trackSelector ?: getTrackSelector( @@ -1204,10 +1196,10 @@ class CS3IPlayer : IPlayer { HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.socketFactory) } - val mime = when { - link.isM3u8 -> MimeTypes.APPLICATION_M3U8 - link.isDash -> MimeTypes.APPLICATION_MPD - else -> MimeTypes.VIDEO_MP4 + val mime = if (link.isM3u8) { + MimeTypes.APPLICATION_M3U8 + } else { + MimeTypes.VIDEO_MP4 } val mediaItems = if (link is ExtractorLinkPlayList) { @@ -1257,4 +1249,4 @@ class CS3IPlayer : IPlayer { loadOfflinePlayer(context, it) } } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CustomSubtitleDecoderFactory.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CustomSubtitleDecoderFactory.kt index 974a5d26..690d3706 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CustomSubtitleDecoderFactory.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CustomSubtitleDecoderFactory.kt @@ -4,16 +4,13 @@ import android.content.Context import android.util.Log import androidx.preference.PreferenceManager import com.google.android.exoplayer2.Format -import com.google.android.exoplayer2.text.* -import com.google.android.exoplayer2.text.cea.Cea608Decoder -import com.google.android.exoplayer2.text.cea.Cea708Decoder -import com.google.android.exoplayer2.text.dvb.DvbDecoder -import com.google.android.exoplayer2.text.pgs.PgsDecoder +import com.google.android.exoplayer2.text.SubtitleDecoder +import com.google.android.exoplayer2.text.SubtitleDecoderFactory +import com.google.android.exoplayer2.text.SubtitleInputBuffer +import com.google.android.exoplayer2.text.SubtitleOutputBuffer import com.google.android.exoplayer2.text.ssa.SsaDecoder import com.google.android.exoplayer2.text.subrip.SubripDecoder import com.google.android.exoplayer2.text.ttml.TtmlDecoder -import com.google.android.exoplayer2.text.tx3g.Tx3gDecoder -import com.google.android.exoplayer2.text.webvtt.Mp4WebvttDecoder import com.google.android.exoplayer2.text.webvtt.WebvttDecoder import com.google.android.exoplayer2.util.MimeTypes import com.lagradost.cloudstream3.R @@ -22,11 +19,7 @@ import org.mozilla.universalchardet.UniversalDetector import java.nio.ByteBuffer import java.nio.charset.Charset -/** - * @param fallbackFormat used to create a decoder based on mimetype if the subtitle string is not - * enough to identify the subtitle format. - **/ -class CustomDecoder(private val fallbackFormat: Format?) : SubtitleDecoder { +class CustomDecoder : SubtitleDecoder { companion object { fun updateForcedEncoding(context: Context) { val settingsManager = PreferenceManager.getDefaultSharedPreferences(context) @@ -146,7 +139,7 @@ class CustomDecoder(private val fallbackFormat: Format?) : SubtitleDecoder { val inputString = getStr(inputBuffer) if (realDecoder == null && !inputString.isNullOrBlank()) { var str: String = inputString - // this way we read the subtitle file and decide what decoder to use instead of relying fully on mimetype + // this way we read the subtitle file and decide what decoder to use instead of relying on mimetype Log.i(TAG, "Got data from queueInputBuffer") //https://github.com/LagradOst/CloudStream-2/blob/ddd774ee66810137ff7bd65dae70bcf3ba2d2489/CloudStreamForms/CloudStreamForms/Script/MainChrome.cs#L388 realDecoder = when { @@ -155,31 +148,8 @@ class CustomDecoder(private val fallbackFormat: Format?) : SubtitleDecoder { (str.startsWith( "[Script Info]", ignoreCase = true - ) || str.startsWith("Title:", ignoreCase = true)) -> SsaDecoder(fallbackFormat?.initializationData) + ) || str.startsWith("Title:", ignoreCase = true)) -> SsaDecoder() str.startsWith("1", ignoreCase = true) -> SubripDecoder() - fallbackFormat != null -> { - when (val mimeType = fallbackFormat.sampleMimeType) { - MimeTypes.TEXT_VTT -> WebvttDecoder() - MimeTypes.TEXT_SSA -> SsaDecoder(fallbackFormat.initializationData) - MimeTypes.APPLICATION_MP4VTT -> Mp4WebvttDecoder() - MimeTypes.APPLICATION_TTML -> TtmlDecoder() - MimeTypes.APPLICATION_SUBRIP -> SubripDecoder() - MimeTypes.APPLICATION_TX3G -> Tx3gDecoder(fallbackFormat.initializationData) - MimeTypes.APPLICATION_CEA608, MimeTypes.APPLICATION_MP4CEA608 -> Cea608Decoder( - mimeType, - fallbackFormat.accessibilityChannel, - Cea608Decoder.MIN_DATA_CHANNEL_TIMEOUT_MS - ) - MimeTypes.APPLICATION_CEA708 -> Cea708Decoder( - fallbackFormat.accessibilityChannel, - fallbackFormat.initializationData - ) - MimeTypes.APPLICATION_DVBSUBS -> DvbDecoder(fallbackFormat.initializationData) - MimeTypes.APPLICATION_PGS -> PgsDecoder() - MimeTypes.TEXT_EXOPLAYER_CUES -> ExoplayerCuesDecoder() - else -> null - } - } else -> null } Log.i( @@ -276,6 +246,28 @@ class CustomSubtitleDecoderFactory : SubtitleDecoderFactory { } override fun createDecoder(format: Format): SubtitleDecoder { - return CustomDecoder(format) + return CustomDecoder() + //return when (val mimeType = format.sampleMimeType) { + // MimeTypes.TEXT_VTT -> WebvttDecoder() + // MimeTypes.TEXT_SSA -> SsaDecoder(format.initializationData) + // MimeTypes.APPLICATION_MP4VTT -> Mp4WebvttDecoder() + // MimeTypes.APPLICATION_TTML -> TtmlDecoder() + // MimeTypes.APPLICATION_SUBRIP -> SubripDecoder() + // MimeTypes.APPLICATION_TX3G -> Tx3gDecoder(format.initializationData) + // MimeTypes.APPLICATION_CEA608, MimeTypes.APPLICATION_MP4CEA608 -> return Cea608Decoder( + // mimeType, + // format.accessibilityChannel, + // Cea608Decoder.MIN_DATA_CHANNEL_TIMEOUT_MS + // ) + // MimeTypes.APPLICATION_CEA708 -> Cea708Decoder( + // format.accessibilityChannel, + // format.initializationData + // ) + // MimeTypes.APPLICATION_DVBSUBS -> DvbDecoder(format.initializationData) + // MimeTypes.APPLICATION_PGS -> PgsDecoder() + // MimeTypes.TEXT_EXOPLAYER_CUES -> ExoplayerCuesDecoder() + // // Default WebVttDecoder + // else -> WebvttDecoder() + //} } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt index 6f40e145..dc1bbba3 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/DownloadedPlayerActivity.kt @@ -42,7 +42,7 @@ class DownloadedPlayerActivity : AppCompatActivity() { R.id.global_to_navigation_player, GeneratorPlayer.newInstance( LinkGenerator( listOf( - BasicLink(url) + url ) ) ) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt index 86e21fd6..9ff1c52d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt @@ -39,6 +39,7 @@ import com.lagradost.cloudstream3.CommonActivity.playerEventListener import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.ui.player.GeneratorPlayer.Companion.subsProvidersIsActive +import com.lagradost.cloudstream3.ui.player.source_priority.QualityDataHelper import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.AppUtils.isUsingMobileData import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog @@ -108,8 +109,15 @@ open class FullScreenPlayer : AbstractPlayerFragment() { // get() = episodes.isNotEmpty() // options for player - protected var currentPrefQuality = - Qualities.P2160.value // preferred maximum quality, used for ppl w bad internet or on cell + + /** + * Default profile 1 + * Decides how links should be sorted based on a priority system. + * This will be set in runtime based on settings. + **/ + protected var currentQualityProfile = 1 +// protected var currentPrefQuality = +// Qualities.P2160.value // preferred maximum quality, used for ppl w bad internet or on cell protected var fastForwardTime = 10000L protected var androidTVInterfaceOffSeekTime = 10000L; protected var androidTVInterfaceOnSeekTime = 30000L; @@ -1221,10 +1229,16 @@ open class FullScreenPlayer : AbstractPlayerFragment() { .toLong() * 1000L androidTVInterfaceOffSeekTime = - settingsManager.getInt(ctx.getString(R.string.android_tv_interface_off_seek_key), 10) + settingsManager.getInt( + ctx.getString(R.string.android_tv_interface_off_seek_key), + 10 + ) .toLong() * 1000L androidTVInterfaceOnSeekTime = - settingsManager.getInt(ctx.getString(R.string.android_tv_interface_on_seek_key), 10) + settingsManager.getInt( + ctx.getString(R.string.android_tv_interface_on_seek_key), + 10 + ) .toLong() * 1000L navigationBarHeight = ctx.getNavigationBarHeight() @@ -1257,10 +1271,20 @@ open class FullScreenPlayer : AbstractPlayerFragment() { ctx.getString(R.string.double_tap_pause_enabled_key), false ) - currentPrefQuality = settingsManager.getInt( - ctx.getString(if (ctx.isUsingMobileData()) R.string.quality_pref_mobile_data_key else R.string.quality_pref_key), - currentPrefQuality - ) + + val profiles = QualityDataHelper.getProfiles() + val type = if (ctx.isUsingMobileData()) + QualityDataHelper.QualityProfileType.Data + else QualityDataHelper.QualityProfileType.WiFi + + currentQualityProfile = + profiles.firstOrNull { it.type == type }?.id ?: profiles.firstOrNull()?.id + ?: currentQualityProfile + +// currentPrefQuality = settingsManager.getInt( +// ctx.getString(if (ctx.isUsingMobileData()) R.string.quality_pref_mobile_data_key else R.string.quality_pref_key), +// currentPrefQuality +// ) // useSystemBrightness = // settingsManager.getBoolean(ctx.getString(R.string.use_system_brightness_key), false) } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt index 46f2bca9..58c50cab 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt @@ -31,6 +31,10 @@ import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.subtitl import com.lagradost.cloudstream3.ui.player.CS3IPlayer.Companion.preferredAudioTrackLanguage import com.lagradost.cloudstream3.ui.player.CustomDecoder.Companion.updateForcedEncoding import com.lagradost.cloudstream3.ui.player.PlayerSubtitleHelper.Companion.toSubtitleMimeType +import com.lagradost.cloudstream3.ui.player.source_priority.QualityDataHelper +import com.lagradost.cloudstream3.ui.player.source_priority.QualityProfileDialog +import com.lagradost.cloudstream3.ui.player.source_priority.SourcePriority +import com.lagradost.cloudstream3.ui.player.source_priority.SourcePriorityDialog import com.lagradost.cloudstream3.ui.result.* import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings import com.lagradost.cloudstream3.ui.subtitles.SubtitlesFragment.Companion.getAutoSelectLanguageISO639_1 @@ -57,6 +61,7 @@ import kotlinx.coroutines.Job import java.util.* import kotlin.collections.ArrayList import kotlin.collections.HashMap +import kotlin.math.abs class GeneratorPlayer : FullScreenPlayer() { companion object { @@ -188,17 +193,31 @@ class GeneratorPlayer : FullScreenPlayer() { player.addTimeStamps(listOf()) // clear stamps } - private fun sortLinks(useQualitySettings: Boolean = true): List> { - return currentLinks.sortedBy { - val (linkData, _) = it - var quality = linkData?.quality ?: Qualities.Unknown.value + private fun closestQuality(target: Int?): Qualities { + if (target == null) return Qualities.Unknown + return Qualities.values().minBy { abs(it.value - target) } + } - // we set all qualities above current max as reverse - if (useQualitySettings && quality > currentPrefQuality) { - quality = currentPrefQuality - quality - 1 - } - // negative because we want to sort highest quality first - -(quality) + private fun getLinkPriority( + qualityProfile: Int, + link: Pair + ): Int { + val (linkData, _) = link + + val qualityPriority = QualityDataHelper.getQualityPriority( + qualityProfile, + closestQuality(linkData?.quality) + ) + val sourcePriority = + QualityDataHelper.getSourcePriority(qualityProfile, linkData?.name) + + // negative because we want to sort highest quality first + return qualityPriority + sourcePriority + } + + private fun sortLinks(qualityProfile: Int): List> { + return currentLinks.sortedBy { + -getLinkPriority(qualityProfile, it) } } @@ -584,33 +603,39 @@ class GeneratorPlayer : FullScreenPlayer() { var sourceIndex = 0 var startSource = 0 + var sortedUrls = emptyList>() - val sortedUrls = sortLinks(useQualitySettings = false) - if (sortedUrls.isEmpty()) { - sourceDialog.findViewById(R.id.sort_sources_holder)?.isGone = true - } else { - startSource = sortedUrls.indexOf(currentSelectedLink) - sourceIndex = startSource + fun refreshLinks(qualityProfile: Int) { + sortedUrls = sortLinks(qualityProfile) + if (sortedUrls.isEmpty()) { + sourceDialog.findViewById(R.id.sort_sources_holder)?.isGone = + true + } else { + startSource = sortedUrls.indexOf(currentSelectedLink) + sourceIndex = startSource - val sourcesArrayAdapter = - ArrayAdapter(ctx, R.layout.sort_bottom_single_choice) + val sourcesArrayAdapter = + ArrayAdapter(ctx, R.layout.sort_bottom_single_choice) - sourcesArrayAdapter.addAll(sortedUrls.map { (link, uri) -> - val name = link?.name ?: uri?.name ?: "NULL" - "$name ${Qualities.getStringByInt(link?.quality)}" - }) + sourcesArrayAdapter.addAll(sortedUrls.map { (link, uri) -> + val name = link?.name ?: uri?.name ?: "NULL" + "$name ${Qualities.getStringByInt(link?.quality)}" + }) - providerList.choiceMode = AbsListView.CHOICE_MODE_SINGLE - providerList.adapter = sourcesArrayAdapter - providerList.setSelection(sourceIndex) - providerList.setItemChecked(sourceIndex, true) + providerList.choiceMode = AbsListView.CHOICE_MODE_SINGLE + providerList.adapter = sourcesArrayAdapter + providerList.setSelection(sourceIndex) + providerList.setItemChecked(sourceIndex, true) - providerList.setOnItemClickListener { _, _, which, _ -> - sourceIndex = which - providerList.setItemChecked(which, true) + providerList.setOnItemClickListener { _, _, which, _ -> + sourceIndex = which + providerList.setItemChecked(which, true) + } } } + refreshLinks(currentQualityProfile) + sourceDialog.setOnDismissListener { if (shouldDismiss) dismiss() selectSourceDialog = null @@ -650,6 +675,29 @@ class GeneratorPlayer : FullScreenPlayer() { sourceDialog.dismissSafe(activity) } + fun setProfileName(profile: Int) { + sourceDialog.source_settings_btt.setText( + QualityDataHelper.getProfileName( + profile + ) + ) + } + setProfileName(currentQualityProfile) + + sourceDialog.source_settings_btt.setOnClickListener { + val activity = activity ?: return@setOnClickListener + QualityProfileDialog( + activity, + R.style.AlertDialogCustomBlack, + currentLinks.mapNotNull { it.first }, + currentQualityProfile + ) { profile -> + currentQualityProfile = profile.id + setProfileName(profile.id) + refreshLinks(profile.id) + }.show() + } + sourceDialog.subtitles_encoding_format?.apply { val settingsManager = PreferenceManager.getDefaultSharedPreferences(ctx) @@ -847,7 +895,7 @@ class GeneratorPlayer : FullScreenPlayer() { private fun startPlayer() { if (isActive) return // we don't want double load when you skip loading - val links = sortLinks() + val links = sortLinks(currentQualityProfile) if (links.isEmpty()) { noLinksFound() return @@ -868,12 +916,12 @@ class GeneratorPlayer : FullScreenPlayer() { } override fun hasNextMirror(): Boolean { - val links = sortLinks() + val links = sortLinks(currentQualityProfile) return links.isNotEmpty() && links.indexOf(currentSelectedLink) + 1 < links.size } override fun nextMirror() { - val links = sortLinks() + val links = sortLinks(currentQualityProfile) if (links.isEmpty()) { noLinksFound() return @@ -1314,6 +1362,15 @@ class GeneratorPlayer : FullScreenPlayer() { val turnVisible = it.isNotEmpty() val wasGone = overlay_loading_skip_button?.isGone == true overlay_loading_skip_button?.isVisible = turnVisible + + normalSafeApiCall { + currentLinks.lastOrNull()?.let { last -> + if (getLinkPriority(currentQualityProfile, last) >= QualityDataHelper.AUTO_SKIP_PRIORITY) { + startPlayer() + } + } + } + if (turnVisible && wasGone) { overlay_loading_skip_button?.requestFocus() } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/LinkGenerator.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/LinkGenerator.kt index 0b560857..1f242481 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/LinkGenerator.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/LinkGenerator.kt @@ -5,15 +5,8 @@ import com.lagradost.cloudstream3.mvvm.normalSafeApiCall import com.lagradost.cloudstream3.utils.* import java.net.URI -/** - * Used to open the player more easily with the LinkGenerator - **/ -data class BasicLink( - val url: String, - val name: String? = null, -) class LinkGenerator( - private val links: List, + private val links: List, private val extract: Boolean = true, private val referer: String? = null, private val isM3u8: Boolean? = null @@ -54,7 +47,7 @@ class LinkGenerator( offset: Int ): Boolean { links.amap { link -> - if (!extract || !loadExtractor(link.url, referer, { + if (!extract || !loadExtractor(link, referer, { subtitleCallback(PlayerSubtitleHelper.getSubtitleData(it)) }) { callback(it to null) @@ -64,11 +57,11 @@ class LinkGenerator( callback( ExtractorLink( "", - link.name ?: link.url, - unshortenLinkSafe(link.url), // unshorten because it might be a raw link + link, + unshortenLinkSafe(link), // unshorten because it might be a raw link referer ?: "", Qualities.Unknown.value, isM3u8 ?: normalSafeApiCall { - URI(link.url).path?.substringAfterLast(".")?.contains("m3u") + URI(link).path?.substringAfterLast(".")?.contains("m3u") } ?: false ) to null ) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/PriorityAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/PriorityAdapter.kt new file mode 100644 index 00000000..8e0ce67c --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/PriorityAdapter.kt @@ -0,0 +1,60 @@ +package com.lagradost.cloudstream3.ui.player.source_priority + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.lagradost.cloudstream3.R +import com.lagradost.cloudstream3.utils.AppUtils +import kotlinx.android.synthetic.main.player_prioritize_item.view.* + +data class SourcePriority( + val data: T, + val name: String, + var priority: Int +) + +class PriorityAdapter(override val items: MutableList>) : + AppUtils.DiffAdapter>(items) { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + return PriorityViewHolder( + LayoutInflater.from(parent.context).inflate(R.layout.player_prioritize_item, parent, false) + ) + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + when (holder) { + is PriorityViewHolder -> holder.bind(items[position]) + } + } + + class PriorityViewHolder( + itemView: View, + ) : RecyclerView.ViewHolder(itemView) { + fun bind(item: SourcePriority) { + val plusButton: ImageView = itemView.add_button + val subtractButton: ImageView = itemView.subtract_button + val priorityText: TextView = itemView.priority_text + val priorityNumber: TextView = itemView.priority_number + priorityText.text = item.name + + fun updatePriority() { + priorityNumber.text = item.priority.toString() + } + + updatePriority() + plusButton.setOnClickListener { + // If someone clicks til the integer limit then they deserve to crash. + item.priority++ + updatePriority() + } + + subtractButton.setOnClickListener { + item.priority-- + updatePriority() + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/ProfilesAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/ProfilesAdapter.kt new file mode 100644 index 00000000..b7289aba --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/ProfilesAdapter.kt @@ -0,0 +1,81 @@ +package com.lagradost.cloudstream3.ui.player.source_priority + +import android.content.res.ColorStateList +import android.graphics.Paint +import android.graphics.Typeface +import android.text.style.StyleSpan +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.core.view.isVisible +import androidx.recyclerview.widget.RecyclerView +import com.lagradost.cloudstream3.R +import com.lagradost.cloudstream3.utils.AppUtils +import kotlinx.android.synthetic.main.player_quality_profile_item.view.* + +class ProfilesAdapter( + override val items: MutableList, + val usedProfile: Int, + val clickCallback: (oldIndex: Int?, newIndex: Int) -> Unit, +) : + AppUtils.DiffAdapter( + items, + comparison = { first: QualityDataHelper.QualityProfile, second: QualityDataHelper.QualityProfile -> + first.id == second.id + }) { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + return ProfilesViewHolder( + LayoutInflater.from(parent.context) + .inflate(R.layout.player_quality_profile_item, parent, false) + ) + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + when (holder) { + is ProfilesViewHolder -> holder.bind(items[position], position) + } + } + + private var currentItem: Pair? = null + + fun getCurrentProfile(): QualityDataHelper.QualityProfile? { + return currentItem?.second + } + + inner class ProfilesViewHolder( + itemView: View, + ) : RecyclerView.ViewHolder(itemView) { + fun bind(item: QualityDataHelper.QualityProfile, index: Int) { + val priorityText: TextView = itemView.profile_text + val wifiText: TextView = itemView.text_is_wifi + val dataText: TextView = itemView.text_is_mobile_data + val outline: View = itemView.outline + + priorityText.text = item.name.asString(itemView.context) + dataText.isVisible = item.type == QualityDataHelper.QualityProfileType.Data + wifiText.isVisible = item.type == QualityDataHelper.QualityProfileType.WiFi + + fun setCurrentItem() { + val prevIndex = currentItem?.first + currentItem = index to item + clickCallback.invoke(prevIndex, index) + } + outline.isVisible = currentItem?.second?.id == item.id + + + val textStyle = + if (item.id == usedProfile) { + Typeface.BOLD + } else { + Typeface.NORMAL + } + + priorityText.setTypeface(null, textStyle) + + itemView.setOnClickListener { + setCurrentItem() + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/QualityDataHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/QualityDataHelper.kt new file mode 100644 index 00000000..28fbb101 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/QualityDataHelper.kt @@ -0,0 +1,159 @@ +package com.lagradost.cloudstream3.ui.player.source_priority + +import android.content.Context +import androidx.annotation.StringRes +import com.lagradost.cloudstream3.AcraApplication.Companion.getKey +import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey +import com.lagradost.cloudstream3.AcraApplication.Companion.setKey +import com.lagradost.cloudstream3.R +import com.lagradost.cloudstream3.mvvm.debugAssert +import com.lagradost.cloudstream3.ui.result.UiText +import com.lagradost.cloudstream3.ui.result.txt +import com.lagradost.cloudstream3.utils.DataStoreHelper.currentAccount +import com.lagradost.cloudstream3.utils.Qualities + +object QualityDataHelper { + private const val VIDEO_SOURCE_PRIORITY = "video_source_priority" + private const val VIDEO_PROFILE_NAME = "video_profile_name" + private const val VIDEO_QUALITY_PRIORITY = "video_quality_priority" + private const val VIDEO_PROFILE_TYPE = "video_profile_type" + private const val DEFAULT_SOURCE_PRIORITY = 1 + /** + * Automatically skip loading links once this priority is reached + **/ + const val AUTO_SKIP_PRIORITY = 10 + + /** + * Must be higher than amount of QualityProfileTypes + **/ + private const val PROFILE_COUNT = 10 + + /** + * Unique guarantees that there will always be one of this type in the profile list. + **/ + enum class QualityProfileType(@StringRes val stringRes: Int, val unique: Boolean) { + None(R.string.none, false), + WiFi(R.string.wifi, true), + Data(R.string.mobile_data, true) + } + + data class QualityProfile( + val name: UiText, + val id: Int, + val type: QualityProfileType + ) + + fun getSourcePriority(profile: Int, name: String?): Int { + if (name == null) return DEFAULT_SOURCE_PRIORITY + return getKey( + "$currentAccount/$VIDEO_SOURCE_PRIORITY/$profile", + name, + DEFAULT_SOURCE_PRIORITY + ) ?: DEFAULT_SOURCE_PRIORITY + } + + fun setSourcePriority(profile: Int, name: String, priority: Int) { + setKey("$currentAccount/$VIDEO_SOURCE_PRIORITY/$profile", name, priority) + } + + fun setProfileName(profile: Int, name: String?) { + val path = "$currentAccount/$VIDEO_PROFILE_NAME/$profile" + if (name == null) { + removeKey(path) + } else { + setKey(path, name.trim()) + } + } + + fun getProfileName(profile: Int): UiText { + return getKey("$currentAccount/$VIDEO_PROFILE_NAME/$profile")?.let { txt(it) } + ?: txt(R.string.profile_number, profile) + } + + fun getQualityPriority(profile: Int, quality: Qualities): Int { + return getKey( + "$currentAccount/$VIDEO_QUALITY_PRIORITY/$profile", + quality.value.toString(), + quality.defaultPriority + ) ?: quality.defaultPriority + } + + fun setQualityPriority(profile: Int, quality: Qualities, priority: Int) { + setKey( + "$currentAccount/$VIDEO_QUALITY_PRIORITY/$profile", + quality.value.toString(), + priority + ) + } + + fun getQualityProfileType(profile: Int): QualityProfileType { + return getKey("$currentAccount/$VIDEO_PROFILE_TYPE/$profile") ?: QualityProfileType.None + } + + fun setQualityProfileType(profile: Int, type: QualityProfileType?) { + val path = "$currentAccount/$VIDEO_PROFILE_TYPE/$profile" + if (type == QualityProfileType.None) { + removeKey(path) + } else { + setKey(path, type) + } + } + + /** + * Gets all quality profiles, always includes one profile with WiFi and Data + * Must under all circumstances at least return one profile + **/ + fun getProfiles(): List { + val availableTypes = QualityProfileType.values().toMutableList() + val profiles = (1..PROFILE_COUNT).map { profileNumber -> + // Get the real type + val type = getQualityProfileType(profileNumber) + + // This makes it impossible to get more than one of each type + // Duplicates will be turned to None + val uniqueType = if (type.unique && !availableTypes.remove(type)) { + QualityProfileType.None + } else { + type + } + + QualityProfile( + getProfileName(profileNumber), + profileNumber, + uniqueType + ) + }.toMutableList() + + /** + * If no profile of this type exists: insert it on the earliest profile with None type + **/ + fun insertType( + list: MutableList, + type: QualityProfileType + ) { + if (list.any { it.type == type }) return + val index = + list.indexOfFirst { it.type == QualityProfileType.None } + list.getOrNull(index)?.copy(type = type) + ?.let { fixed -> + list.set(index, fixed) + } + } + + QualityProfileType.values().forEach { + if (it.unique) insertType(profiles, it) + } + + debugAssert({ + !QualityProfileType.values().all { type -> + !type.unique || profiles.any { it.type == type } + } + }, { "All unique quality types do not exist" }) + + debugAssert({ + profiles.isEmpty() + }, { "No profiles!" }) + + return profiles + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/QualityProfileDialog.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/QualityProfileDialog.kt new file mode 100644 index 00000000..28a6365f --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/QualityProfileDialog.kt @@ -0,0 +1,106 @@ +package com.lagradost.cloudstream3.ui.player.source_priority + +import android.app.Dialog +import android.view.View +import android.widget.TextView +import androidx.annotation.StyleRes +import androidx.core.view.isVisible +import androidx.fragment.app.FragmentActivity +import androidx.recyclerview.widget.RecyclerView +import com.lagradost.cloudstream3.R +import com.lagradost.cloudstream3.ui.player.source_priority.QualityDataHelper.getProfileName +import com.lagradost.cloudstream3.ui.player.source_priority.QualityDataHelper.getProfiles +import com.lagradost.cloudstream3.ui.result.txt +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog +import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe +import kotlinx.android.synthetic.main.player_quality_profile_dialog.* + +class QualityProfileDialog( + val activity: FragmentActivity, + @StyleRes val themeRes: Int, + private val links: List, + private val usedProfile: Int, + private val profileSelectionCallback: (QualityDataHelper.QualityProfile) -> Unit +) : Dialog(activity, themeRes) { + override fun show() { + setContentView(R.layout.player_quality_profile_dialog) + val profilesRecyclerView: RecyclerView = profiles_recyclerview + val useBtt: View = use_btt + val editBtt: View = edit_btt + val cancelBtt: View = cancel_btt + val defaultBtt: View = set_default_btt + val currentProfileText: TextView = currently_selected_profile_text + val selectedItemActionsHolder: View = selected_item_holder + + fun getCurrentProfile(): QualityDataHelper.QualityProfile? { + return (profilesRecyclerView.adapter as? ProfilesAdapter)?.getCurrentProfile() + } + + fun refreshProfiles() { + currentProfileText.text = getProfileName(usedProfile).asString(context) + (profilesRecyclerView.adapter as? ProfilesAdapter)?.updateList(getProfiles()) + } + + profilesRecyclerView.adapter = ProfilesAdapter( + mutableListOf(), + usedProfile, + ) { oldIndex: Int?, newIndex: Int -> + profilesRecyclerView.adapter?.notifyItemChanged(newIndex) + selectedItemActionsHolder.alpha = 1f + if (oldIndex != null) { + profilesRecyclerView.adapter?.notifyItemChanged(oldIndex) + } + } + + refreshProfiles() + + editBtt.setOnClickListener { + getCurrentProfile()?.let { profile -> + SourcePriorityDialog(context, themeRes, links, profile) { + refreshProfiles() + }.show() + } + } + + + defaultBtt.setOnClickListener { + val currentProfile = getCurrentProfile() ?: return@setOnClickListener + val choices = QualityDataHelper.QualityProfileType.values() + .filter { it != QualityDataHelper.QualityProfileType.None } + val choiceNames = choices.map { txt(it.stringRes).asString(context) } + + activity.showBottomDialog( + choiceNames, + choices.indexOf(currentProfile.type), + txt(R.string.set_default).asString(context), + false, + {}, + { index -> + val pickedChoice = choices.getOrNull(index) ?: return@showBottomDialog + // Remove previous picks + if (pickedChoice.unique) { + getProfiles().filter { it.type == pickedChoice }.forEach { + QualityDataHelper.setQualityProfileType(it.id, null) + } + } + + QualityDataHelper.setQualityProfileType(currentProfile.id, pickedChoice) + refreshProfiles() + }) + } + + cancelBtt.setOnClickListener { + this.dismissSafe() + } + + useBtt.setOnClickListener { + getCurrentProfile()?.let { + profileSelectionCallback.invoke(it) + this.dismissSafe() + } + } + + super.show() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/SourcePriorityDialog.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/SourcePriorityDialog.kt new file mode 100644 index 00000000..efc1f1b8 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/source_priority/SourcePriorityDialog.kt @@ -0,0 +1,105 @@ +package com.lagradost.cloudstream3.ui.player.source_priority + +import android.app.Dialog +import android.content.Context +import android.view.View +import android.widget.EditText +import android.widget.TextView +import androidx.annotation.StyleRes +import androidx.appcompat.app.AlertDialog +import androidx.fragment.app.FragmentActivity +import androidx.recyclerview.widget.RecyclerView +import androidx.work.impl.constraints.controllers.ConstraintController +import com.lagradost.cloudstream3.R +import com.lagradost.cloudstream3.ui.result.txt +import com.lagradost.cloudstream3.utils.DataStoreHelper +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.Qualities +import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe +import kotlinx.android.synthetic.main.player_select_source_priority.* + +class SourcePriorityDialog( + ctx: Context, + @StyleRes themeRes: Int, + val links: List, + private val profile: QualityDataHelper.QualityProfile, + /** + * Notify that the profile overview should be updated, for example if the name has been updated + * Should not be called excessively. + **/ + private val updatedCallback: () -> Unit +) : Dialog(ctx, themeRes) { + override fun show() { + setContentView(R.layout.player_select_source_priority) + val sourcesRecyclerView: RecyclerView = sort_sources + val qualitiesRecyclerView: RecyclerView = sort_qualities + val profileText: EditText = profile_text_editable + val saveBtt: View = save_btt + val exitBtt: View = close_btt + val helpBtt: View = help_btt + + profileText.setText(QualityDataHelper.getProfileName(profile.id).asString(context)) + profileText.hint = txt(R.string.profile_number, profile.id).asString(context) + + sourcesRecyclerView.adapter = PriorityAdapter( + links.map { link -> + SourcePriority( + null, + link.source, + QualityDataHelper.getSourcePriority(profile.id, link.source) + ) + }.distinctBy { it.name }.sortedBy { -it.priority }.toMutableList() + ) + + qualitiesRecyclerView.adapter = PriorityAdapter( + Qualities.values().mapNotNull { + SourcePriority( + it, + Qualities.getStringByIntFull(it.value).ifBlank { return@mapNotNull null }, + QualityDataHelper.getQualityPriority(profile.id, it) + ) + }.sortedBy { -it.priority }.toMutableList() + ) + + @Suppress("UNCHECKED_CAST") // We know the types + saveBtt.setOnClickListener { + val qualityAdapter = qualitiesRecyclerView.adapter as? PriorityAdapter + val sourcesAdapter = sourcesRecyclerView.adapter as? PriorityAdapter + + val qualities = qualityAdapter?.items ?: emptyList() + val sources = sourcesAdapter?.items ?: emptyList() + + qualities.forEach { + val data = it.data as? Qualities ?: return@forEach + QualityDataHelper.setQualityPriority(profile.id, data, it.priority) + } + + sources.forEach { + QualityDataHelper.setSourcePriority(profile.id, it.name, it.priority) + } + + qualityAdapter?.updateList(qualities.sortedBy { -it.priority }) + sourcesAdapter?.updateList(sources.sortedBy { -it.priority }) + + val savedProfileName = profileText.text.toString() + if (savedProfileName.isBlank()) { + QualityDataHelper.setProfileName(profile.id, null) + } else { + QualityDataHelper.setProfileName(profile.id, savedProfileName) + } + updatedCallback.invoke() + } + + exitBtt.setOnClickListener { + this.dismissSafe() + } + + helpBtt.setOnClickListener { + AlertDialog.Builder(context, R.style.AlertDialogCustom).apply { + setMessage(R.string.quality_profile_help) + }.show() + } + + super.show() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/LinearListLayout.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/LinearListLayout.kt index affbcbb4..59a46264 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/LinearListLayout.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/LinearListLayout.kt @@ -7,13 +7,13 @@ import androidx.recyclerview.widget.RecyclerView import com.lagradost.cloudstream3.mvvm.logError fun RecyclerView?.setLinearListLayout(isHorizontal: Boolean = true) { - if (this == null) return + if(this == null) return this.layoutManager = this.context?.let { LinearListLayout(it).apply { if (isHorizontal) setHorizontal() else setVertical() } } ?: this.layoutManager } -open class LinearListLayout(context: Context?) : +class LinearListLayout(context: Context?) : LinearLayoutManager(context) { fun setHorizontal() { @@ -24,8 +24,7 @@ open class LinearListLayout(context: Context?) : orientation = VERTICAL } - private fun getCorrectParent(focused: View?): View? { - if (focused == null) return null + private fun getCorrectParent(focused: View): View? { var current: View? = focused val last: ArrayList = arrayListOf(focused) while (current != null && current !is RecyclerView) { @@ -55,17 +54,10 @@ open class LinearListLayout(context: Context?) : linearSmoothScroller.targetPosition = position startSmoothScroll(linearSmoothScroller) }*/ + override fun onInterceptFocusSearch(focused: View, direction: Int): View? { val dir = if (orientation == HORIZONTAL) { - if (direction == View.FOCUS_DOWN || direction == View.FOCUS_UP) { - // This scrolls the recyclerview before doing focus search, which - // allows the focus search to work better. - - // Without this the recyclerview focus location on the screen - // would change when scrolling between recyclerviews. - (focused.parent as? RecyclerView)?.focusSearch(direction) - return null - } + if (direction == View.FOCUS_DOWN || direction == View.FOCUS_UP) return null if (direction == View.FOCUS_RIGHT) 1 else -1 } else { if (direction == View.FOCUS_RIGHT || direction == View.FOCUS_LEFT) return null diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt index 5a3e28b4..bdef14b5 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt @@ -22,7 +22,6 @@ import androidx.core.view.isVisible import androidx.core.widget.doOnTextChanged import androidx.lifecycle.ViewModelProvider import androidx.preference.PreferenceManager -import androidx.recyclerview.widget.RecyclerView import com.discord.panels.OverlappingPanelsLayout import com.google.android.material.chip.Chip import com.google.android.material.chip.ChipDrawable @@ -532,25 +531,6 @@ open class ResultFragment : ResultTrailerPlayer() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - result_cast_items?.layoutManager = object : LinearListLayout(view.context) { - override fun onRequestChildFocus( - parent: RecyclerView, - state: RecyclerView.State, - child: View, - focused: View? - ): Boolean { - // Make the cast always focus the first visible item when focused - // from somewhere else. Otherwise it jumps to the last item. - return if (parent.focusedChild == null) { - scrollToPosition(this.findFirstCompletelyVisibleItemPosition()) - true - } else { - super.onRequestChildFocus(parent, state, child, focused) - } - } - }.apply { - this.orientation = RecyclerView.HORIZONTAL - } result_cast_items?.adapter = ActorAdaptor() updateUIListener = ::updateUI diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel2.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel2.kt index 46a8c9f6..2983b41d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel2.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel2.kt @@ -3,7 +3,6 @@ package com.lagradost.cloudstream3.ui.result import android.app.Activity import android.content.* import android.net.Uri -import android.os.Build import android.os.Bundle import android.util.Log import android.widget.Toast @@ -1126,12 +1125,7 @@ class ResultViewModel2 : ViewModel() { 1L } - // Component no longer safe to use in A13 for VLC - // https://code.videolan.org/videolan/vlc-android/-/issues/2776 - // This will likely need to be updated once VLC fixes their documentation. - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { - component = VLC_COMPONENT - } + component = VLC_COMPONENT putExtra("from_start", !resume) putExtra("position", position) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsAccount.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsAccount.kt index 1ef3cb55..f9627e46 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsAccount.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsAccount.kt @@ -157,28 +157,6 @@ class SettingsAccount : PreferenceFragmentCompat() { ) dialog.dismissSafe() } - - val displayedItems = listOf( - dialog.login_username_input, - dialog.login_email_input, - dialog.login_server_input, - dialog.login_password_input - ).filter { it.isVisible } - - displayedItems.foldRight(displayedItems.firstOrNull()) { item, previous -> - item?.id?.let { previous?.nextFocusDownId = it } - previous?.id?.let { item?.nextFocusUpId = it } - item - } - - displayedItems.firstOrNull()?.let { - dialog.create_account?.nextFocusDownId = it.id - it.nextFocusUpId = dialog.create_account.id - } - dialog.apply_btt?.id?.let { - displayedItems.lastOrNull()?.nextFocusDownId = it - } - dialog.text1?.text = api.name if (api.storesPasswordInPlainText) { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt index 4aa859aa..078419e2 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsGeneral.kt @@ -78,7 +78,6 @@ val appLanguages = arrayListOf( Triple("", "ಕನ್ನಡ", "kn"), Triple("", "македонски", "mk"), Triple("", "മലയാളം", "ml"), - Triple("", "bahasa Melayu", "ms"), Triple("", "Nederlands", "nl"), Triple("", "norsk nynorsk", "nn"), Triple("", "norsk bokmål", "no"), diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/DataStoreHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/DataStoreHelper.kt index 516cd990..3bdb64e1 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/DataStoreHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/DataStoreHelper.kt @@ -117,7 +117,7 @@ object DataStoreHelper { /** * A datastore wide account for future implementations of a multiple account system **/ - private var currentAccount: String = "0" //TODO ACCOUNT IMPLEMENTATION + var currentAccount: String = "0" //TODO ACCOUNT IMPLEMENTATION fun getAllWatchStateIds(): List? { val folder = "$currentAccount/$RESULT_WATCH_STATE" diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt index b03c9fb7..9ca540e2 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt @@ -52,7 +52,7 @@ data class ExtractorLinkPlayList( ) -open class ExtractorLink constructor( +open class ExtractorLink( open val source: String, open val name: String, override val url: String, @@ -62,24 +62,7 @@ open class ExtractorLink constructor( override val headers: Map = mapOf(), /** Used for getExtractorVerifierJob() */ open val extractorData: String? = null, - open val isDash: Boolean = false, ) : VideoDownloadManager.IDownloadableMinimum { - /** - * Old constructor without isDash, allows for backwards compatibility with extensions. - * Should be removed after all extensions have updated their cloudstream.jar - **/ - constructor( - source: String, - name: String, - url: String, - referer: String, - quality: Int, - isM3u8: Boolean = false, - headers: Map = mapOf(), - /** Used for getExtractorVerifierJob() */ - extractorData: String? = null - ) : this(source, name, url, referer, quality, isM3u8, headers, extractorData, false) - override fun toString(): String { return "ExtractorLink(name=$name, url=$url, referer=$referer, isM3u8=$isM3u8)" } @@ -114,16 +97,16 @@ data class ExtractorSubtitleLink( */ val schemaStripRegex = Regex("""^(https:|)//(www\.|)""") -enum class Qualities(var value: Int) { - Unknown(400), - P144(144), // 144p - P240(240), // 240p - P360(360), // 360p - P480(480), // 480p - P720(720), // 720p - P1080(1080), // 1080p - P1440(1440), // 1440p - P2160(2160); // 4k or 2160p +enum class Qualities(var value: Int, val defaultPriority: Int) { + Unknown(400, 4), + P144(144, 0), // 144p + P240(240, 2), // 240p + P360(360, 3), // 360p + P480(480, 4), // 480p + P720(720, 5), // 720p + P1080(1080, 6), // 1080p + P1440(1440, 7), // 1440p + P2160(2160, 8); // 4k or 2160p companion object { fun getStringByInt(qual: Int?): String { @@ -135,6 +118,14 @@ enum class Qualities(var value: Int) { else -> "${qual}p" } } + fun getStringByIntFull(quality: Int): String { + return when (quality) { + 0 -> "Auto" + Unknown.value -> "Unknown" + P2160.value -> "4K" + else -> "${quality}p" + } + } } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/SingleSelectionHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/SingleSelectionHelper.kt index 2dc6846c..1f6d726d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/SingleSelectionHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/SingleSelectionHelper.kt @@ -250,17 +250,6 @@ object SingleSelectionHelper { ) } - fun showBottomDialog( - items: List, - selectedIndex: Int, - name: String, - showApply: Boolean, - dismissCallback: () -> Unit, - callback: (Int) -> Unit, - ) { - - } - /** Only for a low amount of items */ fun Activity?.showBottomDialog( items: List, diff --git a/app/src/main/res/drawable/baseline_help_outline_24.xml b/app/src/main/res/drawable/baseline_help_outline_24.xml new file mode 100644 index 00000000..3a72cda0 --- /dev/null +++ b/app/src/main/res/drawable/baseline_help_outline_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/baseline_remove_24.xml b/app/src/main/res/drawable/baseline_remove_24.xml index 791a2f81..f4455598 100644 --- a/app/src/main/res/drawable/baseline_remove_24.xml +++ b/app/src/main/res/drawable/baseline_remove_24.xml @@ -3,7 +3,7 @@ android:height="24dp" android:viewportWidth="24" android:viewportHeight="24" - android:tint="?attr/colorControlNormal"> + android:tint="?attr/white"> diff --git a/app/src/main/res/layout/fragment_result_tv.xml b/app/src/main/res/layout/fragment_result_tv.xml index 5eacdbe2..a29dc192 100644 --- a/app/src/main/res/layout/fragment_result_tv.xml +++ b/app/src/main/res/layout/fragment_result_tv.xml @@ -199,13 +199,17 @@ android:id="@+id/result_back" android:layout_width="30dp" android:layout_height="30dp" + android:layout_gravity="center_vertical" android:layout_marginEnd="10dp" + android:background="?android:attr/selectableItemBackgroundBorderless" android:clickable="true" android:contentDescription="@string/go_back" + android:focusable="true" android:gravity="center_vertical" + android:nextFocusDown="@id/result_description" android:src="@drawable/ic_baseline_arrow_back_24" app:tint="?attr/white" /> @@ -381,8 +385,8 @@ @@ -419,11 +423,11 @@ @@ -564,7 +568,6 @@ android:layout_weight="1" android:minWidth="250dp" android:nextFocusLeft="@id/result_movie_progress_downloaded_holder" - android:nextFocusRight="@id/result_bookmark_button" android:nextFocusDown="@id/result_resume_series_button_play" android:text="@string/type_none" android:visibility="visible" /> diff --git a/app/src/main/res/layout/homepage_parent_tv.xml b/app/src/main/res/layout/homepage_parent_tv.xml index 9dcf0bae..d0c88c39 100644 --- a/app/src/main/res/layout/homepage_parent_tv.xml +++ b/app/src/main/res/layout/homepage_parent_tv.xml @@ -2,30 +2,33 @@ + android:layout_height="wrap_content"> \ No newline at end of file diff --git a/app/src/main/res/layout/player_prioritize_item.xml b/app/src/main/res/layout/player_prioritize_item.xml new file mode 100644 index 00000000..b78863f8 --- /dev/null +++ b/app/src/main/res/layout/player_prioritize_item.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + diff --git a/app/src/main/res/layout/player_quality_profile_dialog.xml b/app/src/main/res/layout/player_quality_profile_dialog.xml new file mode 100644 index 00000000..640eb90b --- /dev/null +++ b/app/src/main/res/layout/player_quality_profile_dialog.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/player_quality_profile_item.xml b/app/src/main/res/layout/player_quality_profile_item.xml new file mode 100644 index 00000000..ad2a29a0 --- /dev/null +++ b/app/src/main/res/layout/player_quality_profile_item.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/player_select_source_and_subs.xml b/app/src/main/res/layout/player_select_source_and_subs.xml index 067e4ad5..4aefb5cb 100644 --- a/app/src/main/res/layout/player_select_source_and_subs.xml +++ b/app/src/main/res/layout/player_select_source_and_subs.xml @@ -1,5 +1,6 @@ - + android:background="@drawable/outline_drawable_less" + android:foreground="?attr/selectableItemBackgroundBorderless" + android:gravity="center_vertical" + android:orientation="horizontal"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 2a356812..cfd761e3 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -1,4 +1,4 @@ - + ملصق @@ -119,16 +119,16 @@ وضع إيغنغرافي يضيف خيار السرعة في المُشغل السحب لتقديم - اسحب من جانب إلى آخر للتحكم في موضعك في مقطع فيديو + إسحب إلى اليسار أو اليمين للتحكم في الوقت في مُشغل الفيديو السحب لتغيير الإعدادات - مرر لأعلى أو لأسفل على الجانب الأيسر أو الأيمن لتغيير السطوع أو مستوى الصوت + إسحب على الجانب الأيسر أو الأيمن لتغيير السطوع أو مستوى الصوت تشغيل الحلقة التالية تلقائيًا تبدأ الحلقة التالية عندما تنتهي الحالية النقر مرتان للتقديم للأمام أو للخلف الضغط مرتان لإيقاف مؤقت - التحكم في مدى تقديم المُشغل(ثوان) + التحكم في مدى تقديم المُشغل إضغط مرتين على الجانب الأيمن أو الأيسر للتقديم للأمام أو للخلف - اضغط مرتين في المنتصف للتوقف + إضغط في الوسط لإيقاف مؤقت استخدم سطوع النظام استخدم سطوع النظام في مُشغل التطبيق بدلاً من التراكب الداكن تحديث تقدم المشاهدة @@ -155,7 +155,7 @@ تحديث الإضافات تلقائيًا تنزيل الإضافات تلقائيًا التحديث التلقائي - ابحث تلقائيا عن التحديثات الجديدة بعد بدء التطبيق. + البحث تلقائيًا عن التحديثات الجديدة عند البداية التحديث إلى الاصدارات التجريبية (بيتا) البحث عن التحديثات التجريبية بدلاً من الإصدارات الكاملة فقط غيت هاب @@ -218,8 +218,8 @@ فيلم مسلسل كرتون - أنيمي - أوفا + أنمي + اوفا تورنت وثائقي دراما آسيوية @@ -284,7 +284,7 @@ Any legal issues regarding the content on this application should be taken up with the actual file hosts and providers themselves as we are not affiliated with them. In case of copyright infringement, please directly contact the responsible parties or the streaming websites. The app is purely for educational and personal use. CloudStream 3 does not host any content on the app, and has no control over what media is put up or taken down. CloudStream 3 functions like any other search engine, such as Google. CloudStream 3 does not host, upload or manage any videos, films or content. It simply crawls, aggregates and displayes links in a convenient, user-friendly interface. It merely scrapes 3rd-party websites that are publicly accessable via any regular web browser. It is the responsibility of user to avoid any actions that might violate the laws governing his/her locality. Use CloudStream 3 at your own risk. عام زر العشوائي - يظهر الزر على الصفحة الرئيسية والذي يمكنه اختيار فيلم عشوائي أو مسلسل تلفزيوني من الصفحة الرئيسية + إظهار زر العشوائي على الصفحة الرئيسية لغات المزود واجهة التطبيق المحتوى المفضل @@ -342,7 +342,7 @@ الكل الحد الاقصي الحد الأدنى - @string/none + \@string/none الخطوط المحيطة النمط المنخفض ظل @@ -558,7 +558,7 @@ تجاوز مزود خدمة الإنترنت استرجاع فشل الوصول إلى GitHub ، وتمكين وكيل jsdelivr. - باستخدام jsdelivr ، يمكن تجاوز حظر GitHub. قد يؤخر التحديثات لبضعة أيام. + تجاوز حظر GitHub باستخدام jsdelivr ، قد يتسبب في تأخير التحديثات لبضعة أيام. وكيل raw.githubusercontent.com جودة المشاهدة المفضلة (بيانات الجوال) - + \ No newline at end of file diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index 301242cd..f1f512a1 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -1,6 +1,5 @@ - - - + + %s еп. %d Актьори: %s @@ -106,7 +105,7 @@ Продължете да гледате Премахване Повече информация - @string/home_play + \@string/home_play Може да е необходим VPN, за да работи правилно този доставчик Този доставчик е торент, препоръчва се VPN Метаданните не се предоставят от сайта, зареждането на видео ще бъде неуспешно, ако не съществува на сайта. @@ -224,8 +223,8 @@ Филм Серия Анимационен филм - @string/anime - @string/ova + \@string/anime + \@string/ova Торент Документален филм Азиатска драма @@ -498,4 +497,4 @@ Приложението ще се актуализира при изход от него Започна Актуализация Премахване от гледани - + \ No newline at end of file diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index 71d5d6d0..7e0448d6 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -1,4 +1,4 @@ - + পোস্টার ক্লাউডস্ট্রিম দিয়ে চালান @@ -143,9 +143,9 @@ হালনাগাদ ও ব্যাকআপ অ্যাপ এর হালনাগাদ দেখান খুঁজতে সোয়াইপ করুন - @string/result_poster_img_des - @string/home_play + \@string/result_poster_img_des + \@string/home_play আগাতে ডবল ট্যাপ করুন আইজেনগ্রাভি মোড আপডেট শুরু হয়েছে - + \ No newline at end of file diff --git a/app/src/main/res/values-bp/strings.xml b/app/src/main/res/values-bp/strings.xml index 13b34872..2c2e1303 100644 --- a/app/src/main/res/values-bp/strings.xml +++ b/app/src/main/res/values-bp/strings.xml @@ -1,6 +1,5 @@ - - - + + %s Ep %d @@ -11,7 +10,7 @@ %dm Poster - @string/result_poster_img_des + \@string/result_poster_img_des Episode Poster Main Poster Next Random @@ -109,7 +108,7 @@ Continue Assistindo Remover Mais Info - @string/home_play + \@string/home_play Uma VPN pode ser necessária para esse fornecedor funcionar corretamente Esse fornecedor é um torrent, uma VPN é recomendada Metadados não são oferecidas pelo site, o carregamento do video pode falhar se ele não existir no site. @@ -223,8 +222,8 @@ Filme Série Desenho Animado - @string/anime - @string/ova + \@string/anime + \@string/ova Torrent Documentário Drama Asiático @@ -429,4 +428,4 @@ Começa o próximo episódio quando o atual termina Ativar NSFW em fornecedores compatíveis Fornecedores - + \ No newline at end of file diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 1501a5d9..e99e1010 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -1,6 +1,5 @@ - - - + + %s Ep %d @@ -104,7 +103,7 @@ Pokračovat ve sledování Odebrat Další informace - @string/home_play + \@string/home_play Aby tento poskytovatel fungoval správně, budete možná potřebovat VPN Tento poskytovatel je torrent, je doporučená VPN Web neposkytnul žádná metadata, načítání videa selže, pokud na webu neexistuje. @@ -123,14 +122,14 @@ Rychlostní režim Přidá do přehrávače možnost rychlosti Přejet pro posun - Přejeďte prstem ze strany na stranu pro ovládání své pozice ve videu + Přejeďte prstem vlevo nebo vpravo pro ovládání času v přehrávači Přejet pro změnu nastavení - Přejeďte prstem nahoru nebo dolů na levé nebo pravé straně pro změnu jasu nebo hlasitosti + Přejeďte prstem na levé nebo pravé straně pro změnu jasu nebo hlasitosti Dvojité klepnutí pro posun Dvojité klepnutí pro pozastavení - Množství času k posunu (sekundy) + Množství času k posunu Klepněte dvakrát vpravo nebo vlevo pro posun vpřed nebo vzad - Klepněte dvakrát doprostřed pro pozastavení + Klepněte doprostřed pro pozastavení Použít systémový jas V přehrávači použít systémov překrytí Aktualizovat postup sledování @@ -152,7 +151,7 @@ Nebude odesílat žádná data Zobrazit výplňové epizody u anime Zobrazit aktualizace aplikace - Při spuštění aplikace automaticky zkontrolovat nové aktualizace. + Při spuštění automaticky zkontrolovat nové aktualizace Aktualizovat na předběžná vydání Kontrolovat aktualizace předběžných vydání, místo normálních plných vydání GitHub @@ -212,8 +211,8 @@ Film Seriál Animovaný - Anime - OVA + \@string/anime + \@string/ova Torrent Dokument Asijské drama @@ -267,7 +266,7 @@ Jakékoli právní otázky týkající se obsahu této aplikace je třeba řešit se samotnými hostiteli a poskytovateli souborů, protože s nimi nejsme nijak spojeni. V případě porušení autorských práv se obraťte přímo na odpovědné strany nebo na webové stránky, na kterých se streamování odehrává. Aplikace je určena výhradně pro vzdělávací a osobní účely. CloudStream 3 v aplikaci nehostuje žádný obsah a nemá žádnou kontrolu nad tím, jaká média jsou v aplikaci umístěna nebo odstraněna. CloudStream 3 funguje jako jakýkoli jiný vyhledávač, například Google. Služba CloudStream 3 nehostuje, nenahrává ani nespravuje žádná videa, filmy ani obsah. Pouze vyhledává, agreguje a zobrazuje odkazy v pohodlném, uživatelsky přívětivém rozhraní. Pouze shromažďuje webové stránky třetích stran, které jsou veřejně přístupné prostřednictvím jakéhokoli běžného webového prohlížeče. Je odpovědností uživatele, aby se vyvaroval jakýchkoli akcí, které by mohly porušovat zákony platné v jeho lokalitě. Použijte CloudStream 3 na vlastní nebezpečí. Obecné Náhodné tlačítko - Zobrazit na domovské stránce tlačítko, kterým lze vybrat náhodný film nebo seriál z domovské stránky + Zobrazit na domovské stránce náhodné tlačítko Jazyk poskytovatelů Rozložení aplikace Preferovaná média @@ -552,6 +551,6 @@ Nepodařilo se připojit ke GitHubu, povolování proxy jsdelivr. Upřednostněná kvalita sledování (mobilní data) Vrátit zpět - Pomocí jsdelivr lze obejít blokování GitHubu. Může dojít ke zpoždění aktualizací o několik dní. + Obchází blokování GitHubu pomocí jsdelivr, může způsobit zpoždění aktualizací o několik dní. Obcházení ISP - + \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 8fbcc2d0..c5e74a60 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -1,4 +1,4 @@ - + %s Ep %d Besetzung: %s @@ -41,7 +41,7 @@ Suche %s… Keine Daten vorhanden Mehr Optionen - Nächste Episode + Nächste Epsisode Genres Teilen In Browser öffnen @@ -115,7 +115,7 @@ Weiterschauen Entfernen Mehr Infos - @string/home_play + \@string/home_play Damit dieser Anbieter korrekt funktioniert, ist möglicherweise ein VPN erforderlich Dieser Anbieter bietet Torrents an, ein VPN wird dringend empfohlen Metadaten werden nicht von der Website bereitgestellt, das Laden des Videos schlägt fehl, wenn sie auf der Website nicht vorhanden sind. @@ -136,14 +136,14 @@ Wischen zum vor- und zurückspulen Nach links oder rechts wischen, um die Zeit im Videoplayer zu steuern Wischen, um Einstellungen zu ändern - Links oder rechts nach oben oder unten wischen, um die Helligkeit oder Lautstärke zu ändern + Links oder rechts wischen, um die Helligkeit oder Lautstärke zu ändern Nächste Episode automatisch abspielen Nächste Episode wird gestartet, sobald die aktuelle Episode endet Doppeltippen zum vor- und zurückspulen Doppeltippen zum Pausieren - Zeit für vor- und zurückspulen im Player (Sekunden) + Zeit für vor- und zurückspulen im Player Zweimal auf die rechte oder linke Seite tippen, um vor- oder zurückzuspulen - Doppelt in die Mitte tippen, um zu pausieren + In die Mitte tippen, um zu pausieren Systemhelligkeit verwenden Systemhelligkeit anstelle eines dunklen Overlay im Player verwenden Episodenfortschritt aktualisieren @@ -166,7 +166,7 @@ Ausgewählte Videoqualität bei Suchergebnissen ausblenden Automatische Plugin-Updates App-Updates anzeigen - Automatisches Suchen nach neuen Updates nach dem Start + Automatisches Suchen nach neuen Updates beim Start Auf Vorabversionen updaten Suche nach Vorabversionen statt nur nach Vollversionen Github @@ -246,7 +246,7 @@ In Browser wiedergeben Link kopieren Auto-Download - Alternativer Download + Download-Mirror Links neu laden Untertitel herunterladen Qualitätsanzeige @@ -286,7 +286,7 @@ Haftungsausschluss Allgemein Zufalls-Button - Zeigt einen Zufallsbutton auf der Startseite an, mit welchem eine Serie oder ein Film von der Website zufällig ausgewählt wird + Zufallsbutton auf der Startseite anzeigen Anbieter-Sprachen App-Layout Bevorzugte Medien @@ -519,14 +519,14 @@ Start Neustarten Bevorzugte Videoqualität (mobile Daten) - Umgehung der GitHub Sperre mit jsdelivr. Kann zu einigen Tagen Verzögerung bei Updates führen. + Umgehung der GitHub Sperre mit jsdelivr, kann zu einigen Tagen Verzögerung bei Updates führen. %s abonniert %s deabonniert Episode %d erschienen! raw.githubusercontent.com Proxy GitHub kann nicht erreicht werden, der jsdelivr-Proxy wird aktiviert. - Abonnierte Serien werden aktualisiert + Aktualisierung abonnierter Sendungen Rückgängig Abonniert ISP-Umgehungen - + \ No newline at end of file diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index f07ce43c..5e9dafd8 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -1,6 +1,5 @@ - - - + + CloudStream Αρχική Αναζήτηση @@ -388,7 +387,7 @@ Κλείσιμο Εκκαθάριση Γλώσσα υποτίτλων - @string/home_play + \@string/home_play Δεν έχουν παρασχεθεί μεταδεδομένα από τον ιστότοπο, η φόρτωση του βίντεο θα αποτύχει αν δεν υπάρχει στον ιστότοπο. Διπλό πάτημα για παύση Μέγεθος αναζήτησης στο πρόγραμμα αναπαραγωγής @@ -453,7 +452,7 @@ Ανάμεικτοι τίτλοι τέλους -30 Κριτική - @string/ova + \@string/ova Ενημερώσεις εφαρμογής Αντίγραφο ασφαλείας Extensions @@ -465,7 +464,7 @@ Προεπιλεγμένα %s %s Μέγεθος γραμματοσειράς - @string/anime + \@string/anime Σύνδεσμοι Εμφάνιση Χαρακτηριστικά @@ -509,4 +508,4 @@ \nΣυνδέσου σε έναν λογαριασμό που έχει βιβλιοθήκη, ή πρόσθεσε σειρές στην τοπική βιβλιοθήκη σου Βρέθηκε αρχείο Ασφαλούς Λειτουργίας! \nΔεν πρόκειται να φορτωθούν extensions κατά το ξεκίνημα μέχρι να διαγραφεί το αρχείο. - + \ No newline at end of file diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index 5eac8686..09e6941d 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -1,4 +1,4 @@ - + Reen Hejmo @@ -78,4 +78,4 @@ Rapido (%.2fx) Serĉi… Elŝuti - + \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 06c20aa5..18647ef8 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -1,4 +1,4 @@ - + Extensiones Descargue la lista de sitios que quiera utilizar @@ -51,10 +51,10 @@ Elevado Use esto si los subtítulos se muestran %d ms muy pronto Use esto si los subtítulos se muestran %d ms tarde - Desliza el dedo de lado a lado para controlar la posición en un video + Desliza el dedo hacia la izquierda o hacia la derecha para controlar el tiempo en el reproductor de video Filtrar por idioma de medios preferido Eliminar Closed Captions (CC) de los subtítulos - Cantidad de búsquedas del reproductor (segundos) + Cantidad de tiempo de búsqueda en el reproductor (en segundos) Use el brillo del sistema en el reproductor de la app en lugar de una superposición oscura Resolución del reproductor de video MPV @@ -194,7 +194,7 @@ Continuar Viendo Remover Más info - @string/home_play + \@string/home_play Una VPN puede ser necesaria para que este proveedor funcione correctamente Este proveedor es un torrent, se recomienda una VPN El sitio no proporciona los metadatos, la carga del video fallará si no existe en el sitio. @@ -205,16 +205,16 @@ Modo Eigengravy Deslice para avanzar/retroceder Deslice para cambiar la configuración - Deslice hacia arriba o hacia abajo en el lado izquierdo o derecho para cambiar el brillo o el volumen + Deslice el dedo hacia la izquierda o hacia la derecha para cambiar el brillo o el volumen Toca dos veces para buscar Tocar dos veces para pausar Toque dos veces en el lado derecho o izquierdo para buscar hacia adelante o hacia atrás - Toque dos veces en el medio para hacer una pausa + Toque en el medio para pausar Usar brillo del sistema Restaurar datos desde el backup Hacer copia de los datos (backup) Archivo de backup cargado - Busque automáticamente nuevas actualizaciones después de iniciar la aplicación. + Buscar automáticamente nuevas actualizaciones al inicio Rehacer el proceso de configuración inicial Mostrar episodio de relleno para Anime Reproducir Episodio @@ -306,7 +306,7 @@ Aspecto Características Botón de Al azar - Muestra un botón de reproducción \"al azar\" en la página de inicio para poelículas y series + Muestra un botón de reproducción \"al azar\" en la página de inicio cuenta Cerrar sesión Cambiar cuenta @@ -363,8 +363,8 @@ Película Serie Dibujo animado - Anime - OVA + \@string/anime + \@string/ova Torrent Documental Drama asiático @@ -506,11 +506,11 @@ \nInicia sesión en una cuenta de biblioteca o añade series desde tu biblioteca local ¡Se encontró un archivo en modo seguro! \nNo cargar ninguna extensión al inicio hasta que se elimine el archivo. - Reproductor visible - buscar cantidad - Reproductor oculto - buscar cantidad + Jugadora mostrada - buscar cantidad + Jugadora oculta - buscar cantidad Android TV - Tiempo de búsqueda usado (en segundos) cuando el reproductor está visible - Tiempo de búsqueda usado (en segundos) cuando el reproductor está oculto + La cantidad de búsqueda utilizada cuando la jugadora es visible + La cantidad de búsqueda utilizada cuando el jugador está oculto Parar Falló Registro @@ -525,8 +525,8 @@ ¡Episodio %d publicado! Proxy raw.githubusercontent.com No se ha podido acceder a GitHub, activando el proxy jsdelivr. - Con jsdelivr, se puede omitir el bloqueo de GitHub. Puede retrasar las actualizaciones unos días. + Evita el bloqueo de GitHub usando jsdelivr, puede causar que las actualizaciones se retrasen unos días. Revertir ISP Bypasses Calidad de visualización preferida (Datos móviles) - + \ No newline at end of file diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index e4c23628..81853674 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -1,4 +1,4 @@ - + حذف مکث @@ -33,4 +33,4 @@ %dساعت %dدقیقه %dدقیقه پوستر اصلی - + \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index b96ff0cd..18255b3b 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -1,6 +1,5 @@ - - - + + CloudStream Accueil Rechercher @@ -131,7 +130,7 @@ Nouvelle mise à jour trouvée ! \n%s -> %s Épisode spécial - Qualité de visionnage préférée (WiFi) + Qualité de visionnage préférée Taille de la mémoire cache Étendre Non-responsabilité @@ -241,7 +240,7 @@ Continuer à regarder Retirer Plus d\'informations - @string/home_play + \@string/home_play Un VPN peut être nécessaire pour que ce fournisseur fonctionne correctement Ce fournisseur est un torrent, un VPN est recommandé Les métadonnées ne sont pas fournies par le site, le chargement de la vidéo échouera si elles n\'existent pas sur le site. @@ -386,8 +385,8 @@ 4K Web -30 - @string/anime - @string/ova + \@string/anime + \@string/ova NSFW %s %s Filtrez par langue préférée @@ -509,19 +508,4 @@ Mis à jour (ancien vers nouveau) Fichier du mode sans échec trouvé ! \nAucune extension ne sera chargée au démarrage avant que le fichier ne soit enlevé. - Arrêter - Revenir à - Enregistrer - Qualité de visionnage préférée (données mobiles) - Abonné à %s - Démarrer - Test des fournisseurs - Réussi - Désabonné de %s - Redémarrer - Abonné - raw.githubusercontent.com Proxy - Contournements de FAI - L\'épisode %d est sorti ! - Échouer - + \ No newline at end of file diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 833b76f4..f33a2336 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -1,6 +1,5 @@ - - - + + रफ्तार (%.2fx) नया अपडेट आया है! @@ -147,4 +146,4 @@ %dh %dm %dm विज्ञापन - + \ No newline at end of file diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index b4931377..b623ec5d 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -1,6 +1,5 @@ - - - + + %d %s | %s %s • %s @@ -120,7 +119,7 @@ Nastavite s gledanjem Makni Više informacija - @string/home_play + \@string/home_play Za ispravan rad ovog pružatelja usluga može biti potreban VPN Ovaj pružatelj usluga je torrent, preporučuje se VPN Stranica ne daje metapodatke, učitavanje videozapisa neće uspjeti ako ne postoji na stranici. @@ -139,16 +138,16 @@ Eigengravy način Dodaje opciju brzine u playeru Prijeđi prstom za traženje - Prijeđite prstom ulijevo ili udesno kako biste kontrolirali player + Prijeđi prstom ulijevo ili udesno za kontrolu vremena u videoplayeru Klizni za promjenu postavki - Kliznite prstom ulijevo ili udesno za promjenu svjetline ili glasnoće + Prijeđi prstom ulijevo ili udesno za promjenu svjetline ili glasnoće Automatski započni sljedeću epizodu Započne sljedeću epizodu kad trenutna završi Dodirni dvaput za traženje Dodirni dvaput za pauziranje - Iznos preskakanja u playeru (Sekunde) + Iznos preskakanja u playeru Dvaput dodirni desnu ili lijevu stranu ekrana za pomicanje naprijed ili natrag - Dodirnite dvaput u sredinu zaslona za pauziranje + Dodirni u sredinu zaslona za pauziranje Koristi svijetlinu u sustavu Koristi svjetlinu sustava u playeru aplikacija umjesto tamnog preklopa Ažuriraj napredak gledanja @@ -174,7 +173,7 @@ Sakrij odabranu kvalitetu videozapisa u rezultatima pretraživanja Automatsko ažuriranje dodataka Prikaži ažuriranja aplikacije - Automatski traži nova ažuriranja nakon pokretanja aplikacije + Automatski traži nova ažuriranja pri pokretanju aplikacije Ažuriranje na predizdanja Tražite ažuriranja prije izdanja umjesto samo potpunih izdanja Github @@ -239,8 +238,8 @@ Film Serija Crtić - Anime - OVA + \@string/anime + \@string/ova Torrent Dokumentarac Azijska drama @@ -300,7 +299,7 @@ Any legal issues regarding the content on this application should be taken up with the actual file hosts and providers themselves as we are not affiliated with them. In case of copyright infringement, please directly contact the responsible parties or the streaming websites. The app is purely for educational and personal use. CloudStream 3 does not host any content on the app, and has no control over what media is put up or taken down. CloudStream 3 functions like any other search engine, such as Google. CloudStream 3 does not host, upload or manage any videos, films or content. It simply crawls, aggregates and displayes links in a convenient, user-friendly interface. It merely scrapes 3rd-party websites that are publicly accessable via any regular web browser. It is the responsibility of user to avoid any actions that might violate the laws governing his/her locality. Use CloudStream 3 at your own risk. Općenito Random gumb - Prikazuje gumb na početnoj stranici koji može odabrati nasumični film ili TV seriju s početne stranice + Prikaži random gumb na početnoj stranici Jezici pružatelja usluga Izgled aplikacije Preferirani mediji @@ -553,6 +552,5 @@ ISP zaobilaznice raw.githubusercontent.com Proxy Neuspješno dohvaćanje GitHuba, omogućavanje jsdelivr proxyja. - Koristeći jsdelivr, GitHub blokiranje se može zaobići. Može odgoditi ažuriranja za nekoliko dana. - Preferirana kvaliteta gledanja (podatkovna mobilna mreža) - + Zaobilazi blokiranje GitHuba pomoću jsdelivr, može uzrokovati odgode ažuriranja za nekoliko dana. + \ No newline at end of file diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 1389dff0..5b42fd6a 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -1,4 +1,4 @@ - + Stáblista: %s %dn %dó%dp @@ -57,7 +57,7 @@ Megnyitás böngészőben Betöltés kihagyása Poster - @string/result_poster_img_des + \@string/result_poster_img_des Nézés Befejezve Később megnézés @@ -111,7 +111,7 @@ Betűtípusok importálása %s Eltávolítás Több információ - @string/home_play + \@string/home_play VPN szükséges lehet ehhez a szolgáltató megfelelő működéséhez Ez a szolgáltató torrent, VPN ajánlott Leírás @@ -172,11 +172,11 @@ OVA Egyebek Sorozat - @string/anime + \@string/anime Forráshiba NSFW Rajzfilm - @string/ova + \@string/ova Élőadás NSFW Videó @@ -275,4 +275,4 @@ Minőségi jelzés Szinkroncímke Alcímke - + \ No newline at end of file diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 02234c49..84179352 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -1,6 +1,5 @@ - - - + + %s Ep %d Pemeran: %s @@ -102,7 +101,7 @@ Lanjutkan Menonton Hapus Info lebih lanjut - @string/home_play + \@string/home_play Sebuah VPN mungkin diperlukan agar provider ini bisa bekerja dengan benar Provider ini adalah sebuah torrent, VPN direkomendasikan Metadata tidak disediakan oleh situs, loading video akan gagal jika tidak ada di situs. @@ -121,14 +120,14 @@ Mode Eigengravy Menambahkan opsi kecepatan di pemutar Geser untuk mengubah waktu - Geser dari sisi ke sisi untuk mengontrol posisi dalam video + Geser ke kiri atau kanan untuk mengontrol waktu di pemutar video Geser untuk mengubah pengaturan - Geser ke atas atau ke bawah di sisi kiri atau kanan untuk mengubah kecerahan atau volume + Geser ke sisi kiri atau kanan untuk mengubah pencerahan atau volume Tekan dua kali untuk mengubah waktu Tekan dua kali untuk menjeda - Jumlah pengubah waktu pemutar (Detik) + Jumlah pengubah waktu pemutar Tekan dua kali di sisi kanan atau kiri untuk mengubah waktu ke depan atau ke belakang - Tekan dua kali di tengah untuk menjeda + Tekan di tengah untuk menjeda Gunakan pencerahan sistem Gunakan pencerahan sistem di pemutar aplikasi dari pada hamparan gelap Update progres tontonan @@ -150,7 +149,7 @@ Tidak mengirim data Tampilkan episode filler untuk anime Tampilkan update aplikasi - Secara otomatis mencari update terbaru setelah aplikasi dibuka. + Secara otomatis mencari update terbaru saat aplikasi dibuka Update ke prarilis Hanya mencari update prarilis daripada rilis penuh Github @@ -210,8 +209,8 @@ Movie Seri Kartun - Anime - OVA + \@string/anime + \@string/ova Torrent Film Dokumenter Drama Asia @@ -244,7 +243,7 @@ Jangan tunjukkan lagi Skip Update ini Update - Kualitas tontonan yang lebih diinginkan (WIFI) + Kualitas tontonan yang lebih diinginkan Karakter maksimal judul pemutar video Resolusi pemutar video Ukuran buffer video @@ -265,7 +264,7 @@ Any legal issues regarding the content on this application should be taken up with the actual file hosts and providers themselves as we are not affiliated with them. In case of copyright infringement, please directly contact the responsible parties or the streaming websites. The app is purely for educational and personal use. CloudStream 3 does not host any content on the app, and has no control over what media is put up or taken down. CloudStream 3 functions like any other search engine, such as Google. CloudStream 3 does not host, upload or manage any videos, films or content. It simply crawls, aggregates and displayes links in a convenient, user-friendly interface. It merely scrapes 3rd-party websites that are publicly accessable via any regular web browser. It is the responsibility of user to avoid any actions that might violate the laws governing his/her locality. Use CloudStream 3 at your own risk. Umum Tombol Acak - Tampilkan tombol di halaman utama yang dapat memilih seri film atau TV acak dari halaman utama + Tampilkan tombol acak di Beranda Bahasa provider Tata Letak Aplikasi Media yang lebih diinginkan @@ -549,8 +548,7 @@ Episode %d telah rilis! raw.githubusercontent.com Proksi Gagal mencapai GitHub, mengaktifkan proksi jsdelivr. - Mengunakan jsdelivers, bisa melewati pemblokiran GitHub. Mungkin dapat menyebabkan pembaruan tertunda dalam beberapa hari. + Bypass pemblokiran Github menggunakan JSDeliVR, dapat menyebabkan pembaruan tertunda beberapa hari. Bypass ISP Pulihkan - Nonton dengan kualitas yang di inginkan (Data Seluler) - + \ No newline at end of file diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index eca60da1..d6bdc204 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -1,6 +1,5 @@ - - - + + %s Ep %d Cast: %s @@ -109,7 +108,7 @@ Continua a guardare Rimuovi Più info - @string/home_play + \@string/home_play Potrebbe essere necessaria una VPN per far funzionare correttamente questo provider Questo provider è un torrent, si raccomanda una VPN I metadati non sono forniti dal sito, il caricamento del video fallirà se non esiste sul sito. @@ -266,7 +265,7 @@ Non mostrare di nuovo Salta questo aggiornamento Aggiorna - Qualità di visualizzazione preferita (WiFi) + Risoluzione preferita Limita i caratteri del titolo nel player Risoluzione video player Dimensione cache video @@ -551,5 +550,4 @@ Ripristina Aggiornando shows a cui sei iscritto L\'episodio %d è stato rilasciato! - Qualità di visualizzazione preferita (Dati mobili) - + \ No newline at end of file diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index b24f0c60..11cf77ce 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -1,4 +1,4 @@ - + הרקע של ההצגה לפני צוות שחקנים: %s @@ -116,7 +116,7 @@ כתוביות כרומקאסט ממשיך ניגון בנגן מינימלי מעל ישומים אחרים כתוביות - @string/home_play + \@string/home_play היסטוריה מורשת לא @@ -164,8 +164,8 @@ משומש סדרת טלוויזיה סדרות/סרטים מצוירים - @string/anime - @string/ova + \@string/אנימה + \@string/אנימציית וידאו מקורית דרמה אסייתית כרומקאסט את הפרק כרומקאסט את המראה @@ -506,4 +506,4 @@ אלפביתי (ת\' עד א\') פתח עם נראה שהרשימה הזו ריקה, נסו לעבור לרשימה אחרת - + \ No newline at end of file diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 20641b20..a3d1d434 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -1,4 +1,4 @@ - + %d分 ダウンロード @@ -182,4 +182,4 @@ アップデートを確認 作品名 アプリのアップデートをインストール中… - + \ No newline at end of file diff --git a/app/src/main/res/values-kn/strings.xml b/app/src/main/res/values-kn/strings.xml index 4b7b6869..242653be 100644 --- a/app/src/main/res/values-kn/strings.xml +++ b/app/src/main/res/values-kn/strings.xml @@ -1,4 +1,4 @@ - + %sಎಪಿ%d ಕ್ಯಾಸ್ಟ್:%s @@ -125,4 +125,4 @@ ಡೌನ್‌ಲೋಡ್ ಪ್ರಾರಂಭವಾಗಿದೆ ಡೌನ್‌ಲೋಡ್ ರದ್ದುಗೊಳಿಸಲಾಗಿದೆ ಮುಂದಿನ ರಾಂಡಮ್ - + \ No newline at end of file diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index 811a09c5..7251d0d7 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -1,6 +1,5 @@ - - - + + Брзина (%.2fx) Оценето: %.1f @@ -214,4 +213,4 @@ Сенка Подигнат Историја - + \ No newline at end of file diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml index d430d7cc..b6ad3a80 100644 --- a/app/src/main/res/values-ml/strings.xml +++ b/app/src/main/res/values-ml/strings.xml @@ -1,6 +1,5 @@ - - - + + വേഗം (%.2fx) റേറ്റിംഗ്: %.1f @@ -170,4 +169,4 @@ ഔചിത്യ വീഡിയോ ക്വാളിറ്റി ചരിത്രം കണ്ടതാണെന്ന് അടയാളപ്പെടുത്തുക - + \ No newline at end of file diff --git a/app/src/main/res/values-ms/strings.xml b/app/src/main/res/values-ms/strings.xml deleted file mode 100644 index c757504a..00000000 --- a/app/src/main/res/values-ms/strings.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 766bcdc7..c2561914 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -1,6 +1,5 @@ - - - + + %s Ep %d Cast: %s @@ -10,7 +9,7 @@ %dm Poster - Poster + \@string/result_poster_img_des Aflevering Poster Hoofdposter Volgende willekeurig @@ -110,7 +109,7 @@ Doorgaan met kijken Verwijder Meer Info - @string/home_play + \@string/home_play Een VPN kan nodig zijn om deze provider correct te laten werken Deze provider is een torrent, een VPN wordt aanbevolen Metadata wordt niet geleverd door de site, het laden van video\'s zal mislukken als deze niet op de site bestaat. @@ -129,14 +128,14 @@ Eigengravy Modus Voegt een snelheidsoptie toe in de speler Swipe to seek - Veeg naar links of rechts om de tijd in de videospeler te regelen + Veeg naar links of rechts om de tijd in de videoplayer te regelen Veeg om instellingen te wijzigen Veeg naar links of rechts om de helderheid of het volume te wijzigen Dubbeltik om te zien Dubbeltik om te pauzeren - Videospeler aantal zoeken + Speler zoeken bedrag Tik twee keer aan de rechter- of linkerkant om vooruit of achteruit te zoeken - Tik twee keer in het midden om te pauzeren + Tik in het midden om te pauzeren Systeemhelderheid gebruiken Gebruik systeemhelderheid in de app-speler in plaats van een donkere overlay Kijkvoortgang bijwerken @@ -223,8 +222,8 @@ Film Serie Tekenfilm - @string/anime - @string/ova + \@string/anime + \@string/ova Torrent Documentaire Aziatisch drama @@ -406,7 +405,4 @@ Start de volgende episode wanneer deze afgelopen is Volgende episode automatisch afspelen De update is gestart - Bibliotheek - Browser - Logboek - + \ No newline at end of file diff --git a/app/src/main/res/values-nn/strings.xml b/app/src/main/res/values-nn/strings.xml index 43738665..b5132028 100644 --- a/app/src/main/res/values-nn/strings.xml +++ b/app/src/main/res/values-nn/strings.xml @@ -1,4 +1,4 @@ - + Fleire val Heim @@ -183,4 +183,4 @@ Varigheit Direktesendingar Programoppdateringar - + \ No newline at end of file diff --git a/app/src/main/res/values-no/strings.xml b/app/src/main/res/values-no/strings.xml index fddd4919..41bf704d 100644 --- a/app/src/main/res/values-no/strings.xml +++ b/app/src/main/res/values-no/strings.xml @@ -1,8 +1,8 @@ - + Plakat - @string/result_poster_img_des + \@string/result_poster_img_des Episode Plakat Main Plakat Neste tilfeldig @@ -412,7 +412,7 @@ Slå av/på grensesnittselementer på plakat Hopp over denne oppdateringen Forårsaker tilfeldige krasj hvis satt for høyt. Ikke endre dette hvis du ikke har lite minne. - @string/home_play + \@string/home_play Sikkerhetskopier data Data lagret Kunne ikke logge inn på %s @@ -422,11 +422,11 @@ Sensurerbart Vev Lenke til strøm - @string/anime + \@string/anime Skjul valgt videokvalitet i søkeresultater Lastet inn sikkerhetkopifil Oppdateringer og sikkerhetskopi - @string/ova + \@string/ova Avslutt\? Sensurerbart Alle %s er allerede nedlastet @@ -492,4 +492,4 @@ Oppdatering startet Programtillegg nedlastet Programmet vil oppgraderes når du avslutter det - + \ No newline at end of file diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index a2a07dd7..bbaaec57 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -1,6 +1,5 @@ - - - + + Prędkość (%.2fx) Ocena: %.1f Znaleziono nową aktualizację! @@ -255,7 +254,7 @@ Nie pokazuj ponownie Pomiń tę aktualizację Aktualizacja - Domyślna jakość (WiFi) + Domyślna jakość Maksymalna ilość znaków w tytule odtwarzacza Rozdzielczość odtwarzacza wideo Rozmiar bufora wideo @@ -456,7 +455,7 @@ Instalator APK Niektóre telefony nie obsługują nowego instalatora pakietów. Wypróbuj tryb legacy, jeśli aktualizacje nie zostaną zainstalowane. password123 - @string/ova + \@string/ova MojaFajnaWitryna MyCoolUsername 127.0.0.1 @@ -464,9 +463,9 @@ przyklad.pl /\?\? Instalator pakietów - @string/home_play + \@string/home_play hello@world.com - @string/anime + \@string/anime Opening Ending Mixed opening @@ -532,5 +531,4 @@ Został wydany odcinek %d! Obchodzi blokadę GitHuba za pomocą jsdelivr, może spowodować opóźnienie aktualizacji o kilka dni. Nie udało się połączyć z GitHub, włączono serwer pośredniczący jsdelivr. - Domyślna jakość (dane mobilne) - + \ No newline at end of file diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index dd722f62..3754de8b 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -1,65 +1,65 @@ - + %s Ep %d %dh %dm %dm - O episódio %d será lançado em + Episódio %d será lançado em Poster - Pôster do episódio + Capa do Episódio Poster - Pôster Principal + Capa Principal Próximo Aleatório Voltar - Alterar Provedor - %dd %dh %dm + Trocar Provedor + %d dia(s), %d hora(s) e %d mese(s) Fonte Resolução Extras - Visualizar plano de fundo + Preview Background Velocidade (%.2fx) Classificado: %.1f Nova atualização encontrada! \n%s -> %s - Preenchimento + Enchimento CloudStream - Assistir com o CloudStream + Reproduzir com CloudStream Início - Pesquisar - Downloads - Configurações + Pesquisa + Transferências + Opções Procurar… - Pesquisar %s… - Sem dados - Mais opções + Procurar em %s… + Sem Dados + Mais Opções Próximo episódio - Gêneros - Compartilhar - Abrir no navegador - Pular carregamento + Géneros + Partilhar + Abrir no Navegador + Saltar Carga Carregando… Assistindo - Em espera + Em Espera Concluído - Desistido - Pretendo assistir - Nenhum - Reassistindo - Reproduzir filme - Reproduzir transmissão ao vivo + Abandonado + Planeio Assistir + Nenhuma + Assistindo de Novo + Reproduzir Filme + Reproduzir Livestream Transmitir Torrent Fontes Legendas - Tentar conexão novamente… - Voltar - Reproduzir episódio - Download - Baixado - Baixando - Download Pausado - Download Iniciado - Falha no Download - Download cancelado - Download concluído + Voltar a tentar ligação… + Voltar Atrás + Reproduzir Episódio + Transferir + Transferido + A Transferir + Transferência em Pausa + Transferência Iniciada + Transferência Falhou + Transferência Cancelada + Transferência Completa Stream Erro a Carregar Links Armazenamento Interno @@ -123,16 +123,16 @@ Modo Eigengravy Acrescenta uma opção de velocidade no player Deslize para andar - Deslize para os lados para controlar a posição em um vídeo + Deslize para a esq. ou dir. para controlar o tempo no player Deslize para mudar as configurações - Deslize para cima ou para baixo, no lado esquerdo ou direito, para ajustar brilho ou volume + Deslize do lado esq. ou dir. para ajustar brilho ou volume Reproduzir automaticamente próximo episódio Começa o próximo episódio quando o atual termina Toque duplo para avançar Toque duplo para pôr em pausa - Tempo de busca no player (Segundos) + Segundos avançados no player Toque duplo no lado esq. ou dir. para andar para trás ou para a frente - Toque duas vezes no meio para pausar + Toque no meio para pôr em pausa Usar brilho da sistema Usar brilho do sistema no player em vez de uma sobreposição escura Atualizar progresso @@ -142,7 +142,7 @@ Arquivo de backup carregado Falha ao restaurar dados do ficheiro %s Dados guardados com sucesso - Permissão de armazenamento não encontrada, por favor tente novamente. + Permissões de armazenamento em falta, por favor tente de novo Erro no backup de %s Procurar Contas @@ -158,7 +158,7 @@ Esconder qualidades de vídeo selecionadas nos resultados da Pesquisa Atualizações de plugin automáticas Mostrar atualizações da app - Procurar automaticamente por novas atualizações depois de iniciar o app. + Procurar novas atualizações automaticamente ao iniciar Atualizar para pré-lançamentos Procura atualizações de pré-lançamento em vez de só lançamentos oficiais Github @@ -250,15 +250,15 @@ Não mostrar de novo Saltar esta Atualização Atualizar - Qualidade Preferida (WiFi) - Máximo de caracteres do título no player de video + Qualidade Preferida + Máximo de caracteres do título de vídeos Resolução do player de vídeo Tamanho do buffer do vídeo Comprimento do buffer do vídeo Cache do vídeo em disco Limpar cache de vídeo e imagem - Causará travamentos em dispositivos com pouca memória se definido muito alto , como uma Android TV. - Pode causar problemas em sistemas com pouco espaço de armazenamento se definido muito alto, como uma Android TV. + Causará travamentos aleatórios se definido muito alto. Não mude se tiver pouca memória RAM, como um Android TV ou um telefone antigo + Pode causar problemas em sistemas com pouco espaço de armazenamento se definido muito alto, como em dispositivos Android TV DNS sobre HTTPS Útil para contornar bloqueios do fornecedor de internet Clonar site @@ -273,7 +273,7 @@ Aviso Legal Geral Botão Aleatório - Mostra o botão Aleatório na página inicial, que pode escolher aleatoriamente um filme ou série + Mostra o botão Aleatório na página inicial Idioma dos fornecedores Layout da App Mídia preferida @@ -363,7 +363,7 @@ Plugin Carregado Plugin Apagado Falha ao carregar %s - Download iniciado %d %s… + Iniciada a transferência %d %s Transferido %d %s com sucesso Tudo %s já transferido Transferência em batch @@ -375,22 +375,18 @@ Transferido: %d Desativado: %d Não transferido: %d - O CloudStream não possui sites instalados por padrão. Você precisa instalar os sites a partir de repositórios. -\n -\nDevido a uma restrição sem sentido de direitos autorais (DMCA) pela Sky UK Limited 🤮 não podemos vincular o site do repositório no aplicativo. -\n -\nJunte-se ao nosso Discord ou pesquise online. + Adicionar um repositório para instalar extensões de sites Ver repositórios da comunidade Lista pública Todas as legendas em maiúsculas Transferir todos os plugins deste repositório\? %s (Desativado) Instalador APK - %d min - Assistir Trailer + %d minuto(s) + Reproduzir trailer Marcar como visto/não visto Reproduzir - Instalar automaticamente todos os plugins ainda não instalados dos repositórios adicionados. + Instalar automaticamente todas as extensões dos repositórios cadastrados. Baixar extensões automaticamente Refazer o processo de configuração -30 @@ -398,9 +394,9 @@ +30 %s %d%s Elenco: %s - Atualização iniciada + Atualização em andamento Log - Alguns aparelhos não suportam o novo instalador de pacotes. Use a opção legado caso não esteja conseguindo atualizar. + Alguns aparelhos não possuem suporte para o novo instalador de pacotes. Use a opção legado caso não esteja conseguindo atualizar. %d-%d %d %s Iniciar @@ -412,121 +408,4 @@ Ova Anime Player visível - Procurar valor - Instalando atualização do app… - Você tem certeza que deseja sair\? - Versão - Encerramento - Limpar histórico - Abertura - Não - Ordenar por - Sim - Baixando atualização do app… - Episódio %d lançado! - Créditos - Descrição - Tamanho - Parar - Modo seguro ligado - Histórico - Ordenar - Player interno - Autores - Suportado - Idioma - Instalar a extensão primeiro - Playlist HLS - Player de vídeo preferido - Estado - Gestos - Faixas - WP - Cam - Abertura - Selecionar Biblioteca - Usando jsdelivr o bloqueio do GitHub pode ser contornado. Pode atrasar atualizações em alguns dias. - VLC - Todas as linguagens - Atualizado (Novo para Antigo) - Inscrito - HDR - Reiniciar - Navegador Web - Atualizado (Antigo para Novo) - Web Video Cast - DVD - Instalador de pacotes - MPV - Remover dos assistidos - Não foi possível instalar a nova versão do aplicativo - Inscrição cancelada em %s - Final misto - Avaliações (Decrescente) - Aplicar ao reiniciar - Referente - Player oculto - Quantidade de Busca - raw.githubusercontent.com Proxy - Blu-ray - Aparência - 1000 ms - SDR - 18+ - Abrir com - Teste de provedor - UHD - Ver informações sobre falha - Aplicativo não encontrado - Reverter - Link para transmitir - Plugins baixados - %d plugins atualizados - Pular %s - Abertura mista - Alfabético (Z a A) - Parece que esta lista está vazia, tente trocar para outra - Inscrito em %s - 4K - Faixas de vídeo - O aplicativo será atualizado ao sair - Atualizando shows inscritos - Alfabético (A a Z) - Avaliações (Crescente) - Parece que a sua biblioteca está vazia :( -\nFaça login em uma conta de biblioteca ou adicione shows à sua biblioteca local - Arquivo de modo de segurança encontrado! -\nNenhuma extensão será carregada na inicialização do app até que o arquivo seja removido. - Contorno do provedor de serviço de internet (ISP) - Links - Recursos do Player - Recursos - Atualizações de aplicativos - Qualidade Preferida (Dados Móveis) - Quantidade de busca (em segundos) usada quando o player de video está visível - Quantidade de busca (em segundos) usada quando o player de video está oculto - Falha ao conectar com GitHub, ativando proxy jsdelivr. - Cache - Android TV - Legendas - %s %s - TS - Cam - Cam - HQ - HD - TC - Web - Nota: %s - Legado - Todas as extensões foram desativadas devido a uma falha para ajudá-lo a encontrar a que está causando o problema. - Recapitular - Mostrar pop-ups para pular abertura/encerramento - Muito texto. Não é possível salvar na área de transferência. - Marcar como assistido - Backup - Extensões - Ações - Layout - Configurações padrão - SD - Faixas de áudio - + \ No newline at end of file diff --git a/app/src/main/res/values-qt/strings.xml b/app/src/main/res/values-qt/strings.xml index eee28785..c1119bfc 100644 --- a/app/src/main/res/values-qt/strings.xml +++ b/app/src/main/res/values-qt/strings.xml @@ -1,4 +1,4 @@ - + aauugghhaauuh @@ -219,33 +219,4 @@ uuuuhhhoouuooog ooaaahhhh uuu ugggg ooo guggg ooh - auuuooohaaaaagh - uuuuuuuh aaaoo o - ooooooouuuua aa aaagh agh - AAAAUUUOH - aoughoooaaaa - oooouuuh - ahaough aaouuuuh-h - auughooo - ooooooa aauoh - aaaaagh oouoo aaaaaaa - aaaaaagh uuohuoh - aaaaaauo agghhhhhhaoouu - uuuuuuuuh - ouaaahh - ooough aaoough aooou %s aaaa - ouooooouuuu oooooo - aaaaaaaaaaahhhgh-aooohoooo - aau aooooghaao - aagh aaaaaaaaaaaa oooh, aaough, ooga oguuu aaaaaaaaaaa ooooooohghh a-a-aaauo - %dmmmmmm.. -\naaaaooughugh - aooohuohaaaa ooooagh - oooooogh-aaaaaogh - guuuaaaahhhhhhhaaa - woooaaahh ahahaaaauu 🦍 - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOOOGGAGHAGHAAA - aoaaaaaoooghhh - oooooh uuaagh - @string/home_play - + \ No newline at end of file diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index aa443783..42d9b7c8 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -1,6 +1,5 @@ - - - + + %s Ep %d Distribuție: %s @@ -107,7 +106,7 @@ Continuați să urmăriți Eliminați Mai multe informații - @string/home_play + \@string/home_play Există probabilitatea necesitații unui VPN pentru ca acest furnizor să funcționeze corespunzător Acest furnizor este un torrent, se recomandă un VPN Metadatele nu sunt furnizate de către site, există posibilitatea ca încărcarea videoclipului să eșueze. @@ -389,4 +388,4 @@ Log Browser Joacă cu CloudStream - + \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 9d8f6895..2812667a 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -1,4 +1,4 @@ - + История Нет @@ -142,10 +142,10 @@ Добавляет опцию скорости в проигрывателе Проведите пальцем для поиска Проведите пальцем для изменения настроек - Проведите вверх или вниз по левой или правой стороне, чтобы изменить яркость или громкость + Проведите пальцем по левой или правой стороне для изменения яркости или громкости Автопроиграть следующего серия Поток торрент - Проведите пальцем из стороны в сторону, чтобы управлять свое место в видеоролике + Проведите пальцем влево или вправо, чтобы управлять временем в видеоплеере Начните следующий серию, когда закончится текущий Загружена резервная копия Не удалось восстановить данные из %s @@ -159,7 +159,7 @@ Автоматическое обновление плагинов Автоматическая загрузка плагинов Показать обновления приложения - Автоматически проверять обновления при старте приложения. + Автоматически проверять обновления при старте Обновится до пре-релиза APK установщик Github @@ -227,7 +227,7 @@ Использовано Двойное нажатие для паузы Коснитесь дважды правой или левой стороны для поиска вперед или назад - Нажмите дважды в центре, чтобы сделать паузу + Нажмите в центре для паузы Использовать системную яркость Автоматически синхронизировать текущий прогресс эпизода Ошибка резервного копирования %s @@ -318,7 +318,7 @@ Титры Отметить как просмотренное Разрешение видеоплеера - Предпочтительное качество видео (WiFi) + Желаемое качество видео Максимум символов Длинна буфера Кеш видео на диске @@ -363,7 +363,7 @@ Расширения URL репозитория Плагин загружен - @string/home_play + \@string/home_play Перемотка двойным нажатием /\?\? /%d @@ -408,8 +408,8 @@ Съешь ещё этих мягких французских булок, да выпей же чаю Рекомендуется Загружено %s - Аниме - OVA + \@нить/аниме + \@нить/ova Этикетка Dub Сайт Функции @@ -493,7 +493,7 @@ Фильтровать по предпочитаемому языку медиа Неверный ID Ссылка на стрим - Показывает кнопку на главной странице, с помощью которой можно выбрать случайный фильм или сериал с главной страницы + Отображать рандомную кнопку на Главной странице Рандомная кнопка Legacy (старый) Веб видеокаст @@ -501,7 +501,7 @@ Перезагрузить ссылки Предпочтительные медиа Опущенные - Объем перемотки плеера (секундах) + Объем перемотки плеера Объем перемотка, используемый, когда плеер виден Плеер показан - Перемотки объем Плеер спрятан - Перемотки объем @@ -518,15 +518,4 @@ Неудачный Прекратить Перезапустить - Вернуться - Подписался на %s - Предпочтительное качество видео (Мобильный интернет) - raw.githubusercontent.com Прокси-сервер - Не удалось подключиться к GitHub. Будет выполнен прокси jsdelivr. - Эпизод %d выпущен! - Обходы провайдера - Обновление подписки на фильмы и сериалы - Обход ограничения доступа к GitHub с помощью jsdelivr может задержать обновления на несколько дней. - Подписные - Отказались от подписки на %s - + \ No newline at end of file diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index a1afd6d9..66d8ada9 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -1,4 +1,4 @@ - + Našla sa nová aktualizácia! \n%s -> %s @@ -99,9 +99,9 @@ Tento poskytovateľ je torrent, odporúča sa VPN Importovať písma ich umiestnením do %s Viac informácií - @string/home_play + \@string/home_play Pokračovať v sledovaní Na správne fungovanie tohto poskytovateľa môže byť potrebná VPN Stránka neposkytla žiadne metadáta, načítanie videa zlyhá, ak na stránke neexistuje. Popis - + \ No newline at end of file diff --git a/app/src/main/res/values-so/strings.xml b/app/src/main/res/values-so/strings.xml index ce7d557a..b944b6b3 100644 --- a/app/src/main/res/values-so/strings.xml +++ b/app/src/main/res/values-so/strings.xml @@ -1,4 +1,4 @@ - + Metalaya: %s %dm %ds %dd @@ -487,4 +487,4 @@ Bilowga Bilow isku qasan Qoraalka dhamaadka - + \ No newline at end of file diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 0b7ba89e..32336b66 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -1,6 +1,5 @@ - - - + + Betygsatt: %.1f Hastighet (%.2fx) Ny uppdatering hittad! @@ -34,7 +33,7 @@ Undertexter Försök ansluta igen… Gå tillbaka - @string/result_poster_img_des + \@string/result_poster_img_des Spela Avsnitt Ladda ner Intern lagring @@ -45,7 +44,7 @@ Inaktivera automatisk felrapportering Mer information Hide - @string/result_poster_img_des + \@string/result_poster_img_des Spela upp Info Nästa @@ -236,7 +235,7 @@ Episod %d kommer släppas om %d min Visa trailers - @string/home_play + \@string/home_play OVA %d-%d %d %s @@ -245,7 +244,7 @@ %dm \nåterstår NSFW - @string/ova + \@string/ova Torrent NSFW +30 @@ -274,7 +273,7 @@ Asiatiska draman Andra Tecknade serier - @string/anime + \@string/anime Dokumentär Asiatisk drama Video @@ -369,4 +368,4 @@ Titta på videor på dessa språk Föregående Spår - + \ No newline at end of file diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml index 4370e760..b2334c5f 100644 --- a/app/src/main/res/values-ta/strings.xml +++ b/app/src/main/res/values-ta/strings.xml @@ -1,4 +1,4 @@ - + தேடுக தேடல் %s… @@ -107,4 +107,4 @@ இடைநிறுத்துவதற்கு இருமுறை தட்டவும் Chromecast வசன அமைப்புகள் இருண்ட மேலடுக்குக்குப் பதிலாக ஆப் பிளேயரில் சிஸ்டம் பிரகாசத்தைப் பயன்படுத்தவும் - + \ No newline at end of file diff --git a/app/src/main/res/values-tl/strings.xml b/app/src/main/res/values-tl/strings.xml index cf3b1263..9e5b29d4 100644 --- a/app/src/main/res/values-tl/strings.xml +++ b/app/src/main/res/values-tl/strings.xml @@ -1,12 +1,11 @@ - - - + + %s Ep %d Poster - @string/result_poster_img_des + \@string/result_poster_img_des Episode Poster Main Poster Next Random @@ -264,4 +263,4 @@ Magdagdag ng Account Kasaysayan I-tanda bilang napanood na - + \ No newline at end of file diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 74754008..807716d8 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -1,6 +1,5 @@ - - - + + %d %s | %s %s • %s @@ -24,9 +23,9 @@ Bölüm Posteri Ana Poster Sonraki Rastgele - @string/play_episode + \@string/play_episode Geri git - @string/home_change_provider_img_des + \@string/home_change_provider_img_des Change Provider Preview Background @@ -47,7 +46,7 @@ Veri yok Daha fazla seçenek Sonraki bölüm - @string/synopsis + \@string/synopsis Türler Paylaş Tarayıcıda aç @@ -118,47 +117,47 @@ Hiç muz verilmedi Otomatik seçilecek dil İndirilecek diller - Altyazı dili - Sıfırlamak için basılı tut + Alt yazı dili + Varsayılana döndürmek için basılı tut Fontları içe aktarmak için %s konumuna yerleştirin İzlemeye devam et Kaldır Daha fazla bilgi - @string/home_play + \@string/home_play Bu sağlayıcının düzgün çalışması için bir VPN gerekebilir - Bu sağlayıcı torrent kullanıyor, bir VPN önerilir + Bu sağlayıcı bir torrent. VPN önerilir Metadata site tarafından sağlanmamış, veri site\'de bulunmuyorsa video yüklenmesi başarısız olacak. Açıklama Konu bulunamadı Açıklama bulunamadı - Logcat\'i görüntüle 🐈 - Görüntü içinde görüntü - İçerik diğer uygulamaların üzerinde küçük bir pencerede oynatılmaya devam eder + Logcat\'i göster 🐈 + Resim-içinde-resim + Diğer uygulamaların üzerinde minyatür bir oynatıcıda oynatmaya devam eder Oynatıcı yeniden boyutlandırma butonu - Siyah sınır çizgilerini kaldır - Alt yazılar + Siyah sınırları kaldır + Alt yazı Oynatıcı alt yazı ayarları - Chromecast alt yazıları + Chromecast alt yazı Chromecast alt yazı ayarları - Eigengrau modu - Oynatıcıya hız seçeneği ekler - Atlamak için kaydır - Zamanı ayarlamak için yanlardan kaydır + Eigengravy modu + Oynatıcıya bir hız seçeneği ekle + Gözlemek için kaydır + Zamanı ayarlamak için sağa veya sola kaydır Ayarları değiştirmek için kaydır - Sol ve sağ taraftan yukarı kaydırarak ekran parlaklığı ve sesi ayarla + Sol ve sağ taraftan kaydırarak parlaklık ve sesi ayarla Sonraki bölümü otomatik oynat Mevcut bölüm bittiğinde sonraki bölüme başla - Çift dokunarak atla - İki kez dokunarak duraklat - Atlanacak süre (Saniye) - İleri ve geri atlamak için sağa ve sola iki kez dokun - Durdurmak için ekranın ortasına çift dokun + Gözlemek için çift tıkla + Durdurmak için çift tıkla + Oynatıcı gözleme miktarı + İleri ve geri atlamak için sağa ve sola çift tıkla + Durdurmak için ortaya tıkla Sistem parlaklığını kullan - Oynatıcıyı karartmak yerine sistem parlaklığını kullan + Oynatıcıda karanlık kaplama yerine sistem parlaklığını kullan İzleme ilerlemesini güncelle Mevcut bölüm ilerlemesini otomatik güncelle - Verileri yedekten geri yükle - Verileri yedekle + Yedekten geri yükle + Verileri yedekleyin Yedek dosyası yüklendi Geri yükleme başarısız oldu: %s Başarıyla yedeklendi @@ -166,21 +165,21 @@ %s yedeklenirken hata Ara Hesaplar - Güncellemeler ve yedekleme + Güncellemeler ve yedek Bilgi Gelişmiş arama - Arama sonuçlarını sağlayıcıya göre ayırır + Sağlayıcılara göre ayrılmış arama sonuçlarını ver Yalnızca çökmelerle ilgili verileri gönderir - Veri göndermez - Anime için filler bölümleri göster + Hiç veri göndermez + Anime için filler bölümleri gösterir Fragmanları göster Kitsu\'dan posterleri göster - Seçilen video kalitelerini arama sonuçlarında gösterme + Seçilen video kalitelerini arama sonuçlarında gizle Otomatik eklenti güncellemeleri Uygulama güncellemelerini göster - Uygulama başlatıldıktan sonra güncellemeleri otomatik olarak kontrol et. - Deneysel sürümlere güncelle - Yalnızca tam sürümler yerine deneysel güncellemeleri de ara + Başlangıçta yeni güncellemeleri otomatik olarak ara + Ön sürümlere güncelle + Sadece tam sürümler yerine ön sürüm güncellemelerini de ara GitHub Aynı geliştiriciler tarafından LightNovel uygulaması Aynı geliştiriciler tarafından anime uygulaması @@ -192,8 +191,8 @@ Bağlantı bulunamadı Bağlantı panoya kopyalandı Bölümü oynat - Varsayılan değere sıfırla - Üzgünüz, uygulama çöktü. Geliştiricilere anonim bir hata raporu gönderilecek + Varsayılana sıfırla + Üzgünüz, uygulama çöktü. Geliştiricilere isimsiz bir hata raporu gönderilecek Sezon %s %d%s Sezon yok @@ -206,13 +205,13 @@ Bölüm bulunamadı Dosyayı sil Sil - @string/sort_cancel + \@string/sort_cancel Durdur Sürdür -30 +30 - %s tamamen silinecek -\nEmin misiniz\? + %s dosyası tamamen silinecek +\nEmins misiniz\? %dm \nkaldı Devam ediyor @@ -237,21 +236,21 @@ Torrentler Belgeseller OVA - Asya dizileri + Asya dramaları Canlı yayınlar - +18 + NSFW Diğerleri Film Dizi Çizgi film - @string/anime - @string/ova + \@string/anime + \@string/ova Torrent Belgesel - Asya dizisi + Asya draması Canlı yayın - +18 + NSFW Video Kaynak hatası Sunucu hatası @@ -260,10 +259,10 @@ İndirme hatası, depolama izinlerini kontrol edin Bölümü Chromecast ile yayınla Bağlantıyı Chromecast ile yayınla - Burada oynat - %s üzerinden oynat + Uygulamada oynat + %s\'deda oynat Tarayıcıda oynat - Bağlantıyı kopyala + Linki kopyala Otomatik indir Şu kaynaktan indir Bağlantıları yenile @@ -282,22 +281,22 @@ Kilitle Yeniden boyutlandır Kaynak - Jeneriği geç + OP\'yi geç Bir daha gösterme Bu güncellemeyi atla Güncelle - Tercih edilen görüntü kalitesi (WiFi) - Video oynatıcı başlığı karakter üst sınırı - Oynatıcının çözünürlüğü + Tercih edilen izleme kalitesi + Oynatıcıdaki maksimum başlık karakter sayısı + Oynatıcının üst tarafındaki öğeler Video arabelleği boyutu Video arabelleği uzunluğu - Hafızadaki video önbelleği + Diskteki video önbelleği Video ve resim önbelleğini temizle - Çok yükseğe ayarlanırsa düşük belleğe sahip cihazlarda çökmelere neden olur (örn. Android TV). - Çok yükseğe ayarlanırsa düşük depolama alanına sahip sistemlerde sorunlara neden olur (örn. Android TV). - HTTPS üzerinden DNS (DoH) - İnternet Servis Sağlayıcısı (İSS) kısıtlamalarını aşmak için kullanışlıdır - Siteyi kopyala + Android TV gibi düşük belleğe sahip cihazlarda çok yükseğe ayarlanırsa çökmelere neden olur. + Çok yükseğe ayarlanırsa, Android TV cihazları gibi düşük depolama alanına sahip sistemlerde sorunlara neden olabilir. + HTTPS üzerinden DNS + ISP bloklarını atlatmak için kullanışlıdır + Klon site Siteyi kaldır Farklı bir URL ile mevcut bir sitenin klonunu ekleyin İndirme konumu @@ -306,16 +305,16 @@ Ekrana sığdır Uzat Yakınlaştır - Yasal Uyarı + Disclaimer legal_notice_key Any legal issues regarding the content on this application should be taken up with the actual file hosts and providers themselves as we are not affiliated with them. In case of copyright infringement, please directly contact the responsible parties or the streaming websites. The app is purely for educational and personal use. CloudStream 3 does not host any content on the app, and has no control over what media is put up or taken down. CloudStream 3 functions like any other search engine, such as Google. CloudStream 3 does not host, upload or manage any videos, films or content. It simply crawls, aggregates and displayes links in a convenient, user-friendly interface. It merely scrapes 3rd-party websites that are publicly accessable via any regular web browser. It is the responsibility of user to avoid any actions that might violate the laws governing his/her locality. Use CloudStream 3 at your own risk. Genel - Rastgele İçerik - Ana sayfada rastgele bir film veya dizi seçen bir tuş gösterir + Rastgele butonu + Ana sayfada rastgele butonunu göster Sağlayıcı dilleri Uygulama düzeni Tercih edilen medya - Desteklenen sağlayıcılarda +18 içeriği etkinleştir + Desteklenen sağlayıcılarda NSFW\'yi etkinleştir Alt yazı kodlaması Sağlayıcılar Düzen @@ -337,7 +336,7 @@ hello@world.com 127.0.0.1 MyCoolSite - ornek.com + example.com Dil kodu (tr) Hiçbiri Normal Hepsi Maksimum Minimum - @string/none + \@string/none Dış hat Çökmüş Gölge @@ -377,7 +376,7 @@ Alt yazı senkronu 1000 ms Alt yazı gecikmesi - Alt yazılar %d ms erken görüntüleniyorsa bunu kullanın + Alt yazılar %d ms erken gözüküyorsa bunu kullanın Alt yazılar %d ms geç gözüküyorsa bunu kullanın Alt yazı gecikmesi yok Pijamalı hasta yağız şoföre çabucak güvendi Önerilen - %s eklendi + %s yüklendi Dosyadan yükle İnternetten yükle İndirilen dosya @@ -423,10 +422,10 @@ Geçersiz veri Geçersiz URL Hata - Alt yazılardan seçmeli alt yazıyı (CC) kaldır + Alt yazılardan seçmeli alt yazıyı kaldır Alt yazılardaki şişkinliği kaldır Tercih edilen medya diline göre filtrele - Ek içerikler + Ekstralar Fragman Yayına bağlan Yönlendiren @@ -434,7 +433,7 @@ Videoları bu dillerde izle Geri Kurulumu atla - Cihazınıza uygun uygulama görünümünü seçin + Cihazınıza uygun görünümü seçin Çökme raporları Ne izlemek istiyorsunuz Bitti @@ -446,7 +445,7 @@ Eklenti silindi %s yüklenemedi +18 - %d %s indirilmeye başlandı… + %d %s … indirilmeye başlandı %d %s indirildi %s\'nin tamamı zaten indirildi Toplu indir @@ -478,7 +477,7 @@ Çökme bilgisini göster Puan: %s Açıklama - Sürüm + Versiyon Durum Boyut Geliştiriciler @@ -500,14 +499,14 @@ Fragmanı oynat Eklenen depolardan henüz yüklenmemiş tüm eklentileri otomatik olarak yükleyin. Güncelleme başladı - Bazı cihazlar yeni paket yükleyiciyi desteklemez.. Güncellemeler yüklenmezse eski seçeneği deneyin. + Bazı cihazlar yeni paket yükleyiciyi desteklemez.. Güncellemele yüklenmezse eski seçeneği deneyin. Eklentileri otomatik olarak indir APK indirici - Bağlantılar + Linkler Uygulama güncellemeleri Yedek Oynatıcı özellikleri - Alt yazılar + Altyazılar Düzen Varsayılanlar Eklentiler @@ -532,22 +531,22 @@ İzlenenlerden kaldır Karışık son Karışık başlangıç - Katkıda Bulunanlar + Kredi Giriş Eklenti İndirildi - Eylemler - Açılış/bitiş için atlama açılır pencerelerini göster + Aksiyonlar + Açma/bitiş için atlama açılır pencerelerini göster Çok fazla metin. Panoya kaydedilemiyor. Kütüphane Tarayıcı Görünüşe göre kütüphaneniz boş :( -\nBir kütüphane hesabına giriş yapın veya yerel kütüphanenize içerik ekleyin +\nBir kütüphane hesabına giriş yapın veya yerel kütüphanenize gösteri ekleyin Güvenli mod dosyası bulundu! \nDosya kaldırılana kadar başlangıçta herhangi bir uzantı yüklenmiyor. Sırala Sırala - Güncellenme (Yeniden Eskiye) - Güncellenme (Eskiden Yeniye) + Güncel (Yeniden Eskiye) + Güncel (Eskiden Yeniye) Alfabetik (A\'dan Z’ye) Alfabetik (Z - A) Kütüphane Seçin @@ -555,27 +554,4 @@ Görünüşe göre bu liste boş, başka bir listeye geçmeyi deneyin Derecelendirme (Yüksekten Düşüğe) Derecelendirme (Düşükten Yükseğe) - Yeniden başlat - Oynatıcı gizlenmişken atlanacak süre - İSS Kısıtlamaları - GitHub\'a ulaşılamadı, jsdelivr vekil sunucusu etkinleştiriliyor. - Başlat - Başarılı oldu - raw.githubusercontent.com vekil sunucusu (proxy) - Tercih edilen görüntü kalitesi (Mobil veri) - Oynatıcı görünürken atlanacak süre - Oynatıcı gizli durumdayken atlanacak süre miktarı - jsdelivr kullanarak GitHub kısıtlamasını aşar. Güncellemeler birkaç gün gecikebilir. - Android TV - Yeni bölüm %d yayınlandı! - Sağlayıcıyı kontrol et - Başarısız oldu - Durdur - Geri al - Abone olunan gösteriler güncelleniyor - Abone olunan - %s kanalına abone olundu - %s kanalı aboneliğinden çıkıldı - Günlük - Oynatıcı görünür durumdayken atlanacak süre miktarı - + \ No newline at end of file diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index bd062394..a676b583 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -1,13 +1,13 @@ - + Постер - Постер до епізоду + Постер епізоду Завантаження скасовано Змінити постачальника Назад Рейтинг: %.1f Актори: %s - Епізод %d вийде через + Епізод %d буде випущено через Poster %s Еп. %d %dд %dгод %dхв @@ -15,16 +15,16 @@ %dхв Головний постер Наступний випадковий - Попередній перегляд фону + Перегляд фону Швидкість (%.2fx) - Знайдено нове оновлення! + Нове оновлення знайдено! \n%s -> %s Пошук Завантаження %d хв - Налаштування + Параметри Пошук… - Пошук на %s… + Пошук %s… Дані відсутні Більше опцій Наступний епізод @@ -37,7 +37,7 @@ Покинуто Переглянути фільм Переглянути трейлер - Трансляція через торрент + Переглянути торрент Повторити підключення… Назад Переглянути епізод @@ -87,13 +87,13 @@ Налаштування субтитрів Chromecast Режим Eigengravy Проведіть пальцем, щоб змінити налаштування - Проведіть пальцем вгору або вниз ліворуч або праворуч, щоб змінити яскравість або гучність + Проведіть пальцем ліворуч або праворуч, щоб змінити яскравість або гучність Відтворення наступного епізоду після закінчення поточного Головна CloudStream Філер Програти в CloudStream - Трансляція + Потік Переглядаю Поділитися Відкладено @@ -121,10 +121,10 @@ Колір тексту Колір контуру Автовідтворення наступного епізоду - Проведіть пальцем з боку в бік, щоб керувати своїм положенням у відео + Проведіть пальцем ліворуч або праворуч, щоб керувати часом у відеоплеєрі %d Бананів для розробників Кнопка зміни розміру плеєра - @string/home_play + \@string/home_play Для коректної роботи цього постачальника може знадобитися VPN Метадані не надаються сайтом, завантаження відео не відбудеться, якщо їх немає на сайті. Картинка в картинці @@ -133,8 +133,8 @@ Проведіть пальцем, щоб перемотати Двічі торкніться, щоб перемотати Двічі торкніться для паузи - Крок перемотки (Секунди) - Натисніть двічі посередині, щоб призупинити + Крок перемотки + Натисніть посередині, щоб поставити на паузу Використовувати яскравість системи Оновити прогрес перегляду Відновлення даних з резервної копії @@ -230,7 +230,7 @@ Показати постери від Kitsu Автоматичне оновлення плагінів Автоматично встановлювати всі ще не встановлені плагіни з доданих репозиторіїв. - Автоматично шукати нові оновлення після запуску застосунку. + Автоматичний пошук нових оновлень при запуску Оновлення до бета-версій Посилання скопійовано в буфер обміну Деякі телефони не підтримують новий інсталятор пакетів. Спробуйте стару версію, якщо оновлення не встановлюються. @@ -255,7 +255,7 @@ Документальні фільми NSFW Фільм - OVA + \@string/ova Торрент Мітка якості NSFW @@ -283,7 +283,7 @@ Особливості Загальне Випадкова кнопка - Показує кнопку на Головній сторінці, яка може вибрати випадковий фільм або серіал на Головній сторінці + Показати випадкову кнопку на Головній сторінці Мови постачальника Макет програми Бажані медіа @@ -524,9 +524,10 @@ Відписатися від %s Епізод %d випущено! Повернути - raw.githubusercontent.com Proxy + raw.githubusercontent.com +\nProxy Не вдалося зв\'язатися з GitHub, увімкнувши проксі-сервер jsdelivr. Обходи ISP - За допомогою jsdelivr можна обійти блокування GitHub. Можлива затримка оновлень на кілька днів. + Обходити блокування GitHub з використанням jsdlitr, може викликати затримку оновлень на кілька днів. Бажана якість перегляду (Мобільні дані) - + \ No newline at end of file diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml index c19c6472..f733addc 100644 --- a/app/src/main/res/values-ur/strings.xml +++ b/app/src/main/res/values-ur/strings.xml @@ -1,4 +1,4 @@ - + کاسٹ: %s قسط %d جاری کیا جائے گا @@ -230,7 +230,7 @@ سلسلہ کارٹون انیمی - اووا + \@string/اووا ٹورینٹ دستاویزی فلم ایشیائی ڈرامے @@ -356,4 +356,4 @@ %d / 10 اٹھایا اگر سب ٹائٹلز %d ms بہت جلد دکھائے جائیں تو اسے استعمال کریں - + \ No newline at end of file diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 520cfaa4..db647b5d 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -1,6 +1,5 @@ - - - + + %s Tập %d @@ -11,7 +10,7 @@ %dm Poster - Ảnh bìa + \@string/result_poster_img_des Episode Poster Main Poster Next Random @@ -111,7 +110,7 @@ Tiếp tục xem Loại bỏ Thông tin thêm - @string/home_play + \@string/home_play Bạn có thể sẽ cần sử dụng VPN để xem phim này Phim này được chiếu dưới dạng Torrent. Hãy sử dụng VPN để xem Thông tin phim @@ -230,7 +229,7 @@ Phim Bộ Hoạt Hình Anime - @string/ova + \@string/ova Torrent Phim Tài Liệu Truyền Hình Châu Á @@ -261,18 +260,18 @@ Kiểm tra cập nhật Khóa Thu Phóng - Nguồn - Bỏ qua OP + Tuỳ chọn + Tua nhanh Không hiện lại - Bỏ qua bản cập nhật này + Bỏ qua Cập nhật - Chất lượng xem ưu tiên (WiFi) + Tự động chọn chất lượng phim Kí tự tối đa trên tiêu đề - Độ phân giải trình phát video - Kích thước bộ nhớ đệm video + Định dạng trình phát + Dung lượng video cache Thời lượng bộ nhớ đệm - Lưu bộ nhớ đệm video trên ổ cứng - Xoá bộ nhớ đệm hình ảnh và video + Dung lượng video cache + Xoá hình ảnh và video Sẽ gây lỗi nếu đặt quá cao trên máy có dung lượng ram thấp như Android TV. Sẽ gây lỗi nếu đặt quá cao trên máy có dung lượng lưu trữ thấp như Android TV. DNS over HTTPS @@ -520,9 +519,4 @@ Có vẻ như danh sách này trống, hãy thử chuyển sang danh sách khác Chữ cái (A đến Z) Chọn Thư viện - Nhật ký - Chất lượng xem ưu tiên (Dữ liệu di động) - Thất bại - Thành công - Bắt đầu - + \ No newline at end of file diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 3364ea86..8a10208a 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -1,6 +1,5 @@ - - - + + %d %s | %s %s • %s @@ -24,9 +23,9 @@ 劇集封面 主封面 隨機下一個 - @string/play_episode + \@string/play_episode 返回 - @string/home_change_provider_img_des + \@string/home_change_provider_img_des 更改片源 預覽背景 @@ -47,7 +46,7 @@ 無資料 更多選項 下一集 - @string/synopsis + \@string/synopsis 類型 分享 在瀏覽器中打開 @@ -124,7 +123,7 @@ 繼續觀看 移除 更多資訊 - @string/home_play + \@string/home_play 此片源可能需要 VPN 才能正常使用 此片源是種子,建議使用 VPN 站點不提供元數據,如果站點上不存在元數據,影片載入將失敗。 @@ -206,7 +205,7 @@ 未找到劇集 刪除文件 刪除 - @string/sort_cancel + \@string/sort_cancel 暫停 繼續 -30 @@ -245,8 +244,8 @@ 電影 電視劇 卡通 - @string/anime - @string/ova + \@string/anime + \@string/ova 種子 紀錄片 亞洲劇 @@ -369,7 +368,7 @@ 全部 最大 最小 - @string/none + \@string/none 輪廓 凹陷 陰影 @@ -535,4 +534,4 @@ 外觀 功能 瀏覽器 - + \ No newline at end of file diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 44b93430..626cc0fe 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -1,6 +1,5 @@ - - - + + %d %s | %s %s • %s @@ -24,9 +23,9 @@ 剧集封面 主封面 随机下一个 - @string/play_episode + \@string/play_episode 返回 - @string/home_change_provider_img_des + \@string/home_change_provider_img_des 更改片源 预览背景 @@ -47,7 +46,7 @@ 无数据 更多选项 下一集 - @string/synopsis + \@string/synopsis 类型 分享 在浏览器中打开 @@ -124,7 +123,7 @@ 继续观看 移除 更多信息 - @string/home_play + \@string/home_play 此片源可能需要 VPN 才能正常使用 此片源为种子文件,建议使用 VPN 站点不提供元数据,如果站点上不存在元数据,视频加载将失败。 @@ -143,14 +142,14 @@ 倍速模式 在播放器中添加播放速度选项 滑动控制进度 - 左右滑动以控制视频中的位置 + 左右滑动控制播放进度 滑动更改设置 上下滑动修改亮度或音量 自动播放下一集 播放完毕后播放下一集 双击控制进度 双击暂停 - 双击控制进度时间 (秒) + 双击控制进度时间 在左右侧双击快进或快退 双击中间暂停 使用系统亮度 @@ -179,7 +178,7 @@ 自动更新插件 自动下载插件 显示应用更新 - 启动应用后自动搜索更新。 + 启动时自动搜索更新 更新至预览版 搜索预览版更新替代仅搜索完整版本 Github @@ -207,7 +206,7 @@ 未找到剧集 删除文件 删除 - @string/sort_cancel + \@string/sort_cancel 暂停 继续 -30 @@ -246,8 +245,8 @@ 电影 电视剧 卡通 - 动漫 - OVA + \@string/anime + \@string/ova 种子 纪录片 亚洲剧 @@ -287,7 +286,7 @@ 不再显示 跳过此更新 更新 - 首选播放画质(WiFi) + 首选播放画质 视频播放器标题最多字符 视频播放器标题 视频缓冲大小 @@ -312,7 +311,7 @@ Any legal issues regarding the content on this application should be taken up with the actual file hosts and providers themselves as we are not affiliated with them. In case of copyright infringement, please directly contact the responsible parties or the streaming websites. The app is purely for educational and personal use. CloudStream 3 does not host any content on the app, and has no control over what media is put up or taken down. CloudStream 3 functions like any other search engine, such as Google. CloudStream 3 does not host, upload or manage any videos, films or content. It simply crawls, aggregates and displayes links in a convenient, user-friendly interface. It merely scrapes 3rd-party websites that are publicly accessable via any regular web browser. It is the responsibility of user to avoid any actions that might violate the laws governing his/her locality. Use CloudStream 3 at your own risk. 通用 随机按钮 - 在主页上显示按钮,可以从主页上随机选择电影或电视剧 + 在主页中显示随机按钮 片源语言 应用布局 首选类型 @@ -370,7 +369,7 @@ 全部 最大 最小 - @string/none + \@string/none 轮廓 凹陷 阴影 @@ -574,8 +573,7 @@ 日志 raw.githubusercontent.com 代理 连接 Github 失败,正在启用 jsdelivr 代理。 - 使用 jsdelivr,可以绕过 GitHub 的封锁。可能会延迟几天的更新。 + 使用 jsdelivr 绕过对 Github 的封锁,可能导致更新延迟几天。 ISP 绕过 还原 - 首选播放画质(移动数据) - + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 911c0d07..989ee818 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -210,17 +210,17 @@ Eigengravy Mode Adds a speed option in the player Swipe to seek - Swipe from side to side to control your position in a video + Swipe left or right to control time in the videoplayer Swipe to change settings - Slide up or down on the left or right side to change brightness or volume + Swipe on the left or right side to change brightness or volume Autoplay next episode Start the next episode when the current one ends Double tap to seek Double tap to pause - Player seek amount (Seconds) + Player seek amount Tap twice on the right or left side to seek forwards or backwards - Tap twice in the middle to pause + Tap in the middle to pause Use system brightness Use system brightness in the app player instead of a dark overlay @@ -251,7 +251,7 @@ Automatically download plugins Automatically install all not yet installed plugins from added repositories. Show app updates - Automatically search for new updates after starting the app. + Automatically search for new updates on start Redo setup process Update to prereleases Search for prerelease updates instead of full releases only @@ -324,8 +324,8 @@ Movie Series Cartoon - Anime - OVA + @string/anime + @string/ova Torrent Documentary Asian Drama @@ -383,7 +383,7 @@ Useful for bypassing ISP blocks raw.githubusercontent.com Proxy Failed to reach GitHub, enabling jsdelivr proxy. - Using jsdelivr, GitHub blocking can be bypassed. May delay updates by a few days. + Bypasses blocking of GitHub using jsdelivr, may cause updates to be delayed by few days. Clone site Remove site Add a clone of an existing site, with a different URL @@ -428,7 +428,7 @@ Features General Random Button - Shows button on Homepage which can choose a random movie or TV series from the Homepage + Show random button on Homepage Provider languages App Layout Preferred media @@ -657,4 +657,22 @@ Subscribed to %s Unsubscribed from %s Episode %d released! - \ No newline at end of file + Profile %d + Wi-Fi + Mobile data + Set default + Use + Edit + Profiles + Help + + Here you can change how the sources are ordered. If a video has a higher priority it will appear higher in the source selection. + The sum of the source priority and the quality priority is the video priority. + \n\nSource A: 3 + \nQuality B: 7 + \nWill have a combined video priority of 10. + + \n\nNOTE: If the sum is 10 or more the player will automatically skip loading when that link is loaded! + + Qualities + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index b9648162..78c62c69 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -40,6 +40,7 @@ ?attr/textColor ?attr/grayTextColor + ?attr/grayTextColor ?attr/grayTextColor ?attr/textColor diff --git a/app/src/main/res/xml/settings_player.xml b/app/src/main/res/xml/settings_player.xml index 2d2905ea..ad33e036 100644 --- a/app/src/main/res/xml/settings_player.xml +++ b/app/src/main/res/xml/settings_player.xml @@ -11,14 +11,14 @@ - - + + + + + + + +