From e1ae2e9c9de6b6872a2bc97c48cceaa37659435a Mon Sep 17 00:00:00 2001 From: tom79 Date: Sat, 25 May 2019 12:37:50 +0200 Subject: [PATCH] Add filters --- .../android/activities/BaseMainActivity.java | 6 + .../asynctasks/RetrieveFeedsAsyncTask.java | 40 ++++- .../java/app/fedilab/android/client/API.java | 28 +++- .../client/Entities/ManageTimelines.java | 32 +++- .../client/Entities/RetrieveFeedsParam.java | 149 ++++++++++++++++++ .../app/fedilab/android/client/GNUAPI.java | 42 ++++- .../fragments/DisplayStatusFragment.java | 11 ++ .../fedilab/android/sqlite/TimelinesDAO.java | 11 ++ 8 files changed, 309 insertions(+), 10 deletions(-) create mode 100644 app/src/main/java/app/fedilab/android/client/Entities/RetrieveFeedsParam.java diff --git a/app/src/main/java/app/fedilab/android/activities/BaseMainActivity.java b/app/src/main/java/app/fedilab/android/activities/BaseMainActivity.java index 633288e2d..1dd29a474 100644 --- a/app/src/main/java/app/fedilab/android/activities/BaseMainActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/BaseMainActivity.java @@ -2062,6 +2062,12 @@ public abstract class BaseMainActivity extends BaseActivity bundle.putString("remote_instance", "peertube.social"); bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE); }else if( tl.getType() == ManageTimelines.Type.INSTANCE){ + if( tl.getRemoteInstance().getFilteredWith() == null){ + bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE); + }else{ + bundle.putString("currentfilter", tl.getRemoteInstance().getFilteredWith()); + bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE_FILTERED); + } bundle.putString("remote_instance", tl.getRemoteInstance().getHost()!=null?tl.getRemoteInstance().getHost():""); bundle.putString("instanceType", tl.getRemoteInstance().getType()); }else if( tl.getType() == ManageTimelines.Type.LIST){ diff --git a/app/src/main/java/app/fedilab/android/asynctasks/RetrieveFeedsAsyncTask.java b/app/src/main/java/app/fedilab/android/asynctasks/RetrieveFeedsAsyncTask.java index 59b6a50bc..b973a4b19 100644 --- a/app/src/main/java/app/fedilab/android/asynctasks/RetrieveFeedsAsyncTask.java +++ b/app/src/main/java/app/fedilab/android/asynctasks/RetrieveFeedsAsyncTask.java @@ -17,6 +17,7 @@ package app.fedilab.android.asynctasks; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.os.AsyncTask; +import android.util.Log; import java.lang.ref.WeakReference; @@ -27,9 +28,11 @@ import app.fedilab.android.client.APIResponse; import app.fedilab.android.client.Entities.ManageTimelines; import app.fedilab.android.client.Entities.Peertube; import app.fedilab.android.client.Entities.RemoteInstance; +import app.fedilab.android.client.Entities.RetrieveFeedsParam; import app.fedilab.android.client.GNUAPI; import app.fedilab.android.client.PeertubeAPI; import app.fedilab.android.helper.FilterToots; +import app.fedilab.android.helper.Helper; import app.fedilab.android.sqlite.InstancesDAO; import app.fedilab.android.sqlite.PeertubeFavoritesDAO; import app.fedilab.android.sqlite.Sqlite; @@ -61,7 +64,9 @@ public class RetrieveFeedsAsyncTask extends AsyncTask { private String instanceName,remoteInstance, name; private boolean cached = false; private int timelineId; - + private String currentfilter; + private String social; + public enum Type{ HOME, LOCAL, @@ -76,6 +81,7 @@ public class RetrieveFeedsAsyncTask extends AsyncTask { CONTEXT, TAG, REMOTE_INSTANCE, + REMOTE_INSTANCE_FILTERED, ART, PEERTUBE, NOTIFICATION, @@ -182,6 +188,22 @@ public class RetrieveFeedsAsyncTask extends AsyncTask { this.action = Type.REMOTE_INSTANCE; } + public RetrieveFeedsAsyncTask(Context context, RetrieveFeedsParam retrieveFeedsParam, OnRetrieveFeedsInterface onRetrieveFeedsInterface){ + this.contextReference = new WeakReference<>(context); + this.listener = onRetrieveFeedsInterface; + this.action = retrieveFeedsParam.getAction(); + this.max_id = retrieveFeedsParam.getMax_id(); + this.targetedID = retrieveFeedsParam.getTargetedID(); + this.tag = retrieveFeedsParam.getTag(); + this.showMediaOnly = retrieveFeedsParam.isShowMediaOnly(); + this.showPinned = retrieveFeedsParam.isShowPinned(); + this.showReply = retrieveFeedsParam.isShowReply(); + this.name = retrieveFeedsParam.getName(); + this.currentfilter = retrieveFeedsParam.getCurrentfilter(); + this.social = retrieveFeedsParam.getSocial(); + } + + @Override protected Void doInBackground(Void... params) { API api = new API(this.contextReference.get()); @@ -207,6 +229,22 @@ public class RetrieveFeedsAsyncTask extends AsyncTask { case CONVERSATION: apiResponse = api.getConversationTimeline(max_id); break; + case REMOTE_INSTANCE_FILTERED: + if( this.social.equals("MASTODON")) { + apiResponse = api.getPublicTimelineTag(this.currentfilter, true, max_id,this.instanceName); + List statusesTemp = apiResponse.getStatuses(); + if( statusesTemp != null){ + for(app.fedilab.android.client.Entities.Status status: statusesTemp){ + status.setType(action); + } + } + } else if(this.social.equals("GNU") ) { + GNUAPI gnuapi = new GNUAPI(this.contextReference.get()); + apiResponse = gnuapi.searchRemote(instanceName,currentfilter,max_id); + }else { + apiResponse = api.searchPeertube(instanceName, currentfilter); + } + break; case REMOTE_INSTANCE: if( this.name != null && this.remoteInstance != null){ //For Peertube channels apiResponse = api.getPeertubeChannelVideos(this.remoteInstance, this.name); diff --git a/app/src/main/java/app/fedilab/android/client/API.java b/app/src/main/java/app/fedilab/android/client/API.java index e6725e0bb..eab897ee2 100644 --- a/app/src/main/java/app/fedilab/android/client/API.java +++ b/app/src/main/java/app/fedilab/android/client/API.java @@ -1287,6 +1287,8 @@ public class API { public APIResponse searchPeertube(String instance, String query) { HashMap params = new HashMap<>(); params.put("count", "50"); + if( query == null) + return null; try { params.put("search", URLEncoder.encode(query, "UTF-8")); } catch (UnsupportedEncodingException e) { @@ -1578,7 +1580,7 @@ public class API { private APIResponse getArtTimeline(boolean local, String tag, String max_id, String since_id, List any, List all, List none){ if( tag == null) tag = "mastoart"; - APIResponse apiResponse = getPublicTimelineTag(tag, local, true, max_id, since_id, tootPerPage, any, all, none); + APIResponse apiResponse = getPublicTimelineTag(tag, local, true, max_id, since_id, tootPerPage, any, all, none, null); APIResponse apiResponseReply = new APIResponse(); if( apiResponse != null){ apiResponseReply.setMax_id(apiResponse.getMax_id()); @@ -1611,7 +1613,19 @@ public class API { */ @SuppressWarnings("SameParameterValue") public APIResponse getPublicTimelineTag(String tag, boolean local, String max_id, List any, List all, List none){ - return getPublicTimelineTag(tag, local, false, max_id, null, tootPerPage, any, all, none); + return getPublicTimelineTag(tag, local, false, max_id, null, tootPerPage, any, all, none, null); + } + + /** + * Retrieves public tag timeline *synchronously* + * @param tag String + * @param local boolean only local timeline + * @param max_id String id max + * @return APIResponse + */ + @SuppressWarnings("SameParameterValue") + public APIResponse getPublicTimelineTag(String tag, boolean local, String max_id, String instance){ + return getPublicTimelineTag(tag, local, false, max_id, null, tootPerPage, null, null, null, instance); } /** @@ -1623,7 +1637,7 @@ public class API { */ @SuppressWarnings("SameParameterValue") public APIResponse getPublicTimelineTagSinceId(String tag, boolean local, String since_id, List any, List all, List none){ - return getPublicTimelineTag(tag, local, false, null, since_id, tootPerPage, any, all, none); + return getPublicTimelineTag(tag, local, false, null, since_id, tootPerPage, any, all, none, null); } /** * Retrieves public tag timeline *synchronously* @@ -1635,7 +1649,7 @@ public class API { * @return APIResponse */ @SuppressWarnings("SameParameterValue") - private APIResponse getPublicTimelineTag(String tag, boolean local, boolean onlymedia, String max_id, String since_id, int limit, List any, List all, List none){ + private APIResponse getPublicTimelineTag(String tag, boolean local, boolean onlymedia, String max_id, String since_id, int limit, List any, List all, List none, String instance){ HashMap params = new HashMap<>(); if( local) @@ -1694,7 +1708,11 @@ public class API { try { query = URLEncoder.encode(query, "UTF-8"); } catch (UnsupportedEncodingException ignored) {} - String response = httpsConnection.get(getAbsoluteUrl(String.format("/timelines/tag/%s",query)), 60, params, prefKeyOauthTokenT); + String response; + if( instance == null) + response = httpsConnection.get(getAbsoluteUrl(String.format("/timelines/tag/%s",query)), 60, params, prefKeyOauthTokenT); + else + response = httpsConnection.get(getAbsoluteUrlRemote(instance, String.format("/timelines/tag/%s",query)), 60, params, null); apiResponse.setSince_id(httpsConnection.getSince_id()); apiResponse.setMax_id(httpsConnection.getMax_id()); statuses = parseStatuses(context, new JSONArray(response)); diff --git a/app/src/main/java/app/fedilab/android/client/Entities/ManageTimelines.java b/app/src/main/java/app/fedilab/android/client/Entities/ManageTimelines.java index 3b0ea46b7..66f8edad7 100644 --- a/app/src/main/java/app/fedilab/android/client/Entities/ManageTimelines.java +++ b/app/src/main/java/app/fedilab/android/client/Entities/ManageTimelines.java @@ -989,7 +989,29 @@ public class ManageTimelines { item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { + FragmentTransaction fragTransaction = ((MainActivity)context).getSupportFragmentManager().beginTransaction(); + DisplayStatusFragment displayStatusFragment = (DisplayStatusFragment) mPageReferenceMap.get(tl.getPosition()); + if( displayStatusFragment == null) + return false; + tl.getRemoteInstance().setFilteredWith(tag); + new InstancesDAO(context, db).updateInstance(remoteInstance); + tl.setRemoteInstance(remoteInstance); + new TimelinesDAO(context, db).updateRemoteInstance(tl); + fragTransaction.detach(displayStatusFragment); + Bundle bundle = new Bundle(); + bundle.putString("remote_instance", tl.getRemoteInstance().getHost()!=null?tl.getRemoteInstance().getHost():""); + bundle.putString("instanceType", tl.getRemoteInstance().getType()); + bundle.putInt("timelineId", tl.getId()); + if( currentFilter == null){ + bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE); + }else{ + bundle.putString("currentfilter", tl.getRemoteInstance().getFilteredWith()); + bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE_FILTERED); + } + displayStatusFragment.setArguments(bundle); + fragTransaction.attach(displayStatusFragment); + fragTransaction.commit(); return false; } }); @@ -1010,8 +1032,12 @@ public class ManageTimelines { bundle.putString("remote_instance", tl.getRemoteInstance().getHost()!=null?tl.getRemoteInstance().getHost():""); bundle.putString("instanceType", tl.getRemoteInstance().getType()); bundle.putInt("timelineId", tl.getId()); - bundle.putString("currentfilter", tl.getRemoteInstance().getFilteredWith()); - bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE); + if( currentFilter == null){ + bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE); + }else{ + bundle.putString("currentfilter", tl.getRemoteInstance().getFilteredWith()); + bundle.putSerializable("type", RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE_FILTERED); + } displayStatusFragment.setArguments(bundle); fragTransaction.attach(displayStatusFragment); fragTransaction.commit(); @@ -1059,7 +1085,7 @@ public class ManageTimelines { remoteInstance.setTags(tags); new InstancesDAO(context, db).updateInstance(remoteInstance); tl.setRemoteInstance(remoteInstance); - new TimelinesDAO(context, db).updateTag(tl); + new TimelinesDAO(context, db).updateRemoteInstance(tl); } }); AlertDialog alertDialog = dialogBuilder.create(); diff --git a/app/src/main/java/app/fedilab/android/client/Entities/RetrieveFeedsParam.java b/app/src/main/java/app/fedilab/android/client/Entities/RetrieveFeedsParam.java new file mode 100644 index 000000000..a1518a5c6 --- /dev/null +++ b/app/src/main/java/app/fedilab/android/client/Entities/RetrieveFeedsParam.java @@ -0,0 +1,149 @@ +package app.fedilab.android.client.Entities; +/* Copyright 2019 Thomas Schneider + * + * This file is a part of Fedilab + * + * 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. + * + * Fedilab 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 Fedilab; if not, + * see . */ + +import app.fedilab.android.asynctasks.RetrieveFeedsAsyncTask; +import app.fedilab.android.helper.FilterToots; + + +public class RetrieveFeedsParam { + + private FilterToots filterToots; + private String max_id; + private RetrieveFeedsAsyncTask.Type action; + private String targetedID; + private String instanceName; + private String tag; + private String currentfilter; + private String remoteInstance; + private int timelineId; + private boolean showMediaOnly; + private boolean showPinned; + private boolean showReply; + private String name; + private String social; + + public FilterToots getFilterToots() { + return filterToots; + } + + public void setFilterToots(FilterToots filterToots) { + this.filterToots = filterToots; + } + + public String getMax_id() { + return max_id; + } + + public void setMax_id(String max_id) { + this.max_id = max_id; + } + + public RetrieveFeedsAsyncTask.Type getAction() { + return action; + } + + public void setAction(RetrieveFeedsAsyncTask.Type action) { + this.action = action; + } + + public String getTargetedID() { + return targetedID; + } + + public void setTargetedID(String targetedID) { + this.targetedID = targetedID; + } + + public String getInstanceName() { + return instanceName; + } + + public void setInstanceName(String instanceName) { + this.instanceName = instanceName; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public int getTimelineId() { + return timelineId; + } + + public void setTimelineId(int timelineId) { + this.timelineId = timelineId; + } + + public boolean isShowMediaOnly() { + return showMediaOnly; + } + + public void setShowMediaOnly(boolean showMediaOnly) { + this.showMediaOnly = showMediaOnly; + } + + public boolean isShowPinned() { + return showPinned; + } + + public void setShowPinned(boolean showPinned) { + this.showPinned = showPinned; + } + + public boolean isShowReply() { + return showReply; + } + + public void setShowReply(boolean showReply) { + this.showReply = showReply; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCurrentfilter() { + return currentfilter; + } + + public void setCurrentfilter(String currentfilter) { + this.currentfilter = currentfilter; + } + + public String getRemoteInstance() { + return remoteInstance; + } + + public void setRemoteInstance(String remoteInstance) { + this.remoteInstance = remoteInstance; + } + + public String getSocial() { + return social; + } + + public void setSocial(String social) { + this.social = social; + } +} diff --git a/app/src/main/java/app/fedilab/android/client/GNUAPI.java b/app/src/main/java/app/fedilab/android/client/GNUAPI.java index 1e34bb0a8..483f6df4c 100644 --- a/app/src/main/java/app/fedilab/android/client/GNUAPI.java +++ b/app/src/main/java/app/fedilab/android/client/GNUAPI.java @@ -1646,6 +1646,44 @@ public class GNUAPI { } + /** + * Retrieves Accounts and feeds when searching *synchronously* + * + * @param query String search + * @return Results + */ + public APIResponse searchRemote(String instance, String query, String max_id) { + HashMap params = new HashMap<>(); + try { + query = URLEncoder.encode(query, "UTF-8"); + } catch (UnsupportedEncodingException ignored) {} + if (max_id != null) + params.put("max_id", max_id); + try { + HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); + String response = httpsConnection.get(getAbsoluteRemoteUrl(instance, "/statusnet/tags/timeline/"+query.trim().toLowerCase().replaceAll("\\#","")+".json"), 60, params, null); + List statuses = parseStatuses(context, new JSONArray(response)); + if( statuses.size() > 0) { + apiResponse.setSince_id(String.valueOf(Long.parseLong(statuses.get(0).getId())+1)); + apiResponse.setMax_id(String.valueOf(Long.parseLong(statuses.get(statuses.size() - 1).getId())-1)); + } + apiResponse.setStatuses(statuses); + } catch (HttpsConnection.HttpsConnectionException e) { + setError(e.getStatusCode(), e); + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (KeyManagementException e) { + e.printStackTrace(); + } catch (JSONException e) { + e.printStackTrace(); + } + return apiResponse; + } + + /** * Retrieves Accounts and feeds when searching *synchronously* * @@ -2359,6 +2397,8 @@ public class GNUAPI { private String getAbsoluteUrl(String action) { return Helper.instanceWithProtocol(this.context, this.instance) + "/api" + action; } - + private String getAbsoluteRemoteUrl(String instance, String action) { + return Helper.instanceWithProtocol(this.context,instance) + "/api" + action; + } } diff --git a/app/src/main/java/app/fedilab/android/fragments/DisplayStatusFragment.java b/app/src/main/java/app/fedilab/android/fragments/DisplayStatusFragment.java index 574fb2756..98db8395a 100644 --- a/app/src/main/java/app/fedilab/android/fragments/DisplayStatusFragment.java +++ b/app/src/main/java/app/fedilab/android/fragments/DisplayStatusFragment.java @@ -50,6 +50,7 @@ import app.fedilab.android.client.Entities.Account; import app.fedilab.android.client.Entities.Conversation; import app.fedilab.android.client.Entities.Peertube; import app.fedilab.android.client.Entities.RemoteInstance; +import app.fedilab.android.client.Entities.RetrieveFeedsParam; import app.fedilab.android.client.Entities.Status; import app.fedilab.android.client.Entities.TagTimeline; import app.fedilab.android.drawers.ArtListAdapter; @@ -126,6 +127,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn private BroadcastReceiver receive_data; private Date lastReadTootDate, initialBookMarkDate, updatedBookMarkDate; private int timelineId; + private String currentfilter; public DisplayStatusFragment(){ } @@ -156,6 +158,7 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn instanceType = bundle.getString("instanceType", "MASTODON"); ischannel = bundle.getBoolean("ischannel",false); timelineId = bundle.getInt("timelineId"); + currentfilter = bundle.getString("currentfilter", null); } if( ischannel) @@ -1008,6 +1011,14 @@ public class DisplayStatusFragment extends Fragment implements OnRetrieveFeedsIn asyncTask = new RetrieveFeedsAsyncTask(context, remoteInstance, remote_channel_name, null, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } else asyncTask = new RetrievePeertubeSearchAsyncTask(context, remoteInstance, search_peertube, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + }else if(type == RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE_FILTERED){ + RetrieveFeedsParam retrieveFeedsParam = new RetrieveFeedsParam(); + retrieveFeedsParam.setAction(type); + retrieveFeedsParam.setCurrentfilter(currentfilter); + retrieveFeedsParam.setRemoteInstance(remoteInstance); + retrieveFeedsParam.setMax_id(max_id); + retrieveFeedsParam.setSocial(instanceType); + asyncTask = new RetrieveFeedsAsyncTask(context, retrieveFeedsParam, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); }else if( type == RetrieveFeedsAsyncTask.Type.LIST){ new ManageListsAsyncTask(context,targetedId, max_id ,null, DisplayStatusFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); }else { diff --git a/app/src/main/java/app/fedilab/android/sqlite/TimelinesDAO.java b/app/src/main/java/app/fedilab/android/sqlite/TimelinesDAO.java index 45b2a14b6..32cb6fece 100644 --- a/app/src/main/java/app/fedilab/android/sqlite/TimelinesDAO.java +++ b/app/src/main/java/app/fedilab/android/sqlite/TimelinesDAO.java @@ -95,6 +95,17 @@ public class TimelinesDAO { new String[]{String.valueOf(timeline.getId())}); } + //------- UPDATE ------- + public void updateRemoteInstance(ManageTimelines timeline) { + ContentValues values = new ContentValues(); + values.put(Sqlite.COL_DISPLAYED, timeline.isDisplayed()); + if( timeline.getTagTimeline() != null) + values.put(Sqlite.COL_REMOTE_INSTANCE, Helper.remoteInstanceToStringStorage(timeline.getRemoteInstance())); + db.update(Sqlite.TABLE_TIMELINES, + values, Sqlite.COL_ID + " = ? ", + new String[]{String.valueOf(timeline.getId())}); + } + public int countVisibleTimelines(){ SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);