Austin Huang
4 years ago
No known key found for this signature in database
GPG Key ID: 84C23AA04587A91F
29 changed files with 517 additions and 58 deletions
-
7app/src/main/java/awais/instagrabber/adapters/SavedCollectionsAdapter.java
-
2app/src/main/java/awais/instagrabber/adapters/viewholder/TopicClusterViewHolder.java
-
6app/src/main/java/awais/instagrabber/asyncs/DiscoverPostFetchService.java
-
73app/src/main/java/awais/instagrabber/fragments/CollectionPostsFragment.java
-
30app/src/main/java/awais/instagrabber/fragments/PostViewV2Fragment.java
-
38app/src/main/java/awais/instagrabber/fragments/SavedCollectionsFragment.java
-
2app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java
-
23app/src/main/java/awais/instagrabber/repositories/CollectionRepository.java
-
7app/src/main/java/awais/instagrabber/repositories/ProfileRepository.java
-
43app/src/main/java/awais/instagrabber/repositories/responses/WrappedFeedResponse.java
-
13app/src/main/java/awais/instagrabber/repositories/responses/WrappedMedia.java
-
7app/src/main/java/awais/instagrabber/repositories/responses/discover/TopicalExploreFeedResponse.java
-
15app/src/main/java/awais/instagrabber/repositories/responses/discover/TopicalExploreItem.java
-
8app/src/main/java/awais/instagrabber/repositories/responses/saved/SavedCollection.java
-
18app/src/main/java/awais/instagrabber/viewmodels/PostViewV2ViewModel.java
-
120app/src/main/java/awais/instagrabber/webservices/CollectionService.java
-
14app/src/main/java/awais/instagrabber/webservices/MediaService.java
-
30app/src/main/java/awais/instagrabber/webservices/ProfileService.java
-
21app/src/main/res/menu/collection_posts_menu.xml
-
22app/src/main/res/menu/saved_collection_select_menu.xml
-
10app/src/main/res/navigation/direct_messages_nav_graph.xml
-
10app/src/main/res/navigation/discover_nav_graph.xml
-
10app/src/main/res/navigation/feed_nav_graph.xml
-
10app/src/main/res/navigation/hashtag_nav_graph.xml
-
10app/src/main/res/navigation/location_nav_graph.xml
-
10app/src/main/res/navigation/notification_viewer_nav_graph.xml
-
6app/src/main/res/navigation/profile_nav_graph.xml
-
4app/src/main/res/navigation/saved_nav_graph.xml
-
6app/src/main/res/values/strings.xml
@ -0,0 +1,23 @@ |
|||||
|
package awais.instagrabber.repositories; |
||||
|
|
||||
|
import java.util.Map; |
||||
|
|
||||
|
import awais.instagrabber.repositories.responses.UserFeedResponse; |
||||
|
import awais.instagrabber.repositories.responses.WrappedFeedResponse; |
||||
|
import awais.instagrabber.repositories.responses.saved.CollectionsListResponse; |
||||
|
import retrofit2.Call; |
||||
|
import retrofit2.http.FieldMap; |
||||
|
import retrofit2.http.FormUrlEncoded; |
||||
|
import retrofit2.http.GET; |
||||
|
import retrofit2.http.POST; |
||||
|
import retrofit2.http.Path; |
||||
|
import retrofit2.http.QueryMap; |
||||
|
|
||||
|
public interface CollectionRepository { |
||||
|
|
||||
|
@FormUrlEncoded |
||||
|
@POST("/api/v1/collections/{id}/{action}/") |
||||
|
Call<String> changeCollection(@Path("id") String id, |
||||
|
@Path("action") String action, |
||||
|
@FieldMap Map<String, String> signedForm); |
||||
|
} |
@ -0,0 +1,43 @@ |
|||||
|
package awais.instagrabber.repositories.responses; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public class WrappedFeedResponse { |
||||
|
private final int numResults; |
||||
|
private final String nextMaxId; |
||||
|
private final boolean moreAvailable; |
||||
|
private final String status; |
||||
|
private final List<WrappedMedia> items; |
||||
|
|
||||
|
public WrappedFeedResponse(final int numResults, |
||||
|
final String nextMaxId, |
||||
|
final boolean moreAvailable, |
||||
|
final String status, |
||||
|
final List<WrappedMedia> items) { |
||||
|
this.numResults = numResults; |
||||
|
this.nextMaxId = nextMaxId; |
||||
|
this.moreAvailable = moreAvailable; |
||||
|
this.status = status; |
||||
|
this.items = items; |
||||
|
} |
||||
|
|
||||
|
public int getNumResults() { |
||||
|
return numResults; |
||||
|
} |
||||
|
|
||||
|
public String getNextMaxId() { |
||||
|
return nextMaxId; |
||||
|
} |
||||
|
|
||||
|
public boolean isMoreAvailable() { |
||||
|
return moreAvailable; |
||||
|
} |
||||
|
|
||||
|
public String getStatus() { |
||||
|
return status; |
||||
|
} |
||||
|
|
||||
|
public List<WrappedMedia> getItems() { |
||||
|
return items; |
||||
|
} |
||||
|
} |
@ -0,0 +1,13 @@ |
|||||
|
package awais.instagrabber.repositories.responses; |
||||
|
|
||||
|
public class WrappedMedia { |
||||
|
private final Media media; |
||||
|
|
||||
|
public WrappedMedia(final Media media) { |
||||
|
this.media = media; |
||||
|
} |
||||
|
|
||||
|
public Media getMedia() { |
||||
|
return media; |
||||
|
} |
||||
|
} |
@ -1,15 +0,0 @@ |
|||||
package awais.instagrabber.repositories.responses.discover; |
|
||||
|
|
||||
import awais.instagrabber.repositories.responses.Media; |
|
||||
|
|
||||
public class TopicalExploreItem { |
|
||||
private final Media media; |
|
||||
|
|
||||
public TopicalExploreItem(final Media media) { |
|
||||
this.media = media; |
|
||||
} |
|
||||
|
|
||||
public Media getMedia() { |
|
||||
return media; |
|
||||
} |
|
||||
} |
|
@ -0,0 +1,120 @@ |
|||||
|
package awais.instagrabber.webservices; |
||||
|
|
||||
|
import androidx.annotation.NonNull; |
||||
|
|
||||
|
import java.util.HashMap; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
import java.util.Objects; |
||||
|
import java.util.stream.Collectors; |
||||
|
|
||||
|
import awais.instagrabber.repositories.CollectionRepository; |
||||
|
import awais.instagrabber.repositories.responses.Media; |
||||
|
import awais.instagrabber.utils.Utils; |
||||
|
import retrofit2.Call; |
||||
|
import retrofit2.Callback; |
||||
|
import retrofit2.Response; |
||||
|
import retrofit2.Retrofit; |
||||
|
|
||||
|
public class CollectionService extends BaseService { |
||||
|
private static final String TAG = "ProfileService"; |
||||
|
|
||||
|
private final CollectionRepository repository; |
||||
|
private final String deviceUuid, csrfToken; |
||||
|
private final long userId; |
||||
|
|
||||
|
private static CollectionService instance; |
||||
|
|
||||
|
private CollectionService(final String deviceUuid, |
||||
|
final String csrfToken, |
||||
|
final long userId) { |
||||
|
this.deviceUuid = deviceUuid; |
||||
|
this.csrfToken = csrfToken; |
||||
|
this.userId = userId; |
||||
|
final Retrofit retrofit = getRetrofitBuilder() |
||||
|
.baseUrl("https://i.instagram.com") |
||||
|
.build(); |
||||
|
repository = retrofit.create(CollectionRepository.class); |
||||
|
} |
||||
|
|
||||
|
public String getCsrfToken() { |
||||
|
return csrfToken; |
||||
|
} |
||||
|
|
||||
|
public String getDeviceUuid() { |
||||
|
return deviceUuid; |
||||
|
} |
||||
|
|
||||
|
public long getUserId() { |
||||
|
return userId; |
||||
|
} |
||||
|
|
||||
|
public static CollectionService getInstance(final String deviceUuid, final String csrfToken, final long userId) { |
||||
|
if (instance == null |
||||
|
|| !Objects.equals(instance.getCsrfToken(), csrfToken) |
||||
|
|| !Objects.equals(instance.getDeviceUuid(), deviceUuid) |
||||
|
|| !Objects.equals(instance.getUserId(), userId)) { |
||||
|
instance = new CollectionService(deviceUuid, csrfToken, userId); |
||||
|
} |
||||
|
return instance; |
||||
|
} |
||||
|
|
||||
|
public void addPostsToCollection(final String collectionId, |
||||
|
final List<Media> posts, |
||||
|
final ServiceCallback<String> callback) { |
||||
|
final Map<String, Object> form = new HashMap<>(2); |
||||
|
form.put("module_name", "feed_saved_add_to_collection"); |
||||
|
final List<String> ids; |
||||
|
ids = posts.stream() |
||||
|
.map(Media::getPk) |
||||
|
.filter(Objects::nonNull) |
||||
|
.collect(Collectors.toList()); |
||||
|
form.put("added_media_ids", "[" + String.join(",", ids) + "]"); |
||||
|
changeCollection(collectionId, "edit", form, callback); |
||||
|
} |
||||
|
|
||||
|
public void editCollectionName(final String collectionId, |
||||
|
final String name, |
||||
|
final ServiceCallback<String> callback) { |
||||
|
final Map<String, Object> form = new HashMap<>(1); |
||||
|
form.put("name", name); |
||||
|
changeCollection(collectionId, "edit", form, callback); |
||||
|
} |
||||
|
|
||||
|
public void deleteCollection(final String collectionId, |
||||
|
final ServiceCallback<String> callback) { |
||||
|
changeCollection(collectionId, "delete", null, callback); |
||||
|
} |
||||
|
|
||||
|
public void changeCollection(final String collectionId, |
||||
|
final String action, |
||||
|
final Map<String, Object> options, |
||||
|
final ServiceCallback<String> callback) { |
||||
|
final Map<String, Object> form = new HashMap<>(); |
||||
|
form.put("_csrftoken", csrfToken); |
||||
|
form.put("_uuid", deviceUuid); |
||||
|
form.put("_uid", userId); |
||||
|
if (options != null) form.putAll(options); |
||||
|
final Map<String, String> signedForm = Utils.sign(form); |
||||
|
final Call<String> request = repository.changeCollection(collectionId, action, signedForm); |
||||
|
request.enqueue(new Callback<String>() { |
||||
|
@Override |
||||
|
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |
||||
|
if (callback == null) return; |
||||
|
final String collectionsListResponse = response.body(); |
||||
|
if (collectionsListResponse == null) { |
||||
|
callback.onSuccess(null); |
||||
|
return; |
||||
|
} |
||||
|
callback.onSuccess(collectionsListResponse); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { |
||||
|
if (callback != null) { |
||||
|
callback.onFailure(t); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
@ -0,0 +1,21 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" |
||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"> |
||||
|
|
||||
|
<item |
||||
|
android:id="@+id/edit" |
||||
|
android:icon="@android:drawable/ic_menu_edit" |
||||
|
android:title="@string/edit_collection" |
||||
|
app:showAsAction="always" /> |
||||
|
|
||||
|
<item |
||||
|
android:id="@+id/delete" |
||||
|
android:icon="@android:drawable/ic_menu_delete" |
||||
|
android:title="@string/delete_collection" |
||||
|
app:showAsAction="always" /> |
||||
|
|
||||
|
<item |
||||
|
android:id="@+id/layout" |
||||
|
android:title="@string/layout" |
||||
|
app:showAsAction="never" /> |
||||
|
</menu> |
@ -0,0 +1,22 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android" |
||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"> |
||||
|
<item |
||||
|
android:id="@+id/action_add" |
||||
|
android:icon="@drawable/ic_add" |
||||
|
android:title="@string/add_to_collection" |
||||
|
android:titleCondensed="@string/action_download" |
||||
|
app:showAsAction="always" /> |
||||
|
<item |
||||
|
android:id="@+id/action_delete" |
||||
|
android:icon="@drawable/ic_cancel" |
||||
|
android:title="@string/remove_from_collection" |
||||
|
android:titleCondensed="@string/action_download" |
||||
|
app:showAsAction="always" /> |
||||
|
<item |
||||
|
android:id="@+id/action_download" |
||||
|
android:icon="@drawable/ic_download" |
||||
|
android:title="@string/action_download" |
||||
|
android:titleCondensed="@string/action_download" |
||||
|
app:showAsAction="always" /> |
||||
|
</menu> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue