Change displayed videos when clicking a followed account

This commit is contained in:
Thomas 2020-09-03 18:57:10 +02:00
parent 38e9d9f090
commit c82e9e2ad2
13 changed files with 167 additions and 69 deletions

View File

@ -25,7 +25,7 @@ import android.text.SpannableString;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@ -79,7 +79,7 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
private List<Status> statuses;
private StatusListAdapter statusListAdapter;
private ImageButton account_follow;
private Button account_follow;
private ViewPager mPager;
private TabLayout tabLayout;
private TextView account_note;
@ -93,7 +93,7 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
private Account account;
private String accountId;
private boolean ischannel;
private AsyncTask<Void, Void, Void> retrieveRelationship;
private AsyncTask<Void, Void, List<Relationship>> retrieveRelationship;
private action doAction;
@Override
@ -353,16 +353,15 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
}
@Override
public void onRetrieveRelationship(Relationship relationship, Error error) {
public void onRetrieveRelationship(List<Relationship> relationships, Error error) {
if (error != null) {
Toasty.error(ShowAccountActivity.this, error.getError(), Toast.LENGTH_LONG).show();
return;
}
this.relationship = relationship;
this.relationship = relationships.get(0);
manageButtonVisibility();
//The authenticated account is followed by the account
if (relationship != null && relationship.isFollowed_by() && !accountId.equals(userId)) {
TextView account_followed_by = findViewById(R.id.account_followed_by);
@ -395,26 +394,24 @@ public class ShowAccountActivity extends AppCompatActivity implements OnPostActi
}
account_follow.setEnabled(true);
if (relationship.isFollowing()) {
account_follow.setImageResource(R.drawable.ic_user_minus);
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)));
}
doAction = action.UNFOLLOW;
account_follow.setContentDescription(getString(R.string.action_unfollow));
if (ischannel) {
account_follow.setVisibility(View.VISIBLE);
} else {
account_follow.setVisibility(View.GONE);
}
} else if (!relationship.isFollowing()) {
account_follow.setImageResource(R.drawable.ic_user_plus);
account_follow.setText(R.string.action_follow);
doAction = action.FOLLOW;
if (ischannel) {
account_follow.setVisibility(View.VISIBLE);
} else {
account_follow.setVisibility(View.GONE);
}
account_follow.setContentDescription(getString(R.string.action_follow));
} else {
account_follow.setVisibility(View.GONE);
doAction = action.NOTHING;

View File

@ -38,7 +38,7 @@ public class RetrieveFeedsAsyncTask extends AsyncTask<Void, Void, Void> {
private OnRetrieveFeedsInterface listener;
private WeakReference<Context> contextReference;
private String target;
private String forAccount;
public RetrieveFeedsAsyncTask(Context context, Type action, String max_id, OnRetrieveFeedsInterface onRetrieveFeedsInterface) {
this.contextReference = new WeakReference<>(context);
@ -56,6 +56,15 @@ public class RetrieveFeedsAsyncTask extends AsyncTask<Void, Void, Void> {
this.target = target;
}
public RetrieveFeedsAsyncTask(Context context, Type action, String max_id, String target, String forAccount, OnRetrieveFeedsInterface onRetrieveFeedsInterface) {
this.contextReference = new WeakReference<>(context);
this.action = action;
this.max_id = max_id;
this.listener = onRetrieveFeedsInterface;
this.target = target;
this.forAccount = forAccount;
}
@Override
protected Void doInBackground(Void... params) {
@ -88,7 +97,11 @@ public class RetrieveFeedsAsyncTask extends AsyncTask<Void, Void, Void> {
break;
case PSUBSCRIPTIONS:
peertubeAPI = new PeertubeAPI(this.contextReference.get());
apiResponse = peertubeAPI.getSubscriptionsTL(max_id);
if (forAccount == null) {
apiResponse = peertubeAPI.getSubscriptionsTL(max_id);
} else {
apiResponse = peertubeAPI.getVideosChannel(forAccount, max_id);
}
break;
case POVERVIEW:
peertubeAPI = new PeertubeAPI(this.contextReference.get());

View File

@ -18,6 +18,7 @@ import android.content.Context;
import android.os.AsyncTask;
import java.lang.ref.WeakReference;
import java.util.List;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Error;
@ -25,11 +26,10 @@ import app.fedilab.fedilabtube.client.entities.Relationship;
import app.fedilab.fedilabtube.interfaces.OnRetrieveRelationshipInterface;
public class RetrieveRelationshipAsyncTask extends AsyncTask<Void, Void, Void> {
public class RetrieveRelationshipAsyncTask extends AsyncTask<Void, Void, List<Relationship>> {
private String accountId;
private Relationship relationship;
private OnRetrieveRelationshipInterface listener;
private Error error;
private WeakReference<Context> contextReference;
@ -41,18 +41,17 @@ public class RetrieveRelationshipAsyncTask extends AsyncTask<Void, Void, Void> {
}
@Override
protected Void doInBackground(Void... params) {
protected List<Relationship> doInBackground(Void... params) {
PeertubeAPI api = new PeertubeAPI(this.contextReference.get());
relationship = new Relationship();
relationship.setFollowing(api.isFollowing(accountId));
List<Relationship> relationships = api.isFollowing(accountId);
error = api.getError();
return null;
return relationships;
}
@Override
protected void onPostExecute(Void result) {
listener.onRetrieveRelationship(relationship, error);
protected void onPostExecute(List<Relationship> relationships) {
listener.onRetrieveRelationship(relationships, error);
}
}

View File

@ -56,6 +56,7 @@ import app.fedilab.fedilabtube.client.entities.PeertubeNotification;
import app.fedilab.fedilabtube.client.entities.PeertubeVideoNotification;
import app.fedilab.fedilabtube.client.entities.Playlist;
import app.fedilab.fedilabtube.client.entities.PlaylistElement;
import app.fedilab.fedilabtube.client.entities.Relationship;
import app.fedilab.fedilabtube.client.entities.Status;
import app.fedilab.fedilabtube.helper.Helper;
import app.fedilab.fedilabtube.sqlite.AccountDAO;
@ -897,27 +898,37 @@ public class PeertubeAPI {
return account;
}
public List<Relationship> isFollowing(String uri) {
ArrayList<String> uris = new ArrayList<>();
uris.add(uri);
return isFollowing(uris);
}
/**
* Returns a relationship between the authenticated account and an account
*
* @param uri String accounts fetched
* @param uris Array String accounts uri fetched
* @return Relationship entity
*/
public boolean isFollowing(String uri) {
public List<Relationship> isFollowing(ArrayList<String> uris) {
HashMap<String, String> params = new HashMap<>();
params.put("uris", uri);
StringBuilder parameters = new StringBuilder();
for (String uri : uris)
parameters.append("uris[]=").append(uri).append("&");
parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(7));
params.put("uris[]", parameters.toString());
try {
HttpsConnection httpsConnection = new HttpsConnection(context);
String response = httpsConnection.get(getAbsoluteUrl("/users/me/subscriptions/exist"), 60, params, prefKeyOauthTokenT);
return new JSONObject(response).getBoolean(uri);
return parseRelationShip(uris, new JSONObject(response));
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
} catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) {
e.printStackTrace();
}
return false;
return null;
}
/**
@ -1749,6 +1760,28 @@ public class PeertubeAPI {
return apiResponse;
}
/**
* Parse json response for peertube relationship
*
* @param jsonObject JSONObject
* @return List<Relationship>
*/
private List<Relationship> parseRelationShip(ArrayList<String> uris, JSONObject jsonObject) {
List<Relationship> relationships = new ArrayList<>();
try {
for (String uri : uris) {
Relationship relationship = new Relationship();
relationship.setId(uri);
relationship.setFollowing(jsonObject.getBoolean(uri));
relationships.add(relationship);
}
return relationships;
} catch (JSONException e) {
setDefaultError(e);
}
return null;
}
/**
* Parse json response for peertube notifications
*

View File

@ -80,6 +80,7 @@ public class Account implements Parcelable {
private String invite_request;
private String created_by_application_id;
private String invited_by_account_id;
private boolean isSelected;
public Account() {
}
@ -216,6 +217,14 @@ public class Account implements Parcelable {
this.muting_notifications = muting_notifications;
}
public boolean isSelected() {
return isSelected;
}
public void setSelected(boolean selected) {
isSelected = selected;
}
public String getHost() {
return host;

View File

@ -15,22 +15,23 @@ package app.fedilab.fedilabtube.drawer;
* see <http://www.gnu.org/licenses>. */
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.ColorUtils;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import app.fedilab.fedilabtube.R;
import app.fedilab.fedilabtube.ShowAccountActivity;
import app.fedilab.fedilabtube.client.PeertubeAPI;
import app.fedilab.fedilabtube.client.entities.Account;
import app.fedilab.fedilabtube.client.entities.Error;
@ -41,14 +42,15 @@ import es.dmoral.toasty.Toasty;
public class AccountsHorizontalListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements OnPostActionInterface {
EventListener listener;
private List<Account> accounts;
private Context context;
private AccountsHorizontalListAdapter accountsListAdapter;
public AccountsHorizontalListAdapter(List<Account> accounts) {
public AccountsHorizontalListAdapter(List<Account> accounts, EventListener listener) {
this.accounts = accounts;
this.accountsListAdapter = this;
this.listener = listener;
}
@NonNull
@ -71,16 +73,12 @@ public class AccountsHorizontalListAdapter extends RecyclerView.Adapter<Recycler
//Profile picture
Helper.loadGiF(context, account, holder.account_pp, 270);
holder.account_pp.setOnClickListener(v -> {
Intent intent = new Intent(context, ShowAccountActivity.class);
Bundle b = new Bundle();
b.putBoolean("peertubeaccount", true);
b.putBoolean("ischannel", true);
b.putString("targetedid", account.getAcct());
b.putParcelable("account", account);
intent.putExtras(b);
context.startActivity(intent);
});
if (account.isSelected()) {
holder.main_container.setBackgroundColor(ColorUtils.setAlphaComponent(ContextCompat.getColor(context, R.color.colorAccent), 50));
} else {
holder.main_container.setBackgroundColor(Color.TRANSPARENT);
}
}
@ -145,15 +143,36 @@ public class AccountsHorizontalListAdapter extends RecyclerView.Adapter<Recycler
}
}
public interface EventListener {
void click(String forAccount);
}
private static class ViewHolder extends RecyclerView.ViewHolder {
private class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
ImageView account_pp;
TextView account_dn;
LinearLayout main_container;
ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
account_pp = itemView.findViewById(R.id.account_pp);
account_dn = itemView.findViewById(R.id.account_dn);
main_container = itemView.findViewById(R.id.main_container);
}
@Override
public void onClick(View v) {
Account account = accounts.get(getAdapterPosition());
listener.click(account.getAcct());
for (Account acc : accounts) {
if (acc.getAcct().compareTo(account.getAcct()) == 0) {
acc.setSelected(true);
} else {
acc.setSelected(false);
}
}
notifyItemRangeChanged(0, accounts.size());
}
}

View File

@ -74,7 +74,7 @@ public class PeertubeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, "");
boolean ownVideos = peertube.getAccount().getInstance().compareTo(Helper.getLiveInstance(context)) == 0 && peertube.getAccount().getId().compareTo(userId) == 0;
boolean ownVideos = peertube.getAccount().getInstance().compareTo(Helper.getLiveInstance(context)) == 0 && userId != null && peertube.getAccount().getId() != null && peertube.getAccount().getId().compareTo(userId) == 0;
holder.peertube_account_name.setText(account.getAcct());
holder.peertube_title.setText(peertube.getName());

View File

@ -25,6 +25,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
@ -62,7 +63,7 @@ import static app.fedilab.fedilabtube.asynctasks.RetrieveFeedsAsyncTask.Type.POV
import static app.fedilab.fedilabtube.asynctasks.RetrieveFeedsAsyncTask.Type.PSUBSCRIPTIONS;
public class DisplayStatusFragment extends Fragment implements OnPostActionInterface, OnRetrieveFeedsInterface, OnRetrieveAccountsInterface {
public class DisplayStatusFragment extends Fragment implements OnPostActionInterface, OnRetrieveFeedsInterface, OnRetrieveAccountsInterface, AccountsHorizontalListAdapter.EventListener {
private LinearLayoutManager mLayoutManager;
@ -88,6 +89,8 @@ public class DisplayStatusFragment extends Fragment implements OnPostActionInter
private RecyclerView lv_accounts;
private String targetedId;
private boolean check_ScrollingUp;
private Button display_all;
private String forAccount;
public DisplayStatusFragment() {
}
@ -119,10 +122,10 @@ public class DisplayStatusFragment extends Fragment implements OnPostActionInter
type = RetrieveFeedsAsyncTask.Type.CHANNEL;
}
forAccount = null;
lv_status = rootView.findViewById(R.id.lv_status);
lv_accounts = rootView.findViewById(R.id.lv_accounts);
display_all = rootView.findViewById(R.id.display_all);
max_id = null;
max_id_accounts = null;
flag_loading = true;
@ -143,7 +146,7 @@ public class DisplayStatusFragment extends Fragment implements OnPostActionInter
peertubeAdapater = new PeertubeAdapter(this.peertubes);
lv_status.setAdapter(peertubeAdapater);
accountsHorizontalListAdapter = new AccountsHorizontalListAdapter(this.accounts);
accountsHorizontalListAdapter = new AccountsHorizontalListAdapter(this.accounts, this);
LinearLayoutManager layoutManager
= new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false);
lv_accounts.setLayoutManager(layoutManager);
@ -260,6 +263,10 @@ public class DisplayStatusFragment extends Fragment implements OnPostActionInter
new RetrieveAccountSubscriptionsAsyncTask(context, max_id, DisplayStatusFragment.this).execute();
}
display_all.setOnClickListener(v -> {
forAccount = null;
pullToRefresh();
});
return rootView;
}
@ -311,6 +318,7 @@ public class DisplayStatusFragment extends Fragment implements OnPostActionInter
if (apiResponse != null && apiResponse.getAccounts() != null && apiResponse.getAccounts().size() > 0) {
if (lv_accounts.getVisibility() == View.GONE) {
lv_accounts.setVisibility(View.VISIBLE);
display_all.setVisibility(View.VISIBLE);
}
int previousPosition = accounts.size();
accounts.addAll(apiResponse.getAccounts());
@ -396,17 +404,15 @@ public class DisplayStatusFragment extends Fragment implements OnPostActionInter
public void pullToRefresh() {
if (peertubes.size() > 0) {
int size = peertubes.size();
peertubes.clear();
peertubes = new ArrayList<>();
max_id = "0";
peertubeAdapater.notifyItemRangeRemoved(0, size);
if (search_peertube == null) { //Not a Peertube search
asyncTask = new RetrieveFeedsAsyncTask(context, type, "0", targetedId, DisplayStatusFragment.this).execute();
} else {
asyncTask = new RetrievePeertubeSearchAsyncTask(context, "0", search_peertube, DisplayStatusFragment.this).execute();
}
int size = peertubes.size();
peertubes.clear();
peertubes = new ArrayList<>();
max_id = "0";
peertubeAdapater.notifyItemRangeRemoved(0, size);
if (search_peertube == null) { //Not a Peertube search
asyncTask = new RetrieveFeedsAsyncTask(context, type, "0", targetedId, forAccount, DisplayStatusFragment.this).execute();
} else {
asyncTask = new RetrievePeertubeSearchAsyncTask(context, "0", search_peertube, DisplayStatusFragment.this).execute();
}
}
@ -416,6 +422,11 @@ public class DisplayStatusFragment extends Fragment implements OnPostActionInter
}
@Override
public void click(String forAccount) {
this.forAccount = forAccount;
pullToRefresh();
}
static class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {

View File

@ -14,9 +14,11 @@ package app.fedilab.fedilabtube.interfaces;
* You should have received a copy of the GNU General Public License along with TubeLab; if not,
* see <http://www.gnu.org/licenses>. */
import java.util.List;
import app.fedilab.fedilabtube.client.entities.Error;
import app.fedilab.fedilabtube.client.entities.Relationship;
public interface OnRetrieveRelationshipInterface {
void onRetrieveRelationship(Relationship relationship, Error error);
void onRetrieveRelationship(List<Relationship> relationships, Error error);
}

View File

@ -55,7 +55,7 @@
android:layout_marginEnd="10dp"
android:contentDescription="@string/go_back"
android:src="@drawable/ic_baseline_arrow_back_24"
android:tint="@android:color/white"
app:tint="@android:color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@ -121,11 +121,11 @@
</LinearLayout>
<ImageButton
<Button
android:id="@+id/account_follow"
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:contentDescription="@string/make_an_action"
@ -134,11 +134,11 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/names_container" />
<ImageButton
<Button
android:id="@+id/header_edit_profile"
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:contentDescription="@string/edit_profile"

View File

@ -23,6 +23,7 @@
android:orientation="vertical">
<ImageView
android:padding="2dp"
android:id="@+id/account_pp"
android:layout_width="50dp"
android:layout_height="50dp"

View File

@ -29,10 +29,23 @@
<!-- Scrollview for displaying accounts in bubbles -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/lv_accounts"
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toLeftOf="@+id/display_all"
/>
<Button
android:id="@+id/display_all"
android:layout_width="wrap_content"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_height="wrap_content"
android:text="@string/all"
android:visibility="gone"
app:layout_constraintLeft_toRightOf="@+id/lv_accounts"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="@+id/lv_accounts"
/>
<FrameLayout
android:layout_width="match_parent"

View File

@ -111,7 +111,7 @@
<string name="nothing_to_do">Aucune action ne peut être réalisée</string>
<string name="unfollow_confirm">Voulez-vous vous désabonner de ce compte ?</string>
<string name="action_unfollow">Se désabonner</string>
<string name="action_follow">Suivre</string>
<string name="action_follow">S\'abonner</string>
<string name="search">Chercher</string>
<string name="toast_error_search">Une erreur sest produite lors de la recherche!</string>
<string name="no_result">Aucun résultat !</string>
@ -174,4 +174,5 @@
<string name="successful_report">Le compte a été signalé !</string>
<string name="successful_video_report">La vidéo a été signalée !</string>
<string name="report_comment_size">Veuillez préciser les raisons.</string>
<string name="all">Tous</string>
</resources>