Manage Peertube videos

This commit is contained in:
Thomas 2022-06-28 16:28:11 +02:00
parent fc4cbc5334
commit a48f997ae3
9 changed files with 123 additions and 27 deletions

View file

@ -125,7 +125,7 @@ public class MediaActivity extends BaseActivity implements OnDownloadInterface {
ScreenSlidePagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(MediaActivity.this);
binding.mediaViewpager.setAdapter(mPagerAdapter);
binding.mediaViewpager.setSaveEnabled(false);
binding.mediaViewpager.setCurrentItem(mediaPosition - 1);
binding.haulerView.setOnDragDismissedListener(dragDirection -> ActivityCompat.finishAfterTransition(MediaActivity.this));
registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

View file

@ -83,6 +83,7 @@ public class SearchResultTabActivity extends BaseActivity {
binding.searchTabLayout.setTabIconTint(ThemeHelper.getColorStateList(SearchResultTabActivity.this));
ScreenSlidePagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(SearchResultTabActivity.this);
binding.searchViewpager.setAdapter(mPagerAdapter);
binding.searchViewpager.setSaveEnabled(false);
binding.searchViewpager.setOffscreenPageLimit(3);
new TabLayoutMediator(binding.searchTabLayout, binding.searchViewpager,
(tab, position) -> {

View file

@ -224,4 +224,8 @@ public interface MastodonTimelinesService {
@Query("count") int count
);
@GET("api/v1/videos/{id}")
Call<PeertubeVideo.Video> getPeertubeVideo(
@Path("id") String id
);
}

View file

@ -44,4 +44,6 @@ public class Attachment implements Serializable {
@SerializedName("local_path")
public String local_path;
public String peertubeHost = null;
public String peertubeId = null;
}

View file

@ -56,9 +56,11 @@ public class PeertubeVideo implements Serializable {
status.account = account;
List<Attachment> attachmentList = new ArrayList<>();
Attachment attachment = new Attachment();
attachment.type = "video/mp4";
attachment.type = "video";
attachment.url = "https://" + peertubeVideo.account.host + peertubeVideo.embedPath;
attachment.preview_url = "https://" + peertubeVideo.account.host + peertubeVideo.thumbnailPath;
attachment.peertubeId = peertubeVideo.uuid;
attachment.peertubeHost = peertubeVideo.account.host;
attachmentList.add(attachment);
status.media_attachments = attachmentList;
return status;
@ -111,11 +113,33 @@ public class PeertubeVideo implements Serializable {
public Date updatedAt;
@SerializedName("uuid")
public String uuid;
@SerializedName("files")
public List<File> files;
@SerializedName("views")
public int views;
}
public class File implements Serializable {
@SerializedName("fileDownloadUrl")
public String fileDownloadUrl;
@SerializedName("fileUrl")
public String fileUrl;
@SerializedName("fps")
public int fps;
@SerializedName("magnetUri")
public String magnetUri;
@SerializedName("metadataUrl")
public String metadataUrl;
@SerializedName("resolution")
public Item resolutions;
@SerializedName("size")
public long size;
@SerializedName("torrentDownloadUrl")
public String torrentDownloadUrl;
@SerializedName("torrentUrl")
public String torrentUrl;
}
public static class PeertubeAccount implements Serializable {
@SerializedName("avatar")
public Avatar avatar;

View file

@ -280,6 +280,7 @@ public class Helper {
public static final Pattern libredditPattern = Pattern.compile("(www\\.|m\\.)?(reddit\\.com|preview\\.redd\\.it|i\\.redd\\.it|redd\\.it)/(((?!([\"'<])).)*)");
public static final Pattern ouichesPattern = Pattern.compile("https?://ouich\\.es/tag/(\\w+)");
public static final Pattern xmppPattern = Pattern.compile("xmpp:[-a-zA-Z0-9+$&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]");
public static final Pattern peertubePattern = Pattern.compile("(https?://([\\da-z.-]+\\.[a-z.]{2,10}))/videos/watch/(\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12})$");
public static final Pattern mediumPattern = Pattern.compile("([\\w@-]*)?\\.?medium.com/@?([/\\w-]+)");
public static final Pattern wikipediaPattern = Pattern.compile("([\\w_-]+)\\.wikipedia.org/(((?!([\"'<])).)*)");
public static final Pattern codePattern = Pattern.compile("code=([\\w-]+)");

View file

@ -433,6 +433,24 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
holder.binding.statusContent.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
holder.binding.spoiler.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
}
//If the message contain a link to peertube and no media was added, we add it
if (statusToDeal.card != null && statusToDeal.card.url != null && (statusToDeal.media_attachments == null || statusToDeal.media_attachments.size() == 0)) {
Matcher matcherLink = Helper.peertubePattern.matcher(statusToDeal.card.url);
if (matcherLink.find()) { //Peertubee video
List<Attachment> attachmentList = new ArrayList<>();
Attachment attachment = new Attachment();
attachment.type = "video";
attachment.url = matcherLink.group(0);
attachment.preview_url = statusToDeal.card.image;
attachment.peertubeHost = matcherLink.group(2);
attachment.peertubeId = matcherLink.group(3);
attachmentList.add(attachment);
statusToDeal.media_attachments = attachmentList;
adapter.notifyItemChanged(getPositionAsync(notificationList, statusList, statusToDeal));
}
}
if (status.card != null && (display_card || status.isFocused)) {
if (status.card.width > status.card.height) {
holder.binding.cardImageHorizontal.setVisibility(View.VISIBLE);

View file

@ -31,6 +31,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.preference.PreferenceManager;
import com.bumptech.glide.Glide;
@ -51,6 +52,7 @@ import app.fedilab.android.client.entities.api.Attachment;
import app.fedilab.android.databinding.FragmentSlideMediaBinding;
import app.fedilab.android.helper.CacheDataSourceFactory;
import app.fedilab.android.helper.Helper;
import app.fedilab.android.viewmodel.mastodon.TimelinesVM;
import app.fedilab.android.webview.CustomWebview;
import app.fedilab.android.webview.FedilabWebChromeClient;
import app.fedilab.android.webview.FedilabWebViewClient;
@ -198,32 +200,18 @@ public class FragmentMedia extends Fragment {
case "video":
case "audio":
case "gifv":
binding.pbarInf.setIndeterminate(false);
binding.pbarInf.setScaleY(3f);
binding.mediaVideo.setVisibility(View.VISIBLE);
Uri uri = Uri.parse(url);
String userAgent = sharedpreferences.getString(getString(R.string.SET_CUSTOM_USER_AGENT), Helper.USER_AGENT);
int video_cache = sharedpreferences.getInt(getString(R.string.SET_VIDEO_CACHE), Helper.DEFAULT_VIDEO_CACHE_MB);
ProgressiveMediaSource videoSource;
if (video_cache == 0) {
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(requireActivity(),
Util.getUserAgent(requireActivity(), userAgent), null);
videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(uri);
if (attachment.peertubeId != null) {
//It's a peertube video, we are fetching data
TimelinesVM timelinesVM = new ViewModelProvider(requireActivity()).get(TimelinesVM.class);
String finalType = type;
timelinesVM.getPeertubeVideo(attachment.peertubeHost, attachment.peertubeId).observe(requireActivity(), video -> {
if (video != null && video.files != null && video.files.size() > 0) {
loadVideo(video.files.get(0).fileUrl, finalType);
}
});
} else {
CacheDataSourceFactory cacheDataSourceFactory = new CacheDataSourceFactory(requireActivity());
videoSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
.createMediaSource(uri);
loadVideo(url, type);
}
player = new SimpleExoPlayer.Builder(requireActivity()).build();
if (type.equalsIgnoreCase("gifv"))
player.setRepeatMode(Player.REPEAT_MODE_ONE);
binding.mediaVideo.setPlayer(player);
binding.loader.setVisibility(View.GONE);
binding.mediaPicture.setVisibility(View.GONE);
player.prepare(videoSource);
player.setPlayWhenReady(true);
break;
case "web":
binding.loader.setVisibility(View.GONE);
@ -261,6 +249,35 @@ public class FragmentMedia extends Fragment {
}
}
private void loadVideo(String url, String type) {
binding.pbarInf.setIndeterminate(false);
binding.pbarInf.setScaleY(3f);
binding.mediaVideo.setVisibility(View.VISIBLE);
Uri uri = Uri.parse(url);
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity());
String userAgent = sharedpreferences.getString(getString(R.string.SET_CUSTOM_USER_AGENT), Helper.USER_AGENT);
int video_cache = sharedpreferences.getInt(getString(R.string.SET_VIDEO_CACHE), Helper.DEFAULT_VIDEO_CACHE_MB);
ProgressiveMediaSource videoSource;
if (video_cache == 0) {
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(requireActivity(),
Util.getUserAgent(requireActivity(), userAgent), null);
videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(uri);
} else {
CacheDataSourceFactory cacheDataSourceFactory = new CacheDataSourceFactory(requireActivity());
videoSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
.createMediaSource(uri);
}
player = new SimpleExoPlayer.Builder(requireActivity()).build();
if (type.equalsIgnoreCase("gifv"))
player.setRepeatMode(Player.REPEAT_MODE_ONE);
binding.mediaVideo.setPlayer(player);
binding.loader.setVisibility(View.GONE);
binding.mediaPicture.setVisibility(View.GONE);
player.prepare(videoSource);
player.setPlayWhenReady(true);
}
@Override
public void onCreate(Bundle saveInstance) {
super.onCreate(saveInstance);

View file

@ -71,6 +71,7 @@ public class TimelinesVM extends AndroidViewModel {
private MutableLiveData<List<StatusDraft>> statusDraftListMutableLiveData;
private MutableLiveData<Status> statusMutableLiveData;
private MutableLiveData<Statuses> statusesMutableLiveData;
private MutableLiveData<PeertubeVideo.Video> peertubeVideoMutableLiveData;
private MutableLiveData<Conversations> conversationListMutableLiveData;
private MutableLiveData<MastodonList> mastodonListMutableLiveData;
private MutableLiveData<List<MastodonList>> mastodonListListMutableLiveData;
@ -246,6 +247,34 @@ public class TimelinesVM extends AndroidViewModel {
}
/**
* Returns details for a peertube video
*
* @return {@link LiveData} containing a {@link PeertubeVideo.Video}
*/
public LiveData<PeertubeVideo.Video> getPeertubeVideo(@NonNull String instance, String id) {
MastodonTimelinesService mastodonTimelinesService = initInstanceOnly(instance);
peertubeVideoMutableLiveData = new MutableLiveData<>();
new Thread(() -> {
Call<PeertubeVideo.Video> publicTlCall = mastodonTimelinesService.getPeertubeVideo(id);
PeertubeVideo.Video peertubeVideo = null;
try {
Response<PeertubeVideo.Video> videoResponse = publicTlCall.execute();
if (videoResponse.isSuccessful()) {
peertubeVideo = videoResponse.body();
}
} catch (Exception e) {
e.printStackTrace();
}
Handler mainHandler = new Handler(Looper.getMainLooper());
PeertubeVideo.Video finalPeertubeVideo = peertubeVideo;
Runnable myRunnable = () -> peertubeVideoMutableLiveData.setValue(finalPeertubeVideo);
mainHandler.post(myRunnable);
}).start();
return peertubeVideoMutableLiveData;
}
/**
* View public statuses containing the given hashtag.
*