diff --git a/app/src/main/java/awais/instagrabber/asyncs/HashtagPostFetchService.java b/app/src/main/java/awais/instagrabber/asyncs/HashtagPostFetchService.java index 7b26d79b..3eb3fdc5 100644 --- a/app/src/main/java/awais/instagrabber/asyncs/HashtagPostFetchService.java +++ b/app/src/main/java/awais/instagrabber/asyncs/HashtagPostFetchService.java @@ -9,12 +9,13 @@ import awais.instagrabber.repositories.responses.Media; import awais.instagrabber.repositories.responses.PostsFetchResponse; import awais.instagrabber.utils.CoroutineUtilsKt; import awais.instagrabber.webservices.GraphQLRepository; +import awais.instagrabber.webservices.HashtagRepository; import awais.instagrabber.webservices.ServiceCallback; -import awais.instagrabber.webservices.TagsService; +import kotlin.coroutines.Continuation; import kotlinx.coroutines.Dispatchers; public class HashtagPostFetchService implements PostFetcher.PostFetchService { - private final TagsService tagsService; + private final HashtagRepository hashtagRepository; private final GraphQLRepository graphQLRepository; private final Hashtag hashtagModel; private String nextMaxId; @@ -24,42 +25,31 @@ public class HashtagPostFetchService implements PostFetcher.PostFetchService { public HashtagPostFetchService(final Hashtag hashtagModel, final boolean isLoggedIn) { this.hashtagModel = hashtagModel; this.isLoggedIn = isLoggedIn; - tagsService = isLoggedIn ? TagsService.getInstance() : null; + hashtagRepository = isLoggedIn ? HashtagRepository.Companion.getInstance() : null; graphQLRepository = isLoggedIn ? null : GraphQLRepository.Companion.getInstance(); } @Override public void fetch(final FetchListener> fetchListener) { - final ServiceCallback cb = new ServiceCallback() { - @Override - public void onSuccess(final PostsFetchResponse result) { - if (result == null) return; - nextMaxId = result.getNextCursor(); - moreAvailable = result.getHasNextPage(); - if (fetchListener != null) { - fetchListener.onResult(result.getFeedModels()); - } - } - - @Override - public void onFailure(final Throwable t) { - // Log.e(TAG, "onFailure: ", t); + final Continuation cb = CoroutineUtilsKt.getContinuation((result, t) -> { + if (t != null) { if (fetchListener != null) { fetchListener.onFailure(t); } + return; } - }; - if (isLoggedIn) tagsService.fetchPosts(hashtagModel.getName().toLowerCase(), nextMaxId, cb); + if (result == null) return; + nextMaxId = result.getNextCursor(); + moreAvailable = result.getHasNextPage(); + if (fetchListener != null) { + fetchListener.onResult(result.getFeedModels()); + } + }, Dispatchers.getIO()); + if (isLoggedIn) hashtagRepository.fetchPosts(hashtagModel.getName().toLowerCase(), nextMaxId, cb); else graphQLRepository.fetchHashtagPosts( hashtagModel.getName().toLowerCase(), nextMaxId, - CoroutineUtilsKt.getContinuation((postsFetchResponse, throwable) -> { - if (throwable != null) { - cb.onFailure(throwable); - return; - } - cb.onSuccess(postsFetchResponse); - }, Dispatchers.getIO()) + cb ); } diff --git a/app/src/main/java/awais/instagrabber/asyncs/LocationPostFetchService.java b/app/src/main/java/awais/instagrabber/asyncs/LocationPostFetchService.java index 11f5dce3..54143266 100644 --- a/app/src/main/java/awais/instagrabber/asyncs/LocationPostFetchService.java +++ b/app/src/main/java/awais/instagrabber/asyncs/LocationPostFetchService.java @@ -9,12 +9,13 @@ import awais.instagrabber.repositories.responses.Media; import awais.instagrabber.repositories.responses.PostsFetchResponse; import awais.instagrabber.utils.CoroutineUtilsKt; import awais.instagrabber.webservices.GraphQLRepository; -import awais.instagrabber.webservices.LocationService; +import awais.instagrabber.webservices.LocationRepository; import awais.instagrabber.webservices.ServiceCallback; +import kotlin.coroutines.Continuation; import kotlinx.coroutines.Dispatchers; public class LocationPostFetchService implements PostFetcher.PostFetchService { - private final LocationService locationService; + private final LocationRepository locationRepository; private final GraphQLRepository graphQLRepository; private final Location locationModel; private String nextMaxId; @@ -24,42 +25,31 @@ public class LocationPostFetchService implements PostFetcher.PostFetchService { public LocationPostFetchService(final Location locationModel, final boolean isLoggedIn) { this.locationModel = locationModel; this.isLoggedIn = isLoggedIn; - locationService = isLoggedIn ? LocationService.getInstance() : null; + locationRepository = isLoggedIn ? LocationRepository.Companion.getInstance() : null; graphQLRepository = isLoggedIn ? null : GraphQLRepository.Companion.getInstance(); } @Override public void fetch(final FetchListener> fetchListener) { - final ServiceCallback cb = new ServiceCallback() { - @Override - public void onSuccess(final PostsFetchResponse result) { - if (result == null) return; - nextMaxId = result.getNextCursor(); - moreAvailable = result.getHasNextPage(); - if (fetchListener != null) { - fetchListener.onResult(result.getFeedModels()); - } - } - - @Override - public void onFailure(final Throwable t) { - // Log.e(TAG, "onFailure: ", t); + final Continuation cb = CoroutineUtilsKt.getContinuation((result, t) -> { + if (t != null) { if (fetchListener != null) { fetchListener.onFailure(t); } + return; } - }; - if (isLoggedIn) locationService.fetchPosts(locationModel.getPk(), nextMaxId, cb); + if (result == null) return; + nextMaxId = result.getNextCursor(); + moreAvailable = result.getHasNextPage(); + if (fetchListener != null) { + fetchListener.onResult(result.getFeedModels()); + } + }, Dispatchers.getIO()); + if (isLoggedIn) locationRepository.fetchPosts(locationModel.getPk(), nextMaxId, cb); else graphQLRepository.fetchLocationPosts( locationModel.getPk(), nextMaxId, - CoroutineUtilsKt.getContinuation((postsFetchResponse, throwable) -> { - if (throwable != null) { - cb.onFailure(throwable); - return; - } - cb.onSuccess(postsFetchResponse); - }, Dispatchers.getIO()) + cb ); } diff --git a/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java b/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java index 0e5ba714..5fc8101e 100644 --- a/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java @@ -48,7 +48,6 @@ import awais.instagrabber.db.repositories.FavoriteRepository; import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment; import awais.instagrabber.models.PostsLayoutPreferences; import awais.instagrabber.models.enums.FavoriteType; -import awais.instagrabber.models.enums.FollowingType; import awais.instagrabber.repositories.responses.Hashtag; import awais.instagrabber.repositories.responses.Location; import awais.instagrabber.repositories.responses.Media; @@ -61,8 +60,9 @@ import awais.instagrabber.utils.DownloadUtils; import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.Utils; import awais.instagrabber.webservices.GraphQLRepository; +import awais.instagrabber.webservices.HashtagRepository; import awais.instagrabber.webservices.ServiceCallback; -import awais.instagrabber.webservices.TagsService; +import kotlin.coroutines.Continuation; import kotlinx.coroutines.Dispatchers; import static awais.instagrabber.utils.Utils.settingsHelper; @@ -80,7 +80,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe private ActionMode actionMode; // private StoriesRepository storiesRepository; private boolean isLoggedIn; - private TagsService tagsService; + private HashtagRepository hashtagRepository; private GraphQLRepository graphQLRepository; // private boolean storiesFetching; private Set selectedFeedModels; @@ -264,19 +264,6 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe } } }; - private final ServiceCallback cb = new ServiceCallback() { - @Override - public void onSuccess(final Hashtag result) { - hashtagModel = result; - binding.swipeRefreshLayout.setRefreshing(false); - setHashtagDetails(); - } - - @Override - public void onFailure(final Throwable t) { - setHashtagDetails(); - } - }; @Override public void onCreate(@Nullable final Bundle savedInstanceState) { @@ -284,7 +271,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe fragmentActivity = (MainActivity) requireActivity(); final String cookie = settingsHelper.getString(Constants.COOKIE); isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0; - tagsService = isLoggedIn ? TagsService.getInstance() : null; + hashtagRepository = isLoggedIn ? HashtagRepository.Companion.getInstance() : null; // storiesRepository = isLoggedIn ? StoriesRepository.Companion.getInstance() : null; graphQLRepository = isLoggedIn ? null : GraphQLRepository.Companion.getInstance(); setHasOptionsMenu(true); @@ -349,19 +336,20 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe final HashTagFragmentArgs fragmentArgs = HashTagFragmentArgs.fromBundle(getArguments()); hashtag = fragmentArgs.getHashtag(); if (hashtag.charAt(0) == '#') hashtag = hashtag.substring(1); - fetchHashtagModel(); + fetchHashtagModel(true); } - private void fetchHashtagModel() { + private void fetchHashtagModel(final boolean init) { binding.swipeRefreshLayout.setRefreshing(true); - if (isLoggedIn) tagsService.fetch(hashtag, cb); - else graphQLRepository.fetchTag(hashtag, CoroutineUtilsKt.getContinuation((hashtag1, throwable) -> { - if (throwable != null) { - cb.onFailure(throwable); - return; - } - AppExecutors.INSTANCE.getMainThread().execute(() -> cb.onSuccess(hashtag1)); - }, Dispatchers.getIO())); + final Continuation cb = CoroutineUtilsKt.getContinuation((result, t) -> { + hashtagModel = result; + AppExecutors.INSTANCE.getMainThread().execute(() -> { + setHashtagDetails(init); + binding.swipeRefreshLayout.setRefreshing(false); + }); + }, Dispatchers.getIO()); + if (isLoggedIn) hashtagRepository.fetch(hashtag, cb); + else graphQLRepository.fetchTag(hashtag, cb); } private void setupPosts() { @@ -386,7 +374,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe // }); } - private void setHashtagDetails() { + private void setHashtagDetails(final boolean init) { if (hashtagModel == null) { try { Toast.makeText(getContext(), R.string.error_loading_hashtag, Toast.LENGTH_SHORT).show(); @@ -394,14 +382,16 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe } catch (Exception ignored) {} return; } - setTitle(); - setupPosts(); + if (init) { + setTitle(); + setupPosts(); + } if (isLoggedIn) { hashtagDetailsBinding.btnFollowTag.setVisibility(View.VISIBLE); - hashtagDetailsBinding.btnFollowTag.setText(hashtagModel.getFollowing() == FollowingType.FOLLOWING + hashtagDetailsBinding.btnFollowTag.setText(hashtagModel.getFollow() ? R.string.unfollow : R.string.follow); - hashtagDetailsBinding.btnFollowTag.setChipIconResource(hashtagModel.getFollowing() == FollowingType.FOLLOWING + hashtagDetailsBinding.btnFollowTag.setChipIconResource(hashtagModel.getFollow() ? R.drawable.ic_outline_person_add_disabled_24 : R.drawable.ic_outline_person_add_24); hashtagDetailsBinding.btnFollowTag.setOnClickListener(v -> { @@ -411,29 +401,15 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe final String deviceUuid = Utils.settingsHelper.getString(Constants.DEVICE_UUID); if (csrfToken != null && userId != 0) { hashtagDetailsBinding.btnFollowTag.setClickable(false); - tagsService.changeFollow( - hashtagModel.getFollowing() == FollowingType.FOLLOWING ? "unfollow" : "follow", + hashtagRepository.changeFollow( + hashtagModel.getFollow() ? "unfollow" : "follow", hashtag, csrfToken, userId, deviceUuid, - new ServiceCallback() { - @Override - public void onSuccess(final Boolean result) { - hashtagDetailsBinding.btnFollowTag.setClickable(true); - if (!result) { - Log.e(TAG, "onSuccess: result is false"); - Snackbar.make(root, R.string.downloader_unknown_error, BaseTransientBottomBar.LENGTH_LONG) - .show(); - return; - } - hashtagDetailsBinding.btnFollowTag.setText(R.string.unfollow); - hashtagDetailsBinding.btnFollowTag.setChipIconResource(R.drawable.ic_outline_person_add_disabled_24); - } - - @Override - public void onFailure(@NonNull final Throwable t) { - hashtagDetailsBinding.btnFollowTag.setClickable(true); + CoroutineUtilsKt.getContinuation((result, t) -> { + hashtagDetailsBinding.btnFollowTag.setClickable(true); + if (t != null) { Log.e(TAG, "onFailure: ", t); final String message = t.getMessage(); Snackbar.make( @@ -441,8 +417,17 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe message != null ? message : getString(R.string.downloader_unknown_error), BaseTransientBottomBar.LENGTH_LONG) .show(); + return; } - }); + if (result != true) { + Log.e(TAG, "onSuccess: result is false"); + Snackbar.make(root, R.string.downloader_unknown_error, BaseTransientBottomBar.LENGTH_LONG) + .show(); + return; + } + fetchHashtagModel(false); + }) + ); } }); } else { @@ -451,6 +436,18 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe hashtagDetailsBinding.favChip.setVisibility(View.VISIBLE); final Context context = getContext(); if (context == null) return; + final String postCount = String.valueOf(hashtagModel.getMediaCount()); + final SpannableStringBuilder span = new SpannableStringBuilder(getResources().getQuantityString( + R.plurals.main_posts_count_inline, + hashtagModel.getMediaCount() > 2000000000L ? 2000000000 + : Long.valueOf(hashtagModel.getMediaCount()).intValue(), + postCount) + ); + span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0); + span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0); + hashtagDetailsBinding.mainTagPostCount.setText(span); + hashtagDetailsBinding.mainTagPostCount.setVisibility(View.VISIBLE); + if (!init) return; final FavoriteRepository favoriteRepository = FavoriteRepository.Companion.getInstance(context); favoriteRepository.getFavorite( hashtag, @@ -528,17 +525,6 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe ) ); hashtagDetailsBinding.mainHashtagImage.setImageURI("res:/" + R.drawable.ic_hashtag); - final String postCount = String.valueOf(hashtagModel.getMediaCount()); - final SpannableStringBuilder span = new SpannableStringBuilder(getResources().getQuantityString( - R.plurals.main_posts_count_inline, - hashtagModel.getMediaCount() > 2000000000L ? 2000000000 - : Long.valueOf(hashtagModel.getMediaCount()).intValue(), - postCount) - ); - span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0); - span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0); - hashtagDetailsBinding.mainTagPostCount.setText(span); - hashtagDetailsBinding.mainTagPostCount.setVisibility(View.VISIBLE); // hashtagDetailsBinding.mainHashtagImage.setOnClickListener(v -> { // if (!hasStories) return; // // show stories diff --git a/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java b/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java index ab862a91..9fcea652 100644 --- a/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/LocationFragment.java @@ -58,8 +58,8 @@ import awais.instagrabber.utils.DownloadUtils; import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.Utils; import awais.instagrabber.webservices.GraphQLRepository; -import awais.instagrabber.webservices.LocationService; -import awais.instagrabber.webservices.ServiceCallback; +import awais.instagrabber.webservices.LocationRepository; +import kotlin.coroutines.Continuation; import kotlinx.coroutines.Dispatchers; import static awais.instagrabber.utils.Utils.settingsHelper; @@ -76,7 +76,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR private Location locationModel; private ActionMode actionMode; private GraphQLRepository graphQLRepository; - private LocationService locationService; + private LocationRepository locationRepository; private boolean isLoggedIn; private Set selectedFeedModels; private PostsLayoutPreferences layoutPreferences = Utils.getPostsLayoutPreferences(Constants.PREF_LOCATION_POSTS_LAYOUT); @@ -257,19 +257,6 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR } } }; - private final ServiceCallback cb = new ServiceCallback() { - @Override - public void onSuccess(final Location result) { - locationModel = result; - binding.swipeRefreshLayout.setRefreshing(false); - setupLocationDetails(); - } - - @Override - public void onFailure(final Throwable t) { - setupLocationDetails(); - } - }; @Override public void onCreate(@Nullable final Bundle savedInstanceState) { @@ -277,7 +264,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR fragmentActivity = (MainActivity) requireActivity(); final String cookie = settingsHelper.getString(Constants.COOKIE); isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0; - locationService = isLoggedIn ? LocationService.getInstance() : null; + locationRepository = isLoggedIn ? LocationRepository.Companion.getInstance() : null; // storiesRepository = StoriesRepository.Companion.getInstance(); graphQLRepository = isLoggedIn ? null : GraphQLRepository.Companion.getInstance(); setHasOptionsMenu(true); @@ -372,17 +359,15 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR private void fetchLocationModel() { binding.swipeRefreshLayout.setRefreshing(true); - if (isLoggedIn) locationService.fetch(locationId, cb); - else graphQLRepository.fetchLocation( - locationId, - CoroutineUtilsKt.getContinuation((location, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { - if (throwable != null) { - cb.onFailure(throwable); - return; - } - cb.onSuccess(location); - })) - ); + final Continuation cb = CoroutineUtilsKt.getContinuation((result, t) -> { + locationModel = result; + AppExecutors.INSTANCE.getMainThread().execute(() -> { + setupLocationDetails(); + binding.swipeRefreshLayout.setRefreshing(false); + }); + }, Dispatchers.getIO()); + if (isLoggedIn) locationRepository.fetch(locationId, cb); + else graphQLRepository.fetchLocation(locationId, cb); } private void setupLocationDetails() { diff --git a/app/src/main/java/awais/instagrabber/models/enums/FollowingType.kt b/app/src/main/java/awais/instagrabber/models/enums/FollowingType.kt deleted file mode 100755 index 5a908476..00000000 --- a/app/src/main/java/awais/instagrabber/models/enums/FollowingType.kt +++ /dev/null @@ -1,24 +0,0 @@ -package awais.instagrabber.models.enums - -import java.io.Serializable -import java.util.* - -enum class FollowingType(val id: Int) : Serializable { - FOLLOWING(1), - NOT_FOLLOWING(0); - - companion object { - private val map: MutableMap = mutableMapOf() - - @JvmStatic - fun valueOf(id: Int): FollowingType? { - return map[id] - } - - init { - for (type in values()) { - map[type.id] = type - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/repositories/HashtagService.kt b/app/src/main/java/awais/instagrabber/repositories/HashtagService.kt new file mode 100644 index 00000000..c4c9032c --- /dev/null +++ b/app/src/main/java/awais/instagrabber/repositories/HashtagService.kt @@ -0,0 +1,25 @@ +package awais.instagrabber.repositories + +import awais.instagrabber.repositories.responses.Hashtag +import awais.instagrabber.repositories.responses.TagFeedResponse +import retrofit2.Call +import retrofit2.http.* + +interface HashtagService { + @GET("/api/v1/tags/{tag}/info/") + suspend fun fetch(@Path("tag") tag: String?): Hashtag? + + @FormUrlEncoded + @POST("/api/v1/tags/{action}/{tag}/") + suspend fun changeFollow( + @FieldMap signedForm: Map?, + @Path("action") action: String?, + @Path("tag") tag: String? + ): String? + + @GET("/api/v1/feed/tag/{tag}/") + suspend fun fetchPosts( + @Path("tag") tag: String?, + @QueryMap queryParams: Map? + ): TagFeedResponse? +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/repositories/LocationRepository.java b/app/src/main/java/awais/instagrabber/repositories/LocationRepository.java deleted file mode 100644 index 69e7302e..00000000 --- a/app/src/main/java/awais/instagrabber/repositories/LocationRepository.java +++ /dev/null @@ -1,19 +0,0 @@ -package awais.instagrabber.repositories; - -import java.util.Map; - -import awais.instagrabber.repositories.responses.LocationFeedResponse; -import awais.instagrabber.repositories.responses.Place; -import retrofit2.Call; -import retrofit2.http.GET; -import retrofit2.http.Path; -import retrofit2.http.QueryMap; - -public interface LocationRepository { - @GET("/api/v1/locations/{location}/info/") - Call fetch(@Path("location") final long locationId); - - @GET("/api/v1/feed/location/{location}/") - Call fetchPosts(@Path("location") final long locationId, - @QueryMap Map queryParams); -} diff --git a/app/src/main/java/awais/instagrabber/repositories/LocationService.kt b/app/src/main/java/awais/instagrabber/repositories/LocationService.kt new file mode 100644 index 00000000..3987b56e --- /dev/null +++ b/app/src/main/java/awais/instagrabber/repositories/LocationService.kt @@ -0,0 +1,19 @@ +package awais.instagrabber.repositories + +import retrofit2.http.GET +import awais.instagrabber.repositories.responses.Place +import awais.instagrabber.repositories.responses.LocationFeedResponse +import retrofit2.Call +import retrofit2.http.Path +import retrofit2.http.QueryMap + +interface LocationService { + @GET("/api/v1/locations/{location}/info/") + suspend fun fetch(@Path("location") locationId: Long): Place? + + @GET("/api/v1/feed/location/{location}/") + suspend fun fetchPosts( + @Path("location") locationId: Long, + @QueryMap queryParams: Map? + ): LocationFeedResponse? +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/repositories/TagsRepository.java b/app/src/main/java/awais/instagrabber/repositories/TagsRepository.java deleted file mode 100644 index a70ed369..00000000 --- a/app/src/main/java/awais/instagrabber/repositories/TagsRepository.java +++ /dev/null @@ -1,29 +0,0 @@ -package awais.instagrabber.repositories; - -import java.util.Map; - -import awais.instagrabber.repositories.responses.Hashtag; -import awais.instagrabber.repositories.responses.TagFeedResponse; -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; -import retrofit2.http.QueryMap; - -public interface TagsRepository { - @GET("/api/v1/tags/{tag}/info/") - Call fetch(@Path("tag") final String tag); - - @FormUrlEncoded - @POST("/api/v1/tags/{action}/{tag}/") - Call changeFollow(@FieldMap final Map signedForm, - @Path("action") String action, - @Path("tag") String tag); - - @GET("/api/v1/feed/tag/{tag}/") - Call fetchPosts(@Path("tag") final String tag, - @QueryMap Map queryParams); -} diff --git a/app/src/main/java/awais/instagrabber/repositories/responses/Hashtag.kt b/app/src/main/java/awais/instagrabber/repositories/responses/Hashtag.kt index 9d8fef08..a87b848d 100755 --- a/app/src/main/java/awais/instagrabber/repositories/responses/Hashtag.kt +++ b/app/src/main/java/awais/instagrabber/repositories/responses/Hashtag.kt @@ -1,12 +1,14 @@ package awais.instagrabber.repositories.responses -import awais.instagrabber.models.enums.FollowingType import java.io.Serializable data class Hashtag( val id: String, val name: String, val mediaCount: Long, - val following: FollowingType?, // 0 false 1 true; not on search results + val following: Int?, // 0 false 1 true; not on search results val searchResultSubtitle: String? // shows how many posts there are on search results -) : Serializable \ No newline at end of file +) : Serializable { + val follow: Boolean + get() = following == 1 +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/repositories/responses/LocationFeedResponse.kt b/app/src/main/java/awais/instagrabber/repositories/responses/LocationFeedResponse.kt index e1e9ce1d..2c2b2007 100644 --- a/app/src/main/java/awais/instagrabber/repositories/responses/LocationFeedResponse.kt +++ b/app/src/main/java/awais/instagrabber/repositories/responses/LocationFeedResponse.kt @@ -3,9 +3,9 @@ package awais.instagrabber.repositories.responses data class LocationFeedResponse( val numResults: Int, val nextMaxId: String?, - val moreAvailable: Boolean?, + val moreAvailable: Boolean, val mediaCount: Long?, val status: String, - val items: List?, + val items: List, val location: Location ) \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/webservices/GraphQLRepository.kt b/app/src/main/java/awais/instagrabber/webservices/GraphQLRepository.kt index e54b6ec2..509477ae 100644 --- a/app/src/main/java/awais/instagrabber/webservices/GraphQLRepository.kt +++ b/app/src/main/java/awais/instagrabber/webservices/GraphQLRepository.kt @@ -262,7 +262,7 @@ open class GraphQLRepository(private val service: GraphQLService) { body.getString(Constants.EXTRAS_ID), body.getString("name"), timelineMedia.getLong("count"), - if (body.optBoolean("is_following")) FollowingType.FOLLOWING else FollowingType.NOT_FOLLOWING, + if (body.optBoolean("is_following")) 1 else 0, null ) } diff --git a/app/src/main/java/awais/instagrabber/webservices/HashtagRepository.kt b/app/src/main/java/awais/instagrabber/webservices/HashtagRepository.kt new file mode 100644 index 00000000..fef2d116 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/webservices/HashtagRepository.kt @@ -0,0 +1,64 @@ +package awais.instagrabber.webservices + +import android.util.Log +import awais.instagrabber.repositories.HashtagService +import awais.instagrabber.repositories.responses.Hashtag +import awais.instagrabber.repositories.responses.PostsFetchResponse +import awais.instagrabber.repositories.responses.TagFeedResponse +import awais.instagrabber.utils.TextUtils.isEmpty +import awais.instagrabber.utils.Utils +import awais.instagrabber.webservices.RetrofitFactory.retrofit +import com.google.common.collect.ImmutableMap +import org.json.JSONException +import org.json.JSONObject +import retrofit2.Call +import retrofit2.Callback +import java.util.* + +open class HashtagRepository(private val repository: HashtagService) { + suspend fun fetch(tag: String): Hashtag? { + return repository.fetch(tag) + } + + suspend fun changeFollow( + action: String, + tag: String, + csrfToken: String, + userId: Long, + deviceUuid: String + ): Boolean { + val form: MutableMap = HashMap(3) + form["_csrftoken"] = csrfToken + form["_uid"] = userId + form["_uuid"] = deviceUuid + val signedForm = Utils.sign(form) + val body = repository.changeFollow(signedForm, action, tag) ?: return false + val jsonObject = JSONObject(body) + return jsonObject.optString("status") == "ok" + } + + suspend fun fetchPosts(tag: String, maxId: String?): PostsFetchResponse? { + val builder = ImmutableMap.builder() + if (!isEmpty(maxId)) { + builder.put("max_id", maxId) + } + val body = repository.fetchPosts(tag, builder.build()) ?: return null + return PostsFetchResponse( + body.items, + body.moreAvailable, + body.nextMaxId + ) + } + + companion object { + @Volatile + private var INSTANCE: HashtagRepository? = null + + fun getInstance(): HashtagRepository { + return INSTANCE ?: synchronized(this) { + val service = RetrofitFactory.retrofit.create(HashtagService::class.java) + HashtagRepository(service).also { INSTANCE = it } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/webservices/LocationRepository.kt b/app/src/main/java/awais/instagrabber/webservices/LocationRepository.kt new file mode 100644 index 00000000..12198e30 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/webservices/LocationRepository.kt @@ -0,0 +1,46 @@ +package awais.instagrabber.webservices + +import awais.instagrabber.repositories.HashtagService +import awais.instagrabber.repositories.responses.Location +import awais.instagrabber.repositories.responses.LocationFeedResponse +import awais.instagrabber.repositories.responses.Place +import awais.instagrabber.repositories.responses.PostsFetchResponse +import awais.instagrabber.utils.TextUtils.isEmpty +import awais.instagrabber.repositories.LocationService +import awais.instagrabber.webservices.RetrofitFactory.retrofit +import com.google.common.collect.ImmutableMap +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +open class LocationRepository(private val repository: LocationService) { + suspend fun fetchPosts(locationId: Long, maxId: String): PostsFetchResponse? { + val builder = ImmutableMap.builder() + if (!isEmpty(maxId)) { + builder.put("max_id", maxId) + } + val body = repository.fetchPosts(locationId, builder.build()) ?: return null + return PostsFetchResponse( + body.items, + body.moreAvailable, + body.nextMaxId + ) + } + + suspend fun fetch(locationId: Long): Location? { + val place = repository.fetch(locationId) ?: return null + return place.location + } + + companion object { + @Volatile + private var INSTANCE: LocationRepository? = null + + fun getInstance(): LocationRepository { + return INSTANCE ?: synchronized(this) { + val service = RetrofitFactory.retrofit.create(LocationService::class.java) + LocationRepository(service).also { INSTANCE = it } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/webservices/LocationService.java b/app/src/main/java/awais/instagrabber/webservices/LocationService.java deleted file mode 100644 index 3ed70b93..00000000 --- a/app/src/main/java/awais/instagrabber/webservices/LocationService.java +++ /dev/null @@ -1,92 +0,0 @@ -package awais.instagrabber.webservices; - -import androidx.annotation.NonNull; - -import com.google.common.collect.ImmutableMap; - -import awais.instagrabber.repositories.LocationRepository; -import awais.instagrabber.repositories.responses.Location; -import awais.instagrabber.repositories.responses.LocationFeedResponse; -import awais.instagrabber.repositories.responses.Place; -import awais.instagrabber.repositories.responses.PostsFetchResponse; -import awais.instagrabber.utils.TextUtils; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; - -public class LocationService { - private static final String TAG = "LocationService"; - - private final LocationRepository repository; - - private static LocationService instance; - - private LocationService() { - repository = RetrofitFactory.INSTANCE - .getRetrofit() - .create(LocationRepository.class); - } - - public static LocationService getInstance() { - if (instance == null) { - instance = new LocationService(); - } - return instance; - } - - public void fetchPosts(final long locationId, - final String maxId, - final ServiceCallback callback) { - final ImmutableMap.Builder builder = ImmutableMap.builder(); - if (!TextUtils.isEmpty(maxId)) { - builder.put("max_id", maxId); - } - final Call request = repository.fetchPosts(locationId, builder.build()); - request.enqueue(new Callback() { - @Override - public void onResponse(@NonNull final Call call, @NonNull final Response response) { - if (callback == null) return; - final LocationFeedResponse body = response.body(); - if (body == null) { - callback.onSuccess(null); - return; - } - final PostsFetchResponse postsFetchResponse = new PostsFetchResponse( - body.getItems(), - body.getMoreAvailable(), - body.getNextMaxId() - ); - callback.onSuccess(postsFetchResponse); - - } - - @Override - public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { - if (callback != null) { - callback.onFailure(t); - } - } - }); - } - - public void fetch(@NonNull final long locationId, - final ServiceCallback callback) { - final Call request = repository.fetch(locationId); - request.enqueue(new Callback() { - @Override - public void onResponse(@NonNull final Call call, @NonNull final Response response) { - if (callback == null) { - return; - } - callback.onSuccess(response.body() == null ? null : response.body().getLocation()); - } - - @Override - public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { - if (callback != null) { - callback.onFailure(t); - } - } - }); - } -} diff --git a/app/src/main/java/awais/instagrabber/webservices/TagsService.java b/app/src/main/java/awais/instagrabber/webservices/TagsService.java deleted file mode 100644 index f207dcad..00000000 --- a/app/src/main/java/awais/instagrabber/webservices/TagsService.java +++ /dev/null @@ -1,138 +0,0 @@ -package awais.instagrabber.webservices; - -import android.util.Log; - -import androidx.annotation.NonNull; - -import com.google.common.collect.ImmutableMap; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.HashMap; -import java.util.Map; - -import awais.instagrabber.repositories.TagsRepository; -import awais.instagrabber.repositories.responses.Hashtag; -import awais.instagrabber.repositories.responses.PostsFetchResponse; -import awais.instagrabber.repositories.responses.TagFeedResponse; -import awais.instagrabber.utils.TextUtils; -import awais.instagrabber.utils.Utils; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; - -public class TagsService { - - private static final String TAG = "TagsService"; - - private static TagsService instance; - - private final TagsRepository repository; - - private TagsService() { - repository = RetrofitFactory.INSTANCE - .getRetrofit() - .create(TagsRepository.class); - } - - public static TagsService getInstance() { - if (instance == null) { - instance = new TagsService(); - } - return instance; - } - - public void fetch(@NonNull final String tag, - final ServiceCallback callback) { - final Call request = repository.fetch(tag); - request.enqueue(new Callback() { - @Override - public void onResponse(@NonNull final Call call, @NonNull final Response response) { - if (callback == null) { - return; - } - callback.onSuccess(response.body()); - } - - @Override - public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { - if (callback != null) { - callback.onFailure(t); - } - } - }); - } - - public void changeFollow(@NonNull final String action, - @NonNull final String tag, - @NonNull final String csrfToken, - @NonNull final long userId, - @NonNull final String deviceUuid, - final ServiceCallback callback) { - final Map form = new HashMap<>(3); - form.put("_csrftoken", csrfToken); - form.put("_uid", userId); - form.put("_uuid", deviceUuid); - final Map signedForm = Utils.sign(form); - final Call request = repository.changeFollow(signedForm, action, tag); - request.enqueue(new Callback() { - @Override - public void onResponse(@NonNull final Call call, @NonNull final Response response) { - final String body = response.body(); - if (body == null) { - callback.onFailure(new RuntimeException("body is null")); - return; - } - try { - final JSONObject jsonObject = new JSONObject(body); - final String status = jsonObject.optString("status"); - callback.onSuccess(status.equals("ok")); - } catch (JSONException e) { - Log.e(TAG, "onResponse: ", e); - } - } - - @Override - public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { - // Log.e(TAG, "onFailure: ", t); - callback.onFailure(t); - } - }); - } - - public void fetchPosts(@NonNull final String tag, - final String maxId, - final ServiceCallback callback) { - final ImmutableMap.Builder builder = ImmutableMap.builder(); - if (!TextUtils.isEmpty(maxId)) { - builder.put("max_id", maxId); - } - final Call request = repository.fetchPosts(tag, builder.build()); - request.enqueue(new Callback() { - @Override - public void onResponse(@NonNull final Call call, @NonNull final Response response) { - if (callback == null) { - return; - } - final TagFeedResponse body = response.body(); - if (body == null) { - callback.onSuccess(null); - return; - } - callback.onSuccess(new PostsFetchResponse( - body.getItems(), - body.getMoreAvailable(), - body.getNextMaxId() - )); - } - - @Override - public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { - if (callback != null) { - callback.onFailure(t); - } - } - }); - } -}