diff --git a/app/src/fdroid/java/fr.gouv.etalab.mastodon/activities/MainActivity.java b/app/src/fdroid/java/fr.gouv.etalab.mastodon/activities/MainActivity.java index 37c330177..a545fd7a1 100644 --- a/app/src/fdroid/java/fr.gouv.etalab.mastodon/activities/MainActivity.java +++ b/app/src/fdroid/java/fr.gouv.etalab.mastodon/activities/MainActivity.java @@ -100,8 +100,6 @@ import fr.gouv.etalab.mastodon.fragments.TabLayoutSettingsFragment; import fr.gouv.etalab.mastodon.sqlite.AccountDAO; import mastodon.etalab.gouv.fr.mastodon.R; -import static fr.gouv.etalab.mastodon.fragments.DisplayNotificationsFragment.tempNotifications; -import static fr.gouv.etalab.mastodon.fragments.DisplayStatusFragment.tempStatuses; import static fr.gouv.etalab.mastodon.helper.Helper.CHANGE_THEME_INTENT; import static fr.gouv.etalab.mastodon.helper.Helper.CHANGE_USER_INTENT; import static fr.gouv.etalab.mastodon.helper.Helper.HOME_TIMELINE_INTENT; @@ -141,7 +139,7 @@ public class MainActivity extends AppCompatActivity public static int countNewNotifications = 0; private String userIdService; private Intent streamingIntent, streamingFederatedIntent; - public static boolean broadCastRegistred = false, broadCastFederatedRegistred = false; + public static String lastHomeId = null, lastNotificationId = null; public MainActivity() { } @@ -154,73 +152,6 @@ public class MainActivity extends AppCompatActivity final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE); - receive_federated_data = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Bundle b = intent.getExtras(); - userIdService = b.getString("userIdService", null); - String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); - if( userIdService != null && userIdService.equals(userId)) { - Status status = b.getParcelable("data"); - if (federatedFragment != null) { - federatedFragment.refresh(status); - } - } - } - }; - receive_data = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Bundle b = intent.getExtras(); - StreamingService.EventStreaming eventStreaming = (StreamingService.EventStreaming) intent.getSerializableExtra("eventStreaming"); - userIdService = b.getString("userIdService", null); - String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); - if( userIdService != null && userIdService.equals(userId)) { - if (eventStreaming == StreamingService.EventStreaming.NOTIFICATION) { - Notification notification = b.getParcelable("data"); - if (notificationsFragment != null) { - notificationsFragment.refresh(notification); - } else { - tempNotifications.add(notification); - } - } else if (eventStreaming == StreamingService.EventStreaming.UPDATE) { - Status status = b.getParcelable("data"); - if (homeFragment != null) { - homeFragment.refresh(status); - } else { - tempStatuses.add(status); - } - } else if (eventStreaming == StreamingService.EventStreaming.DELETE) { - String id = b.getString("id"); - if (notificationsFragment != null) { - if (notificationsFragment.getUserVisibleHint()) { - - } else { - - } - } - } - updateNotifCounter(); - updateHomeCounter(); - } - } - }; - streamingIntent = new Intent(this, StreamingService.class); - startService(streamingIntent); - - streamingFederatedIntent = new Intent(this, StreamingFederatedTimelineService.class); - startService(streamingFederatedIntent); - - if( !broadCastRegistred) { - LocalBroadcastManager.getInstance(this).registerReceiver(receive_data, new IntentFilter(Helper.RECEIVE_DATA)); - broadCastRegistred = true; - } - if( !broadCastFederatedRegistred) { - LocalBroadcastManager.getInstance(this).registerReceiver(receive_federated_data, new IntentFilter(Helper.RECEIVE_FEDERATED_DATA)); - broadCastFederatedRegistred = true; - } - - final int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK); if( theme == Helper.THEME_LIGHT){ @@ -760,7 +691,6 @@ public class MainActivity extends AppCompatActivity * @param intent Intent - intent related to a notification in top bar */ private boolean mamageNewIntent(Intent intent){ - if( intent == null || intent.getExtras() == null ) return false; @@ -931,10 +861,86 @@ public class MainActivity extends AppCompatActivity //Proceeds to update of the authenticated account if(Helper.isLoggedIn(getApplicationContext())) new UpdateAccountInfoByIDAsyncTask(getApplicationContext(), MainActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + if( lastHomeId != null && homeFragment != null){ + homeFragment.retrieveMissingToots(lastHomeId); + } + if( lastNotificationId != null && notificationsFragment != null){ + notificationsFragment.retrieveMissingNotifications(lastNotificationId); + } } + @Override + public void onStart(){ + super.onStart(); + final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); + receive_federated_data = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Bundle b = intent.getExtras(); + userIdService = b.getString("userIdService", null); + String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); + if( userIdService != null && userIdService.equals(userId)) { + Status status = b.getParcelable("data"); + if (federatedFragment != null) { + federatedFragment.refresh(status); + } + } + } + }; + receive_data = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Bundle b = intent.getExtras(); + StreamingService.EventStreaming eventStreaming = (StreamingService.EventStreaming) intent.getSerializableExtra("eventStreaming"); + userIdService = b.getString("userIdService", null); + String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); + if( userIdService != null && userIdService.equals(userId)) { + if (eventStreaming == StreamingService.EventStreaming.NOTIFICATION) { + Notification notification = b.getParcelable("data"); + if (notificationsFragment != null) { + notificationsFragment.refresh(notification); + } + } else if (eventStreaming == StreamingService.EventStreaming.UPDATE) { + Status status = b.getParcelable("data"); + if (homeFragment != null) { + homeFragment.refresh(status); + } + } else if (eventStreaming == StreamingService.EventStreaming.DELETE) { + String id = b.getString("id"); + if (notificationsFragment != null) { + if (notificationsFragment.getUserVisibleHint()) { + } else { + + } + } + } + updateNotifCounter(); + updateHomeCounter(); + } + } + }; + streamingIntent = new Intent(this, StreamingService.class); + startService(streamingIntent); + streamingFederatedIntent = new Intent(this, StreamingFederatedTimelineService.class); + startService(streamingFederatedIntent); + LocalBroadcastManager.getInstance(this).registerReceiver(receive_data, new IntentFilter(Helper.RECEIVE_DATA)); + LocalBroadcastManager.getInstance(this).registerReceiver(receive_federated_data, new IntentFilter(Helper.RECEIVE_FEDERATED_DATA)); + } + + @Override + public void onStop(){ + super.onStop(); + if( streamingIntent != null) + stopService(streamingIntent); + if( streamingFederatedIntent != null) + stopService(streamingFederatedIntent); + if( receive_data != null) + LocalBroadcastManager.getInstance(this).unregisterReceiver(receive_data); + if( receive_federated_data != null) + LocalBroadcastManager.getInstance(this).unregisterReceiver(receive_federated_data); + } @Override protected void onPause() { @@ -945,14 +951,6 @@ public class MainActivity extends AppCompatActivity @Override public void onDestroy(){ super.onDestroy(); - if( streamingIntent != null) - stopService(streamingIntent); - if( streamingFederatedIntent != null) - stopService(streamingFederatedIntent); - LocalBroadcastManager.getInstance(this).unregisterReceiver(receive_data); - LocalBroadcastManager.getInstance(this).unregisterReceiver(receive_federated_data); - broadCastRegistred = false; - broadCastFederatedRegistred = false; } @SuppressWarnings("StatementWithEmptyBody") diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveFeedsAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveFeedsAsyncTask.java index 210d66d88..cb920b8fc 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveFeedsAsyncTask.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveFeedsAsyncTask.java @@ -16,11 +16,8 @@ package fr.gouv.etalab.mastodon.asynctasks; import android.content.Context; import android.os.AsyncTask; -import android.util.Log; - import fr.gouv.etalab.mastodon.client.API; import fr.gouv.etalab.mastodon.client.APIResponse; -import fr.gouv.etalab.mastodon.helper.Helper; import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface; diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveMissingFeedsAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveMissingFeedsAsyncTask.java new file mode 100644 index 000000000..c6773404c --- /dev/null +++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveMissingFeedsAsyncTask.java @@ -0,0 +1,72 @@ +/* Copyright 2017 Thomas Schneider + * + * This file is a part of Mastalab + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * Mastalab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Mastalab; if not, + * see . */ +package fr.gouv.etalab.mastodon.asynctasks; + +import android.content.Context; +import android.os.AsyncTask; +import java.util.ArrayList; +import java.util.List; +import fr.gouv.etalab.mastodon.activities.MainActivity; +import fr.gouv.etalab.mastodon.client.API; +import fr.gouv.etalab.mastodon.client.APIResponse; +import fr.gouv.etalab.mastodon.interfaces.OnRetrieveMissingFeedsInterface; + + +/** + * Created by Thomas on 27/09/2017. + * Retrieves missing toots since last pause + */ + +public class RetrieveMissingFeedsAsyncTask extends AsyncTask { + + private Context context; + private String since_id; + private OnRetrieveMissingFeedsInterface listener; + private List statuses = new ArrayList<>(); + + public RetrieveMissingFeedsAsyncTask(Context context, String since_id, OnRetrieveMissingFeedsInterface onRetrieveMissingFeedsInterface){ + this.context = context; + this.since_id = since_id; + this.listener = onRetrieveMissingFeedsInterface; + } + + + @Override + protected Void doInBackground(Void... params) { + int loopInc = 0; + API api = new API(context); + List tempStatus; + while (loopInc < 10){ + APIResponse apiResponse = api.getHomeTimelineSinceId(since_id, 80); + String max_id = apiResponse.getMax_id(); + since_id = apiResponse.getSince_id(); + tempStatus = apiResponse.getStatuses(); + if( statuses != null && tempStatus != null) + statuses.addAll(0, tempStatus); + loopInc++; + if( max_id == null || max_id.equals(since_id)) + break; + } + if( statuses != null && statuses.size() > 0) { + MainActivity.lastHomeId = statuses.get(0).getId(); + } + return null; + } + + @Override + protected void onPostExecute(Void result) { + listener.onRetrieveMissingFeeds(statuses); + } +} diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveMissingNotificationsAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveMissingNotificationsAsyncTask.java new file mode 100644 index 000000000..1b952b429 --- /dev/null +++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveMissingNotificationsAsyncTask.java @@ -0,0 +1,75 @@ +/* Copyright 2017 Thomas Schneider + * + * This file is a part of Mastalab + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * Mastalab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Mastalab; if not, + * see . */ +package fr.gouv.etalab.mastodon.asynctasks; + +import android.content.Context; +import android.os.AsyncTask; + +import java.util.ArrayList; +import java.util.List; + +import fr.gouv.etalab.mastodon.activities.MainActivity; +import fr.gouv.etalab.mastodon.client.API; +import fr.gouv.etalab.mastodon.client.APIResponse; +import fr.gouv.etalab.mastodon.client.Entities.Notification; +import fr.gouv.etalab.mastodon.interfaces.OnRetrieveMissingNotificationsInterface; + + +/** + * Created by Thomas on 27/09/2017. + * Retrieves missing notifications since last pause + */ + +public class RetrieveMissingNotificationsAsyncTask extends AsyncTask { + + private Context context; + private String since_id; + private OnRetrieveMissingNotificationsInterface listener; + private List notifications = new ArrayList<>(); + + public RetrieveMissingNotificationsAsyncTask(Context context, String since_id, OnRetrieveMissingNotificationsInterface onRetrieveMissingNotifications){ + this.context = context; + this.since_id = since_id; + this.listener = onRetrieveMissingNotifications; + } + + + @Override + protected Void doInBackground(Void... params) { + int loopInc = 0; + API api = new API(context); + List tempNotifications; + while (loopInc < 10){ + APIResponse apiResponse = api.getNotificationsSince(since_id, 40); + String max_id = apiResponse.getMax_id(); + since_id = apiResponse.getSince_id(); + tempNotifications = apiResponse.getNotifications(); + if( notifications != null && tempNotifications != null) + notifications.addAll(0, tempNotifications); + loopInc++; + if( max_id == null || max_id.equals(since_id)) + break; + } + if( notifications != null && notifications.size() > 0) { + MainActivity.lastNotificationId = notifications.get(0).getId(); + } + return null; + } + + @Override + protected void onPostExecute(Void result) { + listener.onRetrieveMissingNotifications(notifications); + } +} diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java index b420e93bf..aa30a65a1 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java @@ -468,6 +468,14 @@ public class API { return getHomeTimeline(max_id, null, tootPerPage); } + /** + * Retrieves home timeline for the account *synchronously* + * @return APIResponse + */ + public APIResponse getHomeTimeline( String max_id, int tootPerPage) { + return getHomeTimeline(max_id, null, tootPerPage); + } + /** * Retrieves home timeline for the account since an Id value *synchronously* * @return APIResponse @@ -476,6 +484,14 @@ public class API { return getHomeTimeline(null, since_id, tootPerPage); } + /** + * Retrieves home timeline for the account since an Id value *synchronously* + * @return APIResponse + */ + public APIResponse getHomeTimelineSinceId(String since_id, int tootPerPage) { + return getHomeTimeline(null, since_id, tootPerPage); + } + /** * Retrieves home timeline for the account *synchronously* * @param max_id String id max @@ -490,8 +506,8 @@ public class API { params.put("max_id", max_id); if (since_id != null) params.put("since_id", since_id); - if (0 > limit || limit > 40) - limit = 40; + if (0 > limit || limit > 80) + limit = 80; params.put("limit",String.valueOf(limit)); statuses = new ArrayList<>(); get("/timelines/home", params, new JsonHttpResponseHandler() { @@ -1070,6 +1086,15 @@ public class API { return getNotifications(null, since_id, notificationPerPage); } + /** + * Retrieves notifications for the authenticated account since an id*synchronously* + * @param since_id String since max + * @return APIResponse + */ + public APIResponse getNotificationsSince(String since_id, int notificationPerPage){ + return getNotifications(null, since_id, notificationPerPage); + } + /** * Retrieves notifications for the authenticated account *synchronously* * @param max_id String id max diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayNotificationsFragment.java b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayNotificationsFragment.java index c77db26f3..f978d1bba 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayNotificationsFragment.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayNotificationsFragment.java @@ -31,10 +31,12 @@ import java.util.List; import fr.gouv.etalab.mastodon.activities.MainActivity; import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask; +import fr.gouv.etalab.mastodon.asynctasks.RetrieveMissingNotificationsAsyncTask; import fr.gouv.etalab.mastodon.client.APIResponse; import fr.gouv.etalab.mastodon.client.Entities.Status; import fr.gouv.etalab.mastodon.drawers.NotificationsListAdapter; import fr.gouv.etalab.mastodon.helper.Helper; +import fr.gouv.etalab.mastodon.interfaces.OnRetrieveMissingNotificationsInterface; import mastodon.etalab.gouv.fr.mastodon.R; import fr.gouv.etalab.mastodon.asynctasks.RetrieveNotificationsAsyncTask; import fr.gouv.etalab.mastodon.client.Entities.Notification; @@ -45,7 +47,7 @@ import fr.gouv.etalab.mastodon.interfaces.OnRetrieveNotificationsInterface; * Created by Thomas on 28/04/2017. * Fragment to display notifications related to accounts */ -public class DisplayNotificationsFragment extends Fragment implements OnRetrieveNotificationsInterface { +public class DisplayNotificationsFragment extends Fragment implements OnRetrieveNotificationsInterface, OnRetrieveMissingNotificationsInterface { @@ -62,7 +64,6 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve private ListView lv_notifications; private String lastReadNotifications; private String userId; - public static ArrayList tempNotifications = new ArrayList<>(); public DisplayNotificationsFragment(){ } @@ -155,31 +156,6 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve asyncTask.cancel(true); } - - @Override - public void onResume() { - super.onResume(); - ArrayList knownId = new ArrayList<>(); - for(Notification nt: notifications){ - knownId.add(nt.getId()); - } - for(Notification notification: tempNotifications){ - if( !knownId.contains(notification.getId())) { - int index = lv_notifications.getFirstVisiblePosition() + 1; - View v = lv_notifications.getChildAt(0); - int top = (v == null) ? 0 : v.getTop(); - notifications.add(0, notification); - notificationsListAdapter.notifyDataSetChanged(); - lv_notifications.setSelectionFromTop(index, top); - if (textviewNoAction.getVisibility() == View.VISIBLE) - textviewNoAction.setVisibility(View.GONE); - } - } - ((MainActivity)context).updateNotifCounter(); - tempNotifications.clear(); - tempNotifications = new ArrayList<>(); - } - @Override public void onRetrieveNotifications(APIResponse apiResponse, String acct, String userId, boolean refreshData) { final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); @@ -215,6 +191,8 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve this.notifications.add(tmpNotification); } if( firstLoad) { + //Update the id of the last notification retrieved + MainActivity.lastNotificationId = notifications.get(0).getId(); SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + this.userId, notifications.get(0).getId()); editor.apply(); @@ -230,6 +208,14 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve flag_loading = (max_id == null ); } + /** + * Called from main activity in onResume to retrieve missing notifications + * @param sinceId String + */ + public void retrieveMissingNotifications(String sinceId){ + asyncTask = new RetrieveMissingNotificationsAsyncTask(context, sinceId, DisplayNotificationsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + @Override public void setMenuVisibility(final boolean visible) { super.setMenuVisibility(visible); @@ -264,6 +250,8 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve if( context == null) return; if( notification != null){ + //Update the id of the last notification retrieved + MainActivity.lastNotificationId = notification.getId(); int index = lv_notifications.getFirstVisiblePosition() + 1; View v = lv_notifications.getChildAt(0); int top = (v == null) ? 0 : v.getTop(); @@ -275,4 +263,24 @@ public class DisplayNotificationsFragment extends Fragment implements OnRetrieve textviewNoAction.setVisibility(View.GONE); } } + + @Override + public void onRetrieveMissingNotifications(List notifications) { + if( notifications != null && notifications.size() > 0) { + ArrayList knownId = new ArrayList<>(); + for (Notification nt : this.notifications) { + knownId.add(nt.getId()); + } + for (int i = notifications.size()-1 ; i >= 0 ; i--) { + if (!knownId.contains(notifications.get(i).getId())) { + MainActivity.countNewNotifications++; + this.notifications.add(0, notifications.get(i)); + } + } + notificationsListAdapter.notifyDataSetChanged(); + try { + ((MainActivity) context).updateNotifCounter(); + }catch (Exception ignored){} + } + } } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayStatusFragment.java b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayStatusFragment.java index 8c414d063..cfce707e7 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayStatusFragment.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplayStatusFragment.java @@ -36,10 +36,12 @@ import java.util.ArrayList; import java.util.List; import fr.gouv.etalab.mastodon.activities.MainActivity; +import fr.gouv.etalab.mastodon.asynctasks.RetrieveMissingFeedsAsyncTask; import fr.gouv.etalab.mastodon.asynctasks.RetrieveRepliesAsyncTask; import fr.gouv.etalab.mastodon.client.APIResponse; import fr.gouv.etalab.mastodon.drawers.StatusListAdapter; import fr.gouv.etalab.mastodon.helper.Helper; +import fr.gouv.etalab.mastodon.interfaces.OnRetrieveMissingFeedsInterface; import fr.gouv.etalab.mastodon.interfaces.OnRetrieveRepliesInterface; import mastodon.etalab.gouv.fr.mastodon.R; import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask; @@ -51,7 +53,7 @@ import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface; * Created by Thomas on 24/04/2017. * Fragment to display content related to status */ -public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsInterface, OnRetrieveRepliesInterface { +public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsInterface, OnRetrieveRepliesInterface, OnRetrieveMissingFeedsInterface { private boolean flag_loading; @@ -76,8 +78,6 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn private String instanceValue; private String lastReadStatus; private String userId; - public static ArrayList tempStatuses = new ArrayList<>(); - private int lastTotalItemCount = 0; public DisplayStatusFragment(){ } @@ -228,37 +228,6 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn - @Override - public void onResume() { - super.onResume(); - if( type == RetrieveFeedsAsyncTask.Type.HOME && tempStatuses != null && tempStatuses.size() > 0 ){ - ArrayList knownId = new ArrayList<>(); - for(Status st: statuses){ - knownId.add(st.getId()); - } - for(Status status: tempStatuses){ - if( !knownId.contains(status.getId())){ - int index = lv_status.getFirstVisiblePosition() + 1; - View v = lv_status.getChildAt(0); - int top = (v == null) ? 0 : v.getTop(); - status.setReplies(new ArrayList()); - statuses.add(0,status); - statusListAdapter.notifyDataSetChanged(); - lv_status.setSelectionFromTop(index, top); - if (textviewNoAction.getVisibility() == View.VISIBLE) - textviewNoAction.setVisibility(View.GONE); - MainActivity.countNewStatus++; - } - } - if( getActivity() != null && getActivity().getClass().isInstance(MainActivity.class)) - ((MainActivity)context).updateHomeCounter(); - //Resets value for the counter but doesn't update it - MainActivity.countNewStatus = 0; - tempStatuses.clear(); - tempStatuses = new ArrayList<>(); - } - } - @Override public void onAttach(Context context) { super.onAttach(context); @@ -321,6 +290,8 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn } if( firstLoad && type == RetrieveFeedsAsyncTask.Type.HOME) { + //Update the id of the last toot retrieved + MainActivity.lastHomeId = statuses.get(0).getId(); SharedPreferences.Editor editor = sharedpreferences.edit(); String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); editor.putString(Helper.LAST_HOMETIMELINE_MAX_ID + userId, statuses.get(0).getId()); @@ -347,12 +318,18 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn } } + /** + * Deals with new status coming from the streaming api + * @param status Status + */ public void refresh(Status status){ //New data are available if( type == RetrieveFeedsAsyncTask.Type.HOME) { if (context == null) return; if (status != null) { + //Update the id of the last toot retrieved + MainActivity.lastHomeId = status.getId(); int index = lv_status.getFirstVisiblePosition() + 1; View v = lv_status.getChildAt(0); int top = (v == null) ? 0 : v.getTop(); @@ -393,12 +370,24 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn } + + /** + * Called from main activity in onResume to retrieve missing toots (home timeline) + * @param sinceId String + */ + public void retrieveMissingToots(String sinceId){ + asyncTask = new RetrieveMissingFeedsAsyncTask(context, sinceId, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + /** + * When tab comes visible, first displayed toot is defined as read + * @param visible boolean + */ @Override public void setMenuVisibility(final boolean visible) { super.setMenuVisibility(visible); if( context == null) return; - //Store last toot id for home timeline to avoid to notify for those that have been already seen if (type == RetrieveFeedsAsyncTask.Type.HOME && visible && statuses != null && statuses.size() > 0) { SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); @@ -442,4 +431,25 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn } statusListAdapter.notifyDataSetChanged(); } + + @Override + public void onRetrieveMissingFeeds(List statuses) { + if( statuses != null && statuses.size() > 0) { + ArrayList knownId = new ArrayList<>(); + for (Status st : this.statuses) { + knownId.add(st.getId()); + } + for (int i = statuses.size()-1 ; i >= 0 ; i--) { + if (!knownId.contains(statuses.get(i).getId())) { + statuses.get(i).setNew(true); + MainActivity.countNewStatus++; + this.statuses.add(0, statuses.get(i)); + } + } + statusListAdapter.notifyDataSetChanged(); + try { + ((MainActivity) context).updateHomeCounter(); + }catch (Exception ignored){} + } + } } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java b/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java index 9a1f91891..2e458c020 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/helper/Helper.java @@ -937,17 +937,6 @@ public class Helper { } SharedPreferences sharedpreferences = activity.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); String oldUserId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); - //User wont' be the same, temp values are cleared - if( oldUserId != null && !oldUserId.equals(userID)){ - if( DisplayStatusFragment.tempStatuses != null) { - DisplayStatusFragment.tempStatuses.clear(); - DisplayStatusFragment.tempStatuses = new ArrayList<>(); - } - if( DisplayNotificationsFragment.tempNotifications != null) { - DisplayNotificationsFragment.tempNotifications.clear(); - DisplayNotificationsFragment.tempNotifications = new ArrayList<>(); - } - } SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putString(Helper.PREF_KEY_OAUTH_TOKEN, account.getToken()); editor.putString(Helper.PREF_KEY_ID, account.getId()); @@ -967,9 +956,8 @@ public class Helper { final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); final RectF rectF = new RectF(rect); - final float roundPx = roundPixelSize; paint.setAntiAlias(true); - canvas.drawRoundRect(rectF,roundPx,roundPx, paint); + canvas.drawRoundRect(rectF, (float) roundPixelSize, (float) roundPixelSize, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); return output; diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveMissingFeedsInterface.java b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveMissingFeedsInterface.java new file mode 100644 index 000000000..9a1147c43 --- /dev/null +++ b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveMissingFeedsInterface.java @@ -0,0 +1,26 @@ +/* Copyright 2017 Thomas Schneider + * + * This file is a part of Mastalab + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * Mastalab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Mastalab; if not, + * see . */ +package fr.gouv.etalab.mastodon.interfaces; + +import java.util.List; +import fr.gouv.etalab.mastodon.client.Entities.Status; + +/** + * Created by Thomas on 27/09/2017. + * Interface when missing status have been retrieved + */ +public interface OnRetrieveMissingFeedsInterface { + void onRetrieveMissingFeeds(List statuses); +} diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveMissingNotificationsInterface.java b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveMissingNotificationsInterface.java new file mode 100644 index 000000000..4899bb727 --- /dev/null +++ b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveMissingNotificationsInterface.java @@ -0,0 +1,27 @@ +/* Copyright 2017 Thomas Schneider + * + * This file is a part of Mastalab + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * Mastalab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Mastalab; if not, + * see . */ +package fr.gouv.etalab.mastodon.interfaces; + +import java.util.List; + +import fr.gouv.etalab.mastodon.client.Entities.Notification; + +/** + * Created by Thomas on 27/09/2017. + * Interface when missing notifications have been retrieved + */ +public interface OnRetrieveMissingNotificationsInterface { + void onRetrieveMissingNotifications(List notifications); +} diff --git a/app/src/safetynet/java/fr.gouv.etalab.mastodon/activities/MainActivity.java b/app/src/safetynet/java/fr.gouv.etalab.mastodon/activities/MainActivity.java index a16060431..aa5676b52 100644 --- a/app/src/safetynet/java/fr.gouv.etalab.mastodon/activities/MainActivity.java +++ b/app/src/safetynet/java/fr.gouv.etalab.mastodon/activities/MainActivity.java @@ -102,8 +102,6 @@ import fr.gouv.etalab.mastodon.fragments.TabLayoutSettingsFragment; import fr.gouv.etalab.mastodon.sqlite.AccountDAO; import mastodon.etalab.gouv.fr.mastodon.R; -import static fr.gouv.etalab.mastodon.fragments.DisplayNotificationsFragment.tempNotifications; -import static fr.gouv.etalab.mastodon.fragments.DisplayStatusFragment.tempStatuses; import static fr.gouv.etalab.mastodon.helper.Helper.CHANGE_THEME_INTENT; import static fr.gouv.etalab.mastodon.helper.Helper.CHANGE_USER_INTENT; import static fr.gouv.etalab.mastodon.helper.Helper.HOME_TIMELINE_INTENT; @@ -144,7 +142,7 @@ public class MainActivity extends AppCompatActivity public static int countNewNotifications = 0; private String userIdService; private Intent streamingIntent, streamingFederatedIntent; - public static boolean broadCastRegistred = false, broadCastFederatedRegistred = false; + public static String lastHomeId = null, lastNotificationId = null; public MainActivity() { } @@ -157,71 +155,6 @@ public class MainActivity extends AppCompatActivity final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE); - receive_federated_data = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Bundle b = intent.getExtras(); - userIdService = b.getString("userIdService", null); - String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); - if( userIdService != null && userIdService.equals(userId)) { - Status status = b.getParcelable("data"); - if (federatedFragment != null) { - federatedFragment.refresh(status); - } - } - } - }; - receive_data = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Bundle b = intent.getExtras(); - StreamingService.EventStreaming eventStreaming = (StreamingService.EventStreaming) intent.getSerializableExtra("eventStreaming"); - userIdService = b.getString("userIdService", null); - String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); - if( userIdService != null && userIdService.equals(userId)) { - if (eventStreaming == StreamingService.EventStreaming.NOTIFICATION) { - Notification notification = b.getParcelable("data"); - if (notificationsFragment != null) { - notificationsFragment.refresh(notification); - } else { - tempNotifications.add(notification); - } - } else if (eventStreaming == StreamingService.EventStreaming.UPDATE) { - Status status = b.getParcelable("data"); - if (homeFragment != null) { - homeFragment.refresh(status); - } else { - tempStatuses.add(status); - } - } else if (eventStreaming == StreamingService.EventStreaming.DELETE) { - String id = b.getString("id"); - if (notificationsFragment != null) { - if (notificationsFragment.getUserVisibleHint()) { - - } else { - - } - } - } - updateNotifCounter(); - updateHomeCounter(); - } - } - }; - streamingIntent = new Intent(this, StreamingService.class); - startService(streamingIntent); - - - if( !broadCastRegistred) { - LocalBroadcastManager.getInstance(this).registerReceiver(receive_data, new IntentFilter(Helper.RECEIVE_DATA)); - broadCastRegistred = true; - } - if( !broadCastFederatedRegistred) { - LocalBroadcastManager.getInstance(this).registerReceiver(receive_federated_data, new IntentFilter(Helper.RECEIVE_FEDERATED_DATA)); - broadCastFederatedRegistred = true; - } - - ProviderInstaller.installIfNeededAsync(this, this); final int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK); if( theme == Helper.THEME_LIGHT){ @@ -931,10 +864,86 @@ public class MainActivity extends AppCompatActivity //Proceeds to update of the authenticated account if(Helper.isLoggedIn(getApplicationContext())) new UpdateAccountInfoByIDAsyncTask(getApplicationContext(), MainActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + if( lastHomeId != null && homeFragment != null){ + homeFragment.retrieveMissingToots(lastHomeId); + } + if( lastNotificationId != null && notificationsFragment != null){ + notificationsFragment.retrieveMissingNotifications(lastNotificationId); + } } + @Override + public void onStart(){ + super.onStart(); + final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); + receive_federated_data = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Bundle b = intent.getExtras(); + userIdService = b.getString("userIdService", null); + String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); + if( userIdService != null && userIdService.equals(userId)) { + Status status = b.getParcelable("data"); + if (federatedFragment != null) { + federatedFragment.refresh(status); + } + } + } + }; + receive_data = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Bundle b = intent.getExtras(); + StreamingService.EventStreaming eventStreaming = (StreamingService.EventStreaming) intent.getSerializableExtra("eventStreaming"); + userIdService = b.getString("userIdService", null); + String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); + if( userIdService != null && userIdService.equals(userId)) { + if (eventStreaming == StreamingService.EventStreaming.NOTIFICATION) { + Notification notification = b.getParcelable("data"); + if (notificationsFragment != null) { + notificationsFragment.refresh(notification); + } + } else if (eventStreaming == StreamingService.EventStreaming.UPDATE) { + Status status = b.getParcelable("data"); + if (homeFragment != null) { + homeFragment.refresh(status); + } + } else if (eventStreaming == StreamingService.EventStreaming.DELETE) { + String id = b.getString("id"); + if (notificationsFragment != null) { + if (notificationsFragment.getUserVisibleHint()) { + } else { + + } + } + } + updateNotifCounter(); + updateHomeCounter(); + } + } + }; + streamingIntent = new Intent(this, StreamingService.class); + startService(streamingIntent); + streamingFederatedIntent = new Intent(this, StreamingFederatedTimelineService.class); + startService(streamingFederatedIntent); + LocalBroadcastManager.getInstance(this).registerReceiver(receive_data, new IntentFilter(Helper.RECEIVE_DATA)); + LocalBroadcastManager.getInstance(this).registerReceiver(receive_federated_data, new IntentFilter(Helper.RECEIVE_FEDERATED_DATA)); + } + + @Override + public void onStop(){ + super.onStop(); + if( streamingIntent != null) + stopService(streamingIntent); + if( streamingFederatedIntent != null) + stopService(streamingFederatedIntent); + if( receive_data != null) + LocalBroadcastManager.getInstance(this).unregisterReceiver(receive_data); + if( receive_federated_data != null) + LocalBroadcastManager.getInstance(this).unregisterReceiver(receive_federated_data); + } @Override protected void onPause() { @@ -945,14 +954,6 @@ public class MainActivity extends AppCompatActivity @Override public void onDestroy(){ super.onDestroy(); - if( streamingIntent != null) - stopService(streamingIntent); - if( streamingFederatedIntent != null) - stopService(streamingFederatedIntent); - LocalBroadcastManager.getInstance(this).unregisterReceiver(receive_data); - LocalBroadcastManager.getInstance(this).unregisterReceiver(receive_federated_data); - broadCastRegistred = false; - broadCastFederatedRegistred = false; } @SuppressWarnings("StatementWithEmptyBody")