1
0
mirror of https://framagit.org/tom79/fedilab-tube synced 2025-04-17 03:47:24 +02:00

some changes

This commit is contained in:
Thomas 2020-06-26 08:50:49 +02:00
parent b49a1e22d9
commit 84eb7184c9
62 changed files with 11854 additions and 14 deletions

View File

@ -0,0 +1,834 @@
package app.fedilab.fedilabtube;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.PopupMenu;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.ui.PlayerControlView;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.upstream.cache.CacheDataSourceFactory;
import com.google.android.exoplayer2.util.Util;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.WeakReference;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.net.ssl.HttpsURLConnection;
import app.fedilab.fedilabtube.asynctasks.ManagePlaylistsAsyncTask;
import app.fedilab.fedilabtube.asynctasks.PostActionAsyncTask;
import app.fedilab.fedilabtube.asynctasks.RetrievePeertubeSingleCommentsAsyncTask;
import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.TLSSocketFactory;
import app.fedilab.fedilabtube.client.entities.Account;
import app.fedilab.fedilabtube.client.entities.Peertube;
import app.fedilab.fedilabtube.client.entities.Playlist;
import app.fedilab.fedilabtube.helper.FullScreenMediaController;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.interfaces.OnPlaylistActionInterface;
import app.fedilab.fedilabtube.interfaces.OnPostActionInterface;
import app.fedilab.fedilabtube.interfaces.OnRetrievePeertubeInterface;
import app.fedilab.fedilabtube.sqlite.AccountDAO;
import app.fedilab.fedilabtube.sqlite.PeertubeFavoritesDAO;
import app.fedilab.fedilabtube.sqlite.Sqlite;
import app.fedilab.fedilabtube.webview.CustomWebview;
import app.fedilab.fedilabtube.webview.MastalabWebChromeClient;
import app.fedilab.fedilabtube.webview.MastalabWebViewClient;
import es.dmoral.toasty.Toasty;
import static app.fedilab.fedilabtube.asynctasks.ManagePlaylistsAsyncTask.action.GET_PLAYLIST_FOR_VIDEO;
public class PeertubeActivity extends AppCompatActivity implements OnRetrievePeertubeInterface, OnPostActionInterface, OnPlaylistActionInterface {
public static String video_id;
private String peertubeInstance, videoId;
private FullScreenMediaController.fullscreen fullscreen;
private RelativeLayout loader;
private TextView peertube_view_count, peertube_playlist, peertube_bookmark, peertube_like_count, peertube_dislike_count, peertube_share, peertube_download, peertube_description, peertube_title;
private ScrollView peertube_information_container;
private Peertube peertube;
private TextView toolbar_title;
private PlayerView playerView;
private SimpleExoPlayer player;
private boolean fullScreenMode;
private Dialog fullScreenDialog;
private AppCompatImageView fullScreenIcon;
private TextView resolution;
private int mode;
private LinearLayout write_comment_container;
private ImageView send;
private TextView add_comment_read;
private EditText add_comment_write;
private String instance;
private List<String> playlistForVideo;
private List<Playlist> playlists;
public static void hideKeyboard(Activity activity) {
if (activity != null && activity.getWindow() != null) {
activity.getWindow().getDecorView();
InputMethodManager imm = (InputMethodManager) activity.getSystemService(INPUT_METHOD_SERVICE);
assert imm != null;
imm.hideSoftInputFromWindow(activity.getWindow().getDecorView().getWindowToken(), 0);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
fullscreen = FullScreenMediaController.fullscreen.OFF;
fullScreenMode = false;
playlistForVideo = new ArrayList<>();
setContentView(R.layout.activity_peertube);
loader = findViewById(R.id.loader);
peertube_view_count = findViewById(R.id.peertube_view_count);
peertube_bookmark = findViewById(R.id.peertube_bookmark);
peertube_like_count = findViewById(R.id.peertube_like_count);
peertube_dislike_count = findViewById(R.id.peertube_dislike_count);
peertube_share = findViewById(R.id.peertube_share);
peertube_download = findViewById(R.id.peertube_download);
peertube_description = findViewById(R.id.peertube_description);
peertube_title = findViewById(R.id.peertube_title);
peertube_information_container = findViewById(R.id.peertube_information_container);
CustomWebview webview_video = findViewById(R.id.webview_video);
playerView = findViewById(R.id.media_video);
write_comment_container = findViewById(R.id.write_comment_container);
ImageView my_pp = findViewById(R.id.my_pp);
add_comment_read = findViewById(R.id.add_comment_read);
add_comment_write = findViewById(R.id.add_comment_write);
peertube_playlist = findViewById(R.id.peertube_playlist);
send = findViewById(R.id.send);
add_comment_read.setOnClickListener(v -> {
add_comment_read.setVisibility(View.GONE);
add_comment_write.setVisibility(View.VISIBLE);
send.setVisibility(View.VISIBLE);
add_comment_write.requestFocus();
add_comment_write.setSelection(add_comment_write.getText().length());
});
peertube_playlist.setVisibility(View.VISIBLE);
peertube_bookmark.setVisibility(View.GONE);
send.setOnClickListener(v -> {
String comment = add_comment_write.getText().toString();
if (comment.trim().length() > 0) {
new PostActionAsyncTask(PeertubeActivity.this, PeertubeAPI.StatusAction.PEERTUBECOMMENT, peertube.getId(), null, comment, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
add_comment_write.setText("");
add_comment_read.setVisibility(View.VISIBLE);
add_comment_write.setVisibility(View.GONE);
send.setVisibility(View.GONE);
add_comment_read.requestFocus();
}
});
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
instance = sharedpreferences.getString(Helper.PREF_INSTANCE, Helper.getLiveInstance(PeertubeActivity.this));
Account account = new AccountDAO(PeertubeActivity.this, db).getUniqAccount(userId, instance);
Helper.loadGiF(PeertubeActivity.this, account, my_pp);
Bundle b = getIntent().getExtras();
if (b != null) {
peertubeInstance = b.getString("peertube_instance", null);
videoId = b.getString("video_id", null);
}
if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
assert inflater != null;
View view = inflater.inflate(R.layout.simple_bar, new LinearLayout(PeertubeActivity.this), false);
view.setBackground(new ColorDrawable(ContextCompat.getColor(PeertubeActivity.this, R.color.cyanea_primary)));
actionBar.setCustomView(view, new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
ImageView toolbar_close = actionBar.getCustomView().findViewById(R.id.toolbar_close);
toolbar_title = actionBar.getCustomView().findViewById(R.id.toolbar_title);
toolbar_close.setOnClickListener(v -> finish());
}
mode = sharedpreferences.getInt(Helper.SET_VIDEO_MODE, Helper.VIDEO_MODE_DIRECT);
if (mode != Helper.VIDEO_MODE_WEBVIEW && mode != Helper.VIDEO_MODE_DIRECT)
mode = Helper.VIDEO_MODE_DIRECT;
if (mode == Helper.VIDEO_MODE_WEBVIEW) {
webview_video.setVisibility(View.VISIBLE);
playerView.setVisibility(View.GONE);
webview_video = Helper.initializeWebview(PeertubeActivity.this, R.id.webview_video, null);
FrameLayout webview_container = findViewById(R.id.main_media_frame);
final ViewGroup videoLayout = findViewById(R.id.videoLayout);
MastalabWebChromeClient mastalabWebChromeClient = new MastalabWebChromeClient(PeertubeActivity.this, webview_video, webview_container, videoLayout);
mastalabWebChromeClient.setOnToggledFullscreen(fullscreen -> {
if (fullscreen) {
videoLayout.setVisibility(View.VISIBLE);
WindowManager.LayoutParams attrs = getWindow().getAttributes();
attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
attrs.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
getWindow().setAttributes(attrs);
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
peertube_information_container.setVisibility(View.GONE);
} else {
WindowManager.LayoutParams attrs = getWindow().getAttributes();
attrs.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
attrs.flags &= ~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
getWindow().setAttributes(attrs);
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
videoLayout.setVisibility(View.GONE);
peertube_information_container.setVisibility(View.VISIBLE);
}
});
String user_agent = sharedpreferences.getString(Helper.SET_CUSTOM_USER_AGENT, Helper.USER_AGENT);
webview_video.getSettings().setUserAgentString(user_agent);
webview_video.getSettings().setAllowFileAccess(true);
webview_video.setWebChromeClient(mastalabWebChromeClient);
webview_video.getSettings().setDomStorageEnabled(true);
webview_video.getSettings().setAppCacheEnabled(true);
webview_video.getSettings().setMediaPlaybackRequiresUserGesture(false);
webview_video.setWebViewClient(new MastalabWebViewClient(PeertubeActivity.this));
webview_video.loadUrl("https://" + peertubeInstance + "/videos/embed/" + videoId);
} else {
webview_video.setVisibility(View.GONE);
playerView.setVisibility(View.VISIBLE);
loader.setVisibility(View.VISIBLE);
}
if (mode != Helper.VIDEO_MODE_WEBVIEW) {
playerView.setControllerShowTimeoutMs(1000);
playerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIT);
initFullscreenDialog();
initFullscreenButton();
}
if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE) {
new ManagePlaylistsAsyncTask(PeertubeActivity.this, GET_PLAYLIST, null, null, null, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
new RetrievePeertubeSingleAsyncTask(PeertubeActivity.this, peertubeInstance, videoId, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public void change() {
if (fullscreen == FullScreenMediaController.fullscreen.ON) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN |
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Objects.requireNonNull(getSupportActionBar()).hide();
peertube_information_container.setVisibility(View.GONE);
} else {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
Objects.requireNonNull(getSupportActionBar()).show();
peertube_information_container.setVisibility(View.VISIBLE);
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
View v = getCurrentFocus();
if ((ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) &&
v instanceof EditText &&
v.getId() == R.id.add_comment_write) {
int[] scrcoords = new int[2];
v.getLocationOnScreen(scrcoords);
float x = ev.getRawX() + v.getLeft() - scrcoords[0];
float y = ev.getRawY() + v.getTop() - scrcoords[1];
if (x < v.getLeft() || x > v.getRight() || y < v.getTop() || y > v.getBottom()) {
add_comment_read.setVisibility(View.VISIBLE);
add_comment_write.setVisibility(View.GONE);
send.setVisibility(View.GONE);
hideKeyboard(PeertubeActivity.this);
}
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onCreateOptionsMenu(@NotNull Menu menu) {
getMenuInflater().inflate(R.menu.main_webview, menu);
menu.findItem(R.id.action_go).setVisible(false);
menu.findItem(R.id.action_block).setVisible(false);
menu.findItem(R.id.action_comment).setVisible(true);
if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE) {
MenuItem item = menu.findItem(R.id.action_comment);
if (item != null)
item.setVisible(false);
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
case R.id.action_comment:
if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) {
Toasty.info(PeertubeActivity.this, getString(R.string.retrieve_remote_status), Toast.LENGTH_LONG).show();
new commentTask(new WeakReference<>(PeertubeActivity.this), peertube).execute();
} else if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE) {
if (!peertube.isCommentsEnabled()) {
Toasty.info(PeertubeActivity.this, getString(R.string.comment_no_allowed_peertube), Toast.LENGTH_LONG).show();
return true;
}
int style;
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
if (theme == Helper.THEME_DARK) {
style = R.style.DialogDark;
} else if (theme == Helper.THEME_BLACK) {
style = R.style.DialogBlack;
} else {
style = R.style.Dialog;
}
AlertDialog.Builder builderInner;
builderInner = new AlertDialog.Builder(PeertubeActivity.this, style);
builderInner.setTitle(R.string.comment);
EditText input = new EditText(PeertubeActivity.this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
input.setLayoutParams(lp);
builderInner.setView(input);
builderInner.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
builderInner.setPositiveButton(R.string.validate, (dialog, which) -> {
String comment = input.getText().toString();
if (comment.trim().length() > 0) {
new PostActionAsyncTask(PeertubeActivity.this, API.StatusAction.PEERTUBECOMMENT, peertube.getId(), null, comment, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
dialog.dismiss();
}
});
builderInner.show();
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public FullScreenMediaController.fullscreen getFullscreen() {
return fullscreen;
}
public void setFullscreen(FullScreenMediaController.fullscreen fullscreen) {
this.fullscreen = fullscreen;
}
@Override
public void onRetrievePeertube(APIResponse apiResponse) {
if (apiResponse == null || (apiResponse.getError() != null) || apiResponse.getPeertubes() == null || apiResponse.getPeertubes().size() == 0) {
Toasty.error(PeertubeActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
loader.setVisibility(View.GONE);
return;
}
if (apiResponse.getPeertubes() == null || apiResponse.getPeertubes().get(0) == null || apiResponse.getPeertubes().get(0).getFileUrl(null, apiResponse.getPeertubes().get(0).isStreamService()) == null) {
Toasty.error(PeertubeActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
loader.setVisibility(View.GONE);
return;
}
peertube = apiResponse.getPeertubes().get(0);
new ManagePlaylistsAsyncTask(PeertubeActivity.this, GET_PLAYLIST_FOR_VIDEO, null, peertube.getId(), null, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
peertube_playlist.setOnClickListener(v -> {
if (playlists != null && peertube.getId() != null) {
PopupMenu popup = new PopupMenu(PeertubeActivity.this, peertube_playlist);
for (Playlist playlist : playlists) {
String title = null;
for (String id : playlistForVideo) {
if (playlist.getId().equals(id)) {
title = "" + playlist.getDisplayName();
break;
}
}
if (title == null) {
title = playlist.getDisplayName();
}
MenuItem item = popup.getMenu().add(0, 0, Menu.NONE, title);
item.setOnMenuItemClickListener(item1 -> {
item1.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
item1.setActionView(new View(PeertubeActivity.this));
item1.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem item1) {
return false;
}
@Override
public boolean onMenuItemActionCollapse(MenuItem item1) {
return false;
}
});
if (playlistForVideo.contains(playlist.getId())) {
item1.setTitle(playlist.getDisplayName());
new ManagePlaylistsAsyncTask(PeertubeActivity.this, ManagePlaylistsAsyncTask.action.DELETE_VIDEOS, playlist, peertube.getId(), null, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
playlistForVideo.remove(playlist.getId());
} else {
item1.setTitle("" + playlist.getDisplayName());
new ManagePlaylistsAsyncTask(PeertubeActivity.this, ManagePlaylistsAsyncTask.action.ADD_VIDEOS, playlist, peertube.getId(), null, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
playlistForVideo.add(playlist.getId());
}
return false;
});
popup.show();
}
}
});
if (peertube.isCommentsEnabled()) {
new RetrievePeertubeSingleCommentsAsyncTask(PeertubeActivity.this, peertubeInstance, videoId, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
write_comment_container.setVisibility(View.VISIBLE);
} else {
RelativeLayout no_action = findViewById(R.id.no_action);
TextView no_action_text = findViewById(R.id.no_action_text);
no_action_text.setText(getString(R.string.comment_no_allowed_peertube));
no_action.setVisibility(View.VISIBLE);
write_comment_container.setVisibility(View.GONE);
}
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
toolbar_title.setText(peertube.getName());
peertube_description.setText(peertube.getDescription());
peertube_title.setText(peertube.getName());
peertube_dislike_count.setText(String.valueOf(peertube.getDislike()));
peertube_like_count.setText(String.valueOf(peertube.getLike()));
peertube_view_count.setText(String.valueOf(peertube.getView()));
video_id = peertube.getId();
changeColor();
initResolution();
peertube_like_count.setOnClickListener(v -> {
String newState = peertube.getMyRating().equals("like") ? "none" : "like";
new PostActionAsyncTask(PeertubeActivity.this, PeertubeAPI.StatusAction.RATEVIDEO, peertube.getId(), null, newState, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
peertube.setMyRating(newState);
changeColor();
});
peertube_dislike_count.setOnClickListener(v -> {
String newState = peertube.getMyRating().equals("dislike") ? "none" : "dislike";
new PostActionAsyncTask(PeertubeActivity.this, PeertubeAPI.StatusAction.RATEVIDEO, peertube.getId(), null, newState, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
peertube.setMyRating(newState);
changeColor();
});
try {
HttpsURLConnection.setDefaultSSLSocketFactory(new TLSSocketFactory(instance));
} catch (KeyManagementException | NoSuchAlgorithmException e) {
e.printStackTrace();
}
if (mode == Helper.VIDEO_MODE_DIRECT) {
String userAgent = sharedpreferences.getString(Helper.SET_CUSTOM_USER_AGENT, Helper.USER_AGENT);
int video_cache = sharedpreferences.getInt(Helper.SET_VIDEO_CACHE, Helper.DEFAULT_VIDEO_CACHE_MB);
ProgressiveMediaSource videoSource;
if (video_cache == 0) {
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(PeertubeActivity.this,
Util.getUserAgent(PeertubeActivity.this, userAgent), null);
videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(apiResponse.getPeertubes().get(0).getFileUrl(null, apiResponse.getPeertubes().get(0).isStreamService())));
} else {
CacheDataSourceFactory cacheDataSourceFactory = new CacheDataSourceFactory(PeertubeActivity.this);
videoSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
.createMediaSource(Uri.parse(apiResponse.getPeertubes().get(0).getFileUrl(null, apiResponse.getPeertubes().get(0).isStreamService())));
}
player = ExoPlayerFactory.newSimpleInstance(PeertubeActivity.this);
playerView.setPlayer(player);
loader.setVisibility(View.GONE);
player.prepare(videoSource);
player.setPlayWhenReady(true);
}
peertube_download.setOnClickListener(v -> {
if (Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(PeertubeActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(PeertubeActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(PeertubeActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, Helper.EXTERNAL_STORAGE_REQUEST_CODE);
} else {
Helper.manageDownloads(PeertubeActivity.this, peertube.getFileDownloadUrl(null, peertube.isStreamService()));
}
} else {
Helper.manageDownloads(PeertubeActivity.this, peertube.getFileDownloadUrl(null, peertube.isStreamService()));
}
});
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
List<Peertube> peertubes = new PeertubeFavoritesDAO(PeertubeActivity.this, db).getSinglePeertube(peertube);
Drawable img;
if (peertubes == null || peertubes.size() == 0)
img = ContextCompat.getDrawable(PeertubeActivity.this, R.drawable.ic_bookmark_peertube_border);
else
img = ContextCompat.getDrawable(PeertubeActivity.this, R.drawable.ic_bookmark_peertube);
peertube_bookmark.setCompoundDrawablesWithIntrinsicBounds(null, img, null, null);
peertube_bookmark.setOnClickListener(v -> {
List<Peertube> peertubes1 = new PeertubeFavoritesDAO(PeertubeActivity.this, db).getSinglePeertube(peertube);
if (peertubes1 == null || peertubes1.size() == 0) {
new PeertubeFavoritesDAO(PeertubeActivity.this, db).insert(peertube);
Toasty.success(PeertubeActivity.this, getString(R.string.bookmark_add_peertube), Toast.LENGTH_SHORT).show();
} else {
new PeertubeFavoritesDAO(PeertubeActivity.this, db).remove(peertube);
Toasty.success(PeertubeActivity.this, getString(R.string.bookmark_remove_peertube), Toast.LENGTH_SHORT).show();
}
if (peertubes1 != null && peertubes1.size() > 0) //Was initially in cache
peertube_bookmark.setCompoundDrawablesWithIntrinsicBounds(null, ContextCompat.getDrawable(PeertubeActivity.this, R.drawable.ic_bookmark_peertube_border), null, null);
else
peertube_bookmark.setCompoundDrawablesWithIntrinsicBounds(null, ContextCompat.getDrawable(PeertubeActivity.this, R.drawable.ic_bookmark_peertube), null, null);
});
peertube_share.setOnClickListener(v -> {
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.shared_via));
String url;
url = "https://" + peertube.getInstance() + "/videos/watch/" + peertube.getUuid();
boolean share_details = sharedpreferences.getBoolean(Helper.SET_SHARE_DETAILS, true);
String extra_text;
if (share_details) {
extra_text = "@" + peertube.getAccount().getAcct();
extra_text += "\r\n\r\n" + peertube.getName();
extra_text += "\n\n\uD83D\uDD17 " + url + "\r\n-\n";
final String contentToot;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
contentToot = Html.fromHtml(peertube.getDescription(), Html.FROM_HTML_MODE_LEGACY).toString();
else
contentToot = Html.fromHtml(peertube.getDescription()).toString();
extra_text += contentToot;
} else {
extra_text = url;
}
sendIntent.putExtra(Intent.EXTRA_TEXT, extra_text);
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent, getString(R.string.share_with)));
});
}
@Override
public void onConfigurationChanged(@NotNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
if (mode != Helper.VIDEO_MODE_WEBVIEW) {
openFullscreenDialog();
}
setFullscreen(FullScreenMediaController.fullscreen.ON);
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
if (mode != Helper.VIDEO_MODE_WEBVIEW) {
closeFullscreenDialog();
}
setFullscreen(FullScreenMediaController.fullscreen.OFF);
}
change();
}
@Override
public void onRetrievePeertubeComments(APIResponse apiResponse) {
if (apiResponse == null || (apiResponse.getError() != null && apiResponse.getError().getStatusCode() != 404 && apiResponse.getError() != null && apiResponse.getError().getStatusCode() != 501)) {
if (apiResponse == null)
Toasty.error(PeertubeActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
else
Toasty.error(PeertubeActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
return;
}
List<Status> statuses = apiResponse.getStatuses();
RecyclerView lv_comments = findViewById(R.id.peertube_comments);
if (statuses == null || statuses.size() == 0) {
if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE) {
RelativeLayout no_action = findViewById(R.id.no_action);
no_action.setVisibility(View.VISIBLE);
lv_comments.setVisibility(View.GONE);
}
} else {
lv_comments.setVisibility(View.VISIBLE);
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
boolean isOnWifi = Helper.isOnWIFI(PeertubeActivity.this);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
StatusDrawerParams statusDrawerParams = new StatusDrawerParams();
statusDrawerParams.setType(RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE);
statusDrawerParams.setTargetedId(userId);
statusDrawerParams.setOnWifi(isOnWifi);
statusDrawerParams.setStatuses(statuses);
StatusListAdapter statusListAdapter = new StatusListAdapter(statusDrawerParams);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(PeertubeActivity.this);
lv_comments.setLayoutManager(mLayoutManager);
lv_comments.setNestedScrollingEnabled(false);
lv_comments.setAdapter(statusListAdapter);
}
}
@Override
public void onRetrievePeertubeChannels(APIResponse apiResponse) {
}
@Override
public void onDestroy() {
super.onDestroy();
if (player != null)
player.release();
}
@Override
protected void onPause() {
super.onPause();
if (player != null) {
player.setPlayWhenReady(false);
}
}
@Override
public void onResume() {
super.onResume();
if (player != null) {
player.setPlayWhenReady(true);
}
}
public void displayResolution() {
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
int style;
if (theme == Helper.THEME_DARK) {
style = R.style.DialogDark;
} else if (theme == Helper.THEME_BLACK) {
style = R.style.DialogBlack;
} else {
style = R.style.Dialog;
}
AlertDialog.Builder builderSingle = new AlertDialog.Builder(PeertubeActivity.this, style);
builderSingle.setTitle(R.string.pickup_resolution);
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(PeertubeActivity.this, android.R.layout.select_dialog_item);
for (String resolution : peertube.getResolution())
arrayAdapter.add(resolution + "p");
builderSingle.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
builderSingle.setAdapter(arrayAdapter, (dialog, which) -> {
String res = Objects.requireNonNull(arrayAdapter.getItem(which)).substring(0, Objects.requireNonNull(arrayAdapter.getItem(which)).length() - 1);
if (playerView != null) {
loader.setVisibility(View.VISIBLE);
long position = player.getCurrentPosition();
PlayerControlView controlView = playerView.findViewById(R.id.exo_controller);
resolution = controlView.findViewById(R.id.resolution);
resolution.setText(String.format("%sp", res));
if (mode == Helper.VIDEO_MODE_DIRECT) {
if (player != null)
player.release();
player = ExoPlayerFactory.newSimpleInstance(PeertubeActivity.this);
playerView.setPlayer(player);
loader.setVisibility(View.GONE);
String userAgent = sharedpreferences.getString(Helper.SET_CUSTOM_USER_AGENT, Helper.USER_AGENT);
int video_cache = sharedpreferences.getInt(Helper.SET_VIDEO_CACHE, Helper.DEFAULT_VIDEO_CACHE_MB);
ProgressiveMediaSource videoSource;
if (video_cache == 0) {
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(PeertubeActivity.this,
Util.getUserAgent(PeertubeActivity.this, userAgent), null);
videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(Uri.parse(peertube.getFileUrl(res, peertube.isStreamService())));
} else {
CacheDataSourceFactory cacheDataSourceFactory = new CacheDataSourceFactory(PeertubeActivity.this);
videoSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
.createMediaSource(Uri.parse(peertube.getFileUrl(res, peertube.isStreamService())));
}
player.prepare(videoSource);
player.seekTo(0, position);
player.setPlayWhenReady(true);
}
}
});
builderSingle.show();
}
@Override
public void onPostAction(int statusCode, API.StatusAction statusAction, String userId, Error error) {
if (peertube.isCommentsEnabled() && statusAction == API.StatusAction.PEERTUBECOMMENT)
new RetrievePeertubeSingleCommentsAsyncTask(PeertubeActivity.this, peertubeInstance, videoId, PeertubeActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private void initFullscreenDialog() {
fullScreenDialog = new Dialog(this, android.R.style.Theme_Black_NoTitleBar_Fullscreen) {
public void onBackPressed() {
if (fullScreenMode)
closeFullscreenDialog();
super.onBackPressed();
}
};
}
private void openFullscreenDialog() {
((ViewGroup) playerView.getParent()).removeView(playerView);
fullScreenDialog.addContentView(playerView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
fullScreenIcon.setImageDrawable(ContextCompat.getDrawable(PeertubeActivity.this, R.drawable.ic_fullscreen_exit));
fullScreenMode = true;
fullScreenDialog.show();
}
private void closeFullscreenDialog() {
((ViewGroup) playerView.getParent()).removeView(playerView);
((FrameLayout) findViewById(R.id.main_media_frame)).addView(playerView);
fullScreenMode = false;
fullScreenDialog.dismiss();
fullScreenIcon.setImageDrawable(ContextCompat.getDrawable(PeertubeActivity.this, R.drawable.ic_fullscreen));
}
private void initFullscreenButton() {
PlayerControlView controlView = playerView.findViewById(R.id.exo_controller);
fullScreenIcon = controlView.findViewById(R.id.exo_fullscreen_icon);
View fullScreenButton = controlView.findViewById(R.id.exo_fullscreen_button);
fullScreenButton.setOnClickListener(v -> {
if (!fullScreenMode)
openFullscreenDialog();
else
closeFullscreenDialog();
});
}
private void initResolution() {
PlayerControlView controlView = playerView.findViewById(R.id.exo_controller);
resolution = controlView.findViewById(R.id.resolution);
resolution.setText(String.format("%sp", peertube.getResolution().get(0)));
resolution.setOnClickListener(v -> displayResolution());
}
private void changeColor() {
if (peertube.getMyRating() != null && peertube.getMyRating().equals("like")) {
changeDrawableColor(PeertubeActivity.this, R.drawable.ic_thumb_up_peertube, R.color.positive_thumbs);
Drawable thumbUp = ContextCompat.getDrawable(PeertubeActivity.this, R.drawable.ic_thumb_up_peertube);
peertube_like_count.setCompoundDrawablesWithIntrinsicBounds(null, thumbUp, null, null);
} else if (peertube.getMyRating() != null && peertube.getMyRating().equals("dislike")) {
changeDrawableColor(PeertubeActivity.this, R.drawable.ic_thumb_down_peertube, R.color.negative_thumbs);
Drawable thumbDown = ContextCompat.getDrawable(PeertubeActivity.this, R.drawable.ic_thumb_down_peertube);
peertube_dislike_count.setCompoundDrawablesWithIntrinsicBounds(null, thumbDown, null, null);
}
}
@Override
public void onActionDone(ManagePlaylistsAsyncTask.action actionType, APIResponse apiResponse, int statusCode) {
if (actionType == GET_PLAYLIST_FOR_VIDEO && apiResponse != null) {
playlistForVideo = apiResponse.getPlaylistForVideos();
} else if (actionType == GET_PLAYLIST && apiResponse != null) {
playlists = apiResponse.getPlaylists();
}
}
private static class commentTask extends AsyncTask<Void, Void, app.fedilab.android.client.Entities.Status> {
private WeakReference<Context> contextReference;
private Peertube peertube;
commentTask(WeakReference<Context> contextReference, Peertube peertube) {
this.peertube = peertube;
this.contextReference = contextReference;
}
@Override
protected app.fedilab.android.client.Entities.Status doInBackground(Void... voids) {
List<app.fedilab.android.client.Entities.Status> remoteStatuses = null;
if (peertube != null) {
APIResponse search = new API(contextReference.get()).search("https://" + peertube.getAccount().getHost() + "/videos/watch/" + peertube.getUuid());
if (search != null && search.getResults() != null) {
remoteStatuses = search.getResults().getStatuses();
}
}
if (remoteStatuses != null && remoteStatuses.size() > 0) {
return remoteStatuses.get(0);
} else {
return null;
}
}
@Override
protected void onPostExecute(app.fedilab.android.client.Entities.Status remoteStatuses) {
Intent intent = new Intent(contextReference.get(), TootActivity.class);
Bundle b = new Bundle();
if (remoteStatuses == null) {
Toasty.error(contextReference.get(), contextReference.get().getString(R.string.toast_error), Toast.LENGTH_SHORT).show();
return;
}
if (remoteStatuses.getReblog() != null) {
b.putParcelable("tootReply", remoteStatuses.getReblog());
} else {
b.putParcelable("tootReply", remoteStatuses);
}
intent.putExtras(b);
contextReference.get().startActivity(intent);
}
}
}

View File

@ -0,0 +1,588 @@
package app.fedilab.fedilabtube;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.drawable.ColorDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import app.fedilab.android.asynctasks.PostActionAsyncTask;
import app.fedilab.android.asynctasks.PostPeertubeAsyncTask;
import app.fedilab.android.asynctasks.RetrievePeertubeChannelsAsyncTask;
import app.fedilab.android.asynctasks.RetrievePeertubeSingleAsyncTask;
import app.fedilab.android.client.API;
import app.fedilab.android.client.APIResponse;
import app.fedilab.android.client.Entities.Account;
import app.fedilab.android.client.Entities.Peertube;
import app.fedilab.android.helper.Helper;
import app.fedilab.android.interfaces.OnPostActionInterface;
import app.fedilab.android.interfaces.OnRetrievePeertubeInterface;
import es.dmoral.toasty.Toasty;
import mabbas007.tagsedittext.TagsEditText;
import static android.os.AsyncTask.THREAD_POOL_EXECUTOR;
import static app.fedilab.android.asynctasks.RetrievePeertubeInformationAsyncTask.peertubeInformation;
public class PeertubeEditUploadActivity extends BaseActivity implements OnRetrievePeertubeInterface, OnPostActionInterface {
HashMap<Integer, String> categoryToSend;
HashMap<Integer, String> licenseToSend;
HashMap<Integer, String> privacyToSend;
HashMap<String, String> languageToSend;
HashMap<String, String> channelToSend;
private Button set_upload_submit;
private Spinner set_upload_privacy, set_upload_categories, set_upload_licenses, set_upload_languages, set_upload_channel;
private EditText p_video_title, p_video_description;
private TagsEditText p_video_tags;
private CheckBox set_upload_nsfw, set_upload_enable_comments;
private LinkedHashMap<String, String> channels;
private String videoId;
private Account channel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
switch (theme) {
case Helper.THEME_LIGHT:
setTheme(R.style.AppTheme_Fedilab);
break;
case Helper.THEME_BLACK:
setTheme(R.style.AppThemeBlack);
break;
default:
setTheme(R.style.AppThemeDark);
}
Bundle b = getIntent().getExtras();
if (b != null) {
videoId = b.getString("video_id", null);
}
if (videoId == null) {
videoId = sharedpreferences.getString(Helper.VIDEO_ID, null);
}
if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
assert inflater != null;
View view = inflater.inflate(R.layout.simple_bar, new LinearLayout(PeertubeEditUploadActivity.this), false);
view.setBackground(new ColorDrawable(ContextCompat.getColor(PeertubeEditUploadActivity.this, R.color.cyanea_primary)));
actionBar.setCustomView(view, new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
ImageView toolbar_close = actionBar.getCustomView().findViewById(R.id.toolbar_close);
TextView toolbar_title = actionBar.getCustomView().findViewById(R.id.toolbar_title);
toolbar_close.setOnClickListener(v -> finish());
toolbar_title.setText(R.string.update_video);
}
setContentView(R.layout.activity_peertube_edit);
set_upload_submit = findViewById(R.id.set_upload_submit);
Button set_upload_delete = findViewById(R.id.set_upload_delete);
set_upload_privacy = findViewById(R.id.set_upload_privacy);
set_upload_channel = findViewById(R.id.set_upload_channel);
set_upload_categories = findViewById(R.id.set_upload_categories);
set_upload_licenses = findViewById(R.id.set_upload_licenses);
set_upload_languages = findViewById(R.id.set_upload_languages);
p_video_title = findViewById(R.id.p_video_title);
p_video_description = findViewById(R.id.p_video_description);
p_video_tags = findViewById(R.id.p_video_tags);
set_upload_nsfw = findViewById(R.id.set_upload_nsfw);
set_upload_enable_comments = findViewById(R.id.set_upload_enable_comments);
set_upload_delete.setOnClickListener(v -> {
AlertDialog.Builder builderInner;
SharedPreferences sharedpreferences1 = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE);
int theme1 = sharedpreferences1.getInt(Helper.SET_THEME, Helper.THEME_DARK);
int style;
if (theme1 == Helper.THEME_DARK) {
style = R.style.DialogDark;
} else if (theme1 == Helper.THEME_BLACK) {
style = R.style.DialogBlack;
} else {
style = R.style.Dialog;
}
builderInner = new AlertDialog.Builder(PeertubeEditUploadActivity.this, style);
builderInner.setMessage(getString(R.string.delete_video_confirmation));
builderInner.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
builderInner.setPositiveButton(R.string.yes, (dialog, which) -> {
new PostActionAsyncTask(PeertubeEditUploadActivity.this, API.StatusAction.PEERTUBEDELETEVIDEO, videoId, PeertubeEditUploadActivity.this).executeOnExecutor(THREAD_POOL_EXECUTOR);
dialog.dismiss();
});
builderInner.show();
});
//Get params from the API
LinkedHashMap<Integer, String> categories = new LinkedHashMap<>(peertubeInformation.getCategories());
LinkedHashMap<Integer, String> licences = new LinkedHashMap<>(peertubeInformation.getLicences());
LinkedHashMap<Integer, String> privacies = new LinkedHashMap<>(peertubeInformation.getPrivacies());
LinkedHashMap<String, String> languages = new LinkedHashMap<>(peertubeInformation.getLanguages());
LinkedHashMap<String, String> translations = null;
if (peertubeInformation.getTranslations() != null)
translations = new LinkedHashMap<>(peertubeInformation.getTranslations());
//Populate catgories
String[] categoriesA = new String[categories.size()];
Iterator<Map.Entry<Integer, String>> it = categories.entrySet().iterator();
int i = 0;
while (it.hasNext()) {
Map.Entry<Integer, String> pair = it.next();
if (translations == null || translations.size() == 0 || !translations.containsKey(pair.getValue()))
categoriesA[i] = pair.getValue();
else
categoriesA[i] = translations.get(pair.getValue());
it.remove();
i++;
}
ArrayAdapter<String> adapterCatgories = new ArrayAdapter<>(PeertubeEditUploadActivity.this,
android.R.layout.simple_spinner_dropdown_item, categoriesA);
set_upload_categories.setAdapter(adapterCatgories);
//Populate licenses
String[] licensesA = new String[licences.size()];
it = licences.entrySet().iterator();
i = 0;
while (it.hasNext()) {
Map.Entry<Integer, String> pair = it.next();
if (translations == null || translations.size() == 0 || !translations.containsKey(pair.getValue()))
licensesA[i] = pair.getValue();
else
licensesA[i] = translations.get(pair.getValue());
it.remove();
i++;
}
ArrayAdapter<String> adapterLicenses = new ArrayAdapter<>(PeertubeEditUploadActivity.this,
android.R.layout.simple_spinner_dropdown_item, licensesA);
set_upload_licenses.setAdapter(adapterLicenses);
//Populate languages
String[] languagesA = new String[languages.size()];
Iterator<Map.Entry<String, String>> itl = languages.entrySet().iterator();
i = 0;
while (it.hasNext()) {
Map.Entry<String, String> pair = itl.next();
if (translations == null || translations.size() == 0 || !translations.containsKey(pair.getValue()))
languagesA[i] = pair.getValue();
else
languagesA[i] = translations.get(pair.getValue());
it.remove();
i++;
}
ArrayAdapter<String> adapterLanguages = new ArrayAdapter<>(PeertubeEditUploadActivity.this,
android.R.layout.simple_spinner_dropdown_item, languagesA);
set_upload_languages.setAdapter(adapterLanguages);
//Populate languages
String[] privaciesA = new String[privacies.size()];
it = privacies.entrySet().iterator();
i = 0;
while (it.hasNext()) {
Map.Entry<Integer, String> pair = it.next();
if (translations == null || translations.size() == 0 || !translations.containsKey(pair.getValue()))
privaciesA[i] = pair.getValue();
else
privaciesA[i] = translations.get(pair.getValue());
it.remove();
i++;
}
ArrayAdapter<String> adapterPrivacies = new ArrayAdapter<>(PeertubeEditUploadActivity.this,
android.R.layout.simple_spinner_dropdown_item, privaciesA);
set_upload_privacy.setAdapter(adapterPrivacies);
String peertubeInstance = Helper.getLiveInstance(PeertubeEditUploadActivity.this);
new RetrievePeertubeSingleAsyncTask(PeertubeEditUploadActivity.this, peertubeInstance, videoId, PeertubeEditUploadActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
channels = new LinkedHashMap<>();
}
@Override
public void onRetrievePeertube(APIResponse apiResponse) {
if (apiResponse.getError() != null || apiResponse.getPeertubes() == null || apiResponse.getPeertubes().size() == 0) {
if (apiResponse.getError() != null && apiResponse.getError().getError() != null)
Toasty.error(PeertubeEditUploadActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
else
Toasty.error(PeertubeEditUploadActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
set_upload_submit.setEnabled(true);
return;
}
//Peertube video
Peertube peertube = apiResponse.getPeertubes().get(0);
if (peertube.isUpdate()) {
Toasty.success(PeertubeEditUploadActivity.this, getString(R.string.toast_peertube_video_updated), Toast.LENGTH_LONG).show();
peertube.setUpdate(false);
set_upload_submit.setEnabled(true);
} else {
new RetrievePeertubeChannelsAsyncTask(PeertubeEditUploadActivity.this, PeertubeEditUploadActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
languageToSend = peertube.getLanguage();
licenseToSend = peertube.getLicense();
privacyToSend = peertube.getPrivacy();
categoryToSend = peertube.getCategory();
if (languageToSend == null) {
LinkedHashMap<String, String> languages = new LinkedHashMap<>(peertubeInformation.getLanguages());
Map.Entry<String, String> entryString = languages.entrySet().iterator().next();
languageToSend = new HashMap<>();
languageToSend.put(entryString.getKey(), entryString.getValue());
}
if (licenseToSend == null) {
LinkedHashMap<Integer, String> licences = new LinkedHashMap<>(peertubeInformation.getLicences());
Map.Entry<Integer, String> entryInt = licences.entrySet().iterator().next();
licenseToSend = new HashMap<>();
licenseToSend.put(entryInt.getKey(), entryInt.getValue());
}
if (categoryToSend == null) {
LinkedHashMap<Integer, String> categories = new LinkedHashMap<>(peertubeInformation.getCategories());
Map.Entry<Integer, String> entryInt = categories.entrySet().iterator().next();
categoryToSend = new HashMap<>();
categoryToSend.put(entryInt.getKey(), entryInt.getValue());
}
if (privacyToSend == null) {
LinkedHashMap<Integer, String> privacies = new LinkedHashMap<>(peertubeInformation.getPrivacies());
Map.Entry<Integer, String> entryInt = privacies.entrySet().iterator().next();
privacyToSend = new HashMap<>();
privacyToSend.put(entryInt.getKey(), entryInt.getValue());
}
String language = null;
if (languageToSend != null) {
Map.Entry<String, String> entryString = languageToSend.entrySet().iterator().next();
language = entryString.getValue();
}
String license = null;
if (licenseToSend != null) {
Map.Entry<Integer, String> entryInt = licenseToSend.entrySet().iterator().next();
license = entryInt.getValue();
}
String privacy = null;
if (privacyToSend != null) {
Map.Entry<Integer, String> entryInt = privacyToSend.entrySet().iterator().next();
privacy = entryInt.getValue();
}
String category = null;
if (categoryToSend != null) {
Map.Entry<Integer, String> entryInt = categoryToSend.entrySet().iterator().next();
category = entryInt.getValue();
}
channel = peertube.getChannel();
String title = peertube.getName();
boolean commentEnabled = peertube.isCommentsEnabled();
boolean isNSFW = peertube.isSensitive();
set_upload_enable_comments.setChecked(commentEnabled);
set_upload_nsfw.setChecked(isNSFW);
p_video_title.setText(title);
p_video_description.setText(peertube.getDescription());
LinkedHashMap<Integer, String> categories = new LinkedHashMap<>(peertubeInformation.getCategories());
LinkedHashMap<Integer, String> licences = new LinkedHashMap<>(peertubeInformation.getLicences());
LinkedHashMap<Integer, String> privacies = new LinkedHashMap<>(peertubeInformation.getPrivacies());
LinkedHashMap<String, String> languages = new LinkedHashMap<>(peertubeInformation.getLanguages());
int languagePosition = 0;
if (languages.containsValue(language)) {
Iterator<Map.Entry<String, String>> it = languages.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> pair = it.next();
if (pair.getValue().equals(language))
break;
it.remove();
languagePosition++;
}
}
int privacyPosition = 0;
if (privacy != null && privacies.containsValue(privacy)) {
Iterator<Map.Entry<Integer, String>> it = privacies.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Integer, String> pair = it.next();
if (pair.getValue().equals(privacy))
break;
it.remove();
privacyPosition++;
}
}
int licensePosition = 0;
if (license != null && licences.containsValue(license)) {
Iterator<Map.Entry<Integer, String>> it = licences.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Integer, String> pair = it.next();
if (pair.getValue().equals(license))
break;
it.remove();
licensePosition++;
}
}
int categoryPosition = 0;
if (category != null && categories.containsValue(category)) {
Iterator<Map.Entry<Integer, String>> it = categories.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Integer, String> pair = it.next();
if (pair.getValue().equals(category))
break;
it.remove();
categoryPosition++;
}
}
//Manage privacies
set_upload_privacy.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<Integer, String> privaciesCheck = new LinkedHashMap<>(peertubeInformation.getPrivacies());
Iterator<Map.Entry<Integer, String>> it = privaciesCheck.entrySet().iterator();
int i = 0;
while (it.hasNext()) {
Map.Entry<Integer, String> pair = it.next();
if (i == position) {
privacyToSend = new HashMap<>();
privacyToSend.put(pair.getKey(), pair.getValue());
break;
}
it.remove();
i++;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
set_upload_licenses.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<Integer, String> licensesCheck = new LinkedHashMap<>(peertubeInformation.getLicences());
Iterator<Map.Entry<Integer, String>> it = licensesCheck.entrySet().iterator();
int i = 0;
while (it.hasNext()) {
Map.Entry<Integer, String> pair = it.next();
if (i == position) {
licenseToSend = new HashMap<>();
licenseToSend.put(pair.getKey(), pair.getValue());
break;
}
it.remove();
i++;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
//Manage categories
set_upload_categories.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<Integer, String> categoriesCheck = new LinkedHashMap<>(peertubeInformation.getCategories());
Iterator<Map.Entry<Integer, String>> it = categoriesCheck.entrySet().iterator();
int i = 0;
while (it.hasNext()) {
Map.Entry<Integer, String> pair = it.next();
if (i == position) {
categoryToSend = new HashMap<>();
categoryToSend.put(pair.getKey(), pair.getValue());
break;
}
it.remove();
i++;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
//Manage languages
set_upload_languages.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<String, String> languagesCheck = new LinkedHashMap<>(peertubeInformation.getLanguages());
Iterator<Map.Entry<String, String>> it = languagesCheck.entrySet().iterator();
int i = 0;
while (it.hasNext()) {
Map.Entry<String, String> pair = it.next();
if (i == position) {
languageToSend = new HashMap<>();
languageToSend.put(pair.getKey(), pair.getValue());
break;
}
it.remove();
i++;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
//Manage languages
set_upload_channel.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<String, String> channelsCheck = new LinkedHashMap<>(channels);
Iterator<Map.Entry<String, String>> it = channelsCheck.entrySet().iterator();
int i = 0;
while (it.hasNext()) {
Map.Entry<String, String> pair = it.next();
if (i == position) {
channelToSend = new HashMap<>();
channelToSend.put(pair.getKey(), pair.getValue());
break;
}
it.remove();
i++;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
set_upload_submit.setOnClickListener(v -> {
String title1 = p_video_title.getText().toString().trim();
String description = p_video_description.getText().toString().trim();
boolean isNSFW1 = set_upload_nsfw.isChecked();
boolean commentEnabled1 = set_upload_enable_comments.isChecked();
peertube.setName(title1);
peertube.setDescription(description);
peertube.setSensitive(isNSFW1);
peertube.setCommentsEnabled(commentEnabled1);
peertube.setCategory(categoryToSend);
peertube.setLicense(licenseToSend);
peertube.setLanguage(languageToSend);
peertube.setChannelForUpdate(channelToSend);
peertube.setPrivacy(privacyToSend);
List<String> tags = p_video_tags.getTags();
peertube.setTags(tags);
set_upload_submit.setEnabled(false);
new PostPeertubeAsyncTask(PeertubeEditUploadActivity.this, peertube, PeertubeEditUploadActivity.this).executeOnExecutor(THREAD_POOL_EXECUTOR);
});
set_upload_privacy.setSelection(privacyPosition);
set_upload_languages.setSelection(languagePosition);
set_upload_licenses.setSelection(licensePosition);
set_upload_categories.setSelection(categoryPosition);
List<String> tags = peertube.getTags();
if (tags != null && tags.size() > 0) {
String[] tagsA = tags.toArray(new String[0]);
p_video_tags.setTags(tagsA);
}
}
@Override
public void onRetrievePeertubeComments(APIResponse apiResponse) {
}
@Override
public void onRetrievePeertubeChannels(APIResponse apiResponse) {
if (apiResponse.getError() != null || apiResponse.getAccounts() == null || apiResponse.getAccounts().size() == 0) {
if (apiResponse.getError().getError() != null)
Toasty.error(PeertubeEditUploadActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
else
Toasty.error(PeertubeEditUploadActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
return;
}
//Populate channels
List<Account> accounts = apiResponse.getAccounts();
String[] channelName = new String[accounts.size()];
int i = 0;
for (Account account : accounts) {
channels.put(account.getUsername(), account.getId());
channelName[i] = account.getUsername();
i++;
}
ArrayAdapter<String> adapterChannel = new ArrayAdapter<>(PeertubeEditUploadActivity.this,
android.R.layout.simple_spinner_dropdown_item, channelName);
set_upload_channel.setAdapter(adapterChannel);
int channelPosition = 0;
if (channels.containsKey(channel.getUsername())) {
LinkedHashMap<String, String> channelsIterator = new LinkedHashMap<>(channels);
Iterator<Map.Entry<String, String>> it = channelsIterator.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> pair = it.next();
if (pair.getKey().equals(channel.getUsername())) {
channelToSend = new HashMap<>();
channelToSend.put(pair.getKey(), pair.getValue());
break;
}
it.remove();
channelPosition++;
}
}
set_upload_channel.setSelection(channelPosition);
set_upload_submit.setEnabled(true);
}
@Override
public void onPostAction(int statusCode, API.StatusAction statusAction, String userId, Error error) {
Intent intent = new Intent(PeertubeEditUploadActivity.this, MainActivity.class);
intent.putExtra(Helper.INTENT_ACTION, Helper.RELOAD_MYVIDEOS);
startActivity(intent);
finish();
}
}

View File

@ -0,0 +1,384 @@
package app.fedilab.fedilabtube;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.OpenableColumns;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import net.gotev.uploadservice.MultipartUploadRequest;
import net.gotev.uploadservice.ServerResponse;
import net.gotev.uploadservice.UploadInfo;
import net.gotev.uploadservice.UploadNotificationAction;
import net.gotev.uploadservice.UploadNotificationConfig;
import net.gotev.uploadservice.UploadServiceSingleBroadcastReceiver;
import net.gotev.uploadservice.UploadStatusDelegate;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.entities.Account;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.interfaces.OnRetrievePeertubeInterface;
public class PeertubeUploadActivity extends AppCompatActivity implements OnRetrievePeertubeInterface, UploadStatusDelegate {
private final int PICK_IVDEO = 52378;
private final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 724;
private Button set_upload_file, set_upload_submit;
private Spinner set_upload_privacy, set_upload_channel;
private TextView set_upload_file_name;
private EditText video_title;
private HashMap<String, String> channels;
private Uri uri;
private String filename;
private HashMap<Integer, String> privacyToSend;
private HashMap<String, String> channelToSend;
private UploadServiceSingleBroadcastReceiver uploadReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
if (getSupportActionBar() != null)
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
assert inflater != null;
View view = inflater.inflate(R.layout.simple_bar, new LinearLayout(PeertubeUploadActivity.this), false);
view.setBackground(new ColorDrawable(ContextCompat.getColor(PeertubeUploadActivity.this, R.color.cyanea_primary)));
actionBar.setCustomView(view, new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
ImageView toolbar_close = actionBar.getCustomView().findViewById(R.id.toolbar_close);
TextView toolbar_title = actionBar.getCustomView().findViewById(R.id.toolbar_title);
toolbar_close.setOnClickListener(v -> finish());
toolbar_title.setText(R.string.upload_video);
}
setContentView(R.layout.activity_peertube_upload);
set_upload_file = findViewById(R.id.set_upload_file);
set_upload_file_name = findViewById(R.id.set_upload_file_name);
set_upload_channel = findViewById(R.id.set_upload_channel);
set_upload_privacy = findViewById(R.id.set_upload_privacy);
set_upload_submit = findViewById(R.id.set_upload_submit);
video_title = findViewById(R.id.video_title);
new RetrievePeertubeChannelsAsyncTask(PeertubeUploadActivity.this, PeertubeUploadActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
channels = new HashMap<>();
uploadReceiver = new UploadServiceSingleBroadcastReceiver(this);
uploadReceiver.register(this);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IVDEO && resultCode == Activity.RESULT_OK) {
if (data == null || data.getData() == null) {
Toasty.error(PeertubeUploadActivity.this, getString(R.string.toot_select_image_error), Toast.LENGTH_LONG).show();
return;
}
set_upload_submit.setEnabled(true);
uri = data.getData();
String uriString = uri.toString();
File myFile = new File(uriString);
filename = null;
if (uriString.startsWith("content://")) {
Cursor cursor = null;
try {
cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
filename = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
} finally {
assert cursor != null;
cursor.close();
}
} else if (uriString.startsWith("file://")) {
filename = myFile.getName();
}
if (filename == null) {
filename = new Date().toString();
}
set_upload_file_name.setVisibility(View.VISIBLE);
set_upload_file_name.setText(filename);
}
}
@Override
public void onDestroy() {
super.onDestroy();
uploadReceiver.unregister(this);
}
@Override
public void onRetrievePeertube(APIResponse apiResponse) {
}
@Override
public void onRetrievePeertubeComments(APIResponse apiResponse) {
}
@Override
public void onRetrievePeertubeChannels(APIResponse apiResponse) {
if (apiResponse.getError() != null || apiResponse.getAccounts() == null || apiResponse.getAccounts().size() == 0) {
if (apiResponse.getError() != null && apiResponse.getError().getError() != null)
Toasty.error(PeertubeUploadActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show();
else
Toasty.error(PeertubeUploadActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
return;
}
//Populate channels
List<Account> accounts = apiResponse.getAccounts();
String[] channelName = new String[accounts.size()];
String[] channelId = new String[accounts.size()];
int i = 0;
for (Account account : accounts) {
channels.put(account.getUsername(), account.getId());
channelName[i] = account.getUsername();
channelId[i] = account.getId();
i++;
}
channelToSend = new HashMap<>();
channelToSend.put(channelName[0], channelId[0]);
ArrayAdapter<String> adapterChannel = new ArrayAdapter<>(PeertubeUploadActivity.this,
android.R.layout.simple_spinner_dropdown_item, channelName);
set_upload_channel.setAdapter(adapterChannel);
if (peertubeInformation == null) {
return;
}
LinkedHashMap<String, String> translations = null;
if (peertubeInformation.getTranslations() != null)
translations = new LinkedHashMap<>(peertubeInformation.getTranslations());
LinkedHashMap<Integer, String> privaciesInit = new LinkedHashMap<>(peertubeInformation.getPrivacies());
Map.Entry<Integer, String> entryInt = privaciesInit.entrySet().iterator().next();
privacyToSend = new HashMap<>();
privacyToSend.put(entryInt.getKey(), entryInt.getValue());
LinkedHashMap<Integer, String> privacies = new LinkedHashMap<>(peertubeInformation.getPrivacies());
//Populate privacies
String[] privaciesA = new String[privacies.size()];
Iterator<Map.Entry<Integer, String>> it = privacies.entrySet().iterator();
i = 0;
while (it.hasNext()) {
Map.Entry<Integer, String> pair = it.next();
if (translations == null || translations.size() == 0 || !translations.containsKey(pair.getValue()))
privaciesA[i] = pair.getValue();
else
privaciesA[i] = translations.get(pair.getValue());
it.remove();
i++;
}
ArrayAdapter<String> adapterPrivacies = new ArrayAdapter<>(PeertubeUploadActivity.this,
android.R.layout.simple_spinner_dropdown_item, privaciesA);
set_upload_privacy.setAdapter(adapterPrivacies);
//Manage privacies
set_upload_privacy.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<Integer, String> privaciesCheck = new LinkedHashMap<>(peertubeInformation.getPrivacies());
Iterator<Map.Entry<Integer, String>> it = privaciesCheck.entrySet().iterator();
int i = 0;
while (it.hasNext()) {
Map.Entry<Integer, String> pair = it.next();
if (i == position) {
privacyToSend = new HashMap<>();
privacyToSend.put(pair.getKey(), pair.getValue());
break;
}
it.remove();
i++;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
set_upload_file.setEnabled(true);
set_upload_file.setOnClickListener(v -> {
if (ContextCompat.checkSelfPermission(PeertubeUploadActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(PeertubeUploadActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
return;
}
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
intent.setType("*/*");
String[] mimetypes = {"video/*"};
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
startActivityForResult(intent, PICK_IVDEO);
} else {
intent.setType("video/*");
Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
Intent chooserIntent = Intent.createChooser(intent, getString(R.string.toot_select_image));
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[]{pickIntent});
startActivityForResult(chooserIntent, PICK_IVDEO);
}
});
//Manage languages
set_upload_channel.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
LinkedHashMap<String, String> channelsCheck = new LinkedHashMap<>(channels);
Iterator<Map.Entry<String, String>> it = channelsCheck.entrySet().iterator();
int i = 0;
while (it.hasNext()) {
Map.Entry<String, String> pair = it.next();
if (i == position) {
channelToSend = new HashMap<>();
channelToSend.put(pair.getKey(), pair.getValue());
break;
}
it.remove();
i++;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
set_upload_submit.setOnClickListener(v -> {
if (uri != null) {
Map.Entry<String, String> channelM = channelToSend.entrySet().iterator().next();
String idChannel = channelM.getValue();
Map.Entry<Integer, String> privacyM = privacyToSend.entrySet().iterator().next();
Integer idPrivacy = privacyM.getKey();
try {
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String token = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
UploadNotificationConfig uploadConfig = new UploadNotificationConfig();
Intent in = new Intent(PeertubeUploadActivity.this, PeertubeEditUploadActivity.class);
PendingIntent clickIntent = PendingIntent.getActivity(PeertubeUploadActivity.this, 1, in, PendingIntent.FLAG_UPDATE_CURRENT);
uploadConfig
.setClearOnActionForAllStatuses(true);
uploadConfig.getProgress().message = getString(R.string.uploading);
uploadConfig.getCompleted().message = getString(R.string.upload_video_success);
uploadConfig.getError().message = getString(R.string.toast_error);
uploadConfig.getCancelled().message = getString(R.string.toast_cancelled);
uploadConfig.getCompleted().actions.add(new UploadNotificationAction(R.drawable.ic_check, getString(R.string.video_uploaded_action), clickIntent));
if (video_title != null && video_title.getText() != null && video_title.getText().toString().trim().length() > 0) {
filename = video_title.getText().toString().trim();
}
String uploadId = UUID.randomUUID().toString();
uploadReceiver.setUploadID(uploadId);
new MultipartUploadRequest(PeertubeUploadActivity.this, uploadId, "https://" + Helper.getLiveInstance(PeertubeUploadActivity.this) + "/api/v1/videos/upload")
.addFileToUpload(uri.toString().replace("file://", ""), "videofile")
.addHeader("Authorization", "Bearer " + token)
.setNotificationConfig(uploadConfig)
.addParameter("name", filename)
.addParameter("channelId", idChannel)
.addParameter("privacy", String.valueOf(idPrivacy))
.addParameter("nsfw", "false")
.addParameter("commentsEnabled", "true")
.addParameter("waitTranscoding", "true")
.setMaxRetries(2)
.startUpload();
finish();
} catch (Exception exc) {
exc.printStackTrace();
}
}
});
}
@Override
public void onProgress(Context context, UploadInfo uploadInfo) {
// your code here
}
@Override
public void onError(Context context, UploadInfo uploadInfo, ServerResponse serverResponse,
Exception exception) {
// your code here
exception.printStackTrace();
}
@SuppressLint("ApplySharedPref")
@Override
public void onCompleted(Context context, UploadInfo uploadInfo, ServerResponse serverResponse) {
try {
JSONObject response = new JSONObject(serverResponse.getBodyAsString());
String videoID = response.getJSONObject("video").get("id").toString();
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(Helper.VIDEO_ID, videoID);
editor.commit();
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onCancelled(Context context, UploadInfo uploadInfo) {
// your code here
}
}

View File

@ -0,0 +1,80 @@
package app.fedilab.fedilabtube.asynctasks;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import java.lang.ref.WeakReference;
import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Account;
import app.fedilab.fedilabtube.client.entities.Playlist;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.interfaces.OnPlaylistActionInterface;
import app.fedilab.fedilabtube.sqlite.AccountDAO;
import app.fedilab.fedilabtube.sqlite.Sqlite;
public class ManagePlaylistsAsyncTask extends AsyncTask<Void, Void, Void> {
private OnPlaylistActionInterface listener;
private APIResponse apiResponse;
private int statusCode;
private action apiAction;
private WeakReference<Context> contextReference;
private String max_id;
private Playlist playlist;
private String videoId;
public ManagePlaylistsAsyncTask(Context context, action apiAction, Playlist playlist, String videoId, String max_id, OnPlaylistActionInterface onPlaylistActionInterface) {
contextReference = new WeakReference<>(context);
this.listener = onPlaylistActionInterface;
this.apiAction = apiAction;
this.max_id = max_id;
this.playlist = playlist;
this.videoId = videoId;
}
@Override
protected Void doInBackground(Void... params) {
SharedPreferences sharedpreferences = contextReference.get().getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
String instance = sharedpreferences.getString(Helper.PREF_INSTANCE, Helper.getLiveInstance(contextReference.get()));
SQLiteDatabase db = Sqlite.getInstance(contextReference.get().getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
Account account = new AccountDAO(contextReference.get(), db).getUniqAccount(userId, instance);
if (apiAction == action.GET_PLAYLIST) {
apiResponse = new PeertubeAPI(contextReference.get()).getPlayists(account.getUsername());
} else if (apiAction == action.GET_LIST_VIDEOS) {
apiResponse = new PeertubeAPI(contextReference.get()).getPlaylistVideos(playlist.getId(), max_id, null);
} else if (apiAction == action.DELETE_PLAYLIST) {
statusCode = new PeertubeAPI(contextReference.get()).deletePlaylist(playlist.getId());
} else if (apiAction == action.ADD_VIDEOS) {
statusCode = new PeertubeAPI(contextReference.get()).addVideoPlaylist(playlist.getId(), videoId);
} else if (apiAction == action.DELETE_VIDEOS) {
statusCode = new PeertubeAPI(contextReference.get()).deleteVideoPlaylist(playlist.getId(), videoId);
} else if (apiAction == action.GET_PLAYLIST_FOR_VIDEO) {
apiResponse = new PeertubeAPI(contextReference.get()).getPlaylistForVideo(videoId);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
listener.onActionDone(this.apiAction, apiResponse, statusCode);
}
public enum action {
GET_PLAYLIST,
GET_LIST_VIDEOS,
CREATE_PLAYLIST,
DELETE_PLAYLIST,
UPDATE_PLAYLIST,
ADD_VIDEOS,
DELETE_VIDEOS,
GET_PLAYLIST_FOR_VIDEO,
}
}

View File

@ -0,0 +1,88 @@
package app.fedilab.fedilabtube.asynctasks;
import android.content.Context;
import android.os.AsyncTask;
import java.lang.ref.WeakReference;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Account;
import app.fedilab.fedilabtube.client.entities.Error;
import app.fedilab.fedilabtube.interfaces.OnPostActionInterface;
public class PostActionAsyncTask extends AsyncTask<Void, Void, Void> {
private OnPostActionInterface listener;
private int statusCode;
private PeertubeAPI.StatusAction apiAction;
private String targetedId, targetedComment;
private String comment;
private WeakReference<Context> contextReference;
private Error error;
private Account account;
public PostActionAsyncTask(Context context, Account account, PeertubeAPI.StatusAction apiAction, String targetedId, OnPostActionInterface onPostActionInterface) {
this.contextReference = new WeakReference<>(context);
this.listener = onPostActionInterface;
this.apiAction = apiAction;
this.targetedId = targetedId;
this.account = account;
}
public PostActionAsyncTask(Context context, String targetedId, String comment, String targetedComment, OnPostActionInterface onPostActionInterface) {
this.contextReference = new WeakReference<>(context);
this.listener = onPostActionInterface;
this.apiAction = PeertubeAPI.StatusAction.PEERTUBEREPLY;
this.targetedId = targetedId;
this.comment = comment;
this.targetedComment = targetedComment;
}
public PostActionAsyncTask(Context context, PeertubeAPI.StatusAction apiAction, String targetedId, app.fedilab.fedilabtube.client.entities.Status status, String comment, OnPostActionInterface onPostActionInterface) {
contextReference = new WeakReference<>(context);
this.listener = onPostActionInterface;
this.apiAction = apiAction;
this.targetedId = targetedId;
this.comment = comment;
}
@Override
protected Void doInBackground(Void... params) {
//Remote action
PeertubeAPI peertubeAPI;
if (account != null)
peertubeAPI = new PeertubeAPI(contextReference.get(), account.getInstance(), account.getToken());
else
peertubeAPI = new PeertubeAPI(contextReference.get());
if (apiAction == PeertubeAPI.StatusAction.FOLLOW || apiAction == PeertubeAPI.StatusAction.UNFOLLOW)
statusCode = peertubeAPI.postAction(apiAction, targetedId);
else if (apiAction == PeertubeAPI.StatusAction.RATEVIDEO)
statusCode = peertubeAPI.postRating(targetedId, comment);
else if (apiAction == PeertubeAPI.StatusAction.PEERTUBECOMMENT)
statusCode = peertubeAPI.postComment(targetedId, comment);
else if (apiAction == PeertubeAPI.StatusAction.PEERTUBEREPLY)
statusCode = peertubeAPI.postReply(targetedId, comment, targetedComment);
else if (apiAction == PeertubeAPI.StatusAction.PEERTUBEDELETECOMMENT) {
statusCode = peertubeAPI.deleteComment(targetedId, comment);
targetedId = comment;
} else if (apiAction == PeertubeAPI.StatusAction.PEERTUBEDELETEVIDEO) {
statusCode = peertubeAPI.deleteVideo(targetedId);
}
error = peertubeAPI.getError();
return null;
}
@Override
protected void onPostExecute(Void result) {
if (listener != null) {
listener.onPostAction(statusCode, apiAction, targetedId, error);
}
}
}

View File

@ -0,0 +1,165 @@
package app.fedilab.fedilabtube.asynctasks;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Peertube;
import app.fedilab.fedilabtube.interfaces.OnRetrieveFeedsInterface;
import app.fedilab.fedilabtube.sqlite.Sqlite;
public class RetrieveFeedsAsyncTask extends AsyncTask<Void, Void, Void> {
private Type action;
private APIResponse apiResponse;
private String max_id;
private OnRetrieveFeedsInterface listener;
private String targetedID;
private String tag;
private boolean showMediaOnly = false;
private boolean showPinned = false;
private boolean showReply = false;
private WeakReference<Context> contextReference;
private String instanceName, remoteInstance, name;
private int timelineId;
private String search;
private String social;
public RetrieveFeedsAsyncTask(Context context, Type action, String max_id, String search, OnRetrieveFeedsInterface onRetrieveFeedsInterface) {
this.contextReference = new WeakReference<>(context);
this.action = action;
this.max_id = max_id;
this.listener = onRetrieveFeedsInterface;
this.search = search;
}
@Override
protected Void doInBackground(Void... params) {
PeertubeAPI peertubeAPI = new PeertubeAPI(this.contextReference.get());
SQLiteDatabase db = Sqlite.getInstance(this.contextReference.get().getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
if (action == null)
return null;
switch (action) {
case REMOTE_INSTANCE_FILTERED:
apiResponse = peertubeAPI.searchPeertube(this.remoteInstance, search);
break;
case USER:
apiResponse = peertubeAPI.getVideos(targetedID, max_id);
break;
case MYVIDEOS:
peertubeAPI = new PeertubeAPI(this.contextReference.get());
apiResponse = peertubeAPI.getMyVideos(max_id);
break;
case PEERTUBE_HISTORY:
peertubeAPI = new PeertubeAPI(this.contextReference.get());
apiResponse = peertubeAPI.getMyHistory(max_id);
break;
case CHANNEL:
peertubeAPI = new PeertubeAPI(this.contextReference.get());
apiResponse = peertubeAPI.getVideosChannel(targetedID, max_id);
break;
case CACHE_BOOKMARKS_PEERTUBE:
apiResponse = new APIResponse();
db = Sqlite.getInstance(contextReference.get().getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
List<Peertube> peertubes = new PeertubeFavoritesDAO(contextReference.get(), db).getAllPeertube();
apiResponse.setPeertubes(peertubes);
break;
case PSUBSCRIPTIONS:
peertubeAPI = new PeertubeAPI(this.contextReference.get());
apiResponse = peertubeAPI.getSubscriptionsTL(max_id);
break;
case POVERVIEW:
peertubeAPI = new PeertubeAPI(this.contextReference.get());
apiResponse = peertubeAPI.getOverviewTL(max_id);
break;
case PTRENDING:
peertubeAPI = new PeertubeAPI(this.contextReference.get());
apiResponse = peertubeAPI.getTrendingTL(max_id);
break;
case PRECENTLYADDED:
peertubeAPI = new PeertubeAPI(this.contextReference.get());
apiResponse = peertubeAPI.getRecentlyAddedTL(max_id);
break;
case PLOCAL:
peertubeAPI = new PeertubeAPI(this.contextReference.get());
apiResponse = peertubeAPI.getLocalTL(max_id);
break;
}
return null;
}
@Override
protected void onPostExecute(Void result) {
listener.onRetrieveFeeds(apiResponse);
}
public enum Type {
HOME,
LOCAL,
DIRECT,
CONVERSATION,
PUBLIC,
HASHTAG,
LIST,
USER,
FAVOURITES,
ONESTATUS,
CONTEXT,
TAG,
REMOTE_INSTANCE,
REMOTE_INSTANCE_FILTERED,
ART,
PEERTUBE,
NOTIFICATION,
SEARCH,
NEWS,
ANNOUNCEMENTS,
PSUBSCRIPTIONS,
POVERVIEW,
PTRENDING,
PRECENTLYADDED,
PLOCAL,
CHANNEL,
MYVIDEOS,
PEERTUBE_HISTORY,
PIXELFED,
PF_HOME,
PF_LOCAL,
PF_DISCOVER,
PF_NOTIFICATION,
PF_REPLIES,
GNU_HOME,
GNU_LOCAL,
GNU_WHOLE,
GNU_NOTIFICATION,
GNU_DM,
GNU_ART,
GNU_TAG,
GNU_GROUP_TIMELINE,
SCHEDULED_TOOTS,
CACHE_BOOKMARKS,
CACHE_BOOKMARKS_PEERTUBE,
CACHE_STATUS,
}
}

View File

@ -0,0 +1,49 @@
package app.fedilab.fedilabtube.asynctasks;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import java.lang.ref.WeakReference;
import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Account;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.interfaces.OnRetrievePeertubeInterface;
import app.fedilab.fedilabtube.sqlite.AccountDAO;
import app.fedilab.fedilabtube.sqlite.Sqlite;
public class RetrievePeertubeChannelsAsyncTask extends AsyncTask<Void, Void, Void> {
private APIResponse apiResponse;
private OnRetrievePeertubeInterface listener;
private WeakReference<Context> contextReference;
public RetrievePeertubeChannelsAsyncTask(Context context, OnRetrievePeertubeInterface onRetrievePeertubeInterface) {
this.contextReference = new WeakReference<>(context);
this.listener = onRetrievePeertubeInterface;
}
@Override
protected Void doInBackground(Void... params) {
PeertubeAPI peertubeAPI = new PeertubeAPI(this.contextReference.get());
SQLiteDatabase db = Sqlite.getInstance(contextReference.get().getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
SharedPreferences sharedpreferences = contextReference.get().getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
String instance = sharedpreferences.getString(Helper.PREF_INSTANCE, Helper.getLiveInstance(contextReference.get()));
Account account = new AccountDAO(contextReference.get(), db).getUniqAccount(userId, instance);
apiResponse = peertubeAPI.getPeertubeChannel(account.getUsername());
return null;
}
@Override
protected void onPostExecute(Void result) {
listener.onRetrievePeertubeChannels(apiResponse);
}
}

View File

@ -0,0 +1,39 @@
package app.fedilab.fedilabtube.asynctasks;
import android.content.Context;
import android.os.AsyncTask;
import java.lang.ref.WeakReference;
import app.fedilab.fedilabtube.client.HttpsConnection;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.entities.PeertubeInformation;
public class RetrievePeertubeInformationAsyncTask extends AsyncTask<Void, Void, Void> {
public static PeertubeInformation peertubeInformation;
private WeakReference<Context> contextReference;
public RetrievePeertubeInformationAsyncTask(Context context) {
this.contextReference = new WeakReference<>(context);
}
@Override
protected Void doInBackground(Void... params) {
PeertubeAPI peertubeAPI = new PeertubeAPI(this.contextReference.get());
try {
peertubeInformation = peertubeAPI.getPeertubeInformation();
} catch (HttpsConnection.HttpsConnectionException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
}
}

View File

@ -0,0 +1,55 @@
package app.fedilab.fedilabtube.asynctasks;
import android.content.Context;
import android.os.AsyncTask;
import java.lang.ref.WeakReference;
import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Account;
import app.fedilab.fedilabtube.client.entities.Error;
import app.fedilab.fedilabtube.interfaces.OnRetrievePeertubeNotificationsInterface;
public class RetrievePeertubeNotificationsAsyncTask extends AsyncTask<Void, Void, Void> {
private APIResponse apiResponse;
private String max_id;
private Account account;
private OnRetrievePeertubeNotificationsInterface listener;
private WeakReference<Context> contextReference;
public RetrievePeertubeNotificationsAsyncTask(Context context, Account account, String max_id, OnRetrievePeertubeNotificationsInterface onRetrievePeertubeNotificationsInterface) {
this.contextReference = new WeakReference<>(context);
this.max_id = max_id;
this.listener = onRetrievePeertubeNotificationsInterface;
this.account = account;
}
@Override
protected Void doInBackground(Void... params) {
PeertubeAPI api;
if (account == null) {
api = new PeertubeAPI(this.contextReference.get());
apiResponse = api.getNotifications(max_id);
} else {
if (this.contextReference.get() == null) {
apiResponse.setError(new Error());
return null;
}
api = new PeertubeAPI(this.contextReference.get(), account.getInstance(), account.getToken());
apiResponse = api.getNotificationsSince(max_id);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
listener.onRetrievePeertubeNotifications(apiResponse, account);
}
}

View File

@ -0,0 +1,41 @@
package app.fedilab.fedilabtube.asynctasks;
import android.content.Context;
import android.os.AsyncTask;
import java.lang.ref.WeakReference;
import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.interfaces.OnRetrieveFeedsInterface;
public class RetrievePeertubeSearchAsyncTask extends AsyncTask<Void, Void, Void> {
private String query, instance;
private APIResponse apiResponse;
private OnRetrieveFeedsInterface listener;
private WeakReference<Context> contextReference;
public RetrievePeertubeSearchAsyncTask(Context context, String instance, String query, OnRetrieveFeedsInterface onRetrieveFeedsInterface) {
this.contextReference = new WeakReference<>(context);
this.query = query;
this.listener = onRetrieveFeedsInterface;
this.instance = instance;
}
@Override
protected Void doInBackground(Void... params) {
PeertubeAPI api = new PeertubeAPI(this.contextReference.get());
apiResponse = api.searchPeertube(instance, query);
return null;
}
@Override
protected void onPostExecute(Void result) {
listener.onRetrieveFeeds(apiResponse);
}
}

View File

@ -0,0 +1,52 @@
package app.fedilab.fedilabtube.asynctasks;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import java.lang.ref.WeakReference;
import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.interfaces.OnRetrievePeertubeInterface;
public class RetrievePeertubeSingleAsyncTask extends AsyncTask<Void, Void, Void> {
private APIResponse apiResponse;
private String videoId;
private OnRetrievePeertubeInterface listener;
private WeakReference<Context> contextReference;
private String instanceName;
public RetrievePeertubeSingleAsyncTask(Context context, String instanceName, String videoId, OnRetrievePeertubeInterface onRetrievePeertubeInterface) {
this.contextReference = new WeakReference<>(context);
this.videoId = videoId;
this.listener = onRetrievePeertubeInterface;
this.instanceName = instanceName;
}
@Override
protected Void doInBackground(Void... params) {
PeertubeAPI peertubeAPI = new PeertubeAPI(this.contextReference.get());
SharedPreferences sharedpreferences = contextReference.get().getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String token = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null);
apiResponse = peertubeAPI.getSinglePeertube(this.instanceName, videoId, token);
if (apiResponse.getPeertubes() != null && apiResponse.getPeertubes().size() > 0 && apiResponse.getPeertubes().get(0) != null) {
String rate = new PeertubeAPI(this.contextReference.get()).getRating(videoId);
if (rate != null)
apiResponse.getPeertubes().get(0).setMyRating(rate);
}
return null;
}
@Override
protected void onPostExecute(Void result) {
listener.onRetrievePeertube(apiResponse);
}
}

View File

@ -0,0 +1,43 @@
package app.fedilab.fedilabtube.asynctasks;
import android.content.Context;
import android.os.AsyncTask;
import java.lang.ref.WeakReference;
import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.interfaces.OnRetrievePeertubeInterface;
public class RetrievePeertubeSingleCommentsAsyncTask extends AsyncTask<Void, Void, Void> {
private APIResponse apiResponse;
private String videoId;
private OnRetrievePeertubeInterface listener;
private WeakReference<Context> contextReference;
private String instanceName;
public RetrievePeertubeSingleCommentsAsyncTask(Context context, String instanceName, String videoId, OnRetrievePeertubeInterface onRetrievePeertubeInterface) {
this.contextReference = new WeakReference<>(context);
this.videoId = videoId;
this.listener = onRetrievePeertubeInterface;
this.instanceName = instanceName;
}
@Override
protected Void doInBackground(Void... params) {
PeertubeAPI api = new PeertubeAPI(this.contextReference.get());
apiResponse = api.getSinglePeertubeComments(this.instanceName, videoId);
return null;
}
@Override
protected void onPostExecute(Void result) {
listener.onRetrievePeertubeComments(apiResponse);
}
}

View File

@ -0,0 +1,134 @@
package app.fedilab.fedilabtube.client;
import java.util.List;
import app.fedilab.fedilabtube.client.entities.Account;
import app.fedilab.fedilabtube.client.entities.Instance;
import app.fedilab.fedilabtube.client.entities.Peertube;
import app.fedilab.fedilabtube.client.entities.PeertubeNotification;
import app.fedilab.fedilabtube.client.entities.Playlist;
import app.fedilab.fedilabtube.client.entities.Error;
import app.fedilab.fedilabtube.client.entities.Status;
public class APIResponse {
private List<Account> accounts = null;
private List<Status> statuses = null;
private String targetedId = null;
private List<Peertube> peertubes = null;
private List<PeertubeNotification> peertubeNotifications = null;
private List<Playlist> playlists = null;
private List<String> domains = null;
private Error error = null;
private String since_id, max_id;
private List<String> playlistForVideos;
private Instance instance;
public List<Account> getAccounts() {
return accounts;
}
public void setAccounts(List<Account> accounts) {
this.accounts = accounts;
}
public Error getError() {
return error;
}
public void setError(Error error) {
this.error = error;
}
public String getMax_id() {
return max_id;
}
public void setMax_id(String max_id) {
this.max_id = max_id;
}
public String getSince_id() {
return since_id;
}
public void setSince_id(String since_id) {
this.since_id = since_id;
}
public List<String> getDomains() {
return domains;
}
public void setDomains(List<String> domains) {
this.domains = domains;
}
public List<Peertube> getPeertubes() {
return peertubes;
}
public void setPeertubes(List<Peertube> peertubes) {
this.peertubes = peertubes;
}
public List<PeertubeNotification> getPeertubeNotifications() {
return peertubeNotifications;
}
public void setPeertubeNotifications(List<PeertubeNotification> peertubeNotifications) {
this.peertubeNotifications = peertubeNotifications;
}
public List<Playlist> getPlaylists() {
return playlists;
}
public void setPlaylists(List<Playlist> playlists) {
this.playlists = playlists;
}
public List<String> getPlaylistForVideos() {
return playlistForVideos;
}
public void setPlaylistForVideos(List<String> playlistForVideos) {
this.playlistForVideos = playlistForVideos;
}
public String getTargetedId() {
return targetedId;
}
public void setTargetedId(String targetedId) {
this.targetedId = targetedId;
}
public Instance getInstance() {
return instance;
}
public void setInstance(Instance instance) {
this.instance = instance;
}
public List<Status> getStatuses() {
return statuses;
}
public void setStatuses(List<Status> statuses) {
this.statuses = statuses;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,79 @@
package app.fedilab.fedilabtube.client;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class TLSSocketFactory extends SSLSocketFactory {
private SSLSocketFactory sSLSocketFactory;
private SSLContext sslContext;
public TLSSocketFactory(String instance) throws KeyManagementException, NoSuchAlgorithmException {
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, null);
sSLSocketFactory = sslContext.getSocketFactory();
}
public SSLContext getSSLContext() {
return this.sslContext;
}
@Override
public String[] getDefaultCipherSuites() {
return sSLSocketFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return sSLSocketFactory.getSupportedCipherSuites();
}
@Override
public Socket createSocket() throws IOException {
return enableTLSOnSocket(sSLSocketFactory.createSocket());
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSOnSocket(sSLSocketFactory.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException {
return enableTLSOnSocket(sSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
return enableTLSOnSocket(sSLSocketFactory.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSOnSocket(sSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSOnSocket(sSLSocketFactory.createSocket(address, port, localAddress, localPort));
}
private Socket enableTLSOnSocket(Socket socket) {
if ((socket instanceof SSLSocket)) {
((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.1", "TLSv1.2",});
}
return socket;
}
}

View File

@ -0,0 +1,532 @@
package app.fedilab.fedilabtube.client.entities;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.SpannableString;
import android.text.TextUtils;
import org.jetbrains.annotations.NotNull;
import java.util.Date;
public class Account implements Parcelable {
public static final Creator<Account> CREATOR = new Creator<Account>() {
@Override
public Account createFromParcel(Parcel source) {
return new Account(source);
}
@Override
public Account[] newArray(int size) {
return new Account[size];
}
};
private String id;
private String uuid;
private String username;
private String acct;
private String display_name;
private boolean locked;
private Date created_at;
private Date updated_at;
private int followers_count;
private int following_count;
private int statuses_count;
private String followers_count_str;
private String following_count_str;
private String statuses_count_str;
private String note;
private SpannableString noteSpan;
private String url;
private String avatar;
private String avatar_static;
private String header;
private String header_static;
private String token;
private String instance;
private boolean isFollowing;
private followAction followType = followAction.NOTHING;
private boolean isMakingAction = false;
private Account moved_to_account;
private boolean muting_notifications;
private String host;
private boolean isBot;
private String social;
private String client_id;
private String client_secret;
private String refresh_token;
private boolean isModerator = false;
private boolean isAdmin = false;
private String privacy = "public";
private boolean sensitive = false;
private String locale;
private String invite_request;
private String created_by_application_id;
private String invited_by_account_id;
public Account() {
}
protected Account(Parcel in) {
this.id = in.readString();
this.uuid = in.readString();
this.username = in.readString();
this.acct = in.readString();
this.display_name = in.readString();
this.locked = in.readByte() != 0;
long tmpCreated_at = in.readLong();
this.created_at = tmpCreated_at == -1 ? null : new Date(tmpCreated_at);
long tmpUpdated_at = in.readLong();
this.updated_at = tmpUpdated_at == -1 ? null : new Date(tmpUpdated_at);
this.followers_count = in.readInt();
this.following_count = in.readInt();
this.statuses_count = in.readInt();
this.followers_count_str = in.readString();
this.following_count_str = in.readString();
this.statuses_count_str = in.readString();
this.note = in.readString();
this.noteSpan = (SpannableString) TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
this.url = in.readString();
this.avatar = in.readString();
this.avatar_static = in.readString();
this.header = in.readString();
this.header_static = in.readString();
this.token = in.readString();
this.instance = in.readString();
this.isFollowing = in.readByte() != 0;
int tmpFollowType = in.readInt();
this.followType = tmpFollowType == -1 ? null : followAction.values()[tmpFollowType];
this.isMakingAction = in.readByte() != 0;
this.moved_to_account = in.readParcelable(Account.class.getClassLoader());
this.muting_notifications = in.readByte() != 0;
this.host = in.readString();
this.isBot = in.readByte() != 0;
this.social = in.readString();
this.client_id = in.readString();
this.client_secret = in.readString();
this.refresh_token = in.readString();
this.isModerator = in.readByte() != 0;
this.isAdmin = in.readByte() != 0;
this.privacy = in.readString();
this.sensitive = in.readByte() != 0;
this.locale = in.readString();
this.invite_request = in.readString();
this.created_by_application_id = in.readString();
this.invited_by_account_id = in.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.id);
dest.writeString(this.uuid);
dest.writeString(this.username);
dest.writeString(this.acct);
dest.writeString(this.display_name);
dest.writeByte(this.locked ? (byte) 1 : (byte) 0);
dest.writeLong(this.created_at != null ? this.created_at.getTime() : -1);
dest.writeLong(this.updated_at != null ? this.updated_at.getTime() : -1);
dest.writeInt(this.followers_count);
dest.writeInt(this.following_count);
dest.writeInt(this.statuses_count);
dest.writeString(this.followers_count_str);
dest.writeString(this.following_count_str);
dest.writeString(this.statuses_count_str);
dest.writeString(this.note);
TextUtils.writeToParcel(this.noteSpan, dest, flags);
dest.writeString(this.url);
dest.writeString(this.avatar);
dest.writeString(this.avatar_static);
dest.writeString(this.header);
dest.writeString(this.header_static);
dest.writeString(this.token);
dest.writeString(this.instance);
dest.writeByte(this.isFollowing ? (byte) 1 : (byte) 0);
dest.writeInt(this.followType == null ? -1 : this.followType.ordinal());
dest.writeByte(this.isMakingAction ? (byte) 1 : (byte) 0);
dest.writeParcelable(this.moved_to_account, flags);
dest.writeByte(this.muting_notifications ? (byte) 1 : (byte) 0);
dest.writeString(this.host);
dest.writeByte(this.isBot ? (byte) 1 : (byte) 0);
dest.writeString(this.social);
dest.writeString(this.client_id);
dest.writeString(this.client_secret);
dest.writeString(this.refresh_token);
dest.writeByte(this.isModerator ? (byte) 1 : (byte) 0);
dest.writeByte(this.isAdmin ? (byte) 1 : (byte) 0);
dest.writeString(this.privacy);
dest.writeByte(this.sensitive ? (byte) 1 : (byte) 0);
dest.writeString(this.locale);
dest.writeString(this.invite_request);
dest.writeString(this.created_by_application_id);
dest.writeString(this.invited_by_account_id);
}
public followAction getFollowType() {
return followType;
}
public void setFollowType(followAction followType) {
this.followType = followType;
}
public boolean isMakingAction() {
return isMakingAction;
}
public void setMakingAction(boolean makingAction) {
isMakingAction = makingAction;
}
public Account getMoved_to_account() {
return moved_to_account;
}
public void setMoved_to_account(Account moved_to_account) {
this.moved_to_account = moved_to_account;
}
public boolean isMuting_notifications() {
return muting_notifications;
}
public void setMuting_notifications(boolean muting_notifications) {
this.muting_notifications = muting_notifications;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public boolean isBot() {
return isBot;
}
public void setBot(boolean bot) {
isBot = bot;
}
public String getSocial() {
return social;
}
public void setSocial(String social) {
this.social = social;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getClient_id() {
return client_id;
}
public void setClient_id(String client_id) {
this.client_id = client_id;
}
public String getClient_secret() {
return client_secret;
}
public void setClient_secret(String client_secret) {
this.client_secret = client_secret;
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
public boolean isModerator() {
return isModerator;
}
public void setModerator(boolean moderator) {
isModerator = moderator;
}
public boolean isAdmin() {
return isAdmin;
}
public void setAdmin(boolean admin) {
isAdmin = admin;
}
public Date getUpdated_at() {
return updated_at;
}
public void setUpdated_at(Date updated_at) {
this.updated_at = updated_at;
}
public String getPrivacy() {
return privacy;
}
public void setPrivacy(String privacy) {
this.privacy = privacy;
}
public boolean isSensitive() {
return sensitive;
}
public void setSensitive(boolean sensitive) {
this.sensitive = sensitive;
}
public String getLocale() {
return locale;
}
public void setLocale(String locale) {
this.locale = locale;
}
public String getInvite_request() {
return invite_request;
}
public void setInvite_request(String invite_request) {
this.invite_request = invite_request;
}
public String getCreated_by_application_id() {
return created_by_application_id;
}
public void setCreated_by_application_id(String created_by_application_id) {
this.created_by_application_id = created_by_application_id;
}
public String getInvited_by_account_id() {
return invited_by_account_id;
}
public void setInvited_by_account_id(String invited_by_account_id) {
this.invited_by_account_id = invited_by_account_id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAcct() {
return acct;
}
public void setAcct(String acct) {
this.acct = acct;
}
public String getDisplay_name() {
return display_name;
}
public void setDisplay_name(String display_name) {
this.display_name = display_name;
}
public boolean isLocked() {
return locked;
}
public void setLocked(boolean locked) {
this.locked = locked;
}
public Date getCreated_at() {
return created_at;
}
public void setCreated_at(Date created_at) {
this.created_at = created_at;
}
public int getFollowers_count() {
return followers_count;
}
public void setFollowers_count(int followers_count) {
this.followers_count = followers_count;
}
public int getFollowing_count() {
return following_count;
}
public void setFollowing_count(int following_count) {
this.following_count = following_count;
}
public int getStatuses_count() {
return statuses_count;
}
public void setStatuses_count(int statuses_count) {
this.statuses_count = statuses_count;
}
public SpannableString getNoteSpan() {
return noteSpan;
}
public void setNoteSpan(SpannableString noteSpan) {
this.noteSpan = noteSpan;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public String getAvatar_static() {
return avatar_static;
}
public void setAvatar_static(String avatar_static) {
this.avatar_static = avatar_static;
}
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public String getHeader_static() {
return header_static;
}
public void setHeader_static(String header_static) {
this.header_static = header_static;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getInstance() {
return instance;
}
public void setInstance(String instance) {
this.instance = instance;
}
public boolean isFollowing() {
return isFollowing;
}
public void setFollowing(boolean following) {
isFollowing = following;
}
public String getFollowers_count_str() {
return followers_count_str;
}
public void setFollowers_count_str(String followers_count_str) {
this.followers_count_str = followers_count_str;
}
public String getFollowing_count_str() {
return following_count_str;
}
public void setFollowing_count_str(String following_count_str) {
this.following_count_str = following_count_str;
}
public String getStatuses_count_str() {
return statuses_count_str;
}
public void setStatuses_count_str(String statuses_count_str) {
this.statuses_count_str = statuses_count_str;
}
@NotNull
public String toString() {
return this.getAcct() + " - " + this.getUrl();
}
public enum followAction {
FOLLOW,
NOT_FOLLOW,
BLOCK,
MUTE,
REQUEST_SENT,
NOTHING
}
}

View File

@ -0,0 +1,41 @@
package app.fedilab.fedilabtube.client.entities;
public class AccountCreation {
private String username;
private String email;
private String password;
private String passwordConfirm;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPasswordConfirm() {
return passwordConfirm;
}
public void setPasswordConfirm(String passwordConfirm) {
this.passwordConfirm = passwordConfirm;
}
}

View File

@ -0,0 +1,26 @@
package app.fedilab.fedilabtube.client.entities;
public class Error {
private String error = null;
private int statusCode = -1;
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public int getStatusCode() {
return statusCode;
}
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
}

View File

@ -0,0 +1,128 @@
package app.fedilab.fedilabtube.client.entities;
import java.util.HashMap;
public class Instance {
private String uri;
private String title;
private String description;
private String email;
private String version;
private boolean registration;
private boolean approval_required;
private Account contactAccount;
private int userCount;
private int statusCount;
private int domainCount;
private String thumbnail;
private HashMap<String, Integer> poll_limits;
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public HashMap<String, Integer> getPoll_limits() {
return poll_limits;
}
public void setPoll_limits(HashMap<String, Integer> poll_limits) {
this.poll_limits = poll_limits;
}
public boolean isRegistration() {
return registration;
}
public void setRegistration(boolean registration) {
this.registration = registration;
}
public boolean isApproval_required() {
return approval_required;
}
public void setApproval_required(boolean approval_required) {
this.approval_required = approval_required;
}
public Account getContactAccount() {
return contactAccount;
}
public void setContactAccount(Account contactAccount) {
this.contactAccount = contactAccount;
}
public int getUserCount() {
return userCount;
}
public void setUserCount(int userCount) {
this.userCount = userCount;
}
public int getStatusCount() {
return statusCount;
}
public void setStatusCount(int statusCount) {
this.statusCount = statusCount;
}
public int getDomainCount() {
return domainCount;
}
public void setDomainCount(int domainCount) {
this.domainCount = domainCount;
}
public String getThumbnail() {
return thumbnail;
}
public void setThumbnail(String thumbnail) {
this.thumbnail = thumbnail;
}
}

View File

@ -0,0 +1,124 @@
package app.fedilab.fedilabtube.client.entities;
public class InstanceNodeInfo {
private String name;
private String title;
private String version;
private boolean openRegistrations;
private boolean connectionError;
private int numberOfUsers = 0;
private int numberOfPosts = 0;
private int numberOfInstance = 0;
private String staffAccountStr;
private Account staffAccount;
private String nodeName;
private String nodeDescription;
private String thumbnail;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public boolean isOpenRegistrations() {
return openRegistrations;
}
public void setOpenRegistrations(boolean openRegistrations) {
this.openRegistrations = openRegistrations;
}
public boolean isConnectionError() {
return connectionError;
}
public void setConnectionError(boolean connectionError) {
this.connectionError = connectionError;
}
public int getNumberOfUsers() {
return numberOfUsers;
}
public void setNumberOfUsers(int numberOfUsers) {
this.numberOfUsers = numberOfUsers;
}
public int getNumberOfPosts() {
return numberOfPosts;
}
public void setNumberOfPosts(int numberOfPosts) {
this.numberOfPosts = numberOfPosts;
}
public String getStaffAccountStr() {
return staffAccountStr;
}
public void setStaffAccountStr(String staffAccountStr) {
this.staffAccountStr = staffAccountStr;
}
public Account getStaffAccount() {
return staffAccount;
}
public void setStaffAccount(Account staffAccount) {
this.staffAccount = staffAccount;
}
public String getNodeName() {
return nodeName;
}
public void setNodeName(String nodeName) {
this.nodeName = nodeName;
}
public String getNodeDescription() {
return nodeDescription;
}
public void setNodeDescription(String nodeDescription) {
this.nodeDescription = nodeDescription;
}
public String getThumbnail() {
return thumbnail;
}
public void setThumbnail(String thumbnail) {
this.thumbnail = thumbnail;
}
public int getNumberOfInstance() {
return numberOfInstance;
}
public void setNumberOfInstance(int numberOfInstance) {
this.numberOfInstance = numberOfInstance;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}

View File

@ -0,0 +1,124 @@
package app.fedilab.fedilabtube.client.entities;
public class InstanceReg {
private String domain;
private String version;
private String description;
private String language;
private String category;
private String proxied_thumbnail;
private int total_users;
private int last_week_users;
private boolean selected = false;
private int totalVideos;
private String country;
private int totalInstanceFollowers;
private int totalInstanceFollowing;
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getProxied_thumbnail() {
return proxied_thumbnail;
}
public void setProxied_thumbnail(String proxied_thumbnail) {
this.proxied_thumbnail = proxied_thumbnail;
}
public int getTotal_users() {
return total_users;
}
public void setTotal_users(int total_users) {
this.total_users = total_users;
}
public int getLast_week_users() {
return last_week_users;
}
public void setLast_week_users(int last_week_users) {
this.last_week_users = last_week_users;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
public int getTotalVideos() {
return totalVideos;
}
public void setTotalVideos(int totalVideos) {
this.totalVideos = totalVideos;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public int getTotalInstanceFollowers() {
return totalInstanceFollowers;
}
public void setTotalInstanceFollowers(int totalInstanceFollowers) {
this.totalInstanceFollowers = totalInstanceFollowers;
}
public int getTotalInstanceFollowing() {
return totalInstanceFollowing;
}
public void setTotalInstanceFollowing(int totalInstanceFollowing) {
this.totalInstanceFollowing = totalInstanceFollowing;
}
}

View File

@ -0,0 +1,80 @@
package app.fedilab.fedilabtube.client.entities;
import android.os.Parcel;
import android.os.Parcelable;
public class Mention implements Parcelable {
public static final Creator<Mention> CREATOR = new Creator<Mention>() {
@Override
public Mention createFromParcel(Parcel in) {
return new Mention(in);
}
@Override
public Mention[] newArray(int size) {
return new Mention[size];
}
};
private String url;
private String username;
private String acct;
private String id;
private Mention(Parcel in) {
url = in.readString();
username = in.readString();
acct = in.readString();
id = in.readString();
}
public Mention() {
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAcct() {
return acct;
}
public void setAcct(String acct) {
this.acct = acct;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(url);
dest.writeString(username);
dest.writeString(acct);
dest.writeString(id);
}
}

View File

@ -0,0 +1,37 @@
/* Copyright 2019 Thomas Schneider
*
* This file is a part of Fedilab
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
* see <http://www.gnu.org/licenses>. */
package app.fedilab.fedilabtube.client.entities;
@SuppressWarnings("unused")
public class NodeInfo {
private String rel;
private String href;
public String getRel() {
return rel;
}
public void setRel(String rel) {
this.rel = rel;
}
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
}

View File

@ -0,0 +1,345 @@
package app.fedilab.fedilabtube.client.entities;
import org.json.JSONObject;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@SuppressWarnings("unused")
public class Peertube {
private String id;
private String uuid;
private String name;
private String description;
private String host;
private String thumbnailPath;
private String previewPath;
private String embedPath;
private int view;
private int like;
private int dislike;
private Date created_at;
private int duration;
private String instance;
private Account account;
private Account channel;
private List<String> resolution;
private List<String> tags;
private boolean commentsEnabled;
private boolean sensitive;
private HashMap<Integer, String> category;
private HashMap<Integer, String> license;
private HashMap<String, String> language;
private HashMap<Integer, String> privacy;
private HashMap<String, String> channelForUpdate;
private String myRating = "none";
private boolean isUpdate = false;
private String headerType = null;
private String headerTypeValue = null;
private JSONObject cache;
private boolean streamService;
public Peertube() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getThumbnailPath() {
return thumbnailPath;
}
public void setThumbnailPath(String thumbnailPath) {
this.thumbnailPath = thumbnailPath;
}
public String getPreviewPath() {
return previewPath;
}
public void setPreviewPath(String previewPath) {
this.previewPath = previewPath;
}
public String getEmbedPath() {
return embedPath;
}
public void setEmbedPath(String embedPath) {
this.embedPath = embedPath;
}
public int getView() {
return view;
}
public void setView(int view) {
this.view = view;
}
public int getLike() {
return like;
}
public void setLike(int like) {
this.like = like;
}
public int getDislike() {
return dislike;
}
public void setDislike(int dislike) {
this.dislike = dislike;
}
public Date getCreated_at() {
return created_at;
}
public void setCreated_at(Date created_at) {
this.created_at = created_at;
}
public int getDuration() {
return duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
public String getInstance() {
return instance;
}
public void setInstance(String instance) {
this.instance = instance;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public String getFileUrl(String resolution, boolean streamService) {
if (resolution == null)
resolution = this.getResolution().get(0);
if (resolution == null)
return null;
if (streamService) {
return "https://" + this.host + "/static/streaming-playlists/hls/" + getUuid() + "/" + getUuid() + "-" + resolution + "-fragmented.mp4";
} else {
return "https://" + this.host + "/static/webseed/" + getUuid() + "-" + resolution + ".mp4";
}
}
public String getTorrentUrl(String resolution) {
if (resolution == null)
resolution = this.getResolution().get(0);
if (resolution == null)
return null;
return "https://" + this.host + "/static/torrents/" + getUuid() + "-" + resolution + ".torrent";
}
public String getTorrentDownloadUrl(String resolution) {
if (resolution == null)
resolution = this.getResolution().get(0);
if (resolution == null)
return null;
return "https://" + this.host + "/download/torrents/" + getUuid() + "-" + resolution + ".torrent";
}
public String getFileDownloadUrl(String resolution, boolean streamService) {
if (resolution == null)
resolution = this.getResolution().get(0);
if (resolution == null)
return null;
if (streamService) {
return "https://" + this.host + "/download/streaming-playlists/hls/videos/" + getUuid() + "/" + getUuid() + "-" + resolution + "-fragmented.mp4";
} else {
return "https://" + this.host + "/download/videos/" + getUuid() + "-" + resolution + ".mp4";
}
}
public List<String> getResolution() {
return resolution;
}
public void setResolution(List<String> resolution) {
this.resolution = resolution;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public boolean isCommentsEnabled() {
return commentsEnabled;
}
public void setCommentsEnabled(boolean commentsEnabled) {
this.commentsEnabled = commentsEnabled;
}
public JSONObject getCache() {
return cache;
}
public void setCache(JSONObject cache) {
this.cache = cache;
}
public boolean isSensitive() {
return sensitive;
}
public void setSensitive(boolean sensitive) {
this.sensitive = sensitive;
}
public String getMyRating() {
return myRating;
}
public void setMyRating(String myRating) {
this.myRating = myRating;
}
public Account getChannel() {
return channel;
}
public void setChannel(Account channel) {
this.channel = channel;
}
public List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
public HashMap<Integer, String> getCategory() {
return category;
}
public void setCategory(HashMap<Integer, String> category) {
this.category = category;
}
public HashMap<Integer, String> getLicense() {
return license;
}
public void setLicense(HashMap<Integer, String> license) {
this.license = license;
}
public HashMap<String, String> getLanguage() {
return language;
}
public void setLanguage(HashMap<String, String> language) {
this.language = language;
}
public HashMap<Integer, String> getPrivacy() {
return privacy;
}
public void setPrivacy(HashMap<Integer, String> privacy) {
this.privacy = privacy;
}
public HashMap<String, String> getChannelForUpdate() {
return channelForUpdate;
}
public void setChannelForUpdate(HashMap<String, String> channelForUpdate) {
this.channelForUpdate = channelForUpdate;
}
public boolean isUpdate() {
return isUpdate;
}
public void setUpdate(boolean update) {
isUpdate = update;
}
public String getHeaderType() {
return headerType;
}
public void setHeaderType(String headerType) {
this.headerType = headerType;
}
public String getHeaderTypeValue() {
return headerTypeValue;
}
public void setHeaderTypeValue(String headerTypeValue) {
this.headerTypeValue = headerTypeValue;
}
public boolean isStreamService() {
return streamService;
}
public void setStreamService(boolean streamService) {
this.streamService = streamService;
}
}

View File

@ -0,0 +1,62 @@
package app.fedilab.fedilabtube.client.entities;
public class PeertubeAccountNotification {
private String id;
private String avatar;
private String displayName;
private String name;
private String type;
private String host;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
}

View File

@ -0,0 +1,38 @@
package app.fedilab.fedilabtube.client.entities;
public class PeertubeActorFollow {
private String id;
private PeertubeAccountNotification follower;
private PeertubeAccountNotification following;
public PeertubeActorFollow() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public PeertubeAccountNotification getFollower() {
return follower;
}
public void setFollower(PeertubeAccountNotification follower) {
this.follower = follower;
}
public PeertubeAccountNotification getFollowing() {
return following;
}
public void setFollowing(PeertubeAccountNotification following) {
this.following = following;
}
}

View File

@ -0,0 +1,47 @@
package app.fedilab.fedilabtube.client.entities;
public class PeertubeComment {
private String id;
private String threadId;
private PeertubeVideoNotification peertubeVideoNotification;
private PeertubeAccountNotification peertubeAccountNotification;
public PeertubeComment() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getThreadId() {
return threadId;
}
public void setThreadId(String threadId) {
this.threadId = threadId;
}
public PeertubeVideoNotification getPeertubeVideoNotification() {
return peertubeVideoNotification;
}
public void setPeertubeVideoNotification(PeertubeVideoNotification peertubeVideoNotification) {
this.peertubeVideoNotification = peertubeVideoNotification;
}
public PeertubeAccountNotification getPeertubeAccountNotification() {
return peertubeAccountNotification;
}
public void setPeertubeAccountNotification(PeertubeAccountNotification peertubeAccountNotification) {
this.peertubeAccountNotification = peertubeAccountNotification;
}
}

View File

@ -0,0 +1,83 @@
package app.fedilab.fedilabtube.client.entities;
import java.util.LinkedHashMap;
public class PeertubeInformation {
public static final LinkedHashMap<String, String> langueMapped;
static {
LinkedHashMap<String, String> aMap = new LinkedHashMap<>();
aMap.put("ca", "ca-ES");
aMap.put("de", "de-DE");
aMap.put("en", "en-US");
aMap.put("es", "es-ES");
aMap.put("eo", "eo");
aMap.put("eu", "eu-ES");
aMap.put("fr", "fr-FR");
aMap.put("oc", "oc");
aMap.put("pt", "pt-BR");
aMap.put("sv", "sv-SE");
aMap.put("cs", "cs-CZ");
aMap.put("zh-CN", "zh-Hans-CN");
aMap.put("zh-TW", "zh-Hans-TW");
langueMapped = aMap;
}
private LinkedHashMap<Integer, String> categories;
private LinkedHashMap<String, String> languages;
private LinkedHashMap<Integer, String> licences;
private LinkedHashMap<Integer, String> privacies;
private LinkedHashMap<Integer, String> playlistPrivacies;
private LinkedHashMap<String, String> translations;
public LinkedHashMap<String, String> getTranslations() {
return translations;
}
public void setTranslations(LinkedHashMap<String, String> translations) {
this.translations = translations;
}
public LinkedHashMap<Integer, String> getCategories() {
return categories;
}
public void setCategories(LinkedHashMap<Integer, String> categories) {
this.categories = categories;
}
public LinkedHashMap<String, String> getLanguages() {
return languages;
}
public void setLanguages(LinkedHashMap<String, String> languages) {
this.languages = languages;
}
public LinkedHashMap<Integer, String> getLicences() {
return licences;
}
public void setLicences(LinkedHashMap<Integer, String> licences) {
this.licences = licences;
}
public LinkedHashMap<Integer, String> getPrivacies() {
return privacies;
}
public void setPrivacies(LinkedHashMap<Integer, String> privacies) {
this.privacies = privacies;
}
public LinkedHashMap<Integer, String> getPlaylistPrivacies() {
return playlistPrivacies;
}
public void setPlaylistPrivacies(LinkedHashMap<Integer, String> playlistPrivacies) {
this.playlistPrivacies = playlistPrivacies;
}
}

View File

@ -0,0 +1,85 @@
package app.fedilab.fedilabtube.client.entities;
import java.util.Date;
public class PeertubeNotification {
private String id;
private boolean read;
private Date updatedAt, createdAt;
private int type;
private PeertubeComment peertubeComment;
private PeertubeVideoNotification peertubeVideoNotification;
private PeertubeActorFollow peertubeActorFollow;
public PeertubeNotification() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public boolean isRead() {
return read;
}
public void setRead(boolean read) {
this.read = read;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public PeertubeComment getPeertubeComment() {
return peertubeComment;
}
public void setPeertubeComment(PeertubeComment peertubeComment) {
this.peertubeComment = peertubeComment;
}
public PeertubeActorFollow getPeertubeActorFollow() {
return peertubeActorFollow;
}
public void setPeertubeActorFollow(PeertubeActorFollow peertubeActorFollow) {
this.peertubeActorFollow = peertubeActorFollow;
}
public PeertubeVideoNotification getPeertubeVideoNotification() {
return peertubeVideoNotification;
}
public void setPeertubeVideoNotification(PeertubeVideoNotification peertubeVideoNotification) {
this.peertubeVideoNotification = peertubeVideoNotification;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
}

View File

@ -0,0 +1,43 @@
package app.fedilab.fedilabtube.client.entities;
public class PeertubeVideoNotification {
private String id;
private PeertubeAccountNotification peertubeAccountNotification;
private String uuid;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public PeertubeAccountNotification getPeertubeAccountNotification() {
return peertubeAccountNotification;
}
public void setPeertubeAccountNotification(PeertubeAccountNotification peertubeAccountNotification) {
this.peertubeAccountNotification = peertubeAccountNotification;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
}

View File

@ -0,0 +1,185 @@
package app.fedilab.fedilabtube.client.entities;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Date;
import java.util.HashMap;
@SuppressWarnings("unused")
public class Playlist implements Parcelable {
public static final Creator<Playlist> CREATOR = new Creator<Playlist>() {
@Override
public Playlist createFromParcel(Parcel source) {
return new Playlist(source);
}
@Override
public Playlist[] newArray(int size) {
return new Playlist[size];
}
};
private String id;
private String uuid;
private String displayName;
private String description;
private String videoChannelId;
private Date createdAt;
private boolean isLocal;
private Account ownerAccount;
private HashMap<Integer, String> privacy;
private String thumbnailPath;
private HashMap<Integer, String> type;
private Date updatedAt;
private int videosLength;
public Playlist() {
}
private Playlist(Parcel in) {
this.id = in.readString();
this.uuid = in.readString();
this.displayName = in.readString();
this.description = in.readString();
this.videoChannelId = in.readString();
long tmpCreatedAt = in.readLong();
this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt);
this.isLocal = in.readByte() != 0;
this.ownerAccount = in.readParcelable(Account.class.getClassLoader());
this.privacy = (HashMap<Integer, String>) in.readSerializable();
this.thumbnailPath = in.readString();
this.type = (HashMap<Integer, String>) in.readSerializable();
long tmpUpdatedAt = in.readLong();
this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt);
this.videosLength = in.readInt();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getVideoChannelId() {
return videoChannelId;
}
public void setVideoChannelId(String videoChannelId) {
this.videoChannelId = videoChannelId;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public boolean isLocal() {
return isLocal;
}
public void setLocal(boolean local) {
isLocal = local;
}
public Account getOwnerAccount() {
return ownerAccount;
}
public void setOwnerAccount(Account ownerAccount) {
this.ownerAccount = ownerAccount;
}
public HashMap<Integer, String> getPrivacy() {
return privacy;
}
public void setPrivacy(HashMap<Integer, String> privacy) {
this.privacy = privacy;
}
public String getThumbnailPath() {
return thumbnailPath;
}
public void setThumbnailPath(String thumbnailPath) {
this.thumbnailPath = thumbnailPath;
}
public HashMap<Integer, String> getType() {
return type;
}
public void setType(HashMap<Integer, String> type) {
this.type = type;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public int getVideosLength() {
return videosLength;
}
public void setVideosLength(int videosLength) {
this.videosLength = videosLength;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.id);
dest.writeString(this.uuid);
dest.writeString(this.displayName);
dest.writeString(this.description);
dest.writeString(this.videoChannelId);
dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1);
dest.writeByte(this.isLocal ? (byte) 1 : (byte) 0);
dest.writeParcelable(this.ownerAccount, flags);
dest.writeSerializable(this.privacy);
dest.writeString(this.thumbnailPath);
dest.writeSerializable(this.type);
dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1);
dest.writeInt(this.videosLength);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,60 @@
package app.fedilab.fedilabtube.client.entities;
import android.os.Parcel;
import android.os.Parcelable;
public class Tag implements Parcelable {
public static final Creator<Tag> CREATOR = new Creator<Tag>() {
@Override
public Tag createFromParcel(Parcel source) {
return new Tag(source);
}
@Override
public Tag[] newArray(int size) {
return new Tag[size];
}
};
private String name;
private String url;
public Tag() {
}
protected Tag(Parcel in) {
this.name = in.readString();
this.url = in.readString();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
dest.writeString(this.url);
}
}

View File

@ -0,0 +1,27 @@
package app.fedilab.fedilabtube.helper;
import java.util.Arrays;
/**
* Work from https://stackoverflow.com/a/26420820
*/
public class FileNameCleaner {
private final static int[] illegalChars = {34, 60, 62, 124, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 58, 42, 63, 92, 47};
static {
Arrays.sort(illegalChars);
}
public static String cleanFileName(String badFileName) {
StringBuilder cleanName = new StringBuilder();
int len = badFileName.codePointCount(0, badFileName.length());
for (int i = 0; i < len; i++) {
int c = badFileName.codePointAt(i);
if (Arrays.binarySearch(illegalChars, c) < 0) {
cleanName.appendCodePoint(c);
}
}
return cleanName.toString();
}
}

View File

@ -0,0 +1,115 @@
package app.fedilab.fedilabtube.helper;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.MediaController;
import app.fedilab.fedilabtube.PeertubeActivity;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.client.entities.Peertube;
/**
* Created by Thomas
* FullScreenMediaController. Inspired from the work at http://www.zoftino.com/android-videoview-playing-videos-full-screen
*/
public class FullScreenMediaController extends MediaController {
private ImageButton fullScreen;
private Button resolution;
private Context context;
private Peertube peertube;
private String resolutionVal;
public FullScreenMediaController(Context context) {
super(context);
this.context = context;
}
@SuppressWarnings("unused")
public FullScreenMediaController(Context context, Peertube peertube) {
super(context);
this.peertube = peertube;
this.context = context;
}
@Override
public void setAnchorView(View view) {
super.setAnchorView(view);
//image button for full screen to be added to media controller
fullScreen = new ImageButton(context);
LayoutParams params =
new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.END;
params.rightMargin = 80;
params.topMargin = 22;
addView(fullScreen, params);
if (resolutionVal == null)
resolutionVal = peertube.getResolution().get(0) + "p";
resolution = new Button(context);
resolution.setAllCaps(false);
resolution.setBackgroundColor(Color.TRANSPARENT);
resolution.setText(resolutionVal);
resolution.setPadding(0, 0, 0, 0);
LayoutParams paramsButton =
new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
paramsButton.gravity = Gravity.START;
paramsButton.rightMargin = 80;
paramsButton.topMargin = 22;
resolution.setOnClickListener(v -> ((PeertubeActivity) getContext()).displayResolution());
addView(resolution, paramsButton);
if (((PeertubeActivity) getContext()).getFullscreen() == fullscreen.ON) {
Resources resources = getResources();
fullScreen.setImageDrawable(resources.getDrawable(R.drawable.ic_baseline_fullscreen_exit_24));
} else {
Resources resources = getResources();
fullScreen.setImageDrawable(resources.getDrawable(R.drawable.ic_baseline_fullscreen_24));
}
//add listener to image button to handle full screen and exit full screen events
fullScreen.setOnClickListener(v -> {
if (((PeertubeActivity) getContext()).getFullscreen() == fullscreen.ON) {
((PeertubeActivity) getContext()).setFullscreen(fullscreen.OFF);
} else {
((PeertubeActivity) getContext()).setFullscreen(fullscreen.ON);
}
((PeertubeActivity) getContext()).change();
changeIcon();
});
}
@SuppressWarnings("unused")
public void setResolutionVal(String resolutionVal) {
this.resolutionVal = resolutionVal;
if (resolution != null)
resolution.setText(String.format("%sp", resolutionVal));
}
public void changeIcon() {
//fullscreen indicator from intent
if (((PeertubeActivity) getContext()).getFullscreen() == fullscreen.ON) {
Resources resources = getResources();
fullScreen.setImageDrawable(resources.getDrawable(R.drawable.ic_baseline_fullscreen_exit_24));
} else {
Resources resources = getResources();
fullScreen.setImageDrawable(resources.getDrawable(R.drawable.ic_baseline_fullscreen_24));
}
}
public enum fullscreen {
OFF,
ON
}
}

View File

@ -1,8 +1,44 @@
package app.fedilab.fedilabtube.helper;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.DownloadManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.view.WindowManager;
import android.webkit.URLUtil;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestOptions;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Pattern;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.client.entities.Account;
import es.dmoral.toasty.Toasty;
import static android.content.Context.DOWNLOAD_SERVICE;
public class Helper {
@ -40,6 +76,59 @@ public class Helper {
"ac-versailles.fr"
));
public static final String TAG = "mastodon_etalab";
public static final String CLIENT_NAME_VALUE = "Fedilab";
public static final String OAUTH_SCOPES = "read write follow";
public static final String OAUTH_SCOPES_ADMIN = "read write follow admin:read admin:write admin";
public static final String OAUTH_SCOPES_PEERTUBE = "user";
public static final String PREF_KEY_OAUTH_TOKEN = "oauth_token";
public static final Pattern urlPattern = Pattern.compile(
"(?i)\\b((?:[a-z][\\w-]+:(?:/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,10}/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:'\".,<>?«»“”‘’]))",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
public static final String SET_ALLOW_STREAM = "set_allow_stream";
public static final String SET_CUSTOM_USER_AGENT = "set_custom_user_agent";
public static final String SET_VIDEO_CACHE = "set_video_cache";
public static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; rv:60.0) Gecko/20100101 Firefox/60.0";
//Proxy
public static final String SET_PROXY_ENABLED = "set_proxy_enabled";
public static final String SET_PROXY_TYPE = "set_proxy_type";
public static final String SET_PROXY_HOST = "set_proxy_host";
public static final String SET_PROXY_PORT = "set_proxy_port";
public static final String SET_PROXY_LOGIN = "set_proxy_login";
public static final String SET_PROXY_PASSWORD = "set_proxy_password";
public static final String PREF_KEY_ID = "userID";
public static final String PREF_IS_MODERATOR = "is_moderator";
public static final String PREF_IS_ADMINISTRATOR = "is_administrator";
public static final String PREF_INSTANCE = "instance";
public static final String REDIRECT_CONTENT = "urn:ietf:wg:oauth:2.0:oob";
public static final String REDIRECT_CONTENT_WEB = "mastalab://backtomastalab";
public static final int EXTERNAL_STORAGE_REQUEST_CODE = 84;
public static final String CLIENT_NAME = "client_name";
public static final String APP_PREFS = "app_prefs";
public static final String ID = "id";
public static final String CLIENT_ID = "client_id";
public static final String CLIENT_SECRET = "client_secret";
public static final String REDIRECT_URI = "redirect_uri";
public static final String REDIRECT_URIS = "redirect_uris";
public static final String RESPONSE_TYPE = "response_type";
public static final String SCOPE = "scope";
public static final String SCOPES = "scopes";
public static final String WEBSITE = "website";
public static final String SHOW_ACCOUNT_BOOSTS = "show_account_boosts";
public static final String SHOW_ACCOUNT_REPLIES = "show_account_replies";
public static final String WEBSITE_VALUE = "https://fedilab.app";
public static final String SHOW_BATTERY_SAVER_MESSAGE = "show_battery_saver_message";
public static final String LAST_NOTIFICATION_MAX_ID = "last_notification_max_id";
public static final int VIDEOS_PER_PAGE = 40;
public static final String SET_VIDEO_NSFW = "set_video_nsfw";
/**
* Returns the peertube URL depending of the academic domain name
* @param acad String academic domain name
@ -48,4 +137,298 @@ public class Helper {
public static String getPeertubeUrl(String acad) {
return "https://tube-"+acad.replace("ac\\-|\\.fr","")+".beta.education.fr/";
}
/**
* Returns the instance of the authenticated user
*
* @param context Context
* @return String domain instance
*/
public static String getLiveInstance(Context context) {
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
return sharedpreferences.getString(Helper.PREF_INSTANCE, null);
}
public static String getLiveInstanceWithProtocol(Context context) {
return instanceWithProtocol(getLiveInstance(context));
}
public static String instanceWithProtocol(String instance) {
if (instance == null)
return null;
return "https://" + instance;
}
/**
* Convert String date from Mastodon
*
* @param date String
* @return Date
*/
public static Date mstStringToDate(String date) throws ParseException {
if (date == null)
return null;
String STRING_DATE_FORMAT;
Locale local = Locale.getDefault();
if (!date.contains("+")) {
STRING_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
} else { //GNU date format
STRING_DATE_FORMAT = "EEE MMM dd HH:mm:ss ZZZZZ yyyy";
local = Locale.ENGLISH;
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(STRING_DATE_FORMAT, local);
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("gmt"));
simpleDateFormat.setLenient(true);
try {
return simpleDateFormat.parse(date);
} catch (Exception e) {
String newdate = date.split("\\+")[0].trim();
simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", local);
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("gmt"));
simpleDateFormat.setLenient(true);
return simpleDateFormat.parse(newdate);
}
}
/**
* Convert a date in String -> format yyyy-MM-dd HH:mm:ss
*
* @param date Date
* @return String
*/
public static String dateToString(Date date) {
if (date == null)
return null;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
return dateFormat.format(date);
}
/**
* Convert String date from db to Date Object
*
* @param stringDate date to convert
* @return Date
*/
public static Date stringToDate(Context context, String stringDate) {
if (stringDate == null)
return null;
Locale userLocale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
userLocale = context.getResources().getConfiguration().getLocales().get(0);
} else {
userLocale = context.getResources().getConfiguration().locale;
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", userLocale);
Date date = null;
try {
date = dateFormat.parse(stringDate);
} catch (java.text.ParseException ignored) {
}
return date;
}
public static String secondsToString(int pTime) {
int hour = pTime / 3600;
int min = (pTime - (hour * 3600)) / 60;
int sec = pTime - (hour * 3600) - (min * 60);
String strHour = "0", strMin = "0", strSec;
if (hour > 0)
strHour = String.format(Locale.getDefault(), "%02d", hour);
if (min > 0)
strMin = String.format(Locale.getDefault(), "%02d", min);
strSec = String.format(Locale.getDefault(), "%02d", sec);
if (hour > 0)
return String.format(Locale.getDefault(), "%s:%s:%s", strHour, strMin, strSec);
else
return String.format(Locale.getDefault(), "%s:%s", strMin, strSec);
}
/***
* Returns a String depending of the date
* @param context Context
* @param dateToot Date
* @return String
*/
public static String dateDiff(Context context, Date dateToot) {
Date now = new Date();
long diff = now.getTime() - dateToot.getTime();
long seconds = diff / 1000;
long minutes = seconds / 60;
long hours = minutes / 60;
long days = hours / 24;
long months = days / 30;
long years = days / 365;
String format = DateFormat.getDateInstance(DateFormat.SHORT).format(dateToot);
if (years > 0) {
return format;
} else if (months > 0 || days > 7) {
//Removes the year depending of the locale from DateFormat.SHORT format
SimpleDateFormat df = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
df.applyPattern(df.toPattern().replaceAll("[^\\p{Alpha}]*y+[^\\p{Alpha}]*", ""));
return df.format(dateToot);
} else if (days > 0)
return context.getString(R.string.date_day, days);
else if (hours > 0)
return context.getResources().getString(R.string.date_hours, (int) hours);
else if (minutes > 0)
return context.getResources().getString(R.string.date_minutes, (int) minutes);
else {
if (seconds < 0)
seconds = 0;
return context.getResources().getString(R.string.date_seconds, (int) seconds);
}
}
public static String dateDiffFull(Date dateToot) {
SimpleDateFormat df = (SimpleDateFormat) DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.MEDIUM, Locale.getDefault());
try {
return df.format(dateToot);
} catch (Exception e) {
return "";
}
}
public static String withSuffix(long count) {
if (count < 1000) return "" + count;
int exp = (int) (Math.log(count) / Math.log(1000));
Locale locale = null;
try {
locale = Locale.getDefault();
} catch (Exception ignored) {
}
if (locale != null)
return String.format(locale, "%.1f %c",
count / Math.pow(1000, exp),
"kMGTPE".charAt(exp - 1));
else
return String.format(Locale.getDefault(), "%.1f %c",
count / Math.pow(1000, exp),
"kMGTPE".charAt(exp - 1));
}
public static void loadGiF(final Context context, Account account, final ImageView imageView) {
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String url = account.getAvatar();
if (url != null && url.startsWith("/")) {
url = Helper.getLiveInstanceWithProtocol(context) + url;
}
try {
Glide.with(imageView.getContext())
.asDrawable()
.load(url)
.thumbnail(0.1f)
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
.into(imageView);
} catch (Exception e) {
try {
Glide.with(imageView.getContext())
.asDrawable()
.load(R.drawable.missing_peertube)
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
.into(imageView);
} catch (Exception ignored) {
}
}
}
/**
* Manage URLs to open (built-in or external app)
*
* @param context Context
* @param url String url to open
*/
public static void openBrowser(Context context, String url) {
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE);
boolean embedded_browser = sharedpreferences.getBoolean(Helper.SET_EMBEDDED_BROWSER, true);
if (embedded_browser) {
Intent intent = new Intent(context, WebviewActivity.class);
Bundle b = new Bundle();
String finalUrl = url;
if (!url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://"))
finalUrl = "http://" + url;
b.putString("url", finalUrl);
intent.putExtras(b);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} else {
boolean custom_tabs = sharedpreferences.getBoolean(Helper.SET_CUSTOM_TABS, true);
if (custom_tabs) {
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent = builder.build();
builder.setToolbarColor(ContextCompat.getColor(context, R.color.mastodonC1));
try {
customTabsIntent.launchUrl(context, Uri.parse(url));
} catch (Exception ignored) {
Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
}
} else {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setData(Uri.parse(url));
try {
context.startActivity(intent);
} catch (Exception e) {
Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
}
}
}
}
/**
* Manage downloads with URLs
*
* @param context Context
* @param url String download url
*/
public static void manageDownloads(final Context context, final String url) {
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
final DownloadManager.Request request;
try {
request = new DownloadManager.Request(Uri.parse(url.trim()));
} catch (Exception e) {
Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
return;
}
final String fileName = URLUtil.guessFileName(url, null, null);
builder.setMessage(context.getResources().getString(R.string.download_file, fileName));
builder.setCancelable(false)
.setPositiveButton(context.getString(R.string.yes), (dialog, id) -> {
request.allowScanningByMediaScanner();
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
DownloadManager dm = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE);
assert dm != null;
dm.enqueue(request);
dialog.dismiss();
})
.setNegativeButton(context.getString(R.string.cancel), (dialog, id) -> dialog.cancel());
AlertDialog alert = builder.create();
if (alert.getWindow() != null)
alert.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
alert.show();
}
}

View File

@ -0,0 +1,9 @@
package app.fedilab.fedilabtube.interfaces;
import app.fedilab.fedilabtube.client.APIResponse;
public interface OnActionInterface {
void onActionDone(APIResponse apiResponse, int statusCode);
}

View File

@ -0,0 +1,9 @@
package app.fedilab.fedilabtube.interfaces;
public interface OnDownloadInterface {
void onDownloaded(String saveFilePath, String downloadUrl, Error error);
void onUpdateProgress(int progress);
}

View File

@ -0,0 +1,10 @@
package app.fedilab.fedilabtube.interfaces;
import app.fedilab.fedilabtube.asynctasks.ManagePlaylistsAsyncTask;
import app.fedilab.fedilabtube.client.APIResponse;
public interface OnPlaylistActionInterface {
void onActionDone(ManagePlaylistsAsyncTask.action actionType, APIResponse apiResponse, int statusCode);
}

View File

@ -0,0 +1,10 @@
package app.fedilab.fedilabtube.interfaces;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Error;
public interface OnPostActionInterface {
void onPostAction(int statusCode, PeertubeAPI.StatusAction statusAction, String userId, Error error);
}

View File

@ -0,0 +1,9 @@
package app.fedilab.fedilabtube.interfaces;
import app.fedilab.fedilabtube.client.APIResponse;
public interface OnRetrieveFeedsInterface {
void onRetrieveFeeds(APIResponse apiResponse);
}

View File

@ -0,0 +1,13 @@
package app.fedilab.fedilabtube.interfaces;
import app.fedilab.fedilabtube.client.APIResponse;
public interface OnRetrievePeertubeInterface {
void onRetrievePeertube(APIResponse apiResponse);
void onRetrievePeertubeComments(APIResponse apiResponse);
void onRetrievePeertubeChannels(APIResponse apiResponse);
}

View File

@ -0,0 +1,10 @@
package app.fedilab.fedilabtube.interfaces;
import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.entities.Account;
public interface OnRetrievePeertubeNotificationsInterface {
void onRetrievePeertubeNotifications(APIResponse apiResponse, Account account);
}

View File

@ -0,0 +1,372 @@
package app.fedilab.fedilabtube.sqlite;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import app.fedilab.fedilabtube.client.entities.Account;
import app.fedilab.fedilabtube.helper.Helper;
public class AccountDAO {
public Context context;
private SQLiteDatabase db;
public AccountDAO(Context context, SQLiteDatabase db) {
//Creation of the DB with tables
this.context = context;
this.db = db;
}
/**
* Insert an Account in database
*
* @param account Account
* @return boolean
*/
public boolean insertAccount(Account account) {
ContentValues values = new ContentValues();
if (account.getCreated_at() == null)
account.setCreated_at(new Date());
if (account.getNote() == null)
account.setNote("");
values.put(Sqlite.COL_USER_ID, account.getId());
values.put(Sqlite.COL_USERNAME, account.getUsername());
values.put(Sqlite.COL_ACCT, account.getAcct());
values.put(Sqlite.COL_DISPLAYED_NAME, account.getDisplay_name());
values.put(Sqlite.COL_LOCKED, account.isLocked());
values.put(Sqlite.COL_FOLLOWERS_COUNT, account.getFollowers_count());
values.put(Sqlite.COL_FOLLOWING_COUNT, account.getFollowing_count());
values.put(Sqlite.COL_STATUSES_COUNT, account.getStatuses_count());
values.put(Sqlite.COL_NOTE, account.getNote());
values.put(Sqlite.COL_URL, account.getUrl());
values.put(Sqlite.COL_AVATAR, account.getAvatar());
values.put(Sqlite.COL_AVATAR_STATIC, account.getAvatar_static());
values.put(Sqlite.COL_HEADER, account.getHeader());
values.put(Sqlite.COL_HEADER_STATIC, account.getHeader_static());
values.put(Sqlite.COL_CREATED_AT, Helper.dateToString(account.getCreated_at()));
values.put(Sqlite.COL_INSTANCE, account.getInstance());
if (account.getClient_id() != null && account.getClient_secret() != null && account.getRefresh_token() != null) {
values.put(Sqlite.COL_CLIENT_ID, account.getClient_id());
values.put(Sqlite.COL_CLIENT_SECRET, account.getClient_secret());
values.put(Sqlite.COL_REFRESH_TOKEN, account.getRefresh_token());
}
if (account.getToken() != null)
values.put(Sqlite.COL_OAUTHTOKEN, account.getToken());
values.put(Sqlite.COL_SENSITIVE, account.isSensitive());
values.put(Sqlite.COL_PRIVACY, account.getPrivacy());
//Inserts account
try {
db.insertOrThrow(Sqlite.TABLE_USER_ACCOUNT, null, values);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* Update an Account in database
*
* @param account Account
* @return boolean
*/
public int updateAccount(Account account) {
ContentValues values = new ContentValues();
if (account.getNote() == null)
account.setNote("");
if (account.getCreated_at() == null)
account.setCreated_at(new Date());
values.put(Sqlite.COL_ACCT, account.getAcct());
values.put(Sqlite.COL_DISPLAYED_NAME, account.getDisplay_name());
values.put(Sqlite.COL_LOCKED, account.isLocked());
values.put(Sqlite.COL_FOLLOWERS_COUNT, account.getFollowers_count());
values.put(Sqlite.COL_FOLLOWING_COUNT, account.getFollowing_count());
values.put(Sqlite.COL_STATUSES_COUNT, account.getStatuses_count());
values.put(Sqlite.COL_NOTE, account.getNote());
values.put(Sqlite.COL_URL, account.getUrl());
values.put(Sqlite.COL_AVATAR, account.getAvatar());
values.put(Sqlite.COL_AVATAR_STATIC, account.getAvatar_static());
values.put(Sqlite.COL_HEADER, account.getHeader());
values.put(Sqlite.COL_HEADER_STATIC, account.getHeader_static());
values.put(Sqlite.COL_CREATED_AT, Helper.dateToString(account.getCreated_at()));
if (account.getClient_id() != null && account.getClient_secret() != null && account.getRefresh_token() != null) {
values.put(Sqlite.COL_CLIENT_ID, account.getClient_id());
values.put(Sqlite.COL_CLIENT_SECRET, account.getClient_secret());
values.put(Sqlite.COL_REFRESH_TOKEN, account.getRefresh_token());
}
if (account.getToken() != null)
values.put(Sqlite.COL_OAUTHTOKEN, account.getToken());
return db.update(Sqlite.TABLE_USER_ACCOUNT,
values, Sqlite.COL_USER_ID + " = ? AND " + Sqlite.COL_INSTANCE + " =?",
new String[]{account.getId(), account.getInstance()});
}
/**
* Update an Account in database
*
* @param account Account
* @return boolean
*/
public int updateAccountCredential(Account account) {
ContentValues values = new ContentValues();
if (account.getNote() == null)
account.setNote("");
if (account.getCreated_at() == null)
account.setCreated_at(new Date());
values.put(Sqlite.COL_ACCT, account.getAcct());
values.put(Sqlite.COL_DISPLAYED_NAME, account.getDisplay_name());
values.put(Sqlite.COL_LOCKED, account.isLocked());
values.put(Sqlite.COL_FOLLOWERS_COUNT, account.getFollowers_count());
values.put(Sqlite.COL_FOLLOWING_COUNT, account.getFollowing_count());
values.put(Sqlite.COL_STATUSES_COUNT, account.getStatuses_count());
values.put(Sqlite.COL_NOTE, account.getNote());
values.put(Sqlite.COL_URL, account.getUrl());
values.put(Sqlite.COL_AVATAR, account.getAvatar());
values.put(Sqlite.COL_AVATAR_STATIC, account.getAvatar_static());
values.put(Sqlite.COL_HEADER, account.getHeader());
values.put(Sqlite.COL_HEADER_STATIC, account.getHeader_static());
values.put(Sqlite.COL_CREATED_AT, Helper.dateToString(account.getCreated_at()));
if (account.getClient_id() != null && account.getClient_secret() != null && account.getRefresh_token() != null) {
values.put(Sqlite.COL_CLIENT_ID, account.getClient_id());
values.put(Sqlite.COL_CLIENT_SECRET, account.getClient_secret());
values.put(Sqlite.COL_REFRESH_TOKEN, account.getRefresh_token());
}
if (account.getToken() != null)
values.put(Sqlite.COL_OAUTHTOKEN, account.getToken());
values.put(Sqlite.COL_SENSITIVE, account.isSensitive());
values.put(Sqlite.COL_PRIVACY, account.getPrivacy());
return db.update(Sqlite.TABLE_USER_ACCOUNT,
values, Sqlite.COL_USER_ID + " = ? AND " + Sqlite.COL_INSTANCE + " =?",
new String[]{account.getId(), account.getInstance()});
}
public int removeUser(Account account) {
return db.delete(Sqlite.TABLE_USER_ACCOUNT, Sqlite.COL_USER_ID + " = '" + account.getId() +
"' AND " + Sqlite.COL_INSTANCE + " = '" + account.getInstance() + "'", null);
}
/**
* Returns last used account
*
* @return Account
*/
public Account getLastUsedAccount() {
try {
Cursor c = db.query(Sqlite.TABLE_USER_ACCOUNT, null, Sqlite.COL_OAUTHTOKEN + " != 'null'", null, null, null, Sqlite.COL_UPDATED_AT + " DESC", "1");
return cursorToUser(c);
} catch (Exception e) {
return null;
}
}
/**
* Returns an Account by its id and acct
*
* @param accountId String
* @param accountAcct String
* @return Account
*/
public Account getAccountByIDAcct(String accountId, String accountAcct) {
try {
Cursor c = db.query(Sqlite.TABLE_USER_ACCOUNT, null, Sqlite.COL_USER_ID + " = '" + accountId + "' AND " + Sqlite.COL_ACCT + " = '" + accountAcct + "'", null, null, null, null, "1");
return cursorToUser(c);
} catch (Exception e) {
return null;
}
}
/**
* Returns all Account in db
*
* @return Account List<Account>
*/
public List<Account> getAllAccount() {
try {
Cursor c = db.query(Sqlite.TABLE_USER_ACCOUNT, null, null, null, null, null, Sqlite.COL_INSTANCE + " ASC", null);
return cursorToListUser(c);
} catch (Exception e) {
return null;
}
}
/**
* Returns all Account in db
*
* @return Account List<Account>
*/
public List<Account> getAllAccountActivated() {
try {
Cursor c = db.query(Sqlite.TABLE_USER_ACCOUNT, null, Sqlite.COL_OAUTHTOKEN + " != 'null'", null, null, null, Sqlite.COL_INSTANCE + " ASC", null);
return cursorToListUser(c);
} catch (Exception e) {
return null;
}
}
/**
* Returns an Account by token
*
* @param token String
* @return Account
*/
public Account getAccountByToken(String token) {
try {
Cursor c = db.query(Sqlite.TABLE_USER_ACCOUNT, null, Sqlite.COL_OAUTHTOKEN + " = \"" + token + "\"", null, null, null, null, "1");
return cursorToUser(c);
} catch (Exception e) {
return null;
}
}
/**
* Returns an Account by token
*
* @param userId String
* @param instance String
* @return Account
*/
public Account getUniqAccount(String userId, String instance) {
try {
Cursor c = db.query(Sqlite.TABLE_USER_ACCOUNT, null, Sqlite.COL_USER_ID + " = \"" + userId + "\" AND " + Sqlite.COL_INSTANCE + " = \"" + instance + "\"", null, null, null, null, "1");
return cursorToUser(c);
} catch (Exception e) {
return null;
}
}
/**
* Test if the current user is already stored in data base
*
* @param account Account
* @return boolean
*/
public boolean userExist(Account account) {
Cursor mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_USER_ACCOUNT
+ " where " + Sqlite.COL_USERNAME + " = '" + account.getUsername() + "' AND " + Sqlite.COL_INSTANCE + " = '" + account.getInstance() + "'", null);
mCount.moveToFirst();
int count = mCount.getInt(0);
mCount.close();
return (count > 0);
}
/***
* Method to hydrate an Account from database
* @param c Cursor
* @return Account
*/
private Account cursorToUser(Cursor c) {
//No element found
if (c.getCount() == 0) {
c.close();
return null;
}
//Take the first element
c.moveToFirst();
//New user
Account account = new Account();
account.setId(c.getString(c.getColumnIndex(Sqlite.COL_USER_ID)));
account.setUsername(c.getString(c.getColumnIndex(Sqlite.COL_USERNAME)));
account.setAcct(c.getString(c.getColumnIndex(Sqlite.COL_ACCT)));
account.setDisplay_name(c.getString(c.getColumnIndex(Sqlite.COL_DISPLAYED_NAME)));
account.setLocked(c.getInt(c.getColumnIndex(Sqlite.COL_LOCKED)) == 1);
account.setFollowers_count(c.getInt(c.getColumnIndex(Sqlite.COL_FOLLOWERS_COUNT)));
account.setFollowing_count(c.getInt(c.getColumnIndex(Sqlite.COL_FOLLOWING_COUNT)));
account.setStatuses_count(c.getInt(c.getColumnIndex(Sqlite.COL_STATUSES_COUNT)));
account.setNote(c.getString(c.getColumnIndex(Sqlite.COL_NOTE)));
account.setUrl(c.getString(c.getColumnIndex(Sqlite.COL_URL)));
account.setAvatar(c.getString(c.getColumnIndex(Sqlite.COL_AVATAR)));
account.setAvatar_static(c.getString(c.getColumnIndex(Sqlite.COL_AVATAR_STATIC)));
account.setHeader(c.getString(c.getColumnIndex(Sqlite.COL_HEADER)));
account.setHeader_static(c.getString(c.getColumnIndex(Sqlite.COL_HEADER_STATIC)));
account.setUpdated_at(Helper.stringToDate(context, c.getString(c.getColumnIndex(Sqlite.COL_UPDATED_AT))));
account.setCreated_at(Helper.stringToDate(context, c.getString(c.getColumnIndex(Sqlite.COL_CREATED_AT))));
account.setInstance(c.getString(c.getColumnIndex(Sqlite.COL_INSTANCE)));
account.setToken(c.getString(c.getColumnIndex(Sqlite.COL_OAUTHTOKEN)));
account.setClient_id(c.getString(c.getColumnIndex(Sqlite.COL_CLIENT_ID)));
account.setClient_secret(c.getString(c.getColumnIndex(Sqlite.COL_CLIENT_SECRET)));
account.setRefresh_token(c.getString(c.getColumnIndex(Sqlite.COL_REFRESH_TOKEN)));
account.setSensitive(c.getInt(c.getColumnIndex(Sqlite.COL_SENSITIVE)) == 1);
account.setPrivacy((c.getString(c.getColumnIndex(Sqlite.COL_PRIVACY))));
//Close the cursor
c.close();
//User is returned
return account;
}
/***
* Method to hydrate an Accounts from database
* @param c Cursor
* @return List<Account>
*/
private List<Account> cursorToListUser(Cursor c) {
//No element found
if (c.getCount() == 0) {
c.close();
return null;
}
List<Account> accounts = new ArrayList<>();
while (c.moveToNext()) {
//New user
Account account = new Account();
account.setId(c.getString(c.getColumnIndex(Sqlite.COL_USER_ID)));
account.setUsername(c.getString(c.getColumnIndex(Sqlite.COL_USERNAME)));
account.setAcct(c.getString(c.getColumnIndex(Sqlite.COL_ACCT)));
account.setDisplay_name(c.getString(c.getColumnIndex(Sqlite.COL_DISPLAYED_NAME)));
account.setLocked(c.getInt(c.getColumnIndex(Sqlite.COL_LOCKED)) == 1);
account.setFollowers_count(c.getInt(c.getColumnIndex(Sqlite.COL_FOLLOWERS_COUNT)));
account.setFollowing_count(c.getInt(c.getColumnIndex(Sqlite.COL_FOLLOWING_COUNT)));
account.setStatuses_count(c.getInt(c.getColumnIndex(Sqlite.COL_STATUSES_COUNT)));
account.setNote(c.getString(c.getColumnIndex(Sqlite.COL_NOTE)));
account.setUrl(c.getString(c.getColumnIndex(Sqlite.COL_URL)));
account.setAvatar(c.getString(c.getColumnIndex(Sqlite.COL_AVATAR)));
account.setAvatar_static(c.getString(c.getColumnIndex(Sqlite.COL_AVATAR_STATIC)));
account.setHeader(c.getString(c.getColumnIndex(Sqlite.COL_HEADER)));
account.setHeader_static(c.getString(c.getColumnIndex(Sqlite.COL_HEADER_STATIC)));
account.setUpdated_at(Helper.stringToDate(context, c.getString(c.getColumnIndex(Sqlite.COL_UPDATED_AT))));
account.setCreated_at(Helper.stringToDate(context, c.getString(c.getColumnIndex(Sqlite.COL_CREATED_AT))));
account.setInstance(c.getString(c.getColumnIndex(Sqlite.COL_INSTANCE)));
account.setToken(c.getString(c.getColumnIndex(Sqlite.COL_OAUTHTOKEN)));
account.setClient_id(c.getString(c.getColumnIndex(Sqlite.COL_CLIENT_ID)));
account.setClient_secret(c.getString(c.getColumnIndex(Sqlite.COL_CLIENT_SECRET)));
account.setRefresh_token(c.getString(c.getColumnIndex(Sqlite.COL_REFRESH_TOKEN)));
account.setSensitive(c.getInt(c.getColumnIndex(Sqlite.COL_SENSITIVE)) == 1);
account.setPrivacy((c.getString(c.getColumnIndex(Sqlite.COL_PRIVACY))));
accounts.add(account);
}
//Close the cursor
c.close();
//Users list is returned
return accounts;
}
}

View File

@ -0,0 +1,130 @@
package app.fedilab.fedilabtube.sqlite;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Peertube;
import app.fedilab.fedilabtube.helper.Helper;
public class PeertubeFavoritesDAO {
public Context context;
private SQLiteDatabase db;
public PeertubeFavoritesDAO(Context context, SQLiteDatabase db) {
//Creation of the DB with tables
this.context = context;
this.db = db;
}
//------- INSERTIONS -------
/**
* Insert a status in database
*
* @param peertube Peertube
* @return boolean
*/
public long insert(Peertube peertube) {
ContentValues values = new ContentValues();
values.put(Sqlite.COL_UUID, peertube.getUuid());
values.put(Sqlite.COL_INSTANCE, peertube.getInstance());
values.put(Sqlite.COL_DATE, Helper.dateToString(new Date()));
values.put(Sqlite.COL_CACHE, peertube.getCache().toString());
//Inserts cached peertube
long last_id;
try {
last_id = db.insert(Sqlite.TABLE_PEERTUBE_FAVOURITES, null, values);
} catch (Exception e) {
last_id = -1;
}
return last_id;
}
//------- REMOVE -------
/***
* Remove stored status
* @return int
*/
public int remove(Peertube peertube) {
return db.delete(Sqlite.TABLE_PEERTUBE_FAVOURITES, Sqlite.COL_UUID + " = \"" + peertube.getUuid() + "\" AND " + Sqlite.COL_INSTANCE + " = \"" + peertube.getInstance() + "\"", null);
}
/***
* Remove stored status
* @return int
*/
public int removeAll() {
return db.delete(Sqlite.TABLE_PEERTUBE_FAVOURITES, null, null);
}
//------- GETTERS -------
/**
* Returns all cached Peertube
*
* @return stored peertube List<Peertube>
*/
public List<Peertube> getAllPeertube() {
try {
Cursor c = db.query(Sqlite.TABLE_PEERTUBE_FAVOURITES, null, null, null, null, null, Sqlite.COL_DATE + " DESC");
return cursorToListPeertube(c);
} catch (Exception e) {
return null;
}
}
/**
* Returns a cached Peertube
*
* @return stored peertube List<Peertube>
*/
public List<Peertube> getSinglePeertube(Peertube peertube) {
try {
Cursor c = db.query(Sqlite.TABLE_PEERTUBE_FAVOURITES, null, Sqlite.COL_UUID + " = \"" + peertube.getUuid() + "\" AND " + Sqlite.COL_INSTANCE + " = \"" + peertube.getInstance() + "\"", null, null, null, Sqlite.COL_DATE + " DESC");
return cursorToListPeertube(c);
} catch (Exception e) {
return null;
}
}
/***
* Method to hydrate cached statuses from database
* @param c Cursor
* @return List<Peertube>
*/
private List<Peertube> cursorToListPeertube(Cursor c) {
//No element found
if (c.getCount() == 0) {
c.close();
return null;
}
List<Peertube> peertubes = new ArrayList<>();
while (c.moveToNext()) {
//Restore cached status
try {
Peertube peertube = PeertubeAPI.parsePeertube( new JSONObject(c.getString(c.getColumnIndex(Sqlite.COL_CACHE))));
peertubes.add(peertube);
} catch (JSONException e) {
e.printStackTrace();
}
}
//Close the cursor
c.close();
//Peertubes list is returned
return peertubes;
}
}

View File

@ -0,0 +1,125 @@
package app.fedilab.fedilabtube.sqlite;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class Sqlite extends SQLiteOpenHelper {
public static final int DB_VERSION = 1;
public static final String DB_NAME = "mastodon_etalab_db";
/***
* List of tables to manage users and data
*/
//Table of owned accounts
static final String TABLE_USER_ACCOUNT = "USER_ACCOUNT";
static final String COL_USER_ID = "USER_ID";
static final String COL_USERNAME = "USERNAME";
static final String COL_ACCT = "ACCT";
static final String COL_DISPLAYED_NAME = "DISPLAYED_NAME";
static final String COL_LOCKED = "LOCKED";
static final String COL_CREATED_AT = "CREATED_AT";
static final String COL_FOLLOWERS_COUNT = "FOLLOWERS_COUNT";
static final String COL_FOLLOWING_COUNT = "FOLLOWING_COUNT";
static final String COL_STATUSES_COUNT = "STATUSES_COUNT";
static final String COL_NOTE = "NOTE";
static final String COL_URL = "URL";
static final String COL_AVATAR = "AVATAR";
static final String COL_AVATAR_STATIC = "AVATAR_STATIC";
static final String COL_HEADER = "HEADER";
static final String COL_HEADER_STATIC = "HEADER_STATIC";
static final String COL_INSTANCE = "INSTANCE";
static final String COL_OAUTHTOKEN = "OAUTH_TOKEN";
static final String COL_CLIENT_ID = "CLIENT_ID";
static final String COL_CLIENT_SECRET = "CLIENT_SECRET";
static final String COL_REFRESH_TOKEN = "REFRESH_TOKEN";
static final String COL_IS_MODERATOR = "IS_MODERATOR";
static final String COL_IS_ADMIN = "IS_ADMIN";
static final String COL_UPDATED_AT = "UPDATED_AT";
static final String COL_PRIVACY = "PRIVACY";
static final String COL_SENSITIVE = "SENSITIVE";
private static final String CREATE_TABLE_USER_ACCOUNT = "CREATE TABLE " + TABLE_USER_ACCOUNT + " ("
+ COL_USER_ID + " TEXT, " + COL_USERNAME + " TEXT NOT NULL, " + COL_ACCT + " TEXT NOT NULL, "
+ COL_DISPLAYED_NAME + " TEXT NOT NULL, " + COL_LOCKED + " INTEGER NOT NULL, "
+ COL_FOLLOWERS_COUNT + " INTEGER NOT NULL, " + COL_FOLLOWING_COUNT + " INTEGER NOT NULL, " + COL_STATUSES_COUNT + " INTEGER NOT NULL, "
+ COL_NOTE + " TEXT NOT NULL, " + COL_URL + " TEXT NOT NULL, "
+ COL_AVATAR + " TEXT NOT NULL, " + COL_AVATAR_STATIC + " TEXT NOT NULL, "
+ COL_HEADER + " TEXT NOT NULL, " + COL_HEADER_STATIC + " TEXT NOT NULL, "
+ COL_IS_MODERATOR + " INTEGER DEFAULT 0, "
+ COL_IS_ADMIN + " INTEGER DEFAULT 0, "
+ COL_CLIENT_ID + " TEXT, " + COL_CLIENT_SECRET + " TEXT, " + COL_REFRESH_TOKEN + " TEXT,"
+ COL_UPDATED_AT + " TEXT, "
+ COL_PRIVACY + " TEXT, "
+ COL_SENSITIVE + " INTEGER DEFAULT 0, "
+ COL_INSTANCE + " TEXT NOT NULL, " + COL_OAUTHTOKEN + " TEXT NOT NULL, " + COL_CREATED_AT + " TEXT NOT NULL)";
//Table for peertube favorites
static final String TABLE_PEERTUBE_FAVOURITES = "PEERTUBE_FAVOURITES";
static final String COL_ID = "ID";
static final String COL_UUID = "UUID";
static final String COL_CACHE = "CACHE";
static final String COL_DATE = "DATE";
private final String CREATE_TABLE_PEERTUBE_FAVOURITES = "CREATE TABLE "
+ TABLE_PEERTUBE_FAVOURITES + "("
+ COL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ COL_UUID + " TEXT NOT NULL, "
+ COL_INSTANCE + " TEXT NOT NULL, "
+ COL_CACHE + " TEXT NOT NULL, "
+ COL_DATE + " TEXT NOT NULL)";
public static SQLiteDatabase db;
private static Sqlite sInstance;
public Sqlite(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
public static synchronized Sqlite getInstance(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
if (sInstance == null) {
sInstance = new Sqlite(context, name, factory, version);
}
return sInstance;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE_USER_ACCOUNT);
db.execSQL(CREATE_TABLE_PEERTUBE_FAVOURITES);
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1:
}
}
public SQLiteDatabase open() {
//opened with write access
db = getWritableDatabase();
return db;
}
public void close() {
//Close the db
if (db != null && db.isOpen()) {
db.close();
}
}
}

View File

@ -0,0 +1,160 @@
package app.fedilab.fedilabtube.ui.video;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import app.fedilab.fedilabtube.PeertubeActivity;
import app.fedilab.fedilabtube.PeertubeEditUploadActivity;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.client.APIResponse;
import app.fedilab.fedilabtube.client.entities.Account;
import app.fedilab.fedilabtube.client.entities.Peertube;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.interfaces.OnActionInterface;
public class PeertubeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements OnActionInterface {
private List<Peertube> peertubes;
private Context context;
private String instance;
public PeertubeAdapter(String instance, List<Peertube> peertubes) {
this.peertubes = peertubes;
this.instance = instance;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
LayoutInflater layoutInflater = LayoutInflater.from(context);
return new ViewHolder(layoutInflater.inflate(R.layout.drawer_peertube, parent, false));
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
final PeertubeAdapter.ViewHolder holder = (PeertubeAdapter.ViewHolder) viewHolder;
final Peertube peertube = peertubes.get(position);
if (peertube.getInstance() == null)
peertube.setInstance(Helper.getLiveInstance(context));
Account account = peertube.getAccount();
holder.peertube_account_name.setText(account.getAcct());
holder.peertube_title.setText(peertube.getName());
holder.peertube_duration.setText(context.getString(R.string.duration_video, Helper.secondsToString(peertube.getDuration())));
holder.peertube_date.setText(String.format(" - %s", Helper.dateDiff(context, peertube.getCreated_at())));
holder.peertube_views.setText(context.getString(R.string.number_view_video, Helper.withSuffix(peertube.getView())));
Glide.with(holder.peertube_video_image.getContext())
.load("https://" + peertube.getInstance() + peertube.getThumbnailPath())
.into(holder.peertube_video_image);
if (account.getAvatar() != null && !account.getAvatar().equals("null") && !account.getAvatar().startsWith("http")) {
account.setAvatar("https://" + peertube.getInstance() + account.getAvatar());
account.setAvatar_static(account.getAvatar());
}
Helper.loadGiF(context, account, holder.peertube_profile);
if (peertube.getHeaderType() != null && peertube.getHeaderTypeValue() != null) {
String type = peertube.getHeaderType();
if ("tags".equals(type)) {
holder.header_title.setText(String.format("#%s", peertube.getHeaderTypeValue()));
} else {
holder.header_title.setText(peertube.getHeaderTypeValue());
}
holder.header_title.setVisibility(View.VISIBLE);
} else {
holder.header_title.setVisibility(View.GONE);
}
holder.bottom_container.setOnClickListener(v -> {
Intent intent = new Intent(context, PeertubeEditUploadActivity.class);
Bundle b = new Bundle();
b.putString("video_id", peertube.getUuid());
intent.putExtras(b);
context.startActivity(intent);
});
holder.peertube_video_image.setOnClickListener(v -> {
Intent intent = new Intent(context, PeertubeActivity.class);
Bundle b = new Bundle();
if ((instance == null || instance.trim().length() == 0) )
instance = Helper.getLiveInstance(context);
String finalUrl = "https://" + instance + peertube.getEmbedPath();
Pattern link = Pattern.compile("(https?://[\\da-z.-]+\\.[a-z.]{2,10})/videos/embed/(\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12})$");
Matcher matcherLink = link.matcher(finalUrl);
if (matcherLink.find()) {
String url = matcherLink.group(1) + "/videos/watch/" + matcherLink.group(2);
b.putString("peertubeLinkToFetch", url);
b.putString("peertube_instance", Objects.requireNonNull(matcherLink.group(1)).replace("https://", "").replace("http://", ""));
b.putString("video_id", matcherLink.group(2));
}
intent.putExtras(b);
context.startActivity(intent);
});
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemCount() {
return peertubes.size();
}
@Override
public void onActionDone(APIResponse apiResponse, int statusCode) {
}
static class ViewHolder extends RecyclerView.ViewHolder {
LinearLayout main_container, bottom_container;
ImageView peertube_profile, peertube_video_image;
TextView peertube_account_name, peertube_views, peertube_duration;
TextView peertube_title, peertube_date, header_title;
public ViewHolder(@NonNull View itemView) {
super(itemView);
peertube_account_name = itemView.findViewById(R.id.peertube_account_name);
peertube_title = itemView.findViewById(R.id.peertube_title);
peertube_video_image = itemView.findViewById(R.id.peertube_video_image);
peertube_profile = itemView.findViewById(R.id.peertube_profile);
peertube_date = itemView.findViewById(R.id.peertube_date);
peertube_views = itemView.findViewById(R.id.peertube_views);
peertube_duration = itemView.findViewById(R.id.peertube_duration);
main_container = itemView.findViewById(R.id.main_container);
header_title = itemView.findViewById(R.id.header_title);
bottom_container = itemView.findViewById(R.id.bottom_container);
}
}
}

View File

@ -1,9 +1,15 @@
package app.fedilab.fedilabtube.ui.video;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
@ -11,19 +17,65 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.asynctasks.RetrieveFeedsAsyncTask;
import app.fedilab.fedilabtube.client.entities.Peertube;
public class VideoListFragment extends Fragment {
private VideoListModel videoListModel;
private LinearLayoutManager mLayoutManager;
private boolean flag_loading;
private Context context;
private AsyncTask<Void, Void, Void> asyncTask;
private PeertubeAdapter peertubeAdapater;
private String max_id;
private List<Peertube> peertubes;
private RetrieveFeedsAsyncTask.Type type;
private RelativeLayout mainLoader, nextElementLoader, textviewNoAction;
private boolean firstLoad;
private SwipeRefreshLayout swipeRefreshLayout;
private String targetedId;
private String tag;
private RecyclerView lv_status;
private boolean showMediaOnly, showPinned, showReply;
private Intent streamingFederatedIntent, streamingLocalIntent;
private boolean firstTootsLoaded;
private String userId, instance;
private SharedPreferences sharedpreferences;
private boolean isSwipped;
private String remoteInstance;
private String instanceType;
private String search_peertube, remote_channel_name;
private String initialBookMark;
private String updatedBookMark;
private String lastReadToot;
private TextView textviewNoActionText;
private boolean ischannel;
private boolean ownVideos;
private BroadcastReceiver receive_action;
private BroadcastReceiver receive_data;
private Date lastReadTootDate, initialBookMarkDate, updatedBookMarkDate;
private int timelineId;
private String currentfilter;
private View rootView;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
videoListModel =
ViewModelProviders.of(this).get(VideoListModel.class);
View root = inflater.inflate(R.layout.fragment_video, container, false);
final TextView textView = root.findViewById(R.id.text_home);
peertubes = new ArrayList<>();
videoListModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {

View File

@ -0,0 +1,42 @@
package app.fedilab.fedilabtube.webview;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import android.util.AttributeSet;
import android.webkit.WebView;
public class CustomWebview extends WebView {
public CustomWebview(Context context) {
super(getFixedContext(context));
}
public CustomWebview(Context context, AttributeSet attrs) {
super(getFixedContext(context), attrs);
}
public CustomWebview(Context context, AttributeSet attrs, int defStyleAttr) {
super(getFixedContext(context), attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public CustomWebview(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(getFixedContext(context), attrs, defStyleAttr, defStyleRes);
}
@SuppressWarnings("deprecation")
public CustomWebview(Context context, AttributeSet attrs, int defStyleAttr, boolean privateBrowsing) {
super(getFixedContext(context), attrs, defStyleAttr, privateBrowsing);
}
public static Context getFixedContext(Context context) {
return context.createConfigurationContext(new Configuration());
}
}

View File

@ -0,0 +1,217 @@
package app.fedilab.fedilabtube.webview;
import android.app.Activity;
import android.graphics.Bitmap;
import android.media.MediaPlayer;
import android.view.LayoutInflater;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import app.fedilab.fedilabtube.R;
public class MastalabWebChromeClient extends WebChromeClient implements MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener {
private FrameLayout videoViewContainer;
private CustomViewCallback videoViewCallback;
private ToggledFullscreenCallback toggledFullscreenCallback;
private CustomWebview webView;
private View activityNonVideoView;
private ViewGroup activityVideoView;
private ProgressBar pbar;
private boolean isVideoFullscreen;
private Activity activity;
public MastalabWebChromeClient(Activity activity, CustomWebview webView, FrameLayout activityNonVideoView, ViewGroup activityVideoView) {
this.activity = activity;
this.isVideoFullscreen = false;
this.webView = webView;
this.pbar = activity.findViewById(R.id.progress_bar);
this.activityNonVideoView = activityNonVideoView;
this.activityVideoView = activityVideoView;
}
@Override
public void onProgressChanged(WebView view, int progress) {
if (pbar != null) {
if (progress < 100 && pbar.getVisibility() == ProgressBar.GONE) {
pbar.setVisibility(ProgressBar.VISIBLE);
}
pbar.setProgress(progress);
if (progress == 100) {
pbar.setVisibility(ProgressBar.GONE);
}
}
}
@Override
public Bitmap getDefaultVideoPoster() {
return Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888);
}
@Override
public void onReceivedIcon(WebView view, Bitmap icon) {
super.onReceivedIcon(view, icon);
LayoutInflater mInflater = LayoutInflater.from(activity);
ActionBar actionBar = ((AppCompatActivity) activity).getSupportActionBar();
if (actionBar != null) {
View webview_actionbar = mInflater.inflate(R.layout.webview_actionbar, new LinearLayout(activity), false);
TextView webview_title = webview_actionbar.findViewById(R.id.webview_title);
webview_title.setText(view.getTitle());
ImageView webview_favicon = webview_actionbar.findViewById(R.id.webview_favicon);
if (icon != null)
webview_favicon.setImageBitmap(icon);
actionBar.setCustomView(webview_actionbar);
actionBar.setDisplayShowCustomEnabled(true);
} else {
activity.setTitle(view.getTitle());
}
}
/**
* Set a callback that will be fired when the video starts or finishes displaying using a custom view (typically full-screen)
*
* @param callback A VideoEnabledWebChromeClient.ToggledFullscreenCallback callback
*/
public void setOnToggledFullscreen(ToggledFullscreenCallback callback) {
this.toggledFullscreenCallback = callback;
}
//FULLSCREEN VIDEO
//Code from https://stackoverflow.com/a/16179544/3197259
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
if (view instanceof FrameLayout) {
if (((AppCompatActivity) activity).getSupportActionBar() != null)
//noinspection ConstantConditions
((AppCompatActivity) activity).getSupportActionBar().hide();
// A video wants to be shown
FrameLayout frameLayout = (FrameLayout) view;
View focusedChild = frameLayout.getFocusedChild();
// Save video related variables
isVideoFullscreen = true;
this.videoViewContainer = frameLayout;
this.videoViewCallback = callback;
// Hide the non-video view, add the video view, and show it
activityNonVideoView.setVisibility(View.INVISIBLE);
activityVideoView.addView(videoViewContainer, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
activityVideoView.setVisibility(View.VISIBLE);
if (focusedChild instanceof android.widget.VideoView) {
// android.widget.VideoView (typically API level <11)
android.widget.VideoView videoView = (android.widget.VideoView) focusedChild;
// Handle all the required events
videoView.setOnCompletionListener(this);
videoView.setOnErrorListener(this);
} else {
// Other classes, including:
// - android.webkit.HTML5VideoFullScreen$VideoSurfaceView, which inherits from android.view.SurfaceView (typically API level 11-18)
// - android.webkit.HTML5VideoFullScreen$VideoTextureView, which inherits from android.view.TextureView (typically API level 11-18)
// - com.android.org.chromium.content.browser.ContentVideoView$VideoSurfaceView, which inherits from android.view.SurfaceView (typically API level 19+)
// Handle HTML5 video ended event only if the class is a SurfaceView
// Test case: TextureView of Sony Xperia T API level 16 doesn't work fullscreen when loading the javascript below
if (webView != null && webView.getSettings().getJavaScriptEnabled() && focusedChild instanceof SurfaceView) {
// Run javascript code that detects the video end and notifies the Javascript interface
String js = "javascript:";
js += "var _ytrp_html5_video_last;";
js += "var _ytrp_html5_video = document.getElementsByTagName('video')[0];";
js += "if (_ytrp_html5_video != undefined && _ytrp_html5_video != _ytrp_html5_video_last) {";
{
js += "_ytrp_html5_video_last = _ytrp_html5_video;";
js += "function _ytrp_html5_video_ended() {";
{
js += "_VideoEnabledWebView.notifyVideoEnd();"; // Must match Javascript interface name and method of VideoEnableWebView
}
js += "}";
js += "_ytrp_html5_video.addEventListener('ended', _ytrp_html5_video_ended);";
}
js += "}";
webView.loadUrl(js);
}
}
// Notify full-screen change
if (toggledFullscreenCallback != null) {
toggledFullscreenCallback.toggledFullscreen(true);
}
}
}
// Available in API level 14+, deprecated in API level 18+
@Override
@SuppressWarnings("deprecation")
public void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback) {
onShowCustomView(view, callback);
}
@Override
public void onHideCustomView() {
if (((AppCompatActivity) activity).getSupportActionBar() != null)
//noinspection ConstantConditions
((AppCompatActivity) activity).getSupportActionBar().show();
// This method should be manually called on video end in all cases because it's not always called automatically.
// This method must be manually called on back key press (from this class' onBackPressed() method).
if (isVideoFullscreen) {
// Hide the video view, remove it, and show the non-video view
activityVideoView.setVisibility(View.INVISIBLE);
activityVideoView.removeView(videoViewContainer);
activityNonVideoView.setVisibility(View.VISIBLE);
// Call back (only in API level <19, because in API level 19+ with chromium webview it crashes)
if (videoViewCallback != null && !videoViewCallback.getClass().getName().contains(".chromium.")) {
videoViewCallback.onCustomViewHidden();
}
// Reset video related variables
isVideoFullscreen = false;
videoViewContainer = null;
videoViewCallback = null;
// Notify full-screen change
if (toggledFullscreenCallback != null) {
toggledFullscreenCallback.toggledFullscreen(false);
}
}
}
// Video will start loading
@Override
public View getVideoLoadingProgressView() {
return super.getVideoLoadingProgressView();
}
// Video finished playing, only called in the case of android.widget.VideoView (typically API level <11)
@Override
public void onCompletion(MediaPlayer mp) {
onHideCustomView();
}
// Error while playing video, only called in the case of android.widget.VideoView (typically API level <11)
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
return false; // By returning false, onCompletion() will be called
}
public interface ToggledFullscreenCallback {
void toggledFullscreen(boolean fullscreen);
}
}

View File

@ -0,0 +1,76 @@
package app.fedilab.fedilabtube.webview;
import android.app.Activity;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.URLUtil;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;
import app.fedilab.fedilabtube.R;
public class MastalabWebViewClient extends WebViewClient {
public List<String> domains = new ArrayList<>();
private Activity activity;
private int count = 0;
public MastalabWebViewClient(Activity activity) {
this.activity = activity;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
public List<String> getDomains() {
return this.domains;
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (URLUtil.isNetworkUrl(url)) {
return false;
} else {
view.stopLoading();
view.goBack();
}
return false;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
count = 0;
domains = new ArrayList<>();
domains.clear();
ActionBar actionBar = ((AppCompatActivity) activity).getSupportActionBar();
LayoutInflater mInflater = LayoutInflater.from(activity);
if (actionBar != null) {
View webview_actionbar = mInflater.inflate(R.layout.webview_actionbar, new LinearLayout(activity), false);
TextView webview_title = webview_actionbar.findViewById(R.id.webview_title);
webview_title.setText(url);
actionBar.setCustomView(webview_actionbar);
actionBar.setDisplayShowCustomEnabled(true);
} else {
activity.setTitle(url);
}
}
}

View File

@ -0,0 +1,153 @@
package app.fedilab.fedilabtube.webview;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.net.Proxy;
import android.util.ArrayMap;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ProxyHelper {
public static void setProxy(Context context, CustomWebview webview, String host, int port, String applicationClassName) {
setProxyKKPlus(context, webview, host, port, applicationClassName);
}
@SuppressWarnings("all")
private static boolean setProxyICS(CustomWebview webview, String host, int port) {
try {
Class jwcjb = Class.forName("android.webkit.JWebCoreJavaBridge");
Class params[] = new Class[1];
params[0] = Class.forName("android.net.ProxyProperties");
Method updateProxyInstance = jwcjb.getDeclaredMethod("updateProxy", params);
Class wv = Class.forName("android.webkit.WebView");
Field mWebViewCoreField = wv.getDeclaredField("mWebViewCore");
Object mWebViewCoreFieldInstance = getFieldValueSafely(mWebViewCoreField, webview);
Class wvc = Class.forName("android.webkit.WebViewCore");
Field mBrowserFrameField = wvc.getDeclaredField("mBrowserFrame");
Object mBrowserFrame = getFieldValueSafely(mBrowserFrameField, mWebViewCoreFieldInstance);
Class bf = Class.forName("android.webkit.BrowserFrame");
Field sJavaBridgeField = bf.getDeclaredField("sJavaBridge");
Object sJavaBridge = getFieldValueSafely(sJavaBridgeField, mBrowserFrame);
Class ppclass = Class.forName("android.net.ProxyProperties");
Class pparams[] = new Class[3];
pparams[0] = String.class;
pparams[1] = int.class;
pparams[2] = String.class;
Constructor ppcont = ppclass.getConstructor(pparams);
updateProxyInstance.invoke(sJavaBridge, ppcont.newInstance(host, port, null));
return true;
} catch (Exception ex) {
return false;
}
}
/**
* Set Proxy for Android 4.1 - 4.3.
*/
@SuppressWarnings("all")
private static boolean setProxyJB(CustomWebview webview, String host, int port) {
try {
Class wvcClass = Class.forName("android.webkit.WebViewClassic");
Class wvParams[] = new Class[1];
wvParams[0] = Class.forName("android.webkit.WebView");
Method fromWebView = wvcClass.getDeclaredMethod("fromWebView", wvParams);
Object webViewClassic = fromWebView.invoke(null, webview);
Class wv = Class.forName("android.webkit.WebViewClassic");
Field mWebViewCoreField = wv.getDeclaredField("mWebViewCore");
Object mWebViewCoreFieldInstance = getFieldValueSafely(mWebViewCoreField, webViewClassic);
Class wvc = Class.forName("android.webkit.WebViewCore");
Field mBrowserFrameField = wvc.getDeclaredField("mBrowserFrame");
Object mBrowserFrame = getFieldValueSafely(mBrowserFrameField, mWebViewCoreFieldInstance);
Class bf = Class.forName("android.webkit.BrowserFrame");
Field sJavaBridgeField = bf.getDeclaredField("sJavaBridge");
Object sJavaBridge = getFieldValueSafely(sJavaBridgeField, mBrowserFrame);
Class ppclass = Class.forName("android.net.ProxyProperties");
Class pparams[] = new Class[3];
pparams[0] = String.class;
pparams[1] = int.class;
pparams[2] = String.class;
Constructor ppcont = ppclass.getConstructor(pparams);
Class jwcjb = Class.forName("android.webkit.JWebCoreJavaBridge");
Class params[] = new Class[1];
params[0] = Class.forName("android.net.ProxyProperties");
Method updateProxyInstance = jwcjb.getDeclaredMethod("updateProxy", params);
updateProxyInstance.invoke(sJavaBridge, ppcont.newInstance(host, port, null));
} catch (Exception ex) {
return false;
}
return true;
}
// from https://stackoverflow.com/questions/19979578/android-webview-set-proxy-programatically-kitkat
@SuppressLint("NewApi")
@SuppressWarnings("all")
private static void setProxyKKPlus(Context appContext, CustomWebview webView, String host, int port, String applicationClassName) {
System.setProperty("http.proxyHost", host);
System.setProperty("http.proxyPort", port + "");
System.setProperty("https.proxyHost", host);
System.setProperty("https.proxyPort", port + "");
try {
Class applictionCls = Class.forName("android.app.Application");
Field loadedApkField = applictionCls.getDeclaredField("mLoadedApk");
loadedApkField.setAccessible(true);
Object loadedApk = loadedApkField.get(appContext);
Class loadedApkCls = Class.forName("android.app.LoadedApk");
Field receiversField = loadedApkCls.getDeclaredField("mReceivers");
receiversField.setAccessible(true);
ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
for (Object receiverMap : receivers.values()) {
for (Object rec : ((ArrayMap) receiverMap).keySet()) {
Class clazz = rec.getClass();
if (clazz.getName().contains("ProxyChangeListener")) {
Method onReceiveMethod = clazz.getDeclaredMethod("onReceive", Context.class, Intent.class);
Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
onReceiveMethod.invoke(rec, appContext, intent);
}
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
private static Object getFieldValueSafely(Field field, Object classInstance) throws IllegalArgumentException, IllegalAccessException {
boolean oldAccessibleValue = field.isAccessible();
field.setAccessible(true);
Object result = field.get(classInstance);
field.setAccessible(oldAccessibleValue);
return result;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="?android:dividerHorizontal"
android:orientation="vertical"
android:showDividers="end">
<TextView
android:id="@+id/header_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:background="?colorAccent"
android:gravity="center"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:textSize="18sp"
android:textStyle="bold"
android:visibility="gone" />
<ImageView
android:id="@+id/peertube_video_image"
android:layout_width="match_parent"
android:layout_height="200dp"
android:contentDescription="@string/image_preview"
android:gravity="center"
android:scaleType="centerCrop" />
<LinearLayout
android:id="@+id/bottom_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/peertube_profile"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="10dp"
android:contentDescription="@string/profile_picture"
android:gravity="center"
android:scaleType="fitCenter" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:orientation="vertical">
<TextView
android:id="@+id/peertube_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textColor="?colorAccent"
android:textStyle="bold" />
<TextView
android:id="@+id/peertube_account_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/peertube_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/peertube_views"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp" />
<TextView
android:id="@+id/peertube_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/card_status_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:divider="?android:dividerHorizontal"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingTop="10dp"
android:showDividers="end">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/peertube_notif_pp"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="top" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/peertube_notif_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="end"
android:textAlignment="viewEnd" />
<TextView
android:id="@+id/peertube_notif_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
android:autoLink="web" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<RelativeLayout
android:id="@+id/container_trans"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:visibility="gone" />
</FrameLayout>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/fab_margin"
android:paddingRight="@dimen/fab_margin">
<!-- Listview Peertube bookmark -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/lv_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none" />
<RelativeLayout
android:id="@+id/no_action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:padding="10dp"
android:text="@string/bookmark_peertube_empty"
android:textSize="25sp"
android:textStyle="italic|bold"
android:typeface="serif" />
</RelativeLayout>
<!-- Main Loader -->
<RelativeLayout
android:id="@+id/loader"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true" />
</RelativeLayout>
</RelativeLayout>

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/swipeContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/fab_margin"
android:layout_marginLeft="@dimen/fab_margin"
android:layout_marginEnd="@dimen/fab_margin"
android:layout_marginRight="@dimen/fab_margin"
android:paddingLeft="@dimen/drawer_padding"
android:paddingRight="@dimen/drawer_padding">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingLeft="@dimen/fab_margin"
android:paddingRight="@dimen/fab_margin"
tools:ignore="UselessParent">
<!-- Choose stream -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/set_video_mode" />
<Spinner
android:id="@+id/set_video_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<!-- DISPLAY NSFW VIDEOS -->
<CheckBox
android:id="@+id/set_video_nsfw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/display_nsfw_videos" />
</LinearLayout>
</ScrollView>

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/fab_margin"
android:paddingRight="@dimen/fab_margin">
<!-- Listview list -->
<ListView
android:id="@+id/lv_playlist"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@null"
android:scrollbars="none" />
<RelativeLayout
android:id="@+id/no_action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<TextView
android:id="@+id/no_action_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:padding="10dp"
android:text="@string/action_playlist_add"
android:textSize="25sp"
android:textStyle="italic|bold"
android:typeface="serif" />
</RelativeLayout>
<!-- Main Loader -->
<RelativeLayout
android:id="@+id/loader"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true" />
</RelativeLayout>
<!-- Loader for next items -->
<RelativeLayout
android:id="@+id/loading_next_items"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_alignParentBottom="true"
android:layout_gravity="bottom|center_horizontal"
android:gravity="bottom|center_horizontal"
android:visibility="gone">
<ProgressBar
android:layout_width="match_parent"
android:layout_height="match_parent"
android:indeterminate="true" />
</RelativeLayout>
</RelativeLayout>

View File

@ -1,22 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.video.VideoListFragment">
<TextView
android:id="@+id/text_home"
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipeContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/lv_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</FrameLayout>
<RelativeLayout
android:id="@+id/no_action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<TextView
android:id="@+id/no_action_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:padding="10dp"
android:text="@string/no_videos"
android:textSize="25sp"
android:textStyle="italic|bold"
android:typeface="serif" />
</RelativeLayout>
<!-- Main Loader -->
<RelativeLayout
android:id="@+id/loader"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true" />
</RelativeLayout>
<!-- Loader for next status -->
<RelativeLayout
android:id="@+id/loading_next_status"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_alignParentBottom="true"
android:layout_gravity="bottom|center_horizontal"
android:gravity="bottom|center_horizontal"
android:visibility="gone">
<ProgressBar
android:layout_width="match_parent"
android:layout_height="match_parent"
android:indeterminate="true" />
</RelativeLayout>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -2,4 +2,5 @@
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="fab_margin">5dp</dimen>
</resources>

View File

@ -8,4 +8,25 @@
<string name="title_trending">Tendances</string>
<string name="title_account">Compte</string>
<string name="title_most_liked">Plus aimées</string>
<string name="toast_error">Une erreur s\'est produite !</string>
<string name="no_videos">Aucune vidéo !</string>
<string name="favicon">Favicon</string>
<string name="close">Fermer</string>
<string name="upload_video">Téléverser</string>
<string name="bookmark_peertube_empty">Il ny a aucune vidéo Peertube dans vos favoris !</string>
<string name="image_preview">Aperçu de l\'image</string>
<string name="file_to_upload">Sélectionnez un fichier à transférer</string>
<string name="channel">Chaîne</string>
<string name="videos">Vidéos</string>
<string name="channels">Chaînes</string>
<string name="profile_picture">Photo du profil</string>
<!-- Date -->
<string name="date_seconds">%d s</string>
<string name="date_minutes">%d min</string>
<string name="date_hours">%d h</string>
<string name="date_day">%d j</string>
<string name="number_view_video">%s vues</string>
<string name="duration_video">Durée : %s</string>
</resources>