Cache for all home

This commit is contained in:
stom79 2018-11-17 14:31:03 +01:00
parent 07746b2634
commit 37913818ce
10 changed files with 200 additions and 33 deletions

View File

@ -42,6 +42,9 @@
<service
android:name=".services.LiveNotificationService"
android:exported="false"/>
<service
android:name=".services.CacheTootsService"
android:exported="false"/>
<service android:name=".services.BackupStatusService"
android:exported="false"/>
<service android:name=".services.BackupStatusInDataBaseService"

View File

@ -1936,9 +1936,10 @@ public abstract class BaseMainActivity extends BaseActivity
@Override
public void onDestroy(){
super.onDestroy();
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
if( receive_data != null)
LocalBroadcastManager.getInstance(this).unregisterReceiver(receive_data);
SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
boolean backgroundProcess = sharedpreferences.getBoolean(Helper.SET_KEEP_BACKGROUND_PROCESS, true);
if(!backgroundProcess)
sendBroadcast(new Intent("StopLiveNotificationService"));

View File

@ -274,10 +274,13 @@ public class ShowConversationActivity extends BaseActivity implements OnRetriev
@Override
public void onRetrieveContext(Context context, Error error) {
swipeRefreshLayout.setRefreshing(false);
if( error != null){
if( error != null ){
Toast.makeText(getApplicationContext(), error.getError(),Toast.LENGTH_LONG).show();
return;
}
if( context.getAncestors() == null ){
return;
}
statusListAdapter.setConversationPosition( context.getAncestors().size());
if(!expanded) {

View File

@ -25,9 +25,7 @@ import fr.gouv.etalab.mastodon.client.API;
import fr.gouv.etalab.mastodon.client.APIResponse;
import fr.gouv.etalab.mastodon.client.Entities.Peertube;
import fr.gouv.etalab.mastodon.client.Entities.RemoteInstance;
import fr.gouv.etalab.mastodon.client.Entities.Status;
import fr.gouv.etalab.mastodon.helper.FilterToots;
import fr.gouv.etalab.mastodon.helper.Helper;
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface;
import fr.gouv.etalab.mastodon.sqlite.InstancesDAO;
import fr.gouv.etalab.mastodon.sqlite.PeertubeFavoritesDAO;
@ -142,7 +140,14 @@ public class RetrieveFeedsAsyncTask extends AsyncTask<Void, Void, Void> {
SQLiteDatabase db = Sqlite.getInstance(this.contextReference.get(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
switch (action){
case HOME:
apiResponse = api.getHomeTimeline(max_id);
List<fr.gouv.etalab.mastodon.client.Entities.Status> statuses = new StatusCacheDAO(contextReference.get(), db).getAllCachedStatus(max_id);
if( statuses == null || statuses.size() == 0)
apiResponse = api.getHomeTimeline(max_id);
else{
apiResponse = new APIResponse();
apiResponse.setStatuses(statuses);
apiResponse.setMax_id(statuses.get(statuses.size()-1).getId());
}
break;
case LOCAL:
apiResponse = api.getPublicTimeline(true, max_id);
@ -194,7 +199,7 @@ public class RetrieveFeedsAsyncTask extends AsyncTask<Void, Void, Void> {
case CACHE_BOOKMARKS:
apiResponse = new APIResponse();
db = Sqlite.getInstance(contextReference.get(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
List<fr.gouv.etalab.mastodon.client.Entities.Status> statuses = new StatusCacheDAO(contextReference.get(), db).getAllStatus(StatusCacheDAO.BOOKMARK_CACHE);
statuses = new StatusCacheDAO(contextReference.get(), db).getAllStatus(StatusCacheDAO.BOOKMARK_CACHE);
apiResponse.setStatuses(statuses);
break;
case CACHE_BOOKMARKS_PEERTUBE:

View File

@ -15,16 +15,16 @@ package fr.gouv.etalab.mastodon.client;
* see <http://www.gnu.org/licenses>. */
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.*;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
@ -36,10 +36,28 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import fr.gouv.etalab.mastodon.R;
import fr.gouv.etalab.mastodon.client.Entities.*;
import fr.gouv.etalab.mastodon.client.Entities.Account;
import fr.gouv.etalab.mastodon.client.Entities.Application;
import fr.gouv.etalab.mastodon.client.Entities.Attachment;
import fr.gouv.etalab.mastodon.client.Entities.Card;
import fr.gouv.etalab.mastodon.client.Entities.Conversation;
import fr.gouv.etalab.mastodon.client.Entities.Emojis;
import fr.gouv.etalab.mastodon.client.Entities.Error;
import fr.gouv.etalab.mastodon.client.Entities.Filters;
import fr.gouv.etalab.mastodon.client.Entities.HowToVideo;
import fr.gouv.etalab.mastodon.client.Entities.Instance;
import fr.gouv.etalab.mastodon.client.Entities.InstanceSocial;
import fr.gouv.etalab.mastodon.client.Entities.Mention;
import fr.gouv.etalab.mastodon.client.Entities.Notification;
import fr.gouv.etalab.mastodon.client.Entities.Peertube;
import fr.gouv.etalab.mastodon.client.Entities.Relationship;
import fr.gouv.etalab.mastodon.client.Entities.Results;
import fr.gouv.etalab.mastodon.client.Entities.Status;
import fr.gouv.etalab.mastodon.client.Entities.Tag;
import fr.gouv.etalab.mastodon.helper.Helper;
import fr.gouv.etalab.mastodon.services.CacheTootsService;
/**
@ -413,7 +431,7 @@ public class API {
try {
HttpsConnection httpsConnection = new HttpsConnection(context);
String response = httpsConnection.get(getAbsoluteUrl(String.format("/accounts/%s/statuses", accountId)), 60, params, prefKeyOauthTokenT);
statuses = parseStatuses(new JSONArray(response));
statuses = parseStatuses(context, new JSONArray(response));
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
} catch (HttpsConnection.HttpsConnectionException e) {
@ -662,7 +680,7 @@ public class API {
String response = httpsConnection.get(getAbsoluteUrl("/timelines/direct"), 60, params, prefKeyOauthTokenT);
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
statuses = parseStatuses(new JSONArray(response));
statuses = parseStatuses(context, new JSONArray(response));
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
} catch (NoSuchAlgorithmException e) {
@ -731,7 +749,12 @@ public class API {
String response = httpsConnection.get(getAbsoluteUrl("/timelines/home"), 60, params, prefKeyOauthTokenT);
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
statuses = parseStatuses(new JSONArray(response));
statuses = parseStatuses(context, new JSONArray(response));
if( response != null) {
Intent intent = new Intent(context, CacheTootsService.class);
intent.putExtra("response", response);
context.startService(intent);
}
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
} catch (NoSuchAlgorithmException e) {
@ -1023,7 +1046,7 @@ public class API {
String response = httpsConnection.get(url, 60, params, prefKeyOauthTokenT);
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
statuses = parseStatuses(new JSONArray(response));
statuses = parseStatuses(context, new JSONArray(response));
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
} catch (NoSuchAlgorithmException e) {
@ -1080,7 +1103,7 @@ public class API {
String response = httpsConnection.get(getAbsoluteUrl(String.format("/timelines/tag/%s",tag.trim())), 60, params, prefKeyOauthTokenT);
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
statuses = parseStatuses(new JSONArray(response));
statuses = parseStatuses(context, new JSONArray(response));
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
} catch (NoSuchAlgorithmException e) {
@ -1327,7 +1350,7 @@ public class API {
String response = httpsConnection.get(getAbsoluteUrl("/favourites"), 60, params, prefKeyOauthTokenT);
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
statuses = parseStatuses(new JSONArray(response));
statuses = parseStatuses(context, new JSONArray(response));
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
} catch (NoSuchAlgorithmException e) {
@ -2119,7 +2142,7 @@ public class API {
String response = httpsConnection.get(getAbsoluteUrl(String.format("/timelines/list/%s",list_id)), 60, params, prefKeyOauthTokenT);
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
statuses = parseStatuses(new JSONArray(response));
statuses = parseStatuses(context, new JSONArray(response));
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
e.printStackTrace();
@ -2425,7 +2448,7 @@ public class API {
Results results = new Results();
try {
results.setAccounts(parseAccountResponse(resobj.getJSONArray("accounts")));
results.setStatuses(parseStatuses(resobj.getJSONArray("statuses")));
results.setStatuses(parseStatuses(context, resobj.getJSONArray("statuses")));
results.setHashtags(parseTags(resobj.getJSONArray("hashtags")));
} catch (JSONException e) {
setDefaultError(e);
@ -2792,7 +2815,7 @@ public class API {
* @param jsonArray JSONArray
* @return List<Status>
*/
private List<Status> parseStatuses(JSONArray jsonArray){
public static List<Status> parseStatuses(Context context, JSONArray jsonArray){
List<Status> statuses = new ArrayList<>();
try {
@ -2806,7 +2829,7 @@ public class API {
}
} catch (JSONException e) {
setDefaultError(e);
e.printStackTrace();
}
return statuses;
}
@ -3327,8 +3350,8 @@ public class API {
fr.gouv.etalab.mastodon.client.Entities.Context context = new fr.gouv.etalab.mastodon.client.Entities.Context();
try {
context.setAncestors(parseStatuses(jsonObject.getJSONArray("ancestors")));
context.setDescendants(parseStatuses(jsonObject.getJSONArray("descendants")));
context.setAncestors(parseStatuses(this.context, jsonObject.getJSONArray("ancestors")));
context.setDescendants(parseStatuses(this.context, jsonObject.getJSONArray("descendants")));
} catch (JSONException e) {
setDefaultError(e);
}

View File

@ -13,6 +13,7 @@ package fr.gouv.etalab.mastodon.fragments;
*
* You should have received a copy of the GNU General Public License along with Mastalab; if not,
* see <http://www.gnu.org/licenses>. */
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
@ -33,12 +34,14 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import fr.gouv.etalab.mastodon.R;
import fr.gouv.etalab.mastodon.activities.BaseMainActivity;
import fr.gouv.etalab.mastodon.activities.MainActivity;
import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask;
import fr.gouv.etalab.mastodon.asynctasks.RetrieveMissingFeedsAsyncTask;
import fr.gouv.etalab.mastodon.asynctasks.RetrievePeertubeSearchAsyncTask;
import fr.gouv.etalab.mastodon.client.APIResponse;
@ -46,15 +49,14 @@ import fr.gouv.etalab.mastodon.client.Entities.Account;
import fr.gouv.etalab.mastodon.client.Entities.Conversation;
import fr.gouv.etalab.mastodon.client.Entities.Peertube;
import fr.gouv.etalab.mastodon.client.Entities.RemoteInstance;
import fr.gouv.etalab.mastodon.client.Entities.Status;
import fr.gouv.etalab.mastodon.drawers.PeertubeAdapter;
import fr.gouv.etalab.mastodon.drawers.StatusListAdapter;
import fr.gouv.etalab.mastodon.helper.Helper;
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface;
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveMissingFeedsInterface;
import fr.gouv.etalab.mastodon.services.StreamingFederatedTimelineService;
import fr.gouv.etalab.mastodon.services.StreamingLocalTimelineService;
import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask;
import fr.gouv.etalab.mastodon.client.Entities.Status;
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface;
import fr.gouv.etalab.mastodon.sqlite.AccountDAO;
import fr.gouv.etalab.mastodon.sqlite.InstancesDAO;
import fr.gouv.etalab.mastodon.sqlite.Sqlite;
@ -94,6 +96,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
private List<String> mutedAccount;
private String instanceType;
private String search_peertube, remote_channel_name;
private String bookmark;
public DisplayStatusFragment(){
}
@ -204,6 +207,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
if( context instanceof BaseMainActivity){
SharedPreferences.Editor editor = sharedpreferences.edit();
Long bookmarkL = Long.parseLong(statuses.get(firstVisibleItem).getId()) + 1;
bookmark = String.valueOf(bookmarkL);
editor.putString(Helper.BOOKMARK_ID + userId + instance, String.valueOf(bookmarkL));
editor.apply();
}
@ -279,7 +283,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
String bookmark;
if( context instanceof BaseMainActivity){
bookmark = ((BaseMainActivity) context).getBookmark();
asyncTask = new RetrieveFeedsAsyncTask(context, type, bookmark, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
asyncTask = new RetrieveFeedsAsyncTask(context, type, bookmark,DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
firstTootsLoaded = false;
}
@ -310,7 +314,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn
String bookmark;
if( context instanceof BaseMainActivity){
bookmark = ((BaseMainActivity) context).getBookmark();
asyncTask = new RetrieveFeedsAsyncTask(context, type, bookmark, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
asyncTask = new RetrieveFeedsAsyncTask(context, type, bookmark,DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
firstTootsLoaded = false;
}
}else {

View File

@ -1,18 +1,13 @@
package fr.gouv.etalab.mastodon.helper;
import android.app.Activity;
import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
import com.oguzdev.circularfloatingactionmenu.library.FloatingActionButton;
import java.util.ArrayList;

View File

@ -0,0 +1,108 @@
package fr.gouv.etalab.mastodon.services;
/* Copyright 2018 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 <http://www.gnu.org/licenses>. */
import android.app.IntentService;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.Nullable;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.HttpsURLConnection;
import fr.gouv.etalab.mastodon.client.API;
import fr.gouv.etalab.mastodon.client.Entities.Account;
import fr.gouv.etalab.mastodon.client.Entities.Status;
import fr.gouv.etalab.mastodon.helper.Helper;
import fr.gouv.etalab.mastodon.sqlite.Sqlite;
import fr.gouv.etalab.mastodon.sqlite.StatusCacheDAO;
/**
* Created by Thomas on 17/11/2018.
* Manage service for caching status
*/
public class CacheTootsService extends IntentService {
static {
Helper.installProvider();
}
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
@SuppressWarnings("unused")
public CacheTootsService(String name) {
super(name);
}
@SuppressWarnings("unused")
public CacheTootsService() {
super("CacheTootsService");
}
private static HttpsURLConnection httpsURLConnection;
protected Account account;
public void onCreate() {
super.onCreate();
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
if( intent == null || intent.getExtras() == null)
return;
String response = intent.getExtras().getString("response");
String payload = intent.getExtras().getString("payload");
if( payload == null && response == null)
return;
try {
List<Status> statuses;
if( response != null)
statuses = API.parseStatuses(getApplicationContext(), new JSONArray(response));
else {
statuses = new ArrayList<>();
Status status = API.parseStatuses(getApplicationContext(), new JSONObject(payload));
statuses.add(status);
}
SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
List<Status> alreadyCached = new StatusCacheDAO(getApplicationContext(), db).getAllStatus(StatusCacheDAO.STATUS_CACHE);
ArrayList<String> cachedId = new ArrayList<>();
if(alreadyCached != null){
for(Status status: alreadyCached){
cachedId.add(status.getId());
}
}
for(Status status: statuses){
if(!cachedId.contains(status.getId())){
new StatusCacheDAO(getApplicationContext(), db).insertStatus(StatusCacheDAO.STATUS_CACHE, status);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}

View File

@ -239,6 +239,8 @@ public class LiveNotificationService extends Service implements NetworkStateRece
Bundle b = new Bundle();
boolean canSendBroadCast = true;
Helper.EventStreaming event = null;
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
try {
switch (response.get("event").toString()) {
case "notification":
@ -246,11 +248,11 @@ public class LiveNotificationService extends Service implements NetworkStateRece
notification = API.parseNotificationResponse(getApplicationContext(), new JSONObject(response.get("payload").toString()));
b.putParcelable("data", notification);
final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
boolean liveNotifications = sharedpreferences.getBoolean(Helper.SET_LIVE_NOTIFICATIONS, true);
boolean canNotify = Helper.canNotify(getApplicationContext());
boolean notify = sharedpreferences.getBoolean(Helper.SET_NOTIFY, true);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
String targeted_account = null;
Helper.NotifType notifType = Helper.NotifType.MENTION;
boolean activityRunning = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("isMainActivityRunning", false);
@ -373,6 +375,12 @@ public class LiveNotificationService extends Service implements NetworkStateRece
case "update":
event = Helper.EventStreaming.UPDATE;
status = API.parseStatuses(getApplicationContext(), new JSONObject(response.get("payload").toString()));
String instance = Helper.getLiveInstance(getApplicationContext());
if(userId != null && instance != null && userId.equals(account.getId()) && instance.equals(account.getInstance())){
Intent intent = new Intent(getApplicationContext(), CacheTootsService.class);
intent.putExtra("payload",response.get("payload").toString());
startService(intent);
}
status.setNew(true);
b.putParcelable("data", status);
break;

View File

@ -217,6 +217,23 @@ public class StatusCacheDAO {
}
}
/**
* Returns all cached Statuses in db depending prior to max_id
* @return stored status List<StoredStatus>
*/
public List<Status> getAllCachedStatus(String max_id){
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
String instance = Helper.getLiveInstance(context);
try {
Cursor c = db.query(Sqlite.TABLE_STATUSES_CACHE, null, Sqlite.COL_CACHED_ACTION + " = '" + StatusCacheDAO.STATUS_CACHE+ "' AND " + Sqlite.COL_INSTANCE + " = '" + instance+ "' AND " + Sqlite.COL_USER_ID + " = '" + userId+ "' AND " + Sqlite.COL_STATUS_ID +" <= '" + max_id+ "'", null, null, null, Sqlite.COL_STATUS_ID + " DESC", "40");
return cursorToListStatuses(c);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Returns all cached Statuses in db depending of their cache type
* @return stored status List<StoredStatus>