diff --git a/app/src/main/java/app/fedilab/android/activities/ActionActivity.java b/app/src/main/java/app/fedilab/android/activities/ActionActivity.java index 2320778b8..18c5e7df1 100644 --- a/app/src/main/java/app/fedilab/android/activities/ActionActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/ActionActivity.java @@ -60,6 +60,7 @@ public class ActionActivity extends BaseActivity { fragmentMastodonAccount = new FragmentMastodonAccount(); Bundle bundle = new Bundle(); bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, type); + bundle.putString(Helper.ARG_VIEW_MODEL_KEY, "FEDILAB_" + type.getValue()); fragmentMastodonAccount.setArguments(bundle); FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction fragmentTransaction = @@ -74,6 +75,7 @@ public class ActionActivity extends BaseActivity { fragmentMastodonTimeline = new FragmentMastodonTimeline(); Bundle bundle = new Bundle(); bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, type); + bundle.putString(Helper.ARG_VIEW_MODEL_KEY, "FEDILAB_" + type.getValue()); fragmentMastodonTimeline.setArguments(bundle); FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction fragmentTransaction = diff --git a/app/src/main/java/app/fedilab/android/activities/StatusInfoActivity.java b/app/src/main/java/app/fedilab/android/activities/StatusInfoActivity.java index 21c335cb1..77c9d813e 100644 --- a/app/src/main/java/app/fedilab/android/activities/StatusInfoActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/StatusInfoActivity.java @@ -119,7 +119,7 @@ public class StatusInfoActivity extends BaseActivity { startId = accountList.size(); } accountList.addAll(accounts.accounts); - max_id = accounts.pagination.min_id; + max_id = accounts.pagination.max_id; accountAdapter.notifyItemRangeInserted(startId, accounts.accounts.size()); } } diff --git a/app/src/main/java/app/fedilab/android/client/mastodon/MastodonSearchService.java b/app/src/main/java/app/fedilab/android/client/mastodon/MastodonSearchService.java index a8a7f1440..58531fd75 100644 --- a/app/src/main/java/app/fedilab/android/client/mastodon/MastodonSearchService.java +++ b/app/src/main/java/app/fedilab/android/client/mastodon/MastodonSearchService.java @@ -29,12 +29,12 @@ public interface MastodonSearchService { @Query("q") String q, @Query("account_id") String account_id, @Query("type") String type, - @Query("exclude_unreviewed") boolean exclude_unreviewed, - @Query("resolve") boolean resolve, - @Query("following") boolean following, - @Query("offset") int offset, + @Query("exclude_unreviewed") Boolean exclude_unreviewed, + @Query("resolve") Boolean resolve, + @Query("following") Boolean following, + @Query("offset") Integer offset, @Query("max_id") String max_id, @Query("min_id") String min_id, - @Query("limit") int limit + @Query("limit") Integer limit ); } diff --git a/app/src/main/java/app/fedilab/android/client/mastodon/MastodonTimelinesService.java b/app/src/main/java/app/fedilab/android/client/mastodon/MastodonTimelinesService.java index 085b2d996..d381a376d 100644 --- a/app/src/main/java/app/fedilab/android/client/mastodon/MastodonTimelinesService.java +++ b/app/src/main/java/app/fedilab/android/client/mastodon/MastodonTimelinesService.java @@ -38,13 +38,13 @@ public interface MastodonTimelinesService { @GET("timelines/public") Call> getPublic( @Header("Authorization") String token, - @Query("local") boolean local, - @Query("remote") boolean remote, - @Query("only_media") boolean only_media, + @Query("local") Boolean local, + @Query("remote") Boolean remote, + @Query("only_media") Boolean only_media, @Query("max_id") String max_id, @Query("since_id") String since_id, @Query("min_id") String min_id, - @Query("limit") int limit + @Query("limit") Integer limit ); //Public Tags timelines diff --git a/app/src/main/java/app/fedilab/android/helper/CrossActionHelper.java b/app/src/main/java/app/fedilab/android/helper/CrossActionHelper.java index 73db56ac8..cb361281b 100644 --- a/app/src/main/java/app/fedilab/android/helper/CrossActionHelper.java +++ b/app/src/main/java/app/fedilab/android/helper/CrossActionHelper.java @@ -15,6 +15,7 @@ package app.fedilab.android.helper; * see . */ import android.content.Context; +import android.content.Intent; import android.content.SharedPreferences; import android.os.Handler; import android.os.Looper; @@ -31,6 +32,7 @@ import java.util.List; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; +import app.fedilab.android.activities.ComposeActivity; import app.fedilab.android.client.entities.Account; import app.fedilab.android.client.mastodon.entities.Status; import app.fedilab.android.exception.DBException; @@ -224,6 +226,12 @@ public class CrossActionHelper { statusesVM.unReblog(ownerAccount.instance, ownerAccount.token, targetedStatus.id) .observe((LifecycleOwner) context, status -> Toasty.info(context, context.getString(R.string.toast_unreblog), Toasty.LENGTH_SHORT).show()); break; + case REPLY_ACTION: + Intent intent = new Intent(context, ComposeActivity.class); + intent.putExtra(Helper.ARG_STATUS_REPLY, targetedStatus); + intent.putExtra(Helper.ARG_ACCOUNT, ownerAccount); + context.startActivity(intent); + break; } } @@ -239,6 +247,7 @@ public class CrossActionHelper { BOOKMARK_ACTION, UNBOOKMARK_ACTION, REBLOG_ACTION, - UNREBLOG_ACTION + UNREBLOG_ACTION, + REPLY_ACTION } } diff --git a/app/src/main/java/app/fedilab/android/helper/MastodonHelper.java b/app/src/main/java/app/fedilab/android/helper/MastodonHelper.java index 546a485a3..bddb62e9a 100644 --- a/app/src/main/java/app/fedilab/android/helper/MastodonHelper.java +++ b/app/src/main/java/app/fedilab/android/helper/MastodonHelper.java @@ -42,20 +42,17 @@ import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; -import java.util.List; import java.util.Locale; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; +import java.util.regex.Pattern; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; import app.fedilab.android.client.entities.ScheduledBoost; import app.fedilab.android.client.mastodon.entities.Account; -import app.fedilab.android.client.mastodon.entities.Conversation; -import app.fedilab.android.client.mastodon.entities.Notification; import app.fedilab.android.client.mastodon.entities.Pagination; import app.fedilab.android.client.mastodon.entities.RelationShip; -import app.fedilab.android.client.mastodon.entities.ScheduledStatus; import app.fedilab.android.client.mastodon.entities.Status; import app.fedilab.android.databinding.DatetimePickerBinding; import app.fedilab.android.exception.DBException; @@ -63,6 +60,7 @@ import app.fedilab.android.jobs.ScheduleBoostWorker; import app.fedilab.android.ui.drawer.ComposeAdapter; import app.fedilab.android.viewmodel.mastodon.AccountsVM; import es.dmoral.toasty.Toasty; +import okhttp3.Headers; public class MastodonHelper { @@ -114,13 +112,13 @@ public class MastodonHelper { return "https://" + instance + "/oauth/authorize" + "?" + queryString; } - /* /** + /** * Retrieve pagination from header * * @param headers Headers * @return Pagination */ - /* public static Pagination getPagination(Headers headers) { + public static Pagination getPagination(Headers headers) { String link = headers.get("Link"); Pagination pagination = new Pagination(); if (link != null) { @@ -141,9 +139,9 @@ public class MastodonHelper { } } return pagination; - }*/ + } - public static Pagination getPaginationNotification(List notificationList) { + /*public static Pagination getPaginationNotification(List notificationList) { Pagination pagination = new Pagination(); if (notificationList == null || notificationList.size() == 0) { return pagination; @@ -192,7 +190,7 @@ public class MastodonHelper { pagination.min_id = conversationList.get(conversationList.size() - 1).id; return pagination; } - +*/ public static void loadPPMastodon(ImageView view, app.fedilab.android.client.mastodon.entities.Account account) { loadProfileMediaMastodon(view, account, MediaAccountType.AVATAR); } diff --git a/app/src/main/java/app/fedilab/android/helper/NotificationsHelper.java b/app/src/main/java/app/fedilab/android/helper/NotificationsHelper.java index 1876bc7cf..e55aaf4c1 100644 --- a/app/src/main/java/app/fedilab/android/helper/NotificationsHelper.java +++ b/app/src/main/java/app/fedilab/android/helper/NotificationsHelper.java @@ -114,7 +114,7 @@ public class NotificationsHelper { } } } - notifications.pagination = MastodonHelper.getPaginationNotification(notifications.notifications); + notifications.pagination = MastodonHelper.getPagination(notificationsResponse.headers()); } } catch (IOException e) { e.printStackTrace(); diff --git a/app/src/main/java/app/fedilab/android/helper/TimelineHelper.java b/app/src/main/java/app/fedilab/android/helper/TimelineHelper.java index a47a6e90d..edc3ebd6d 100644 --- a/app/src/main/java/app/fedilab/android/helper/TimelineHelper.java +++ b/app/src/main/java/app/fedilab/android/helper/TimelineHelper.java @@ -49,11 +49,16 @@ public class TimelineHelper { //A security to make sure filters have been fetched before displaying messages List statusesToRemove = new ArrayList<>(); if (!BaseMainActivity.filterFetched) { - AccountsVM accountsVM = new ViewModelProvider((ViewModelStoreOwner) context).get(AccountsVM.class); - accountsVM.getFilters(BaseMainActivity.currentInstance, BaseMainActivity.currentToken).observe((LifecycleOwner) context, filters -> { - BaseMainActivity.filterFetched = true; - BaseMainActivity.mainFilters = filters; - }); + try { + AccountsVM accountsVM = new ViewModelProvider((ViewModelStoreOwner) context).get(AccountsVM.class); + accountsVM.getFilters(BaseMainActivity.currentInstance, BaseMainActivity.currentToken).observe((LifecycleOwner) context, filters -> { + BaseMainActivity.filterFetched = true; + BaseMainActivity.mainFilters = filters; + }); + } catch (ClassCastException e) { + e.printStackTrace(); + return statuses; + } } //If there are filters: if (BaseMainActivity.mainFilters != null && BaseMainActivity.mainFilters.size() > 0) { diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/NotificationAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/NotificationAdapter.java index 4663a19c3..1389dd8b2 100644 --- a/app/src/main/java/app/fedilab/android/ui/drawer/NotificationAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/drawer/NotificationAdapter.java @@ -174,6 +174,16 @@ public class NotificationAdapter extends RecyclerView.Adapter { + Intent intent = new Intent(context, ProfileActivity.class); + Bundle b = new Bundle(); + b.putSerializable(Helper.ARG_ACCOUNT, notification.account); + intent.putExtras(b); + ActivityOptionsCompat options = ActivityOptionsCompat + .makeSceneTransitionAnimation((Activity) context, holderStatus.bindingNotification.status.avatar, context.getString(R.string.activity_porfile_pp)); + // start the new activity + context.startActivity(intent, options.toBundle()); + }); holderStatus.bindingNotification.status.displayName.setText(title); holderStatus.bindingNotification.status.username.setText(String.format("@%s", notification.account.acct)); holderStatus.bindingNotification.status.actionButtons.setVisibility(View.GONE); diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java index 88611ce58..9941b96b9 100644 --- a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java @@ -236,7 +236,7 @@ public class StatusAdapter extends RecyclerView.Adapter while (matcherAcct.find()) { int matchStart = matcherAcct.start(1); int matchEnd = matcherAcct.end(); - if (wordToSpan.length() >= matchEnd && matchStart < matchEnd) { + if (wordToSpan.length() >= matchEnd && matchStart < matchEnd && matchStart >= 0) { wordToSpan.setSpan(new ForegroundColorSpan(theme_text_header_2_line), matchStart, matchEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); } } @@ -330,6 +330,7 @@ public class StatusAdapter extends RecyclerView.Adapter }); holder.binding.actionButtonBookmark.setOnClickListener(v -> { if (remote) { + Toasty.info(context, context.getString(R.string.retrieve_remote_status), Toasty.LENGTH_SHORT).show(); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.url, null, "statuses", false, true, false, 0, null, null, 1) .observe((LifecycleOwner) context, results -> { if (results.statuses != null && results.statuses.size() > 0) { @@ -366,10 +367,11 @@ public class StatusAdapter extends RecyclerView.Adapter holder.binding.actionButtonFavorite.setChecked(statusToDeal.favourited); holder.binding.statusUserInfo.setOnClickListener(v -> { if (remote) { + Toasty.info(context, context.getString(R.string.retrieve_remote_status), Toasty.LENGTH_SHORT).show(); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.url, null, "statuses", false, true, false, 0, null, null, 1) .observe((LifecycleOwner) context, results -> { if (results.statuses != null && results.statuses.size() > 0) { - Status fetchedStatus = statusList.get(0); + Status fetchedStatus = results.statuses.get(0); Intent intent = new Intent(context, ProfileActivity.class); Bundle b = new Bundle(); b.putSerializable(Helper.ARG_ACCOUNT, fetchedStatus.reblog != null ? fetchedStatus.reblog.account : fetchedStatus.account); @@ -395,10 +397,11 @@ public class StatusAdapter extends RecyclerView.Adapter }); holder.binding.statusBoosterAvatar.setOnClickListener(v -> { if (remote) { + Toasty.info(context, context.getString(R.string.retrieve_remote_status), Toasty.LENGTH_SHORT).show(); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.url, null, "statuses", false, true, false, 0, null, null, 1) .observe((LifecycleOwner) context, results -> { if (results.statuses != null && results.statuses.size() > 0) { - Status fetchedStatus = statusList.get(0); + Status fetchedStatus = results.statuses.get(0); Intent intent = new Intent(context, ProfileActivity.class); Bundle b = new Bundle(); b.putSerializable(Helper.ARG_ACCOUNT, fetchedStatus.account); @@ -440,10 +443,11 @@ public class StatusAdapter extends RecyclerView.Adapter } alt_bld.setPositiveButton(R.string.yes, (dialog, id) -> { if (remote) { + Toasty.info(context, context.getString(R.string.retrieve_remote_status), Toasty.LENGTH_SHORT).show(); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.url, null, "statuses", false, true, false, 0, null, null, 1) .observe((LifecycleOwner) context, results -> { if (results.statuses != null && results.statuses.size() > 0) { - Status fetchedStatus = statusList.get(0); + Status fetchedStatus = results.statuses.get(0); statusesVM.reblog(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, fetchedStatus.id, null) .observe((LifecycleOwner) context, _status -> { statusToDeal.reblogged = _status.reblogged; @@ -482,10 +486,11 @@ public class StatusAdapter extends RecyclerView.Adapter alert.show(); } else { if (remote) { + Toasty.info(context, context.getString(R.string.retrieve_remote_status), Toasty.LENGTH_SHORT).show(); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.url, null, "statuses", false, true, false, 0, null, null, 1) .observe((LifecycleOwner) context, results -> { if (results.statuses != null && results.statuses.size() > 0) { - Status fetchedStatus = statusList.get(0); + Status fetchedStatus = results.statuses.get(0); statusesVM.reblog(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, fetchedStatus.id, null) .observe((LifecycleOwner) context, _status -> { statusToDeal.reblogged = _status.reblogged; @@ -538,10 +543,11 @@ public class StatusAdapter extends RecyclerView.Adapter } alt_bld.setPositiveButton(R.string.yes, (dialog, id) -> { if (remote) { + Toasty.info(context, context.getString(R.string.retrieve_remote_status), Toasty.LENGTH_SHORT).show(); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.url, null, "statuses", false, true, false, 0, null, null, 1) .observe((LifecycleOwner) context, results -> { if (results.statuses != null && results.statuses.size() > 0) { - Status fetchedStatus = statusList.get(0); + Status fetchedStatus = results.statuses.get(0); statusesVM.favourite(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, fetchedStatus.id) .observe((LifecycleOwner) context, _status -> { statusToDeal.favourited = _status.favourited; @@ -579,10 +585,11 @@ public class StatusAdapter extends RecyclerView.Adapter alert.show(); } else { if (remote) { + Toasty.info(context, context.getString(R.string.retrieve_remote_status), Toasty.LENGTH_SHORT).show(); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.url, null, "statuses", false, true, false, 0, null, null, 1) .observe((LifecycleOwner) context, results -> { if (results.statuses != null && results.statuses.size() > 0) { - Status fetchedStatus = statusList.get(0); + Status fetchedStatus = results.statuses.get(0); statusesVM.favourite(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, fetchedStatus.id) .observe((LifecycleOwner) context, _status -> { statusToDeal.favourited = _status.favourited; @@ -855,10 +862,11 @@ public class StatusAdapter extends RecyclerView.Adapter holder.binding.reblogInfo.setOnClickListener(v -> { if (remote) { + Toasty.info(context, context.getString(R.string.retrieve_remote_status), Toasty.LENGTH_SHORT).show(); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.url, null, "statuses", false, true, false, 0, null, null, 1) .observe((LifecycleOwner) context, results -> { if (results.statuses != null && results.statuses.size() > 0) { - Status fetchedStatus = statusList.get(0); + Status fetchedStatus = results.statuses.get(0); if (fetchedStatus.reblogs_count > 0) { Intent intent = new Intent(context, StatusInfoActivity.class); intent.putExtra(Helper.ARG_TYPE_OF_INFO, StatusInfoActivity.typeOfInfo.BOOSTED_BY); @@ -881,10 +889,11 @@ public class StatusAdapter extends RecyclerView.Adapter holder.binding.favouriteInfo.setOnClickListener(v -> { if (remote) { + Toasty.info(context, context.getString(R.string.retrieve_remote_status), Toasty.LENGTH_SHORT).show(); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.url, null, "statuses", false, true, false, 0, null, null, 1) .observe((LifecycleOwner) context, results -> { if (results.statuses != null && results.statuses.size() > 0) { - Status fetchedStatus = statusList.get(0); + Status fetchedStatus = results.statuses.get(0); if (fetchedStatus.favourites_count > 0) { Intent intent = new Intent(context, StatusInfoActivity.class); intent.putExtra(Helper.ARG_TYPE_OF_INFO, StatusInfoActivity.typeOfInfo.LIKED_BY); @@ -1004,10 +1013,11 @@ public class StatusAdapter extends RecyclerView.Adapter } //Vote on the poll if (remote) { + Toasty.info(context, context.getString(R.string.retrieve_remote_status), Toasty.LENGTH_SHORT).show(); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.url, null, "statuses", false, true, false, 0, null, null, 1) .observe((LifecycleOwner) context, results -> { if (results.statuses != null && results.statuses.size() > 0) { - Status fetchedStatus = statusList.get(0); + Status fetchedStatus = results.statuses.get(0); statusesVM.votePoll(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, fetchedStatus.poll.id, choice) .observe((LifecycleOwner) context, poll -> { int i = 0; @@ -1084,10 +1094,11 @@ public class StatusAdapter extends RecyclerView.Adapter ((ContextActivity) context).setCurrentFragment((FragmentMastodonContext) fragment); } else { if (remote) { + Toasty.info(context, context.getString(R.string.retrieve_remote_status), Toasty.LENGTH_SHORT).show(); searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.url, null, "statuses", false, true, false, 0, null, null, 1) .observe((LifecycleOwner) context, results -> { if (results.statuses != null && results.statuses.size() > 0) { - Status fetchedStatus = statusList.get(0); + Status fetchedStatus = results.statuses.get(0); Intent intent = new Intent(context, ContextActivity.class); intent.putExtra(Helper.ARG_STATUS, fetchedStatus); context.startActivity(intent); @@ -1354,10 +1365,29 @@ public class StatusAdapter extends RecyclerView.Adapter }); popup.show(); }); + holder.binding.actionButtonReply.setOnLongClickListener(v -> { + CrossActionHelper.doCrossAction(context, CrossActionHelper.TypeOfCrossAction.REPLY_ACTION, null, statusToDeal); + return true; + }); holder.binding.actionButtonReply.setOnClickListener(v -> { - Intent intent = new Intent(context, ComposeActivity.class); - intent.putExtra(Helper.ARG_STATUS_REPLY, statusToDeal); - context.startActivity(intent); + if (remote) { + Toasty.info(context, context.getString(R.string.retrieve_remote_status), Toasty.LENGTH_SHORT).show(); + searchVM.search(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, statusToDeal.url, null, "statuses", false, true, false, 0, null, null, 1) + .observe((LifecycleOwner) context, results -> { + if (results.statuses != null && results.statuses.size() > 0) { + Status fetchedStatus = statusList.get(0); + Intent intent = new Intent(context, ComposeActivity.class); + intent.putExtra(Helper.ARG_STATUS_REPLY, fetchedStatus); + context.startActivity(intent); + } else { + Toasty.info(context, context.getString(R.string.toast_error_search), Toasty.LENGTH_SHORT).show(); + } + }); + } else { + Intent intent = new Intent(context, ComposeActivity.class); + intent.putExtra(Helper.ARG_STATUS_REPLY, statusToDeal); + context.startActivity(intent); + } }); //For reports diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java index d3977b9f7..ffdf5e534 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java @@ -202,7 +202,7 @@ public class FragmentMastodonAccount extends Fragment { binding.recyclerView.setAdapter(accountAdapter); //Fetch the relationship fetchRelationShip(accounts.accounts, 0); - max_id = accounts.pagination.min_id; + max_id = accounts.pagination.max_id; binding.recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { @@ -253,7 +253,7 @@ public class FragmentMastodonAccount extends Fragment { accounts.addAll(fetched_accounts.accounts); //Fetch the relationship fetchRelationShip(fetched_accounts.accounts, position); - max_id = fetched_accounts.pagination.min_id; + max_id = fetched_accounts.pagination.max_id; accountAdapter.notifyItemRangeInserted(startId, fetched_accounts.accounts.size()); } } diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonConversation.java b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonConversation.java index 870ada87e..4235fda67 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonConversation.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonConversation.java @@ -99,7 +99,7 @@ public class FragmentMastodonConversation extends Fragment { LinearLayoutManager mLayoutManager = new LinearLayoutManager(requireActivity()); binding.recyclerView.setLayoutManager(mLayoutManager); binding.recyclerView.setAdapter(conversationAdapter); - max_id = conversations.pagination.min_id; + max_id = conversations.pagination.max_id; binding.recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { @@ -122,7 +122,7 @@ public class FragmentMastodonConversation extends Fragment { startId = currentFragment.conversations.size(); } currentFragment.conversations.addAll(fetched_conversations.conversations); - max_id = fetched_conversations.pagination.min_id; + max_id = fetched_conversations.pagination.max_id; conversationAdapter.notifyItemRangeInserted(startId, fetched_conversations.conversations.size()); } }); diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonNotification.java b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonNotification.java index 68d60e8bd..63ed92930 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonNotification.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonNotification.java @@ -144,7 +144,7 @@ public class FragmentMastodonNotification extends Fragment { LinearLayoutManager mLayoutManager = new LinearLayoutManager(requireActivity()); binding.recyclerView.setLayoutManager(mLayoutManager); binding.recyclerView.setAdapter(notificationAdapter); - max_id = notifications.pagination.min_id; + max_id = notifications.pagination.max_id; binding.recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { @@ -196,7 +196,7 @@ public class FragmentMastodonNotification extends Fragment { startId = currentFragment.notifications.size(); } currentFragment.notifications.addAll(fetched_notifications.notifications); - max_id = fetched_notifications.pagination.min_id; + max_id = fetched_notifications.pagination.max_id; notificationAdapter.notifyItemRangeInserted(startId, fetched_notifications.notifications.size()); } } diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTimeline.java b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTimeline.java index 074cbb825..162cb8b4a 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTimeline.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonTimeline.java @@ -196,7 +196,6 @@ public class FragmentMastodonTimeline extends Fragment { timelinesVM = new ViewModelProvider(FragmentMastodonTimeline.this).get(viewModelKey, TimelinesVM.class); accountsVM = new ViewModelProvider(FragmentMastodonTimeline.this).get(viewModelKey, AccountsVM.class); - binding.loader.setVisibility(View.VISIBLE); binding.recyclerView.setVisibility(View.GONE); //Markers for home and notifications to get last read ones @@ -244,9 +243,8 @@ public class FragmentMastodonTimeline extends Fragment { } this.statuses.addAll(statuses.statuses); - max_id = this.statuses.get(this.statuses.size() - 1).id; - min_id = this.statuses.get(0).id; - + max_id = statuses.pagination.max_id; + min_id = statuses.pagination.min_id; statusAdapter = new StatusAdapter(this.statuses, timelineType == Timeline.TimeLineEnum.REMOTE, minified); if (statusReport != null) { @@ -317,8 +315,8 @@ public class FragmentMastodonTimeline extends Fragment { statuses.addAll(fetched_statuses.statuses); statusAdapter.notifyItemRangeInserted(startId, fetched_statuses.statuses.size()); } - max_id = statuses.get(statuses.size() - 1).id; - min_id = statuses.get(0).id; + max_id = fetched_statuses.pagination.max_id; + min_id = fetched_statuses.pagination.min_id; } } @@ -403,13 +401,13 @@ public class FragmentMastodonTimeline extends Fragment { } } else if (timelineType == Timeline.TimeLineEnum.REMOTE) { //REMOTE TIMELINE if (direction == null) { - timelinesVM.getPublic(null, remoteInstance, false, true, false, null, null, null, MastodonHelper.statusesPerCall(requireActivity())) + timelinesVM.getPublic(null, remoteInstance, true, false, false, null, null, null, MastodonHelper.statusesPerCall(requireActivity())) .observe(getViewLifecycleOwner(), this::initializeStatusesCommonView); } else if (direction == DIRECTION.BOTTOM) { - timelinesVM.getPublic(null, remoteInstance, false, true, false, max_id, null, null, MastodonHelper.statusesPerCall(requireActivity())) + timelinesVM.getPublic(null, remoteInstance, true, false, false, max_id, null, null, MastodonHelper.statusesPerCall(requireActivity())) .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM)); } else if (direction == DIRECTION.TOP) { - timelinesVM.getPublic(null, remoteInstance, false, true, false, null, null, min_id, MastodonHelper.statusesPerCall(requireActivity())) + timelinesVM.getPublic(null, remoteInstance, true, false, false, null, null, min_id, MastodonHelper.statusesPerCall(requireActivity())) .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.TOP)); } } else if (timelineType == Timeline.TimeLineEnum.LIST) { //LIST TIMELINE @@ -445,8 +443,10 @@ public class FragmentMastodonTimeline extends Fragment { accountsVM.getAccountStatuses(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, accountTimeline.id, null, null, null, null, null, false, true, MastodonHelper.statusesPerCall(requireActivity())) .observe(getViewLifecycleOwner(), pinnedStatuses -> accountsVM.getAccountStatuses(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, accountTimeline.id, null, null, null, exclude_replies, exclude_reblogs, media_only, false, MastodonHelper.statusesPerCall(requireActivity())) .observe(getViewLifecycleOwner(), otherStatuses -> { - otherStatuses.statuses.addAll(0, pinnedStatuses.statuses); - initializeStatusesCommonView(otherStatuses); + if (otherStatuses != null && otherStatuses.statuses != null) { + otherStatuses.statuses.addAll(0, pinnedStatuses.statuses); + initializeStatusesCommonView(otherStatuses); + } })); } else { accountsVM.getAccountStatuses(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, accountTimeline.id, null, null, null, exclude_replies, exclude_reblogs, media_only, false, MastodonHelper.statusesPerCall(requireActivity())) @@ -483,20 +483,18 @@ public class FragmentMastodonTimeline extends Fragment { } else if (direction == DIRECTION.BOTTOM) { accountsVM.getFavourites(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.statusesPerCall(requireActivity())), null, max_id) .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM)); - } else if (direction == DIRECTION.TOP) { - accountsVM.getFavourites(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.statusesPerCall(requireActivity())), min_id, null) - .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.TOP)); + } else { + flagLoading = false; } } else if (timelineType == Timeline.TimeLineEnum.BOOKMARK_TIMELINE) { if (direction == null) { accountsVM.getBookmarks(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.statusesPerCall(requireActivity())), null, null, null) .observe(getViewLifecycleOwner(), this::initializeStatusesCommonView); } else if (direction == DIRECTION.BOTTOM) { - accountsVM.getBookmarks(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.statusesPerCall(requireActivity())), null, max_id, null) + accountsVM.getBookmarks(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.statusesPerCall(requireActivity())), max_id, null, null) .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM)); - } else if (direction == DIRECTION.TOP) { - accountsVM.getBookmarks(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.statusesPerCall(requireActivity())), min_id, null, null) - .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.TOP)); + } else { + flagLoading = false; } } } diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java index 8b8236d84..5dd49ea65 100644 --- a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java +++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java @@ -339,7 +339,7 @@ public class AccountsVM extends AndroidViewModel { Response> accountStatusesResponse = accountStatusesCall.execute(); if (accountStatusesResponse.isSuccessful()) { statusList = SpannableHelper.convertStatus(getApplication().getApplicationContext(), accountStatusesResponse.body()); - pagination = MastodonHelper.getPaginationStatus(statusList); + pagination = MastodonHelper.getPagination(accountStatusesResponse.headers()); } } catch (IOException e) { @@ -375,7 +375,7 @@ public class AccountsVM extends AndroidViewModel { Response> followersResponse = followersCall.execute(); if (followersResponse.isSuccessful()) { accountList = followersResponse.body(); - pagination = MastodonHelper.getPaginationAccount(accountList); + pagination = MastodonHelper.getPagination(followersResponse.headers()); } } catch (IOException e) { e.printStackTrace(); @@ -411,7 +411,7 @@ public class AccountsVM extends AndroidViewModel { Response> followingResponse = followingCall.execute(); if (followingResponse.isSuccessful()) { accountList = followingResponse.body(); - pagination = MastodonHelper.getPaginationAccount(accountList); + pagination = MastodonHelper.getPagination(followingResponse.headers()); } } catch (IOException e) { e.printStackTrace(); @@ -909,7 +909,7 @@ public class AccountsVM extends AndroidViewModel { if (bookmarksResponse.isSuccessful()) { statusList = bookmarksResponse.body(); statuses.statuses = SpannableHelper.convertStatus(getApplication().getApplicationContext(), statusList); - statuses.pagination = MastodonHelper.getPaginationStatus(statusList); + statuses.pagination = MastodonHelper.getPagination(bookmarksResponse.headers()); } } catch (IOException e) { e.printStackTrace(); @@ -940,7 +940,7 @@ public class AccountsVM extends AndroidViewModel { if (favouritesResponse.isSuccessful()) { statusList = favouritesResponse.body(); statuses.statuses = SpannableHelper.convertStatus(getApplication().getApplicationContext(), statusList); - statuses.pagination = MastodonHelper.getPaginationStatus(statusList); + statuses.pagination = MastodonHelper.getPagination(favouritesResponse.headers()); } } catch (IOException e) { e.printStackTrace(); @@ -972,7 +972,7 @@ public class AccountsVM extends AndroidViewModel { if (mutesResponse.isSuccessful()) { accountList = mutesResponse.body(); accounts.accounts = SpannableHelper.convertAccounts(getApplication().getApplicationContext(), accountList); - accounts.pagination = MastodonHelper.getPaginationAccount(accountList); + accounts.pagination = MastodonHelper.getPagination(mutesResponse.headers()); } } catch (IOException e) { e.printStackTrace(); @@ -1004,7 +1004,7 @@ public class AccountsVM extends AndroidViewModel { if (blocksResponse.isSuccessful()) { accountList = blocksResponse.body(); accounts.accounts = SpannableHelper.convertAccounts(getApplication().getApplicationContext(), accountList); - accounts.pagination = MastodonHelper.getPaginationAccount(accountList); + accounts.pagination = MastodonHelper.getPagination(blocksResponse.headers()); } } catch (IOException e) { e.printStackTrace(); diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/NotificationsVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/NotificationsVM.java index 74c633aad..37e762833 100644 --- a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/NotificationsVM.java +++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/NotificationsVM.java @@ -99,12 +99,14 @@ public class NotificationsVM extends AndroidViewModel { if (notificationsResponse.isSuccessful()) { List notFilteredNotifications = notificationsResponse.body(); notifications.notifications = TimelineHelper.filterNotification(getApplication().getApplicationContext(), notFilteredNotifications); - for (Notification notification : notifications.notifications) { - if (notification != null) { - notification.status = SpannableHelper.convertStatus(getApplication().getApplicationContext(), notification.status); + if (notifications.notifications != null) { + for (Notification notification : notifications.notifications) { + if (notification != null) { + notification.status = SpannableHelper.convertStatus(getApplication().getApplicationContext(), notification.status); + } } } - notifications.pagination = MastodonHelper.getPaginationNotification(notifications.notifications); + notifications.pagination = MastodonHelper.getPagination(notificationsResponse.headers()); } } catch (IOException e) { e.printStackTrace(); diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/SearchVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/SearchVM.java index 5a0d8078b..b6eeb05dc 100644 --- a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/SearchVM.java +++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/SearchVM.java @@ -86,13 +86,13 @@ public class SearchVM extends AndroidViewModel { @NonNull String q, String account_id, String type, - boolean exclude_unreviewed, - boolean resolve, - boolean following, - int offset, + Boolean exclude_unreviewed, + Boolean resolve, + Boolean following, + Integer offset, String max_id, String min_id, - int limit) { + Integer limit) { MastodonSearchService mastodonSearchService = init(instance); resultsMutableLiveData = new MutableLiveData<>(); new Thread(() -> { diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/StatusesVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/StatusesVM.java index 11dbdf848..8e708d35c 100644 --- a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/StatusesVM.java +++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/StatusesVM.java @@ -400,7 +400,7 @@ public class StatusesVM extends AndroidViewModel { } Accounts accountsPagination = new Accounts(); accountsPagination.accounts = accounts; - accountsPagination.pagination = MastodonHelper.getPaginationAccount(accounts); + accountsPagination.pagination = MastodonHelper.getPagination(headers); Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> accountsMutableLiveData.setValue(accountsPagination); mainHandler.post(myRunnable); @@ -446,7 +446,7 @@ public class StatusesVM extends AndroidViewModel { Handler mainHandler = new Handler(Looper.getMainLooper()); Accounts accountsPagination = new Accounts(); accountsPagination.accounts = accounts; - accountsPagination.pagination = MastodonHelper.getPaginationAccount(accounts); + accountsPagination.pagination = MastodonHelper.getPagination(headers); Runnable myRunnable = () -> accountsMutableLiveData.setValue(accountsPagination); mainHandler.post(myRunnable); }).start(); @@ -1098,7 +1098,7 @@ public class StatusesVM extends AndroidViewModel { Response> scheduledStatusResponse = scheduledStatuseCall.execute(); if (scheduledStatusResponse.isSuccessful()) { scheduledStatusList = scheduledStatusResponse.body(); - pagination = MastodonHelper.getPaginationScheduledStatus(scheduledStatusList); + pagination = MastodonHelper.getPagination(scheduledStatusResponse.headers()); } } catch (IOException e) { e.printStackTrace(); diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/TimelinesVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/TimelinesVM.java index b9cfb17f7..6b5b670ed 100644 --- a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/TimelinesVM.java +++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/TimelinesVM.java @@ -37,6 +37,7 @@ import app.fedilab.android.client.mastodon.entities.Conversation; import app.fedilab.android.client.mastodon.entities.Conversations; import app.fedilab.android.client.mastodon.entities.Marker; import app.fedilab.android.client.mastodon.entities.MastodonList; +import app.fedilab.android.client.mastodon.entities.Pagination; import app.fedilab.android.client.mastodon.entities.Status; import app.fedilab.android.client.mastodon.entities.Statuses; import app.fedilab.android.exception.DBException; @@ -95,13 +96,13 @@ public class TimelinesVM extends AndroidViewModel { * @return {@link LiveData} containing a {@link Statuses} */ public LiveData getPublic(String token, @NonNull String instance, - boolean local, - boolean remote, - boolean onlyMedia, + Boolean local, + Boolean remote, + Boolean onlyMedia, String maxId, String sinceId, String minId, - int limit) { + Integer limit) { MastodonTimelinesService mastodonTimelinesService = init(instance); statusesMutableLiveData = new MutableLiveData<>(); new Thread(() -> { @@ -114,7 +115,7 @@ public class TimelinesVM extends AndroidViewModel { List notFilteredStatuses = publicTlResponse.body(); List filteredStatuses = TimelineHelper.filterStatus(getApplication(), notFilteredStatuses, TimelineHelper.FilterTimeLineType.PUBLIC); statuses.statuses = SpannableHelper.convertStatus(getApplication().getApplicationContext(), filteredStatuses); - statuses.pagination = MastodonHelper.getPaginationStatus(statuses.statuses); + statuses.pagination = MastodonHelper.getPagination(publicTlResponse.headers()); } } catch (IOException e) { e.printStackTrace(); @@ -163,7 +164,7 @@ public class TimelinesVM extends AndroidViewModel { List notFilteredStatuses = hashTagTlResponse.body(); List filteredStatuses = TimelineHelper.filterStatus(getApplication().getApplicationContext(), notFilteredStatuses, TimelineHelper.FilterTimeLineType.PUBLIC); statuses.statuses = SpannableHelper.convertStatus(getApplication().getApplicationContext(), filteredStatuses); - statuses.pagination = MastodonHelper.getPaginationStatus(statuses.statuses); + statuses.pagination = MastodonHelper.getPagination(hashTagTlResponse.headers()); } } catch (IOException e) { e.printStackTrace(); @@ -205,7 +206,7 @@ public class TimelinesVM extends AndroidViewModel { List notFilteredStatuses = homeTlResponse.body(); List filteredStatuses = TimelineHelper.filterStatus(getApplication().getApplicationContext(), notFilteredStatuses, TimelineHelper.FilterTimeLineType.HOME); statuses.statuses = SpannableHelper.convertStatus(getApplication().getApplicationContext(), filteredStatuses); - statuses.pagination = MastodonHelper.getPaginationStatus(statuses.statuses); + statuses.pagination = MastodonHelper.getPagination(homeTlResponse.headers()); for (Status status : statuses.statuses) { StatusCache statusCacheDAO = new StatusCache(getApplication().getApplicationContext()); StatusCache statusCache = new StatusCache(); @@ -253,6 +254,11 @@ public class TimelinesVM extends AndroidViewModel { statuses = statusCacheDAO.geStatuses(StatusCache.CacheEnum.HOME, instance, user_id, maxId, minId); if (statuses != null) { statuses.statuses = SpannableHelper.convertStatus(getApplication().getApplicationContext(), statuses.statuses); + if (statuses.statuses != null && statuses.statuses.size() > 0) { + statuses.pagination = new Pagination(); + statuses.pagination.min_id = statuses.statuses.get(0).id; + statuses.pagination.max_id = statuses.statuses.get(statuses.statuses.size() - 1).id; + } } } catch (DBException e) { e.printStackTrace(); @@ -315,7 +321,7 @@ public class TimelinesVM extends AndroidViewModel { Response> listTlResponse = listTlCall.execute(); if (listTlResponse.isSuccessful()) { statuses.statuses = SpannableHelper.convertStatus(getApplication().getApplicationContext(), listTlResponse.body()); - statuses.pagination = MastodonHelper.getPaginationStatus(statuses.statuses); + statuses.pagination = MastodonHelper.getPagination(listTlResponse.headers()); } } catch (IOException e) { e.printStackTrace(); @@ -355,7 +361,7 @@ public class TimelinesVM extends AndroidViewModel { conversation.last_status = SpannableHelper.convertStatus(getApplication().getApplicationContext(), conversation.last_status); } } - conversations.pagination = MastodonHelper.getPaginationConversation(conversations.conversations); + conversations.pagination = MastodonHelper.getPagination(conversationsResponse.headers()); } } catch (IOException e) { e.printStackTrace();