mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master'
This commit is contained in:
		
						commit
						e1128e7a39
					
				
					 8 changed files with 316 additions and 13 deletions
				
			
		| 
						 | 
				
			
			@ -131,6 +131,7 @@ object APIHolder {
 | 
			
		|||
            NineAnimeProvider(),
 | 
			
		||||
            AnimeWorldProvider(),
 | 
			
		||||
            AnimeSaturnProvider(),
 | 
			
		||||
            AniPlayProvider(),
 | 
			
		||||
            ZoroProvider(),
 | 
			
		||||
            DubbedAnimeProvider(),
 | 
			
		||||
            MonoschinosProvider(),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,215 @@
 | 
			
		|||
package com.lagradost.cloudstream3.animeproviders
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonProperty
 | 
			
		||||
import com.lagradost.cloudstream3.*
 | 
			
		||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
 | 
			
		||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addDuration
 | 
			
		||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
 | 
			
		||||
import com.lagradost.cloudstream3.utils.ExtractorLink
 | 
			
		||||
import com.lagradost.cloudstream3.utils.M3u8Helper
 | 
			
		||||
import com.lagradost.cloudstream3.utils.Qualities
 | 
			
		||||
 | 
			
		||||
class AniPlayProvider : MainAPI() {
 | 
			
		||||
    override var mainUrl = "https://aniplay.it"
 | 
			
		||||
    override var name = "AniPlay"
 | 
			
		||||
    override var lang = "it"
 | 
			
		||||
    override val hasMainPage = true
 | 
			
		||||
    private val dubIdentifier = " (ITA)"
 | 
			
		||||
 | 
			
		||||
    override val supportedTypes = setOf(
 | 
			
		||||
        TvType.Anime,
 | 
			
		||||
        TvType.AnimeMovie,
 | 
			
		||||
        TvType.OVA
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        fun getStatus(t: String?): ShowStatus? {
 | 
			
		||||
            return when (t?.lowercase()) {
 | 
			
		||||
                "completato" -> ShowStatus.Completed
 | 
			
		||||
                "in corso" -> ShowStatus.Ongoing
 | 
			
		||||
                else -> null // "annunciato"
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        fun getType(t: String?): TvType {
 | 
			
		||||
            return when (t?.lowercase()) {
 | 
			
		||||
                "ona" -> TvType.OVA
 | 
			
		||||
                "movie" -> TvType.AnimeMovie
 | 
			
		||||
                else -> TvType.Anime //"serie", "special"
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun isDub(title: String): Boolean{
 | 
			
		||||
        return title.contains(dubIdentifier)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    data class ApiPoster(
 | 
			
		||||
        @JsonProperty("imageFull") val posterUrl: String
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    data class ApiMainPageAnime(
 | 
			
		||||
        @JsonProperty("animeId") val id: Int,
 | 
			
		||||
        @JsonProperty("episodeNumber") val episode: String?,
 | 
			
		||||
        @JsonProperty("animeTitle") val title: String,
 | 
			
		||||
        @JsonProperty("animeType") val type: String,
 | 
			
		||||
        @JsonProperty("fullHd") val fullHD: Boolean,
 | 
			
		||||
        @JsonProperty("animeVerticalImages") val posters: List<ApiPoster>
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    data class ApiSearchResult(
 | 
			
		||||
        @JsonProperty("id") val id: Int,
 | 
			
		||||
        @JsonProperty("title") val title: String,
 | 
			
		||||
        @JsonProperty("status") val status: String,
 | 
			
		||||
        @JsonProperty("type") val type: String,
 | 
			
		||||
        @JsonProperty("verticalImages") val posters: List<ApiPoster>
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    data class ApiGenres(
 | 
			
		||||
        @JsonProperty("description") val name: String
 | 
			
		||||
    )
 | 
			
		||||
    data class ApiWebsite(
 | 
			
		||||
        @JsonProperty("listWebsiteId") val websiteId: Int,
 | 
			
		||||
        @JsonProperty("url") val url: String
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    data class ApiEpisode(
 | 
			
		||||
        @JsonProperty("id") val id: Int,
 | 
			
		||||
        @JsonProperty("title") val title: String?,
 | 
			
		||||
        @JsonProperty("episodeNumber") val number: String,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    private fun ApiEpisode.toEpisode() : Episode? {
 | 
			
		||||
        val number = this.number.toIntOrNull() ?: return null
 | 
			
		||||
        return Episode(
 | 
			
		||||
            data = "$mainUrl/api/episode/${this.id}",
 | 
			
		||||
            episode = number,
 | 
			
		||||
            name = this.title
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    data class ApiSeason(
 | 
			
		||||
        @JsonProperty("id") val id: Int,
 | 
			
		||||
        @JsonProperty("name") val name: String
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    private suspend fun ApiSeason.toEpisodeList(url: String) : List<Episode> {
 | 
			
		||||
        return app.get("$url/season/${this.id}").parsed<List<ApiEpisode>>().mapNotNull { it.toEpisode() }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    data class ApiAnime(
 | 
			
		||||
        @JsonProperty("title") val title: String,
 | 
			
		||||
        @JsonProperty("alternativeTitle") val japTitle: String?,
 | 
			
		||||
        @JsonProperty("episodeDuration") val duration: Int,
 | 
			
		||||
        @JsonProperty("storyline") val plot: String,
 | 
			
		||||
        @JsonProperty("type") val type: String,
 | 
			
		||||
        @JsonProperty("status") val status: String,
 | 
			
		||||
        @JsonProperty("genres") val genres: List<ApiGenres>,
 | 
			
		||||
        @JsonProperty("verticalImages") val posters: List<ApiPoster>,
 | 
			
		||||
        @JsonProperty("listWebsites") val websites: List<ApiWebsite>,
 | 
			
		||||
        @JsonProperty("episodes") val episodes: List<ApiEpisode>,
 | 
			
		||||
        @JsonProperty("seasons") val seasons: List<ApiSeason>?
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    data class ApiEpisodeUrl(
 | 
			
		||||
        @JsonProperty("videoUrl") val url: String
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    override suspend fun getMainPage(): HomePageResponse {
 | 
			
		||||
        val response = app.get("$mainUrl/api/home/latest-episodes?page=0").parsed<List<ApiMainPageAnime>>()
 | 
			
		||||
 | 
			
		||||
        val results = response.map{
 | 
			
		||||
            val isDub = isDub(it.title)
 | 
			
		||||
            newAnimeSearchResponse(
 | 
			
		||||
                name = if (isDub) it.title.replace(dubIdentifier, "") else it.title,
 | 
			
		||||
                url = "$mainUrl/api/anime/${it.id}",
 | 
			
		||||
                type = getType(it.type),
 | 
			
		||||
            ){
 | 
			
		||||
                addDubStatus(isDub, it.episode?.toIntOrNull())
 | 
			
		||||
                this.posterUrl = it.posters.first().posterUrl
 | 
			
		||||
                this.quality = if (it.fullHD) SearchQuality.HD else null
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return HomePageResponse(listOf(HomePageList("Ultime uscite",results)))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun search(query: String): List<SearchResponse> {
 | 
			
		||||
        val response = app.get("$mainUrl/api/anime/advanced-search?page=0&size=36&query=$query").parsed<List<ApiSearchResult>>()
 | 
			
		||||
 | 
			
		||||
        return response.map {
 | 
			
		||||
            val isDub = isDub(it.title)
 | 
			
		||||
 | 
			
		||||
            newAnimeSearchResponse(
 | 
			
		||||
                name = if (isDub) it.title.replace(dubIdentifier, "") else it.title,
 | 
			
		||||
                url = "$mainUrl/api/anime/${it.id}",
 | 
			
		||||
                type = getType(it.type),
 | 
			
		||||
            ){
 | 
			
		||||
                addDubStatus(isDub)
 | 
			
		||||
                this.posterUrl = it.posters.first().posterUrl
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun load(url: String): LoadResponse {
 | 
			
		||||
 | 
			
		||||
        val response = app.get(url).parsed<ApiAnime>()
 | 
			
		||||
 | 
			
		||||
        val tags: List<String> = response.genres.map { it.name }
 | 
			
		||||
 | 
			
		||||
        val malId: Int? = response.websites.find { it.websiteId == 1 }?.url?.removePrefix("https://myanimelist.net/anime/")?.split("/")?.first()?.toIntOrNull()
 | 
			
		||||
        val aniListId: Int? = response.websites.find { it.websiteId == 4 }?.url?.removePrefix("https://anilist.co/anime/")?.split("/")?.first()?.toIntOrNull()
 | 
			
		||||
 | 
			
		||||
        val episodes = if (response.seasons.isNullOrEmpty()) response.episodes.mapNotNull { it.toEpisode() } else response.seasons.map{ it.toEpisodeList(url) }.flatten()
 | 
			
		||||
        val isDub = isDub(response.title)
 | 
			
		||||
 | 
			
		||||
        return newAnimeLoadResponse(response.title, url, getType(response.type)) {
 | 
			
		||||
            this.name = if (isDub) response.title.replace(dubIdentifier, "") else response.title
 | 
			
		||||
            this.japName = response.japTitle
 | 
			
		||||
            this.plot = response.plot
 | 
			
		||||
            this.tags = tags
 | 
			
		||||
            this.showStatus = getStatus(response.status)
 | 
			
		||||
            addPoster(response.posters.first().posterUrl)
 | 
			
		||||
            addEpisodes(if (isDub) DubStatus.Dubbed else DubStatus.Subbed, episodes)
 | 
			
		||||
            addMalId(malId)
 | 
			
		||||
            addAniListId(aniListId)
 | 
			
		||||
            addDuration(response.duration.toString())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun loadLinks(
 | 
			
		||||
        data: String,
 | 
			
		||||
        isCasting: Boolean,
 | 
			
		||||
        subtitleCallback: (SubtitleFile) -> Unit,
 | 
			
		||||
        callback: (ExtractorLink) -> Unit
 | 
			
		||||
    ): Boolean {
 | 
			
		||||
 | 
			
		||||
        val episode = app.get(data).parsed<ApiEpisodeUrl>()
 | 
			
		||||
 | 
			
		||||
        if(episode.url.contains(".m3u8")){
 | 
			
		||||
            val m3u8Helper = M3u8Helper()
 | 
			
		||||
            val streams = m3u8Helper.m3u8Generation(M3u8Helper.M3u8Stream(episode.url,Qualities.Unknown.value), false)
 | 
			
		||||
 | 
			
		||||
            streams.forEach {
 | 
			
		||||
                callback.invoke(
 | 
			
		||||
                    ExtractorLink(
 | 
			
		||||
                        name,
 | 
			
		||||
                        name,
 | 
			
		||||
                        it.streamUrl,
 | 
			
		||||
                        referer = mainUrl,
 | 
			
		||||
                        quality = it.quality ?: Qualities.Unknown.value,
 | 
			
		||||
                        isM3u8 = it.streamUrl.contains(".m3u8"))) }
 | 
			
		||||
            return true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        callback.invoke(
 | 
			
		||||
            ExtractorLink(
 | 
			
		||||
                name,
 | 
			
		||||
                name,
 | 
			
		||||
                episode.url,
 | 
			
		||||
                referer = mainUrl,
 | 
			
		||||
                quality = Qualities.Unknown.value,
 | 
			
		||||
                isM3u8 = false,
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
        return true
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -3,6 +3,7 @@ package com.lagradost.cloudstream3.ui.home
 | 
			
		|||
import android.annotation.SuppressLint
 | 
			
		||||
import android.app.Activity
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.content.DialogInterface
 | 
			
		||||
import android.content.Intent
 | 
			
		||||
import android.content.res.Configuration
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
| 
						 | 
				
			
			@ -11,6 +12,7 @@ import android.view.LayoutInflater
 | 
			
		|||
import android.view.View
 | 
			
		||||
import android.view.ViewGroup
 | 
			
		||||
import android.widget.*
 | 
			
		||||
import androidx.appcompat.app.AlertDialog
 | 
			
		||||
import androidx.appcompat.widget.SearchView
 | 
			
		||||
import androidx.core.view.isGone
 | 
			
		||||
import androidx.core.view.isVisible
 | 
			
		||||
| 
						 | 
				
			
			@ -50,6 +52,8 @@ import com.lagradost.cloudstream3.utils.AppUtils.loadSearchResult
 | 
			
		|||
import com.lagradost.cloudstream3.utils.DataStore.getKey
 | 
			
		||||
import com.lagradost.cloudstream3.utils.DataStore.setKey
 | 
			
		||||
import com.lagradost.cloudstream3.utils.DataStoreHelper
 | 
			
		||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.deleteAllBookmarkedData
 | 
			
		||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.deleteAllResumeStateIds
 | 
			
		||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.removeLastWatched
 | 
			
		||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultWatchState
 | 
			
		||||
import com.lagradost.cloudstream3.utils.Event
 | 
			
		||||
| 
						 | 
				
			
			@ -91,6 +95,7 @@ import kotlinx.android.synthetic.main.fragment_home.home_watch_holder
 | 
			
		|||
import kotlinx.android.synthetic.main.fragment_home.home_watch_parent_item_title
 | 
			
		||||
import kotlinx.android.synthetic.main.fragment_home.result_error_text
 | 
			
		||||
import kotlinx.android.synthetic.main.fragment_home_tv.*
 | 
			
		||||
import kotlinx.android.synthetic.main.home_episodes_expanded.*
 | 
			
		||||
import java.util.*
 | 
			
		||||
 | 
			
		||||
const val HOME_BOOKMARK_VALUE_LIST = "home_bookmarked_last_list"
 | 
			
		||||
| 
						 | 
				
			
			@ -117,7 +122,7 @@ class HomeFragment : Fragment() {
 | 
			
		|||
 | 
			
		||||
        val errorProfilePic = errorProfilePics.random()
 | 
			
		||||
 | 
			
		||||
        fun Activity.loadHomepageList(item: HomePageList) {
 | 
			
		||||
        fun Activity.loadHomepageList(item: HomePageList, deleteCallback: (() -> Unit)? = null) {
 | 
			
		||||
            val context = this
 | 
			
		||||
            val bottomSheetDialogBuilder = BottomSheetDialog(context)
 | 
			
		||||
            bottomSheetDialogBuilder.setContentView(R.layout.home_episodes_expanded)
 | 
			
		||||
| 
						 | 
				
			
			@ -128,10 +133,44 @@ class HomeFragment : Fragment() {
 | 
			
		|||
            val titleHolder =
 | 
			
		||||
                bottomSheetDialogBuilder.findViewById<FrameLayout>(R.id.home_expanded_drag_down)!!
 | 
			
		||||
 | 
			
		||||
            val delete = bottomSheetDialogBuilder.home_expanded_delete
 | 
			
		||||
            delete.isGone = deleteCallback == null
 | 
			
		||||
            if (deleteCallback != null) {
 | 
			
		||||
                delete.setOnClickListener {
 | 
			
		||||
                    try {
 | 
			
		||||
                        val builder: AlertDialog.Builder = AlertDialog.Builder(context)
 | 
			
		||||
                        val dialogClickListener =
 | 
			
		||||
                            DialogInterface.OnClickListener { _, which ->
 | 
			
		||||
                                when (which) {
 | 
			
		||||
                                    DialogInterface.BUTTON_POSITIVE -> {
 | 
			
		||||
                                        deleteCallback.invoke()
 | 
			
		||||
                                        bottomSheetDialogBuilder.dismissSafe(this)
 | 
			
		||||
                                    }
 | 
			
		||||
                                    DialogInterface.BUTTON_NEGATIVE -> {}
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                        builder.setTitle(R.string.delete_file)
 | 
			
		||||
                            .setMessage(
 | 
			
		||||
                                context.getString(R.string.delete_message).format(
 | 
			
		||||
                                    item.name
 | 
			
		||||
                                )
 | 
			
		||||
                            )
 | 
			
		||||
                            .setPositiveButton(R.string.delete, dialogClickListener)
 | 
			
		||||
                            .setNegativeButton(R.string.cancel, dialogClickListener)
 | 
			
		||||
                            .show()
 | 
			
		||||
                    } catch (e: Exception) {
 | 
			
		||||
                        logError(e)
 | 
			
		||||
                        // ye you somehow fucked up formatting did you?
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            titleHolder.setOnClickListener {
 | 
			
		||||
                bottomSheetDialogBuilder.dismissSafe(this)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            // Span settings
 | 
			
		||||
            recycle.spanCount = currentSpan
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -642,7 +681,10 @@ class HomeFragment : Fragment() {
 | 
			
		|||
                        getString(R.string.error_bookmarks_text), //home_bookmarked_parent_item_title?.text?.toString() ?: getString(R.string.error_bookmarks_text),
 | 
			
		||||
                        bookmarks
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
                ) {
 | 
			
		||||
                    deleteAllBookmarkedData()
 | 
			
		||||
                    homeViewModel.loadStoredData(null)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -665,7 +707,10 @@ class HomeFragment : Fragment() {
 | 
			
		|||
                            ?: getString(R.string.continue_watching),
 | 
			
		||||
                        resumeWatching
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
                ) {
 | 
			
		||||
                    deleteAllResumeStateIds()
 | 
			
		||||
                    homeViewModel.loadResumeWatching()
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty
 | 
			
		|||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
 | 
			
		||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKeys
 | 
			
		||||
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
 | 
			
		||||
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKeys
 | 
			
		||||
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
 | 
			
		||||
import com.lagradost.cloudstream3.DubStatus
 | 
			
		||||
import com.lagradost.cloudstream3.SearchQuality
 | 
			
		||||
| 
						 | 
				
			
			@ -76,6 +77,18 @@ object DataStoreHelper {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun deleteAllResumeStateIds() {
 | 
			
		||||
        val folder = "$currentAccount/$RESULT_RESUME_WATCHING"
 | 
			
		||||
        removeKeys(folder)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun deleteAllBookmarkedData() {
 | 
			
		||||
        val folder1 = "$currentAccount/$RESULT_WATCH_STATE"
 | 
			
		||||
        val folder2 = "$currentAccount/$RESULT_WATCH_STATE_DATA"
 | 
			
		||||
        removeKeys(folder1)
 | 
			
		||||
        removeKeys(folder2)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun getAllResumeStateIds(): List<Int>? {
 | 
			
		||||
        val folder = "$currentAccount/$RESULT_RESUME_WATCHING"
 | 
			
		||||
        return getKeys(folder)?.mapNotNull {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -103,7 +103,7 @@ class M3u8Helper {
 | 
			
		|||
        }.filter {
 | 
			
		||||
            listOf("m3u", "m3u8").contains(absoluteExtensionDetermination(it.streamUrl))
 | 
			
		||||
        }
 | 
			
		||||
        return result.getOrNull(0)
 | 
			
		||||
        return result.lastOrNull()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun getParentLink(uri: String): String {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
        xmlns:tools="http://schemas.android.com/tools"
 | 
			
		||||
        xmlns:app="http://schemas.android.com/apk/res-auto"
 | 
			
		||||
        android:orientation="vertical"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:background="?attr/primaryGrayBackground"
 | 
			
		||||
| 
						 | 
				
			
			@ -17,10 +18,25 @@
 | 
			
		|||
 | 
			
		||||
        <requestFocus />
 | 
			
		||||
 | 
			
		||||
        <TextView
 | 
			
		||||
                android:id="@+id/home_expanded_text"
 | 
			
		||||
                style="@style/WatchHeaderText"
 | 
			
		||||
                tools:text="Trending" />
 | 
			
		||||
        <LinearLayout
 | 
			
		||||
                android:layout_width="match_parent"
 | 
			
		||||
                android:layout_height="wrap_content">
 | 
			
		||||
 | 
			
		||||
            <ImageView
 | 
			
		||||
                    app:tint="?attr/textColor"
 | 
			
		||||
                    android:id="@+id/home_expanded_delete"
 | 
			
		||||
                    android:layout_marginEnd="10dp"
 | 
			
		||||
                    android:layout_gravity="start|center_vertical"
 | 
			
		||||
                    android:src="@drawable/ic_baseline_delete_outline_24"
 | 
			
		||||
                    android:layout_width="30dp"
 | 
			
		||||
                    android:layout_height="match_parent"
 | 
			
		||||
                    android:contentDescription="@string/delete" />
 | 
			
		||||
 | 
			
		||||
            <TextView
 | 
			
		||||
                    android:id="@+id/home_expanded_text"
 | 
			
		||||
                    style="@style/WatchHeaderText"
 | 
			
		||||
                    tools:text="Trending" />
 | 
			
		||||
        </LinearLayout>
 | 
			
		||||
 | 
			
		||||
        <ImageView
 | 
			
		||||
                android:layout_marginEnd="5dp"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,6 +36,7 @@
 | 
			
		|||
    <string name="duration_format" formatted="true">%d min</string>
 | 
			
		||||
 | 
			
		||||
    <!-- <string name="app_name">CloudStream</string> -->
 | 
			
		||||
    <string name="play_with_app_name">Riproduci con CloudStream</string>
 | 
			
		||||
    <string name="title_home">Home</string>
 | 
			
		||||
    <string name="title_search">Cerca</string>
 | 
			
		||||
    <string name="title_downloads">Scaricati</string>
 | 
			
		||||
| 
						 | 
				
			
			@ -62,6 +63,7 @@
 | 
			
		|||
    <string name="type_re_watching">Riguardando</string>
 | 
			
		||||
 | 
			
		||||
    <string name="play_movie_button">Riproduci film</string>
 | 
			
		||||
    <string name="play_livestream_button">Riproduci Livestream</string>
 | 
			
		||||
    <string name="play_torrent_button">Stream Torrent</string>
 | 
			
		||||
    <string name="pick_source">Fonti</string>
 | 
			
		||||
    <string name="pick_subtitle">Sottotitoli</string>
 | 
			
		||||
| 
						 | 
				
			
			@ -185,7 +187,7 @@
 | 
			
		|||
    <string name="backup_failed_error_format">Errore nel backup %s</string>
 | 
			
		||||
 | 
			
		||||
    <string name="search">Cerca</string>
 | 
			
		||||
    <string name="category_account">Accounts e Crediti</string>
 | 
			
		||||
    <string name="category_account">Accounts</string>
 | 
			
		||||
    <string name="category_updates">Aggiornamenti e Backup</string>
 | 
			
		||||
    <string name="nginx_info_title">Cos\'è Nginx?</string>
 | 
			
		||||
    <string name="nginx_info_summary">Nginx è un software che può essere utilizzato per visualizzare i file da un server di proprietà. Fare clic per vedere la guida all\'installazione di Nginx</string>
 | 
			
		||||
| 
						 | 
				
			
			@ -204,9 +206,9 @@
 | 
			
		|||
    <string name="uprereleases_settings">Aggiorna alle prerelease</string>
 | 
			
		||||
    <string name="uprereleases_settings_des">Cerca per aggiornamenti alle prerelease invice di cercare solo le release complete</string>
 | 
			
		||||
    <string name="github">GitHub</string>
 | 
			
		||||
    <string name="lightnovel">App di light novel degli stessi sviluppatori</string>
 | 
			
		||||
    <string name="anim">App di anime dagli stessi sviluppatori</string>
 | 
			
		||||
    <string name="discord">Entra Discord</string>
 | 
			
		||||
    <string name="lightnovel">App per Light Novel degli stessi sviluppatori</string>
 | 
			
		||||
    <string name="anim">App per Anime degli stessi sviluppatori</string>
 | 
			
		||||
    <string name="discord">Entra in Discord</string>
 | 
			
		||||
    <string name="benene">Dai una banana agli sviluppatori</string>
 | 
			
		||||
    <string name="benene_des">Dai una banana</string>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -263,6 +265,7 @@
 | 
			
		|||
    <string name="torrent">Torrent</string>
 | 
			
		||||
    <string name="documentaries">Documentari</string>
 | 
			
		||||
    <string name="asian_drama">Drama Asiatici</string>
 | 
			
		||||
    <string name="livestreams">Livestreams</string>
 | 
			
		||||
 | 
			
		||||
    <!--singular-->
 | 
			
		||||
    <string name="movies_singular">Film</string>
 | 
			
		||||
| 
						 | 
				
			
			@ -273,6 +276,7 @@
 | 
			
		|||
    <string name="torrent_singular">Torrent</string>
 | 
			
		||||
    <string name="documentaries_singular">Documentario</string>
 | 
			
		||||
    <string name="asian_drama_singular">Drama Asiatico</string>
 | 
			
		||||
    <string name="live_singular">Livestream</string>
 | 
			
		||||
 | 
			
		||||
    <string name="source_error">Source error</string>
 | 
			
		||||
    <string name="remote_error">Remote error</string>
 | 
			
		||||
| 
						 | 
				
			
			@ -445,11 +449,14 @@
 | 
			
		|||
    <string name="resolution_and_title">Titolo e Risoluzione</string>
 | 
			
		||||
    <string name="title">Titolo</string>
 | 
			
		||||
    <string name="resolution">Risoluzione</string>
 | 
			
		||||
    <string name="error_invalid_id">ID invalido</string>
 | 
			
		||||
    <string name="error_invalid_id">ID non valido</string>
 | 
			
		||||
    <string name="error_invalid_data">Dati non validi</string>
 | 
			
		||||
    <string name="error_invalid_url">Url non valido</string>
 | 
			
		||||
    <string name="error">Errore</string>
 | 
			
		||||
    <!--<string name="subtitles_remove_captions">Remove closed captions from subtitles</string>-->
 | 
			
		||||
    <!--<string name="subtitles_remove_bloat">Remove bloat from subtitles</string>-->
 | 
			
		||||
    <!--<string name="extras">Extra</string>-->
 | 
			
		||||
    <string name="trailer">Trailer</string>
 | 
			
		||||
    <string name="network_adress_example">Link allo stream</string>
 | 
			
		||||
    <!--<string name="referer">Referer</string>-->
 | 
			
		||||
</resources>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue