Browse Source

post likes viewer

renovate/org.robolectric-robolectric-4.x
Austin Huang 4 years ago
parent
commit
ae27d5d57a
No known key found for this signature in database GPG Key ID: 84C23AA04587A91F
  1. 45
      app/src/main/java/awais/instagrabber/adapters/LikesAdapter.java
  2. 2
      app/src/main/java/awais/instagrabber/adapters/viewholder/FollowsViewHolder.java
  3. 118
      app/src/main/java/awais/instagrabber/fragments/LikesViewerFragment.java
  4. 7
      app/src/main/java/awais/instagrabber/fragments/PostViewV2Fragment.java
  5. 4
      app/src/main/java/awais/instagrabber/repositories/MediaRepository.java
  6. 47
      app/src/main/java/awais/instagrabber/webservices/MediaService.java
  7. 21
      app/src/main/res/layout/fragment_likes.xml
  8. 11
      app/src/main/res/navigation/direct_messages_nav_graph.xml
  9. 11
      app/src/main/res/navigation/discover_nav_graph.xml
  10. 11
      app/src/main/res/navigation/feed_nav_graph.xml
  11. 11
      app/src/main/res/navigation/hashtag_nav_graph.xml
  12. 40
      app/src/main/res/navigation/likes_nav_graph.xml
  13. 11
      app/src/main/res/navigation/location_nav_graph.xml
  14. 1
      app/src/main/res/navigation/more_nav_graph.xml
  15. 1
      app/src/main/res/navigation/notification_viewer_nav_graph.xml
  16. 12
      app/src/main/res/navigation/profile_nav_graph.xml

45
app/src/main/java/awais/instagrabber/adapters/LikesAdapter.java

@ -0,0 +1,45 @@
package awais.instagrabber.adapters;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import awais.instagrabber.adapters.viewholder.FollowsViewHolder;
import awais.instagrabber.databinding.ItemFollowBinding;
import awais.instagrabber.models.ProfileModel;
public final class LikesAdapter extends RecyclerView.Adapter<FollowsViewHolder> {
private final List<ProfileModel> profileModels;
private final View.OnClickListener onClickListener;
public LikesAdapter(final List<ProfileModel> profileModels,
final View.OnClickListener onClickListener) {
this.profileModels = profileModels;
this.onClickListener = onClickListener;
}
@NonNull
@Override
public FollowsViewHolder onCreateViewHolder(@NonNull final ViewGroup parent, final int viewType) {
final LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
final ItemFollowBinding binding = ItemFollowBinding.inflate(layoutInflater, parent, false);
return new FollowsViewHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull final FollowsViewHolder holder, final int position) {
final ProfileModel model = profileModels.get(position);
holder.bind(model, null, onClickListener);
}
@Override
public int getItemCount() {
return profileModels.size();
}
}

2
app/src/main/java/awais/instagrabber/adapters/viewholder/FollowsViewHolder.java

