From d790f113c0d8934b8a6ea0cce98ab7c0dbc92b8e Mon Sep 17 00:00:00 2001 From: LagradOst Date: Thu, 28 Oct 2021 13:54:04 +0200 Subject: [PATCH 01/26] bump --- app/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 6329201f..119700d4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,7 +34,7 @@ android { applicationId "com.lagradost.cloudstream3" minSdkVersion 21 targetSdkVersion 31 - versionCode 31 + versionCode 32 versionName "2.1.2" resValue "string", "app_version", @@ -141,8 +141,8 @@ dependencies { //implementation 'com.github.TorrentStream:TorrentStream-Android:2.7.0' // Downloading - implementation "androidx.work:work-runtime:2.7.0-rc01" - implementation "androidx.work:work-runtime-ktx:2.7.0-rc01" + implementation "androidx.work:work-runtime:2.7.0" + implementation "androidx.work:work-runtime-ktx:2.7.0" // Networking implementation "com.squareup.okhttp3:okhttp:4.9.1" From 225744984a16da17b1fef0853dcd514c83d9cbae Mon Sep 17 00:00:00 2001 From: ArjixWasTaken <53124886+ArjixWasTaken@users.noreply.github.com> Date: Thu, 28 Oct 2021 21:47:46 +0300 Subject: [PATCH 02/26] Provider: AllAnime --- .../com/lagradost/cloudstream3/MainAPI.kt | 1 + .../animeproviders/AllAnimeProvider.kt | 300 ++++++++++++++++++ 2 files changed, 301 insertions(+) create mode 100644 app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt index 5e920f60..126366d2 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt @@ -28,6 +28,7 @@ object APIHolder { val apis = arrayListOf( GogoanimeProvider(), + AllAnimeProvider(), //ShiroProvider(), // v2 fucked me //AnimePaheProvider(), //ddos guard AnimeFlickProvider(), diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt new file mode 100644 index 00000000..6ac0dd66 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt @@ -0,0 +1,300 @@ +package com.lagradost.cloudstream3.animeproviders + +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.network.get +import com.lagradost.cloudstream3.network.text +import com.lagradost.cloudstream3.utils.ExtractorLink +import org.jsoup.Jsoup +import java.util.* + +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.module.kotlin.readValue +import kotlin.collections.ArrayList +import org.mozilla.javascript.Context +import org.mozilla.javascript.Scriptable +import java.net.URI +import java.net.URLDecoder +import com.lagradost.cloudstream3.utils.getQualityFromName + + +class AllAnimeProvider : MainAPI() { + override val mainUrl: String + get() = "https://allanime.site" + override val name: String + get() = "AllAnime" + override val hasQuickSearch: Boolean + get() = false + override val hasMainPage: Boolean + get() = false + + private fun getStatus(t: String): ShowStatus { + return when (t) { + "Finished" -> ShowStatus.Completed + "Releasing" -> ShowStatus.Ongoing + else -> ShowStatus.Completed + } + } + + override val supportedTypes: Set + get() = setOf(TvType.Anime, TvType.AnimeMovie) + + private data class Data ( + @JsonProperty("shows") val shows: Shows + ) + + private data class Shows ( + @JsonProperty("pageInfo") val pageInfo: PageInfo, + @JsonProperty("edges") val edges: List, + @JsonProperty("__typename") val _typename: String + ) + + private data class Edges ( + @JsonProperty("_id") val Id: String?, + @JsonProperty("name") val name: String, + @JsonProperty("englishName") val englishName: String?, + @JsonProperty("nativeName") val nativeName: String?, + @JsonProperty("thumbnail") val thumbnail: String?, + @JsonProperty("type") val type: String?, + @JsonProperty("season") val season: Season?, + @JsonProperty("score") val score: Double?, + @JsonProperty("airedStart") val airedStart: AiredStart?, + @JsonProperty("availableEpisodes") val availableEpisodes: AvailableEpisodes?, + @JsonProperty("availableEpisodesDetail") val availableEpisodesDetail: AvailableEpisodesDetail?, + @JsonProperty("studios") val studios: List?, + @JsonProperty("description") val description: String?, + @JsonProperty("status") val status: String?, + ) + + private data class AvailableEpisodes ( + @JsonProperty("sub") val sub: Int, + @JsonProperty("dub") val dub: Int, + @JsonProperty("raw") val raw: Int + ) + + private data class AiredStart ( + @JsonProperty("year") val year: Int, + @JsonProperty("month") val month: Int, + @JsonProperty("date") val date: Int + ) + + private data class Season ( + @JsonProperty("quarter") val quarter: String, + @JsonProperty("year") val year: Int + ) + + private data class PageInfo ( + @JsonProperty("total") val total: Int, + @JsonProperty("__typename") val _typename: String + ) + + private data class AllAnimeQuery ( + @JsonProperty("data") val data: Data + ) + + override fun search(query: String): ArrayList { + val link = """$mainUrl/graphql?variables=%7B%22search%22%3A%7B%22allowAdult%22%3Afalse%2C%22query%22%3A%22$query%22%7D%2C%22limit%22%3A26%2C%22page%22%3A1%2C%22translationType%22%3A%22sub%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%229343797cc3d9e3f444e2d3b7db9a84d759b816a4d84512ea72d079f85bb96e98%22%7D%7D""" + var res = get(link).text + if (res.contains("PERSISTED_QUERY_NOT_FOUND")) { + res = get(link).text + if (res.contains("PERSISTED_QUERY_NOT_FOUND")) return ArrayList() + } + val response = mapper.readValue(res) + + val results = response.data.shows.edges.filter { + // filtering in case there is an anime with 0 episodes available on the site. + !(it.availableEpisodes?.raw == 0 && it.availableEpisodes.sub == 0 && it.availableEpisodes.dub == 0) + } + + return ArrayList(results.map { + AnimeSearchResponse( + it.name, + "$mainUrl/anime/${it.Id}", + this.name, + TvType.Anime, + it.thumbnail, + it.airedStart?.year, + EnumSet.of(DubStatus.Subbed), //, DubStatus.Dubbed), + it.englishName, + null, //it.availableEpisodes?.dub, + it.availableEpisodes?.sub + ) + }) + } + + private data class AvailableEpisodesDetail ( + @JsonProperty("sub") val sub: List, + @JsonProperty("dub") val dub: List, + @JsonProperty("raw") val raw: List + ) + + + override fun load(url: String): LoadResponse? { + val rhino = Context.enter() + rhino.initStandardObjects() + rhino.optimizationLevel = -1 + val scope: Scriptable = rhino.initStandardObjects() + + + val html = get(url).text + val soup = Jsoup.parse(html) + + val script = soup.select("script").firstOrNull { + it.html().contains("window.__NUXT__") + } ?: return null + + val js = """ + const window = {} + ${script.html()} + const returnValue = JSON.stringify(window.__NUXT__.fetch[0].show) + """.trimIndent() + + rhino.evaluateString(scope, js, "JavaScript", 1, null) + val jsEval = scope.get("returnValue", scope) ?: return null + val showData = mapper.readValue(jsEval as String) + + val title = showData.name + val description = showData.description + val poster = showData.thumbnail + + val episodes = showData.availableEpisodes.let { + if (it == null) return@let Pair(null, null) + Pair(if (it.sub != 0) ArrayList((1 .. it.sub).map { epNum -> + AnimeEpisode( + "$mainUrl/anime/${showData.Id}/episodes/sub/$epNum", + null, + null, + null, + null, + null, + epNum + ) + }) else null, if (it.dub != 0) ArrayList((1 .. it.dub).map { epNum -> + AnimeEpisode( + "$mainUrl/anime/${showData.Id}/episodes/dub/$epNum", + null, + null, + null, + null, + null, + epNum + ) + }) else null) + } + + return AnimeLoadResponse( + null, + null, + title, + url, + this.name, + TvType.Anime, + poster, + showData.airedStart?.year, + null, // no dub, because there is no way to switch from dub to sub //episodes.second, + episodes.first, + getStatus(showData.status.toString()), + description.replace(Regex("""\<(.*?)\>"""), "") + ) + } + + private val embedBlackList = listOf( + "https://mp4upload.com/", + "https://streamsb.net/", + "https://dood.to/", + "https://videobin.co/", + "https://ok.ru", + "https://streamlare.com", + ) + + private fun embedIsBlacklisted(url: String): Boolean { + embedBlackList.forEach { + if (it.javaClass.name == "kotlin.text.Regex") { + if ((it as Regex).matches(url)) { + return true + } + } else { + if (url.contains(it as String)) { + return true + } + } + } + return false + } + + private fun String.sanitize(): String { + var out = this + listOf(Pair("\\u002F", "/")).forEach { + out = out.replace(it.first, it.second) + } + return out + } + + private data class Links ( + @JsonProperty("link") val link: String, + @JsonProperty("hls") val hls: Boolean?, + @JsonProperty("resolutionStr") val resolutionStr: String, + @JsonProperty("src") val src: String? + ) + + private data class AllAnimeVideoApiResponse ( + @JsonProperty("links") val links: List + ) + + private data class ApiEndPoint( + @JsonProperty("episodeIframeHead") val episodeIframeHead: String + ) + + override fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + var apiEndPoint = mapper.readValue(get("$mainUrl/getVersion").text).episodeIframeHead + if (apiEndPoint.endsWith("/")) apiEndPoint = apiEndPoint.slice(0 until apiEndPoint.length - 1) + + val html = get(data).text + + val sources = Regex("""sourceUrl[:=]"(.+?)"""").findAll(html).toList().map { URLDecoder.decode(it.destructured.component1().sanitize(), "UTF-8") } + sources.forEach { + var link = it + if (URI(link).isAbsolute || link.startsWith("//")) { + if (link.startsWith("//")) link = "https:$it" + + if (Regex("""streaming\.php\?""").matches(link)) { + // for now ignore + } else if (!embedIsBlacklisted(link)) { + callback( + ExtractorLink( + "AllAnime - " + URI(link).host, + "", + link, + data, + getQualityFromName("1080"), + URI(link).path.contains(".m3u") + ) + ) + } + } else { + link = apiEndPoint + URI(link).path + ".json?" + URI(link).query + val response = get(link) + + if (response.code < 400) { + val links = mapper.readValue(response.text).links + links.forEach { server -> + callback(ExtractorLink( + "AllAnime - " + URI(server.link).host, + server.resolutionStr, + server.link, + "$apiEndPoint/player?uri=" + (if (URI(server.link).host.isNotEmpty()) server.link else apiEndPoint + URI(server.link).path), + getQualityFromName("1080"), + server.hls != null && server.hls + )) + } + } + } + } + return true + } + +} From 0167573426b96a012a8cbde96fb7d784924fabb0 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Thu, 28 Oct 2021 18:48:07 +0000 Subject: [PATCH 03/26] chore(docs): update list of sites --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e74a8121..3c8a57ec 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ It merely scrapes 3rd-party websites that are publicly accessable via any regula - [gogoanime.vc](https://gogoanime.vc) +- [allanime.site](https://allanime.site) - [animeflick.net](https://animeflick.net) - [kawaiifu.com](https://kawaiifu.com) - [tenshi.moe](https://tenshi.moe) From 97700bfd1721a78c34ecbcdd050dd2c1f056ca9f Mon Sep 17 00:00:00 2001 From: Arjix <53124886+ArjixWasTaken@users.noreply.github.com> Date: Thu, 28 Oct 2021 21:59:50 +0300 Subject: [PATCH 04/26] Update AllAnimeProvider.kt --- .../lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt index 6ac0dd66..b141089a 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt @@ -193,7 +193,7 @@ class AllAnimeProvider : MainAPI() { null, // no dub, because there is no way to switch from dub to sub //episodes.second, episodes.first, getStatus(showData.status.toString()), - description.replace(Regex("""\<(.*?)\>"""), "") + description?.replace(Regex("""\<(.*?)\>"""), "") ) } From 0766f04deda7ceac1ccc05bcc9d254b65cc88b5d Mon Sep 17 00:00:00 2001 From: LagradOst Date: Sat, 30 Oct 2021 13:33:35 +0200 Subject: [PATCH 05/26] android tv stuff (morpheasgr) --- app/src/main/AndroidManifest.xml | 9 ++- .../res/drawable/ic_banner_foreground.xml | 54 ++++++++++++++++++ .../main/res/mipmap-anydpi-v26/ic_banner.xml | 5 ++ app/src/main/res/mipmap-xhdpi/ic_banner.png | Bin 0 -> 4037 bytes .../main/res/values/ic_banner_background.xml | 4 ++ 5 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 app/src/main/res/drawable/ic_banner_foreground.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_banner.xml create mode 100644 app/src/main/res/mipmap-xhdpi/ic_banner.png create mode 100644 app/src/main/res/values/ic_banner_background.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7f8694ec..722a8329 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,10 +10,16 @@ + + + + @@ -63,7 +70,7 @@ android:enabled="false" android:exported="true"> - + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_banner.xml b/app/src/main/res/mipmap-anydpi-v26/ic_banner.xml new file mode 100644 index 00000000..a0a0dece --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_banner.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-xhdpi/ic_banner.png b/app/src/main/res/mipmap-xhdpi/ic_banner.png new file mode 100644 index 0000000000000000000000000000000000000000..fea1217c342c8a669183cb56bd5e01cdfa94dcbb GIT binary patch literal 4037 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 u1PWLd_<48$ literal 0 HcmV?d00001 diff --git a/app/src/main/res/values/ic_banner_background.xml b/app/src/main/res/values/ic_banner_background.xml new file mode 100644 index 00000000..8661bdd1 --- /dev/null +++ b/app/src/main/res/values/ic_banner_background.xml @@ -0,0 +1,4 @@ + + + #3242D3 + \ No newline at end of file From 37348716080b635acf0d78c5e238203fcfada036 Mon Sep 17 00:00:00 2001 From: LagradOst Date: Sat, 30 Oct 2021 20:14:12 +0200 Subject: [PATCH 06/26] android tv layout stuff --- .../com/lagradost/cloudstream3/MainAPI.kt | 7 +-- .../lagradost/cloudstream3/MainActivity.kt | 49 ++++++++++++--- .../cloudstream3/ui/player/PlayerFragment.kt | 2 +- .../cloudstream3/ui/search/SearchFragment.kt | 13 ++-- .../ui/settings/SettingsFragment.kt | 45 +++++++++++++- .../lagradost/cloudstream3/utils/UIHelper.kt | 18 ++++-- .../main/res/drawable/ic_baseline_tv_24.xml | 5 ++ app/src/main/res/layout/activity_main.xml | 2 +- app/src/main/res/layout/activity_main_tv.xml | 59 +++++++++++++++++++ app/src/main/res/layout/fragment_home.xml | 2 +- app/src/main/res/layout/fragment_search.xml | 6 +- app/src/main/res/values/array.xml | 12 ++++ app/src/main/res/values/strings.xml | 7 ++- app/src/main/res/xml/settings.xml | 10 ++++ 14 files changed, 207 insertions(+), 30 deletions(-) create mode 100644 app/src/main/res/drawable/ic_baseline_tv_24.xml create mode 100644 app/src/main/res/layout/activity_main_tv.xml diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt index 126366d2..ddc36dda 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt @@ -254,11 +254,8 @@ fun sortSubs(urls: List): List { } /** https://www.imdb.com/title/tt2861424/ -> tt2861424 */ -fun imdbUrlToId(url: String): String { - return url - .removePrefix("https://www.imdb.com/title/") - .removePrefix("https://imdb.com/title/tt2861424/") - .replace("/", "") +fun imdbUrlToId(url: String): String? { + return Regex("/title/(tt[0-9]*)").find(url)?.groupValues?.get(1) ?: Regex("tt[0-9]{5,}").find(url)?.groupValues?.get(0) } fun imdbUrlToIdNullable(url: String?): String? { diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index 0c9a956d..8b1927d4 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -9,8 +9,10 @@ import android.content.pm.PackageManager import android.content.res.ColorStateList import android.content.res.Configuration import android.content.res.Resources +import android.graphics.Rect import android.os.Build import android.os.Bundle +import android.util.TypedValue import android.view.* import android.widget.TextView import android.widget.Toast @@ -31,6 +33,7 @@ import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver import com.lagradost.cloudstream3.ui.APIRepository import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO import com.lagradost.cloudstream3.ui.player.PlayerEventType +import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable import com.lagradost.cloudstream3.utils.AppUtils.loadResult import com.lagradost.cloudstream3.utils.DataStore.getKey @@ -49,6 +52,7 @@ import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.fragment_result.* import java.util.* import kotlin.concurrent.thread +import kotlin.math.roundToInt const val VLC_PACKAGE = "org.videolan.vlc" @@ -136,8 +140,28 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { } } + private fun Activity.getRootView(): View { + return findViewById(android.R.id.content) + } + + private fun Context.convertDpToPx(dp: Float): Float { + return TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + dp, + this.resources.displayMetrics + ) + } + + private fun Activity.isKeyboardOpen(): Boolean { + val visibleBounds = Rect() + this.getRootView().getWindowVisibleDisplayFrame(visibleBounds) + val heightDiff = getRootView().height - visibleBounds.height() + val marginOfError = this.convertDpToPx(50F).roundToInt() + return heightDiff > marginOfError + } + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { - //println("Keycode: $keyCode") + println("Keycode: $keyCode") //showToast( // this, // "Got Keycode $keyCode | ${KeyEvent.keyCodeToString(keyCode)} \n ${event?.action}", @@ -160,16 +184,16 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_A, KeyEvent.KEYCODE_MEDIA_SKIP_BACKWARD, KeyEvent.KEYCODE_MEDIA_REWIND -> { PlayerEventType.SeekBack } - KeyEvent.KEYCODE_MEDIA_NEXT -> { + KeyEvent.KEYCODE_MEDIA_NEXT, KeyEvent.KEYCODE_BUTTON_R1 -> { PlayerEventType.NextEpisode } - KeyEvent.KEYCODE_MEDIA_PREVIOUS -> { + KeyEvent.KEYCODE_MEDIA_PREVIOUS, KeyEvent.KEYCODE_BUTTON_L1 -> { PlayerEventType.PrevEpisode } KeyEvent.KEYCODE_MEDIA_PAUSE -> { PlayerEventType.Pause } - KeyEvent.KEYCODE_MEDIA_PLAY -> { + KeyEvent.KEYCODE_MEDIA_PLAY, KeyEvent.KEYCODE_BUTTON_START -> { PlayerEventType.Play } KeyEvent.KEYCODE_L, KeyEvent.KEYCODE_NUMPAD_7 -> { @@ -184,13 +208,13 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { KeyEvent.KEYCODE_S, KeyEvent.KEYCODE_NUMPAD_9 -> { PlayerEventType.ShowMirrors } - KeyEvent.KEYCODE_E, KeyEvent.KEYCODE_NUMPAD_3 -> { + KeyEvent.KEYCODE_E, KeyEvent.KEYCODE_NUMPAD_3 -> { PlayerEventType.ShowSpeed } KeyEvent.KEYCODE_R, KeyEvent.KEYCODE_NUMPAD_0 -> { PlayerEventType.Resize } - KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, KeyEvent.KEYCODE_P, KeyEvent.KEYCODE_SPACE -> { // space is not captured due to navigation + KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, KeyEvent.KEYCODE_P, KeyEvent.KEYCODE_SPACE, KeyEvent.KEYCODE_NUMPAD_ENTER, KeyEvent.KEYCODE_ENTER -> { // space is not captured due to navigation PlayerEventType.PlayPauseToggle } else -> null @@ -198,6 +222,12 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { playerEventListener?.invoke(playerEvent) } + when (keyCode) { + KeyEvent.KEYCODE_DPAD_CENTER -> { + println("DPAD PRESSED ${this.isKeyboardOpen()}") + } + } + return super.onKeyDown(keyCode, event) } @@ -371,7 +401,12 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN) - setContentView(R.layout.activity_main) + if (isTvSettings()) { + setContentView(R.layout.activity_main_tv) + } else { + setContentView(R.layout.activity_main) + } + // val navView: BottomNavigationView = findViewById(R.id.nav_view) //https://stackoverflow.com/questions/52594181/how-to-know-if-user-has-disabled-picture-in-picture-feature-permission diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt index 9e016807..72d3bfcb 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt @@ -996,7 +996,7 @@ class PlayerFragment : Fragment() { activity?.unregisterReceiver(it) } activity?.hideSystemUI() - this.view?.let { activity?.hideKeyboard(it) } + this.view?.let { hideKeyboard(it) } } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt index 17a9fd79..4669a73e 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt @@ -35,9 +35,11 @@ import com.lagradost.cloudstream3.utils.SEARCH_PROVIDER_TOGGLE import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar import com.lagradost.cloudstream3.utils.UIHelper.getGridIsCompact import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard +import com.lagradost.cloudstream3.utils.UIHelper.showInputMethod import kotlinx.android.synthetic.main.fragment_search.* import java.util.concurrent.locks.ReentrantLock + class SearchFragment : Fragment() { companion object { fun List.filterSearchResponse(): List { @@ -360,18 +362,13 @@ class SearchFragment : Fragment() { typesActive = it.getApiTypeSettings() } - /*main_search.setOnQueryTextFocusChangeListener { searchView, b -> + main_search.setOnQueryTextFocusChangeListener { searchView, b -> if (b) { // https://stackoverflow.com/questions/12022715/unable-to-show-keyboard-automatically-in-the-searchview - searchView?.postDelayed({ - (activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager?)?.showSoftInput( - view.findFocus(), - 0 - ) - }, 200) + showInputMethod(view.findFocus()) } } - main_search.onActionViewExpanded()*/ + //main_search.onActionViewExpanded()*/ val masterAdapter: RecyclerView.Adapter = ParentItemAdapter(listOf(), { callback -> SearchHelper.handleSearchClickCallback(activity, callback) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt index 328090d3..f4fe9923 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt @@ -1,5 +1,8 @@ package com.lagradost.cloudstream3.ui.settings +import android.app.UiModeManager +import android.content.Context +import android.content.res.Configuration import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AlertDialog @@ -30,6 +33,22 @@ import kotlin.concurrent.thread class SettingsFragment : PreferenceFragmentCompat() { + companion object { + fun Context.isTvSettings(): Boolean { + val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) + var value = settingsManager.getInt(this.getString(R.string.app_layout_key), -1) + if (value == -1) { + value = if (isAutoTv()) 1 else 0 + } + return value == 1 + } + + private fun Context.isAutoTv(): Boolean { + val uiModeManager = getSystemService(Context.UI_MODE_SERVICE) as UiModeManager? + return uiModeManager?.currentModeType == Configuration.UI_MODE_TYPE_TELEVISION + } + } + private var beneneCount = 0 // idk, if you find a way of automating this it would be great @@ -61,6 +80,7 @@ class SettingsFragment : PreferenceFragmentCompat() { val legalPreference = findPreference(getString(R.string.legal_notice_key))!! val subdubPreference = findPreference(getString(R.string.display_sub_key))!! val providerLangPreference = findPreference(getString(R.string.provider_lang_key))!! + val allLayoutPreference = findPreference(getString(R.string.app_layout_key))!! legalPreference.setOnPreferenceClickListener { val builder: AlertDialog.Builder = AlertDialog.Builder(it.context) @@ -141,6 +161,29 @@ class SettingsFragment : PreferenceFragmentCompat() { return@setOnPreferenceClickListener true } + allLayoutPreference.setOnPreferenceClickListener { + val prefNames = resources.getStringArray(R.array.app_layout) + val prefValues = resources.getIntArray(R.array.app_layout_values) + val settingsManager = PreferenceManager.getDefaultSharedPreferences(context) + + val currentLayout = + settingsManager.getInt(getString(R.string.app_layout_key), -1) + context?.showBottomDialog( + prefNames.toList(), + prefValues.indexOf(currentLayout), + getString(R.string.app_layout), + true, + {}) { + try { + settingsManager.edit().putInt(getString(R.string.app_layout_key), prefValues[it]).apply() + activity?.recreate() + } catch (e : Exception) { + logError(e) + } + } + return@setOnPreferenceClickListener true + } + watchQualityPreference.setOnPreferenceClickListener { val prefNames = resources.getStringArray(R.array.quality_pref) val prefValues = resources.getIntArray(R.array.quality_pref_values) @@ -193,7 +236,7 @@ class SettingsFragment : PreferenceFragmentCompat() { settingsManager.edit().putInt(getString(R.string.benene_count), beneneCount).apply() it.summary = getString(R.string.benene_count_text).format(beneneCount) } catch (e: Exception) { - e.printStackTrace() + logError(e) } return@setOnPreferenceClickListener true diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt index ea6b1bec..a5d946de 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt @@ -36,6 +36,7 @@ import androidx.preference.PreferenceManager import com.bumptech.glide.load.model.GlideUrl import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.mvvm.logError +import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings import kotlin.math.roundToInt @@ -68,7 +69,7 @@ object UIHelper { activity?.window?.decorView?.clearFocus() view.let { if (it != null) { - activity?.hideKeyboard(it) + hideKeyboard(it) } } } @@ -202,6 +203,10 @@ object UIHelper { }*/ fun Context.getStatusBarHeight(): Int { + if(isTvSettings()) { + return 0 + } + var result = 0 val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android") if (resourceId > 0) { @@ -285,9 +290,14 @@ object UIHelper { ) == AppOpsManager.MODE_ALLOWED } - fun Context.hideKeyboard(view: View) { - val inputMethodManager = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager - inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0) + fun hideKeyboard(view: View) { + val inputMethodManager = view.context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager? + inputMethodManager?.hideSoftInputFromWindow(view.windowToken, 0) + } + + fun showInputMethod(view: View) { + val inputMethodManager = view.context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager? + inputMethodManager?.showSoftInput(view, 0) } /**id, stringRes */ diff --git a/app/src/main/res/drawable/ic_baseline_tv_24.xml b/app/src/main/res/drawable/ic_baseline_tv_24.xml new file mode 100644 index 00000000..d578ed0d --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_tv_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 7f949ab5..17903e53 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -6,7 +6,7 @@ android:id="@+id/homeRoot" android:layout_width="match_parent" android:layout_height="match_parent" - android:configChanges="orientation|screenSize|screenLayout|keyboardHidden" + android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|keyboard|navigation" android:paddingTop="0dp"> + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 1aa84a8d..307122fd 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -103,7 +103,7 @@ android:id="@+id/home_settings_bar" android:background="?attr/darkBackground" android:layout_width="match_parent" - android:layout_height="60dp"> + android:layout_height="70dp"> - + + diff --git a/app/src/main/res/values/array.xml b/app/src/main/res/values/array.xml index c2a1504f..1184d36b 100644 --- a/app/src/main/res/values/array.xml +++ b/app/src/main/res/values/array.xml @@ -68,4 +68,16 @@ 7 8 + + + @string/automatic + @string/phone_layout + @string/tv_layout + + + + -1 + 0 + 1 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e057a0f3..f0da348f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -24,7 +24,7 @@ show_fillers_key provider_lang_key dns_key - + app_layout_key %d %s | %sMB @@ -294,4 +294,9 @@ General Provider Languages + App Layout + + Auto + Tv Layout + Phone Layout diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index c866a536..c1af7fba 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -99,6 +99,16 @@ android:summary="@string/dns_pref_summary" android:icon="@drawable/ic_baseline_dns_24"> + + + + Date: Sat, 30 Oct 2021 20:42:58 +0200 Subject: [PATCH 07/26] android tv search focus --- .../lagradost/cloudstream3/MainActivity.kt | 35 ++++--------------- .../cloudstream3/ui/search/SearchFragment.kt | 2 ++ app/src/main/res/layout/provider_list.xml | 11 +++++- 3 files changed, 18 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index 8b1927d4..1f82890a 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -9,10 +9,8 @@ import android.content.pm.PackageManager import android.content.res.ColorStateList import android.content.res.Configuration import android.content.res.Resources -import android.graphics.Rect import android.os.Build import android.os.Bundle -import android.util.TypedValue import android.view.* import android.widget.TextView import android.widget.Toast @@ -52,7 +50,6 @@ import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.fragment_result.* import java.util.* import kotlin.concurrent.thread -import kotlin.math.roundToInt const val VLC_PACKAGE = "org.videolan.vlc" @@ -140,28 +137,8 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { } } - private fun Activity.getRootView(): View { - return findViewById(android.R.id.content) - } - - private fun Context.convertDpToPx(dp: Float): Float { - return TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, - dp, - this.resources.displayMetrics - ) - } - - private fun Activity.isKeyboardOpen(): Boolean { - val visibleBounds = Rect() - this.getRootView().getWindowVisibleDisplayFrame(visibleBounds) - val heightDiff = getRootView().height - visibleBounds.height() - val marginOfError = this.convertDpToPx(50F).roundToInt() - return heightDiff > marginOfError - } - override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { - println("Keycode: $keyCode") + //println("Keycode: $keyCode") //showToast( // this, // "Got Keycode $keyCode | ${KeyEvent.keyCodeToString(keyCode)} \n ${event?.action}", @@ -222,11 +199,11 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { playerEventListener?.invoke(playerEvent) } - when (keyCode) { - KeyEvent.KEYCODE_DPAD_CENTER -> { - println("DPAD PRESSED ${this.isKeyboardOpen()}") - } - } + //when (keyCode) { + // KeyEvent.KEYCODE_DPAD_CENTER -> { + // println("DPAD PRESSED ${this.isKeyboardOpen()}") + // } + //} return super.onKeyDown(keyCode, event) } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt index 4669a73e..959d8697 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt @@ -300,6 +300,8 @@ class SearchFragment : Fragment() { main_search.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String): Boolean { searchViewModel.searchAndCancel(query) + main_search?.clearFocus() + search_filter?.requestFocus() return true } diff --git a/app/src/main/res/layout/provider_list.xml b/app/src/main/res/layout/provider_list.xml index 0c8321d4..4300b8d8 100644 --- a/app/src/main/res/layout/provider_list.xml +++ b/app/src/main/res/layout/provider_list.xml @@ -13,6 +13,9 @@ - + Date: Sat, 30 Oct 2021 21:04:35 +0200 Subject: [PATCH 08/26] monke if this does not work then buy an android tv --- .../com/lagradost/cloudstream3/ui/search/SearchFragment.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt index 959d8697..caa9d78f 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt @@ -300,8 +300,10 @@ class SearchFragment : Fragment() { main_search.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String): Boolean { searchViewModel.searchAndCancel(query) - main_search?.clearFocus() - search_filter?.requestFocus() + main_search?.let { + hideKeyboard(it) + } + return true } From 1252ad45318c915244ce4cedbafbc55fb732816d Mon Sep 17 00:00:00 2001 From: cutterchop <31880937+cutterchop@users.noreply.github.com> Date: Sat, 30 Oct 2021 20:09:00 +0100 Subject: [PATCH 09/26] Arabic translation fix #69 (#185) Co-authored-by: Arjix <53124886+ArjixWasTaken@users.noreply.github.com> --- app/src/main/res/values-ar/strings.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 07980d4f..041cf991 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -25,7 +25,7 @@ لايوجد بيانات المزيد من الخيارات الحلقة القادمة - الأنواع + النواع شارك فتح في الويب تخطي التحميل @@ -106,7 +106,7 @@ قد تكون هناك حاجة إلى شبكة ظاهرية خاصة لكي يعمل هذا المزود بشكل صحيح هذا المزود هو تورنت ، يوصى باستخدام شبكة ظاهرية خاصة الوصف - لم يتم العثور على قطعة + لم يتم العثور على وصف لم يتم العثور على وصف صورة داخل صورة @@ -116,7 +116,7 @@ الترجمة إعدادات ترجمة المشغل وضع إيغنغرافي - يضيف خيار السرعة في اللاعب + يضيف خيار السرعة في المشغل اسحب للسعي اسحب إلى اليسار أو اليمين للتحكم في الوقت في مشغل الفيديو اسحب لتغيير الإعدادات @@ -129,7 +129,7 @@ بحث معلومات البحث المتقدم - يعطيك نتائج البحث مفصولة عن طريق مزود + يعطيك نتائج البحث مفصولة عن طريق المزود إرسال البيانات عن الأعطال فقط لا ترسل أي بيانات عرض حلقة فلر لأنيمي @@ -184,7 +184,7 @@ تطبيق أفلام - مسلسلت + مسلسلات رسوم متحركة انمي تورنت From 44100c4e0925406359b662955f99a7d3e78e1761 Mon Sep 17 00:00:00 2001 From: Arjix <53124886+ArjixWasTaken@users.noreply.github.com> Date: Sat, 30 Oct 2021 23:20:46 +0300 Subject: [PATCH 10/26] Extracted quality from AllAnime m3u8 streams. (Untested) --- .../animeproviders/AllAnimeProvider.kt | 60 +++++++++++++------ 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt index b141089a..a72c21a5 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt @@ -1,6 +1,7 @@ package com.lagradost.cloudstream3.animeproviders import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.network.get import com.lagradost.cloudstream3.network.text import com.lagradost.cloudstream3.utils.ExtractorLink @@ -26,6 +27,8 @@ class AllAnimeProvider : MainAPI() { get() = false override val hasMainPage: Boolean get() = false + + private val hlsHelper = M3u8Helper() private fun getStatus(t: String): ShowStatus { return when (t) { @@ -243,6 +246,21 @@ class AllAnimeProvider : MainAPI() { private data class ApiEndPoint( @JsonProperty("episodeIframeHead") val episodeIframeHead: String ) + + private fun getM3u8Qualities(m3u8Link: String, referer: String): ArrayList { + return ArrayList(hlsHelper.m3u8Generation(M3u8Helper.M3u8Stream(m3u8Link, null), true).map { stream -> + val qualityString = if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p" + ExtractorLink( + this.name, + "${this.name} $qualityString", + stream.streamUrl, + referer, + getQualityFromName(stream.quality.toString()), + true, + stream.headers + ) + }) + } override fun loadLinks( data: String, @@ -264,16 +282,20 @@ class AllAnimeProvider : MainAPI() { if (Regex("""streaming\.php\?""").matches(link)) { // for now ignore } else if (!embedIsBlacklisted(link)) { - callback( - ExtractorLink( - "AllAnime - " + URI(link).host, - "", - link, - data, - getQualityFromName("1080"), - URI(link).path.contains(".m3u") + if (URI(link).path.contains(".m3u")) { + getM3u8Qualities(link, referer).forEach(callback) + } else { + callback( + ExtractorLink( + "AllAnime - " + URI(link).host, + "", + link, + data, + getQualityFromName("1080"), + false + ) ) - ) + } } } else { link = apiEndPoint + URI(link).path + ".json?" + URI(link).query @@ -282,14 +304,18 @@ class AllAnimeProvider : MainAPI() { if (response.code < 400) { val links = mapper.readValue(response.text).links links.forEach { server -> - callback(ExtractorLink( - "AllAnime - " + URI(server.link).host, - server.resolutionStr, - server.link, - "$apiEndPoint/player?uri=" + (if (URI(server.link).host.isNotEmpty()) server.link else apiEndPoint + URI(server.link).path), - getQualityFromName("1080"), - server.hls != null && server.hls - )) + if (server.hls != null && server.hls) { + getM3u8Qualities(server.link, "$apiEndPoint/player?uri=" + (if (URI(server.link).host.isNotEmpty()) server.link else apiEndPoint + URI(server.link).path)).forEach(callback) + } else { + callback(ExtractorLink( + "AllAnime - " + URI(server.link).host, + server.resolutionStr, + server.link, + "$apiEndPoint/player?uri=" + (if (URI(server.link).host.isNotEmpty()) server.link else apiEndPoint + URI(server.link).path), + getQualityFromName("1080"), + false + )) + } } } } From 0687079889ababc5a563f7861d338954a2bd2750 Mon Sep 17 00:00:00 2001 From: Arjix <53124886+ArjixWasTaken@users.noreply.github.com> Date: Sat, 30 Oct 2021 23:24:44 +0300 Subject: [PATCH 11/26] Update AllAnimeProvider.kt --- .../lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt index a72c21a5..fdb316f5 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt @@ -283,7 +283,7 @@ class AllAnimeProvider : MainAPI() { // for now ignore } else if (!embedIsBlacklisted(link)) { if (URI(link).path.contains(".m3u")) { - getM3u8Qualities(link, referer).forEach(callback) + getM3u8Qualities(link, data).forEach(callback) } else { callback( ExtractorLink( From ddccd31f0f39ef7072084f3457cac7cc3eba557e Mon Sep 17 00:00:00 2001 From: Arjix <53124886+ArjixWasTaken@users.noreply.github.com> Date: Sat, 30 Oct 2021 23:35:03 +0300 Subject: [PATCH 12/26] Update AllAnimeProvider.kt --- .../cloudstream3/animeproviders/AllAnimeProvider.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt index fdb316f5..9fb45c00 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/AllAnimeProvider.kt @@ -247,12 +247,12 @@ class AllAnimeProvider : MainAPI() { @JsonProperty("episodeIframeHead") val episodeIframeHead: String ) - private fun getM3u8Qualities(m3u8Link: String, referer: String): ArrayList { + private fun getM3u8Qualities(m3u8Link: String, referer: String, qualityName: String): ArrayList { return ArrayList(hlsHelper.m3u8Generation(M3u8Helper.M3u8Stream(m3u8Link, null), true).map { stream -> val qualityString = if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p" ExtractorLink( this.name, - "${this.name} $qualityString", + "${this.name} - $qualityName $qualityString", stream.streamUrl, referer, getQualityFromName(stream.quality.toString()), @@ -283,7 +283,7 @@ class AllAnimeProvider : MainAPI() { // for now ignore } else if (!embedIsBlacklisted(link)) { if (URI(link).path.contains(".m3u")) { - getM3u8Qualities(link, data).forEach(callback) + getM3u8Qualities(link, data, URI(link).host).forEach(callback) } else { callback( ExtractorLink( @@ -305,7 +305,7 @@ class AllAnimeProvider : MainAPI() { val links = mapper.readValue(response.text).links links.forEach { server -> if (server.hls != null && server.hls) { - getM3u8Qualities(server.link, "$apiEndPoint/player?uri=" + (if (URI(server.link).host.isNotEmpty()) server.link else apiEndPoint + URI(server.link).path)).forEach(callback) + getM3u8Qualities(server.link, "$apiEndPoint/player?uri=" + (if (URI(server.link).host.isNotEmpty()) server.link else apiEndPoint + URI(server.link).path), server.resolutionStr).forEach(callback) } else { callback(ExtractorLink( "AllAnime - " + URI(server.link).host, From 173face342f0e900a30030d45e5e47b2eb2c25fd Mon Sep 17 00:00:00 2001 From: LagradOst Date: Sun, 31 Oct 2021 02:17:56 +0100 Subject: [PATCH 13/26] colorprimary and prep for flashbang --- app/build.gradle | 5 +- .../lagradost/cloudstream3/MainActivity.kt | 24 +++++ .../cloudstream3/ui/player/PlayerFragment.kt | 9 +- .../cloudstream3/ui/result/ResultFragment.kt | 28 ++--- .../ui/settings/SettingsFragment.kt | 23 ++++ .../drawable/ic_baseline_color_lens_24.xml | 5 + app/src/main/res/drawable/outline_card.xml | 2 +- app/src/main/res/drawable/tab_selector.xml | 2 +- app/src/main/res/layout/activity_main.xml | 4 +- app/src/main/res/layout/activity_main_tv.xml | 4 +- app/src/main/res/layout/dialog_loading.xml | 23 ++-- .../res/layout/download_child_episode.xml | 5 +- .../res/layout/download_header_episode.xml | 6 +- .../res/layout/fragment_child_downloads.xml | 4 +- .../main/res/layout/fragment_downloads.xml | 5 +- app/src/main/res/layout/fragment_home.xml | 11 +- app/src/main/res/layout/fragment_result.xml | 12 ++- app/src/main/res/layout/fragment_search.xml | 4 +- .../res/layout/home_episodes_expanded.xml | 2 +- .../main/res/layout/home_result_big_grid.xml | 6 +- app/src/main/res/layout/home_result_grid.xml | 2 +- app/src/main/res/layout/homepage_parent.xml | 1 + .../main/res/layout/player_custom_layout.xml | 6 ++ app/src/main/res/layout/result_episode.xml | 3 +- .../main/res/layout/result_episode_large.xml | 8 +- .../main/res/layout/search_result_grid.xml | 4 +- .../layout/search_result_super_compact.xml | 2 +- app/src/main/res/values/array.xml | 21 ++++ app/src/main/res/values/attrs.xml | 3 +- app/src/main/res/values/colors.xml | 23 +++- app/src/main/res/values/strings.xml | 3 + app/src/main/res/values/styles.xml | 100 ++++++++++++++++-- app/src/main/res/xml/settings.xml | 5 + 33 files changed, 291 insertions(+), 74 deletions(-) create mode 100644 app/src/main/res/drawable/ic_baseline_color_lens_24.xml diff --git a/app/build.gradle b/app/build.gradle index 119700d4..f236b425 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,8 +34,9 @@ android { applicationId "com.lagradost.cloudstream3" minSdkVersion 21 targetSdkVersion 31 - versionCode 32 - versionName "2.1.2" + + versionCode 33 + versionName "2.2.2" resValue "string", "app_version", "${defaultConfig.versionName}${versionNameSuffix ?: ""}" diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index 1f82890a..1291dbd8 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -365,6 +365,30 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { R.style.LoadedStyle, true ) // THEME IS SET BEFORE VIEW IS CREATED TO APPLY THE THEME TO THE MAIN VIEW + + val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) + + val currentTheme = when (settingsManager.getString("theme", "")) { + "Black" -> R.style.AppTheme + "Light" -> R.style.LightMode + else -> R.style.AppTheme + } + + val currentOverlayTheme = when (settingsManager.getString(getString(R.string.primary_color_key), "Normal")) { + "Normal" -> R.style.OverlayPrimaryColorNormal + "Blue" -> R.style.OverlayPrimaryColorBlue + "Purple" -> R.style.OverlayPrimaryColorPurple + "Green" -> R.style.OverlayPrimaryColorGreen + "GreenApple" -> R.style.OverlayPrimaryColorGreenApple + "Red" -> R.style.OverlayPrimaryColorRed + "Banana" -> R.style.OverlayPrimaryColorBanana + "Party" -> R.style.OverlayPrimaryColorParty + else -> R.style.OverlayPrimaryColorNormal + } + + //theme.applyStyle(currentTheme, true) + theme.applyStyle(currentOverlayTheme, true) + updateLocale() initRequestClient() super.onCreate(savedInstanceState) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt index 72d3bfcb..3d29c87b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt @@ -89,6 +89,7 @@ import com.lagradost.cloudstream3.utils.DataStore.setKey import com.lagradost.cloudstream3.utils.DataStoreHelper.setLastWatched import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showDialog +import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute import com.lagradost.cloudstream3.utils.UIHelper.getNavigationBarHeight import com.lagradost.cloudstream3.utils.UIHelper.getStatusBarHeight import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard @@ -869,11 +870,13 @@ class PlayerFragment : Fragment() { private fun updateLock() { video_locked_img?.setImageResource(if (isLocked) R.drawable.video_locked else R.drawable.video_unlocked) - val color = if (isLocked) ContextCompat.getColor(requireContext(), R.color.videoColorPrimary) + val color = if (isLocked) context?.colorFromAttribute(R.attr.colorPrimary) else Color.WHITE - video_locked_text?.setTextColor(color) - video_locked_img?.setColorFilter(color) + if(color != null) { + video_locked_text?.setTextColor(color) + video_locked_img?.setColorFilter(color) + } val isClick = !isLocked 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 8752a17c..b14b0712 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 @@ -18,7 +18,6 @@ import android.view.ViewGroup import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.coordinatorlayout.widget.CoordinatorLayout -import androidx.core.content.ContextCompat import androidx.core.content.FileProvider import androidx.core.text.color import androidx.core.view.isVisible @@ -196,7 +195,7 @@ class ResultFragment : Fragment() { super.onDestroy() activity?.let { it.window?.navigationBarColor = - it.colorFromAttribute(R.attr.darkBackground) + it.colorFromAttribute(R.attr.primaryGrayBackground) } } @@ -959,20 +958,23 @@ class ResultFragment : Fragment() { metadataInfoArray.add(Pair(R.string.site, d.apiName)) - if (metadataInfoArray.size > 0) { - result_metadata.visibility = VISIBLE - val text = SpannableStringBuilder() - val grayColor = ContextCompat.getColor(requireContext(), R.color.grayTextColor) - val textColor = ContextCompat.getColor(requireContext(), R.color.textColor) - for (meta in metadataInfoArray) { - text.color(grayColor) { append(getString(meta.first) + ": ") } - .color(textColor) { append("${meta.second}\n") } + context?.let { ctx -> + if (metadataInfoArray.size > 0) { + result_metadata.visibility = VISIBLE + val text = SpannableStringBuilder() + val grayColor = ctx.colorFromAttribute(R.attr.grayTextColor) //ContextCompat.getColor(requireContext(), R.color.grayTextColor) + val textColor = ctx.colorFromAttribute(R.attr.textColor) //ContextCompat.getColor(requireContext(), R.color.textColor) + for (meta in metadataInfoArray) { + text.color(grayColor) { append(getString(meta.first) + ": ") } + .color(textColor) { append("${meta.second}\n") } + } + result_metadata.text = text + } else { + result_metadata.visibility = GONE } - result_metadata.text = text - } else { - result_metadata.visibility = GONE } + result_poster?.setImage(d.posterUrl) result_poster_holder?.visibility = if (d.posterUrl.isNullOrBlank()) GONE else VISIBLE diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt index f4fe9923..89e5d65f 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsFragment.kt @@ -81,6 +81,7 @@ class SettingsFragment : PreferenceFragmentCompat() { val subdubPreference = findPreference(getString(R.string.display_sub_key))!! val providerLangPreference = findPreference(getString(R.string.provider_lang_key))!! val allLayoutPreference = findPreference(getString(R.string.app_layout_key))!! + val colorPrimaryPreference = findPreference(getString(R.string.primary_color_key))!! legalPreference.setOnPreferenceClickListener { val builder: AlertDialog.Builder = AlertDialog.Builder(it.context) @@ -184,6 +185,28 @@ class SettingsFragment : PreferenceFragmentCompat() { return@setOnPreferenceClickListener true } + colorPrimaryPreference.setOnPreferenceClickListener { + val prefNames = resources.getStringArray(R.array.themes_overlay_names) + val prefValues = resources.getStringArray(R.array.themes_overlay_names_values) + val settingsManager = PreferenceManager.getDefaultSharedPreferences(context) + + val currentLayout = settingsManager.getString( getString(R.string.primary_color_key),prefValues.first()) + context?.showBottomDialog( + prefNames.toList(), + prefValues.indexOf(currentLayout), + getString(R.string.primary_color_settings), + true, + {}) { + try { + settingsManager.edit().putString(getString(R.string.primary_color_key), prefValues[it]).apply() + activity?.recreate() + } catch (e : Exception) { + logError(e) + } + } + return@setOnPreferenceClickListener true + } + watchQualityPreference.setOnPreferenceClickListener { val prefNames = resources.getStringArray(R.array.quality_pref) val prefValues = resources.getIntArray(R.array.quality_pref_values) diff --git a/app/src/main/res/drawable/ic_baseline_color_lens_24.xml b/app/src/main/res/drawable/ic_baseline_color_lens_24.xml new file mode 100644 index 00000000..b87ca001 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_color_lens_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/outline_card.xml b/app/src/main/res/drawable/outline_card.xml index 442c662e..02116bb8 100644 --- a/app/src/main/res/drawable/outline_card.xml +++ b/app/src/main/res/drawable/outline_card.xml @@ -14,7 +14,7 @@ - + diff --git a/app/src/main/res/drawable/tab_selector.xml b/app/src/main/res/drawable/tab_selector.xml index ab31dbf8..92bb27dd 100644 --- a/app/src/main/res/drawable/tab_selector.xml +++ b/app/src/main/res/drawable/tab_selector.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 17903e53..078e52f9 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -15,7 +15,7 @@ android:id="@+id/nav_view" android:layout_width="0dp" android:layout_height="wrap_content" - android:background="?attr/darkBackground" + android:background="?attr/primaryGrayBackground" app:labelVisibilityMode="labeled" @@ -41,7 +41,7 @@ > - + android:layout_height="match_parent"> + - + @@ -71,7 +71,7 @@ android:layout_gravity="center_vertical" android:gravity="center_vertical" tools:text="128MB / 237MB" - android:textColor="@color/grayTextColor" + android:textColor="?attr/grayTextColor" android:layout_width="wrap_content" android:layout_height="match_parent"> @@ -111,6 +111,7 @@ android:layout_width="30dp" android:background="?selectableItemBackgroundBorderless" android:src="@drawable/ic_baseline_play_arrow_24" + android:tint="?attr/textColor" android:contentDescription="@string/download"/> diff --git a/app/src/main/res/layout/download_header_episode.xml b/app/src/main/res/layout/download_header_episode.xml index ff4c62cf..cc52646a 100644 --- a/app/src/main/res/layout/download_header_episode.xml +++ b/app/src/main/res/layout/download_header_episode.xml @@ -6,7 +6,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" app:cardCornerRadius="@dimen/roundedImageRadius" - app:cardBackgroundColor="@color/itemBackground" + app:cardBackgroundColor="?attr/boxItemBackground" android:id="@+id/episode_holder" android:foreground="@drawable/outline_drawable" android:layout_marginBottom="10dp" @@ -41,14 +41,14 @@ android:id="@+id/download_header_title" tools:text="Perfect Run" android:textStyle="bold" - android:textColor="@color/textColor" + android:textColor="?attr/textColor" android:layout_width="wrap_content" android:layout_height="wrap_content"> diff --git a/app/src/main/res/layout/fragment_child_downloads.xml b/app/src/main/res/layout/fragment_child_downloads.xml index 7f914cb6..6ad31711 100644 --- a/app/src/main/res/layout/fragment_child_downloads.xml +++ b/app/src/main/res/layout/fragment_child_downloads.xml @@ -1,6 +1,6 @@ - #1E1E32 #F53B66 #3700B3 #3b65f5 @@ -11,12 +10,11 @@ #2B2C30 #111111 #1C1C20 - #161616 + #161616 #e9eaee #9ba0a4 - @color/textColor #1AFFFFFF #00000000 @@ -34,10 +32,27 @@ #121212 #66B5B5B5 - @color/colorPrimary #9ba0a6 #FFF #676767 + + + #fff + #EFEFEF + #FFF + #EDEDED + #202125 + #5f6267 + #5f6267 + + + #5664B7 + #D50000 + #6200EA + #00BFA5 + #48E484 + #E4D448 + #ea596e \ 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 f0da348f..39ba9ec3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -25,6 +25,7 @@ provider_lang_key dns_key app_layout_key + primary_color_key %d %s | %sMB @@ -299,4 +300,6 @@ Auto Tv Layout Phone Layout + + Primary Color diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 7e577030..da07f6dc 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -8,8 +8,8 @@ ?attr/iconGrayBackground - @color/searchColor - @color/textColor + ?attr/textColor + ?attr/textColor @null @null @@ -37,17 +37,102 @@ @color/colorPrimaryDark @color/colorAccent @color/textColor - @color/colorItemSeen @color/grayTextColor - @color/primaryGrayBackground + @color/primaryGrayBackground @color/primaryBlackBackground @color/iconGrayBackground - @color/itemBackground + @color/boxItemBackground @color/iconColor #FFF + + + + + + + + + + + + + + + + + + + + + + +