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 b718c1aa9..ca1275a98 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 @@ -43,8 +43,10 @@ import app.fedilab.android.R; import app.fedilab.android.client.entities.api.Notification; import app.fedilab.android.client.entities.api.Notifications; import app.fedilab.android.client.entities.api.Status; +import app.fedilab.android.client.entities.app.StatusCache; import app.fedilab.android.client.entities.app.Timeline; import app.fedilab.android.databinding.FragmentPaginationBinding; +import app.fedilab.android.exception.DBException; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.MastodonHelper; import app.fedilab.android.helper.ThemeHelper; @@ -111,6 +113,25 @@ public class FragmentMastodonNotification extends Fragment implements Notificati return found ? position : -1; } + /** + * Return the position of the notification in the ArrayList + * + * @param notification - Notification to fetch + * @return position or -1 if not found + */ + private int getPosition(Notification notification) { + int position = 0; + boolean found = false; + for (Notification _notification : notificationList) { + if (_notification.status != null && _notification.id.compareTo(notification.id) == 0) { + found = true; + break; + } + position++; + } + return found ? position : -1; + } + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -307,7 +328,6 @@ public class FragmentMastodonNotification extends Fragment implements Notificati } else { timelineParams.maxId = max_id; } - timelineParams.userId = null; timelineParams.excludeType = getExcludeType(); timelineParams.fetchingMissing = fetchingMissing; @@ -416,6 +436,7 @@ public class FragmentMastodonNotification extends Fragment implements Notificati } + /** * Update view and pagination when scrolling down * @@ -429,10 +450,31 @@ public class FragmentMastodonNotification extends Fragment implements Notificati binding.loadingNextElements.setVisibility(View.GONE); flagLoading = false; if (notificationList != null && fetched_notifications != null && fetched_notifications.notifications != null && fetched_notifications.notifications.size() > 0) { + try { + if (notificationToUpdate != null) { + new Thread(() -> { + StatusCache statusCache = new StatusCache(); + statusCache.instance = BaseMainActivity.currentInstance; + statusCache.user_id = BaseMainActivity.currentUserID; + statusCache.notification = notificationToUpdate; + statusCache.status_id = notificationToUpdate.id; + try { + new StatusCache(requireActivity()).updateIfExists(statusCache); + } catch (DBException e) { + e.printStackTrace(); + } + }).start(); + } + } catch (Exception ignored) { + } + flagLoading = fetched_notifications.pagination.max_id == null; binding.noAction.setVisibility(View.GONE); //Update the timeline with new statuses - updateNotificationListWith(direction, fetched_notifications.notifications, fetchingMissing); + updateNotificationListWith(fetched_notifications.notifications); + if (direction == FragmentMastodonTimeline.DIRECTION.TOP && fetchingMissing) { + binding.recyclerView.scrollToPosition(getPosition(fetched_notifications.notifications.get(fetched_notifications.notifications.size() - 1)) + 1); + } if (!fetchingMissing) { if (fetched_notifications.pagination.max_id == null) { flagLoading = true; @@ -452,83 +494,34 @@ public class FragmentMastodonNotification extends Fragment implements Notificati * Update the timeline with received statuses * * @param notificationsReceived - List Notifications received - * @param fetchingMissing - boolean if the call concerns fetching messages (ie: refresh of from fetch more button) */ - private void updateNotificationListWith(FragmentMastodonTimeline.DIRECTION direction, List notificationsReceived, boolean fetchingMissing) { - int numberInserted = 0; - int lastInsertedPosition = 0; - int initialInsertedPosition = NOTIFICATION_PRESENT; + private void updateNotificationListWith(List notificationsReceived) { if (notificationsReceived != null && notificationsReceived.size() > 0) { - int insertedPosition = NOTIFICATION_PRESENT; for (Notification notificationReceived : notificationsReceived) { - insertedPosition = insertNotification(notificationReceived); - if (insertedPosition != NOTIFICATION_PRESENT && insertedPosition != NOTIFICATION__AT_THE_BOTTOM) { - numberInserted++; - if (initialInsertedPosition == NOTIFICATION_PRESENT) { - initialInsertedPosition = insertedPosition; + int position = 0; + //We loop through messages already in the timeline + if (this.notificationList != null) { + notificationAdapter.notifyItemRangeChanged(0, this.notificationList.size()); + for (Notification notificationsAlreadyPresent : this.notificationList) { + //We compare the date of each status and we only add status having a date greater than the another, it is inserted at this position + //Pinned messages are ignored because their date can be older + if (notificationReceived.id.compareTo(notificationsAlreadyPresent.id) > 0) { + notificationList.add(position, notificationReceived); + notificationAdapter.notifyItemInserted(position); + break; + } + position++; } - if (insertedPosition < initialInsertedPosition) { - initialInsertedPosition = lastInsertedPosition; + //Statuses added at the bottom, we flag them by position = -2 for not dealing with them and fetch more + if (position == notificationList.size() && !notificationList.contains(notificationReceived)) { + notificationList.add(position, notificationReceived); + notificationAdapter.notifyItemInserted(position); } } } - lastInsertedPosition = initialInsertedPosition + numberInserted; - //lastInsertedPosition contains the position of the last inserted status - //If there were no overlap for top status - if (fetchingMissing && insertedPosition != NOTIFICATION_PRESENT && insertedPosition != NOTIFICATION__AT_THE_BOTTOM && this.notificationList.size() > insertedPosition) { - Notification notificationFetchMore = new Notification(); - notificationFetchMore.isFetchMore = true; - notificationFetchMore.id = Helper.generateString(); - int insertAt; - if (direction == FragmentMastodonTimeline.DIRECTION.REFRESH) { - insertAt = lastInsertedPosition; - } else { - insertAt = initialInsertedPosition; - } - - this.notificationList.add(insertAt, notificationFetchMore); - notificationAdapter.notifyItemInserted(insertAt); - } } } - /** - * Insert a status if not yet in the timeline - * - * @param notificationReceived - Notification coming from the api/db - * @return int >= 0 | STATUS_PRESENT = -1 | STATUS_AT_THE_BOTTOM = -2 - */ - private int insertNotification(Notification notificationReceived) { - if (idOfAddedNotifications.contains(notificationReceived.id)) { - return NOTIFICATION_PRESENT; - } - int position = 0; - //We loop through messages already in the timeline - if (this.notificationList != null) { - notificationAdapter.notifyItemRangeChanged(0, this.notificationList.size()); - for (Notification notificationsAlreadyPresent : this.notificationList) { - //We compare the date of each status and we only add status having a date greater than the another, it is inserted at this position - //Pinned messages are ignored because their date can be older - if (notificationReceived.id.compareTo(notificationsAlreadyPresent.id) > 0) { - //We add the status to a list of id - thus we know it is already in the timeline - idOfAddedNotifications.add(notificationReceived.id); - this.notificationList.add(position, notificationReceived); - notificationAdapter.notifyItemInserted(position); - break; - } - position++; - } - //Statuses added at the bottom, we flag them by position = -2 for not dealing with them and fetch more - if (position == this.notificationList.size()) { - //We add the status to a list of id - thus we know it is already in the timeline - idOfAddedNotifications.add(notificationReceived.id); - this.notificationList.add(position, notificationReceived); - notificationAdapter.notifyItemInserted(position); - return NOTIFICATION__AT_THE_BOTTOM; - } - } - return position; - } @Override 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 a7ed2dc18..0dcb1b36d 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 @@ -391,20 +391,20 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter. flagLoading = false; if (timelineStatuses != null && fetched_statuses != null && fetched_statuses.statuses != null && fetched_statuses.statuses.size() > 0) { try { - new Thread(() -> { - StatusCache statusCache = new StatusCache(); - statusCache.instance = BaseMainActivity.currentInstance; - statusCache.user_id = BaseMainActivity.currentUserID; - statusCache.status = statusToUpdate; - if (statusToUpdate != null) { + if (statusToUpdate != null) { + new Thread(() -> { + StatusCache statusCache = new StatusCache(); + statusCache.instance = BaseMainActivity.currentInstance; + statusCache.user_id = BaseMainActivity.currentUserID; + statusCache.status = statusToUpdate; statusCache.status_id = statusToUpdate.id; - } - try { - new StatusCache(requireActivity()).updateIfExists(statusCache); - } catch (DBException e) { - e.printStackTrace(); - } - }).start(); + try { + new StatusCache(requireActivity()).updateIfExists(statusCache); + } catch (DBException e) { + e.printStackTrace(); + } + }).start(); + } } catch (Exception ignored) { } flagLoading = fetched_statuses.pagination.max_id == null; @@ -460,8 +460,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter. * * @param statusListReceived - List Statuses received */ - private int updateStatusListWith(List statusListReceived) { - int inserted = 0; + private void updateStatusListWith(List statusListReceived) { if (statusListReceived != null && statusListReceived.size() > 0) { for (Status statusReceived : statusListReceived) { int position = 0; @@ -477,7 +476,6 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter. if (!timelineStatuses.contains(statusReceived) && !statusReceived.pinned && timelineType != Timeline.TimeLineEnum.ACCOUNT_TIMELINE) { timelineStatuses.add(position, statusReceived); statusAdapter.notifyItemInserted(position); - inserted++; } break; } @@ -492,7 +490,6 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter. } } } - return inserted; } @Override 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 45b0d924b..efb4ba3d8 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 @@ -104,7 +104,7 @@ public class NotificationsVM extends AndroidViewModel { MastodonNotificationsService mastodonNotificationsService = init(timelineParams.instance); new Thread(() -> { Notifications notifications = new Notifications(); - Call> notificationsCall = mastodonNotificationsService.getNotifications(timelineParams.token, timelineParams.excludeType, timelineParams.userId, timelineParams.maxId, timelineParams.sinceId, timelineParams.minId, timelineParams.limit); + Call> notificationsCall = mastodonNotificationsService.getNotifications(timelineParams.token, timelineParams.excludeType, null, timelineParams.maxId, timelineParams.sinceId, timelineParams.minId, timelineParams.limit); if (notificationsCall != null) { try { Response> notificationsResponse = notificationsCall.execute(); @@ -125,7 +125,7 @@ public class NotificationsVM extends AndroidViewModel { statusCache.type = Timeline.TimeLineEnum.NOTIFICATION; statusCache.status_id = notification.id; try { - statusCacheDAO.insertOrUpdate(statusCache, timelineParams.slug); + statusCacheDAO.insertOrUpdate(statusCache, notification.type); } catch (DBException e) { e.printStackTrace(); }