@ -1,5 +1,6 @@
package awais.instagrabber.adapters.viewholder;
import android.util.Log;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
@ -22,6 +23,7 @@ public final class FollowsViewHolder extends RecyclerView.ViewHolder {
public void bind(final ProfileModel model,
final List<Long> admins,
final View.OnClickListener onClickListener) {
Log.d("austin_debug", "bind "+model);
if (model == null) return;
itemView.setTag(model);
itemView.setOnClickListener(onClickListener);

118
app/src/main/java/awais/instagrabber/fragments/LikesViewerFragment.java

@ -0,0 +1,118 @@
package awais.instagrabber.fragments;
import android.content.Context;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.LinearLayoutCompat;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavDirections;
import androidx.navigation.fragment.NavHostFragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import java.util.Collections;
import java.util.List;
import awais.instagrabber.BuildConfig;
import awais.instagrabber.R;
import awais.instagrabber.adapters.LikesAdapter;
import awais.instagrabber.databinding.FragmentLikesBinding;
import awais.instagrabber.models.ProfileModel;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
import awais.instagrabber.webservices.MediaService;
import awais.instagrabber.webservices.ServiceCallback;
public final class LikesViewerFragment extends BottomSheetDialogFragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "LikesViewerFragment";
private final String cookie = Utils.settingsHelper.getString(Constants.COOKIE);
private LikesAdapter likesAdapter;
private FragmentLikesBinding binding;
private LinearLayoutManager layoutManager;
private Resources resources;
private AppCompatActivity fragmentActivity;
private LinearLayoutCompat root;
private MediaService mediaService;
private String postId;
private final ServiceCallback<List<ProfileModel>> cb = new ServiceCallback<List<ProfileModel>>() {
@Override
public void onSuccess(final List<ProfileModel> result) {
final LikesAdapter likesAdapter = new LikesAdapter(result, v -> {
final Object tag = v.getTag();
if (tag instanceof ProfileModel) {
ProfileModel model = (ProfileModel) tag;
final Bundle bundle = new Bundle();
bundle.putString("username", "@" + model.getUsername());
NavHostFragment.findNavController(LikesViewerFragment.this).navigate(R.id.action_global_profileFragment, bundle);
}
});
binding.rvLikes.setAdapter(likesAdapter);
binding.rvLikes.setLayoutManager(new LinearLayoutManager(getContext()));
binding.swipeRefreshLayout.setRefreshing(false);
}
@Override
public void onFailure(final Throwable t) {
Log.e(TAG, "Error", t);
try {
final Context context = getContext();
Toast.makeText(context, t.getMessage(), Toast.LENGTH_SHORT).show();
}
catch (Exception e) {}
}
};
@Override
public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fragmentActivity = (AppCompatActivity) getActivity();
mediaService = MediaService.getInstance();
// setHasOptionsMenu(true);
}
@NonNull
@Override
public View onCreateView(@NonNull final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
binding = FragmentLikesBinding.inflate(getLayoutInflater());
binding.swipeRefreshLayout.setEnabled(false);
binding.swipeRefreshLayout.setNestedScrollingEnabled(false);
root = binding.getRoot();
return root;
}
@Override
public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
init();
}
@Override
public void onRefresh() {
mediaService.fetchLikes(postId, cb);
}
private void init() {
if (getArguments() == null) return;
final LikesViewerFragmentArgs fragmentArgs = LikesViewerFragmentArgs.fromBundle(getArguments());
postId = fragmentArgs.getPostId();
binding.swipeRefreshLayout.setOnRefreshListener(this);
binding.swipeRefreshLayout.setRefreshing(true);
resources = getResources();
onRefresh();
}
}

7
app/src/main/java/awais/instagrabber/fragments/PostViewV2Fragment.java

@ -535,7 +535,12 @@ public class PostViewV2Fragment extends SharedElementTransitionDialogFragment {
}
});
binding.like.setOnLongClickListener(v -> {
Utils.displayToastAboveView(context, v, getString(R.string.like_without_count));
final NavController navController = getNavController();
if (navController != null) {
final Bundle bundle = new Bundle();
bundle.putString("postId", feedModel.getPostId());
navController.navigate(R.id.action_global_likesViewerFragment, bundle);
}
return true;
});
}

4
app/src/main/java/awais/instagrabber/repositories/MediaRepository.java

@ -5,11 +5,15 @@ import java.util.Map;
import retrofit2.Call;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.POST;
import retrofit2.http.Path;
public interface MediaRepository {
@GET("/api/v1/media/{mediaId}/likers/")
Call<String> fetchLikes(@Header("User-Agent") final String userAgent,
@Path("mediaId") final String mediaId);
@FormUrlEncoded
@POST("/api/v1/media/{mediaId}/{action}/")

47
app/src/main/java/awais/instagrabber/webservices/MediaService.java

@ -5,15 +5,18 @@ import android.util.Log;
import androidx.annotation.NonNull;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import awais.instagrabber.models.ProfileModel;
import awais.instagrabber.repositories.MediaRepository;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.Utils;
@ -277,4 +280,48 @@ public class MediaService extends BaseService {
}
});
}
public void fetchLikes(final String mediaId,
@NonNull final ServiceCallback<List<ProfileModel>> callback) {
final Call<String> likesRequest = repository.fetchLikes(Constants.I_USER_AGENT, mediaId);
likesRequest.enqueue(new Callback<String>() {
@Override
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
final String body = response.body();
if (body == null) {
Log.e(TAG, "Error occurred while fetching likes of "+mediaId);
callback.onSuccess(null);
return;
}
try {
final JSONObject data = new JSONObject(body);
final JSONArray users = data.getJSONArray("users");
final int usersLen = users.length();
final List<ProfileModel> userModels = new ArrayList<>();
for (int j = 0; j < usersLen; ++j) {
final JSONObject userObject = users.getJSONObject(j);
userModels.add(new ProfileModel(userObject.optBoolean("is_private"),
false,
userObject.optBoolean("is_verified"),
String.valueOf(userObject.get("pk")),
userObject.getString("username"),
userObject.optString("full_name"),
null, null,
userObject.getString("profile_pic_url"),
null, 0, 0, 0, false, false, false, false, false));
}
callback.onSuccess(userModels);
} catch (JSONException e) {
// Log.e(TAG, "Error parsing body", e);
callback.onFailure(e);
}
}
@Override
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
Log.e(TAG, "Error getting likes", t);
callback.onFailure(t);
}
});
}
}

