Add download video option

This commit is contained in:
Ivan Agosto 2024-06-05 12:28:06 -06:00
parent f86d66fdab
commit 3141500c53
8 changed files with 245 additions and 4 deletions

View File

@ -1,6 +1,7 @@
package org.libre.agosto.p2play
import android.annotation.SuppressLint
import android.app.DownloadManager
import android.content.Intent
import android.content.pm.ActivityInfo
import android.graphics.Bitmap
@ -34,6 +35,7 @@ import org.libre.agosto.p2play.ajax.Videos
import org.libre.agosto.p2play.databinding.ActivityReproductorBinding
import org.libre.agosto.p2play.helpers.setFullscreen
import org.libre.agosto.p2play.models.CommentaryModel
import org.libre.agosto.p2play.models.DownloadFiles
import org.libre.agosto.p2play.models.VideoModel
import org.libre.agosto.p2play.singletons.PlaybackSingleton
@ -127,6 +129,8 @@ class ReproductorActivity : AppCompatActivity() {
binding.reportLayout.setOnClickListener { reportIntent() }
fullscreenButton.setOnClickListener { toggleFullscreen() }
fullscreenButton2.setOnClickListener { toggleFullscreen() }
binding.downloadLayout!!.setOnClickListener { downloadVideo() }
binding.userImg.setOnClickListener {
val intent = Intent(this, ChannelActivity::class.java)
@ -444,6 +448,31 @@ class ReproductorActivity : AppCompatActivity() {
}
}
private fun downloadVideo() {
val downloadFile = videoPlayback.streamingData?.downloadFiles?.first()
if (downloadFile != null) {
val manager = getSystemService(DOWNLOAD_SERVICE) as DownloadManager
val request = DownloadManager.Request(Uri.parse(downloadFile.url))
val fileName = "${videoPlayback.name}-${downloadFile.resolution}.${downloadFile.url.split('.').last()}"
try {
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
.setTitle(fileName)
.setDescription(getString(R.string.downloadText))
.setDestinationInExternalPublicDir(
android.os.Environment.DIRECTORY_DOWNLOADS,
fileName
)
manager.enqueue(request)
ManagerSingleton.toast(getString(R.string.downloadStarted), this)
} catch (_: Exception) {
ManagerSingleton.toast(getString(R.string.downloadFailed), this)
}
} else {
ManagerSingleton.toast(getString(R.string.downloadFailed), this)
}
}
override fun onDestroy() {
if (!player.isPlaying) {
PlaybackSingleton.release()

View File

@ -2,10 +2,15 @@ package org.libre.agosto.p2play.models
import android.util.JsonReader
class DownloadFiles(
var resolution: String = "",
var url: String = ""
)
class StreamingModel(
var playlistUrl: String = "",
var segmentsSha256Url: String = "",
// TODO: Download Files
var downloadFiles: ArrayList<DownloadFiles> = arrayListOf<DownloadFiles>()
) {
fun parse(data: JsonReader) {
data.beginObject()
@ -18,6 +23,37 @@ class StreamingModel(
"segmentsSha256Url" -> {
this.segmentsSha256Url = data.nextString()
}
"files" -> {
data.beginArray()
if (data.hasNext()) {
data.beginObject()
val downloadFile = DownloadFiles()
while (data.hasNext()) {
val key2 = data.nextName()
when (key2.toString()) {
"fileDownloadUrl" -> downloadFile.url = data.nextString()
"resolution" -> {
data.beginObject()
while(data.hasNext()) {
val keyRes = data.nextName()
when (keyRes!!) {
"label" -> downloadFile.resolution = data.nextString()
else -> data.skipValue()
}
}
data.endObject()
}
else -> data.skipValue()
}
}
this.downloadFiles.add(downloadFile)
data.endObject()
}
while (data.hasNext()) {
data.skipValue()
}
data.endArray()
}
else -> data.skipValue()
}
}

View File

@ -77,13 +77,27 @@ class VideoModel(
data.beginObject()
while (data.hasNext()) {
val key2 = data.nextName()
streamingData = StreamingModel()
val downloadFile = DownloadFiles()
when (key2.toString()) {
"fileUrl" -> {
streamingData = StreamingModel()
streamingData!!.playlistUrl = data.nextString()
}
"fileDownloadUrl" -> downloadFile.url = data.nextString()
"resolution" -> {
data.beginObject()
while(data.hasNext()) {
val keyRes = data.nextName()
when (keyRes!!) {
"label" -> downloadFile.resolution = data.nextString()
else -> data.skipValue()
}
}
data.endObject()
}
else -> data.skipValue()
}
streamingData!!.downloadFiles.add(downloadFile)
}
data.endObject()
}

View File

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="960" android:viewportWidth="960" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M260,800Q169,800 104.5,737Q40,674 40,583Q40,505 87,444Q134,383 210,366Q227,294 295,229Q363,164 440,164Q473,164 496.5,187.5Q520,211 520,244L520,486L584,424L640,480L480,640L320,480L376,424L440,486L440,244Q364,258 322,317.5Q280,377 280,440L260,440Q202,440 161,481Q120,522 120,580Q120,638 161,679Q202,720 260,720L740,720Q782,720 811,691Q840,662 840,620Q840,578 811,549Q782,520 740,520L680,520L680,440Q680,392 658,350.5Q636,309 600,280L600,187Q674,222 717,290.5Q760,359 760,440L760,440L760,440Q829,448 874.5,499.5Q920,551 920,620Q920,695 867.5,747.5Q815,800 740,800L260,800ZM480,442Q480,442 480,442Q480,442 480,442L480,442Q480,442 480,442Q480,442 480,442L480,442Q480,442 480,442Q480,442 480,442L480,442Q480,442 480,442Q480,442 480,442Q480,442 480,442Q480,442 480,442L480,442Q480,442 480,442Q480,442 480,442Q480,442 480,442Q480,442 480,442L480,442L480,442Q480,442 480,442Q480,442 480,442Z"/>
</vector>

View File

@ -160,6 +160,35 @@
android:textAlignment="center" />
</LinearLayout>
<LinearLayout
android:id="@+id/downloadLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:visibility="visible">
<ImageView
android:id="@+id/downloadImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:adjustViewBounds="false"
android:contentDescription="@string/reportBtn"
android:cropToPadding="false"
android:visibility="visible"
app:srcCompat="@drawable/ic_outline_cloud_download_24"
app:tint="#585858" />
<TextView
android:id="@+id/downloadText"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="@string/downloadText"
android:textAlignment="center" />
</LinearLayout>
<LinearLayout
android:id="@+id/reportLayout"
android:layout_width="match_parent"
@ -174,7 +203,7 @@
android:layout_height="match_parent"
android:layout_weight="1"
android:adjustViewBounds="false"
android:contentDescription="@string/dislikeBtn"
android:contentDescription="@string/reportBtn"
android:cropToPadding="false"
android:visibility="visible"
app:srcCompat="@drawable/ic_alert" />
@ -188,6 +217,7 @@
android:textAlignment="center" />
</LinearLayout>
<LinearLayout
android:id="@+id/shareLayout"
android:layout_width="match_parent"

View File

@ -0,0 +1,124 @@
<resources>
<!-- Start Global string -->
<string name="comming">Bientôt disponible !</string>
<string name="charging">Chargement…</string>
<!-- End Global string -->
<!-- Start About strings -->
<string name="aboutLabel">À propos de P2Play</string>
<string name="aboutText">P2Play est une application Android non officielle pour PeerTube. Vous pouvez regarder et contribuer avec le code sur GitLab :</string>
<string name="aboutStatus">Vous pouvez suivre notre blog :</string>
<string name="aboutLicense">Licence GNU GPLv3</string>
<string name="aboutInstance">À propos de l\'instance</string>
<string name="aboutInWeb">Vous pouvez voir les termes et plus sur le web :</string>
<!-- End About strings -->
<!-- Start Host strings -->
<string name="hostInfoText">Sélectionnez votre instance</string>
<string name="okButton">Accepter</string>
<string name="errorMsg">Erreur, réessayez</string>
<string name="finallyMsg">Hôte enregistré</string>
<string name="instance">Instance</string>
<!-- End Host strings -->
<!-- Start Login strings -->
<string name="loginInfo">Connectez-vous ou créez un nouveau compte</string>
<string name="userTxt">Nom d\'utilisateur :</string>
<string name="userText" translatable="false"> </string>
<string name="passwordTxt">Mot de passe :</string>
<string name="passwordText" translatable="false"> </string>
<string name="loginBtn">Connectez-vous maintenant</string>
<string name="registerActionBtn">Créer un nouveau compte</string>
<string name="twoFactorLabel">Code à deux facteurs</string>
<!-- Toast msg -->
<string name="loginSuccess_msg">Vous êtes maintenant connecté</string>
<string name="loginError_msg">Une erreur est survenue</string>
<string name="loginFailed_msg">Identifiants invalides</string>
<string name="registerSuccess_msg">Vous êtes maintenant enregistré</string>
<string name="registerError_msg">Une erreur est survenue</string>
<string name="registerFailed_msg">Données invalides</string>
<!-- Register msg -->
<string name="registerBtn">Inscrivez-vous maintenant</string>
<string name="emailTxt">E-mail :</string>
<string name="emailText" translatable="false">user@mail.com</string>
<!-- End Login strings -->
<!-- Start Main strings -->
<string name="title_subscriptions">Abonnements</string>
<string name="title_recent">Récent</string>
<string name="title_popular">Populaire</string>
<string name="title_trending">Tendance</string>
<string name="title_local">Vidéos locales</string>
<string name="title_myVideos">Mes vidéos</string>
<string name="view_text">vues</string>
<string name="timeSec_text">secondes</string>
<string name="timeMin_text">minutes</string>
<string name="timeHrs_text">heures</string>
<string name="nav_header_title">Se connecter</string>
<string name="is_live_video">En direct</string>
<!-- Toast msg -->
<string name="logout_msg">Vous êtes maintenant déconnecté</string>
<!-- End Main strings -->
<!-- Start Menu strings -->
<string name="nav_subscriptions">Abonnements</string>
<string name="nav_popular">Populaire</string>
<string name="nav_trending">Tendance</string>
<string name="nav_recent">Récent</string>
<string name="nav_local">Local</string>
<string name="nav_about">À propos</string>
<string name="nav_history">Historique</string>
<string name="nav_menu_myLibrary">Ma bibliothèque</string>
<string name="nav_menu_videos">Vidéos</string>
<string name="nav_menu_more">Plus</string>
<string name="nav_likes">Les plus aimés</string>
<!-- End Menu strings -->
<!-- Start MiniMenu strings -->
<string name="action_settings">Paramètres</string>
<string name="action_login">Se connecter</string>
<string name="action_logout">Déconnexion</string>
<!-- End MiniMenu strings -->
<!-- Start Reproductor strings -->
<string name="descriptionTxt">Description :</string>
<string name="commentariesTxt">Commentaires :</string>
<string name="commentHolder">Faire un commentaire</string>
<!-- Actions -->
<string name="subscribeBtn">S\'abonner</string>
<string name="likeBtn">J\'aime</string>
<string name="dislikeBtn">Je n\'aime pas</string>
<string name="shareBtn">Partager</string>
<string name="reportBtn">Signaler</string>
<string name="unSubscribeBtn">Se désabonner</string>
<string name="commentaryText">Commentaire</string>
<string name="showMore">Afficher plus</string>
<!-- Comments -->
<string name="reply">Répondre</string>
<string name="see_replies">Voir les réponses (%1$d)</string>
<!-- Messages -->
<string name="subscribeMsg">Vous êtes abonné à cette chaîne</string>
<string name="rateMsg">Vous avez évalué la vidéo</string>
<string name="unSubscribeMsg">Vous vous êtes désabonné de cette chaîne</string>
<string name="makedCommentaryMsg">Vous avez commenté cette vidéo</string>
<string name="errorCommentaryMsg">Une erreur est survenue, réessayez</string>
<string name="emptyCommentaryMsg">Veuillez d\'abord faire un commentaire</string>
<!-- End Reproductor strings -->
<!-- Start Settings strings -->
<string name="title_activity_settings">Paramètres</string>
<!-- Example General settings -->
<string name="pref_header_general">Général</string>
<string name="pref_nfsw_title">Contenu NFSW</string>
<string name="pref_nfsw_description">Quand activé, cela peut afficher du contenu adulte et sensible.</string>
<string name="pref_hostname_title">Instance Peertube</string>
<string name="pref_hostname_error" translatable="false">-</string>
<string name="pref_message_exit">Redémarrez l\'application pour appliquer les changements</string>
<string name="pref_videos_count_title">Vidéos par page</string>
<!-- End Settings strings -->
<!-- Start Channel/Account strings -->
<string name="followersIndicator">Abonnés :</string>
<string name="hostIndicator">Hôte :</string>
<string name="accountName">Nom du compte :</string>
<!-- End Channel strings -->
<!-- Start Prompt string -->
<string name="reportDialog">Raison pour signaler cette vidéo :</string>
<string name="reportDialogMsg">Vous avez signalé la vidéo</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Bonjour fragment vide</string>
<!-- End Prompt strings -->
</resources>

View File

@ -105,6 +105,9 @@
<string name="makedCommentaryMsg">You have commented on this video</string>
<string name="errorCommentaryMsg">An error has occurred, try again</string>
<string name="emptyCommentaryMsg">Please make a comment first</string>
<string name="downloadText">Download</string>
<string name="downloadStarted">Download as started</string>
<string name="downloadFailed">Unable to download this video</string>
<!-- End Reproductor strings -->
<!-- Start Settings strings -->
<string name="title_activity_settings">Settings</string>

View File

@ -21,6 +21,6 @@ allprojects {
}
}
task clean(type: Delete) {
tasks.register('clean', Delete) {
delete rootProject.buildDir
}