From 266a511cd7f591c00a2e40786af7bbd8c11b93c4 Mon Sep 17 00:00:00 2001 From: reduplicated <110570621+reduplicated@users.noreply.github.com> Date: Sun, 18 Sep 2022 00:05:28 +0200 Subject: [PATCH 1/7] testing aria2c UI --- app/build.gradle | 3 + .../lagradost/cloudstream3/CommonActivity.kt | 15 ++ .../cloudstream3/ui/result/EpisodeAdapter.kt | 98 ++------- .../cloudstream3/ui/result/ResultFragment.kt | 1 - ...{circle_shape.xml => circle_shape_cs3.xml} | 0 ..._bar.xml => circular_progress_bar_cs3.xml} | 0 ...l => circular_progress_bar_filled_cs3.xml} | 0 .../res/layout/download_child_episode.xml | 4 +- .../res/layout/download_header_episode.xml | 4 +- app/src/main/res/layout/fragment_result.xml | 4 +- .../main/res/layout/fragment_result_tv.xml | 4 +- app/src/main/res/layout/result_episode.xml | 37 +--- .../main/res/layout/result_episode_large.xml | 198 ++++++++---------- 13 files changed, 136 insertions(+), 232 deletions(-) rename app/src/main/res/drawable/{circle_shape.xml => circle_shape_cs3.xml} (100%) rename app/src/main/res/drawable/{circular_progress_bar.xml => circular_progress_bar_cs3.xml} (100%) rename app/src/main/res/drawable/{circular_progress_bar_filled.xml => circular_progress_bar_filled_cs3.xml} (100%) diff --git a/app/build.gradle b/app/build.gradle index b80c820f..8ece81c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -199,6 +199,9 @@ dependencies { // Library/extensions searching with Levenshtein distance implementation 'me.xdrop:fuzzywuzzy:1.4.0' + + // aria2c downloader + implementation 'com.github.LagradOst:Aria2cButton:master-SNAPSHOT' } task androidSourcesJar(type: Jar) { diff --git a/app/src/main/java/com/lagradost/cloudstream3/CommonActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/CommonActivity.kt index 49143498..dd3942f9 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/CommonActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/CommonActivity.kt @@ -25,8 +25,11 @@ import com.lagradost.cloudstream3.utils.UIHelper import com.lagradost.cloudstream3.utils.UIHelper.hasPIPPermission import com.lagradost.cloudstream3.utils.UIHelper.shouldShowPIPMode import com.lagradost.cloudstream3.utils.UIHelper.toPx +import com.lagradost.fetchbutton.aria2c.Aria2Settings +import com.lagradost.fetchbutton.aria2c.Aria2Starter import org.schabi.newpipe.extractor.NewPipe import java.util.* +import kotlin.concurrent.thread object CommonActivity { @MainThread @@ -129,6 +132,18 @@ object CommonActivity { act.updateLocale() act.updateTv() NewPipe.init(DownloaderTestImpl.getInstance()) + + thread { + Aria2Starter.start( + act, + Aria2Settings( + UUID.randomUUID().toString(), + 4337, + act.filesDir.path, + "${act.filesDir.path}/session" + ) + ) + } } private fun Activity.enterPIPMode() { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt index 3abd827e..71b2822d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt @@ -13,23 +13,17 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.google.android.material.button.MaterialButton import com.lagradost.cloudstream3.R -import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD import com.lagradost.cloudstream3.ui.download.DownloadButtonViewHolder import com.lagradost.cloudstream3.ui.download.DownloadClickEvent -import com.lagradost.cloudstream3.ui.download.EasyDownloadButton import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings import com.lagradost.cloudstream3.utils.AppUtils.html import com.lagradost.cloudstream3.utils.UIHelper.setImage -import com.lagradost.cloudstream3.utils.VideoDownloadHelper -import com.lagradost.cloudstream3.utils.VideoDownloadManager +import com.lagradost.fetchbutton.aria2c.newUriRequest import kotlinx.android.synthetic.main.result_episode.view.* import kotlinx.android.synthetic.main.result_episode.view.episode_text -import kotlinx.android.synthetic.main.result_episode_large.view.* import kotlinx.android.synthetic.main.result_episode_large.view.episode_filler import kotlinx.android.synthetic.main.result_episode_large.view.episode_progress -import kotlinx.android.synthetic.main.result_episode_large.view.result_episode_download -import kotlinx.android.synthetic.main.result_episode_large.view.result_episode_progress_downloaded -import java.util.* +import kotlinx.android.synthetic.main.result_episode_large_tv.view.* const val ACTION_PLAY_EPISODE_IN_PLAYER = 1 const val ACTION_PLAY_EPISODE_IN_VLC_PLAYER = 2 @@ -62,17 +56,6 @@ class EpisodeAdapter( ) : RecyclerView.Adapter() { private var cardList: MutableList = mutableListOf() - private val mBoundViewHolders: HashSet = HashSet() - private fun getAllBoundViewHolders(): Set? { - return Collections.unmodifiableSet(mBoundViewHolders) - } - - fun killAdapter() { - getAllBoundViewHolders()?.forEach { view -> - view?.downloadButton?.dispose() - } - } - override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) { if (holder.itemView.hasFocus()) { holder.itemView.clearFocus() @@ -85,15 +68,6 @@ class EpisodeAdapter( } } - override fun onViewRecycled(holder: RecyclerView.ViewHolder) { - if (holder is DownloadButtonViewHolder) { - holder.downloadButton.dispose() - mBoundViewHolders.remove(holder) - //(holder.itemView as? FrameLayout?)?.descendantFocusability = - // ViewGroup.FOCUS_BLOCK_DESCENDANTS - } - } - override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) { if (holder is DownloadButtonViewHolder) { //println("onViewAttachedToWindow = ${holder.absoluteAdapterPosition}") @@ -138,7 +112,6 @@ class EpisodeAdapter( when (holder) { is EpisodeCardViewHolder -> { holder.bind(cardList[position]) - mBoundViewHolders.add(holder) } } } @@ -153,17 +126,11 @@ class EpisodeAdapter( private val hasDownloadSupport: Boolean, private val clickCallback: (EpisodeClickEvent) -> Unit, private val downloadClickCallback: (DownloadClickEvent) -> Unit, - ) : RecyclerView.ViewHolder(itemView), DownloadButtonViewHolder { - override var downloadButton = EasyDownloadButton() - - var episodeDownloadBar: ContentLoadingProgressBar? = null - var episodeDownloadImage: ImageView? = null - var localCard: ResultEpisode? = null + ) : RecyclerView.ViewHolder(itemView) { + //override var downloadButton = EasyDownloadButton() @SuppressLint("SetTextI18n") fun bind(card: ResultEpisode) { - localCard = card - val isTrueTv = isTrueTvSettings() val (parentView, otherView) = if (card.poster == null) { @@ -181,9 +148,17 @@ class EpisodeAdapter( val episodeProgress: ContentLoadingProgressBar? = parentView.episode_progress val episodePoster: ImageView? = parentView.episode_poster - episodeDownloadBar = - parentView.result_episode_progress_downloaded - episodeDownloadImage = parentView.result_episode_download + val downloadButton = parentView.result_episode_download + + downloadButton.setPersistentId(card.id.toLong()) + downloadButton.isVisible = hasDownloadSupport + downloadButton.setDefaultClickListener { + listOf( + newUriRequest( + card.id.toLong(), "https://speed.hetzner.de/100MB.bin", "Hello World", + ) + ) + } val name = if (card.name == null) "${episodeText.context.getString(R.string.episode)} ${card.episode}" else "${card.episode}. ${card.name}" @@ -242,49 +217,6 @@ class EpisodeAdapter( return@setOnLongClickListener true } - - episodeDownloadImage?.isVisible = hasDownloadSupport - episodeDownloadBar?.isVisible = hasDownloadSupport - reattachDownloadButton() - } - - override fun reattachDownloadButton() { - downloadButton.dispose() - val card = localCard - if (hasDownloadSupport && card != null) { - if (episodeDownloadBar == null || - episodeDownloadImage == null - ) return - val downloadInfo = VideoDownloadManager.getDownloadFileInfoAndUpdateSettings( - itemView.context, - card.id - ) - - downloadButton.setUpButton( - downloadInfo?.fileLength, - downloadInfo?.totalBytes, - episodeDownloadBar ?: return, - episodeDownloadImage ?: return, - null, - VideoDownloadHelper.DownloadEpisodeCached( - card.name, - card.poster, - card.episode, - card.season, - card.id, - card.parentId, - card.rating, - card.description, - System.currentTimeMillis(), - ) - ) { - if (it.action == DOWNLOAD_ACTION_DOWNLOAD) { - clickCallback.invoke(EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, card)) - } else { - downloadClickCallback.invoke(it) - } - } - } } } } 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 5fc61146..082e334a 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 @@ -256,7 +256,6 @@ open class ResultFragment : ResultTrailerPlayer() { private var downloadButton: EasyDownloadButton? = null override fun onDestroyView() { updateUIListener = null - (result_episodes?.adapter as EpisodeAdapter?)?.killAdapter() downloadButton?.dispose() super.onDestroyView() diff --git a/app/src/main/res/drawable/circle_shape.xml b/app/src/main/res/drawable/circle_shape_cs3.xml similarity index 100% rename from app/src/main/res/drawable/circle_shape.xml rename to app/src/main/res/drawable/circle_shape_cs3.xml diff --git a/app/src/main/res/drawable/circular_progress_bar.xml b/app/src/main/res/drawable/circular_progress_bar_cs3.xml similarity index 100% rename from app/src/main/res/drawable/circular_progress_bar.xml rename to app/src/main/res/drawable/circular_progress_bar_cs3.xml diff --git a/app/src/main/res/drawable/circular_progress_bar_filled.xml b/app/src/main/res/drawable/circular_progress_bar_filled_cs3.xml similarity index 100% rename from app/src/main/res/drawable/circular_progress_bar_filled.xml rename to app/src/main/res/drawable/circular_progress_bar_filled_cs3.xml diff --git a/app/src/main/res/layout/download_child_episode.xml b/app/src/main/res/layout/download_child_episode.xml index f2633dd6..8cef5e7e 100644 --- a/app/src/main/res/layout/download_child_episode.xml +++ b/app/src/main/res/layout/download_child_episode.xml @@ -90,8 +90,8 @@ android:layout_width="40dp" android:layout_height="40dp" android:indeterminate="false" - android:progressDrawable="@drawable/circular_progress_bar" - android:background="@drawable/circle_shape" + android:progressDrawable="@drawable/circular_progress_bar_cs3" + android:background="@drawable/circle_shape_cs3" style="?android:attr/progressBarStyleHorizontal" android:max="100" android:layout_margin="5dp" diff --git a/app/src/main/res/layout/download_header_episode.xml b/app/src/main/res/layout/download_header_episode.xml index da4b3617..ead483e3 100644 --- a/app/src/main/res/layout/download_header_episode.xml +++ b/app/src/main/res/layout/download_header_episode.xml @@ -78,8 +78,8 @@ android:layout_height="40dp" android:id="@+id/download_header_progress_downloaded" android:indeterminate="false" - android:progressDrawable="@drawable/circular_progress_bar" - android:background="@drawable/circle_shape" + android:progressDrawable="@drawable/circular_progress_bar_cs3" + android:background="@drawable/circle_shape_cs3" style="?android:attr/progressBarStyleHorizontal" android:max="100" android:layout_margin="5dp" diff --git a/app/src/main/res/layout/fragment_result.xml b/app/src/main/res/layout/fragment_result.xml index d26c1b5a..48aeb72e 100644 --- a/app/src/main/res/layout/fragment_result.xml +++ b/app/src/main/res/layout/fragment_result.xml @@ -604,13 +604,13 @@ android:layout_height="25dp" android:layout_gravity="end|center_vertical" android:layout_margin="5dp" - android:background="@drawable/circle_shape" + android:background="@drawable/circle_shape_cs3" android:indeterminate="false" android:max="100" android:paddingStart="5dp" android:paddingEnd="5dp" android:progress="30" - android:progressDrawable="@drawable/circular_progress_bar_filled" + android:progressDrawable="@drawable/circular_progress_bar_filled_cs3" android:visibility="visible" /> - - - - + + \ No newline at end of file diff --git a/app/src/main/res/layout/result_episode_large.xml b/app/src/main/res/layout/result_episode_large.xml index 0aeedeea..6ead564a 100644 --- a/app/src/main/res/layout/result_episode_large.xml +++ b/app/src/main/res/layout/result_episode_large.xml @@ -1,151 +1,129 @@ + app:cardCornerRadius="@dimen/rounded_image_radius"> + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:foreground="?android:attr/selectableItemBackgroundBorderless" + android:orientation="vertical" + android:padding="10dp"> + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + android:layout_width="126dp" + android:layout_height="72dp" + android:foreground="@drawable/outline_drawable"> + android:foreground="?android:attr/selectableItemBackgroundBorderless" + android:nextFocusRight="@id/result_episode_download" + android:scaleType="centerCrop" + tools:src="@drawable/example_poster" /> + android:layout_width="36dp" + android:layout_height="36dp" + android:layout_gravity="center" + android:contentDescription="@string/play_episode" + android:src="@drawable/play_button" /> + android:id="@+id/episode_progress" + style="@android:style/Widget.Material.ProgressBar.Horizontal" + android:layout_width="match_parent" + android:layout_height="5dp" + android:layout_gravity="bottom" + android:layout_marginBottom="-1.5dp" + android:progressBackgroundTint="?attr/colorPrimary" + android:progressTint="?attr/colorPrimary" + tools:progress="50" /> + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginStart="15dp" + android:layout_marginEnd="50dp" + android:orientation="vertical"> + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal"> + android:id="@+id/episode_filler" + style="@style/SmallBlackButton" + android:layout_gravity="start" + android:layout_marginEnd="10dp" + android:text="@string/filler" /> + android:id="@+id/episode_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:textColor="?attr/textColor" + android:textStyle="bold" + tools:text="1. Jobless" /> + android:id="@+id/episode_rating" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textColor="?attr/grayTextColor" + tools:text="Rated: 8.8" /> + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_gravity="end" + android:layout_marginStart="-50dp"> - - - + + + android:id="@+id/episode_descript" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:ellipsize="end" + android:maxLines="4" + android:paddingTop="10dp" + android:paddingBottom="10dp" + android:textColor="?attr/grayTextColor" + tools:text="Jon and Daenerys arrive in Winterfell and are met with skepticism. Sam learns about the fate of his family. Cersei gives Euron the reward he aims for. Theon follows his heart. Jon and Daenerys arrive in Winterfell and are met with skepticism. Sam learns about the fate of his family. Cersei gives Euron the reward he aims for. Theon follows his heart." /> \ No newline at end of file From 63e4e670c039e9e43309e9ff52518587f179c63b Mon Sep 17 00:00:00 2001 From: reduplicated <110570621+reduplicated@users.noreply.github.com> Date: Sun, 18 Sep 2022 13:25:17 +0200 Subject: [PATCH 2/7] episode test --- .../cloudstream3/ui/result/EpisodeAdapter.kt | 11 +- .../cloudstream3/ui/result/ResultFragment.kt | 7 +- .../ui/result/ResultViewModel2.kt | 337 ++++++++++-------- .../utils/VideoDownloadManager.kt | 2 +- 4 files changed, 205 insertions(+), 152 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt index 71b2822d..8dd17d86 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt @@ -18,6 +18,7 @@ import com.lagradost.cloudstream3.ui.download.DownloadClickEvent import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings import com.lagradost.cloudstream3.utils.AppUtils.html import com.lagradost.cloudstream3.utils.UIHelper.setImage +import com.lagradost.fetchbutton.aria2c.UriRequest import com.lagradost.fetchbutton.aria2c.newUriRequest import kotlinx.android.synthetic.main.result_episode.view.* import kotlinx.android.synthetic.main.result_episode.view.episode_text @@ -52,7 +53,7 @@ data class EpisodeClickEvent(val action: Int, val data: ResultEpisode) class EpisodeAdapter( private val hasDownloadSupport: Boolean, private val clickCallback: (EpisodeClickEvent) -> Unit, - private val downloadClickCallback: (DownloadClickEvent) -> Unit, + private val downloadClickCallback: suspend ResultEpisode.() -> List, ) : RecyclerView.Adapter() { private var cardList: MutableList = mutableListOf() @@ -125,7 +126,7 @@ class EpisodeAdapter( itemView: View, private val hasDownloadSupport: Boolean, private val clickCallback: (EpisodeClickEvent) -> Unit, - private val downloadClickCallback: (DownloadClickEvent) -> Unit, + private val downloadClickCallback : suspend ResultEpisode.() -> List, ) : RecyclerView.ViewHolder(itemView) { //override var downloadButton = EasyDownloadButton() @@ -153,11 +154,7 @@ class EpisodeAdapter( downloadButton.setPersistentId(card.id.toLong()) downloadButton.isVisible = hasDownloadSupport downloadButton.setDefaultClickListener { - listOf( - newUriRequest( - card.id.toLong(), "https://speed.hetzner.de/100MB.bin", "Hello World", - ) - ) + downloadClickCallback.invoke(card) } val name = 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 082e334a..f3ff7562 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 @@ -36,8 +36,10 @@ import com.lagradost.cloudstream3.syncproviders.providers.Kitsu import com.lagradost.cloudstream3.ui.WatchType import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick +import com.lagradost.cloudstream3.ui.download.DownloadViewModel import com.lagradost.cloudstream3.ui.download.EasyDownloadButton import com.lagradost.cloudstream3.ui.quicksearch.QuickSearchFragment +import com.lagradost.cloudstream3.ui.result.ResultViewModel2.Companion.getDownloadRequest import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings import com.lagradost.cloudstream3.utils.* @@ -506,8 +508,9 @@ open class ResultFragment : ResultTrailerPlayer() { { episodeClick -> viewModel.handleAction(activity, episodeClick) }, - { downloadClickEvent -> - handleDownloadClick(activity, downloadClickEvent) + { + viewModel.getRequest(this)?.links ?: emptyList() + //handleDownloadClick(activity, downloadClickEvent) } ) 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 48919308..f620fc65 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 @@ -28,7 +28,6 @@ import com.lagradost.cloudstream3.syncproviders.SyncAPI import com.lagradost.cloudstream3.syncproviders.providers.Kitsu 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.player.GeneratorPlayer import com.lagradost.cloudstream3.ui.player.IGenerator import com.lagradost.cloudstream3.ui.player.RepoLinkGenerator @@ -55,6 +54,10 @@ import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultSeason import com.lagradost.cloudstream3.utils.UIHelper.checkWrite import com.lagradost.cloudstream3.utils.UIHelper.navigate import com.lagradost.cloudstream3.utils.UIHelper.requestRW +import com.lagradost.cloudstream3.utils.VideoDownloadManager.getBasePath +import com.lagradost.fetchbutton.aria2c.Aria2Starter +import com.lagradost.fetchbutton.aria2c.UriRequest +import com.lagradost.fetchbutton.aria2c.newUriRequest import kotlinx.coroutines.* import java.io.File import java.lang.Math.abs @@ -584,8 +587,7 @@ class ResultViewModel2 : ViewModel() { } } - fun startDownload( - context: Context?, + fun getDownloadRequest( episode: ResultEpisode, currentIsMovie: Boolean, currentHeaderName: String, @@ -596,93 +598,139 @@ class ResultViewModel2 : ViewModel() { url: String, links: List, subs: List? - ) { - try { - if (context == null) return - - val meta = - getMeta( - episode, - currentHeaderName, - apiName, - currentPoster, - currentIsMovie, - currentType - ) - - val folder = getFolder(currentType, currentHeaderName) - - val src = "$DOWNLOAD_NAVIGATE_TO/$parentId" // url ?: return@let - - // SET VISUAL KEYS - AcraApplication.setKey( - DOWNLOAD_HEADER_CACHE, - parentId.toString(), - VideoDownloadHelper.DownloadHeaderCached( - apiName, - url, - currentType, - currentHeaderName, - currentPoster, - parentId, - System.currentTimeMillis(), - ) + ): DownloadRequest? { + val meta = + getMeta( + episode, + currentHeaderName, + apiName, + currentPoster, + currentIsMovie, + currentType ) - AcraApplication.setKey( - DataStore.getFolderName( - DOWNLOAD_EPISODE_CACHE, - parentId.toString() - ), // 3 deep folder for faster acess - episode.id.toString(), - VideoDownloadHelper.DownloadEpisodeCached( - episode.name, - episode.poster, - episode.episode, - episode.season, - episode.id, - parentId, - episode.rating, - episode.description, - System.currentTimeMillis(), - ) - ) + val topFolder = AcraApplication.context?.getBasePath()?.first?.filePath - // DOWNLOAD VIDEO - VideoDownloadManager.downloadEpisodeUsingWorker( - context, - src,//url ?: return, - folder, - meta, - links - ) + val folder = + topFolder + "/" + getFolder(currentType, currentHeaderName).replace(".", "") + //val src = "$DOWNLOAD_NAVIGATE_TO/$parentId" // url ?: return@let - // 1. Checks if the lang should be downloaded - // 2. Makes it into the download format - // 3. Downloads it as a .vtt file - val downloadList = SubtitlesFragment.getDownloadSubsLanguageISO639_1() - subs?.let { subsList -> - subsList.filter { - downloadList.contains( - SubtitleHelper.fromLanguageToTwoLetters( - it.name, - true - ) - ) - } - .map { ExtractorSubtitleLink(it.name, it.url, "") } - .forEach { link -> - val fileName = VideoDownloadManager.getFileName(context, meta) - downloadSubtitle(context, link, fileName, folder) - } - } - } catch (e: Exception) { - logError(e) + // SET VISUAL KEYS + AcraApplication.setKey( + DOWNLOAD_HEADER_CACHE, + parentId.toString(), + VideoDownloadHelper.DownloadHeaderCached( + apiName, + url, + currentType, + currentHeaderName, + currentPoster, + parentId, + System.currentTimeMillis(), + ) + ) + + AcraApplication.setKey( + DataStore.getFolderName( + DOWNLOAD_EPISODE_CACHE, + parentId.toString() + ), // 3 deep folder for faster acess + episode.id.toString(), + VideoDownloadHelper.DownloadEpisodeCached( + episode.name, + episode.poster, + episode.episode, + episode.season, + episode.id, + parentId, + episode.rating, + episode.description, + System.currentTimeMillis(), + ) + ) + val linkRequests = links.filter { link -> !link.isM3u8 }.map { link -> + newUriRequest( + episode.id.toLong(), link.url, + VideoDownloadManager.getDisplayName( + VideoDownloadManager.getFileName( + AcraApplication.context ?: return null, + meta + ), ".mp4" + ), folder, link.headers, USER_AGENT + ) } + + val downloadList = SubtitlesFragment.getDownloadSubsLanguageISO639_1() + val downloadSubsList = (subs ?: emptyList()).filter { + downloadList.contains( + SubtitleHelper.fromLanguageToTwoLetters( + it.name, + true + ) + ) + } + .map { ExtractorSubtitleLink(it.name, it.url, "") } + .map { link -> + val fileName = VideoDownloadManager.getFileName( + AcraApplication.context ?: return null, + meta + ) + newUriRequest(0, link.url, fileName, folder, link.headers, USER_AGENT) + //downloadSubtitle(context, link, fileName, folder) + } + + return DownloadRequest(linkRequests, downloadSubsList) + + // DOWNLOAD VIDEO + //VideoDownloadManager.downloadEpisodeUsingWorker( + // context, + // src,//url ?: return, + // folder, + // meta, + // links + //) + + // 1. Checks if the lang should be downloaded + // 2. Makes it into the download format + // 3. Downloads it as a .vtt file + //val downloadList = SubtitlesFragment.getDownloadSubsLanguageISO639_1() + //subs?.let { subsList -> + // subsList.filter { + // downloadList.contains( + // SubtitleHelper.fromLanguageToTwoLetters( + // it.name, + // true + // ) + // ) + // } + // .map { ExtractorSubtitleLink(it.name, it.url, "") } + // .forEach { link -> + // val fileName = VideoDownloadManager.getFileName(context, meta) + // downloadSubtitle(context, link, fileName, folder) + // } + //} } + data class DownloadRequest( + val links: List, + val subs: List, + ) + + + /*suspend fun download(episode: ResultEpisode): DownloadRequest { + val generator = RepoLinkGenerator(listOf(episode)) + val currentLinks = mutableSetOf() + val currentSubs = mutableSetOf() + generator.generateLinks(clearCache = false, isCasting = false, callback = { + it.first?.let { link -> + currentLinks.add(link) + } + }, subtitleCallback = { sub -> + currentSubs.add(sub) + }) + }*/ + suspend fun downloadEpisode( - activity: Activity?, episode: ResultEpisode, currentIsMovie: Boolean, currentHeaderName: String, @@ -691,52 +739,49 @@ class ResultViewModel2 : ViewModel() { apiName: String, parentId: Int, url: String, - ) { - ioSafe { - val generator = RepoLinkGenerator(listOf(episode)) - val currentLinks = mutableSetOf() - val currentSubs = mutableSetOf() - generator.generateLinks(clearCache = false, isCasting = false, callback = { - it.first?.let { link -> - currentLinks.add(link) - } - }, subtitleCallback = { sub -> - currentSubs.add(sub) - }) - - if (currentLinks.isEmpty()) { - main { - showToast( - activity, - R.string.no_links_found_toast, - Toast.LENGTH_SHORT - ) - } - return@ioSafe - } else { - main { - showToast( - activity, - R.string.download_started, - Toast.LENGTH_SHORT - ) - } + ): DownloadRequest? { + val generator = RepoLinkGenerator(listOf(episode)) + val currentLinks = mutableSetOf() + val currentSubs = mutableSetOf() + generator.generateLinks(clearCache = false, isCasting = false, callback = { + it.first?.let { link -> + currentLinks.add(link) } + }, subtitleCallback = { sub -> + currentSubs.add(sub) + }) - startDownload( - activity, - episode, - currentIsMovie, - currentHeaderName, - currentType, - currentPoster, - apiName, - parentId, - url, - sortUrls(currentLinks), - sortSubs(currentSubs), - ) - } + //if (currentLinks.isEmpty()) { + // main { + // showToast( + // activity, + // R.string.no_links_found_toast, + // Toast.LENGTH_SHORT + // ) + // } + // return@ioSafe + //} else { + // main { + // showToast( + // activity, + // R.string.download_started, + // Toast.LENGTH_SHORT + // ) + // } + //} + + return getDownloadRequest( + episode, + currentIsMovie, + currentHeaderName, + currentType, + currentPoster, + apiName, + parentId, + url, + sortUrls(currentLinks), + sortSubs(currentSubs), + ) } private fun getMeta( @@ -1021,6 +1066,20 @@ class ResultViewModel2 : ViewModel() { handleEpisodeClickEvent(activity, click) } + suspend fun getRequest(card: ResultEpisode): DownloadRequest? { + val response = currentResponse ?: return null + return downloadEpisode( + card, + response.isMovie(), + response.name, + response.type, + response.posterUrl, + response.apiName, + response.getId(), + response.url + ) + } + private suspend fun handleEpisodeClickEvent(activity: Activity?, click: EpisodeClickEvent) { when (click.action) { ACTION_SHOW_OPTIONS -> { @@ -1117,18 +1176,11 @@ class ResultViewModel2 : ViewModel() { showToast(activity, R.string.play_episode_toast, Toast.LENGTH_SHORT) } ACTION_DOWNLOAD_EPISODE -> { - val response = currentResponse ?: return - downloadEpisode( - activity, - click.data, - response.isMovie(), - response.name, - response.type, - response.posterUrl, - response.apiName, - response.getId(), - response.url - ) + ioSafe { + val response = currentResponse ?: return@ioSafe + val req = getRequest(click.data) ?: return@ioSafe + Aria2Starter.client?.downloadFailQueue(req.links) { _, _ -> } + } } ACTION_DOWNLOAD_MIRROR -> { val response = currentResponse ?: return @@ -1138,8 +1190,7 @@ class ResultViewModel2 : ViewModel() { txt(R.string.episode_action_download_mirror) ) { (result, index) -> ioSafe { - startDownload( - activity, + val req = getDownloadRequest( click.data, response.isMovie(), response.name, @@ -1150,7 +1201,8 @@ class ResultViewModel2 : ViewModel() { response.url, listOf(result.links[index]), result.subs, - ) + ) ?: return@ioSafe + Aria2Starter.client?.downloadFailQueue(req.links) { _, _ -> } } showToast( activity, @@ -1592,7 +1644,8 @@ class ResultViewModel2 : ViewModel() { val idIndex = ep.key.id for ((index, i) in ep.value.withIndex()) { val episode = i.episode ?: (index + 1) - val id = mainId + episode + idIndex * 1_000_000 + (i.season?.times(10_000) ?: 0) + val id = + mainId + episode + idIndex * 1_000_000 + (i.season?.times(10_000) ?: 0) if (!existingEpisodes.contains(id)) { existingEpisodes.add(id) val seasonData = loadResponse.seasonNames.getSeason(i.season) diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt index a629dad9..32cb4b4f 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt @@ -995,7 +995,7 @@ object VideoDownloadManager { } } - private fun getDisplayName(name: String, extension: String): String { + fun getDisplayName(name: String, extension: String): String { return "$name.$extension" } From 45ea1a8d8e523b47b88b33aad493db709a415a76 Mon Sep 17 00:00:00 2001 From: reduplicated <110570621+reduplicated@users.noreply.github.com> Date: Thu, 22 Sep 2022 00:23:26 +0200 Subject: [PATCH 3/7] testing movies --- app/build.gradle | 2 +- .../cloudstream3/ui/DownloadButton.kt | 42 ++++++ .../ui/download/DownloadChildAdapter.kt | 2 + .../cloudstream3/ui/result/DownloadHelper.kt | 130 ++++++++++++++++++ .../cloudstream3/ui/result/EpisodeAdapter.kt | 14 +- .../cloudstream3/ui/result/ResultFragment.kt | 60 ++++---- .../ui/result/ResultViewModel2.kt | 50 ++++++- app/src/main/res/layout/download_button.xml | 9 ++ .../res/layout/download_button_layout.xml | 58 ++++++++ app/src/main/res/layout/fragment_result.xml | 84 +---------- .../main/res/layout/fragment_result_tv.xml | 98 +------------ app/src/main/res/values/styles.xml | 4 + 12 files changed, 341 insertions(+), 212 deletions(-) create mode 100644 app/src/main/java/com/lagradost/cloudstream3/ui/DownloadButton.kt create mode 100644 app/src/main/java/com/lagradost/cloudstream3/ui/result/DownloadHelper.kt create mode 100644 app/src/main/res/layout/download_button.xml create mode 100644 app/src/main/res/layout/download_button_layout.xml diff --git a/app/build.gradle b/app/build.gradle index 8ece81c4..5bf72d99 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -201,7 +201,7 @@ dependencies { implementation 'me.xdrop:fuzzywuzzy:1.4.0' // aria2c downloader - implementation 'com.github.LagradOst:Aria2cButton:master-SNAPSHOT' + implementation 'com.github.LagradOst:Aria2cButton:v0.0.3' } task androidSourcesJar(type: Jar) { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/DownloadButton.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/DownloadButton.kt new file mode 100644 index 00000000..b026eb9d --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/DownloadButton.kt @@ -0,0 +1,42 @@ +package com.lagradost.cloudstream3.ui + +import android.content.Context +import android.util.AttributeSet +import android.widget.TextView +import androidx.core.view.isVisible +import com.lagradost.cloudstream3.R +import com.lagradost.fetchbutton.aria2c.DownloadStatusTell +import com.lagradost.fetchbutton.aria2c.Metadata +import com.lagradost.fetchbutton.ui.PieFetchButton + +class DownloadButton(context: Context, attributeSet: AttributeSet) : + PieFetchButton(context, attributeSet) { + + var progressText: TextView? = null + var mainText: TextView? = null + override fun onAttachedToWindow() { + super.onAttachedToWindow() + progressText = findViewById(R.id.result_movie_download_text_precentage) + mainText = findViewById(R.id.result_movie_download_text) + } + + override fun setStatus(status: DownloadStatusTell?) { + super.setStatus(status) + val txt = when (status) { + DownloadStatusTell.Paused -> R.string.download_paused + DownloadStatusTell.Active -> R.string.downloading + DownloadStatusTell.Complete -> R.string.downloaded + else -> R.string.download + } + mainText?.setText(txt) + } + + override fun updateViewOnDownload(metadata: Metadata) { + super.updateViewOnDownload(metadata) + + val isVis = metadata.progressPercentage > 0 + progressText?.isVisible = isVis + if (isVis) + progressText?.text = "${metadata.progressPercentage}%" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildAdapter.kt index a541171b..98362b13 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildAdapter.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildAdapter.kt @@ -9,6 +9,7 @@ import androidx.cardview.widget.CardView import androidx.core.widget.ContentLoadingProgressBar import androidx.recyclerview.widget.RecyclerView import com.lagradost.cloudstream3.R +import com.lagradost.cloudstream3.ui.result.ResultEpisode import com.lagradost.cloudstream3.utils.AppUtils.getNameFull import com.lagradost.cloudstream3.utils.DataStoreHelper.fixVisual import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos @@ -30,6 +31,7 @@ data class VisualDownloadChildCached( ) data class DownloadClickEvent(val action: Int, val data: EasyDownloadButton.IMinimumData) +data class DownloadEpisodeClickEvent(val action: Int, val data: ResultEpisode) class DownloadChildAdapter( var cardList: List, diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/DownloadHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/DownloadHelper.kt new file mode 100644 index 00000000..067874b1 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/DownloadHelper.kt @@ -0,0 +1,130 @@ +package com.lagradost.cloudstream3.ui.result + +import android.net.Uri +import com.lagradost.cloudstream3.R +import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD +import com.lagradost.cloudstream3.ui.download.DownloadEpisodeClickEvent +import com.lagradost.cloudstream3.ui.player.DownloadFileGenerator +import com.lagradost.cloudstream3.utils.ExtractorUri +import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIcons +import com.lagradost.fetchbutton.aria2c.DownloadStatusTell +import com.lagradost.fetchbutton.ui.PieFetchButton + +object DownloadHelper { + fun PieFetchButton.play(card: ResultEpisode) { + val files = this.getVideos() + DownloadFileGenerator( + files.map { path -> + ExtractorUri( + uri = Uri.parse(path), + + id = card.id, + parentId = card.parentId, + name = context.getString(R.string.downloaded_file), //click.data.name ?: keyInfo.displayName + season = card.season, + episode = card.episode, + headerName = card.headerName, + tvType = card.tvType, + + //basePath = keyInfo.basePath, + //displayName = keyInfo.displayName, + //relativePath = keyInfo.relativePath, + ) + } + ) + } + + fun PieFetchButton.setUp( + card: ResultEpisode, + downloadClickCallback: (DownloadEpisodeClickEvent) -> Unit + ) { + setPersistentId(card.id.toLong()) + + setOnClickListener { view -> + if (view !is PieFetchButton) return@setOnClickListener + when (view.currentStatus) { + null, DownloadStatusTell.Removed -> { + view.setStatus(DownloadStatusTell.Waiting) + downloadClickCallback.invoke( + DownloadEpisodeClickEvent( + DOWNLOAD_ACTION_DOWNLOAD, + card + ) + ) + } + DownloadStatusTell.Paused -> { + view.popupMenuNoIcons( + listOf( + 1 to R.string.resume, + 2 to R.string.play_episode, + 3 to R.string.delete + ) + ) { + when (itemId) { + 1 -> if (!view.resumeDownload()) { + downloadClickCallback.invoke( + DownloadEpisodeClickEvent( + DOWNLOAD_ACTION_DOWNLOAD, + card + ) + ) + } + 2 -> { + play(card) + } + 3 -> { + view.deleteAllFiles() + } + } + } + } + DownloadStatusTell.Complete -> { + view.popupMenuNoIcons( + listOf( + 2 to R.string.play_episode, + 3 to R.string.delete + ) + ) { + when (itemId) { + 2 -> { + play(card) + } + 3 -> { + view.deleteAllFiles() + } + } + } + } + DownloadStatusTell.Active -> { + view.popupMenuNoIcons( + listOf( + 4 to R.string.pause, + 2 to R.string.play_episode, + 3 to R.string.delete + ) + ) { + when (itemId) { + 4 -> { + view.pauseDownload() + } + 2 -> { + play(card) + } + 3 -> { + view.deleteAllFiles() + } + } + } + } + DownloadStatusTell.Error -> { + view.redownload() + } + DownloadStatusTell.Waiting -> { + + } + else -> {} + } + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt index 8dd17d86..e5e886b0 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt @@ -14,12 +14,11 @@ import androidx.recyclerview.widget.RecyclerView import com.google.android.material.button.MaterialButton import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.ui.download.DownloadButtonViewHolder -import com.lagradost.cloudstream3.ui.download.DownloadClickEvent +import com.lagradost.cloudstream3.ui.download.DownloadEpisodeClickEvent +import com.lagradost.cloudstream3.ui.result.DownloadHelper.setUp import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings import com.lagradost.cloudstream3.utils.AppUtils.html import com.lagradost.cloudstream3.utils.UIHelper.setImage -import com.lagradost.fetchbutton.aria2c.UriRequest -import com.lagradost.fetchbutton.aria2c.newUriRequest import kotlinx.android.synthetic.main.result_episode.view.* import kotlinx.android.synthetic.main.result_episode.view.episode_text import kotlinx.android.synthetic.main.result_episode_large.view.episode_filler @@ -53,7 +52,7 @@ data class EpisodeClickEvent(val action: Int, val data: ResultEpisode) class EpisodeAdapter( private val hasDownloadSupport: Boolean, private val clickCallback: (EpisodeClickEvent) -> Unit, - private val downloadClickCallback: suspend ResultEpisode.() -> List, + private val downloadClickCallback: (DownloadEpisodeClickEvent) -> Unit, ) : RecyclerView.Adapter() { private var cardList: MutableList = mutableListOf() @@ -126,7 +125,7 @@ class EpisodeAdapter( itemView: View, private val hasDownloadSupport: Boolean, private val clickCallback: (EpisodeClickEvent) -> Unit, - private val downloadClickCallback : suspend ResultEpisode.() -> List, + private val downloadClickCallback: (DownloadEpisodeClickEvent) -> Unit, ) : RecyclerView.ViewHolder(itemView) { //override var downloadButton = EasyDownloadButton() @@ -151,11 +150,8 @@ class EpisodeAdapter( val downloadButton = parentView.result_episode_download - downloadButton.setPersistentId(card.id.toLong()) downloadButton.isVisible = hasDownloadSupport - downloadButton.setDefaultClickListener { - downloadClickCallback.invoke(card) - } + downloadButton.setUp(card, downloadClickCallback) val name = if (card.name == null) "${episodeText.context.getString(R.string.episode)} ${card.episode}" else "${card.episode}. ${card.name}" 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 f3ff7562..e0f76509 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 @@ -34,12 +34,8 @@ import com.lagradost.cloudstream3.TvType import com.lagradost.cloudstream3.mvvm.* import com.lagradost.cloudstream3.syncproviders.providers.Kitsu import com.lagradost.cloudstream3.ui.WatchType -import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD -import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick -import com.lagradost.cloudstream3.ui.download.DownloadViewModel -import com.lagradost.cloudstream3.ui.download.EasyDownloadButton import com.lagradost.cloudstream3.ui.quicksearch.QuickSearchFragment -import com.lagradost.cloudstream3.ui.result.ResultViewModel2.Companion.getDownloadRequest +import com.lagradost.cloudstream3.ui.result.DownloadHelper.setUp import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings import com.lagradost.cloudstream3.utils.* @@ -47,21 +43,19 @@ import com.lagradost.cloudstream3.utils.AppUtils.getNameFull import com.lagradost.cloudstream3.utils.AppUtils.html import com.lagradost.cloudstream3.utils.AppUtils.loadCache import com.lagradost.cloudstream3.utils.AppUtils.openBrowser -import com.lagradost.cloudstream3.utils.Coroutines.ioWorkSafe -import com.lagradost.cloudstream3.utils.Coroutines.main import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard +import kotlinx.android.synthetic.main.download_button.* import kotlinx.android.synthetic.main.fragment_result.* import kotlinx.android.synthetic.main.fragment_result.result_cast_items import kotlinx.android.synthetic.main.fragment_result.result_cast_text import kotlinx.android.synthetic.main.fragment_result.result_coming_soon import kotlinx.android.synthetic.main.fragment_result.result_data_holder import kotlinx.android.synthetic.main.fragment_result.result_description -import kotlinx.android.synthetic.main.fragment_result.result_download_movie import kotlinx.android.synthetic.main.fragment_result.result_episode_loading import kotlinx.android.synthetic.main.fragment_result.result_episodes import kotlinx.android.synthetic.main.fragment_result.result_error_text @@ -74,11 +68,6 @@ import kotlinx.android.synthetic.main.fragment_result.result_meta_rating import kotlinx.android.synthetic.main.fragment_result.result_meta_site import kotlinx.android.synthetic.main.fragment_result.result_meta_type import kotlinx.android.synthetic.main.fragment_result.result_meta_year -import kotlinx.android.synthetic.main.fragment_result.result_movie_download_icon -import kotlinx.android.synthetic.main.fragment_result.result_movie_download_text -import kotlinx.android.synthetic.main.fragment_result.result_movie_download_text_precentage -import kotlinx.android.synthetic.main.fragment_result.result_movie_progress_downloaded -import kotlinx.android.synthetic.main.fragment_result.result_movie_progress_downloaded_holder import kotlinx.android.synthetic.main.fragment_result.result_next_airing import kotlinx.android.synthetic.main.fragment_result.result_next_airing_time import kotlinx.android.synthetic.main.fragment_result.result_no_episodes @@ -255,10 +244,8 @@ open class ResultFragment : ResultTrailerPlayer() { return inflater.inflate(resultLayout, container, false) } - private var downloadButton: EasyDownloadButton? = null override fun onDestroyView() { updateUIListener = null - downloadButton?.dispose() super.onDestroyView() } @@ -345,7 +332,12 @@ open class ResultFragment : ResultTrailerPlayer() { return@setOnLongClickListener true } - main { + + result_download_movie?.setUp(ep) { + viewModel.download(it.data) + } + result_download_movie?.isVisible = true + /*main { val file = ioWorkSafe { context?.let { @@ -390,11 +382,12 @@ open class ResultFragment : ResultTrailerPlayer() { } } result_movie_progress_downloaded_holder?.isVisible = true - } + }*/ } } else -> { - result_movie_progress_downloaded_holder?.isVisible = false + //result_movie_progress_downloaded_holder?.isVisible = false + result_download_movie?.isVisible = false result_play_movie?.isVisible = false } } @@ -459,7 +452,14 @@ open class ResultFragment : ResultTrailerPlayer() { val storedData = getStoredData(activity ?: context ?: return) ?: return //viewModel.clear() - viewModel.load(activity, storedData.url ?: return, storedData.apiName, storedData.showFillers, storedData.dubStatus, storedData.start) + viewModel.load( + activity, + storedData.url ?: return, + storedData.apiName, + storedData.showFillers, + storedData.dubStatus, + storedData.start + ) } } @@ -508,8 +508,8 @@ open class ResultFragment : ResultTrailerPlayer() { { episodeClick -> viewModel.handleAction(activity, episodeClick) }, - { - viewModel.getRequest(this)?.links ?: emptyList() + { clickEvent -> + viewModel.download(clickEvent.data) //handleDownloadClick(activity, downloadClickEvent) } ) @@ -918,7 +918,14 @@ open class ResultFragment : ResultTrailerPlayer() { if (storedData?.url != null) { result_reload_connectionerror.setOnClickListener { - viewModel.load(activity, storedData.url, storedData.apiName, storedData.showFillers, storedData.dubStatus, storedData.start) + viewModel.load( + activity, + storedData.url, + storedData.apiName, + storedData.showFillers, + storedData.dubStatus, + storedData.start + ) } result_reload_connection_open_in_browser?.setOnClickListener { @@ -954,7 +961,14 @@ open class ResultFragment : ResultTrailerPlayer() { if (restart || !viewModel.hasLoaded()) { //viewModel.clear() - viewModel.load(activity, storedData.url, storedData.apiName, storedData.showFillers, storedData.dubStatus, storedData.start) + viewModel.load( + activity, + storedData.url, + storedData.apiName, + storedData.showFillers, + storedData.dubStatus, + storedData.start + ) } } } 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 f620fc65..51caaf79 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 @@ -52,9 +52,11 @@ import com.lagradost.cloudstream3.utils.DataStoreHelper.setDub import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultEpisode import com.lagradost.cloudstream3.utils.DataStoreHelper.setResultSeason import com.lagradost.cloudstream3.utils.UIHelper.checkWrite +import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute import com.lagradost.cloudstream3.utils.UIHelper.navigate import com.lagradost.cloudstream3.utils.UIHelper.requestRW import com.lagradost.cloudstream3.utils.VideoDownloadManager.getBasePath +import com.lagradost.fetchbutton.NotificationMetaData import com.lagradost.fetchbutton.aria2c.Aria2Starter import com.lagradost.fetchbutton.aria2c.UriRequest import com.lagradost.fetchbutton.aria2c.newUriRequest @@ -648,6 +650,29 @@ class ResultViewModel2 : ViewModel() { System.currentTimeMillis(), ) ) + + val notification = AcraApplication.context?.let { ctx -> + val rowTwoExtra = if (episode.name != null) " - ${episode.name}\n" else "" + val rowTwo = if (episode.season != null && episode.episode > 0) { + "${ctx.getString(R.string.season_short)}${episode.season}:${ctx.getString(R.string.episode_short)}${episode.episode}" + rowTwoExtra + } else if (episode.episode > 0) { + "${ctx.getString(R.string.episode)} ${episode.episode}" + rowTwoExtra + } else { + (episode.name ?: "") + "" + } + NotificationMetaData( + episode.id, + iconColor = ctx.colorFromAttribute(R.attr.colorPrimary), + posterUrl = currentPoster, + contentTitle = currentHeaderName, + secondRow = rowTwo, + subText = null, + linkName = currentHeaderName, + rowTwoExtra = null + ) + } + + val linkRequests = links.filter { link -> !link.isM3u8 }.map { link -> newUriRequest( episode.id.toLong(), link.url, @@ -656,7 +681,8 @@ class ResultViewModel2 : ViewModel() { AcraApplication.context ?: return null, meta ), ".mp4" - ), folder, link.headers, USER_AGENT + ), folder, link.headers, USER_AGENT, + notificationMetaData = notification ) } @@ -668,13 +694,14 @@ class ResultViewModel2 : ViewModel() { true ) ) - } - .map { ExtractorSubtitleLink(it.name, it.url, "") } + }.distinctBy { it.url } + //.map { ExtractorSubtitleLink(it.name, it.url, "") } .map { link -> val fileName = VideoDownloadManager.getFileName( AcraApplication.context ?: return null, meta - ) + ) + ".vtt" + newUriRequest(0, link.url, fileName, folder, link.headers, USER_AGENT) //downloadSubtitle(context, link, fileName, folder) } @@ -1066,6 +1093,19 @@ class ResultViewModel2 : ViewModel() { handleEpisodeClickEvent(activity, click) } + private fun downloadFromRequest(req: DownloadRequest) { + Aria2Starter.download(req.links) + for (sub in req.subs.take(5)) { + Aria2Starter.download(sub) + } + } + + fun download(card: ResultEpisode) = ioSafe { + getRequest(card)?.let { req -> + downloadFromRequest(req) + } + } + suspend fun getRequest(card: ResultEpisode): DownloadRequest? { val response = currentResponse ?: return null return downloadEpisode( @@ -1202,7 +1242,7 @@ class ResultViewModel2 : ViewModel() { listOf(result.links[index]), result.subs, ) ?: return@ioSafe - Aria2Starter.client?.downloadFailQueue(req.links) { _, _ -> } + downloadFromRequest(req) } showToast( activity, diff --git a/app/src/main/res/layout/download_button.xml b/app/src/main/res/layout/download_button.xml new file mode 100644 index 00000000..9014102e --- /dev/null +++ b/app/src/main/res/layout/download_button.xml @@ -0,0 +1,9 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/download_button_layout.xml b/app/src/main/res/layout/download_button_layout.xml new file mode 100644 index 00000000..7f9caa1c --- /dev/null +++ b/app/src/main/res/layout/download_button_layout.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_result.xml b/app/src/main/res/layout/fragment_result.xml index 48aeb72e..eb6c7f33 100644 --- a/app/src/main/res/layout/fragment_result.xml +++ b/app/src/main/res/layout/fragment_result.xml @@ -570,89 +570,7 @@ android:focusable="true" android:layout_width="match_parent" />--> - - - - - - - - - - - - - - - - + @@ -65,6 +66,9 @@ #FFF @style/CustomPreferenceThemeOverlay + ?attr/white + ?attr/white + ?attr/white @@ -115,7 +117,7 @@ @color/colorPrimaryBlue #4855A2 #5A6BCB - #5A6BCB + @color/whiteText @color/colorPrimaryBlue @@ -125,7 +127,7 @@ @color/colorPrimaryPurple #4704A3 #7125DB - #7125DB + @color/whiteText @color/colorPrimaryPurple @@ -134,7 +136,7 @@ @color/colorPrimaryGreen #007363 #39C1AE - #39C1AE + @color/blackText @color/colorPrimaryGreen @@ -143,7 +145,7 @@ @color/colorPrimaryGreenApple #319B5A #51C57E - #51C57E + @color/blackText @color/colorPrimaryGreenApple @@ -152,7 +154,7 @@ @color/colorPrimaryRed #B62B2B @color/colorPrimaryRed - @color/colorPrimaryRed + @color/whiteText @color/colorPrimaryRed @@ -162,7 +164,7 @@ @color/colorPrimaryBanana #9B7D31 #C5B251 - #C5A851 + @color/blackText @color/colorPrimaryBanana @@ -171,7 +173,7 @@ @color/colorPrimaryParty #C1495B #FD798C - #BF5968 + @color/blackText @color/colorPrimaryParty @@ -180,7 +182,7 @@ @color/colorPrimaryPink #DD1280 #FF4DAE - #DD1280 + @color/blackText @color/colorPrimaryPink @@ -189,7 +191,7 @@ @color/colorPrimaryCarnationPink #83366f #BD5DA5 - #BD5DA5 + @color/blackText @color/colorPrimaryCarnationPink @@ -199,7 +201,7 @@ @color/colorPrimaryMaroon #370C0C #451010 - #451010 + @color/whiteText @color/colorPrimaryMaroon @@ -209,7 +211,7 @@ @color/colorPrimaryDarkGreen #003d00 #004500 - #004500 + @color/whiteText @color/colorPrimaryDarkGreen @@ -219,7 +221,7 @@ @color/colorPrimaryNavyBlue #000073 #000080 - #000080 + @color/whiteText @color/colorPrimaryNavyBlue @@ -229,7 +231,7 @@ @color/colorPrimaryGrey #484848 #515151 - #515151 + @color/whiteText @color/colorPrimaryGrey @@ -239,7 +241,7 @@ @color/colorPrimaryWhite #CCCCCC #FFFFFF - #FFFFFF + @color/blackText @color/colorPrimaryWhite @@ -249,7 +251,7 @@ @color/colorPrimaryBrown #582700 #622C00 - #622C00 + @color/whiteText @color/colorPrimaryBrown From a1165344d37b4ee15db0319323b3b37f596662c8 Mon Sep 17 00:00:00 2001 From: reduplicated <110570621+reduplicated@users.noreply.github.com> Date: Sun, 30 Oct 2022 22:41:26 +0100 Subject: [PATCH 7/7] download UI fixes --- .../lagradost/cloudstream3/CommonActivity.kt | 4 +- .../cloudstream3/ui/download/Aria2cHelper.kt | 5 +- .../ui/download/DownloadButtonSetup.kt | 142 +++++++++++++++++- .../ui/download/DownloadChildAdapter.kt | 138 ++--------------- .../ui/download/DownloadChildFragment.kt | 9 +- .../ui/download/DownloadFragment.kt | 3 +- .../ui/download/DownloadHeaderAdapter.kt | 85 +++-------- .../ui/download/DownloadViewModel.kt | 8 +- .../utils/VideoDownloadManager.kt | 13 +- .../res/layout/download_header_episode.xml | 135 ++++++----------- 10 files changed, 248 insertions(+), 294 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/CommonActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/CommonActivity.kt index 4eb1181d..aa0ad969 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/CommonActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/CommonActivity.kt @@ -168,8 +168,8 @@ object CommonActivity { Aria2Settings( "1337", //UUID.randomUUID().toString() 4337, - act.filesDir.path, //"/storage/emulated/0/Download",// - "${act.filesDir.path}/session" + act.filesDir.path + "/download", //"/storage/emulated/0/Download",// + null//"${act.filesDir.path}/session" ) ) } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/download/Aria2cHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/download/Aria2cHelper.kt index cb920f7c..94e52b8a 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/download/Aria2cHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/download/Aria2cHelper.kt @@ -16,7 +16,10 @@ object Aria2cHelper { VideoDownloadManager.downloadDeleteEvent.invoke(id.toInt()) getMetadata(id)?.let { data -> - Aria2Starter.deleteFiles(data.items.flatMap { it.files }) + Aria2Starter.delete( + DownloadListener.sessionIdToGid[id], + id, + data.items.flatMap { it.files }) } removeMetadata(id) AcraApplication.removeKey(KEY_DOWNLOAD_INFO, id.toString()) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadButtonSetup.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadButtonSetup.kt index 6fca517a..5f007de6 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadButtonSetup.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadButtonSetup.kt @@ -2,23 +2,160 @@ package com.lagradost.cloudstream3.ui.download import android.app.Activity import android.content.DialogInterface +import android.text.format.Formatter +import android.widget.TextView import android.widget.Toast import androidx.appcompat.app.AlertDialog +import androidx.core.view.doOnAttach +import androidx.lifecycle.findViewTreeLifecycleOwner import com.lagradost.cloudstream3.AcraApplication.Companion.getKey import com.lagradost.cloudstream3.CommonActivity.showToast import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.ui.player.DownloadFileGenerator import com.lagradost.cloudstream3.ui.player.GeneratorPlayer +import com.lagradost.cloudstream3.ui.result.DownloadHelper.play import com.lagradost.cloudstream3.utils.AppUtils.getNameFull import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE import com.lagradost.cloudstream3.utils.ExtractorUri import com.lagradost.cloudstream3.utils.UIHelper.navigate +import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIcons import com.lagradost.cloudstream3.utils.VideoDownloadHelper import com.lagradost.cloudstream3.utils.VideoDownloadManager -import com.lagradost.fetchbutton.aria2c.Aria2Starter +import com.lagradost.fetchbutton.aria2c.DownloadListener +import com.lagradost.fetchbutton.aria2c.DownloadStatusTell +import com.lagradost.fetchbutton.ui.PieFetchButton object DownloadButtonSetup { + fun bind( + card: IVisualDownloadChildCached, + downloadButton: PieFetchButton, + extraInfo: TextView, + clickCallback: (DownloadClickEvent) -> Unit + ) { + val d = card.data ?: return + + fun updateText(downloadBytes: Long, totalBytes: Long) { + extraInfo?.apply { + text = + context.getString(R.string.download_size_format).format( + Formatter.formatShortFileSize(context, downloadBytes), + Formatter.formatShortFileSize(context, totalBytes) + ) + } + } + updateText(card.currentBytes, card.totalBytes) + downloadButton.apply { + val play = + if (card is VisualDownloadChildCached) R.string.play_episode else R.string.play_movie_button//if (card.episode <= 0) R.string.play_movie_button else R.string.play_episode + + setPersistentId(d.id.toLong()) + doOnAttach { view -> + view.findViewTreeLifecycleOwner()?.let { life -> + DownloadListener.observe(life) { + gid?.let { realGId -> + val meta = DownloadListener.getInfo(realGId) + updateText(meta.downloadedLength, meta.totalLength) + } + } + } + } + + val isValid = when (downloadButton.currentStatus) { + null, DownloadStatusTell.Removed -> false + else -> true + } + + + downloadButton.setOnClickListener { + val view = downloadButton + + fun delete() { + // view.deleteAllFiles() + clickCallback.invoke( + DownloadClickEvent( + DOWNLOAD_ACTION_DELETE_FILE, + d + ) + ) + } + + //if (view !is PieFetchButton) return@setOnClickListener + when (view.currentStatus) { + /*null, DownloadStatusTell.Removed -> { + view.setStatus(DownloadStatusTell.Waiting) + downloadClickCallback.invoke( + DownloadEpisodeClickEvent( + DOWNLOAD_ACTION_DOWNLOAD, + card + ) + ) + }*/ + DownloadStatusTell.Paused -> { + view.popupMenuNoIcons( + if (isValid) listOf( + 1 to R.string.resume, + 2 to play, + 3 to R.string.delete + ) else listOf(2 to play, 3 to R.string.delete) + ) { + when (itemId) { + 1 -> if (!view.resumeDownload()) { + /*downloadClickCallback.invoke( + DownloadEpisodeClickEvent( + DOWNLOAD_ACTION_DOWNLOAD, + card + ) + )*/ + } + 2 -> play(d) + 3 -> delete() + } + } + } + DownloadStatusTell.Complete -> { + view.popupMenuNoIcons( + listOf( + 2 to play, + 3 to R.string.delete + ) + ) { + when (itemId) { + 2 -> play(d) + 3 -> delete() + } + } + } + DownloadStatusTell.Active -> { + view.popupMenuNoIcons( + if (isValid) listOf( + 4 to R.string.pause, + 2 to play, + 3 to R.string.delete + ) else listOf( + 2 to play, + 3 to R.string.delete + ) + ) { + when (itemId) { + 4 -> view.pauseDownload() + 2 -> play(d) + 3 -> delete() + } + } + } + DownloadStatusTell.Error -> { + view.redownload() + } + DownloadStatusTell.Waiting -> { + + } + else -> {} + } + } + } + } + fun handleDownloadClick(activity: Activity?, click: DownloadClickEvent) { val id = click.data.id if (click.data !is VideoDownloadHelper.DownloadEpisodeCached) return @@ -90,7 +227,8 @@ object DownloadButtonSetup { VideoDownloadManager.getDownloadFileInfoAndUpdateSettings( act, click.data.id - )?.fileLength ?: Aria2cHelper.getMetadata(click.data.id.toLong())?.downloadedLength + )?.fileLength + ?: Aria2cHelper.getMetadata(click.data.id.toLong())?.downloadedLength ?: 0 if (length > 0) { showToast(act, R.string.delete, Toast.LENGTH_LONG) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildAdapter.kt index 544a6985..2f8a42e5 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildAdapter.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildAdapter.kt @@ -1,15 +1,12 @@ package com.lagradost.cloudstream3.ui.download -import android.text.format.Formatter import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.cardview.widget.CardView -import androidx.core.view.doOnAttach import androidx.core.view.isVisible import androidx.core.widget.ContentLoadingProgressBar -import androidx.lifecycle.findViewTreeLifecycleOwner import androidx.recyclerview.widget.RecyclerView import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.ui.result.DownloadHelper.play @@ -17,10 +14,7 @@ import com.lagradost.cloudstream3.ui.result.ResultEpisode import com.lagradost.cloudstream3.utils.AppUtils.getNameFull import com.lagradost.cloudstream3.utils.DataStoreHelper.fixVisual import com.lagradost.cloudstream3.utils.DataStoreHelper.getViewPos -import com.lagradost.cloudstream3.utils.UIHelper.popupMenuNoIcons import com.lagradost.cloudstream3.utils.VideoDownloadHelper -import com.lagradost.fetchbutton.aria2c.DownloadListener -import com.lagradost.fetchbutton.aria2c.DownloadStatusTell import com.lagradost.fetchbutton.ui.PieFetchButton import kotlinx.android.synthetic.main.download_child_episode.view.* @@ -31,11 +25,17 @@ const val DOWNLOAD_ACTION_PAUSE_DOWNLOAD = 3 const val DOWNLOAD_ACTION_DOWNLOAD = 4 const val DOWNLOAD_ACTION_LONG_CLICK = 5 +interface IVisualDownloadChildCached{ + val currentBytes: Long + val totalBytes: Long + val data: VideoDownloadHelper.DownloadEpisodeCached? +} + data class VisualDownloadChildCached( - val currentBytes: Long, - val totalBytes: Long, - val data: VideoDownloadHelper.DownloadEpisodeCached, -) + override val currentBytes: Long, + override val totalBytes: Long, + override val data: VideoDownloadHelper.DownloadEpisodeCached, +) : IVisualDownloadChildCached data class DownloadClickEvent(val action: Int, val data: EasyDownloadButton.IMinimumData) data class DownloadEpisodeClickEvent(val action: Int, val data: ResultEpisode) @@ -97,124 +97,8 @@ class DownloadChildAdapter( title.text = title.context.getNameFull(d.name, d.episode, d.season) title.isSelected = true // is needed for text repeating //extraInfo.text = card.currentBytes + DownloadButtonSetup.bind(card, downloadButton, extraInfo, clickCallback) - fun updateText(downloadBytes: Long, totalBytes: Long) { - extraInfo?.apply { - text = - context.getString(R.string.download_size_format).format( - Formatter.formatShortFileSize(context, downloadBytes), - Formatter.formatShortFileSize(context, totalBytes) - ) - } - } - updateText(card.currentBytes, card.totalBytes) - - downloadButton.apply { - val play = - R.string.play_episode//if (card.episode <= 0) R.string.play_movie_button else R.string.play_episode - - setPersistentId(d.id.toLong()) - doOnAttach { view -> - view.findViewTreeLifecycleOwner()?.let { life -> - DownloadListener.observe(life) { - gid?.let { realGId -> - val meta = DownloadListener.getInfo(realGId) - updateText(meta.downloadedLength, meta.totalLength) - } - } - } - } - - downloadButton.isVisible = when (downloadButton.currentStatus) { - null, DownloadStatusTell.Removed -> false - else -> true - } - - - downloadButton.setOnClickListener { - val view = downloadButton - - fun delete() { - // view.deleteAllFiles() - clickCallback.invoke( - DownloadClickEvent( - DOWNLOAD_ACTION_DELETE_FILE, - d - ) - ) - } - - //if (view !is PieFetchButton) return@setOnClickListener - when (view.currentStatus) { - /*null, DownloadStatusTell.Removed -> { - view.setStatus(DownloadStatusTell.Waiting) - downloadClickCallback.invoke( - DownloadEpisodeClickEvent( - DOWNLOAD_ACTION_DOWNLOAD, - card - ) - ) - }*/ - DownloadStatusTell.Paused -> { - view.popupMenuNoIcons( - listOf( - 1 to R.string.resume, - 2 to play, - 3 to R.string.delete - ) - ) { - when (itemId) { - 1 -> if (!view.resumeDownload()) { - /*downloadClickCallback.invoke( - DownloadEpisodeClickEvent( - DOWNLOAD_ACTION_DOWNLOAD, - card - ) - )*/ - } - 2 -> play(d) - 3 -> delete() - } - } - } - DownloadStatusTell.Complete -> { - view.popupMenuNoIcons( - listOf( - 2 to play, - 3 to R.string.delete - ) - ) { - when (itemId) { - 2 -> play(d) - 3 -> delete() - } - } - } - DownloadStatusTell.Active -> { - view.popupMenuNoIcons( - listOf( - 4 to R.string.pause, - 2 to play, - 3 to R.string.delete - ) - ) { - when (itemId) { - 4 -> view.pauseDownload() - 2 -> play(d) - 3 -> delete() - } - } - } - DownloadStatusTell.Error -> { - view.redownload() - } - DownloadStatusTell.Waiting -> { - - } - else -> {} - } - } - } holder.setOnClickListener { if (downloadButton.isVisible) { downloadButton.play(d) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildFragment.kt index b96d097e..7d402d8b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadChildFragment.kt @@ -13,6 +13,7 @@ import com.lagradost.cloudstream3.utils.Coroutines.main import com.lagradost.cloudstream3.utils.DataStore.getKey import com.lagradost.cloudstream3.utils.DataStore.getKeys import com.lagradost.cloudstream3.utils.UIHelper.fixPaddingStatusbar +import com.lagradost.cloudstream3.utils.UIHelper.popCurrentPage import com.lagradost.cloudstream3.utils.VideoDownloadHelper import com.lagradost.cloudstream3.utils.VideoDownloadManager import kotlinx.android.synthetic.main.fragment_child_downloads.* @@ -41,7 +42,7 @@ class DownloadChildFragment : Fragment() { ): View? { return inflater.inflate(R.layout.fragment_child_downloads, container, false) } - + private var hasPopped = false // fix stupid bug private fun updateList(folder: String) = main { context?.let { ctx -> val data = withContext(Dispatchers.IO) { ctx.getKeys(folder) } @@ -54,8 +55,10 @@ class DownloadChildFragment : Fragment() { VisualDownloadChildCached(info.fileLength, info.totalBytes, it) } }.sortedBy { it.data.episode + (it.data.season ?: 0) * 100000 } - if (eps.isEmpty()) { - activity?.onBackPressed() + + if (eps.isEmpty() && !hasPopped) { + hasPopped = true + activity?.popCurrentPage() return@main } 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 b2286c99..cc47771f 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 @@ -69,7 +69,6 @@ class DownloadFragment : Fragment() { VideoDownloadManager.downloadDeleteEvent -= downloadDeleteEventListener!! downloadDeleteEventListener = null } - (download_list?.adapter as DownloadHeaderAdapter?)?.killAdapter() super.onDestroyView() } @@ -165,7 +164,7 @@ class DownloadFragment : Fragment() { downloadDeleteEventListener = { id -> val list = (download_list?.adapter as DownloadHeaderAdapter?)?.cardList if (list != null) { - if (list.any { it.data.id == id }) { + if (list.any { it.data?.id == id }) { context?.let { ctx -> setList(ArrayList()) downloadsViewModel.updateList(ctx) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadHeaderAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadHeaderAdapter.kt index 29bb303a..c1cb7e1c 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadHeaderAdapter.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadHeaderAdapter.kt @@ -8,23 +8,25 @@ import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView import androidx.cardview.widget.CardView +import androidx.core.view.isVisible import androidx.core.widget.ContentLoadingProgressBar import androidx.recyclerview.widget.RecyclerView import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.utils.UIHelper.setImage import com.lagradost.cloudstream3.utils.VideoDownloadHelper +import com.lagradost.fetchbutton.ui.PieFetchButton import kotlinx.android.synthetic.main.download_header_episode.view.* import java.util.* data class VisualDownloadHeaderCached( val currentOngoingDownloads: Int, val totalDownloads: Int, - val totalBytes: Long, - val currentBytes: Long, - val data: VideoDownloadHelper.DownloadHeaderCached, - val child: VideoDownloadHelper.DownloadEpisodeCached?, -) + override val totalBytes: Long, + override val currentBytes: Long, + val header: VideoDownloadHelper.DownloadHeaderCached, + override val data: VideoDownloadHelper.DownloadEpisodeCached?, +) : IVisualDownloadChildCached data class DownloadHeaderClickEvent(val action: Int, val data: VideoDownloadHelper.DownloadHeaderCached) @@ -34,35 +36,6 @@ class DownloadHeaderAdapter( private val movieClickCallback: (DownloadClickEvent) -> Unit, ) : RecyclerView.Adapter() { - private val mBoundViewHolders: HashSet = HashSet() - private fun getAllBoundViewHolders(): Set? { - return Collections.unmodifiableSet(mBoundViewHolders) - } - - fun killAdapter() { - getAllBoundViewHolders()?.forEach { view -> - view?.downloadButton?.dispose() - } - } - - override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) { - if (holder is DownloadButtonViewHolder) { - holder.downloadButton.dispose() - } - } - - override fun onViewRecycled(holder: RecyclerView.ViewHolder) { - if (holder is DownloadButtonViewHolder) { - holder.downloadButton.dispose() - mBoundViewHolders.remove(holder) - } - } - - override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) { - if (holder is DownloadButtonViewHolder) { - holder.reattachDownloadButton() - } - } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return DownloadHeaderViewHolder( @@ -76,7 +49,6 @@ class DownloadHeaderAdapter( when (holder) { is DownloadHeaderViewHolder -> { holder.bind(cardList[position]) - mBoundViewHolders.add(holder) } } } @@ -90,23 +62,17 @@ class DownloadHeaderAdapter( itemView: View, private val clickCallback: (DownloadHeaderClickEvent) -> Unit, private val movieClickCallback: (DownloadClickEvent) -> Unit, - ) : RecyclerView.ViewHolder(itemView), DownloadButtonViewHolder { - override var downloadButton = EasyDownloadButton() - + ) : RecyclerView.ViewHolder(itemView) { private val poster: ImageView? = itemView.download_header_poster private val title: TextView = itemView.download_header_title private val extraInfo: TextView = itemView.download_header_info private val holder: CardView = itemView.episode_holder - private val downloadBar: ContentLoadingProgressBar = itemView.download_header_progress_downloaded - private val downloadImage: ImageView = itemView.download_header_episode_download - private val normalImage: ImageView = itemView.download_header_goto_child - private var localCard: VisualDownloadHeaderCached? = null + private val downloadButton: PieFetchButton = itemView.download_header_download @SuppressLint("SetTextI18n") fun bind(card: VisualDownloadHeaderCached) { - localCard = card - val d = card.data + val d = card.header poster?.setImage(d.poster) poster?.setOnClickListener { @@ -117,10 +83,8 @@ class DownloadHeaderAdapter( val mbString = formatShortFileSize(itemView.context, card.totalBytes) //val isMovie = d.type.isMovieType() - if (card.child != null) { - downloadBar.visibility = View.VISIBLE - downloadImage.visibility = View.VISIBLE - normalImage.visibility = View.GONE + if (card.data != null) { + downloadButton.isVisible = true /*setUpButton( card.currentBytes, card.totalBytes, @@ -130,14 +94,15 @@ class DownloadHeaderAdapter( card.child, movieClickCallback )*/ + DownloadButtonSetup.bind(card, downloadButton, extraInfo) { click -> + movieClickCallback.invoke(DownloadClickEvent(click.action, card.data)) + } holder.setOnClickListener { - movieClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, card.child)) + movieClickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_PLAY_FILE, card.data)) } } else { - downloadBar.visibility = View.GONE - downloadImage.visibility = View.GONE - normalImage.visibility = View.VISIBLE + downloadButton.isVisible = false try { extraInfo.text = @@ -160,21 +125,5 @@ class DownloadHeaderAdapter( } } } - - override fun reattachDownloadButton() { - downloadButton.dispose() - val card = localCard - if (card?.child != null) { - downloadButton.setUpButton( - card.currentBytes, - card.totalBytes, - downloadBar, - downloadImage, - extraInfo, - card.child, - movieClickCallback - ) - } - } } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadViewModel.kt index d7bd618f..70458a62 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadViewModel.kt @@ -49,6 +49,8 @@ class DownloadViewModel : ViewModel() { .distinctBy { it.id } // Remove duplicates } + println("CHILDRE:$children") + // parentId : bytes val totalBytesUsedByChild = HashMap() // parentId : bytes @@ -69,7 +71,8 @@ class DownloadViewModel : ViewModel() { totalDownloads[c.parentId] = totalDownloads[c.parentId]?.plus(1) ?: 1 } } - println("FIXED: $totalDownloads") + println("TotalDownloads:$totalDownloads") + //println("FIXED: $totalDownloads") val cached = withContext(Dispatchers.IO) { // wont fetch useless keys totalDownloads.entries.filter { it.value > 0 }.mapNotNull { context.getKey( @@ -78,6 +81,7 @@ class DownloadViewModel : ViewModel() { ) } } + println("Cached:$cached") val visual = withContext(Dispatchers.IO) { cached.mapNotNull { // TODO FIX @@ -100,7 +104,7 @@ class DownloadViewModel : ViewModel() { movieEpisode ) }.sortedBy { - (it.child?.episode ?: 0) + (it.child?.season?.times(10000) ?: 0) + (it.data?.episode ?: 0) + (it.data?.season?.times(10000) ?: 0) } // episode sorting by episode, lowest to highest } try { diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt index 498b68e9..eec7ab17 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt @@ -530,6 +530,7 @@ object VideoDownloadManager { MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY), projection, selection, null, null ) + println("result:$result ${result?.count}") result.use { c -> if (c != null && c.count >= 1) { @@ -1505,21 +1506,31 @@ object VideoDownloadManager { private fun getDownloadFileInfo(context: Context, id: Int): DownloadedFileInfoResult? { try { + println("getDownloadFileInfo:$id") + val info = context.getKey(KEY_DOWNLOAD_INFO, id.toString()) ?: return null val base = basePathToFile(context, info.basePath) - + println("BASE:$info") if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && base.isDownloadDir()) { val cr = context.contentResolver ?: return null + println("CR:$cr") + val fileUri = cr.getExistingDownloadUriOrNullQ(info.relativePath, info.displayName) ?: return null + println("FILEURI:$fileUri") + val fileLength = cr.getFileLength(fileUri) ?: return null + println("fileLength:$fileLength") + if (fileLength == 0L) return null return DownloadedFileInfoResult(fileLength, info.totalBytes, fileUri) } else { + println("STUFF:$base") val file = base?.gotoDir(info.relativePath, false)?.findFile(info.displayName) + println("file:$file") // val normalPath = context.getNormalPath(getFile(info.relativePath), info.displayName) // val dFile = File(normalPath) diff --git a/app/src/main/res/layout/download_header_episode.xml b/app/src/main/res/layout/download_header_episode.xml index ead483e3..b422e8d4 100644 --- a/app/src/main/res/layout/download_header_episode.xml +++ b/app/src/main/res/layout/download_header_episode.xml @@ -1,103 +1,66 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/episode_holder" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="10dp" + android:layout_marginTop="10dp" + android:layout_marginEnd="10dp" + android:foreground="@drawable/outline_drawable" + app:cardBackgroundColor="?attr/boxItemBackground" + app:cardCornerRadius="@dimen/rounded_image_radius"> + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:foreground="?android:attr/selectableItemBackgroundBorderless" + android:orientation="horizontal"> + android:layout_width="70dp" + android:layout_height="104dp"> + android:id="@+id/download_header_poster" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:contentDescription="@string/episode_poster_img_des" + android:scaleType="centerCrop" + tools:src="@drawable/example_poster" /> + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginStart="15dp" + android:layout_marginEnd="50dp" + android:orientation="vertical"> - - - - - - - + android:layout_height="wrap_content" + android:textColor="?attr/textColor" + android:textStyle="bold" + tools:text="Perfect Run" /> - - - - + + + + \ No newline at end of file