21
app/src/main/res/layout/fragment_likes.xml

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvLikes"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</androidx.appcompat.widget.LinearLayoutCompat>

11
app/src/main/res/navigation/direct_messages_nav_graph.xml

@ -63,6 +63,17 @@
app:nullable="false" />
</action>
<include app:graph="@navigation/likes_nav_graph" />
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likes_nav_graph">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
</action>
<fragment
android:id="@+id/directMessagesInboxFragment"
android:name="awais.instagrabber.fragments.directmessages.DirectMessageInboxFragment"

11
app/src/main/res/navigation/discover_nav_graph.xml

@ -57,6 +57,17 @@
app:nullable="false" />
</action>
<include app:graph="@navigation/likes_nav_graph" />
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likes_nav_graph">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
</action>
<include app:graph="@navigation/notification_viewer_nav_graph" />
<action

11
app/src/main/res/navigation/feed_nav_graph.xml

@ -57,6 +57,17 @@
app:nullable="false" />
</action>
<include app:graph="@navigation/likes_nav_graph" />
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likes_nav_graph">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
</action>
<include app:graph="@navigation/notification_viewer_nav_graph" />
<action

11
app/src/main/res/navigation/hashtag_nav_graph.xml

@ -24,6 +24,17 @@
app:nullable="false" />
</action>
<include app:graph="@navigation/likes_nav_graph" />
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likes_nav_graph">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
</action>
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profile_nav_graph">

40
app/src/main/res/navigation/likes_nav_graph.xml

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/likes_nav_graph"
app:startDestination="@id/likesViewerFragment">
<!--<include app:graph="@navigation/hashtag_nav_graph" />-->
<!--<include app:graph="@navigation/profile_nav_graph" />-->
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profile_nav_graph">
<argument
android:name="username"
app:argType="string"
app:nullable="true" />
</action>
<dialog
android:id="@+id/likesViewerFragment"
android:name="awais.instagrabber.fragments.LikesViewerFragment"
android:label="Comments"
tools:layout="@layout/fragment_likes">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
</dialog>
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likesViewerFragment">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
</action>
</navigation>

11
app/src/main/res/navigation/location_nav_graph.xml

@ -24,6 +24,17 @@
app:nullable="false" />
</action>
<include app:graph="@navigation/likes_nav_graph" />
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likes_nav_graph">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
</action>
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profile_nav_graph">

1
app/src/main/res/navigation/more_nav_graph.xml

@ -8,6 +8,7 @@
<include app:graph="@navigation/hashtag_nav_graph" />
<include app:graph="@navigation/location_nav_graph" />
<include app:graph="@navigation/comments_nav_graph" />
<include app:graph="@navigation/likes_nav_graph" />
<include app:graph="@navigation/notification_viewer_nav_graph" />
<action

1
app/src/main/res/navigation/notification_viewer_nav_graph.xml

@ -16,6 +16,7 @@
app:destination="@id/notificationsViewer" />
<include app:graph="@navigation/comments_nav_graph" />
<include app:graph="@navigation/likes_nav_graph" />
<action
android:id="@+id/action_global_commentsViewerFragment"

12
app/src/main/res/navigation/profile_nav_graph.xml

@ -24,6 +24,18 @@
app:nullable="false" />
</action>
<include app:graph="@navigation/likes_nav_graph" />
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likes_nav_graph">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
</action>
<include app:graph="@navigation/hashtag_nav_graph" />
<action

Loading…
Cancel
Save