forked from mirrors/Fedilab
Familiar followers on profiles
This commit is contained in:
parent
098e2d87ec
commit
c37f4bb643
8 changed files with 192 additions and 2 deletions
|
@ -34,6 +34,7 @@ import android.text.method.LinkMovementMethod;
|
||||||
import android.text.style.ForegroundColorSpan;
|
import android.text.style.ForegroundColorSpan;
|
||||||
import android.text.style.UnderlineSpan;
|
import android.text.style.UnderlineSpan;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -76,6 +77,7 @@ import app.fedilab.android.BaseMainActivity;
|
||||||
import app.fedilab.android.R;
|
import app.fedilab.android.R;
|
||||||
import app.fedilab.android.client.entities.api.Account;
|
import app.fedilab.android.client.entities.api.Account;
|
||||||
import app.fedilab.android.client.entities.api.Attachment;
|
import app.fedilab.android.client.entities.api.Attachment;
|
||||||
|
import app.fedilab.android.client.entities.api.FamiliarFollowers;
|
||||||
import app.fedilab.android.client.entities.api.Field;
|
import app.fedilab.android.client.entities.api.Field;
|
||||||
import app.fedilab.android.client.entities.api.IdentityProof;
|
import app.fedilab.android.client.entities.api.IdentityProof;
|
||||||
import app.fedilab.android.client.entities.api.MastodonList;
|
import app.fedilab.android.client.entities.api.MastodonList;
|
||||||
|
@ -86,6 +88,7 @@ import app.fedilab.android.client.entities.app.RemoteInstance;
|
||||||
import app.fedilab.android.client.entities.app.Timeline;
|
import app.fedilab.android.client.entities.app.Timeline;
|
||||||
import app.fedilab.android.client.entities.app.WellKnownNodeinfo;
|
import app.fedilab.android.client.entities.app.WellKnownNodeinfo;
|
||||||
import app.fedilab.android.databinding.ActivityProfileBinding;
|
import app.fedilab.android.databinding.ActivityProfileBinding;
|
||||||
|
import app.fedilab.android.databinding.NotificationsRelatedAccountsBinding;
|
||||||
import app.fedilab.android.exception.DBException;
|
import app.fedilab.android.exception.DBException;
|
||||||
import app.fedilab.android.helper.CrossActionHelper;
|
import app.fedilab.android.helper.CrossActionHelper;
|
||||||
import app.fedilab.android.helper.Helper;
|
import app.fedilab.android.helper.Helper;
|
||||||
|
@ -106,6 +109,7 @@ public class ProfileActivity extends BaseActivity {
|
||||||
|
|
||||||
|
|
||||||
private RelationShip relationship;
|
private RelationShip relationship;
|
||||||
|
private FamiliarFollowers familiarFollowers;
|
||||||
private Account account;
|
private Account account;
|
||||||
private ScheduledExecutorService scheduledExecutorService;
|
private ScheduledExecutorService scheduledExecutorService;
|
||||||
private action doAction;
|
private action doAction;
|
||||||
|
@ -255,6 +259,13 @@ public class ProfileActivity extends BaseActivity {
|
||||||
updateAccount();
|
updateAccount();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
accountsVM.getFamiliarFollowers(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, accountListToCheck).observe(ProfileActivity.this, familiarFollowersList -> {
|
||||||
|
if (familiarFollowersList != null && familiarFollowersList.size() > 0) {
|
||||||
|
this.familiarFollowers = familiarFollowersList.get(0);
|
||||||
|
updateAccount();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
//Retrieve identity proofs
|
//Retrieve identity proofs
|
||||||
accountsVM.getIdentityProofs(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, account.id).observe(ProfileActivity.this, identityProofs -> {
|
accountsVM.getIdentityProofs(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, account.id).observe(ProfileActivity.this, identityProofs -> {
|
||||||
this.identityProofList = identityProofs;
|
this.identityProofList = identityProofs;
|
||||||
|
@ -567,6 +578,27 @@ public class ProfileActivity extends BaseActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (familiarFollowers != null && familiarFollowers.accounts != null && familiarFollowers.accounts.size() > 0) {
|
||||||
|
binding.relatedAccounts.removeAllViews();
|
||||||
|
for (Account account : familiarFollowers.accounts) {
|
||||||
|
NotificationsRelatedAccountsBinding notificationsRelatedAccountsBinding = NotificationsRelatedAccountsBinding.inflate(LayoutInflater.from(ProfileActivity.this));
|
||||||
|
MastodonHelper.loadProfileMediaMastodonRound(ProfileActivity.this, notificationsRelatedAccountsBinding.profilePicture, account);
|
||||||
|
notificationsRelatedAccountsBinding.acc.setText(account.username);
|
||||||
|
notificationsRelatedAccountsBinding.relatedAccountContainer.setOnClickListener(v -> {
|
||||||
|
Intent intent = new Intent(ProfileActivity.this, ProfileActivity.class);
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.putSerializable(Helper.ARG_ACCOUNT, account);
|
||||||
|
intent.putExtras(b);
|
||||||
|
ActivityOptionsCompat options = ActivityOptionsCompat
|
||||||
|
.makeSceneTransitionAnimation(ProfileActivity.this, notificationsRelatedAccountsBinding.profilePicture, getString(R.string.activity_porfile_pp));
|
||||||
|
// start the new activity
|
||||||
|
startActivity(intent, options.toBundle());
|
||||||
|
});
|
||||||
|
binding.relatedAccounts.addView(notificationsRelatedAccountsBinding.getRoot());
|
||||||
|
}
|
||||||
|
binding.familiarFollowers.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
binding.accountFollow.setEnabled(true);
|
binding.accountFollow.setEnabled(true);
|
||||||
//Visibility depending of the relationship
|
//Visibility depending of the relationship
|
||||||
if (relationship != null) {
|
if (relationship != null) {
|
||||||
|
|
|
@ -18,6 +18,7 @@ package app.fedilab.android.client.endpoints;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import app.fedilab.android.client.entities.api.Account;
|
import app.fedilab.android.client.entities.api.Account;
|
||||||
|
import app.fedilab.android.client.entities.api.FamiliarFollowers;
|
||||||
import app.fedilab.android.client.entities.api.FeaturedTag;
|
import app.fedilab.android.client.entities.api.FeaturedTag;
|
||||||
import app.fedilab.android.client.entities.api.IdentityProof;
|
import app.fedilab.android.client.entities.api.IdentityProof;
|
||||||
import app.fedilab.android.client.entities.api.MastodonList;
|
import app.fedilab.android.client.entities.api.MastodonList;
|
||||||
|
@ -253,6 +254,13 @@ public interface MastodonAccountsService {
|
||||||
@Query("id[]") List<String> ids
|
@Query("id[]") List<String> ids
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//Get familiar followers
|
||||||
|
@GET("accounts/familiar_followers ")
|
||||||
|
Call<List<FamiliarFollowers>> getFamiliarFollowers(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Query("id[]") List<String> ids
|
||||||
|
);
|
||||||
|
|
||||||
//Get search
|
//Get search
|
||||||
@GET("accounts/search")
|
@GET("accounts/search")
|
||||||
Call<List<Account>> searchAccounts(
|
Call<List<Account>> searchAccounts(
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package app.fedilab.android.client.entities.api;
|
||||||
|
/* Copyright 2022 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Fedilab
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class FamiliarFollowers implements Serializable {
|
||||||
|
|
||||||
|
@SerializedName("id")
|
||||||
|
public String id;
|
||||||
|
@SerializedName("accounts")
|
||||||
|
public List<Account> accounts;
|
||||||
|
}
|
|
@ -40,6 +40,9 @@ import androidx.work.OneTimeWorkRequest;
|
||||||
import androidx.work.WorkManager;
|
import androidx.work.WorkManager;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||||
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||||
|
import com.bumptech.glide.request.RequestOptions;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
@ -268,6 +271,52 @@ public class MastodonHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void loadProfileMediaMastodonRound(Activity activity, ImageView view, Account account) {
|
||||||
|
Context context = view.getContext();
|
||||||
|
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
boolean disableGif = sharedpreferences.getBoolean(context.getString(R.string.SET_DISABLE_GIF), false);
|
||||||
|
@DrawableRes int placeholder = R.drawable.ic_person;
|
||||||
|
if (Helper.isValidContextForGlide(activity != null ? activity : context)) {
|
||||||
|
if (account == null) {
|
||||||
|
Glide.with(activity != null ? activity : context)
|
||||||
|
.asDrawable()
|
||||||
|
.load(placeholder)
|
||||||
|
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(16)))
|
||||||
|
.thumbnail(0.1f)
|
||||||
|
.placeholder(placeholder)
|
||||||
|
.into(view);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String targetedUrl = disableGif ? account.avatar_static : account.avatar;
|
||||||
|
if (targetedUrl != null) {
|
||||||
|
if (disableGif || (!targetedUrl.endsWith(".gif"))) {
|
||||||
|
Glide.with(activity != null ? activity : context)
|
||||||
|
.asDrawable()
|
||||||
|
.load(targetedUrl)
|
||||||
|
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
|
||||||
|
.thumbnail(0.1f)
|
||||||
|
.placeholder(placeholder)
|
||||||
|
.into(view);
|
||||||
|
} else {
|
||||||
|
Glide.with(activity != null ? activity : context)
|
||||||
|
.asGif()
|
||||||
|
.load(targetedUrl)
|
||||||
|
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
|
||||||
|
.thumbnail(0.1f)
|
||||||
|
.placeholder(placeholder)
|
||||||
|
.into(view);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Glide.with(activity != null ? activity : context)
|
||||||
|
.asDrawable()
|
||||||
|
.load(placeholder)
|
||||||
|
.apply(new RequestOptions().transform(new CenterCrop(), new RoundedCorners(10)))
|
||||||
|
.thumbnail(0.1f)
|
||||||
|
.into(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a date in String -> format yyyy-MM-dd HH:mm:ss
|
* Convert a date in String -> format yyyy-MM-dd HH:mm:ss
|
||||||
*
|
*
|
||||||
|
|
|
@ -38,6 +38,7 @@ import app.fedilab.android.client.endpoints.MastodonAccountsService;
|
||||||
import app.fedilab.android.client.entities.api.Account;
|
import app.fedilab.android.client.entities.api.Account;
|
||||||
import app.fedilab.android.client.entities.api.Accounts;
|
import app.fedilab.android.client.entities.api.Accounts;
|
||||||
import app.fedilab.android.client.entities.api.Domains;
|
import app.fedilab.android.client.entities.api.Domains;
|
||||||
|
import app.fedilab.android.client.entities.api.FamiliarFollowers;
|
||||||
import app.fedilab.android.client.entities.api.FeaturedTag;
|
import app.fedilab.android.client.entities.api.FeaturedTag;
|
||||||
import app.fedilab.android.client.entities.api.Field;
|
import app.fedilab.android.client.entities.api.Field;
|
||||||
import app.fedilab.android.client.entities.api.Filter;
|
import app.fedilab.android.client.entities.api.Filter;
|
||||||
|
@ -90,6 +91,7 @@ public class AccountsVM extends AndroidViewModel {
|
||||||
private MutableLiveData<List<IdentityProof>> identityProofListMutableLiveData;
|
private MutableLiveData<List<IdentityProof>> identityProofListMutableLiveData;
|
||||||
private MutableLiveData<RelationShip> relationShipMutableLiveData;
|
private MutableLiveData<RelationShip> relationShipMutableLiveData;
|
||||||
private MutableLiveData<List<RelationShip>> relationShipListMutableLiveData;
|
private MutableLiveData<List<RelationShip>> relationShipListMutableLiveData;
|
||||||
|
private MutableLiveData<List<FamiliarFollowers>> familiarFollowersListMutableLiveData;
|
||||||
private MutableLiveData<Filter> filterMutableLiveData;
|
private MutableLiveData<Filter> filterMutableLiveData;
|
||||||
private MutableLiveData<List<Filter>> filterListMutableLiveData;
|
private MutableLiveData<List<Filter>> filterListMutableLiveData;
|
||||||
private MutableLiveData<List<Tag>> tagListMutableLiveData;
|
private MutableLiveData<List<Tag>> tagListMutableLiveData;
|
||||||
|
@ -1025,6 +1027,38 @@ public class AccountsVM extends AndroidViewModel {
|
||||||
return relationShipListMutableLiveData;
|
return relationShipListMutableLiveData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain a list of all accounts that follow a given account, filtered for accounts you follow.
|
||||||
|
*
|
||||||
|
* @param ids {@link List} of account IDs to check
|
||||||
|
* @return {@link LiveData} containing a {@link List} of {@link FamiliarFollowers}s to given account(s)
|
||||||
|
*/
|
||||||
|
public LiveData<List<FamiliarFollowers>> getFamiliarFollowers(@NonNull String instance, String token, @NonNull List<String> ids) {
|
||||||
|
familiarFollowersListMutableLiveData = new MutableLiveData<>();
|
||||||
|
MastodonAccountsService mastodonAccountsService = init(instance);
|
||||||
|
new Thread(() -> {
|
||||||
|
List<FamiliarFollowers> familiarFollowers = null;
|
||||||
|
Call<List<FamiliarFollowers>> familiarFollowersCall = mastodonAccountsService.getFamiliarFollowers(token, ids);
|
||||||
|
|
||||||
|
if (familiarFollowersCall != null) {
|
||||||
|
try {
|
||||||
|
Response<List<FamiliarFollowers>> familiarFollowersResponse = familiarFollowersCall.execute();
|
||||||
|
if (familiarFollowersResponse.isSuccessful()) {
|
||||||
|
familiarFollowers = familiarFollowersResponse.body();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||||
|
List<FamiliarFollowers> finalFamiliarFollowers = familiarFollowers;
|
||||||
|
Runnable myRunnable = () -> familiarFollowersListMutableLiveData.setValue(finalFamiliarFollowers);
|
||||||
|
mainHandler.post(myRunnable);
|
||||||
|
}).start();
|
||||||
|
return familiarFollowersListMutableLiveData;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for matching accounts by username or display name.
|
* Search for matching accounts by username or display name.
|
||||||
*
|
*
|
||||||
|
|
|
@ -341,6 +341,44 @@
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/info" />
|
app:layout_constraintTop_toBottomOf="@+id/info" />
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.LinearLayoutCompat
|
||||||
|
android:id="@+id/familiar_followers"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="6dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/fields_container"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/type_of_concat"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:text="@string/also_followed_by" />
|
||||||
|
|
||||||
|
<HorizontalScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.LinearLayoutCompat
|
||||||
|
android:id="@+id/related_accounts"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal" />
|
||||||
|
</HorizontalScrollView>
|
||||||
|
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||||
|
|
||||||
<!-- End Fields container -->
|
<!-- End Fields container -->
|
||||||
<androidx.appcompat.widget.LinearLayoutCompat
|
<androidx.appcompat.widget.LinearLayoutCompat
|
||||||
android:id="@+id/warning_container"
|
android:id="@+id/warning_container"
|
||||||
|
@ -350,7 +388,7 @@
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/fields_container"
|
app:layout_constraintTop_toBottomOf="@+id/familiar_followers"
|
||||||
tools:visibility="visible">
|
tools:visibility="visible">
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
|
|
@ -2205,4 +2205,5 @@
|
||||||
<string name="set_pixelfed_presentation">Pixelfed presentation for media</string>
|
<string name="set_pixelfed_presentation">Pixelfed presentation for media</string>
|
||||||
<string name="set_display_compact_buttons">Compact action buttons</string>
|
<string name="set_display_compact_buttons">Compact action buttons</string>
|
||||||
<string name="set_display_compact_buttons_description">Buttons at the bottom of messages will not take the whole width</string>
|
<string name="set_display_compact_buttons_description">Buttons at the bottom of messages will not take the whole width</string>
|
||||||
|
<string name="also_followed_by">Followed by:</string>
|
||||||
</resources>
|
</resources>
|
|
@ -1,5 +1,5 @@
|
||||||
Added:
|
Added:
|
||||||
|
- Display familiar followers on profiles
|
||||||
|
|
||||||
Changed:
|
Changed:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue