From 4f3eac9977df7cfeedfdb0abfbfa46db7b6934e4 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Sun, 18 Dec 2016 15:07:00 +0100 Subject: [PATCH] Allow to jump to last visited page on stream; FIX NullPtr in shared text methods --- .../activity/DiasporaStreamFragment.java | 17 +++++-- .../activity/MainActivity.java | 47 ++++++++++++------- .../data/DiasporaUserProfile.java | 35 +++++++++++++- .../receiver/UpdateTitleReceiver.java | 21 +++++---- .../diaspora_android/util/AppSettings.java | 32 +++++++++---- .../util/DiasporaUrlHelper.java | 10 ++++ .../main/res/values/strings-preferences.xml | 2 +- app/src/main/res/values/strings.xml | 1 + 8 files changed, 125 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/DiasporaStreamFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/DiasporaStreamFragment.java index b2ab2cb3..aacf9836 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/DiasporaStreamFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/DiasporaStreamFragment.java @@ -28,6 +28,7 @@ import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.os.Handler; import android.provider.MediaStore; import android.support.design.widget.Snackbar; import android.view.Menu; @@ -231,7 +232,10 @@ public class DiasporaStreamFragment extends BrowserFragment { protected DiasporaStreamWebChromeClient.SharedTextCallback sharedTextCallback = new DiasporaStreamWebChromeClient.SharedTextCallback() { @Override public String getSharedText() { - return ((MainActivity) getActivity()).getTextToBeShared(); + if(getActivity() != null) { + return ((MainActivity) getActivity()).getTextToBeShared(); + } + return ""; } @Override @@ -328,11 +332,16 @@ public class DiasporaStreamFragment extends BrowserFragment { @SuppressWarnings("unused") @JavascriptInterface public void setUserProfile(final String webMessage) throws JSONException { - DiasporaUserProfile pup = ((App) getActivity().getApplication()).getDiasporaUserProfile(); + final DiasporaUserProfile pup = ((App) getActivity().getApplication()).getDiasporaUserProfile(); AppLog.spam(this, "StreamFragment.JavaScriptInterface.setUserProfile()"); if (pup.isRefreshNeeded()) { AppLog.v(this, "DiasporaUserProfile needs refresh; Try to parse JSON"); pup.parseJson(webMessage); + getActivity().runOnUiThread(new Runnable() { + public void run() { + pup.analyzeUrl(webView.getUrl()); + } + }); } else { AppLog.spam(this, "No DiasporaUserProfile refresh needed"); } @@ -341,7 +350,9 @@ public class DiasporaStreamFragment extends BrowserFragment { @SuppressWarnings("unused") @JavascriptInterface public void contentHasBeenShared() { - ((MainActivity) getActivity()).setTextToBeShared(null); + if (getActivity() != null) { + ((MainActivity) getActivity()).setTextToBeShared(null); + } } } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/MainActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/MainActivity.java index 1683b8f7..007eaa7c 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/MainActivity.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/MainActivity.java @@ -115,8 +115,7 @@ public class MainActivity extends ThemedActivity private final Handler uiHandler = new Handler(); private OpenExternalLinkReceiver brOpenExternalLink; private BroadcastReceiver brSetTitle; - private Snackbar snackbarExitApp; - private Snackbar snackbarNoInternet; + private Snackbar snackbarExitApp, snackbarNoInternet, snackbarLastVisitedTimestampInStream; private FragmentManager fm; private CustomTabsSession customTabsSession; @@ -182,14 +181,15 @@ public class MainActivity extends ThemedActivity brOpenExternalLink = new OpenExternalLinkReceiver(this); brSetTitle = new UpdateTitleReceiver(app, urls, new UpdateTitleReceiver.TitleCallback() { - public void setTitle(int resId) { + public void setTitle(String url, int resId) { CustomFragment top = getTopFragment(); if (top != null && top.getFragmentTag().equals(DiasporaStreamFragment.TAG)) { MainActivity.this.setTitle(resId); + showLastVisitedTimestampMessageIfNeeded(url); } } - public void setTitle(String title) { + public void setTitle(String url, String title) { CustomFragment top = getTopFragment(); if (top != null && top.getFragmentTag().equals(DiasporaStreamFragment.TAG)) { MainActivity.this.setTitle(title); @@ -238,12 +238,17 @@ public class MainActivity extends ThemedActivity snackbarExitApp = Snackbar .make(fragmentContainer, R.string.confirm_exit, Snackbar.LENGTH_LONG) .setAction(android.R.string.yes, new View.OnClickListener() { - @Override public void onClick(View view) { finish(); moveTaskToBack(true); } }); + snackbarLastVisitedTimestampInStream = Snackbar.make(fragmentContainer, R.string.jump_to_last_visited_timestamp_in_stream, Snackbar.LENGTH_SHORT) + .setAction(android.R.string.yes, new View.OnClickListener() { + public void onClick(View view) { + openDiasporaUrl(urls.getStreamWithTimestampUrl(diasporaUserProfile.getLastVisitedPositionInStream())); + } + }); snackbarNoInternet = Snackbar.make(fragmentContainer, R.string.no_internet, Snackbar.LENGTH_LONG); // Load app settings @@ -251,18 +256,6 @@ public class MainActivity extends ThemedActivity AppLog.v(this, "UI successfully set up"); } - /** - * Show DiasporaStreamFragment if necessary and load URL url - * - * @param url URL to load in the DiasporaStreamFragment - */ - public void openDiasporaUrl(String url) { - AppLog.v(this, "openDiasporaUrl()"); - DiasporaStreamFragment streamFragment = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG); - showFragment(streamFragment); - streamFragment.loadUrl(url); - } - /** * Get an instance of the CustomFragment with the tag fragmentTag. * If there was no instance so far, create a new one and add it to the FragmentManagers pool. @@ -305,6 +298,26 @@ public class MainActivity extends ThemedActivity } } + /** + * Show DiasporaStreamFragment if necessary and load URL url + * + * @param url URL to load in the DiasporaStreamFragment + */ + public void openDiasporaUrl(String url) { + AppLog.v(this, "openDiasporaUrl()"); + DiasporaStreamFragment streamFragment = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG); + showFragment(streamFragment); + showLastVisitedTimestampMessageIfNeeded(url); + streamFragment.loadUrl(url); + } + + public void showLastVisitedTimestampMessageIfNeeded(String url){ + if (url.equals(urls.getStreamUrl()) && diasporaUserProfile.hasLastVisitedTimestampInStream()){ + snackbarLastVisitedTimestampInStream.show(); + diasporaUserProfile.resetLastVisitedPositionInStream(); + } + } + /** * Show the Fragment fragment in R.id.fragment_container. If the fragment was already visible, do nothing. * diff --git a/app/src/main/java/com/github/dfa/diaspora_android/data/DiasporaUserProfile.java b/app/src/main/java/com/github/dfa/diaspora_android/data/DiasporaUserProfile.java index 75d9ce99..3393389b 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/data/DiasporaUserProfile.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/data/DiasporaUserProfile.java @@ -18,12 +18,14 @@ */ package com.github.dfa.diaspora_android.data; +import android.net.ParseException; import android.os.Handler; import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.listener.DiasporaUserProfileChangedListener; import com.github.dfa.diaspora_android.util.AppLog; import com.github.dfa.diaspora_android.util.AppSettings; +import com.github.dfa.diaspora_android.util.DiasporaUrlHelper; import org.json.JSONArray; import org.json.JSONException; @@ -40,6 +42,7 @@ public class DiasporaUserProfile { private DiasporaUserProfileChangedListener listener; private final App app; private final AppSettings appSettings; + DiasporaUrlHelper urls; private JSONObject json; private long userProfileLastLoadedTimestamp; private boolean isWebUserProfileLoaded; @@ -51,15 +54,17 @@ public class DiasporaUserProfile { private String[] followedTags; private int notificationCount; private int unreadMessagesCount; + private long lastVisitedPositionInStream = -1; public DiasporaUserProfile(App app) { this.app = app; appSettings = app.getSettings(); + urls = new DiasporaUrlHelper(appSettings); loadFromAppSettings(); } - public void loadFromAppSettings(){ + public void loadFromAppSettings() { avatarUrl = appSettings.getAvatarUrl(); guid = appSettings.getProfileId(); name = appSettings.getName(); @@ -67,6 +72,7 @@ public class DiasporaUserProfile { followedTags = appSettings.getFollowedTags(); notificationCount = appSettings.getNotificationCount(); unreadMessagesCount = appSettings.getUnreadMessageCount(); + lastVisitedPositionInStream = appSettings.getLastVisitedPositionInStream(); } public DiasporaUserProfile(App app, Handler callbackHandler, DiasporaUserProfileChangedListener listener) { @@ -137,6 +143,16 @@ public class DiasporaUserProfile { return isWebUserProfileLoaded; } + public void analyzeUrl(String url) { + String prefix = urls.getPodUrl() + DiasporaUrlHelper.SUBURL_STREAM_WITH_TIMESTAMP; + if (url.startsWith(prefix)) { + try { + setLastVisitedPositionInStream(Long.parseLong(url.replace(prefix, ""))); + } catch (NumberFormatException ignored) { + } + } + } + /* // Getters & Setters */ @@ -169,6 +185,23 @@ public class DiasporaUserProfile { return followedTags; } + public long getLastVisitedPositionInStream() { + return lastVisitedPositionInStream; + } + + public void setLastVisitedPositionInStream(long lastVisitedPositionInStream) { + this.lastVisitedPositionInStream = lastVisitedPositionInStream; + appSettings.setLastVisitedPositionInStream(lastVisitedPositionInStream); + } + + public boolean hasLastVisitedTimestampInStream() { + return appSettings.getLastVisitedPositionInStream() != -1; + } + + public void resetLastVisitedPositionInStream() { + appSettings.setLastVisitedPositionInStream(-1); + } + /* * Private property setters */ diff --git a/app/src/main/java/com/github/dfa/diaspora_android/receiver/UpdateTitleReceiver.java b/app/src/main/java/com/github/dfa/diaspora_android/receiver/UpdateTitleReceiver.java index f5259c64..a4cdaca8 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/receiver/UpdateTitleReceiver.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/receiver/UpdateTitleReceiver.java @@ -38,6 +38,7 @@ public class UpdateTitleReceiver extends BroadcastReceiver { private AppSettings appSettings; private App app; private TitleCallback callback; + private String lastUrl; public UpdateTitleReceiver(App app, DiasporaUrlHelper urls, TitleCallback callback) { this.urls = urls; @@ -48,9 +49,9 @@ public class UpdateTitleReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - String url = intent.getStringExtra(MainActivity.EXTRA_URL); - if (url != null && url.startsWith(urls.getPodUrl())) { - String subUrl = url.substring((urls.getPodUrl()).length()); + lastUrl = intent.getStringExtra(MainActivity.EXTRA_URL); + if (lastUrl != null && lastUrl.startsWith(urls.getPodUrl())) { + String subUrl = lastUrl.substring((urls.getPodUrl()).length()); AppLog.spam(this, "onReceive()- Set title for subUrl " + subUrl); if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_STREAM)) { setTitle(R.string.nav_stream); @@ -74,24 +75,24 @@ public class UpdateTitleReceiver extends BroadcastReceiver { setTitle(R.string.nav_mentions); } else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_PUBLIC)) { setTitle(R.string.public_); - } else if (urls.isAspectUrl(url)) { - setTitle(urls.getAspectNameFromUrl(url, app)); + } else if (urls.isAspectUrl(lastUrl)) { + setTitle(urls.getAspectNameFromUrl(lastUrl, app)); } } else { - AppLog.spam(this, "onReceive()- Invalid url: " + url); + AppLog.spam(this, "onReceive()- Invalid url: " + lastUrl); } } private void setTitle(int rId) { - callback.setTitle(rId); + callback.setTitle(lastUrl, rId); } private void setTitle(String title) { - callback.setTitle(title); + callback.setTitle(lastUrl, title); } public interface TitleCallback { - void setTitle(int resId); - void setTitle(String title); + void setTitle(String url, int resId); + void setTitle(String url, String title); } } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/util/AppSettings.java b/app/src/main/java/com/github/dfa/diaspora_android/util/AppSettings.java index 002e0a6d..3f985e64 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/util/AppSettings.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/util/AppSettings.java @@ -87,6 +87,10 @@ public class AppSettings { pref.edit().putInt(context.getString(keyRessourceId), value).apply(); } + private void setLong(SharedPreferences pref, int keyRessourceId, long value) { + pref.edit().putLong(context.getString(keyRessourceId), value).apply(); + } + private void setBool(SharedPreferences pref, int keyRessourceId, boolean value) { pref.edit().putBoolean(context.getString(keyRessourceId), value).apply(); } @@ -123,11 +127,23 @@ public class AppSettings { private int getInt(SharedPreferences pref, int ressourceId, int defaultValue) { return pref.getInt(context.getString(ressourceId), defaultValue); } + private long getLong(SharedPreferences pref, int ressourceId, long defaultValue) { + return pref.getLong(context.getString(ressourceId), defaultValue); + } + public int getColor(SharedPreferences pref, String key, int defaultColor) { return pref.getInt(key, defaultColor); } + public void registerPrefAppPreferenceChangedListener(SharedPreferences.OnSharedPreferenceChangeListener listener) { + prefApp.registerOnSharedPreferenceChangeListener(listener); + } + + public void unregisterPrefAppPreferenceChangedListener(SharedPreferences.OnSharedPreferenceChangeListener listener) { + prefApp.unregisterOnSharedPreferenceChangeListener(listener); + } + /* // Setters & Getters @@ -396,6 +412,14 @@ public class AppSettings { return getString(prefApp, R.string.pref_key__screen_rotation, R.string.rotation_val_system); } + + public long getLastVisitedPositionInStream(){ + return getLong(prefPod, R.string.pref_key__podprofile_last_stream_position, -1); + } + public void setLastVisitedPositionInStream(long timestamp){ + setLong(prefPod, R.string.pref_key__podprofile_last_stream_position, timestamp); + } + public void setPrimaryColorSettings(int base, int shade) { setInt(prefApp, R.string.pref_key__primary_color_base, base); setInt(prefApp, R.string.pref_key__primary_color_shade, shade); @@ -431,12 +455,4 @@ public class AppSettings { public boolean isExtendedNotificationsActivated() { return getBoolean(prefApp, R.string.pref_key__extended_notifications, false); } - - public void registerPrefAppPreferenceChangedListener(SharedPreferences.OnSharedPreferenceChangeListener listener) { - prefApp.registerOnSharedPreferenceChangeListener(listener); - } - - public void unregisterPrefAppPreferenceChangedListener(SharedPreferences.OnSharedPreferenceChangeListener listener) { - prefApp.unregisterOnSharedPreferenceChangeListener(listener); - } } \ No newline at end of file diff --git a/app/src/main/java/com/github/dfa/diaspora_android/util/DiasporaUrlHelper.java b/app/src/main/java/com/github/dfa/diaspora_android/util/DiasporaUrlHelper.java index 1e0dc582..bbfb53d1 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/util/DiasporaUrlHelper.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/util/DiasporaUrlHelper.java @@ -34,6 +34,7 @@ public class DiasporaUrlHelper { public static final String SUBURL_NOTIFICATIONS = "/notifications"; public static final String SUBURL_POSTS = "/posts/"; public static final String SUBURL_STREAM = "/stream"; + public static final String SUBURL_STREAM_WITH_TIMESTAMP = SUBURL_STREAM+"?max_time="; public static final String SUBURL_CONVERSATIONS = "/conversations"; public static final String SUBURL_NEW_POST = "/status_messages/new"; public static final String SUBURL_PEOPLE = "/people/"; @@ -90,6 +91,15 @@ public class DiasporaUrlHelper { return getPodUrl() + SUBURL_STREAM; } + /** + * Return a url that points to the stream of the configured diaspora account on a timestamp + * + * @return https://(pod-domain.tld)/stream?max_time=1482057867 + */ + public String getStreamWithTimestampUrl(long timestamp) { + return getPodUrl() + SUBURL_STREAM_WITH_TIMESTAMP + timestamp; + } + /** * Return a url that points to the notifications feed of the configured diaspora account * diff --git a/app/src/main/res/values/strings-preferences.xml b/app/src/main/res/values/strings-preferences.xml index 5062d966..0abf23f0 100644 --- a/app/src/main/res/values/strings-preferences.xml +++ b/app/src/main/res/values/strings-preferences.xml @@ -1,7 +1,6 @@ - podDomain pref_key__current_pod_0 pref_key_font_size pref_key_intellihide_toolbars @@ -59,6 +58,7 @@ podUserProfile_followedTags_favs podUserProfile_unreadMessageCount podUserProfile_NotificationCount + podUserProfile_LastStreamPosition pref_key__logging_spam_enabled diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index af8a67f4..8094fa76 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -113,4 +113,5 @@ https Pod address Missing value + Jump to last visited page?