mirror of
https://codeberg.org/tom79/Fedilab.git
synced 2024-12-22 16:50:04 +02:00
Manage Peertube videos
This commit is contained in:
parent
fc4cbc5334
commit
a48f997ae3
9 changed files with 123 additions and 27 deletions
|
@ -125,7 +125,7 @@ public class MediaActivity extends BaseActivity implements OnDownloadInterface {
|
||||||
|
|
||||||
ScreenSlidePagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(MediaActivity.this);
|
ScreenSlidePagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(MediaActivity.this);
|
||||||
binding.mediaViewpager.setAdapter(mPagerAdapter);
|
binding.mediaViewpager.setAdapter(mPagerAdapter);
|
||||||
|
binding.mediaViewpager.setSaveEnabled(false);
|
||||||
binding.mediaViewpager.setCurrentItem(mediaPosition - 1);
|
binding.mediaViewpager.setCurrentItem(mediaPosition - 1);
|
||||||
binding.haulerView.setOnDragDismissedListener(dragDirection -> ActivityCompat.finishAfterTransition(MediaActivity.this));
|
binding.haulerView.setOnDragDismissedListener(dragDirection -> ActivityCompat.finishAfterTransition(MediaActivity.this));
|
||||||
registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
|
registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
|
||||||
|
|
|
@ -83,6 +83,7 @@ public class SearchResultTabActivity extends BaseActivity {
|
||||||
binding.searchTabLayout.setTabIconTint(ThemeHelper.getColorStateList(SearchResultTabActivity.this));
|
binding.searchTabLayout.setTabIconTint(ThemeHelper.getColorStateList(SearchResultTabActivity.this));
|
||||||
ScreenSlidePagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(SearchResultTabActivity.this);
|
ScreenSlidePagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(SearchResultTabActivity.this);
|
||||||
binding.searchViewpager.setAdapter(mPagerAdapter);
|
binding.searchViewpager.setAdapter(mPagerAdapter);
|
||||||
|
binding.searchViewpager.setSaveEnabled(false);
|
||||||
binding.searchViewpager.setOffscreenPageLimit(3);
|
binding.searchViewpager.setOffscreenPageLimit(3);
|
||||||
new TabLayoutMediator(binding.searchTabLayout, binding.searchViewpager,
|
new TabLayoutMediator(binding.searchTabLayout, binding.searchViewpager,
|
||||||
(tab, position) -> {
|
(tab, position) -> {
|
||||||
|
|
|
@ -224,4 +224,8 @@ public interface MastodonTimelinesService {
|
||||||
@Query("count") int count
|
@Query("count") int count
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@GET("api/v1/videos/{id}")
|
||||||
|
Call<PeertubeVideo.Video> getPeertubeVideo(
|
||||||
|
@Path("id") String id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,4 +44,6 @@ public class Attachment implements Serializable {
|
||||||
@SerializedName("local_path")
|
@SerializedName("local_path")
|
||||||
public String local_path;
|
public String local_path;
|
||||||
|
|
||||||
|
public String peertubeHost = null;
|
||||||
|
public String peertubeId = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,9 +56,11 @@ public class PeertubeVideo implements Serializable {
|
||||||
status.account = account;
|
status.account = account;
|
||||||
List<Attachment> attachmentList = new ArrayList<>();
|
List<Attachment> attachmentList = new ArrayList<>();
|
||||||
Attachment attachment = new Attachment();
|
Attachment attachment = new Attachment();
|
||||||
attachment.type = "video/mp4";
|
attachment.type = "video";
|
||||||
attachment.url = "https://" + peertubeVideo.account.host + peertubeVideo.embedPath;
|
attachment.url = "https://" + peertubeVideo.account.host + peertubeVideo.embedPath;
|
||||||
attachment.preview_url = "https://" + peertubeVideo.account.host + peertubeVideo.thumbnailPath;
|
attachment.preview_url = "https://" + peertubeVideo.account.host + peertubeVideo.thumbnailPath;
|
||||||
|
attachment.peertubeId = peertubeVideo.uuid;
|
||||||
|
attachment.peertubeHost = peertubeVideo.account.host;
|
||||||
attachmentList.add(attachment);
|
attachmentList.add(attachment);
|
||||||
status.media_attachments = attachmentList;
|
status.media_attachments = attachmentList;
|
||||||
return status;
|
return status;
|
||||||
|
@ -111,11 +113,33 @@ public class PeertubeVideo implements Serializable {
|
||||||
public Date updatedAt;
|
public Date updatedAt;
|
||||||
@SerializedName("uuid")
|
@SerializedName("uuid")
|
||||||
public String uuid;
|
public String uuid;
|
||||||
|
@SerializedName("files")
|
||||||
|
public List<File> files;
|
||||||
@SerializedName("views")
|
@SerializedName("views")
|
||||||
public int 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 {
|
public static class PeertubeAccount implements Serializable {
|
||||||
@SerializedName("avatar")
|
@SerializedName("avatar")
|
||||||
public Avatar avatar;
|
public Avatar avatar;
|
||||||
|
|
|
@ -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 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 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 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 mediumPattern = Pattern.compile("([\\w@-]*)?\\.?medium.com/@?([/\\w-]+)");
|
||||||
public static final Pattern wikipediaPattern = Pattern.compile("([\\w_-]+)\\.wikipedia.org/(((?!([\"'<])).)*)");
|
public static final Pattern wikipediaPattern = Pattern.compile("([\\w_-]+)\\.wikipedia.org/(((?!([\"'<])).)*)");
|
||||||
public static final Pattern codePattern = Pattern.compile("code=([\\w-]+)");
|
public static final Pattern codePattern = Pattern.compile("code=([\\w-]+)");
|
||||||
|
|
|
@ -433,6 +433,24 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
|
||||||
holder.binding.statusContent.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
|
holder.binding.statusContent.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
|
||||||
holder.binding.spoiler.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 != null && (display_card || status.isFocused)) {
|
||||||
if (status.card.width > status.card.height) {
|
if (status.card.width > status.card.height) {
|
||||||
holder.binding.cardImageHorizontal.setVisibility(View.VISIBLE);
|
holder.binding.cardImageHorizontal.setVisibility(View.VISIBLE);
|
||||||
|
|
|
@ -31,6 +31,7 @@ import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
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.databinding.FragmentSlideMediaBinding;
|
||||||
import app.fedilab.android.helper.CacheDataSourceFactory;
|
import app.fedilab.android.helper.CacheDataSourceFactory;
|
||||||
import app.fedilab.android.helper.Helper;
|
import app.fedilab.android.helper.Helper;
|
||||||
|
import app.fedilab.android.viewmodel.mastodon.TimelinesVM;
|
||||||
import app.fedilab.android.webview.CustomWebview;
|
import app.fedilab.android.webview.CustomWebview;
|
||||||
import app.fedilab.android.webview.FedilabWebChromeClient;
|
import app.fedilab.android.webview.FedilabWebChromeClient;
|
||||||
import app.fedilab.android.webview.FedilabWebViewClient;
|
import app.fedilab.android.webview.FedilabWebViewClient;
|
||||||
|
@ -198,32 +200,18 @@ public class FragmentMedia extends Fragment {
|
||||||
case "video":
|
case "video":
|
||||||
case "audio":
|
case "audio":
|
||||||
case "gifv":
|
case "gifv":
|
||||||
binding.pbarInf.setIndeterminate(false);
|
if (attachment.peertubeId != null) {
|
||||||
binding.pbarInf.setScaleY(3f);
|
//It's a peertube video, we are fetching data
|
||||||
binding.mediaVideo.setVisibility(View.VISIBLE);
|
TimelinesVM timelinesVM = new ViewModelProvider(requireActivity()).get(TimelinesVM.class);
|
||||||
Uri uri = Uri.parse(url);
|
String finalType = type;
|
||||||
|
timelinesVM.getPeertubeVideo(attachment.peertubeHost, attachment.peertubeId).observe(requireActivity(), video -> {
|
||||||
String userAgent = sharedpreferences.getString(getString(R.string.SET_CUSTOM_USER_AGENT), Helper.USER_AGENT);
|
if (video != null && video.files != null && video.files.size() > 0) {
|
||||||
int video_cache = sharedpreferences.getInt(getString(R.string.SET_VIDEO_CACHE), Helper.DEFAULT_VIDEO_CACHE_MB);
|
loadVideo(video.files.get(0).fileUrl, finalType);
|
||||||
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 {
|
} else {
|
||||||
CacheDataSourceFactory cacheDataSourceFactory = new CacheDataSourceFactory(requireActivity());
|
loadVideo(url, type);
|
||||||
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);
|
|
||||||
break;
|
break;
|
||||||
case "web":
|
case "web":
|
||||||
binding.loader.setVisibility(View.GONE);
|
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
|
@Override
|
||||||
public void onCreate(Bundle saveInstance) {
|
public void onCreate(Bundle saveInstance) {
|
||||||
super.onCreate(saveInstance);
|
super.onCreate(saveInstance);
|
||||||
|
|
|
@ -71,6 +71,7 @@ public class TimelinesVM extends AndroidViewModel {
|
||||||
private MutableLiveData<List<StatusDraft>> statusDraftListMutableLiveData;
|
private MutableLiveData<List<StatusDraft>> statusDraftListMutableLiveData;
|
||||||
private MutableLiveData<Status> statusMutableLiveData;
|
private MutableLiveData<Status> statusMutableLiveData;
|
||||||
private MutableLiveData<Statuses> statusesMutableLiveData;
|
private MutableLiveData<Statuses> statusesMutableLiveData;
|
||||||
|
private MutableLiveData<PeertubeVideo.Video> peertubeVideoMutableLiveData;
|
||||||
private MutableLiveData<Conversations> conversationListMutableLiveData;
|
private MutableLiveData<Conversations> conversationListMutableLiveData;
|
||||||
private MutableLiveData<MastodonList> mastodonListMutableLiveData;
|
private MutableLiveData<MastodonList> mastodonListMutableLiveData;
|
||||||
private MutableLiveData<List<MastodonList>> mastodonListListMutableLiveData;
|
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.
|
* View public statuses containing the given hashtag.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue