1
0
mirror of https://github.com/KokaKiwi/BarInsta synced 2024-11-26 08:37:29 +00:00

profile viewer improvement

1. restore tagged posts access for anons
2. chip-ify profile viewer, bring it to consistency with tag/loc viewers
3. add a following/er status chip
4. pluralize "post(s)" and "follower(s)"
5. correct favourited string
This commit is contained in:
Austin Huang 2020-12-19 21:38:21 -05:00
parent 8240829fa8
commit 4d6ac5d293
No known key found for this signature in database
GPG Key ID: 84C23AA04587A91F
18 changed files with 301 additions and 296 deletions

View File

@ -122,6 +122,7 @@ public final class CommentsFetcher extends AsyncTask<Void, Void, List<CommentMod
false, false,
false, false,
false, false,
false,
false); false);
final JSONObject likedBy = childComment.optJSONObject("edge_liked_by"); final JSONObject likedBy = childComment.optJSONObject("edge_liked_by");
@ -207,6 +208,7 @@ public final class CommentsFetcher extends AsyncTask<Void, Void, List<CommentMod
false, false,
false, false,
false, false,
false,
false); false);
final JSONObject likedBy = comment.optJSONObject("edge_liked_by"); final JSONObject likedBy = comment.optJSONObject("edge_liked_by");
@ -256,6 +258,7 @@ public final class CommentsFetcher extends AsyncTask<Void, Void, List<CommentMod
false, false,
false, false,
false, false,
false,
false); false);
tempJsonObject = childComment.optJSONObject("edge_liked_by"); tempJsonObject = childComment.optJSONObject("edge_liked_by");

View File

@ -65,6 +65,7 @@ public final class PostFetcher extends AsyncTask<Void, Void, FeedModel> {
owner.optInt("edge_followed_by"), owner.optInt("edge_followed_by"),
-1, -1,
owner.optBoolean("followed_by_viewer"), owner.optBoolean("followed_by_viewer"),
false,
owner.optBoolean("restricted_by_viewer"), owner.optBoolean("restricted_by_viewer"),
owner.optBoolean("blocked_by_viewer"), owner.optBoolean("blocked_by_viewer"),
owner.optBoolean("requested_by_viewer") owner.optBoolean("requested_by_viewer")

View File

@ -72,6 +72,7 @@ public final class ProfileFetcher extends AsyncTask<Void, Void, ProfileModel> {
user.getJSONObject("edge_followed_by").getLong("count"), user.getJSONObject("edge_followed_by").getLong("count"),
user.getJSONObject("edge_follow").getLong("count"), user.getJSONObject("edge_follow").getLong("count"),
user.optBoolean("followed_by_viewer"), user.optBoolean("followed_by_viewer"),
user.optBoolean("follows_viewer"),
user.optBoolean("restricted_by_viewer"), user.optBoolean("restricted_by_viewer"),
user.optBoolean("blocked_by_viewer"), user.optBoolean("blocked_by_viewer"),
user.optBoolean("requested_by_viewer")); user.optBoolean("requested_by_viewer"));

View File

@ -50,7 +50,7 @@ public class SavedPostFetchService implements PostFetcher.PostFetchService {
profileService.fetchLiked(nextMaxId, callback); profileService.fetchLiked(nextMaxId, callback);
break; break;
case TAGGED: case TAGGED:
profileService.fetchTagged(profileId, nextMaxId, callback); profileService.fetchTagged(profileId, 30, nextMaxId, callback);
break; break;
case SAVED: case SAVED:
default: default:

View File

@ -513,7 +513,9 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
})); }));
hashtagDetailsBinding.mainHashtagImage.setImageURI(hashtagModel.getSdProfilePic()); hashtagDetailsBinding.mainHashtagImage.setImageURI(hashtagModel.getSdProfilePic());
final String postCount = String.valueOf(hashtagModel.getPostCount()); final String postCount = String.valueOf(hashtagModel.getPostCount());
final SpannableStringBuilder span = new SpannableStringBuilder(getString(R.string.main_posts_count_inline, postCount)); final SpannableStringBuilder span = new SpannableStringBuilder(getResources().getQuantityString(R.plurals.main_posts_count_inline,
hashtagModel.getPostCount() > 2000000000L ? 2000000000 : hashtagModel.getPostCount().intValue(),
postCount));
span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0); span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0);
span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0); span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0);
hashtagDetailsBinding.mainTagPostCount.setText(span); hashtagDetailsBinding.mainTagPostCount.setText(span);

View File

@ -400,8 +400,9 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
// binding.swipeRefreshLayout.setRefreshing(true); // binding.swipeRefreshLayout.setRefreshing(true);
locationDetailsBinding.mainLocationImage.setImageURI(locationModel.getSdProfilePic()); locationDetailsBinding.mainLocationImage.setImageURI(locationModel.getSdProfilePic());
final String postCount = String.valueOf(locationModel.getPostCount()); final String postCount = String.valueOf(locationModel.getPostCount());
final SpannableStringBuilder span = new SpannableStringBuilder(getString(R.string.main_posts_count_inline, final SpannableStringBuilder span = new SpannableStringBuilder(getResources().getQuantityString(R.plurals.main_posts_count_inline,
postCount)); locationModel.getPostCount() > 2000000000L ? 2000000000 : locationModel.getPostCount().intValue(),
postCount));
span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0); span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0);
span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0); span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0);
locationDetailsBinding.mainLocPostCount.setText(span); locationDetailsBinding.mainLocPostCount.setText(span);

View File

@ -370,10 +370,10 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
} }
if (item.getItemId() == R.id.restrict) { if (item.getItemId() == R.id.restrict) {
if (!isLoggedIn) return false; if (!isLoggedIn) return false;
final String action = profileModel.getRestricted() ? "Unrestrict" : "Restrict"; final String action = profileModel.isRestricted() ? "Unrestrict" : "Restrict";
friendshipService.toggleRestrict( friendshipService.toggleRestrict(
profileModel.getId(), profileModel.getId(),
!profileModel.getRestricted(), !profileModel.isRestricted(),
CookieUtils.getCsrfTokenFromCookie(cookie), CookieUtils.getCsrfTokenFromCookie(cookie),
new ServiceCallback<FriendshipRepoRestrictRootResponse>() { new ServiceCallback<FriendshipRepoRestrictRootResponse>() {
@Override @Override
@ -392,7 +392,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
if (item.getItemId() == R.id.block) { if (item.getItemId() == R.id.block) {
final String userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie); final String userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie);
if (!isLoggedIn) return false; if (!isLoggedIn) return false;
if (profileModel.getBlocked()) { if (profileModel.isBlocked()) {
friendshipService.unblock( friendshipService.unblock(
userIdFromCookie, userIdFromCookie,
profileModel.getId(), profileModel.getId(),
@ -571,44 +571,85 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
fetchStoryAndHighlights(profileId); fetchStoryAndHighlights(profileId);
} }
setupButtons(profileId, myId); setupButtons(profileId, myId);
if (!profileId.equals(myId)) { profileDetailsBinding.favChip.setVisibility(View.VISIBLE);
profileDetailsBinding.favCb.setVisibility(View.VISIBLE); final FavoriteRepository favoriteRepository = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(getContext()));
favoriteRepository.getFavorite(username.substring(1), FavoriteType.USER, new RepositoryCallback<Favorite>() { favoriteRepository.getFavorite(profileModel.getUsername(), FavoriteType.USER, new RepositoryCallback<Favorite>() {
@Override @Override
public void onSuccess(final Favorite result) { public void onSuccess(final Favorite result) {
profileDetailsBinding.favCb.setChecked(true); profileDetailsBinding.favChip.setChipIconResource(R.drawable.ic_star_check_24);
profileDetailsBinding.favCb.setButtonDrawable(R.drawable.ic_star_check_24); profileDetailsBinding.favChip.setText(R.string.added_to_favs);
} }
@Override @Override
public void onDataNotAvailable() { public void onDataNotAvailable() {
profileDetailsBinding.favCb.setChecked(false); profileDetailsBinding.favChip.setChipIconResource(R.drawable.ic_outline_star_plus_24);
profileDetailsBinding.favCb.setButtonDrawable(R.drawable.ic_outline_star_plus_24); profileDetailsBinding.favChip.setText(R.string.add_to_favorites);
} }
}); });
} else { profileDetailsBinding.favChip.setOnClickListener(
profileDetailsBinding.favCb.setVisibility(View.GONE); v -> favoriteRepository.getFavorite(profileModel.getUsername(), FavoriteType.USER, new RepositoryCallback<Favorite>() {
} @Override
public void onSuccess(final Favorite result) {
favoriteRepository.deleteFavorite(profileModel.getUsername(), FavoriteType.USER, new RepositoryCallback<Void>() {
@Override
public void onSuccess(final Void result) {
profileDetailsBinding.favChip.setText(R.string.add_to_favorites);
profileDetailsBinding.favChip.setChipIconResource(R.drawable.ic_outline_star_plus_24);
showSnackbar(getString(R.string.removed_from_favs));
}
@Override
public void onDataNotAvailable() {}
});
}
@Override
public void onDataNotAvailable() {
final String finalUsername = username.startsWith("@") ? username.substring(1) : username;
favoriteRepository.insertOrUpdateFavorite(new Favorite(
-1,
finalUsername,
FavoriteType.USER,
profileModel.getName(),
profileModel.getSdProfilePic(),
new Date()
), new RepositoryCallback<Void>() {
@Override
public void onSuccess(final Void result) {
profileDetailsBinding.favChip.setText(R.string.added_to_favs);
profileDetailsBinding.favChip.setChipIconResource(R.drawable.ic_star_check_24);
showSnackbar(getString(R.string.added_to_favs));
}
@Override
public void onDataNotAvailable() {}
});
}
}));
profileDetailsBinding.mainProfileImage.setImageURI(profileModel.getHdProfilePic()); profileDetailsBinding.mainProfileImage.setImageURI(profileModel.getHdProfilePic());
final long followersCount = profileModel.getFollowersCount(); final Long followersCount = profileModel.getFollowersCount();
final long followingCount = profileModel.getFollowingCount(); final Long followingCount = profileModel.getFollowingCount();
final String postCount = String.valueOf(profileModel.getPostCount()); final String postCount = String.valueOf(profileModel.getPostCount());
SpannableStringBuilder span = new SpannableStringBuilder(getString(R.string.main_posts_count, SpannableStringBuilder span = new SpannableStringBuilder(getResources().getQuantityString(R.plurals.main_posts_count_inline,
postCount)); profileModel.getPostCount() > 2000000000L ? 2000000000 : profileModel.getPostCount().intValue(),
postCount));
span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0); span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0);
span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0); span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0);
profileDetailsBinding.mainPostCount.setText(span); profileDetailsBinding.mainPostCount.setText(span);
profileDetailsBinding.mainPostCount.setVisibility(View.VISIBLE);
final String followersCountStr = String.valueOf(followersCount); final String followersCountStr = String.valueOf(followersCount);
final int followersCountStrLen = followersCountStr.length(); final int followersCountStrLen = followersCountStr.length();
span = new SpannableStringBuilder(getString(R.string.main_posts_followers, span = new SpannableStringBuilder(getResources().getQuantityString(R.plurals.main_posts_followers,
followersCountStr)); followersCount > 2000000000L ? 2000000000 : followersCount.intValue(),
followersCountStr));
span.setSpan(new RelativeSizeSpan(1.2f), 0, followersCountStrLen, 0); span.setSpan(new RelativeSizeSpan(1.2f), 0, followersCountStrLen, 0);
span.setSpan(new StyleSpan(Typeface.BOLD), 0, followersCountStrLen, 0); span.setSpan(new StyleSpan(Typeface.BOLD), 0, followersCountStrLen, 0);
profileDetailsBinding.mainFollowers.setText(span); profileDetailsBinding.mainFollowers.setText(span);
profileDetailsBinding.mainFollowers.setVisibility(View.VISIBLE);
final String followingCountStr = String.valueOf(followingCount); final String followingCountStr = String.valueOf(followingCount);
final int followingCountStrLen = followingCountStr.length(); final int followingCountStrLen = followingCountStr.length();
@ -617,6 +658,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
span.setSpan(new RelativeSizeSpan(1.2f), 0, followingCountStrLen, 0); span.setSpan(new RelativeSizeSpan(1.2f), 0, followingCountStrLen, 0);
span.setSpan(new StyleSpan(Typeface.BOLD), 0, followingCountStrLen, 0); span.setSpan(new StyleSpan(Typeface.BOLD), 0, followingCountStrLen, 0);
profileDetailsBinding.mainFollowing.setText(span); profileDetailsBinding.mainFollowing.setText(span);
profileDetailsBinding.mainFollowing.setVisibility(View.VISIBLE);
profileDetailsBinding.mainFullName.setText(TextUtils.isEmpty(profileModel.getName()) ? profileModel.getUsername() profileDetailsBinding.mainFullName.setText(TextUtils.isEmpty(profileModel.getName()) ? profileModel.getUsername()
: profileModel.getName()); : profileModel.getName());
@ -701,10 +743,25 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
profileDetailsBinding.btnLiked.setVisibility(View.GONE); profileDetailsBinding.btnLiked.setVisibility(View.GONE);
profileDetailsBinding.btnDM.setVisibility(View.VISIBLE); // maybe there is a judgment mechanism? profileDetailsBinding.btnDM.setVisibility(View.VISIBLE); // maybe there is a judgment mechanism?
profileDetailsBinding.btnFollow.setVisibility(View.VISIBLE); profileDetailsBinding.btnFollow.setVisibility(View.VISIBLE);
if (profileModel.getFollowing()) { if (profileModel.isFollowing() || profileModel.isFollower()) {
profileDetailsBinding.mainStatus.setVisibility(View.VISIBLE);
if (!profileModel.isFollowing()) {
profileDetailsBinding.mainStatus.setChipBackgroundColor(getResources().getColorStateList(R.color.blue_800));
profileDetailsBinding.mainStatus.setText(R.string.status_follower);
}
else if (!profileModel.isFollower()) {
profileDetailsBinding.mainStatus.setChipBackgroundColor(getResources().getColorStateList(R.color.deep_orange_800));
profileDetailsBinding.mainStatus.setText(R.string.status_following);
}
else {
profileDetailsBinding.mainStatus.setChipBackgroundColor(getResources().getColorStateList(R.color.green_800));
profileDetailsBinding.mainStatus.setText(R.string.status_mutual);
}
}
if (profileModel.isFollowing()) {
profileDetailsBinding.btnFollow.setText(R.string.unfollow); profileDetailsBinding.btnFollow.setText(R.string.unfollow);
profileDetailsBinding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_disabled_24); profileDetailsBinding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_disabled_24);
} else if (profileModel.getRequested()) { } else if (profileModel.isRequested()) {
profileDetailsBinding.btnFollow.setText(R.string.cancel); profileDetailsBinding.btnFollow.setText(R.string.cancel);
profileDetailsBinding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_disabled_24); profileDetailsBinding.btnFollow.setIconResource(R.drawable.ic_outline_person_add_disabled_24);
} else { } else {
@ -713,7 +770,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
} }
if (restrictMenuItem != null) { if (restrictMenuItem != null) {
restrictMenuItem.setVisible(true); restrictMenuItem.setVisible(true);
if (profileModel.getRestricted()) { if (profileModel.isRestricted()) {
restrictMenuItem.setTitle(R.string.unrestrict); restrictMenuItem.setTitle(R.string.unrestrict);
} else { } else {
restrictMenuItem.setTitle(R.string.restrict); restrictMenuItem.setTitle(R.string.restrict);
@ -722,7 +779,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
profileDetailsBinding.btnTagged.setVisibility(profileModel.isReallyPrivate() ? View.GONE : View.VISIBLE); profileDetailsBinding.btnTagged.setVisibility(profileModel.isReallyPrivate() ? View.GONE : View.VISIBLE);
if (blockMenuItem != null) { if (blockMenuItem != null) {
blockMenuItem.setVisible(true); blockMenuItem.setVisible(true);
if (profileModel.getBlocked()) { if (profileModel.isBlocked()) {
blockMenuItem.setTitle(R.string.unblock); blockMenuItem.setTitle(R.string.unblock);
} else { } else {
blockMenuItem.setTitle(R.string.block); blockMenuItem.setTitle(R.string.block);
@ -732,7 +789,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
} }
if (!profileModel.isReallyPrivate() && restrictMenuItem != null) { if (!profileModel.isReallyPrivate() && restrictMenuItem != null) {
restrictMenuItem.setVisible(true); restrictMenuItem.setVisible(true);
if (profileModel.getRestricted()) { if (profileModel.isRestricted()) {
restrictMenuItem.setTitle(R.string.unrestrict); restrictMenuItem.setTitle(R.string.unrestrict);
} else { } else {
restrictMenuItem.setTitle(R.string.restrict); restrictMenuItem.setTitle(R.string.restrict);
@ -771,9 +828,34 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
} }
private void setupCommonListeners() { private void setupCommonListeners() {
final Context context = getContext();
final String userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie); final String userIdFromCookie = CookieUtils.getUserIdFromCookie(cookie);
profileDetailsBinding.btnFollow.setOnClickListener(v -> { profileDetailsBinding.btnFollow.setOnClickListener(v -> {
if (profileModel.getFollowing() || profileModel.getRequested()) { if (profileModel.isFollowing() && profileModel.isPrivate()) {
new AlertDialog.Builder(context)
.setTitle(R.string.priv_acc)
.setMessage(R.string.priv_acc_confirm)
.setPositiveButton(R.string.confirm, (d, w) ->
friendshipService.unfollow(
userIdFromCookie,
profileModel.getId(),
CookieUtils.getCsrfTokenFromCookie(cookie),
new ServiceCallback<FriendshipRepoChangeRootResponse>() {
@Override
public void onSuccess(final FriendshipRepoChangeRootResponse result) {
// Log.d(TAG, "Unfollow success: " + result);
onRefresh();
}
@Override
public void onFailure(final Throwable t) {
Log.e(TAG, "Error unfollowing", t);
}
}))
.setNegativeButton(R.string.cancel, null)
.show();
}
else if (profileModel.isFollowing() || profileModel.isRequested()) {
friendshipService.unfollow( friendshipService.unfollow(
userIdFromCookie, userIdFromCookie,
profileModel.getId(), profileModel.getId(),
@ -860,66 +942,12 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
} }
showProfilePicDialog(); showProfilePicDialog();
}; };
final Context context = getContext();
if (context == null) return; if (context == null) return;
new AlertDialog.Builder(context) new AlertDialog.Builder(context)
.setItems(options, profileDialogListener) .setItems(options, profileDialogListener)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
.show(); .show();
}); });
profileDetailsBinding.favCb.setOnCheckedChangeListener((buttonView, isChecked) -> {
// do not do anything if state matches the db, as listener is set before profile details are set
final Context context = getContext();
if (context == null) return;
final String finalUsername = username.startsWith("@") ? username.substring(1) : username;
favoriteRepository.getFavorite(finalUsername, FavoriteType.USER, new RepositoryCallback<Favorite>() {
@Override
public void onSuccess(final Favorite result) {
if (isChecked) return; // already a fav
buttonView.setVisibility(View.GONE);
profileDetailsBinding.favProgress.setVisibility(View.VISIBLE);
favoriteRepository.deleteFavorite(finalUsername, FavoriteType.USER, new RepositoryCallback<Void>() {
@Override
public void onSuccess(final Void result) {
profileDetailsBinding.favCb.setButtonDrawable(R.drawable.ic_outline_star_plus_24);
profileDetailsBinding.favProgress.setVisibility(View.GONE);
profileDetailsBinding.favCb.setVisibility(View.VISIBLE);
showSnackbar(getString(R.string.removed_from_favs));
}
@Override
public void onDataNotAvailable() {}
});
}
@Override
public void onDataNotAvailable() {
if (!isChecked) return; // not in fav already
buttonView.setVisibility(View.GONE);
profileDetailsBinding.favProgress.setVisibility(View.VISIBLE);
final Favorite model = new Favorite(
-1,
finalUsername,
FavoriteType.USER,
profileModel.getName(),
profileModel.getSdProfilePic(),
new Date()
);
favoriteRepository.insertOrUpdateFavorite(model, new RepositoryCallback<Void>() {
@Override
public void onSuccess(final Void result) {
profileDetailsBinding.favCb.setButtonDrawable(R.drawable.ic_star_check_24);
profileDetailsBinding.favProgress.setVisibility(View.GONE);
profileDetailsBinding.favCb.setVisibility(View.VISIBLE);
showSnackbar(getString(R.string.added_to_favs));
}
@Override
public void onDataNotAvailable() {}
});
}
});
});
} }
private void showSnackbar(final String message) { private void showSnackbar(final String message) {

View File

@ -29,7 +29,7 @@ public final class HashtagModel implements Serializable {
return sdProfilePic; return sdProfilePic;
} }
public long getPostCount() { return postCount; } public Long getPostCount() { return postCount; }
public boolean getFollowing() { return following; } public boolean getFollowing() { return following; }
} }

View File

@ -59,5 +59,5 @@ public final class LocationModel implements Serializable {
return sdProfilePic; return sdProfilePic;
} }
public long getPostCount() { return postCount; } public Long getPostCount() { return postCount; }
} }

View File

@ -3,15 +3,15 @@ package awais.instagrabber.models;
import java.io.Serializable; import java.io.Serializable;
public final class ProfileModel implements Serializable { public final class ProfileModel implements Serializable {
private final boolean isPrivate, reallyPrivate, isVerified, following, restricted, blocked, requested; private final boolean isPrivate, reallyPrivate, isVerified, following, follower, restricted, blocked, requested;
private final long postCount, followersCount, followingCount; private final long postCount, followersCount, followingCount;
private final String id, username, name, biography, url, sdProfilePic, hdProfilePic; private final String id, username, name, biography, url, sdProfilePic, hdProfilePic;
public ProfileModel(final boolean isPrivate, final boolean reallyPrivate, public ProfileModel(final boolean isPrivate, final boolean reallyPrivate,
final boolean isVerified, final String id, final String username, final String name, final String biography, final boolean isVerified, final String id, final String username, final String name, final String biography,
final String url, final String sdProfilePic, final String hdProfilePic, final long postCount, final String url, final String sdProfilePic, final String hdProfilePic, final long postCount,
final long followersCount, final long followingCount, final boolean following, final boolean restricted, final long followersCount, final long followingCount, final boolean following, final boolean follower,
final boolean blocked, final boolean requested) { final boolean restricted, final boolean blocked, final boolean requested) {
this.isPrivate = isPrivate; this.isPrivate = isPrivate;
this.reallyPrivate = reallyPrivate; this.reallyPrivate = reallyPrivate;
this.isVerified = isVerified; this.isVerified = isVerified;
@ -26,21 +26,22 @@ public final class ProfileModel implements Serializable {
this.followersCount = followersCount; this.followersCount = followersCount;
this.followingCount = followingCount; this.followingCount = followingCount;
this.following = following; this.following = following;
this.follower = follower;
this.restricted = restricted; this.restricted = restricted;
this.blocked = blocked; this.blocked = blocked;
this.requested = requested; this.requested = requested;
} }
public static ProfileModel getDefaultProfileModel() { public static ProfileModel getDefaultProfileModel() {
return new ProfileModel(false, false, false, null, null, null, null, null, null, null, 0, 0, 0, false, false, false, false); return new ProfileModel(false, false, false, null, null, null, null, null, null, null, 0, 0, 0, false, false, false, false, false);
} }
public static ProfileModel getDefaultProfileModel(final String userId) { public static ProfileModel getDefaultProfileModel(final String userId) {
return new ProfileModel(false, false, false, userId, null, null, null, null, null, null, 0, 0, 0, false, false, false, false); return new ProfileModel(false, false, false, userId, null, null, null, null, null, null, 0, 0, 0, false, false, false, false, false);
} }
public static ProfileModel getDefaultProfileModel(final String userId, final String username) { public static ProfileModel getDefaultProfileModel(final String userId, final String username) {
return new ProfileModel(false, false, false, userId, username, null, null, null, null, null, 0, 0, 0, false, false, false, false); return new ProfileModel(false, false, false, userId, username, null, null, null, null, null, 0, 0, 0, false, false, false, false, false);
} }
public boolean isPrivate() { public boolean isPrivate() {
@ -83,31 +84,35 @@ public final class ProfileModel implements Serializable {
return hdProfilePic; return hdProfilePic;
} }
public long getPostCount() { public Long getPostCount() {
return postCount; return postCount;
} }
public long getFollowersCount() { public Long getFollowersCount() {
return followersCount; return followersCount;
} }
public long getFollowingCount() { public Long getFollowingCount() {
return followingCount; return followingCount;
} }
public boolean getFollowing() { public boolean isFollowing() {
return following; return following;
} }
public boolean getRestricted() { public boolean isFollower() {
return follower;
}
public boolean isRestricted() {
return restricted; return restricted;
} }
public boolean getBlocked() { public boolean isBlocked() {
return blocked; return blocked;
} }
public boolean getRequested() { public boolean isRequested() {
return requested; return requested;
} }
} }

View File

@ -20,7 +20,4 @@ public interface ProfileRepository {
@GET("/api/v1/feed/liked/") @GET("/api/v1/feed/liked/")
Call<String> fetchLiked(@QueryMap Map<String, String> queryParams); Call<String> fetchLiked(@QueryMap Map<String, String> queryParams);
@GET("/api/v1/usertags/{profileId}/feed/")
Call<String> fetchTagged(@Path("profileId") final String profileId, @QueryMap Map<String, String> queryParams);
} }

View File

@ -203,7 +203,7 @@ public final class ResponseBodyUtils {
userObj.getString("full_name"), userObj.getString("full_name"),
null, null, null, null,
userObj.getString("profile_pic_url"), userObj.getString("profile_pic_url"),
null, 0, 0, 0, false, false, false, false); null, 0, 0, 0, false, false, false, false, false);
} }
final MediaItemType mediaType = getMediaItemType(mediaObj.optInt("media_type", -1)); final MediaItemType mediaType = getMediaItemType(mediaObj.optInt("media_type", -1));
@ -291,7 +291,7 @@ public final class ResponseBodyUtils {
userObject.getString("full_name"), userObject.getString("full_name"),
null, null, null, null,
userObject.getString("profile_pic_url"), userObject.getString("profile_pic_url"),
null, 0, 0, 0, false, false, false, false); null, 0, 0, 0, false, false, false, false, false);
} }
final ProfileModel[] leftuserModels = new ProfileModel[leftusersLen]; final ProfileModel[] leftuserModels = new ProfileModel[leftusersLen];
@ -305,7 +305,7 @@ public final class ResponseBodyUtils {
userObject.getString("full_name"), userObject.getString("full_name"),
null, null, null, null,
userObject.getString("profile_pic_url"), userObject.getString("profile_pic_url"),
null, 0, 0, 0, false, false, false, false); null, 0, 0, 0, false, false, false, false, false);
} }
final Long[] adminIDs = new Long[adminsLen]; final Long[] adminIDs = new Long[adminsLen];
@ -470,7 +470,7 @@ public final class ResponseBodyUtils {
profile.getString("full_name"), profile.getString("full_name"),
null, null, null, null,
profile.getString("profile_pic_url"), profile.getString("profile_pic_url"),
null, 0, 0, 0, false, false, false, false); null, 0, 0, 0, false, false, false, false, false);
} }
break; break;
@ -622,6 +622,7 @@ public final class ResponseBodyUtils {
0, 0,
0, 0,
following, following,
false,
restricted, restricted,
false, false,
requested); requested);
@ -705,6 +706,7 @@ public final class ResponseBodyUtils {
false, false,
false, false,
false, false,
false,
false); false);
} }
JSONObject tempJsonObject = feedItem.optJSONObject("edge_media_preview_comment"); JSONObject tempJsonObject = feedItem.optJSONObject("edge_media_preview_comment");

