diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6f13d98..4edaeac 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -52,7 +52,7 @@ android:windowSoftInputMode="stateAlwaysHidden" /> diff --git a/app/src/main/java/app/fedilab/fedilabtube/LoginActivity.java b/app/src/main/java/app/fedilab/fedilabtube/LoginActivity.java index 11f08a6..eed7189 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/LoginActivity.java +++ b/app/src/main/java/app/fedilab/fedilabtube/LoginActivity.java @@ -35,19 +35,20 @@ import androidx.core.content.ContextCompat; import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputLayout; -import org.json.JSONException; import org.json.JSONObject; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Arrays; -import java.util.HashMap; -import app.fedilab.fedilabtube.client.HttpsConnection; +import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; +import app.fedilab.fedilabtube.client.entities.Oauth; +import app.fedilab.fedilabtube.client.entities.OauthParams; +import app.fedilab.fedilabtube.client.entities.RefreshToken; import app.fedilab.fedilabtube.helper.Helper; import es.dmoral.toasty.Toasty; -import static app.fedilab.fedilabtube.client.HttpsConnection.updateCredential; +import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.updateCredential; public class LoginActivity extends AppCompatActivity { @@ -55,8 +56,6 @@ public class LoginActivity extends AppCompatActivity { //Peertube notification type public static int NEW_VIDEO_FROM_SUBSCRIPTION = 1; - // public static int NEW_COMMENT_ON_MY_VIDEO = 2; - // public static int NEW_VIDEO_ABUSE_FOR_MODERATORS = 3; public static int BLACKLIST_ON_MY_VIDEO = 4; public static int UNBLACKLIST_ON_MY_VIDEO = 5; public static int MY_VIDEO_PUBLISHED = 6; @@ -67,7 +66,6 @@ public class LoginActivity extends AppCompatActivity { private EditText login_uid; private EditText login_passwd; private Button connectionButton; - private String actionToken; private TextInputEditText login_instance; @Override @@ -139,10 +137,7 @@ public class LoginActivity extends AppCompatActivity { Toasty.error(LoginActivity.this, getString(R.string.email_error)).show(); return; } - - connectionButton.setEnabled(false); - final HashMap parameters = new HashMap<>(); String instance, host; if (!BuildConfig.full_instances) { String[] emailArray = login_uid.getText().toString().split("@"); @@ -164,27 +159,21 @@ public class LoginActivity extends AppCompatActivity { if (Arrays.asList(Helper.openid).contains(host) && !BuildConfig.full_instances) { new Thread(() -> { try { - actionToken = "/api/v1/oauth-clients/local"; - String response = new HttpsConnection(LoginActivity.this).get("https://" + instance + actionToken, 30, null, null); - if (response == null) { + Oauth oauth = new RetrofitPeertubeAPI(LoginActivity.this, instance, null).oauthClient(); + if (oauth == null) { runOnUiThread(() -> { connectionButton.setEnabled(true); Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show(); }); return; } - JSONObject resobj; - resobj = new JSONObject(response); - client_id = resobj.get(Helper.CLIENT_ID).toString(); - client_secret = resobj.get(Helper.CLIENT_SECRET).toString(); + client_id = oauth.getClient_id(); + client_secret = oauth.getClient_secret(); SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putString(Helper.CLIENT_ID, client_id); editor.putString(Helper.CLIENT_SECRET, client_secret); editor.apply(); - parameters.clear(); - parameters.put(Helper.CLIENT_ID, sharedpreferences.getString(Helper.CLIENT_ID, null)); - parameters.put(Helper.CLIENT_SECRET, sharedpreferences.getString(Helper.CLIENT_SECRET, null)); Intent intent = new Intent(LoginActivity.this, WebviewConnectActivity.class); Bundle b = new Bundle(); b.putString("url", "https://" + Helper.getPeertubeUrl(host) + "/plugins/auth-openid-connect/0.0.1/auth/openid-connect"); @@ -201,89 +190,65 @@ public class LoginActivity extends AppCompatActivity { }).start(); } else { - parameters.clear(); - parameters.put(Helper.CLIENT_NAME, Helper.CLIENT_NAME_VALUE); - parameters.put(Helper.REDIRECT_URIS, Helper.REDIRECT_CONTENT); - parameters.put(Helper.SCOPES, Helper.OAUTH_SCOPES_PEERTUBE); - parameters.put(Helper.WEBSITE, Helper.WEBSITE_VALUE); new Thread(() -> { try { - actionToken = "/api/v1/oauth-clients/local"; - String response = new HttpsConnection(LoginActivity.this).get("https://" + instance + actionToken, 30, parameters, null); - if (response == null) { + Oauth oauth = new RetrofitPeertubeAPI(LoginActivity.this, instance, null).oauthClient(); + if (oauth == null) { runOnUiThread(() -> { connectionButton.setEnabled(true); Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show(); }); return; } - JSONObject resobj; + + client_id = oauth.getClient_id(); + client_secret = oauth.getClient_secret(); + SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); + SharedPreferences.Editor editor = sharedpreferences.edit(); + editor.putString(Helper.CLIENT_ID, client_id); + editor.putString(Helper.CLIENT_SECRET, client_secret); + editor.apply(); + OauthParams oauthParams = new OauthParams(); + oauthParams.setClient_id(sharedpreferences.getString(Helper.CLIENT_ID, null)); + oauthParams.setClient_secret(sharedpreferences.getString(Helper.CLIENT_SECRET, null)); + oauthParams.setGrant_type("password"); try { - resobj = new JSONObject(response); - client_id = resobj.get(Helper.CLIENT_ID).toString(); - client_secret = resobj.get(Helper.CLIENT_SECRET).toString(); - SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); - SharedPreferences.Editor editor = sharedpreferences.edit(); - editor.putString(Helper.CLIENT_ID, client_id); - editor.putString(Helper.CLIENT_SECRET, client_secret); - editor.apply(); - parameters.clear(); - parameters.put(Helper.CLIENT_ID, sharedpreferences.getString(Helper.CLIENT_ID, null)); - parameters.put(Helper.CLIENT_SECRET, sharedpreferences.getString(Helper.CLIENT_SECRET, null)); - parameters.put("grant_type", "password"); + oauthParams.setUsername(URLEncoder.encode(login_uid.getText().toString().trim(), "UTF-8")); + } catch (UnsupportedEncodingException e) { + oauthParams.setUsername(login_uid.getText().toString().trim()); + } + try { + oauthParams.setPassword(URLEncoder.encode(login_passwd.getText().toString(), "UTF-8")); + } catch (UnsupportedEncodingException e) { + oauthParams.setPassword(login_passwd.getText().toString()); + } + + try { + RefreshToken refreshToken = new RetrofitPeertubeAPI(LoginActivity.this, instance, null).manageToken(oauthParams); + proceedLogin(refreshToken, host); + } catch (final Exception e) { try { - parameters.put("username", URLEncoder.encode(login_uid.getText().toString().trim(), "UTF-8")); - } catch (UnsupportedEncodingException e) { - parameters.put("username", login_uid.getText().toString().trim()); + oauthParams.setUsername(URLEncoder.encode(login_uid.getText().toString().toLowerCase().trim(), "UTF-8")); + } catch (UnsupportedEncodingException e2) { + oauthParams.setUsername(login_uid.getText().toString().toLowerCase().trim()); } try { - parameters.put("password", URLEncoder.encode(login_passwd.getText().toString(), "UTF-8")); - } catch (UnsupportedEncodingException e) { - parameters.put("password", login_passwd.getText().toString()); + RefreshToken refreshToken = new RetrofitPeertubeAPI(LoginActivity.this, instance, null).manageToken(oauthParams); + proceedLogin(refreshToken, host); + } catch (final Exception e2) { + e2.printStackTrace(); + runOnUiThread(() -> { + connectionButton.setEnabled(true); + String message; + if (e2.getLocalizedMessage() != null && e2.getLocalizedMessage().trim().length() > 0) + message = e2.getLocalizedMessage(); + else if (e2.getMessage() != null && e2.getMessage().trim().length() > 0) + message = e2.getMessage(); + else + message = getString(R.string.client_error); + Toasty.error(LoginActivity.this, message, Toast.LENGTH_LONG).show(); + }); } - parameters.put("scope", "user"); - String oauthUrl = "/api/v1/users/token"; - try { - String responseLogin = new HttpsConnection(LoginActivity.this).post("https://" + instance + oauthUrl, 30, parameters, null); - proceedLogin(responseLogin, host); - } catch (final Exception e) { - parameters.clear(); - parameters.put(Helper.CLIENT_ID, sharedpreferences.getString(Helper.CLIENT_ID, null)); - parameters.put(Helper.CLIENT_SECRET, sharedpreferences.getString(Helper.CLIENT_SECRET, null)); - parameters.put("grant_type", "password"); - try { - parameters.put("username", URLEncoder.encode(login_uid.getText().toString().toLowerCase().trim(), "UTF-8")); - } catch (UnsupportedEncodingException e2) { - parameters.put("username", login_uid.getText().toString().toLowerCase().trim()); - } - try { - parameters.put("password", URLEncoder.encode(login_passwd.getText().toString(), "UTF-8")); - } catch (UnsupportedEncodingException e2) { - parameters.put("password", login_passwd.getText().toString()); - } - parameters.put("scope", "user"); - try { - String responseLogin = new HttpsConnection(LoginActivity.this).post("https://" + instance + oauthUrl, 30, parameters, null); - proceedLogin(responseLogin, host); - } catch (final Exception e2) { - e2.printStackTrace(); - runOnUiThread(() -> { - connectionButton.setEnabled(true); - String message; - if (e2.getLocalizedMessage() != null && e2.getLocalizedMessage().trim().length() > 0) - message = e2.getLocalizedMessage(); - else if (e2.getMessage() != null && e2.getMessage().trim().length() > 0) - message = e2.getMessage(); - else - message = getString(R.string.client_error); - Toasty.error(LoginActivity.this, message, Toast.LENGTH_LONG).show(); - }); - } - } - } catch (JSONException e) { - e.printStackTrace(); - e.printStackTrace(); - runOnUiThread(() -> connectionButton.setEnabled(true)); } } catch (final Exception e) { e.printStackTrace(); @@ -305,24 +270,16 @@ public class LoginActivity extends AppCompatActivity { }); } - private void proceedLogin(String responseLogin, String host) { + private void proceedLogin(RefreshToken refreshToken, String host) { runOnUiThread(() -> { JSONObject resobjLogin; - try { - SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); - SharedPreferences.Editor editor = sharedpreferences.edit(); - resobjLogin = new JSONObject(responseLogin); - String token = resobjLogin.getString("access_token"); - String refresh_token = resobjLogin.getString("refresh_token"); - editor.putString(Helper.PREF_KEY_OAUTH_TOKEN, token); - editor.putString(Helper.PREF_INSTANCE, host); - editor.apply(); - //Update the account with the token; - updateCredential(LoginActivity.this, token, client_id, client_secret, refresh_token, host); - } catch (JSONException e) { - e.printStackTrace(); - runOnUiThread(() -> connectionButton.setEnabled(true)); - } + SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); + SharedPreferences.Editor editor = sharedpreferences.edit(); + editor.putString(Helper.PREF_KEY_OAUTH_TOKEN, refreshToken.getAccess_token()); + editor.putString(Helper.PREF_INSTANCE, host); + editor.apply(); + //Update the account with the token; + updateCredential(LoginActivity.this, refreshToken.getAccess_token(), client_id, client_secret, refreshToken.getRefresh_token(), host); }); } diff --git a/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java b/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java index 52a01ce..337bec2 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java +++ b/app/src/main/java/app/fedilab/fedilabtube/MainActivity.java @@ -45,7 +45,9 @@ import org.jetbrains.annotations.NotNull; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.data.AccountData.Account; +import app.fedilab.fedilabtube.client.entities.OauthParams; import app.fedilab.fedilabtube.client.entities.PeertubeInformation; +import app.fedilab.fedilabtube.client.entities.WellKnownNodeinfo; import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.services.RetrieveInfoService; import app.fedilab.fedilabtube.sqlite.AccountDAO; @@ -164,7 +166,12 @@ public class MainActivity extends AppCompatActivity { SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); Account account = new AccountDAO(MainActivity.this, db).getUniqAccount(userId, instance); if (account != null) { - new Thread(() -> new RetrofitPeertubeAPI(MainActivity.this).refreshToken(account.getClient_id(), account.getClient_secret(),account.getToken())).start(); + OauthParams oauthParams = new OauthParams(); + oauthParams.setGrant_type("refresh_token"); + oauthParams.setClient_id(account.getClient_id()); + oauthParams.setClient_secret(account.getClient_secret()); + oauthParams.setRefresh_token(account.getRefresh_token()); + new Thread(() -> new RetrofitPeertubeAPI(MainActivity.this).manageToken(oauthParams)).start(); } } else { instanceItem.setVisible(true); @@ -285,8 +292,8 @@ public class MainActivity extends AppCompatActivity { (dialog, which) -> new Thread(() -> { try { String newInstance = input.getText().toString().trim(); - InstanceNodeInfo instanceNodeInfo = new RetrofitPeertubeAPI(MainActivity.this).displayNodeInfo(newInstance); - if (instanceNodeInfo.getName() != null && instanceNodeInfo.getName().trim().toLowerCase().compareTo("peertube") == 0) { + WellKnownNodeinfo.NodeInfo instanceNodeInfo = new RetrofitPeertubeAPI(MainActivity.this).getNodeInfo(newInstance); + if (instanceNodeInfo.getSoftware() != null && instanceNodeInfo.getSoftware().getName().trim().toLowerCase().compareTo("peertube") == 0) { SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putString(Helper.PREF_INSTANCE, newInstance); editor.commit(); diff --git a/app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java b/app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java index 62d94e2..aac322c 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java +++ b/app/src/main/java/app/fedilab/fedilabtube/PeertubeActivity.java @@ -83,9 +83,7 @@ import com.google.android.exoplayer2.util.Util; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Objects; @@ -97,7 +95,7 @@ import app.fedilab.fedilabtube.client.data.CommentData.Comment; import app.fedilab.fedilabtube.client.data.PlaylistData.Playlist; import app.fedilab.fedilabtube.client.data.VideoData; import app.fedilab.fedilabtube.client.entities.File; -import app.fedilab.fedilabtube.client.entities.PlaylistParams; +import app.fedilab.fedilabtube.client.entities.Item; import app.fedilab.fedilabtube.client.entities.Report; import app.fedilab.fedilabtube.drawer.CommentListAdapter; import app.fedilab.fedilabtube.helper.CacheDataSourceFactory; @@ -115,6 +113,10 @@ import app.fedilab.fedilabtube.webview.MastalabWebChromeClient; import app.fedilab.fedilabtube.webview.MastalabWebViewClient; import es.dmoral.toasty.Toasty; +import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.ADD_COMMENT; +import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.RATEVIDEO; +import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.REPORT_ACCOUNT; +import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.REPORT_VIDEO; import static app.fedilab.fedilabtube.helper.Helper.getAttColor; import static app.fedilab.fedilabtube.helper.Helper.getLiveInstance; import static app.fedilab.fedilabtube.helper.Helper.isLoggedIn; @@ -142,7 +144,7 @@ public class PeertubeActivity extends AppCompatActivity { private ImageView send; private TextView add_comment_read; private EditText add_comment_write; - private List playlistForVideo; + private List playlistForVideo; private List playlists; private PlaylistsVM playlistsViewModel; private boolean playInMinimized; @@ -371,8 +373,8 @@ public class PeertubeActivity extends AppCompatActivity { dialogBuilder.setNeutralButton(R.string.cancel, (dialog, id) -> dialog.dismiss()); androidx.appcompat.app.AlertDialog alertDialog = dialogBuilder.create(); alertDialog.show(); - report_video.setOnClickListener(v -> reportAlert(RetrofitPeertubeAPI.reportType.VIDEO, alertDialog)); - report_account.setOnClickListener(v -> reportAlert(PeertubeAPI.reportType.ACCOUNT, alertDialog)); + report_video.setOnClickListener(v -> reportAlert(REPORT_VIDEO, alertDialog)); + report_account.setOnClickListener(v -> reportAlert(REPORT_ACCOUNT, alertDialog)); return true; } return super.onOptionsItemSelected(item); @@ -467,7 +469,7 @@ public class PeertubeActivity extends AppCompatActivity { String comment = add_comment_write.getText().toString(); if (comment.trim().length() > 0) { PostActionsVM viewModel = new ViewModelProvider(PeertubeActivity.this).get(PostActionsVM.class); - viewModel.post(RetrofitPeertubeAPI.ActionType.PEERTUBECOMMENT, peertube.getAccount().getId(), comment, null).observe(PeertubeActivity.this, apiResponse1 -> manageVIewPostActions(PeertubeAPI.StatusAction.PEERTUBECOMMENT, apiResponse1)); + viewModel.comment(ADD_COMMENT, peertube.getId(), null, comment).observe(PeertubeActivity.this, apiResponse1 -> manageVIewPostActions(ADD_COMMENT, apiResponse1)); add_comment_write.setText(""); add_comment_read.setVisibility(View.VISIBLE); add_comment_write.setVisibility(View.GONE); @@ -488,12 +490,12 @@ public class PeertubeActivity extends AppCompatActivity { String title = null; boolean isPresent = false; String elementId = null; - PlaylistParams playlistElementFinal = null; - for (PlaylistParams playlistElement : playlistForVideo) { - if (playlist.getId().equals(playlistElement.getPlaylistId())) { + Playlist playlistElementFinal = null; + for (Playlist playlistElement : playlistForVideo) { + if (playlist.getId().equals(playlistElement.getId())) { title = "✔ " + playlist.getDisplayName(); isPresent = true; - elementId = playlistElement.getPlaylistElementId(); + elementId = playlistElement.getId(); playlistElementFinal = playlistElement; break; } @@ -504,7 +506,7 @@ public class PeertubeActivity extends AppCompatActivity { MenuItem item = popup.getMenu().add(0, 0, Menu.NONE, title); boolean finalIsPresent = isPresent; String finalElementId = elementId; - PlaylistParams finalPlaylistElementFinal = playlistElementFinal; + Playlist finalPlaylistElementFinal = playlistElementFinal; item.setOnMenuItemClickListener(item1 -> { item1.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW); item1.setActionView(new View(PeertubeActivity.this)); @@ -526,9 +528,8 @@ public class PeertubeActivity extends AppCompatActivity { } else { item1.setTitle("✔ " + playlist.getDisplayName()); playlistsViewModel.manage(PlaylistsVM.action.ADD_VIDEOS, playlist, peertube.getId()).observe(PeertubeActivity.this, apiResponse3 -> manageVIewPlaylists(PlaylistsVM.action.ADD_VIDEOS, apiResponse3)); - PlaylistParams playlistElement = new PlaylistParams(); - playlistElement.setPlaylistElementId(null); - playlistElement.setPlaylistId(playlist.getId()); + Playlist playlistElement = new Playlist(); + playlistElement.setId(playlist.getId()); playlistForVideo.add(playlistElement); } return false; @@ -541,7 +542,7 @@ public class PeertubeActivity extends AppCompatActivity { if (peertube.isCommentsEnabled()) { CommentVM commentViewModel = new ViewModelProvider(PeertubeActivity.this).get(CommentVM.class); - commentViewModel.getComment(peertubeInstance, videoId).observe(PeertubeActivity.this, this::manageVIewComment); + commentViewModel.getThread(videoId).observe(PeertubeActivity.this, this::manageVIewComment); write_comment_container.setVisibility(View.VISIBLE); } else { @@ -567,7 +568,7 @@ public class PeertubeActivity extends AppCompatActivity { if (isLoggedIn(PeertubeActivity.this)) { String newState = peertube.getMyRating().equals("like") ? "none" : "like"; PostActionsVM viewModel = new ViewModelProvider(PeertubeActivity.this).get(PostActionsVM.class); - viewModel.post(RetrofitPeertubeAPI.ActionType.RATEVIDEO, peertube.getId(), newState, null).observe(PeertubeActivity.this, apiResponse1 -> manageVIewPostActions(PeertubeAPI.StatusAction.RATEVIDEO, apiResponse1)); + viewModel.post(RATEVIDEO, peertube.getId(), newState).observe(PeertubeActivity.this, apiResponse1 -> manageVIewPostActions(RATEVIDEO, apiResponse1)); peertube.setMyRating(newState); int count = Integer.parseInt(peertube_like_count.getText().toString()); if (newState.compareTo("none") == 0) { @@ -588,7 +589,7 @@ public class PeertubeActivity extends AppCompatActivity { if (isLoggedIn(PeertubeActivity.this)) { String newState = peertube.getMyRating().equals("dislike") ? "none" : "dislike"; PostActionsVM viewModel = new ViewModelProvider(PeertubeActivity.this).get(PostActionsVM.class); - viewModel.post(RetrofitPeertubeAPI.ActionType.RATEVIDEO, peertube.getId(), newState).observe(PeertubeActivity.this, apiResponse1 -> manageVIewPostActions(PeertubeAPI.StatusAction.RATEVIDEO, apiResponse1)); + viewModel.post(RATEVIDEO, peertube.getId(), newState).observe(PeertubeActivity.this, apiResponse1 -> manageVIewPostActions(RATEVIDEO, apiResponse1)); peertube.setMyRating(newState); int count = Integer.parseInt(peertube_dislike_count.getText().toString()); if (newState.compareTo("none") == 0) { @@ -690,10 +691,9 @@ public class PeertubeActivity extends AppCompatActivity { int i = 1; if (captions.size() > 0) { for (Caption caption : captions) { - Iterator> it = caption.getLanguage().entrySet().iterator(); - Map.Entry pair = it.next(); - itemsLabelLanguage[i] = pair.getValue(); - itemsKeyLanguage[i] = pair.getKey(); + Item lang = caption.getLanguage(); + itemsLabelLanguage[i] = String.valueOf(lang.getId()); + itemsKeyLanguage[i] = lang.getLabel(); i++; } } @@ -944,10 +944,9 @@ public class PeertubeActivity extends AppCompatActivity { @SuppressWarnings({"unused", "RedundantSuppression"}) public void manageVIewPostActions(RetrofitPeertubeAPI.ActionType statusAction, APIResponse apiResponse) { - - if (peertube.isCommentsEnabled() && statusAction == RetrofitPeertubeAPI.ActionType.PEERTUBECOMMENT) { + if (peertube.isCommentsEnabled() && statusAction == ADD_COMMENT) { CommentVM commentViewModel = new ViewModelProvider(PeertubeActivity.this).get(CommentVM.class); - commentViewModel.getComment(peertubeInstance, videoId).observe(PeertubeActivity.this, this::manageVIewComment); + commentViewModel.getThread(videoId).observe(PeertubeActivity.this, this::manageVIewComment); } else if (statusAction == RetrofitPeertubeAPI.ActionType.REPORT_ACCOUNT) { Toasty.success(PeertubeActivity.this, getString(R.string.successful_report), Toasty.LENGTH_LONG).show(); } else if (statusAction == RetrofitPeertubeAPI.ActionType.REPORT_VIDEO) { @@ -1037,7 +1036,7 @@ public class PeertubeActivity extends AppCompatActivity { public void manageVIewPlaylists(PlaylistsVM.action actionType, APIResponse apiResponse) { if (actionType == GET_PLAYLIST_FOR_VIDEO && apiResponse != null) { - playlistForVideo = apiResponse.getPlaylistForVideos(); + playlistForVideo = apiResponse.getPlaylists(); } else if (actionType == GET_PLAYLISTS && apiResponse != null) { playlists = apiResponse.getPlaylists(); } diff --git a/app/src/main/java/app/fedilab/fedilabtube/ShowAccountActivity.java b/app/src/main/java/app/fedilab/fedilabtube/ShowChannelActivity.java similarity index 63% rename from app/src/main/java/app/fedilab/fedilabtube/ShowAccountActivity.java rename to app/src/main/java/app/fedilab/fedilabtube/ShowChannelActivity.java index e076ff2..6da9c41 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/ShowAccountActivity.java +++ b/app/src/main/java/app/fedilab/fedilabtube/ShowChannelActivity.java @@ -48,40 +48,46 @@ import com.google.android.material.tabs.TabLayout; import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; import java.util.List; +import java.util.Map; import app.fedilab.fedilabtube.client.APIResponse; -import app.fedilab.fedilabtube.client.PeertubeAPI; -import app.fedilab.fedilabtube.client.data.AccountData.Account; -import app.fedilab.fedilabtube.client.entities.Relationship; +import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; +import app.fedilab.fedilabtube.client.data.ChannelData.Channel; import app.fedilab.fedilabtube.fragment.DisplayAccountsFragment; import app.fedilab.fedilabtube.fragment.DisplayVideosFragment; import app.fedilab.fedilabtube.helper.Helper; -import app.fedilab.fedilabtube.viewmodel.AccountsVM; +import app.fedilab.fedilabtube.viewmodel.ChannelsVM; import app.fedilab.fedilabtube.viewmodel.TimelineVM; import app.fedilab.fedilabtube.viewmodel.PostActionsVM; import app.fedilab.fedilabtube.viewmodel.RelationshipVM; import es.dmoral.toasty.Toasty; import static androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY; +import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.FOLLOW; +import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.MUTE; +import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.REPORT_ACCOUNT; +import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.ActionType.UNFOLLOW; +import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.DataType.CHANNEL; import static app.fedilab.fedilabtube.helper.Helper.getLiveInstance; import static app.fedilab.fedilabtube.helper.Helper.isLoggedIn; -public class ShowAccountActivity extends AppCompatActivity { +public class ShowChannelActivity extends AppCompatActivity { private Button account_follow; private ViewPager mPager; private TabLayout tabLayout; private TextView account_note, subscriber_count; - private Relationship relationship; + private List> relationship; private ImageView account_pp; private TextView account_dn; - private Account account; - private String accountId; - private boolean ischannel; + private Channel channel; private action doAction; + private String channelAcct; @Override protected void onCreate(Bundle savedInstanceState) { @@ -96,15 +102,10 @@ public class ShowAccountActivity extends AppCompatActivity { account_dn = findViewById(R.id.account_dn); account_pp.setBackgroundResource(R.drawable.account_pp_border); if (b != null) { - account = b.getParcelable("account"); - if (account == null) { - accountId = b.getString("accountId"); - } else { - accountId = account.getId(); - } - ischannel = b.getBoolean("ischannel", false); + channel = b.getParcelable("channel"); + channelAcct = b.getString("channelId"); } else { - Toasty.error(ShowAccountActivity.this, getString(R.string.toast_error_loading_account), Toast.LENGTH_LONG).show(); + Toasty.error(ShowChannelActivity.this, getString(R.string.toast_error_loading_account), Toast.LENGTH_LONG).show(); } if (getSupportActionBar() != null) { @@ -115,19 +116,16 @@ public class ShowAccountActivity extends AppCompatActivity { account_note = findViewById(R.id.account_note); - AccountsVM viewModel = new ViewModelProvider(ShowAccountActivity.this).get(AccountsVM.class); - if (account != null) { - manageAccount(); - viewModel.getAccounts(null, account.getAcct(), AccountsVM.accountFetch.SINGLE_CHANNEL).observe(ShowAccountActivity.this, this::manageViewAccounts); - } else { - viewModel.getAccounts(null, accountId, AccountsVM.accountFetch.SINGLE_CHANNEL).observe(ShowAccountActivity.this, this::manageViewAccounts); - } + ChannelsVM viewModel = new ViewModelProvider(ShowChannelActivity.this).get(ChannelsVM.class); + + manageChannel(); + viewModel.get(CHANNEL, channelAcct==null?channel.getAcct():channelAcct).observe(ShowChannelActivity.this, this::manageViewAccounts); } @Override public boolean onCreateOptionsMenu(@NotNull Menu menu) { getMenuInflater().inflate(R.menu.main_account, menu); - if (!Helper.isLoggedIn(ShowAccountActivity.this)) { + if (!Helper.isLoggedIn(ShowChannelActivity.this)) { menu.findItem(R.id.action_mute).setVisible(false); } return true; @@ -139,21 +137,21 @@ public class ShowAccountActivity extends AppCompatActivity { finish(); return true; } else if (item.getItemId() == R.id.action_mute) { - PostActionsVM viewModel = new ViewModelProvider(ShowAccountActivity.this).get(PostActionsVM.class); - viewModel.post(PeertubeAPI.StatusAction.MUTE, account.getchannelOwner() != null ? account.getchannelOwner().getAcct() : account.getAcct(), null, null).observe(ShowAccountActivity.this, apiResponse -> manageVIewPostActions(PeertubeAPI.StatusAction.MUTE, apiResponse)); + PostActionsVM viewModel = new ViewModelProvider(ShowChannelActivity.this).get(PostActionsVM.class); + viewModel.post(MUTE, channel.getOwnerAccount() != null ? channel.getOwnerAccount().getAcct() : channel.getAcct(), null).observe(ShowChannelActivity.this, apiResponse -> manageVIewPostActions(MUTE, apiResponse)); } else if (item.getItemId() == R.id.action_report) { - androidx.appcompat.app.AlertDialog.Builder dialogBuilder = new androidx.appcompat.app.AlertDialog.Builder(ShowAccountActivity.this); + androidx.appcompat.app.AlertDialog.Builder dialogBuilder = new androidx.appcompat.app.AlertDialog.Builder(ShowChannelActivity.this); LayoutInflater inflater1 = getLayoutInflater(); - View dialogView = inflater1.inflate(R.layout.popup_report, new LinearLayout(ShowAccountActivity.this), false); + View dialogView = inflater1.inflate(R.layout.popup_report, new LinearLayout(ShowChannelActivity.this), false); dialogBuilder.setView(dialogView); EditText report_content = dialogView.findViewById(R.id.report_content); dialogBuilder.setNeutralButton(R.string.cancel, (dialog, id) -> dialog.dismiss()); dialogBuilder.setPositiveButton(R.string.report, (dialog, id) -> { if (report_content.getText().toString().trim().length() == 0) { - Toasty.info(ShowAccountActivity.this, getString(R.string.report_comment_size), Toasty.LENGTH_LONG).show(); + Toasty.info(ShowChannelActivity.this, getString(R.string.report_comment_size), Toasty.LENGTH_LONG).show(); } else { - PostActionsVM viewModel = new ViewModelProvider(ShowAccountActivity.this).get(PostActionsVM.class); - viewModel.post(PeertubeAPI.StatusAction.REPORT_ACCOUNT, account.getId(), report_content.getText().toString(), null).observe(ShowAccountActivity.this, apiResponse -> manageVIewPostActions(PeertubeAPI.StatusAction.REPORT_ACCOUNT, apiResponse)); + PostActionsVM viewModel = new ViewModelProvider(ShowChannelActivity.this).get(PostActionsVM.class); + viewModel.post(REPORT_ACCOUNT, channel.getId(), report_content.getText().toString()).observe(ShowChannelActivity.this, apiResponse -> manageVIewPostActions(REPORT_ACCOUNT, apiResponse)); dialog.dismiss(); } }); @@ -163,36 +161,30 @@ public class ShowAccountActivity extends AppCompatActivity { return super.onOptionsItemSelected(item); } - private void manageAccount() { + private void manageChannel() { SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); - String accountIdRelation = account.getAcct(); - if (isLoggedIn(ShowAccountActivity.this)) { - RelationshipVM viewModel = new ViewModelProvider(ShowAccountActivity.this).get(RelationshipVM.class); - viewModel.get(accountIdRelation).observe(ShowAccountActivity.this, this::manageVIewRelationship); + String accountIdRelation = channel.getAcct(); + if (isLoggedIn(ShowChannelActivity.this)) { + RelationshipVM viewModel = new ViewModelProvider(ShowChannelActivity.this).get(RelationshipVM.class); + List uids = new ArrayList<>(); + uids.add(accountIdRelation); + viewModel.get(uids).observe(ShowChannelActivity.this, this::manageVIewRelationship); } - setTitle(account.getAcct()); + setTitle(channel.getAcct()); mPager = findViewById(R.id.account_viewpager); - if (!ischannel) { - tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.videos))); - tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.channels))); - mPager.setOffscreenPageLimit(2); - } else { - tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.videos))); - mPager.setOffscreenPageLimit(1); - } + tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.videos))); + mPager.setOffscreenPageLimit(1); PagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager()); mPager.setAdapter(mPagerAdapter); - if (ischannel) { - ViewGroup.LayoutParams params = tabLayout.getLayoutParams(); - params.height = 0; - tabLayout.setLayoutParams(params); - } + ViewGroup.LayoutParams params = tabLayout.getLayoutParams(); + params.height = 0; + tabLayout.setLayoutParams(params); mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { @@ -245,39 +237,39 @@ public class ShowAccountActivity extends AppCompatActivity { } }); - account_dn.setText(account.getDisplay_name()); + account_dn.setText(channel.getDisplayName()); - manageNotes(account); - Helper.loadGiF(ShowAccountActivity.this, account, account_pp); + manageNotes(channel); + Helper.loadGiF(ShowChannelActivity.this, channel.getAvatar().getPath(), account_pp); //Follow button - String target = account.getAcct(); + String target = channel.getAcct(); account_follow.setOnClickListener(v -> { if (doAction == action.NOTHING) { - Toasty.info(ShowAccountActivity.this, getString(R.string.nothing_to_do), Toast.LENGTH_LONG).show(); + Toasty.info(ShowChannelActivity.this, getString(R.string.nothing_to_do), Toast.LENGTH_LONG).show(); } else if (doAction == action.FOLLOW) { account_follow.setEnabled(false); - PostActionsVM viewModel = new ViewModelProvider(ShowAccountActivity.this).get(PostActionsVM.class); - viewModel.post(PeertubeAPI.StatusAction.FOLLOW, target, null, null).observe(ShowAccountActivity.this, apiResponse -> manageVIewPostActions(PeertubeAPI.StatusAction.FOLLOW, apiResponse)); + PostActionsVM viewModel = new ViewModelProvider(ShowChannelActivity.this).get(PostActionsVM.class); + viewModel.post(FOLLOW, target, null).observe(ShowChannelActivity.this, apiResponse -> manageVIewPostActions(FOLLOW, apiResponse)); } else if (doAction == action.UNFOLLOW) { boolean confirm_unfollow = sharedpreferences.getBoolean(Helper.SET_UNFOLLOW_VALIDATION, true); if (confirm_unfollow) { - AlertDialog.Builder unfollowConfirm = new AlertDialog.Builder(ShowAccountActivity.this); + AlertDialog.Builder unfollowConfirm = new AlertDialog.Builder(ShowChannelActivity.this); unfollowConfirm.setTitle(getString(R.string.unfollow_confirm)); - unfollowConfirm.setMessage(account.getAcct()); + unfollowConfirm.setMessage(channel.getAcct()); unfollowConfirm.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss()); unfollowConfirm.setPositiveButton(R.string.yes, (dialog, which) -> { account_follow.setEnabled(false); - PostActionsVM viewModel = new ViewModelProvider(ShowAccountActivity.this).get(PostActionsVM.class); - viewModel.post(PeertubeAPI.StatusAction.UNFOLLOW, target, null, null).observe(ShowAccountActivity.this, apiResponse -> manageVIewPostActions(PeertubeAPI.StatusAction.UNFOLLOW, apiResponse)); + PostActionsVM viewModel = new ViewModelProvider(ShowChannelActivity.this).get(PostActionsVM.class); + viewModel.post(UNFOLLOW, target, null).observe(ShowChannelActivity.this, apiResponse -> manageVIewPostActions(UNFOLLOW, apiResponse)); dialog.dismiss(); }); unfollowConfirm.show(); } else { account_follow.setEnabled(false); - PostActionsVM viewModel = new ViewModelProvider(ShowAccountActivity.this).get(PostActionsVM.class); - viewModel.post(PeertubeAPI.StatusAction.UNFOLLOW, target, null, null).observe(ShowAccountActivity.this, apiResponse -> manageVIewPostActions(PeertubeAPI.StatusAction.UNFOLLOW, apiResponse)); + PostActionsVM viewModel = new ViewModelProvider(ShowChannelActivity.this).get(PostActionsVM.class); + viewModel.post(UNFOLLOW, target, null).observe(ShowChannelActivity.this, apiResponse -> manageVIewPostActions(UNFOLLOW, apiResponse)); } } @@ -288,11 +280,10 @@ public class ShowAccountActivity extends AppCompatActivity { public void manageVIewRelationship(APIResponse apiResponse) { if (apiResponse.getError() != null) { - Toasty.error(ShowAccountActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show(); + Toasty.error(ShowChannelActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show(); return; } - List relationships = apiResponse.getRelationships(); - this.relationship = relationships.get(0); + this.relationship = apiResponse.getRelationships(); manageButtonVisibility(); invalidateOptionsMenu(); @@ -313,36 +304,27 @@ public class ShowAccountActivity extends AppCompatActivity { }; int[] colors = new int[]{ - ContextCompat.getColor(ShowAccountActivity.this, Helper.getColorAccent()), - ContextCompat.getColor(ShowAccountActivity.this, Helper.getColorAccent()), - ContextCompat.getColor(ShowAccountActivity.this, Helper.getColorAccent()), - ContextCompat.getColor(ShowAccountActivity.this, Helper.getColorAccent()) + ContextCompat.getColor(ShowChannelActivity.this, Helper.getColorAccent()), + ContextCompat.getColor(ShowChannelActivity.this, Helper.getColorAccent()), + ContextCompat.getColor(ShowChannelActivity.this, Helper.getColorAccent()), + ContextCompat.getColor(ShowChannelActivity.this, Helper.getColorAccent()) }; account_follow.setBackgroundTintList(new ColorStateList(states, colors)); } account_follow.setEnabled(true); - if (relationship.isFollowing()) { + + boolean isFollowing = relationship.get(0).get(channel.getAcct()); + if (isFollowing) { account_follow.setText(R.string.action_unfollow); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - account_follow.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor(ShowAccountActivity.this, R.color.red_1))); + account_follow.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor(ShowChannelActivity.this, R.color.red_1))); } doAction = action.UNFOLLOW; - if (ischannel) { - account_follow.setVisibility(View.VISIBLE); - } else { - account_follow.setVisibility(View.GONE); - } - } else if (!relationship.isFollowing()) { + account_follow.setVisibility(View.VISIBLE); + } else { account_follow.setText(R.string.action_follow); doAction = action.FOLLOW; - if (ischannel) { - account_follow.setVisibility(View.VISIBLE); - } else { - account_follow.setVisibility(View.GONE); - } - } else { - account_follow.setVisibility(View.GONE); - doAction = action.NOTHING; + account_follow.setVisibility(View.VISIBLE); } } @@ -358,54 +340,55 @@ public class ShowAccountActivity extends AppCompatActivity { } - public void manageVIewPostActions(PeertubeAPI.StatusAction statusAction, APIResponse apiResponse) { + public void manageVIewPostActions(RetrofitPeertubeAPI.ActionType statusAction, APIResponse apiResponse) { if (apiResponse.getError() != null) { - Toasty.error(ShowAccountActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show(); + Toasty.error(ShowChannelActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show(); return; } - String target = account.getAcct(); + String target = channel.getAcct(); //IF action is unfollow or mute, sends an intent to remove statuses - if (statusAction == PeertubeAPI.StatusAction.UNFOLLOW) { + if (statusAction == RetrofitPeertubeAPI.ActionType.UNFOLLOW) { Bundle b = new Bundle(); b.putString("receive_action", apiResponse.getTargetedId()); Intent intentBC = new Intent(Helper.RECEIVE_ACTION); intentBC.putExtras(b); } - if (statusAction == PeertubeAPI.StatusAction.UNFOLLOW || statusAction == PeertubeAPI.StatusAction.FOLLOW) { - RelationshipVM viewModel = new ViewModelProvider(ShowAccountActivity.this).get(RelationshipVM.class); - viewModel.get(target).observe(ShowAccountActivity.this, this::manageVIewRelationship); - } else if (statusAction == PeertubeAPI.StatusAction.MUTE) { - Toasty.info(ShowAccountActivity.this, getString(R.string.muted_done), Toast.LENGTH_LONG).show(); + if (statusAction == RetrofitPeertubeAPI.ActionType.UNFOLLOW || statusAction == RetrofitPeertubeAPI.ActionType.FOLLOW) { + RelationshipVM viewModel = new ViewModelProvider(ShowChannelActivity.this).get(RelationshipVM.class); + List uris = new ArrayList<>(); + uris.add(target); + viewModel.get(uris).observe(ShowChannelActivity.this, this::manageVIewRelationship); + } else if (statusAction == RetrofitPeertubeAPI.ActionType.MUTE) { + Toasty.info(ShowChannelActivity.this, getString(R.string.muted_done), Toast.LENGTH_LONG).show(); } } public void manageViewAccounts(APIResponse apiResponse) { - if (apiResponse.getAccounts() != null && apiResponse.getAccounts().size() == 1) { - Account account = apiResponse.getAccounts().get(0); - if (this.account == null) { - this.account = account; - manageAccount(); + if (apiResponse.getChannels() != null && apiResponse.getChannels().size() == 1) { + Channel channel = apiResponse.getChannels().get(0); + if (this.channel == null) { + this.channel = channel; + manageChannel(); } - if (account.getchannelOwner() != null) { - this.account.setchannelOwner(account.getchannelOwner()); + if (channel.getOwnerAccount() != null) { + this.channel.setOwnerAccount(channel.getOwnerAccount()); } - subscriber_count.setText(getString(R.string.followers_count, Helper.withSuffix(account.getFollowers_count()))); + subscriber_count.setText(getString(R.string.followers_count, Helper.withSuffix(channel.getFollowersCount()))); subscriber_count.setVisibility(View.VISIBLE); - manageNotes(account); + manageNotes(channel); } } - private void manageNotes(Account account) { - if (account.getNote() != null && account.getNote().compareTo("null") != 0 && account.getNote().trim().length() > 0) { + private void manageNotes(Channel channel) { + if (channel.getDescription() != null && channel.getDescription().compareTo("null") != 0 && channel.getDescription().trim().length() > 0) { SpannableString spannableString; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - spannableString = new SpannableString(Html.fromHtml(account.getNote(), FROM_HTML_MODE_LEGACY)); + spannableString = new SpannableString(Html.fromHtml(channel.getDescription(), FROM_HTML_MODE_LEGACY)); else - spannableString = new SpannableString(Html.fromHtml(account.getNote())); + spannableString = new SpannableString(Html.fromHtml(channel.getDescription())); - account.setNoteSpan(spannableString); - account_note.setText(account.getNoteSpan(), TextView.BufferType.SPANNABLE); + account_note.setText(spannableString, TextView.BufferType.SPANNABLE); account_note.setMovementMethod(LinkMovementMethod.getInstance()); account_note.setVisibility(View.VISIBLE); } else { @@ -435,16 +418,15 @@ public class ShowAccountActivity extends AppCompatActivity { if (position == 0) { DisplayVideosFragment displayVideosFragment = new DisplayVideosFragment(); bundle = new Bundle(); - bundle.putSerializable("type", TimelineVM.Type.USER); - bundle.putString("targetedid", account.getAcct()); - bundle.putBoolean("ischannel", ischannel); + bundle.putSerializable("type", TimelineVM.TimelineType.USER_VIDEOS); + bundle.putString("channelId", channel.getAcct()); displayVideosFragment.setArguments(bundle); return displayVideosFragment; } DisplayAccountsFragment displayAccountsFragment = new DisplayAccountsFragment(); - bundle.putString("targetedid", account.getId()); - bundle.putString("instance", getLiveInstance(ShowAccountActivity.this)); - bundle.putString("name", account.getAcct()); + bundle.putString("targetedid", channel.getId()); + bundle.putString("instance", getLiveInstance(ShowChannelActivity.this)); + bundle.putString("name", channel.getAcct()); displayAccountsFragment.setArguments(bundle); return displayAccountsFragment; } @@ -452,10 +434,7 @@ public class ShowAccountActivity extends AppCompatActivity { @Override public int getCount() { - if (ischannel) - return 1; - else - return 2; + return 1; } } diff --git a/app/src/main/java/app/fedilab/fedilabtube/WebviewConnectActivity.java b/app/src/main/java/app/fedilab/fedilabtube/WebviewConnectActivity.java index 6feca15..b9bde75 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/WebviewConnectActivity.java +++ b/app/src/main/java/app/fedilab/fedilabtube/WebviewConnectActivity.java @@ -28,18 +28,16 @@ import android.widget.ProgressBar; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; - -import org.json.JSONObject; - import java.net.URL; -import java.util.HashMap; import java.util.regex.Matcher; -import app.fedilab.fedilabtube.client.HttpsConnection; +import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; +import app.fedilab.fedilabtube.client.entities.OauthParams; +import app.fedilab.fedilabtube.client.entities.RefreshToken; import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.webview.CustomWebview; -import static app.fedilab.fedilabtube.client.HttpsConnection.updateCredential; +import static app.fedilab.fedilabtube.client.RetrofitPeertubeAPI.updateCredential; public class WebviewConnectActivity extends AppCompatActivity { @@ -118,24 +116,20 @@ public class WebviewConnectActivity extends AppCompatActivity { String username = matcher.group(2); new Thread(() -> { try { - String newUrl = "https://" + new URL(url).getHost() + "/api/v1/users/token"; - HashMap params = new HashMap<>(); - clientId = sharedpreferences.getString(Helper.CLIENT_ID, "null"); - clientSecret = sharedpreferences.getString(Helper.CLIENT_SECRET, "null"); - params.put("client_id", clientId); - params.put("client_secret", clientSecret); - params.put("username", username); - params.put("grant_type", "password"); - params.put("externalAuthToken", externalAuthToken); - String response = new HttpsConnection(WebviewConnectActivity.this).post(newUrl, 30, params, null); - JSONObject jsonObject = new JSONObject(response); - String token = jsonObject.getString("access_token"); - String refresh_token = jsonObject.getString("refresh_token"); + OauthParams oauthParams = new OauthParams(); + oauthParams.setClient_id(sharedpreferences.getString(Helper.CLIENT_ID, null)); + oauthParams.setClient_secret(sharedpreferences.getString(Helper.CLIENT_SECRET, null)); + oauthParams.setGrant_type("password"); + oauthParams.setUsername(username); + oauthParams.setExternalAuthToken(externalAuthToken); + String instance = new URL(url).getHost(); + RefreshToken refreshToken = new RetrofitPeertubeAPI(WebviewConnectActivity.this, instance, null).manageToken(oauthParams); + SharedPreferences.Editor editor = sharedpreferences.edit(); - editor.putString(Helper.PREF_KEY_OAUTH_TOKEN, token); - editor.putString(Helper.PREF_INSTANCE, new URL(url).getHost()); + editor.putString(Helper.PREF_KEY_OAUTH_TOKEN, refreshToken.getAccess_token()); + editor.putString(Helper.PREF_INSTANCE, instance); editor.apply(); - updateCredential(WebviewConnectActivity.this, token, clientId, clientSecret, refresh_token, new URL(url).getHost()); + updateCredential(WebviewConnectActivity.this, refreshToken.getAccess_token(), clientId, clientSecret, refreshToken.getRefresh_token(), new URL(url).getHost()); finish(); } catch (Exception e) { e.printStackTrace(); @@ -144,8 +138,6 @@ public class WebviewConnectActivity extends AppCompatActivity { } super.onPageFinished(view, url); } - - }); webView.loadUrl(url); diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/HttpsConnection.java b/app/src/main/java/app/fedilab/fedilabtube/client/HttpsConnection.java deleted file mode 100644 index e81e0e8..0000000 --- a/app/src/main/java/app/fedilab/fedilabtube/client/HttpsConnection.java +++ /dev/null @@ -1,704 +0,0 @@ -package app.fedilab.fedilabtube.client; -/* Copyright 2020 Thomas Schneider - * - * This file is a part of TubeLab - * - * 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. - * - * TubeLab 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 TubeLab; if not, - * see . */ - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.database.sqlite.SQLiteDatabase; -import android.os.Build; -import android.os.Handler; -import android.os.Looper; -import android.text.Html; -import android.text.SpannableString; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.net.Authenticator; -import java.net.HttpURLConnection; -import java.net.InetSocketAddress; -import java.net.MalformedURLException; -import java.net.PasswordAuthentication; -import java.net.Proxy; -import java.net.URL; -import java.net.URLDecoder; -import java.nio.charset.StandardCharsets; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Scanner; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.net.ssl.HttpsURLConnection; - -import app.fedilab.fedilabtube.MainActivity; -import app.fedilab.fedilabtube.R; -import app.fedilab.fedilabtube.client.data.AccountData.Account; -import app.fedilab.fedilabtube.helper.Helper; -import app.fedilab.fedilabtube.sqlite.AccountDAO; -import app.fedilab.fedilabtube.sqlite.Sqlite; - - -@SuppressWarnings({"unused", "RedundantSuppression"}) -public class HttpsConnection { - - - private static final String LINE_FEED = "\r\n"; - private HttpsURLConnection httpsURLConnection; - private String since_id, max_id; - private Context context; - private int CHUNK_SIZE = 4096; - private Proxy proxy; - - - public HttpsConnection(Context context) { - this.context = context; - SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); - boolean proxyEnabled = sharedpreferences.getBoolean(Helper.SET_PROXY_ENABLED, false); - int type = sharedpreferences.getInt(Helper.SET_PROXY_TYPE, 0); - proxy = null; - - if (proxyEnabled) { - try { - String host = sharedpreferences.getString(Helper.SET_PROXY_HOST, "127.0.0.1"); - int port = sharedpreferences.getInt(Helper.SET_PROXY_PORT, 8118); - if (type == 0) - proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, port)); - else - proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(host, port)); - final String login = sharedpreferences.getString(Helper.SET_PROXY_LOGIN, null); - final String pwd = sharedpreferences.getString(Helper.SET_PROXY_PASSWORD, null); - if (login != null) { - Authenticator authenticator = new Authenticator() { - public PasswordAuthentication getPasswordAuthentication() { - assert pwd != null; - return (new PasswordAuthentication(login, - pwd.toCharArray())); - } - }; - Authenticator.setDefault(authenticator); - } - } catch (Exception e) { - proxy = null; - } - - } - } - - /** - * Update user credentials - * - * @param _mContext Context - * @param token String - * @param client_id String - * @param client_secret String - * @param refresh_token String - * @param host String - */ - public static void updateCredential(Context _mContext, String token, String client_id, String client_secret, String refresh_token, String host) { - new Thread(() -> { - Account account; - String instance; - if (host.startsWith("tube")) { - instance = host; - } else { - instance = Helper.getPeertubeUrl(host); - } - account = new PeertubeAPI(_mContext).verifyCredentials(token, instance); - if (account == null) - return; - try { - //At the state the instance can be encoded - instance = URLDecoder.decode(instance, "utf-8"); - } catch (UnsupportedEncodingException ignored) { - } - SharedPreferences sharedpreferences = _mContext.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); - account.setToken(token); - account.setClient_id(client_id); - account.setClient_secret(client_secret); - account.setRefresh_token(refresh_token); - account.setInstance(instance); - SQLiteDatabase db = Sqlite.getInstance(_mContext.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); - boolean userExists = new AccountDAO(_mContext, db).userExist(account); - SharedPreferences.Editor editor = sharedpreferences.edit(); - editor.putString(Helper.PREF_KEY_ID, account.getId()); - editor.putBoolean(Helper.PREF_IS_MODERATOR, account.isModerator()); - editor.putBoolean(Helper.PREF_IS_ADMINISTRATOR, account.isAdmin()); - if (!host.startsWith("tube")) { - editor.putString(Helper.PREF_INSTANCE, host); - } - editor.apply(); - if (userExists) - new AccountDAO(_mContext, db).updateAccountCredential(account); - else { - if (account.getUsername() != null && account.getCreated_at() != null) - new AccountDAO(_mContext, db).insertAccount(account); - } - Handler mainHandler = new Handler(Looper.getMainLooper()); - Runnable myRunnable = () -> { - Intent mainActivity = new Intent(_mContext, MainActivity.class); - mainActivity.putExtra(Helper.INTENT_ACTION, Helper.ADD_USER_INTENT); - _mContext.startActivity(mainActivity); - ((Activity) _mContext).finish(); - }; - mainHandler.post(myRunnable); - }).start(); - } - - /** - * Get calls - * - * @param urlConnection String url - * @param timeout int timeout - * @param paramaters HashMap paramaters - * @param token String token - * @return String - * @throws IOException IOException - * @throws NoSuchAlgorithmException NoSuchAlgorithmException - * @throws KeyManagementException KeyManagementException - * @throws HttpsConnectionException HttpsConnectionException - */ - public String get(String urlConnection, int timeout, HashMap paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { - - - Map params = new LinkedHashMap<>(); - if (paramaters != null) { - Iterator> it = paramaters.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry pair = it.next(); - params.put(pair.getKey(), pair.getValue()); - it.remove(); - } - } - StringBuilder postData = new StringBuilder(); - URL url; - if (params.size() > 0) { - for (Map.Entry param : params.entrySet()) { - if (postData.length() != 0) postData.append('&'); - postData.append(param.getKey()); - postData.append('='); - postData.append(param.getValue()); - } - url = new URL(urlConnection + "?" + postData); - } else { - url = new URL(urlConnection); - } - - if (proxy != null) - httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy); - else - httpsURLConnection = (HttpsURLConnection) url.openConnection(); - httpsURLConnection.setConnectTimeout(timeout * 1000); - httpsURLConnection.setRequestProperty("http.keepAlive", "false"); - httpsURLConnection.setRequestProperty("Content-Type", "application/json"); - httpsURLConnection.setRequestProperty("Accept", "application/json"); - httpsURLConnection.setUseCaches(true); - httpsURLConnection.setDefaultUseCaches(true); - httpsURLConnection.setSSLSocketFactory(new TLSSocketFactory()); - if (token != null) - httpsURLConnection.setRequestProperty("Authorization", "Bearer " + token); - httpsURLConnection.setRequestMethod("GET"); - String response; - if (httpsURLConnection.getResponseCode() >= 200 && httpsURLConnection.getResponseCode() < 400) { - response = converToString(httpsURLConnection.getInputStream()); - } else { - String error = null; - if (httpsURLConnection.getErrorStream() != null) { - InputStream stream = httpsURLConnection.getErrorStream(); - if (stream == null) { - stream = httpsURLConnection.getInputStream(); - } - try (Scanner scanner = new Scanner(stream)) { - scanner.useDelimiter("\\Z"); - if (scanner.hasNext()) { - error = scanner.next(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - int responseCode = httpsURLConnection.getResponseCode(); - try { - httpsURLConnection.getInputStream().close(); - } catch (Exception ignored) { - } - throw new HttpsConnectionException(responseCode, error); - } - getSinceMaxId(); - httpsURLConnection.getInputStream().close(); - return response; - } - - public String get(String urlConnection) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { - - - URL url = new URL(urlConnection); - if (proxy != null) - httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy); - else - httpsURLConnection = (HttpsURLConnection) url.openConnection(); - httpsURLConnection.setConnectTimeout(30 * 1000); - httpsURLConnection.setRequestProperty("http.keepAlive", "false"); - httpsURLConnection.setRequestProperty("Content-Type", "application/json"); - httpsURLConnection.setRequestProperty("Accept", "application/json"); - httpsURLConnection.setSSLSocketFactory(new TLSSocketFactory()); - httpsURLConnection.setRequestMethod("GET"); - httpsURLConnection.setDefaultUseCaches(true); - httpsURLConnection.setUseCaches(true); - String response; - if (httpsURLConnection.getResponseCode() >= 200 && httpsURLConnection.getResponseCode() < 400) { - getSinceMaxId(); - response = converToString(httpsURLConnection.getInputStream()); - } else { - String error = null; - if (httpsURLConnection.getErrorStream() != null) { - InputStream stream = httpsURLConnection.getErrorStream(); - if (stream == null) { - stream = httpsURLConnection.getInputStream(); - } - try (Scanner scanner = new Scanner(stream)) { - scanner.useDelimiter("\\Z"); - if (scanner.hasNext()) { - error = scanner.next(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - int responseCode = httpsURLConnection.getResponseCode(); - try { - httpsURLConnection.getInputStream().close(); - } catch (Exception ignored) { - } - throw new HttpsConnectionException(responseCode, error); - } - getSinceMaxId(); - httpsURLConnection.getInputStream().close(); - return response; - } - - public String postBoundary(boundaryType type, String urlConnection, int timeout, LinkedHashMap paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { - URL url = new URL(urlConnection); - - String boundary = "----TubeLabBoundary" + System.currentTimeMillis(); - if (proxy != null) - httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy); - else - httpsURLConnection = (HttpsURLConnection) url.openConnection(); - httpsURLConnection.setConnectTimeout(timeout * 1000); - httpsURLConnection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); - httpsURLConnection.setDoOutput(true); - httpsURLConnection.setSSLSocketFactory(new TLSSocketFactory()); - - if (type == boundaryType.POST) { - httpsURLConnection.setRequestMethod("POST"); - } else if (type == boundaryType.PUT) { - httpsURLConnection.setRequestMethod("PUT"); - } - if (token != null) - httpsURLConnection.setRequestProperty("Authorization", "Bearer " + token); - - StringBuilder postData = new StringBuilder(); - if (paramaters != null) { - Iterator> it = paramaters.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry pair = it.next(); - postData = addFormField(postData, pair.getKey(), pair.getValue(), boundary); - it.remove(); - } - postData.append("--").append(boundary).append("--"); - } - byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8); - httpsURLConnection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); - OutputStream outputStream = httpsURLConnection.getOutputStream(); - outputStream.write(postDataBytes); - - String response; - if (httpsURLConnection.getResponseCode() >= 200 && httpsURLConnection.getResponseCode() < 400) { - getSinceMaxId(); - response = converToString(httpsURLConnection.getInputStream()); - } else { - String error = null; - if (httpsURLConnection.getErrorStream() != null) { - InputStream stream = httpsURLConnection.getErrorStream(); - if (stream == null) { - stream = httpsURLConnection.getInputStream(); - } - try (Scanner scanner = new Scanner(stream)) { - scanner.useDelimiter("\\Z"); - if (scanner.hasNext()) { - error = scanner.next(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - int responseCode = httpsURLConnection.getResponseCode(); - try { - httpsURLConnection.getInputStream().close(); - } catch (Exception ignored) { - } - throw new HttpsConnectionException(responseCode, error); - } - getSinceMaxId(); - httpsURLConnection.getInputStream().close(); - return response; - } - - /** - * Adds a form field to the request - * - * @param writer StringBuilder - * @param name field name - * @param value field value - */ - private StringBuilder addFormField(StringBuilder writer, String name, String value, String boundary) { - if (writer != null) { - writer.append("--").append(boundary).append(LINE_FEED); - writer.append("Content-Disposition: form-data; name=\"").append(name).append("\"") - .append(LINE_FEED); - writer.append("Content-Type: text/plain; charset=").append(StandardCharsets.UTF_8).append( - LINE_FEED); - writer.append(LINE_FEED); - writer.append(value).append(LINE_FEED); - } - return writer; - } - - public String post(String urlConnection, int timeout, HashMap paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { - URL url = new URL(urlConnection); - Map params = new LinkedHashMap<>(); - if (paramaters != null) { - Iterator> it = paramaters.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry pair = it.next(); - params.put(pair.getKey(), pair.getValue()); - it.remove(); - } - } - StringBuilder postData = new StringBuilder(); - for (Map.Entry param : params.entrySet()) { - if (postData.length() != 0) postData.append('&'); - postData.append(param.getKey()); - postData.append('='); - postData.append(param.getValue()); - } - byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8); - if (proxy != null) - httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy); - else - httpsURLConnection = (HttpsURLConnection) url.openConnection(); - httpsURLConnection.setConnectTimeout(timeout * 1000); - httpsURLConnection.setDoOutput(true); - httpsURLConnection.setSSLSocketFactory(new TLSSocketFactory()); - httpsURLConnection.setRequestMethod("POST"); - if (token != null) - httpsURLConnection.setRequestProperty("Authorization", "Bearer " + token); - httpsURLConnection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); - - - httpsURLConnection.getOutputStream().write(postDataBytes); - String response; - if (httpsURLConnection.getResponseCode() >= 200 && httpsURLConnection.getResponseCode() < 400) { - getSinceMaxId(); - response = converToString(httpsURLConnection.getInputStream()); - } else { - String error = null; - if (httpsURLConnection.getErrorStream() != null) { - InputStream stream = httpsURLConnection.getErrorStream(); - if (stream == null) { - stream = httpsURLConnection.getInputStream(); - } - try (Scanner scanner = new Scanner(stream)) { - scanner.useDelimiter("\\Z"); - if (scanner.hasNext()) { - error = scanner.next(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - int responseCode = httpsURLConnection.getResponseCode(); - try { - httpsURLConnection.getInputStream().close(); - } catch (Exception ignored) { - } - throw new HttpsConnectionException(responseCode, error); - } - getSinceMaxId(); - httpsURLConnection.getInputStream().close(); - return response; - } - - public InputStream getPicture(final String downloadUrl) { - - URL url; - try { - url = new URL(downloadUrl); - } catch (MalformedURLException e) { - return null; - } - try { - if (proxy != null) - httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy); - else - httpsURLConnection = (HttpsURLConnection) url.openConnection(); - httpsURLConnection.setSSLSocketFactory(new TLSSocketFactory()); - int responseCode = httpsURLConnection.getResponseCode(); - // always check HTTP response code first - if (responseCode == HttpURLConnection.HTTP_OK) { - // opens input stream from the HTTP connection - return httpsURLConnection.getInputStream(); - } - httpsURLConnection.getInputStream().close(); - } catch (IOException | NoSuchAlgorithmException | KeyManagementException ignored) { - } - if (httpsURLConnection != null) - try { - httpsURLConnection.getInputStream().close(); - } catch (Exception ignored) { - } - return null; - } - - - public String put(String urlConnection, int timeout, HashMap paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { - - URL url = new URL(urlConnection); - Map params = new LinkedHashMap<>(); - if (paramaters != null) { - Iterator> it = paramaters.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry pair = it.next(); - params.put(pair.getKey(), pair.getValue()); - it.remove(); - } - } - StringBuilder postData = new StringBuilder(); - for (Map.Entry param : params.entrySet()) { - if (postData.length() != 0) postData.append('&'); - postData.append(param.getKey()); - postData.append('='); - postData.append(param.getValue()); - } - byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8); - - if (proxy != null) - httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy); - else - httpsURLConnection = (HttpsURLConnection) url.openConnection(); - httpsURLConnection.setConnectTimeout(timeout * 1000); - httpsURLConnection.setSSLSocketFactory(new TLSSocketFactory()); - if (token != null) - httpsURLConnection.setRequestProperty("Authorization", "Bearer " + token); - httpsURLConnection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); - - httpsURLConnection.setRequestMethod("PUT"); - httpsURLConnection.setDoInput(true); - httpsURLConnection.setDoOutput(true); - - httpsURLConnection.getOutputStream().write(postDataBytes); - String response; - if (httpsURLConnection.getResponseCode() >= 200 && httpsURLConnection.getResponseCode() < 400) { - getSinceMaxId(); - response = converToString(httpsURLConnection.getInputStream()); - } else { - String error = null; - if (httpsURLConnection.getErrorStream() != null) { - InputStream stream = httpsURLConnection.getErrorStream(); - if (stream == null) { - stream = httpsURLConnection.getInputStream(); - } - try (Scanner scanner = new Scanner(stream)) { - scanner.useDelimiter("\\Z"); - if (scanner.hasNext()) { - error = scanner.next(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - int responseCode = httpsURLConnection.getResponseCode(); - try { - httpsURLConnection.getInputStream().close(); - } catch (Exception ignored) { - } - throw new HttpsConnectionException(responseCode, error); - } - getSinceMaxId(); - httpsURLConnection.getInputStream().close(); - return response; - - } - - public void delete(String urlConnection, int timeout, HashMap paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException { - - URL url = new URL(urlConnection); - Map params = new LinkedHashMap<>(); - if (paramaters != null) { - Iterator> it = paramaters.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry pair = it.next(); - params.put(pair.getKey(), pair.getValue()); - it.remove(); - } - } - StringBuilder postData = new StringBuilder(); - for (Map.Entry param : params.entrySet()) { - if (postData.length() != 0) postData.append('&'); - postData.append(param.getKey()); - postData.append('='); - postData.append(param.getValue()); - } - byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8); - - if (proxy != null) - httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy); - else - httpsURLConnection = (HttpsURLConnection) url.openConnection(); - httpsURLConnection.setSSLSocketFactory(new TLSSocketFactory()); - if (token != null) - httpsURLConnection.setRequestProperty("Authorization", "Bearer " + token); - httpsURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - httpsURLConnection.setRequestMethod("DELETE"); - httpsURLConnection.setConnectTimeout(timeout * 1000); - httpsURLConnection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length)); - - httpsURLConnection.getOutputStream().write(postDataBytes); - if (httpsURLConnection.getResponseCode() >= 200 && httpsURLConnection.getResponseCode() < 400) { - getSinceMaxId(); - httpsURLConnection.getInputStream().close(); - httpsURLConnection.getResponseCode(); - } else { - String error = null; - if (httpsURLConnection.getErrorStream() != null) { - InputStream stream = httpsURLConnection.getErrorStream(); - if (stream == null) { - stream = httpsURLConnection.getInputStream(); - } - try (Scanner scanner = new Scanner(stream)) { - scanner.useDelimiter("\\Z"); - if (scanner.hasNext()) { - error = scanner.next(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - int responseCode = httpsURLConnection.getResponseCode(); - try { - httpsURLConnection.getInputStream().close(); - } catch (Exception ignored) { - } - throw new HttpsConnectionException(responseCode, error); - } - } - - public String getSince_id() { - return since_id; - } - - public String getMax_id() { - return max_id; - } - - private void getSinceMaxId() { - - if (httpsURLConnection == null) - return; - Map> map = httpsURLConnection.getHeaderFields(); - - for (Map.Entry> entry : map.entrySet()) { - if (entry.toString().startsWith("Link") || entry.toString().startsWith("link")) { - Pattern patternMaxId = Pattern.compile("max_id=([0-9a-zA-Z]+).*"); - Matcher matcherMaxId = patternMaxId.matcher(entry.toString()); - if (matcherMaxId.find()) { - max_id = matcherMaxId.group(1); - } - if (entry.toString().startsWith("Link")) { - Pattern patternSinceId = Pattern.compile("since_id=([0-9a-zA-Z]+).*"); - Matcher matcherSinceId = patternSinceId.matcher(entry.toString()); - if (matcherSinceId.find()) { - since_id = matcherSinceId.group(1); - } - - } - } else if (entry.toString().startsWith("Min-Id") || entry.toString().startsWith("min-id")) { - Pattern patternMaxId = Pattern.compile("min-id=\\[([0-9a-zA-Z]+).*]"); - Matcher matcherMaxId = patternMaxId.matcher(entry.toString()); - if (matcherMaxId.find()) { - max_id = matcherMaxId.group(1); - } - } - } - } - - private String converToString(InputStream inputStream) { - Scanner s = new Scanner(inputStream).useDelimiter("\\A"); - return s.hasNext() ? s.next() : ""; - } - - int getActionCode() { - try { - return httpsURLConnection.getResponseCode(); - } catch (IOException e) { - return -1; - } - } - - public enum boundaryType { - POST, - PUT - } - - public class HttpsConnectionException extends Exception { - - private int statusCode; - private String message; - - HttpsConnectionException(int statusCode, String message) { - this.statusCode = statusCode; - SpannableString spannableString; - if (message != null) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - spannableString = new SpannableString(Html.fromHtml(message, Html.FROM_HTML_MODE_LEGACY)); - else - spannableString = new SpannableString(Html.fromHtml(message)); - } else { - spannableString = new SpannableString(context.getString(R.string.toast_error)); - } - this.message = spannableString.toString(); - } - - - public int getStatusCode() { - return statusCode; - } - - @Override - public String getMessage() { - return message; - } - - } -} diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/PeertubeService.java b/app/src/main/java/app/fedilab/fedilabtube/client/PeertubeService.java index 5c03d17..f0fc366 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/client/PeertubeService.java +++ b/app/src/main/java/app/fedilab/fedilabtube/client/PeertubeService.java @@ -27,6 +27,8 @@ import app.fedilab.fedilabtube.client.data.PlaylistData; import app.fedilab.fedilabtube.client.data.VideoData; import app.fedilab.fedilabtube.client.entities.CaptionsParams; import app.fedilab.fedilabtube.client.entities.ChannelParams; +import app.fedilab.fedilabtube.client.entities.Oauth; +import app.fedilab.fedilabtube.client.entities.OauthParams; import app.fedilab.fedilabtube.client.entities.OverviewVideo; import app.fedilab.fedilabtube.client.entities.PlaylistExist; import app.fedilab.fedilabtube.client.entities.PlaylistParams; @@ -34,6 +36,7 @@ import app.fedilab.fedilabtube.client.entities.Rating; import app.fedilab.fedilabtube.client.entities.RefreshToken; import app.fedilab.fedilabtube.client.entities.Report; import app.fedilab.fedilabtube.client.entities.VideoParams; +import app.fedilab.fedilabtube.client.entities.WellKnownNodeinfo; import okhttp3.MultipartBody; import retrofit2.Call; import retrofit2.http.Body; @@ -53,6 +56,15 @@ public interface PeertubeService { Call getInstances(@QueryMap Map params, @Query("nsfwPolicy[]") String nsfwPolicy, @Query("categoriesOr[]") List categories, @Query("languagesOr[]") List languages); //Server settings + @GET(".well-known/nodeinfo") + Call getWellKnownNodeinfo(); + + @GET("{nodeInfoPath}") + Call getNodeinfo(@Path("nodeInfoPath") String nodeInfoPath); + + @GET("{captionContent}") + Call getCaptionContent(@Path("captionContent") String captionContent); + @GET("videos/categories") Call> getCategories(); @@ -75,7 +87,7 @@ public interface PeertubeService { //TOKEN //Refresh @POST("users/token") - Call refreshToken(@Query("grant_type") String grantType, @Query("client_id") String clientId, @Query("client_secret") String clientSecret, @Query("refresh_token") String refreshToken); + Call manageToken(@Body OauthParams oauthParams); @GET("users/me") Call verifyCredentials(@Header("Authorization") String credentials); @@ -138,6 +150,10 @@ public interface PeertubeService { Call deleteVideo(@Header("Authorization") String credentials, @Path("id") String videoId); + @GET("oauth-clients/local") + Call getOauth(); + + //Post/Update/Delete channel //Channels for account @GET("accounts/{accountId}/video-channels") diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/RetrofitPeertubeAPI.java b/app/src/main/java/app/fedilab/fedilabtube/client/RetrofitPeertubeAPI.java index ef96713..7e5148b 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/client/RetrofitPeertubeAPI.java +++ b/app/src/main/java/app/fedilab/fedilabtube/client/RetrofitPeertubeAPI.java @@ -14,11 +14,18 @@ package app.fedilab.fedilabtube.client; * You should have received a copy of the GNU General Public License along with TubeLab; if not, * see . */ +import android.app.Activity; import android.content.Context; +import android.content.Intent; import android.content.SharedPreferences; +import android.database.sqlite.SQLiteDatabase; +import android.os.Handler; +import android.os.Looper; import java.io.File; import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; @@ -26,6 +33,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; +import app.fedilab.fedilabtube.MainActivity; import app.fedilab.fedilabtube.R; import app.fedilab.fedilabtube.client.data.AccountData; import app.fedilab.fedilabtube.client.data.CaptionData; @@ -39,6 +47,8 @@ import app.fedilab.fedilabtube.client.entities.AccountCreation; import app.fedilab.fedilabtube.client.entities.ChannelParams; import app.fedilab.fedilabtube.client.entities.Error; import app.fedilab.fedilabtube.client.entities.InstanceParams; +import app.fedilab.fedilabtube.client.entities.Oauth; +import app.fedilab.fedilabtube.client.entities.OauthParams; import app.fedilab.fedilabtube.client.entities.OverviewVideo; import app.fedilab.fedilabtube.client.entities.PeertubeInformation; import app.fedilab.fedilabtube.client.entities.PlaylistParams; @@ -46,7 +56,10 @@ import app.fedilab.fedilabtube.client.entities.Rating; import app.fedilab.fedilabtube.client.entities.RefreshToken; import app.fedilab.fedilabtube.client.entities.Report; import app.fedilab.fedilabtube.client.entities.VideoParams; +import app.fedilab.fedilabtube.client.entities.WellKnownNodeinfo; import app.fedilab.fedilabtube.helper.Helper; +import app.fedilab.fedilabtube.sqlite.AccountDAO; +import app.fedilab.fedilabtube.sqlite.Sqlite; import app.fedilab.fedilabtube.viewmodel.ChannelsVM; import app.fedilab.fedilabtube.viewmodel.CommentVM; import app.fedilab.fedilabtube.viewmodel.PlaylistsVM; @@ -104,9 +117,9 @@ public class RetrofitPeertubeAPI { * Verifiy credential of the authenticated user *synchronously* * @return Account */ - public RefreshToken refreshToken(String client_id, String client_secret, String refresh_token) { + public RefreshToken manageToken(OauthParams oauthParams) { PeertubeService peertubeService = init(); - Call refreshTokenCall = peertubeService.refreshToken("refresh_token", client_id, client_secret, refresh_token); + Call refreshTokenCall = peertubeService.manageToken(oauthParams); try { Response response = refreshTokenCall.execute(); if (response.isSuccessful()) { @@ -160,6 +173,78 @@ public class RetrofitPeertubeAPI { return apiResponse; } + + /** + * Get caption content + * @param path String path to caption + * @return APIResponse + */ + public APIResponse getCaptionContent(String path) { + APIResponse apiResponse = new APIResponse(); + PeertubeService peertubeService = init(); + Call captionContentCall = peertubeService.getCaptionContent(path); + try { + Response response = captionContentCall.execute(); + if (response.isSuccessful()) { + apiResponse.setCaptionText(response.body()); + } else { + Error error = new Error(); + error.setStatusCode(response.code()); + if (response.errorBody() != null) { + error.setError(response.message()); + } else { + error.setError(_context.getString(R.string.toast_error)); + } + apiResponse.setError(error); + } + } catch (IOException e) { + Error error = new Error(); + error.setError(_context.getString(R.string.toast_error)); + apiResponse.setError(error); + e.printStackTrace(); + } + return apiResponse; + } + + + + /** + * Get videos in a channel + * @param channelId String id of the channel + * @param max_id String pagination + * @return APIResponse + */ + public APIResponse getVideosForChannel(String channelId, String max_id) { + APIResponse apiResponse = new APIResponse(); + PeertubeService peertubeService = init(); + Call> videoCall = peertubeService.getChannelVideos(channelId, max_id); + if (videoCall != null) { + try { + Response> response = videoCall.execute(); + if (response.isSuccessful()) { + apiResponse.setPeertubes(response.body()); + } else { + Error error = new Error(); + error.setStatusCode(response.code()); + if (response.errorBody() != null) { + error.setError(response.message()); + } else { + error.setError(_context.getString(R.string.toast_error)); + } + apiResponse.setError(error); + } + } catch (IOException e) { + Error error = new Error(); + error.setError(_context.getString(R.string.toast_error)); + apiResponse.setError(error); + e.printStackTrace(); + } + } + return apiResponse; + } + + + public APIResponse getTL(TimelineVM.TimelineType timelineType, String max_id) { APIResponse apiResponse = new APIResponse(); PeertubeService peertubeService = init(); @@ -773,6 +858,52 @@ public class RetrofitPeertubeAPI { } + /** + * Get Oauth + * @return APIResponse + */ + public Oauth oauthClient() { + PeertubeService peertubeService = init(); + try { + Call oauth = peertubeService.getOauth(); + Response response = oauth.execute(); + if( response.isSuccessful() && response.body() != null) { + return response.body(); + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + + /** + * Get NodeInfo + * @param instance String + * @return APIResponse + */ + public WellKnownNodeinfo.NodeInfo getNodeInfo(String instance) { + PeertubeService peertubeService = init(); + try { + Call wellKnownNodeinfoCall = peertubeService.getWellKnownNodeinfo(); + Response response = wellKnownNodeinfoCall.execute(); + if( response.isSuccessful() && response.body() != null) { + if (response.body().getHref() != null) { + Call nodeinfo = peertubeService.getNodeinfo(response.body().getHref()); + Response responseNodeInfo = nodeinfo.execute(); + return responseNodeInfo.body(); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + + + /** * Get channel data * @@ -1017,12 +1148,12 @@ public class RetrofitPeertubeAPI { * @param text String text * @return APIResponse */ - public APIResponse commentAction(CommentVM.action type, String videoId, String toCommentId, String text) { + public APIResponse commentAction(RetrofitPeertubeAPI.ActionType type, String videoId, String toCommentId, String text) { PeertubeService peertubeService = init(); APIResponse apiResponse = new APIResponse(); try { - if (type == CommentVM.action.ADD_COMMENT) { + if (type == ActionType.ADD_COMMENT) { Call stringCall = peertubeService.postComment(token, videoId, text); Response response = stringCall.execute(); if (response.isSuccessful()) { @@ -1031,7 +1162,7 @@ public class RetrofitPeertubeAPI { Error error = generateError(response.code(), response.message()); apiResponse.setError(error); } - } else if (type == CommentVM.action.REPLY) { + } else if (type == ActionType.REPLY) { Call stringCall = peertubeService.postReply(token, videoId, toCommentId, text); Response response = stringCall.execute(); if (response.isSuccessful()) { @@ -1158,6 +1289,56 @@ public class RetrofitPeertubeAPI { } + public static void updateCredential(Context _mContext, String token, String client_id, String client_secret, String refresh_token, String host) { + new Thread(() -> { + AccountData.Account account; + String instance; + if (host.startsWith("tube")) { + instance = host; + } else { + instance = Helper.getPeertubeUrl(host); + } + account = new RetrofitPeertubeAPI(_mContext).verifyCredentials(token, instance); + if (account == null) + return; + try { + //At the state the instance can be encoded + instance = URLDecoder.decode(instance, "utf-8"); + } catch (UnsupportedEncodingException ignored) { + } + SharedPreferences sharedpreferences = _mContext.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); + account.setToken(token); + account.setClient_id(client_id); + account.setClient_secret(client_secret); + account.setRefresh_token(refresh_token); + account.setHost(instance); + SQLiteDatabase db = Sqlite.getInstance(_mContext.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); + boolean userExists = new AccountDAO(_mContext, db).userExist(account); + SharedPreferences.Editor editor = sharedpreferences.edit(); + editor.putString(Helper.PREF_KEY_ID, account.getId()); + if (!host.startsWith("tube")) { + editor.putString(Helper.PREF_INSTANCE, host); + } + editor.apply(); + if (userExists) + new AccountDAO(_mContext, db).updateAccountCredential(account); + else { + if (account.getName() != null && account.getCreatedAt() != null) + new AccountDAO(_mContext, db).insertAccount(account); + } + Handler mainHandler = new Handler(Looper.getMainLooper()); + Runnable myRunnable = () -> { + Intent mainActivity = new Intent(_mContext, MainActivity.class); + mainActivity.putExtra(Helper.INTENT_ACTION, Helper.ADD_USER_INTENT); + _mContext.startActivity(mainActivity); + ((Activity) _mContext).finish(); + }; + mainHandler.post(myRunnable); + }).start(); + } + + + public enum DataType { SUBSCRIBER, @@ -1178,7 +1359,9 @@ public class RetrofitPeertubeAPI { PEERTUBEDELETEVIDEO, REPORT_VIDEO, REPORT_ACCOUNT, - DELETE_CHANNEL + DELETE_CHANNEL, + ADD_COMMENT, + REPLY, } diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/entities/NodeInfo.java b/app/src/main/java/app/fedilab/fedilabtube/client/entities/Oauth.java similarity index 59% rename from app/src/main/java/app/fedilab/fedilabtube/client/entities/NodeInfo.java rename to app/src/main/java/app/fedilab/fedilabtube/client/entities/Oauth.java index 56a6a52..79fb1eb 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/client/entities/NodeInfo.java +++ b/app/src/main/java/app/fedilab/fedilabtube/client/entities/Oauth.java @@ -1,5 +1,4 @@ package app.fedilab.fedilabtube.client.entities; - /* Copyright 2020 Thomas Schneider * * This file is a part of TubeLab @@ -14,24 +13,31 @@ package app.fedilab.fedilabtube.client.entities; * * You should have received a copy of the GNU General Public License along with TubeLab; if not, * see . */ -@SuppressWarnings("unused") -public class NodeInfo { - private String rel; - private String href; - public String getRel() { - return rel; +import com.google.gson.annotations.SerializedName; + +public class Oauth { + + @SerializedName("client_id") + private String client_id; + @SerializedName("client_secret") + private String client_secret; + + public String getClient_id() { + return client_id; } - public void setRel(String rel) { - this.rel = rel; + public void setClient_id(String client_id) { + this.client_id = client_id; } - public String getHref() { - return href; + public String getClient_secret() { + return client_secret; } - public void setHref(String href) { - this.href = href; + public void setClient_secret(String client_secret) { + this.client_secret = client_secret; } + + } diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/entities/OauthParams.java b/app/src/main/java/app/fedilab/fedilabtube/client/entities/OauthParams.java new file mode 100644 index 0000000..2ce6f6e --- /dev/null +++ b/app/src/main/java/app/fedilab/fedilabtube/client/entities/OauthParams.java @@ -0,0 +1,102 @@ +package app.fedilab.fedilabtube.client.entities; +/* Copyright 2020 Thomas Schneider + * + * This file is a part of TubeLab + * + * 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. + * + * TubeLab 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 TubeLab; if not, + * see . */ + +import com.google.gson.annotations.SerializedName; + +public class OauthParams { + + @SerializedName("grant_type") + private String grant_type; + @SerializedName("client_secret") + private String client_secret; + @SerializedName("client_id") + private String client_id; + @SerializedName("username") + private String username; + @SerializedName("password") + private String password; + @SerializedName("scope") + private String scope = "user"; + @SerializedName("externalAuthToken") + private String externalAuthToken; + @SerializedName("refresh_token") + private String refresh_token; + + + public String getClient_secret() { + return client_secret; + } + + public void setClient_secret(String client_secret) { + this.client_secret = client_secret; + } + + public String getClient_id() { + return client_id; + } + + public void setClient_id(String client_id) { + this.client_id = client_id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getScope() { + return scope; + } + + public void setScope(String scope) { + this.scope = scope; + } + + public String getGrant_type() { + return grant_type; + } + + public void setGrant_type(String grant_type) { + this.grant_type = grant_type; + } + + public String getExternalAuthToken() { + return externalAuthToken; + } + + public void setExternalAuthToken(String externalAuthToken) { + this.externalAuthToken = externalAuthToken; + } + + public String getRefresh_token() { + return refresh_token; + } + + public void setRefresh_token(String refresh_token) { + this.refresh_token = refresh_token; + } +} diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/entities/WellKnownNodeinfo.java b/app/src/main/java/app/fedilab/fedilabtube/client/entities/WellKnownNodeinfo.java new file mode 100644 index 0000000..9d1b08e --- /dev/null +++ b/app/src/main/java/app/fedilab/fedilabtube/client/entities/WellKnownNodeinfo.java @@ -0,0 +1,88 @@ +package app.fedilab.fedilabtube.client.entities; +/* Copyright 2020 Thomas Schneider + * + * This file is a part of TubeLab + * + * 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. + * + * TubeLab 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 TubeLab; if not, + * see . */ + + +import com.google.gson.annotations.SerializedName; + +@SuppressWarnings("unused") +public class WellKnownNodeinfo { + @SerializedName("reel") + private String reel; + @SerializedName("href") + private String href; + + public String getReel() { + return reel; + } + + public void setReel(String reel) { + this.reel = reel; + } + + public String getHref() { + return href; + } + + public void setHref(String href) { + this.href = href; + } + + public static class NodeInfo { + @SerializedName("version") + private String version; + @SerializedName("software") + private Software software; + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public Software getSoftware() { + return software; + } + + public void setSoftware(Software software) { + this.software = software; + } + } + + public static class Software{ + @SerializedName("name") + private String name; + @SerializedName("version") + private String version; + + 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; + } + } +} diff --git a/app/src/main/java/app/fedilab/fedilabtube/drawer/AccountsListAdapter.java b/app/src/main/java/app/fedilab/fedilabtube/drawer/AccountsListAdapter.java index 4ebad06..7c2ec24 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/drawer/AccountsListAdapter.java +++ b/app/src/main/java/app/fedilab/fedilabtube/drawer/AccountsListAdapter.java @@ -40,7 +40,7 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton; import java.util.List; import app.fedilab.fedilabtube.R; -import app.fedilab.fedilabtube.ShowAccountActivity; +import app.fedilab.fedilabtube.ShowChannelActivity; import app.fedilab.fedilabtube.client.APIResponse; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.data.AccountData.Account; @@ -107,12 +107,9 @@ public class AccountsListAdapter extends RecyclerView.Adapter { - Intent intent = new Intent(context, ShowAccountActivity.class); + Intent intent = new Intent(context, ShowChannelActivity.class); Bundle b = new Bundle(); - b.putBoolean("peertubeaccount", true); - b.putBoolean("ischannel", true); - b.putString("targetedid", account.getName()); - b.putParcelable("account", account); + b.putParcelable("channel", account); intent.putExtras(b); context.startActivity(intent); }); diff --git a/app/src/main/java/app/fedilab/fedilabtube/drawer/ChannelListAdapter.java b/app/src/main/java/app/fedilab/fedilabtube/drawer/ChannelListAdapter.java index 3807d39..b9be5fd 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/drawer/ChannelListAdapter.java +++ b/app/src/main/java/app/fedilab/fedilabtube/drawer/ChannelListAdapter.java @@ -39,7 +39,7 @@ import java.util.List; import app.fedilab.fedilabtube.AccountActivity; import app.fedilab.fedilabtube.R; -import app.fedilab.fedilabtube.ShowAccountActivity; +import app.fedilab.fedilabtube.ShowChannelActivity; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.data.ChannelData.Channel; import app.fedilab.fedilabtube.helper.Helper; @@ -131,12 +131,9 @@ public class ChannelListAdapter extends RecyclerView.Adapter { - Intent intent = new Intent(context, ShowAccountActivity.class); + Intent intent = new Intent(context, ShowChannelActivity.class); Bundle b = new Bundle(); - b.putBoolean("peertubeaccount", true); - b.putBoolean("ischannel", true); - b.putString("targetedid", channel.getName()); - b.putParcelable("account", channel); + b.putParcelable("channel", channel); intent.putExtras(b); context.startActivity(intent); }); diff --git a/app/src/main/java/app/fedilab/fedilabtube/drawer/PeertubeAdapter.java b/app/src/main/java/app/fedilab/fedilabtube/drawer/PeertubeAdapter.java index 82d708c..401d206 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/drawer/PeertubeAdapter.java +++ b/app/src/main/java/app/fedilab/fedilabtube/drawer/PeertubeAdapter.java @@ -33,7 +33,7 @@ import java.util.List; import app.fedilab.fedilabtube.PeertubeActivity; import app.fedilab.fedilabtube.PeertubeEditUploadActivity; import app.fedilab.fedilabtube.R; -import app.fedilab.fedilabtube.ShowAccountActivity; +import app.fedilab.fedilabtube.ShowChannelActivity; import app.fedilab.fedilabtube.client.data.AccountData.Account; import app.fedilab.fedilabtube.client.data.VideoData; import app.fedilab.fedilabtube.helper.Helper; @@ -88,13 +88,12 @@ public class PeertubeAdapter extends RecyclerView.Adapter { - Intent intent = new Intent(context, ShowAccountActivity.class); + Intent intent = new Intent(context, ShowChannelActivity.class); Bundle b = new Bundle(); if (peertube.getChannel() == null) { - b.putParcelable("account", peertube.getAccount()); + b.putParcelable("channel", peertube.getAccount()); } else { - b.putParcelable("account", peertube.getChannel()); - b.putBoolean("ischannel", true); + b.putParcelable("channel", peertube.getChannel()); } intent.putExtras(b); context.startActivity(intent); diff --git a/app/src/main/java/app/fedilab/fedilabtube/drawer/PeertubeNotificationsListAdapter.java b/app/src/main/java/app/fedilab/fedilabtube/drawer/PeertubeNotificationsListAdapter.java index 4e92cea..c4ac6c4 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/drawer/PeertubeNotificationsListAdapter.java +++ b/app/src/main/java/app/fedilab/fedilabtube/drawer/PeertubeNotificationsListAdapter.java @@ -34,7 +34,7 @@ import java.util.List; import app.fedilab.fedilabtube.LoginActivity; import app.fedilab.fedilabtube.PeertubeActivity; import app.fedilab.fedilabtube.R; -import app.fedilab.fedilabtube.ShowAccountActivity; +import app.fedilab.fedilabtube.ShowChannelActivity; import app.fedilab.fedilabtube.client.data.AccountData; import app.fedilab.fedilabtube.client.data.NotificationData.Notification; import app.fedilab.fedilabtube.client.entities.Actor; @@ -84,10 +84,9 @@ public class PeertubeNotificationsListAdapter extends RecyclerView.Adapter { - Intent intent = new Intent(context, ShowAccountActivity.class); + Intent intent = new Intent(context, ShowChannelActivity.class); Bundle b = new Bundle(); - b.putString("accountId", accountActionFollow.getName() + "@" + accountActionFollow.getHost()); - b.putBoolean("ischannel", true); + b.putString("channelId", accountActionFollow.getName() + "@" + accountActionFollow.getHost()); intent.putExtras(b); context.startActivity(intent); }); @@ -149,10 +148,9 @@ public class PeertubeNotificationsListAdapter extends RecyclerView.Adapter { if (finalAccountAction != null) { - Intent intent = new Intent(context, ShowAccountActivity.class); + Intent intent = new Intent(context, ShowChannelActivity.class); Bundle b = new Bundle(); - b.putString("accountId", finalAccountAction.getName() + "@" + finalAccountAction.getHost()); - b.putBoolean("ischannel", true); + b.putString("channelId", finalAccountAction.getName() + "@" + finalAccountAction.getHost()); intent.putExtras(b); context.startActivity(intent); } diff --git a/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayVideosFragment.java b/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayVideosFragment.java index 74744c5..2d3d100 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayVideosFragment.java +++ b/app/src/main/java/app/fedilab/fedilabtube/fragment/DisplayVideosFragment.java @@ -46,6 +46,7 @@ import app.fedilab.fedilabtube.R; import app.fedilab.fedilabtube.client.APIResponse; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.data.AccountData.Account; +import app.fedilab.fedilabtube.client.data.PlaylistData; import app.fedilab.fedilabtube.client.data.VideoData; import app.fedilab.fedilabtube.drawer.AccountsHorizontalListAdapter; import app.fedilab.fedilabtube.drawer.PeertubeAdapter; @@ -55,9 +56,6 @@ import app.fedilab.fedilabtube.viewmodel.TimelineVM; import app.fedilab.fedilabtube.viewmodel.SearchVM; import es.dmoral.toasty.Toasty; -import static app.fedilab.fedilabtube.viewmodel.TimelineVM.Type.POVERVIEW; -import static app.fedilab.fedilabtube.viewmodel.TimelineVM.Type.PSUBSCRIPTIONS; - public class DisplayVideosFragment extends Fragment implements AccountsHorizontalListAdapter.EventListener { @@ -71,23 +69,22 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta private String max_id, max_id_accounts; private List peertubes; private List accounts; - private TimelineVM.Type type; + private TimelineVM.TimelineType timelineType; private RelativeLayout mainLoader, nextElementLoader, textviewNoAction; private boolean firstLoad; private SwipeRefreshLayout swipeRefreshLayout; private SharedPreferences sharedpreferences; private String search_peertube; private TextView textviewNoActionText; - private boolean ischannel; private View rootView; private RecyclerView lv_status; - private String targetedId; private boolean check_ScrollingUp; private String forAccount; private ConstraintLayout top_account_container; private TimelineVM viewModelFeeds; private SearchVM viewModelSearch; private AccountsVM viewModelAccounts; + private String channelId; public DisplayVideosFragment() { } @@ -105,18 +102,12 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta if (bundle != null) { search_peertube = bundle.getString("search_peertube", null); - targetedId = bundle.getString("targetedid", null); - ischannel = bundle.getBoolean("ischannel", false); - type = (TimelineVM.Type) bundle.get("type"); + channelId = bundle.getString("channelId", null); + timelineType = (TimelineVM.TimelineType) bundle.get("timelineType"); } - if (getArguments() != null && type == null) { - type = DisplayVideosFragment.fromBundle(getArguments()).getType(); - } - - - if (ischannel) { - type = TimelineVM.Type.CHANNEL; + if (getArguments() != null && timelineType == null) { + timelineType = DisplayVideosFragment.fromBundle(getArguments()).getType(); } forAccount = null; @@ -166,7 +157,7 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta swipeRefreshLayout.setOnRefreshListener(this::pullToRefresh); //Load data depending of the value if (search_peertube == null) { //Not a Peertube search - viewModelFeeds.getVideos(type, "0", targetedId, forAccount).observe(DisplayVideosFragment.this.requireActivity(), this::manageVIewVideos); + viewModelFeeds.getVideos(timelineType, "0").observe(DisplayVideosFragment.this.requireActivity(), this::manageVIewVideos); } else { viewModelSearch.getVideos("0", search_peertube).observe(DisplayVideosFragment.this.requireActivity(), this::manageVIewVideos); } @@ -185,10 +176,10 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta }); - if (type != POVERVIEW) { + if (timelineType != TimelineVM.TimelineType.OVERVIEW) { lv_status.addOnScrollListener(new RecyclerView.OnScrollListener() { public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { - if (type == PSUBSCRIPTIONS) { + if (timelineType == TimelineVM.TimelineType.SUBSCRIBTIONS) { if (dy > 0) { if (check_ScrollingUp) { top_account_container.setVisibility(View.GONE); @@ -213,7 +204,11 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta if (!flag_loading) { flag_loading = true; if (search_peertube == null) { //Not a Peertube search - viewModelFeeds.getVideos(type, max_id, null, forAccount).observe(DisplayVideosFragment.this.requireActivity(), apiResponse -> manageVIewVideos(apiResponse)); + if( timelineType != TimelineVM.TimelineType.USER_VIDEOS){ + viewModelFeeds.getVideosInChannel(channelId, max_id).observe(DisplayVideosFragment.this.requireActivity(), apiResponse -> manageVIewVideos(apiResponse)); + }else { + viewModelFeeds.getVideos(timelineType, max_id).observe(DisplayVideosFragment.this.requireActivity(), apiResponse -> manageVIewVideos(apiResponse)); + } } else { viewModelSearch.getVideos(max_id, search_peertube).observe(DisplayVideosFragment.this.requireActivity(), apiResponse -> manageVIewVideos(apiResponse)); } @@ -232,10 +227,15 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta if (!flag_loading) { flag_loading = true; if (search_peertube == null) { //Not a Peertube search - viewModelFeeds.getVideos(type, max_id, null, forAccount).observe(DisplayVideosFragment.this.requireActivity(), apiResponse -> manageVIewVideos(apiResponse)); + if( timelineType != TimelineVM.TimelineType.USER_VIDEOS){ + viewModelFeeds.getVideosInChannel(channelId, max_id).observe(DisplayVideosFragment.this.requireActivity(), apiResponse -> manageVIewVideos(apiResponse)); + }else { + viewModelFeeds.getVideos(timelineType, max_id).observe(DisplayVideosFragment.this.requireActivity(), apiResponse -> manageVIewVideos(apiResponse)); + } } else { viewModelSearch.getVideos(max_id, search_peertube).observe(DisplayVideosFragment.this.requireActivity(), apiResponse -> manageVIewVideos(apiResponse)); } + nextElementLoader.setVisibility(View.VISIBLE); } } else { @@ -246,7 +246,7 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta } }); } - if (type == PSUBSCRIPTIONS) { + if (timelineType == TimelineVM.TimelineType.SUBSCRIBTIONS) { AccountsVM viewModel = new ViewModelProvider(this).get(AccountsVM.class); viewModel.getAccounts(RetrofitPeertubeAPI.DataType.SUBSCRIBER, max_id).observe(DisplayVideosFragment.this.requireActivity(), this::manageViewAccounts); } @@ -401,7 +401,12 @@ public class DisplayVideosFragment extends Fragment implements AccountsHorizonta accountsHorizontalListAdapter.notifyItemRangeRemoved(0, accounts.size()); } if (search_peertube == null) { //Not a Peertube search - viewModelFeeds.getVideos(type, "0", targetedId, forAccount).observe(this.requireActivity(), this::manageVIewVideos); + + if( timelineType != TimelineVM.TimelineType.USER_VIDEOS){ + viewModelFeeds.getVideosInChannel(channelId, "0").observe(this.requireActivity(), this::manageVIewVideos); + }else { + viewModelFeeds.getVideos(timelineType, "0").observe(this.requireActivity(), this::manageVIewVideos); + } } else { viewModelSearch.getVideos("0", search_peertube).observe(this.requireActivity(), this::manageVIewVideos); } diff --git a/app/src/main/java/app/fedilab/fedilabtube/services/RetrieveInfoService.java b/app/src/main/java/app/fedilab/fedilabtube/services/RetrieveInfoService.java index 8c3f317..4aa1bf0 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/services/RetrieveInfoService.java +++ b/app/src/main/java/app/fedilab/fedilabtube/services/RetrieveInfoService.java @@ -31,7 +31,6 @@ import java.util.LinkedHashMap; import java.util.Objects; import app.fedilab.fedilabtube.R; -import app.fedilab.fedilabtube.client.HttpsConnection; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.entities.PeertubeInformation; import app.fedilab.fedilabtube.helper.NetworkStateReceiver; @@ -136,13 +135,8 @@ public class RetrieveInfoService extends Service implements NetworkStateReceiver peertubeInformation.setPrivacies(new LinkedHashMap<>()); peertubeInformation.setPlaylistPrivacies(new LinkedHashMap<>()); peertubeInformation.setTranslations(new LinkedHashMap<>()); - try { - peertubeInformation = new PeertubeAPI(RetrieveInfoService.this).getPeertubeInformation(); - } catch (HttpsConnection.HttpsConnectionException e) { - e.printStackTrace(); - } + peertubeInformation = new RetrofitPeertubeAPI(RetrieveInfoService.this).getPeertubeInformation(); stopForeground(true); - } }; thread.start(); diff --git a/app/src/main/java/app/fedilab/fedilabtube/sqlite/PeertubeFavoritesDAO.java b/app/src/main/java/app/fedilab/fedilabtube/sqlite/PeertubeFavoritesDAO.java deleted file mode 100644 index 42aaed0..0000000 --- a/app/src/main/java/app/fedilab/fedilabtube/sqlite/PeertubeFavoritesDAO.java +++ /dev/null @@ -1,145 +0,0 @@ -package app.fedilab.fedilabtube.sqlite; -/* Copyright 2020 Thomas Schneider - * - * This file is a part of TubeLab - * - * 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. - * - * TubeLab 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 TubeLab; if not, - * see . */ - -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 - */ - public List 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 - */ - public List 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 - */ - private List cursorToListPeertube(Cursor c) { - //No element found - if (c.getCount() == 0) { - c.close(); - return null; - } - List peertubes = new ArrayList<>(); - while (c.moveToNext()) { - //Restore cached status - try { - Peertube peertube = PeertubeAPI.parsePeertube(new JSONObject(c.getString(c.getColumnIndex(Sqlite.COL_CACHE)))); - if (peertube != null) { - peertubes.add(peertube); - } - } catch (JSONException e) { - e.printStackTrace(); - } - } - //Close the cursor - c.close(); - //Peertubes list is returned - return peertubes; - } -} diff --git a/app/src/main/java/app/fedilab/fedilabtube/viewmodel/CaptionsVM.java b/app/src/main/java/app/fedilab/fedilabtube/viewmodel/CaptionsVM.java index df808b2..bb3ff40 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/viewmodel/CaptionsVM.java +++ b/app/src/main/java/app/fedilab/fedilabtube/viewmodel/CaptionsVM.java @@ -23,12 +23,11 @@ import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; - import app.fedilab.fedilabtube.client.APIResponse; -import app.fedilab.fedilabtube.client.HttpsConnection; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; + public class CaptionsVM extends AndroidViewModel { private MutableLiveData apiResponseMutableLiveData; @@ -67,9 +66,8 @@ public class CaptionsVM extends AndroidViewModel { Context _mContext = getApplication().getApplicationContext(); new Thread(() -> { try { - String captionText = new HttpsConnection(_mContext).get(url); - APIResponse apiResponse = new APIResponse(); - apiResponse.setCaptionText(captionText); + RetrofitPeertubeAPI peertubeAPI = new RetrofitPeertubeAPI(_mContext); + APIResponse apiResponse = peertubeAPI.getCaptionContent(url); Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> apiResponseMutableLiveData.setValue(apiResponse); mainHandler.post(myRunnable); diff --git a/app/src/main/java/app/fedilab/fedilabtube/viewmodel/CommentVM.java b/app/src/main/java/app/fedilab/fedilabtube/viewmodel/CommentVM.java index 72763f7..32eff83 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/viewmodel/CommentVM.java +++ b/app/src/main/java/app/fedilab/fedilabtube/viewmodel/CommentVM.java @@ -80,8 +80,6 @@ public class CommentVM extends AndroidViewModel { } public enum action { - ADD_COMMENT, - REPLY, GET_THREAD, GET_REPLIES } diff --git a/app/src/main/java/app/fedilab/fedilabtube/viewmodel/PostActionsVM.java b/app/src/main/java/app/fedilab/fedilabtube/viewmodel/PostActionsVM.java index 0fe984e..402d039 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/viewmodel/PostActionsVM.java +++ b/app/src/main/java/app/fedilab/fedilabtube/viewmodel/PostActionsVM.java @@ -48,6 +48,12 @@ public class PostActionsVM extends AndroidViewModel { return apiResponseMutableLiveData; } + public LiveData comment(RetrofitPeertubeAPI.ActionType type, String videoId, String commentId, String content) { + apiResponseMutableLiveData = new MutableLiveData<>(); + postComment(type, videoId, commentId, content); + return apiResponseMutableLiveData; + } + private void makeAction(RetrofitPeertubeAPI.ActionType apiAction, String id, String element) { Context _mContext = getApplication().getApplicationContext(); new Thread(() -> { @@ -78,4 +84,20 @@ public class PostActionsVM extends AndroidViewModel { }).start(); } + + private void postComment(RetrofitPeertubeAPI.ActionType type, String videoId, String commentId, String content) { + Context _mContext = getApplication().getApplicationContext(); + new Thread(() -> { + try { + RetrofitPeertubeAPI peertubeAPI = new RetrofitPeertubeAPI(_mContext); + APIResponse apiResponse = peertubeAPI.commentAction(type, videoId, commentId, content); + Handler mainHandler = new Handler(Looper.getMainLooper()); + Runnable myRunnable = () -> apiResponseMutableLiveData.setValue(apiResponse); + mainHandler.post(myRunnable); + } catch (Exception e) { + e.printStackTrace(); + } + }).start(); + } + } diff --git a/app/src/main/java/app/fedilab/fedilabtube/viewmodel/TimelineVM.java b/app/src/main/java/app/fedilab/fedilabtube/viewmodel/TimelineVM.java index 5265d4e..789d7a5 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/viewmodel/TimelineVM.java +++ b/app/src/main/java/app/fedilab/fedilabtube/viewmodel/TimelineVM.java @@ -48,6 +48,26 @@ public class TimelineVM extends AndroidViewModel { return apiResponseMutableLiveData; } + public LiveData getVideosInChannel(String channelId, String max_id) { + apiResponseMutableLiveData = new MutableLiveData<>(); + loadVideosForChannel(channelId, max_id); + return apiResponseMutableLiveData; + } + + private void loadVideosForChannel(String channelId, String max_id) { + Context _mContext = getApplication().getApplicationContext(); + new Thread(() -> { + try { + RetrofitPeertubeAPI retrofitPeertubeAPI = new RetrofitPeertubeAPI(_mContext); + APIResponse apiResponse = retrofitPeertubeAPI.getVideosForChannel(channelId, max_id); + Handler mainHandler = new Handler(Looper.getMainLooper()); + Runnable myRunnable = () -> apiResponseMutableLiveData.setValue(apiResponse); + mainHandler.post(myRunnable); + } catch (Exception e) { + e.printStackTrace(); + } + }).start(); + } private void getSingle(String videoId) { Context _mContext = getApplication().getApplicationContext(); @@ -77,10 +97,10 @@ public class TimelineVM extends AndroidViewModel { if (timeline == null) return; APIResponse apiResponse; - if( timeline != TimelineType.OVERVIEW) { - apiResponse = retrofitPeertubeAPI.getTL(timeline, max_id); - }else{ + if( timeline == TimelineType.OVERVIEW) { apiResponse = retrofitPeertubeAPI.getOverviewVideo(max_id); + }else{ + apiResponse = retrofitPeertubeAPI.getTL(timeline, max_id); } Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> apiResponseMutableLiveData.setValue(apiResponse); @@ -93,6 +113,7 @@ public class TimelineVM extends AndroidViewModel { public enum TimelineType { + USER_VIDEOS, SUBSCRIBTIONS, MY_VIDEOS, LOCAL, diff --git a/app/src/main/res/layout/activity_show_account.xml b/app/src/main/res/layout/activity_show_account.xml index 212d12a..8acf84a 100644 --- a/app/src/main/res/layout/activity_show_account.xml +++ b/app/src/main/res/layout/activity_show_account.xml @@ -20,7 +20,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" - tools:context=".ShowAccountActivity"> + tools:context=".ShowChannelActivity"> + android:defaultValue="OVERVIEW" + app:argType="app.fedilab.fedilabtube.viewmodel.TimelineVM$TimelineType" /> @@ -24,8 +24,8 @@ tools:layout="@layout/fragment_video"> + android:defaultValue="TRENDING" + app:argType="app.fedilab.fedilabtube.viewmodel.TimelineVM$TimelineType" /> + android:defaultValue="MOST_LIKED" + app:argType="app.fedilab.fedilabtube.viewmodel.TimelineVM$TimelineType" /> @@ -47,8 +47,8 @@ tools:layout="@layout/fragment_video"> + android:defaultValue="RECENT" + app:argType="app.fedilab.fedilabtube.viewmodel.TimelineVM$TimelineType" /> @@ -59,7 +59,7 @@ tools:layout="@layout/fragment_video"> + android:defaultValue="LOCAL" + app:argType="app.fedilab.fedilabtube.viewmodel.TimelineVM$TimelineType" /> \ No newline at end of file diff --git a/app/src/main/res/navigation/mobile_navigation_connected.xml b/app/src/main/res/navigation/mobile_navigation_connected.xml index 4375c05..b9d3fc3 100644 --- a/app/src/main/res/navigation/mobile_navigation_connected.xml +++ b/app/src/main/res/navigation/mobile_navigation_connected.xml @@ -12,8 +12,8 @@ tools:layout="@layout/fragment_video"> + android:defaultValue="OVERVIEW" + app:argType="app.fedilab.fedilabtube.viewmodel.TimelineVM$TimelineType" /> @@ -24,8 +24,8 @@ tools:layout="@layout/fragment_video"> + android:defaultValue="SUBSCRIBTIONS" + app:argType="app.fedilab.fedilabtube.viewmodel.TimelineVM$TimelineType" /> @@ -36,8 +36,8 @@ tools:layout="@layout/fragment_video"> + android:defaultValue="TRENDING" + app:argType="app.fedilab.fedilabtube.viewmodel.TimelineVM$TimelineType" /> + android:defaultValue="MOST_LIKED" + app:argType="app.fedilab.fedilabtube.viewmodel.TimelineVM$TimelineType" /> @@ -59,8 +59,8 @@ tools:layout="@layout/fragment_video"> + android:defaultValue="RECENT" + app:argType="app.fedilab.fedilabtube.viewmodel.TimelineVM$TimelineType" /> \ No newline at end of file