View File

@ -165,6 +165,7 @@ public class DiscoverService extends BaseService {
false, false,
false, false,
false, false,
false,
false); false);
} }
final String resourceUrl = ResponseBodyUtils.getHighQualityImage(coverMediaJson); final String resourceUrl = ResponseBodyUtils.getHighQualityImage(coverMediaJson);

View File

@ -89,7 +89,6 @@ public class ProfileService extends BaseService {
}); });
} }
public void fetchPosts(final ProfileModel profileModel, public void fetchPosts(final ProfileModel profileModel,
final int postsPerPage, final int postsPerPage,
final String cursor, final String cursor,
@ -156,135 +155,18 @@ public class ProfileService extends BaseService {
} }
final JSONArray edges = mediaPosts.getJSONArray("edges"); final JSONArray edges = mediaPosts.getJSONArray("edges");
for (int i = 0; i < edges.length(); ++i) { for (int i = 0; i < edges.length(); ++i) {
final JSONObject mediaNode = edges.getJSONObject(i).getJSONObject("node"); final JSONObject itemJson = edges.optJSONObject(i);
final String mediaType = mediaNode.optString("__typename"); if (itemJson == null) {
if (mediaType.isEmpty() || "GraphSuggestedUserFeedUnit".equals(mediaType))
continue; continue;
final boolean isVideo = mediaNode.getBoolean("is_video");
final long videoViews = mediaNode.optLong("video_view_count", 0);
final String displayUrl = mediaNode.optString("display_url");
if (TextUtils.isEmpty(displayUrl)) continue;
final String resourceUrl;
if (isVideo) {
resourceUrl = mediaNode.getString("video_url");
} else {
resourceUrl = mediaNode.has("display_resources") ? ResponseBodyUtils.getHighQualityImage(mediaNode) : displayUrl;
} }
JSONObject tempJsonObject = mediaNode.optJSONObject("edge_media_to_comment"); final FeedModel feedModel = ResponseBodyUtils.parseGraphQLItem(itemJson);
final long commentsCount = tempJsonObject != null ? tempJsonObject.optLong("count") : 0; if (feedModel != null) {
tempJsonObject = mediaNode.optJSONObject("edge_media_preview_like"); feedModels.add(feedModel);
final long likesCount = tempJsonObject != null ? tempJsonObject.optLong("count") : 0;
tempJsonObject = mediaNode.optJSONObject("edge_media_to_caption");
final JSONArray captions = tempJsonObject != null ? tempJsonObject.getJSONArray("edges") : null;
String captionText = null;
if (captions != null && captions.length() > 0) {
if ((tempJsonObject = captions.optJSONObject(0)) != null &&
(tempJsonObject = tempJsonObject.optJSONObject("node")) != null) {
captionText = tempJsonObject.getString("text");
}
} }
final JSONObject location = mediaNode.optJSONObject("location");
// Log.d(TAG, "location: " + (location == null ? null : location.toString()));
String locationId = null;
String locationName = null;
if (location != null) {
locationName = location.optString("name");
if (location.has("id")) {
locationId = location.getString("id");
} else if (location.has("pk")) {
locationId = location.getString("pk");
}
// Log.d(TAG, "locationId: " + locationId);
}
int height = 0;
int width = 0;
final JSONObject dimensions = mediaNode.optJSONObject("dimensions");
if (dimensions != null) {
height = dimensions.optInt("height");
width = dimensions.optInt("width");
}
String thumbnailUrl = null;
try {
thumbnailUrl = mediaNode.getJSONArray("display_resources")
.getJSONObject(0)
.getString("src");
} catch (JSONException ignored) {}
final FeedModel.Builder builder = new FeedModel.Builder()
.setProfileModel(profileModel)
.setItemType(isVideo ? MediaItemType.MEDIA_TYPE_VIDEO
: MediaItemType.MEDIA_TYPE_IMAGE)
.setViewCount(videoViews)
.setPostId(mediaNode.getString(Constants.EXTRAS_ID))
.setDisplayUrl(resourceUrl)
.setThumbnailUrl(thumbnailUrl != null ? thumbnailUrl : displayUrl)
.setShortCode(mediaNode.getString(Constants.EXTRAS_SHORTCODE))
.setPostCaption(captionText)
.setCommentsCount(commentsCount)
.setTimestamp(mediaNode.optLong("taken_at_timestamp", -1))
.setLiked(mediaNode.getBoolean("viewer_has_liked"))
.setBookmarked(mediaNode.getBoolean("viewer_has_saved"))
.setLikesCount(likesCount)
.setLocationName(locationName)
.setLocationId(locationId)
.setImageHeight(height)
.setImageWidth(width);
final boolean isSlider = "GraphSidecar".equals(mediaType) && mediaNode.has("edge_sidecar_to_children");
if (isSlider) {
builder.setItemType(MediaItemType.MEDIA_TYPE_SLIDER);
final JSONObject sidecar = mediaNode.optJSONObject("edge_sidecar_to_children");
if (sidecar != null) {
final JSONArray children = sidecar.optJSONArray("edges");
if (children != null) {
final List<PostChild> sliderItems = getSliderItems(children);
builder.setSliderItems(sliderItems);
}
}
}
final FeedModel feedModel = builder.build();
feedModels.add(feedModel);
} }
return new PostsFetchResponse(feedModels, hasNextPage, endCursor); return new PostsFetchResponse(feedModels, hasNextPage, endCursor);
} }
@NonNull
private List<PostChild> getSliderItems(final JSONArray children) throws JSONException {
final List<PostChild> sliderItems = new ArrayList<>();
for (int j = 0; j < children.length(); ++j) {
final JSONObject childNode = children.optJSONObject(j).getJSONObject("node");
final boolean isChildVideo = childNode.optBoolean("is_video");
int height = 0;
int width = 0;
final JSONObject dimensions = childNode.optJSONObject("dimensions");
if (dimensions != null) {
height = dimensions.optInt("height");
width = dimensions.optInt("width");
}
String thumbnailUrl = null;
try {
thumbnailUrl = childNode.getJSONArray("display_resources")
.getJSONObject(0)
.getString("src");
} catch (JSONException ignored) {}
final PostChild sliderItem = new PostChild.Builder()
.setItemType(isChildVideo ? MediaItemType.MEDIA_TYPE_VIDEO
: MediaItemType.MEDIA_TYPE_IMAGE)
.setPostId(childNode.getString(Constants.EXTRAS_ID))
.setDisplayUrl(isChildVideo ? childNode.getString("video_url")
: childNode.getString("display_url"))
.setThumbnailUrl(thumbnailUrl != null ? thumbnailUrl
: childNode.getString("display_url"))
.setVideoViews(childNode.optLong("video_view_count", 0))
.setHeight(height)
.setWidth(width)
.build();
// Log.d(TAG, "getSliderItems: sliderItem: " + sliderItem);
sliderItems.add(sliderItem);
}
return sliderItems;
}
public void fetchSaved(final String maxId, public void fetchSaved(final String maxId,
final ServiceCallback<SavedPostsFetchResponse> callback) { final ServiceCallback<SavedPostsFetchResponse> callback) {
final ImmutableMap.Builder<String, String> builder = ImmutableMap.builder(); final ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
@ -358,13 +240,17 @@ public class ProfileService extends BaseService {
} }
public void fetchTagged(final String profileId, public void fetchTagged(final String profileId,
final String maxId, final int postsPerPage,
final String cursor,
final ServiceCallback<SavedPostsFetchResponse> callback) { final ServiceCallback<SavedPostsFetchResponse> callback) {
final ImmutableMap.Builder<String, String> builder = ImmutableMap.builder(); final Map<String, String> queryMap = new HashMap<>();
if (!TextUtils.isEmpty(maxId)) { queryMap.put("query_hash", "31fe64d9463cbbe58319dced405c6206");
builder.put("max_id", maxId); queryMap.put("variables", "{" +
} "\"id\":\"" + profileId + "\"," +
final Call<String> request = repository.fetchTagged(profileId, builder.build()); "\"first\":" + postsPerPage + "," +
"\"after\":\"" + (cursor == null ? "" : cursor) + "\"" +
"}");
final Call<String> request = wwwRepository.fetch(queryMap);
request.enqueue(new Callback<String>() { request.enqueue(new Callback<String>() {
@Override @Override
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
@ -377,7 +263,7 @@ public class ProfileService extends BaseService {
callback.onSuccess(null); callback.onSuccess(null);
return; return;
} }
final SavedPostsFetchResponse savedPostsFetchResponse = parseSavedPostsResponse(body, false); final SavedPostsFetchResponse savedPostsFetchResponse = parseTaggedPostsResponse(body);
callback.onSuccess(savedPostsFetchResponse); callback.onSuccess(savedPostsFetchResponse);
} catch (JSONException e) { } catch (JSONException e) {
Log.e(TAG, "onResponse", e); Log.e(TAG, "onResponse", e);
@ -411,6 +297,41 @@ public class ProfileService extends BaseService {
); );
} }
@NonNull
private SavedPostsFetchResponse parseTaggedPostsResponse(@NonNull final String body)
throws JSONException {
final List<FeedModel> feedModels = new ArrayList<>();
final JSONObject timelineFeed = new JSONObject(body)
.getJSONObject("data")
.getJSONObject(Constants.EXTRAS_USER)
.getJSONObject("edge_user_to_photos_of_you");
final String endCursor;
final boolean hasNextPage;
final JSONObject pageInfo = timelineFeed.getJSONObject("page_info");
if (pageInfo.has("has_next_page")) {
hasNextPage = pageInfo.getBoolean("has_next_page");
endCursor = hasNextPage ? pageInfo.getString("end_cursor") : null;
} else {
hasNextPage = false;
endCursor = null;
}
final JSONArray feedItems = timelineFeed.getJSONArray("edges");
for (int i = 0; i < feedItems.length(); ++i) {
final JSONObject itemJson = feedItems.optJSONObject(i);
if (itemJson == null) {
continue;
}
final FeedModel feedModel = ResponseBodyUtils.parseGraphQLItem(itemJson);
if (feedModel != null) {
feedModels.add(feedModel);
}
}
return new SavedPostsFetchResponse(hasNextPage, endCursor, timelineFeed.getInt("count"), "ok", feedModels);
}
private List<FeedModel> parseItems(final JSONArray items, final boolean isInMedia) throws JSONException { private List<FeedModel> parseItems(final JSONArray items, final boolean isInMedia) throws JSONException {
if (items == null) { if (items == null) {
return Collections.emptyList(); return Collections.emptyList();

View File

@ -123,7 +123,7 @@ public class StoriesService extends BaseService {
user.getString("username"), user.getString("username"),
null, null, null, null, null, null,
user.getString("profile_pic_url"), user.getString("profile_pic_url"),
null, 0, 0, 0, false, false, false, false); null, 0, 0, 0, false, false, false, false, false);
final String id = node.getString("id"); final String id = node.getString("id");
final boolean fullyRead = !node.isNull("seen") && node.getLong("seen") == node.getLong("latest_reel_media"); final boolean fullyRead = !node.isNull("seen") && node.getLong("seen") == node.getLong("latest_reel_media");
feedStoryModels.add(new FeedStoryModel(id, profileModel, fullyRead)); feedStoryModels.add(new FeedStoryModel(id, profileModel, fullyRead));

View File

@ -18,45 +18,96 @@
app:layout_constraintEnd_toStartOf="@id/mainPostCount" app:layout_constraintEnd_toStartOf="@id/mainPostCount"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="@id/fav_chip"
tools:background="@mipmap/ic_launcher" /> tools:background="@mipmap/ic_launcher" />
<androidx.appcompat.widget.AppCompatTextView <com.google.android.material.chip.Chip
android:id="@+id/mainPostCount" android:id="@+id/mainPostCount"
android:layout_width="0dp" android:layout_width="wrap_content"
android:layout_height="0dp" android:layout_height="@dimen/profile_chip_size"
android:layout_marginStart="4dp"
android:clickable="false"
android:visibility="gone"
tools:visibility="visible"
android:gravity="center" android:gravity="center"
android:textAppearance="@style/TextAppearance.AppCompat" app:layout_constraintBottom_toTopOf="@id/mainFollowers"
app:layout_constraintBottom_toBottomOf="@id/mainProfileImage"
app:layout_constraintEnd_toStartOf="@id/mainFollowers"
app:layout_constraintStart_toEndOf="@id/mainProfileImage" app:layout_constraintStart_toEndOf="@id/mainProfileImage"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="@id/mainProfileImage"
tools:text="35\nPosts" /> tools:text="35 Posts" />
<androidx.appcompat.widget.AppCompatTextView <com.google.android.material.chip.Chip
android:id="@+id/mainFollowers" android:id="@+id/mainStatus"
android:layout_width="0dp" android:layout_width="wrap_content"
android:layout_height="0dp" android:layout_height="@dimen/profile_chip_size"
android:background="?selectableItemBackgroundBorderless" android:layout_marginStart="4dp"
android:clickable="false"
android:visibility="gone"
tools:visibility="visible"
android:gravity="center" android:gravity="center"
android:textAppearance="@style/TextAppearance.AppCompat" app:layout_constraintBottom_toTopOf="@id/mainFollowers"
app:layout_constraintBottom_toBottomOf="@id/mainProfileImage"
app:layout_constraintEnd_toStartOf="@id/mainFollowing"
app:layout_constraintStart_toEndOf="@id/mainPostCount" app:layout_constraintStart_toEndOf="@id/mainPostCount"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="@id/mainPostCount"
tools:text="68\nFollowers" /> tools:text="omg what do u expect" />
<androidx.appcompat.widget.AppCompatTextView <com.google.android.material.chip.Chip
android:id="@+id/mainFollowing" android:id="@+id/mainFollowers"
android:layout_width="0dp" android:layout_width="wrap_content"
android:layout_height="0dp" android:layout_height="@dimen/profile_chip_size"
android:background="?selectableItemBackgroundBorderless" android:layout_marginStart="4dp"
android:clickable="false"
android:visibility="gone"
tools:visibility="visible"
android:gravity="center" android:gravity="center"
android:textAppearance="@style/TextAppearance.AppCompat" app:layout_constraintBottom_toTopOf="@id/fav_chip"
app:layout_constraintBottom_toBottomOf="@id/mainProfileImage" app:layout_constraintStart_toEndOf="@id/mainProfileImage"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@id/mainPostCount"
app:rippleColor="@color/grey_400"
tools:text="10 Followers" />
<com.google.android.material.chip.Chip
android:id="@+id/mainFollowing"
android:layout_width="wrap_content"
android:layout_height="@dimen/profile_chip_size"
android:layout_marginStart="4dp"
android:clickable="false"
android:visibility="gone"
tools:visibility="visible"
android:gravity="center"
app:layout_constraintBottom_toTopOf="@id/fav_chip"
app:layout_constraintStart_toEndOf="@id/mainFollowers" app:layout_constraintStart_toEndOf="@id/mainFollowers"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toBottomOf="@id/mainPostCount"
tools:text="64\nFollowing" /> app:rippleColor="@color/grey_400"
tools:text="10 Following" />
<com.google.android.material.chip.Chip
android:id="@+id/fav_chip"
android:layout_width="wrap_content"
android:layout_height="@dimen/profile_chip_size"
android:layout_marginStart="8dp"
android:text="@string/add_to_favorites"
android:visibility="gone"
app:chipIcon="@drawable/ic_outline_star_plus_24"
app:chipIconTint="@color/yellow_800"
app:layout_constraintBottom_toBottomOf="@id/mainProfileImage"
app:layout_constraintStart_toEndOf="@id/mainProfileImage"
app:layout_constraintTop_toBottomOf="@id/mainFollowers"
app:rippleColor="@color/yellow_400"
tools:visibility="visible" />
<com.google.android.material.chip.Chip
android:id="@+id/btnTagged"
android:layout_width="wrap_content"
android:layout_height="@dimen/profile_chip_size"
android:layout_marginStart="4dp"
android:text="@string/tagged"
android:visibility="gone"
app:chipIcon="@drawable/ic_outline_person_pin_24"
app:chipIconTint="@color/deep_orange_800"
app:layout_constraintBottom_toBottomOf="@id/fav_chip"
app:layout_constraintStart_toEndOf="@id/fav_chip"
app:layout_constraintTop_toBottomOf="@id/mainFollowers"
app:rippleColor="@color/deep_orange_400"
tools:visibility="visible" />
<androidx.appcompat.widget.AppCompatTextView <androidx.appcompat.widget.AppCompatTextView
android:id="@+id/mainFullName" android:id="@+id/mainFullName"
@ -70,7 +121,7 @@
android:textAppearance="@style/TextAppearance.AppCompat.Body1" android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/mainProfileImage" app:layout_constraintTop_toBottomOf="@id/fav_chip"
tools:text="Austin Huang" /> tools:text="Austin Huang" />
<androidx.appcompat.widget.AppCompatImageView <androidx.appcompat.widget.AppCompatImageView
@ -84,7 +135,7 @@
android:visibility="gone" android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/mainFullName" app:layout_constraintBottom_toBottomOf="@id/mainFullName"
app:layout_constraintStart_toEndOf="@id/mainFullName" app:layout_constraintStart_toEndOf="@id/mainFullName"
app:layout_constraintTop_toBottomOf="@id/mainProfileImage" app:layout_constraintTop_toBottomOf="@id/fav_chip"
app:srcCompat="@drawable/verified" app:srcCompat="@drawable/verified"
tools:visibility="visible" /> tools:visibility="visible" />
@ -151,29 +202,12 @@
app:iconGravity="top" app:iconGravity="top"
app:iconTint="@color/deep_purple_200" app:iconTint="@color/deep_purple_200"
app:layout_constraintBottom_toTopOf="@id/highlights_barrier" app:layout_constraintBottom_toTopOf="@id/highlights_barrier"
app:layout_constraintEnd_toStartOf="@id/btnTagged" app:layout_constraintEnd_toStartOf="@id/btnSaved"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/mainUrl" app:layout_constraintTop_toBottomOf="@id/mainUrl"
app:rippleColor="@color/purple_200" app:rippleColor="@color/purple_200"
tools:visibility="visible" /> tools:visibility="visible" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btnTagged"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/tagged"
android:textColor="@color/deep_orange_600"
android:visibility="gone"
app:icon="@drawable/ic_outline_person_pin_24"
app:iconGravity="top"
app:iconTint="@color/deep_orange_600"
app:layout_constraintBottom_toTopOf="@id/highlights_barrier"
app:layout_constraintEnd_toStartOf="@id/btnSaved"
app:layout_constraintStart_toEndOf="@id/btnFollow"
app:layout_constraintTop_toBottomOf="@id/mainUrl"
tools:visibility="visible" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/btnSaved" android:id="@+id/btnSaved"
style="@style/Widget.MaterialComponents.Button.TextButton" style="@style/Widget.MaterialComponents.Button.TextButton"
@ -187,7 +221,7 @@
app:iconTint="@color/blue_700" app:iconTint="@color/blue_700"
app:layout_constraintBottom_toTopOf="@id/highlights_barrier" app:layout_constraintBottom_toTopOf="@id/highlights_barrier"
app:layout_constraintEnd_toStartOf="@id/btnLiked" app:layout_constraintEnd_toStartOf="@id/btnLiked"
app:layout_constraintStart_toEndOf="@id/btnTagged" app:layout_constraintStart_toEndOf="@id/btnFollow"
app:layout_constraintTop_toBottomOf="@id/mainUrl" app:layout_constraintTop_toBottomOf="@id/mainUrl"
app:rippleColor="@color/blue_A400" app:rippleColor="@color/blue_A400"
tools:visibility="visible" /> tools:visibility="visible" />

View File

@ -4,6 +4,7 @@
<dimen name="private_page_margins">@dimen/profile_picture_size</dimen> <dimen name="private_page_margins">@dimen/profile_picture_size</dimen>
<dimen name="profile_picture_size">90dp</dimen> <dimen name="profile_picture_size">90dp</dimen>
<dimen name="profile_chip_size">40dp</dimen>
<dimen name="image_size_40">40dp</dimen> <dimen name="image_size_40">40dp</dimen>
<dimen name="profile_pic_size_tiny">24dp</dimen> <dimen name="profile_pic_size_tiny">24dp</dimen>

View File

@ -45,10 +45,15 @@
<string name="instadp_settings">Use Instadp for high definition profile pictures</string> <string name="instadp_settings">Use Instadp for high definition profile pictures</string>
<string name="import_export">Import/Export</string> <string name="import_export">Import/Export</string>
<string name="select_language">Language</string> <string name="select_language">Language</string>
<string name="main_posts_count">%s\nPosts</string> <plurals name="main_posts_count_inline">
<string name="main_posts_count_inline">%s Posts</string> <item quantity="one">%s Post</item>
<string name="main_posts_followers">%s\nFollowers</string> <item quantity="other">%s Posts</item>
<string name="main_posts_following">%s\nFollowing</string> </plurals>
<plurals name="main_posts_followers">
<item quantity="one">%s Follower</item>
<item quantity="other">%s Followers</item>
</plurals>
<string name="main_posts_following">%s Following </string>
<string name="post_viewer_autoplay_video">Autoplay videos</string> <string name="post_viewer_autoplay_video">Autoplay videos</string>
<string name="post_viewer_muted_autoplay">Always mute videos</string> <string name="post_viewer_muted_autoplay">Always mute videos</string>
<string name="post_viewer_download_dialog_title">Select what to download</string> <string name="post_viewer_download_dialog_title">Select what to download</string>
@ -107,6 +112,9 @@
<string name="unblock">Unblock</string> <string name="unblock">Unblock</string>
<string name="restrict">Restrict</string> <string name="restrict">Restrict</string>
<string name="unrestrict">Unrestrict</string> <string name="unrestrict">Unrestrict</string>
<string name="status_mutual">Following each other</string>
<string name="status_following">Followed by you</string>
<string name="status_follower">Following you</string>
<string name="map">Map</string> <string name="map">Map</string>
<string name="dialog_export_btn_export">Export</string> <string name="dialog_export_btn_export">Export</string>
<string name="dialog_export_btn_import">Import</string> <string name="dialog_export_btn_import">Import</string>