From a086923804a31bbb346364967448caf516c4b453 Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Tue, 20 Sep 2016 21:44:43 +0200 Subject: [PATCH 001/360] Removed newNotificationSnackbar --- .../activity/MainActivity.java | 22 ------------------- 1 file changed, 22 deletions(-) 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 95c9cbbf..5a257e21 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 @@ -139,7 +139,6 @@ public class MainActivity extends AppCompatActivity private OpenExternalLinkReceiver brOpenExternalLink; private BroadcastReceiver brSetTitle; private Snackbar snackbarExitApp; - private Snackbar snackbarNewNotification; private Snackbar snackbarNoInternet; private String textToBeShared = null; @@ -266,18 +265,6 @@ public class MainActivity extends AppCompatActivity moveTaskToBack(true); } }); - snackbarNewNotification = Snackbar - .make(contentLayout, R.string.new_notifications, Snackbar.LENGTH_LONG) - .setAction(android.R.string.yes, new View.OnClickListener() { - @Override - public void onClick(View view) { - if (WebHelper.isOnline(MainActivity.this)) { - webView.loadUrlNew(urls.getNotificationsUrl()); - } else { - Snackbar.make(contentLayout, R.string.no_internet, Snackbar.LENGTH_LONG).show(); - } - } - }); snackbarNoInternet = Snackbar.make(contentLayout, R.string.no_internet, Snackbar.LENGTH_LONG); // Load app settings @@ -1082,11 +1069,6 @@ public class MainActivity extends AppCompatActivity AppLog.i(this, "onNotificationCountChanged()"); // Count saved in PodUserProfile invalidateOptionsMenu(); - - if (notificationCount > 0 && !snackbarNewNotification.isShown() - && !webView.getUrl().equals(urls.getNotificationsUrl())) { - snackbarNewNotification.show(); - } } // TODO: Move from Javascript interface @@ -1095,10 +1077,6 @@ public class MainActivity extends AppCompatActivity AppLog.i(this, "onUnreadMessageCountChanged()"); // Count saved in PodUserProfile invalidateOptionsMenu(); - if (unreadMessageCount > 0 && !snackbarNewNotification.isShown() - && !webView.getUrl().equals(urls.getNotificationsUrl())) { - snackbarNewNotification.show(); - } } private class JavaScriptInterface { From b12e021e99a15be07c928613c2afae0ccae4693b Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Tue, 20 Sep 2016 23:55:50 +0200 Subject: [PATCH 002/360] Update AppSettings.java --- .../java/com/github/dfa/diaspora_android/data/AppSettings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/github/dfa/diaspora_android/data/AppSettings.java b/app/src/main/java/com/github/dfa/diaspora_android/data/AppSettings.java index b8135e86..da5839c9 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/data/AppSettings.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/data/AppSettings.java @@ -253,7 +253,7 @@ public class AppSettings { } public boolean isIntellihideToolbars() { - return getBoolean(prefApp, R.string.pref_key__intellihide_toolbars, true); + return getBoolean(prefApp, R.string.pref_key__intellihide_toolbars, false); } public boolean isChromeCustomTabsEnabled() { From 52d6947d3e26ce04fede997fc04b91798d5f740c Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Wed, 21 Sep 2016 12:36:42 +0200 Subject: [PATCH 003/360] Refactor layout file names --- .../activity/AboutActivity.java | 8 ++--- .../activity/MainActivity.java | 6 ++-- .../activity/PodSelectionActivity.java | 2 +- .../receivers/UpdateTitleReceiver.java | 2 +- .../CustomTabActivityHelper.java | 2 +- ...activity_about.xml => about__activity.xml} | 0 ...nt_about.xml => about__fragment_about.xml} | 0 ...nt_debug.xml => about__fragment_debug.xml} | 0 ...icense.xml => about__fragment_license.xml} | 0 ...xml => ui__dialog_search__people_tags.xml} | 0 .../layout/{webview.xml => ui__webview.xml} | 0 ...{pods__menu.xml => podselection__menu.xml} | 0 .../main/res/values/strings-preferences.xml | 2 ++ app/src/main/res/xml/preferences.xml | 35 +++++++++++-------- 14 files changed, 32 insertions(+), 25 deletions(-) rename app/src/main/res/layout/{activity_about.xml => about__activity.xml} (100%) rename app/src/main/res/layout/{fragment_about.xml => about__fragment_about.xml} (100%) rename app/src/main/res/layout/{fragment_debug.xml => about__fragment_debug.xml} (100%) rename app/src/main/res/layout/{fragment_license.xml => about__fragment_license.xml} (100%) rename app/src/main/res/layout/{dialog_search__people_tags.xml => ui__dialog_search__people_tags.xml} (100%) rename app/src/main/res/layout/{webview.xml => ui__webview.xml} (100%) rename app/src/main/res/menu/{pods__menu.xml => podselection__menu.xml} (100%) diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/AboutActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/AboutActivity.java index 492dcc55..f2c46bdd 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/AboutActivity.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/AboutActivity.java @@ -71,7 +71,7 @@ public class AboutActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_about); + setContentView(R.layout.about__activity); ButterKnife.bind(this); setSupportActionBar(toolbar); @@ -111,7 +111,7 @@ public class AboutActivity extends AppCompatActivity { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_about, container, false); + View rootView = inflater.inflate(R.layout.about__fragment_about, container, false); TextView appVersion = (TextView) rootView.findViewById(R.id.fragment_about__app_version); if (isAdded()) { @@ -143,7 +143,7 @@ public class AboutActivity extends AppCompatActivity { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_license, container, false); + View rootView = inflater.inflate(R.layout.about__fragment_license, container, false); ButterKnife.bind(this, rootView); final Context context = rootView.getContext(); accentColor = Helpers.hexColorFromRessourceColor(context, R.color.colorAccent); @@ -201,7 +201,7 @@ public class AboutActivity extends AppCompatActivity { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.fragment_debug, container, false); + View rootView = inflater.inflate(R.layout.about__fragment_debug, container, false); TextView packageName = (TextView) rootView.findViewById(R.id.fragment_debug__package_name); TextView appVersion = (TextView) rootView.findViewById(R.id.fragment_debug__app_version); TextView osVersion = (TextView) rootView.findViewById(R.id.fragment_debug__android_version); 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 5a257e21..c736489e 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 @@ -235,7 +235,7 @@ public class MainActivity extends AppCompatActivity boolean newWebView = (webView == null); if (newWebView) { AppLog.v(this, "WebView was null. Create new one."); - View webviewHolder = getLayoutInflater().inflate(R.layout.webview, this.contentLayout, false); + View webviewHolder = getLayoutInflater().inflate(R.layout.ui__webview, this.contentLayout, false); this.webView = (ContextMenuWebView) webviewHolder.findViewById(R.id.webView); ((LinearLayout) webView.getParent()).removeView(webView); setupWebView(savedInstanceState); @@ -840,7 +840,7 @@ public class MainActivity extends AppCompatActivity if (WebHelper.isOnline(MainActivity.this)) { final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - View layout = getLayoutInflater().inflate(R.layout.dialog_search__people_tags, null, false); + View layout = getLayoutInflater().inflate(R.layout.ui__dialog_search__people_tags, null, false); final EditText input = (EditText) layout.findViewById(R.id.dialog_search__input); final DialogInterface.OnClickListener clickListener = new DialogInterface.OnClickListener() { @Override @@ -1249,7 +1249,7 @@ public class MainActivity extends AppCompatActivity AppLog.v(this, "Apply NetCipher proxy settings"); NetCipher.setProxy(host, port); //Proxy for HttpsUrlConnections try { - //Proxy for the webview + //Proxy for the ui__webview AppLog.v(this, "Apply Webkit proxy settings"); WebkitProxy.setProxy(MainActivity.class.getName(), getApplicationContext(), null, host, port); } catch (Exception e) { diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionActivity.java index ec307c92..9729b8e4 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionActivity.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionActivity.java @@ -224,7 +224,7 @@ public class PodSelectionActivity extends AppCompatActivity { @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.pods__menu, menu); + getMenuInflater().inflate(R.menu.podselection__menu, menu); return true; } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/receivers/UpdateTitleReceiver.java b/app/src/main/java/com/github/dfa/diaspora_android/receivers/UpdateTitleReceiver.java index c722baac..10ddc5f5 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/receivers/UpdateTitleReceiver.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/receivers/UpdateTitleReceiver.java @@ -12,7 +12,7 @@ import com.github.dfa.diaspora_android.util.AppLog; import com.github.dfa.diaspora_android.util.DiasporaUrlHelper; /** - * BroadcastReceiver used to update the title of the MainActivity depending on the url of the webview + * BroadcastReceiver used to update the title of the MainActivity depending on the url of the ui__webview * Created by vanitas on 11.09.16. */ public class UpdateTitleReceiver extends BroadcastReceiver { diff --git a/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/CustomTabActivityHelper.java b/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/CustomTabActivityHelper.java index 9e14c748..e43ce0b0 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/CustomTabActivityHelper.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/CustomTabActivityHelper.java @@ -37,7 +37,7 @@ public class CustomTabActivityHelper { String packageName = CustomTabsHelper.getPackageNameToUse(activity); //If we cant find a package name, it means there's no browser that supports - //Chrome Custom Tabs installed. So, we fallback to the webview + //Chrome Custom Tabs installed. So, we fallback to the ui__webview if (packageName == null) { if (fallback != null) { fallback.openUri(activity, uri); diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/about__activity.xml similarity index 100% rename from app/src/main/res/layout/activity_about.xml rename to app/src/main/res/layout/about__activity.xml diff --git a/app/src/main/res/layout/fragment_about.xml b/app/src/main/res/layout/about__fragment_about.xml similarity index 100% rename from app/src/main/res/layout/fragment_about.xml rename to app/src/main/res/layout/about__fragment_about.xml diff --git a/app/src/main/res/layout/fragment_debug.xml b/app/src/main/res/layout/about__fragment_debug.xml similarity index 100% rename from app/src/main/res/layout/fragment_debug.xml rename to app/src/main/res/layout/about__fragment_debug.xml diff --git a/app/src/main/res/layout/fragment_license.xml b/app/src/main/res/layout/about__fragment_license.xml similarity index 100% rename from app/src/main/res/layout/fragment_license.xml rename to app/src/main/res/layout/about__fragment_license.xml diff --git a/app/src/main/res/layout/dialog_search__people_tags.xml b/app/src/main/res/layout/ui__dialog_search__people_tags.xml similarity index 100% rename from app/src/main/res/layout/dialog_search__people_tags.xml rename to app/src/main/res/layout/ui__dialog_search__people_tags.xml diff --git a/app/src/main/res/layout/webview.xml b/app/src/main/res/layout/ui__webview.xml similarity index 100% rename from app/src/main/res/layout/webview.xml rename to app/src/main/res/layout/ui__webview.xml diff --git a/app/src/main/res/menu/pods__menu.xml b/app/src/main/res/menu/podselection__menu.xml similarity index 100% rename from app/src/main/res/menu/pods__menu.xml rename to app/src/main/res/menu/podselection__menu.xml diff --git a/app/src/main/res/values/strings-preferences.xml b/app/src/main/res/values/strings-preferences.xml index 9e367342..fe4e728b 100644 --- a/app/src/main/res/values/strings-preferences.xml +++ b/app/src/main/res/values/strings-preferences.xml @@ -81,6 +81,8 @@ Disable image loading to safe mobile data + Proxy + @string/pref_desc__proxy_enabled Enable Proxy Proxy Diaspora\'s traffic to circumvent firewalls.\nMay require restart Host diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 6c6308a3..4bbc7b4c 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -125,21 +125,26 @@ android:summary="@string/pref_desc__clear_cache" android:title="@string/pref_title__clear_cache"/> - - - + + + + + + From c94a511ace64d547cebb768c72069f01fc7a3d47 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Wed, 21 Sep 2016 15:03:54 +0200 Subject: [PATCH 004/360] Proxy tor preset --- .../activity/SettingsActivity.java | 20 ++++++--- .../diaspora_android/data/AppSettings.java | 17 +++++--- app/src/main/res/drawable/tor_onion.xml | 13 ++++++ .../res/values-de/strings-preferences.xml | 6 +-- .../res/values-es/strings-preferences.xml | 6 +-- .../res/values-fr/strings-preferences.xml | 6 +-- .../res/values-it/strings-preferences.xml | 6 +-- .../res/values-ja/strings-preferences.xml | 6 +-- .../res/values-ml/strings-preferences.xml | 6 +-- .../res/values-nl/strings-preferences.xml | 6 +-- .../res/values-pt-rBR/strings-preferences.xml | 6 +-- .../res/values-ru/strings-preferences.xml | 6 +-- .../main/res/values/strings-preferences.xml | 19 +++++--- app/src/main/res/xml/preferences.xml | 43 ++++++++++++------- 14 files changed, 106 insertions(+), 60 deletions(-) create mode 100644 app/src/main/res/drawable/tor_onion.xml diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/SettingsActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/SettingsActivity.java index 88f13171..a1af7b9d 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/SettingsActivity.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/SettingsActivity.java @@ -78,12 +78,12 @@ public class SettingsActivity extends AppCompatActivity { sharedPreferences.registerOnSharedPreferenceChangeListener(this); setPreferenceSummaries(); sharedPreferences.edit().putBoolean(getString(R.string.pref_key__proxy_was_enabled), - sharedPreferences.getBoolean(getString(R.string.pref_key__proxy_enabled), false)).apply(); + sharedPreferences.getBoolean(getString(R.string.pref_key__http_proxy_enabled), false)).apply(); } private void setPreferenceSummaries() { String[] editTextKeys = new String[]{ - getString(R.string.pref_key__proxy_host), getString(R.string.pref_key__proxy_port) + getString(R.string.pref_key__http_proxy_host), getString(R.string.pref_key__http_proxy_port) }; for (String key : editTextKeys) { EditTextPreference p = (EditTextPreference) findPreference(key); @@ -98,9 +98,9 @@ public class SettingsActivity extends AppCompatActivity { key.equals(getString(R.string.pref_key__font_size)) || key.equals(getString(R.string.pref_key__load_images)) || key.equals(getString(R.string.pref_key__intellihide_toolbars)) || - key.equals(getString(R.string.pref_key__proxy_enabled)) || - key.equals(getString(R.string.pref_key__proxy_host)) || - key.equals(getString(R.string.pref_key__proxy_port)) || + key.equals(getString(R.string.pref_key__http_proxy_enabled)) || + key.equals(getString(R.string.pref_key__http_proxy_host)) || + key.equals(getString(R.string.pref_key__http_proxy_port)) || key.startsWith("pref_key__visibility_nav__"))) { ((SettingsActivity) getActivity()).setActivityRestartRequired(); } @@ -123,8 +123,11 @@ public class SettingsActivity extends AppCompatActivity { @Override public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) { + App app = ((App) getActivity().getApplication()); + AppSettings appSettings = app.getSettings(); Intent intent = new Intent(getActivity(), MainActivity.class); - String podDomain = ((App) getActivity().getApplication()).getSettings().getPodDomain(); + String podDomain = appSettings.getPodDomain(); + switch (preference.getTitleRes()) { case R.string.pref_title__personal_settings: { intent.setAction(MainActivity.ACTION_OPEN_URL); @@ -158,6 +161,11 @@ public class SettingsActivity extends AppCompatActivity { .show(); return true; } + case R.string.pref_title__http_proxy_load_tor_preset: { + ((EditTextPreference)findPreference(getString(R.string.pref_key__http_proxy_host))).setText("127.0.0.1"); + ((EditTextPreference)findPreference(getString(R.string.pref_key__http_proxy_port))).setText("8118"); + return true; + } default: { intent = null; diff --git a/app/src/main/java/com/github/dfa/diaspora_android/data/AppSettings.java b/app/src/main/java/com/github/dfa/diaspora_android/data/AppSettings.java index da5839c9..8d0160dd 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/data/AppSettings.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/data/AppSettings.java @@ -202,7 +202,7 @@ public class AppSettings { @SuppressLint("CommitPrefEdits") public void setProxyEnabled(boolean enabled) { //commit instead of apply because the app is likely to be killed before apply is called. - prefApp.edit().putBoolean(context.getString(R.string.pref_key__proxy_enabled), enabled).commit(); + prefApp.edit().putBoolean(context.getString(R.string.pref_key__http_proxy_enabled), enabled).commit(); } /** @@ -211,7 +211,7 @@ public class AppSettings { * @return whether proxy is enabled or not */ public boolean isProxyEnabled() { - return getBoolean(prefApp, R.string.pref_key__proxy_enabled, false); + return getBoolean(prefApp, R.string.pref_key__http_proxy_enabled, false); } public boolean wasProxyEnabled() { @@ -235,9 +235,12 @@ public class AppSettings { * @return proxy host */ public String getProxyHost() { - return getString(prefApp, R.string.pref_key__proxy_host, ""); + return getString(prefApp, R.string.pref_key__http_proxy_host, ""); } + public void setProxyHttpHost(String value) { + setString(prefApp, R.string.pref_key__http_proxy_host, value); + } /** * Default value: 0 * @@ -245,13 +248,17 @@ public class AppSettings { */ public int getProxyPort() { try { - return Integer.parseInt(getString(prefApp, R.string.pref_key__proxy_port, "0")); + return Integer.parseInt(getString(prefApp, R.string.pref_key__http_proxy_port, "0")); } catch (Exception e) { - setString(prefApp, R.string.pref_key__proxy_port, "0"); + setString(prefApp, R.string.pref_key__http_proxy_port, "0"); return 0; } } + public void setProxyHttpPort(int value) { + setInt(prefApp, R.string.pref_key__http_proxy_port, value); + } + public boolean isIntellihideToolbars() { return getBoolean(prefApp, R.string.pref_key__intellihide_toolbars, false); } diff --git a/app/src/main/res/drawable/tor_onion.xml b/app/src/main/res/drawable/tor_onion.xml new file mode 100644 index 00000000..7df39ce0 --- /dev/null +++ b/app/src/main/res/drawable/tor_onion.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/values-de/strings-preferences.xml b/app/src/main/res/values-de/strings-preferences.xml index ed3586f7..c629a28e 100644 --- a/app/src/main/res/values-de/strings-preferences.xml +++ b/app/src/main/res/values-de/strings-preferences.xml @@ -22,9 +22,9 @@ Deaktiviere das Laden von Bildern, um den Datenverbrauch zu verringern Aktiviere Netzwerkproxy - Nutze einen Proxyserver, um Firewalls zu umgehen - Host - Port + Nutze einen Proxyserver, um Firewalls zu umgehen + Host + Port Chrome Custom Tabs Externe Links mit Chrome Custom Tabs öffnen. Für dieses Feature muss Chromium oder Google Chrome installiert sein diff --git a/app/src/main/res/values-es/strings-preferences.xml b/app/src/main/res/values-es/strings-preferences.xml index 6a6b67c1..9cab7553 100644 --- a/app/src/main/res/values-es/strings-preferences.xml +++ b/app/src/main/res/values-es/strings-preferences.xml @@ -22,9 +22,9 @@ Desactivar la carga de de imágenes a datos móviles seguros Activar Proxy - El tráfico proxificado de Diaspora para evitar firewalls.\nPuede necesitar reiniciarse - Anfitrión - Puerto + El tráfico proxificado de Diaspora para evitar firewalls.\nPuede necesitar reiniciarse + Anfitrión + Puerto Configuración personal diff --git a/app/src/main/res/values-fr/strings-preferences.xml b/app/src/main/res/values-fr/strings-preferences.xml index 48b8d71d..2ff27c03 100644 --- a/app/src/main/res/values-fr/strings-preferences.xml +++ b/app/src/main/res/values-fr/strings-preferences.xml @@ -22,9 +22,9 @@ Désactiver le chargements des images pour préserver la data mobile Activer Proxy - Serveur Proxy.\n(Nécessite un redémarrage) - Hôte - Port + Serveur Proxy.\n(Nécessite un redémarrage) + Hôte + Port Onglets personnalisés de Chrome Ouvrir les liens externes avec les onglets personnalisés. Chromium ou Google Chrome doit être installé pour cette fonctionnalité diff --git a/app/src/main/res/values-it/strings-preferences.xml b/app/src/main/res/values-it/strings-preferences.xml index 01fbf921..7ace8cf5 100644 --- a/app/src/main/res/values-it/strings-preferences.xml +++ b/app/src/main/res/values-it/strings-preferences.xml @@ -22,9 +22,9 @@ Disabilita il caricamento delle immagini per risparmiare la rete dati Attiva proxy - Traffico del proxy di Diaspora per bypassare i firewall.\nPuò essere necessario il riavvio dell\'app - Host - Porta + Traffico del proxy di Diaspora per bypassare i firewall.\nPuò essere necessario il riavvio dell\'app + Host + Porta Impostazioni personali diff --git a/app/src/main/res/values-ja/strings-preferences.xml b/app/src/main/res/values-ja/strings-preferences.xml index 909ff218..de7154e6 100644 --- a/app/src/main/res/values-ja/strings-preferences.xml +++ b/app/src/main/res/values-ja/strings-preferences.xml @@ -22,9 +22,9 @@ 安全なモバイルデータのため、画像の読み込みを無効にします プロキシを有効にする - Diaspora の通信をプロキシして、ファイアウォールに回避します。\n再起動が必要になることがあります - ホスト - ポート + Diaspora の通信をプロキシして、ファイアウォールに回避します。\n再起動が必要になることがあります + ホスト + ポート Chrome カスタムタブ Chrome カスタム タブで外部リンクを開きます。この機能は Chromium または Google Chrome をインストールする必要があります diff --git a/app/src/main/res/values-ml/strings-preferences.xml b/app/src/main/res/values-ml/strings-preferences.xml index 390a9139..decc542a 100644 --- a/app/src/main/res/values-ml/strings-preferences.xml +++ b/app/src/main/res/values-ml/strings-preferences.xml @@ -22,9 +22,9 @@ മൊബൈൽ ഡാറ്റ ഉപഭോഗം കുറയ്ക്കാനായി ചിത്രങ്ങൾ ലോഡ് ചെയ്യാതിരിക്കുക പ്രോക്സി അനുവദിക്കൂ - ഫയർവാളുകളെ മറികടക്കാൻ ഡയസ്പോറ ട്രാഫിക് പ്രോക്സി ചെയ്യൂ.\nപുനരാരംഭിക്കേണ്ടി വന്നേക്കാം - ആഥിതേയൻ - പോർട്ട് + ഫയർവാളുകളെ മറികടക്കാൻ ഡയസ്പോറ ട്രാഫിക് പ്രോക്സി ചെയ്യൂ.\nപുനരാരംഭിക്കേണ്ടി വന്നേക്കാം + ആഥിതേയൻ + പോർട്ട് സ്വകാര്യ സജ്ജീകരണങ്ങൾ diff --git a/app/src/main/res/values-nl/strings-preferences.xml b/app/src/main/res/values-nl/strings-preferences.xml index 47b807ca..8526b891 100644 --- a/app/src/main/res/values-nl/strings-preferences.xml +++ b/app/src/main/res/values-nl/strings-preferences.xml @@ -21,9 +21,9 @@ Afbeelding laden uitschakelen om mobiele data te besparen Proxy inschakelen - Gebruik een Proxy voor Diaspora om de firewalls te omzeilen.\nRestart nodig - Host - Poort + Gebruik een Proxy voor Diaspora om de firewalls te omzeilen.\nRestart nodig + Host + Poort Persoonlijke instellingen diff --git a/app/src/main/res/values-pt-rBR/strings-preferences.xml b/app/src/main/res/values-pt-rBR/strings-preferences.xml index ee8eebc8..1fbd4608 100644 --- a/app/src/main/res/values-pt-rBR/strings-preferences.xml +++ b/app/src/main/res/values-pt-rBR/strings-preferences.xml @@ -22,9 +22,9 @@ Desabilitar o carregamento de imagens para economizar seus créditos Habilitar o Proxy - Usar proxy para o tráfego da diáspora para contornar firewalls.\nPode requerer reinicialização - Servidor - Porta + Usar proxy para o tráfego da diáspora para contornar firewalls.\nPode requerer reinicialização + Servidor + Porta Configurações pessoais diff --git a/app/src/main/res/values-ru/strings-preferences.xml b/app/src/main/res/values-ru/strings-preferences.xml index 3bc04e85..0b924029 100644 --- a/app/src/main/res/values-ru/strings-preferences.xml +++ b/app/src/main/res/values-ru/strings-preferences.xml @@ -22,9 +22,9 @@ Отключить загрузку изображений для экономии траффика Использовать прокси - Перенаправить трафик Диаспоры в обход брандмауэров.\nМожет потребовать перезапуска - Хост - Порт + Перенаправить трафик Диаспоры в обход брандмауэров.\nМожет потребовать перезапуска + Хост + Порт Личные настройки diff --git a/app/src/main/res/values/strings-preferences.xml b/app/src/main/res/values/strings-preferences.xml index fe4e728b..225eb33b 100644 --- a/app/src/main/res/values/strings-preferences.xml +++ b/app/src/main/res/values/strings-preferences.xml @@ -15,11 +15,12 @@ pref_key_load_images pref_key_clear_cache pref_key__chrome_custom_tabs_enabled + pref_key__http_proxy_load_tor_preset pref_key_append_shared_via_app - pref_key_proxy_enabled - pref_key_proxy_host - pref_key_proxy_port + pref_key_proxy_enabled + pref_key_proxy_host + pref_key_proxy_port wasProxyEnabled @@ -81,12 +82,16 @@ Disable image loading to safe mobile data + Load Tor Preset + Load proxy settings for Tor (Orbot) HTTP Proxy Proxy - @string/pref_desc__proxy_enabled + @string/pref_desc__http_proxy_enabled Enable Proxy - Proxy Diaspora\'s traffic to circumvent firewalls.\nMay require restart - Host - Port + Proxy Diaspora\'s traffic to circumvent firewalls.\nMay require restart + Host + Port + HTTP + SOCKS5 diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 4bbc7b4c..fca5961e 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -129,21 +129,34 @@ - - - + + + + + + + + + + From b2337b195568d18ba3d24f97021841a3e2dfa454 Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Wed, 21 Sep 2016 21:15:34 +0200 Subject: [PATCH 005/360] Moved WebView in own fragments. There is still a bug, where the webview cannot be returned for some reason. --- .../activity/AboutActivity.java | 2 +- .../activity/MainActivity.java | 575 +++--------------- .../activity/PodSelectionActivity.java | 2 +- .../fragment/CustomFragment.java | 33 + .../fragment/StreamFragment.java | 141 +++++ .../fragment/WebViewFragment.java | 430 +++++++++++++ .../OpenExternalLinkReceiver.java | 4 +- .../UpdateTitleReceiver.java | 2 +- app/src/main/res/layout/about__activity.xml | 2 +- app/src/main/res/layout/main__activity.xml | 2 +- app/src/main/res/layout/main__app_bar.xml | 9 +- .../res/layout/podselection__activity.xml | 2 +- ...main__content.xml => stream__fragment.xml} | 11 +- app/src/main/res/menu/main__menu_bottom.xml | 27 +- app/src/main/res/menu/main__menu_top.xml | 15 +- app/src/main/res/menu/stream__menu_bottom.xml | 23 + app/src/main/res/menu/stream__menu_top.xml | 12 + build.gradle | 2 +- 18 files changed, 764 insertions(+), 530 deletions(-) create mode 100644 app/src/main/java/com/github/dfa/diaspora_android/fragment/CustomFragment.java create mode 100644 app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java create mode 100644 app/src/main/java/com/github/dfa/diaspora_android/fragment/WebViewFragment.java rename app/src/main/java/com/github/dfa/diaspora_android/{receivers => receiver}/OpenExternalLinkReceiver.java (94%) rename app/src/main/java/com/github/dfa/diaspora_android/{receivers => receiver}/UpdateTitleReceiver.java (98%) rename app/src/main/res/layout/{main__content.xml => stream__fragment.xml} (80%) create mode 100644 app/src/main/res/menu/stream__menu_bottom.xml create mode 100644 app/src/main/res/menu/stream__menu_top.xml diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/AboutActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/AboutActivity.java index f2c46bdd..4d8e2ecd 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/AboutActivity.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/AboutActivity.java @@ -62,7 +62,7 @@ public class AboutActivity extends AppCompatActivity { private SectionsPagerAdapter mSectionsPagerAdapter; private ViewPager mViewPager; - @BindView(R.id.toolbar) + @BindView(R.id.main__topbar) protected Toolbar toolbar; @BindView(R.id.linearlayout) 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 c736489e..8e113f13 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 @@ -45,6 +45,8 @@ import android.support.annotation.NonNull; import android.support.design.widget.AppBarLayout; import android.support.design.widget.NavigationView; import android.support.design.widget.Snackbar; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; import android.support.v4.content.LocalBroadcastManager; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; @@ -69,7 +71,6 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; -import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; @@ -77,9 +78,11 @@ import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.data.AppSettings; import com.github.dfa.diaspora_android.data.PodUserProfile; +import com.github.dfa.diaspora_android.fragment.CustomFragment; +import com.github.dfa.diaspora_android.fragment.StreamFragment; import com.github.dfa.diaspora_android.listener.WebUserProfileChangedListener; -import com.github.dfa.diaspora_android.receivers.OpenExternalLinkReceiver; -import com.github.dfa.diaspora_android.receivers.UpdateTitleReceiver; +import com.github.dfa.diaspora_android.receiver.OpenExternalLinkReceiver; +import com.github.dfa.diaspora_android.receiver.UpdateTitleReceiver; import com.github.dfa.diaspora_android.ui.BadgeDrawable; import com.github.dfa.diaspora_android.ui.ContextMenuWebView; import com.github.dfa.diaspora_android.ui.CustomWebViewClient; @@ -110,9 +113,9 @@ public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, WebUserProfileChangedListener { - private static final int INPUT_FILE_REQUEST_CODE_NEW = 1; - private static final int INPUT_FILE_REQUEST_CODE_OLD = 2; - private static final int REQUEST_CODE_ASK_PERMISSIONS = 123; + public static final int INPUT_FILE_REQUEST_CODE_NEW = 1; + public static final int INPUT_FILE_REQUEST_CODE_OLD = 2; + public static final int REQUEST_CODE_ASK_PERMISSIONS = 123; public static final int REQUEST_CODE__ACCESS_EXTERNAL_STORAGE = 124; public static final String ACTION_OPEN_URL = "com.github.dfa.diaspora_android.MainActivity.open_url"; @@ -130,42 +133,33 @@ public class MainActivity extends AppCompatActivity private ValueCallback imageUploadFilePathCallbackOld; private String mCameraPhotoPath; private CustomTabActivityHelper customTabActivityHelper; - private WebSettings webSettings; private AppSettings appSettings; private DiasporaUrlHelper urls; private PodUserProfile podUserProfile; private final Handler uiHandler = new Handler(); - private CustomWebViewClient webViewClient; private OpenExternalLinkReceiver brOpenExternalLink; private BroadcastReceiver brSetTitle; private Snackbar snackbarExitApp; private Snackbar snackbarNoInternet; - private String textToBeShared = null; + + private FragmentManager fm; /** * UI Bindings */ - @BindView(R.id.content_layout) - RelativeLayout contentLayout; - - @BindView(R.id.progressBar) - ProgressBar progressBar; - - @BindView(R.id.toolbar) + @BindView(R.id.main__topbar) Toolbar toolbarTop; - @BindView(R.id.toolbar2) + @BindView(R.id.main__bottombar) ActionMenuView toolbarBottom; - @BindView(R.id.placeholder_webview) - FrameLayout webviewPlaceholder; - - ContextMenuWebView webView; + @BindView(R.id.fragment_container) + FrameLayout fragmentContainer; @BindView(R.id.main__navigaion_view) NavigationView navView; - @BindView(R.id.main__layout) + @BindView(R.id.main__navdrawer) DrawerLayout navDrawer; @@ -187,6 +181,14 @@ public class MainActivity extends AppCompatActivity // Bind UI setContentView(R.layout.main__activity); + ButterKnife.bind(this); + + fm = getSupportFragmentManager(); + if(fm.findFragmentByTag(StreamFragment.TAG) == null) { + fm.beginTransaction().replace(R.id.fragment_container, new StreamFragment()).commit(); + } else { + fm.beginTransaction().replace(R.id.fragment_container, fm.findFragmentByTag(StreamFragment.TAG)).commit(); + } if ((app = (App) getApplication()) == null) AppLog.e(this, "App is null!"); if ((appSettings = app.getSettings()) == null) AppLog.e(this, "AppSettings is null!"); @@ -199,15 +201,6 @@ public class MainActivity extends AppCompatActivity setupUI(savedInstanceState); - if (appSettings.isProxyEnabled()) { - if (!setProxy(appSettings.getProxyHost(), appSettings.getProxyPort())) { - AppLog.e(this, "Could not enable Proxy"); - Toast.makeText(MainActivity.this, R.string.toast_set_proxy_failed, Toast.LENGTH_SHORT).show(); - } - } else if (appSettings.wasProxyEnabled()) { - resetProxy(); - } - brOpenExternalLink = new OpenExternalLinkReceiver(this); brSetTitle = new UpdateTitleReceiver(app, urls, new UpdateTitleReceiver.TitleCallback() { @Override @@ -224,27 +217,7 @@ public class MainActivity extends AppCompatActivity private void setupUI(Bundle savedInstanceState) { AppLog.i(this, "setupUI()"); - ButterKnife.bind(this); - if (webviewPlaceholder.getChildCount() != 0) { - AppLog.v(this, "remove child views from webViewPlaceholder"); - webviewPlaceholder.removeAllViews(); - } else { - AppLog.v(this, "webViewPlaceholder had no child views"); - } - boolean newWebView = (webView == null); - if (newWebView) { - AppLog.v(this, "WebView was null. Create new one."); - View webviewHolder = getLayoutInflater().inflate(R.layout.ui__webview, this.contentLayout, false); - this.webView = (ContextMenuWebView) webviewHolder.findViewById(R.id.webView); - ((LinearLayout) webView.getParent()).removeView(webView); - setupWebView(savedInstanceState); - } else { - AppLog.v(this, "Reuse old WebView to avoid reloading page"); - } - - AppLog.v(this, "Add WebView to placeholder"); - webviewPlaceholder.addView(webView); // Setup toolbar setSupportActionBar(toolbarTop); getMenuInflater().inflate(R.menu.main__menu_bottom, toolbarBottom.getMenu()); @@ -257,7 +230,7 @@ public class MainActivity extends AppCompatActivity //Setup snackbar snackbarExitApp = Snackbar - .make(contentLayout, R.string.confirm_exit, Snackbar.LENGTH_LONG) + .make(fragmentContainer, R.string.confirm_exit, Snackbar.LENGTH_LONG) .setAction(android.R.string.yes, new View.OnClickListener() { @Override public void onClick(View view) { @@ -265,24 +238,11 @@ public class MainActivity extends AppCompatActivity moveTaskToBack(true); } }); - snackbarNoInternet = Snackbar.make(contentLayout, R.string.no_internet, Snackbar.LENGTH_LONG); + snackbarNoInternet = Snackbar.make(fragmentContainer, R.string.no_internet, Snackbar.LENGTH_LONG); // Load app settings setupNavigationSlider(); - progressBar = (ProgressBar) findViewById(R.id.progressBar); - - String url = urls.getPodUrl(); - if (newWebView) { - if (WebHelper.isOnline(MainActivity.this)) { - AppLog.v(this, "setupUI: reload url"); - webView.loadData("", "text/html", null); - webView.loadUrlNew(url); - } else { - snackbarNoInternet.show(); - } - } - if (!appSettings.isIntellihideToolbars()) { AppLog.v(this, "Disable intelligent hiding of toolbars"); AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) toolbarTop.getLayoutParams(); @@ -293,14 +253,26 @@ public class MainActivity extends AppCompatActivity handleIntent(getIntent()); } + public void openDiasporaUrl(String url) { + StreamFragment streamFragment = getStreamFragment(); + if(!streamFragment.isVisible()) { + fm.beginTransaction().replace(R.id.fragment_container, streamFragment, StreamFragment.TAG).commit(); + streamFragment.onCreateBottomOptionsMenu(toolbarBottom.getMenu(), getMenuInflater()); + } + streamFragment.loadUrl(url); + } + + public StreamFragment getStreamFragment() { + StreamFragment streamFragment = (StreamFragment) fm.findFragmentByTag(StreamFragment.TAG); + if(streamFragment == null) { + streamFragment = new StreamFragment(); + } + return streamFragment; + } + @Override public void onConfigurationChanged(Configuration newConfig) { AppLog.i(this, "onConfigurationChanged()"); - if (webView != null) { - // Remove the WebView from the old placeholder - AppLog.v(this, "removeView from placeholder in order to prevent recreation"); - webviewPlaceholder.removeView(webView); - } super.onConfigurationChanged(newConfig); @@ -312,161 +284,6 @@ public class MainActivity extends AppCompatActivity setupUI(null); } - private void setupWebView(Bundle savedInstanceState) { - - webSettings = webView.getSettings(); - webSettings.setJavaScriptEnabled(true); - webSettings.setAllowFileAccess(false); - webSettings.setUseWideViewPort(true); - webSettings.setLoadWithOverviewMode(true); - webSettings.setDomStorageEnabled(true); - webSettings.setMinimumFontSize(appSettings.getMinimumFontSize()); - webSettings.setLoadsImagesAutomatically(appSettings.isLoadImages()); - webSettings.setAppCacheEnabled(true); - - if (savedInstanceState != null) { - AppLog.v(this, "restore WebView state"); - webView.restoreState(savedInstanceState); - } - - if (android.os.Build.VERSION.SDK_INT >= 21) { - WebView.enableSlowWholeDocumentDraw(); - webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); - } - - this.registerForContextMenu(webView); - webView.setParentActivity(this); - webView.setOverScrollMode(WebView.OVER_SCROLL_ALWAYS); - - // Setup WebView - webView.addJavascriptInterface(new JavaScriptInterface(), "AndroidBridge"); - - //Set proxy - if (appSettings.isProxyEnabled()) { - if (!setProxy()) - Toast.makeText(this, R.string.toast_set_proxy_failed, Toast.LENGTH_LONG).show(); - } - - /* - * WebViewClient - */ - webViewClient = new CustomWebViewClient(app, webView); - webView.setWebViewClient(webViewClient); - - /* - * WebChromeClient - */ - webView.setWebChromeClient(new WebChromeClient() { - - public void onProgressChanged(WebView wv, int progress) { - progressBar.setProgress(progress); - - if (progress > 0 && progress <= 60) { - WebHelper.getUserProfile(wv); - WebHelper.optimizeMobileSiteLayout(wv); - } - - if (progress > 60) { - WebHelper.optimizeMobileSiteLayout(wv); - - if (textToBeShared != null) { - WebHelper.shareTextIntoWebView(wv, textToBeShared); - } - } - - progressBar.setVisibility(progress == 100 ? View.GONE : View.VISIBLE); - } - - //For Android 4.1/4.2 only. DO NOT REMOVE! - @SuppressWarnings("unused") - protected void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) { - AppLog.v(this, "openFileChooser(ValCallback, String, String"); - imageUploadFilePathCallbackOld = uploadMsg; - Intent intent = new Intent(); - intent.setType("image/*"); - intent.setAction(Intent.ACTION_GET_CONTENT); - intent.putExtra("return-data", true); - intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); - AppLog.v(this, "startActivityForResult"); - startActivityForResult(Intent.createChooser(intent, "Select Picture"), INPUT_FILE_REQUEST_CODE_OLD); - } - - @Override - public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) { - if (Build.VERSION.SDK_INT >= 23) { - int hasWRITE_EXTERNAL_STORAGE = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE); - if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) { - if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - new AlertDialog.Builder(MainActivity.this) - .setMessage(R.string.permissions_image) - .setNegativeButton(android.R.string.no, null) - .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (android.os.Build.VERSION.SDK_INT >= 23) - requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - REQUEST_CODE_ASK_PERMISSIONS); - } - }) - .show(); - return false; - } - requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - REQUEST_CODE_ASK_PERMISSIONS); - return false; - } - } - - AppLog.v(MainActivity.this, "onOpenFileChooser"); - imageUploadFilePathCallbackNew = filePathCallback; - - Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - if (takePictureIntent.resolveActivity(getPackageManager()) != null) { - // Create the File where the photo should go - File photoFile; - try { - photoFile = Helpers.createImageFile(); - takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath); - } catch (IOException ex) { - AppLog.e(this, "ERROR creating temp file: " + ex.toString()); - // Error occurred while creating the File - Snackbar.make(contentLayout, R.string.unable_to_load_image, Snackbar.LENGTH_LONG).show(); - return false; - } - - // Continue only if the File was successfully created - if (photoFile != null) { - mCameraPhotoPath = "file:" + photoFile.getAbsolutePath(); - takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, - Uri.fromFile(photoFile)); - } else { - takePictureIntent = null; - } - } - - Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT); - contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE); - contentSelectionIntent.setType("image/*"); - - Intent[] intentArray; - if (takePictureIntent != null) { - intentArray = new Intent[]{takePictureIntent}; - } else { - intentArray = new Intent[0]; - } - - Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER); - chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent); - chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser"); - chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray); - - AppLog.v(this, "startActivityForResult"); - startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE_NEW); - return true; - } - }); - } - private void setupNavigationSlider() { ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, navDrawer, toolbarTop, R.string.navigation_drawer_open, R.string.navigation_drawer_close); @@ -478,12 +295,13 @@ public class MainActivity extends AppCompatActivity View navHeader = navView.getHeaderView(0); LinearLayout navheaderProfileSection = ButterKnife.findById(navHeader, R.id.nav_profile_picture); + //Handle clicks on profile picture navheaderProfileSection.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { navDrawer.closeDrawer(GravityCompat.START); if (WebHelper.isOnline(MainActivity.this)) { - webView.loadUrlNew(urls.getProfileUrl()); + openDiasporaUrl(urls.getProfileUrl()); } else { snackbarNoInternet.show(); } @@ -530,7 +348,7 @@ public class MainActivity extends AppCompatActivity navMenu.findItem(R.id.nav_public).setVisible(appSettings.isVisibleInNavPublic_activities()); } - @OnClick(R.id.toolbar) + @OnClick(R.id.main__topbar) public void onToolBarClicked(View view) { AppLog.i(this, "onToolBarClicked()"); onNavigationItemSelected(navView.getMenu().findItem(R.id.nav_stream)); @@ -566,11 +384,11 @@ public class MainActivity extends AppCompatActivity } } else if (ACTION_CHANGE_ACCOUNT.equals(action)) { AppLog.v(this, "Reset pod data and animate to PodSelectionActivity"); - app.resetPodData(webView); + app.resetPodData(getStreamFragment().getWebView()); Helpers.animateToActivity(MainActivity.this, PodSelectionActivity.class, true); } else if (ACTION_CLEAR_CACHE.equals(action)) { AppLog.v(this, "Clear WebView cache"); - webView.clearCache(true); + getStreamFragment().getWebView().clearCache(true); } else if (ACTION_RELOAD_ACTIVITY.equals(action)) { AppLog.v(this, "Recreate activity"); recreate(); @@ -593,9 +411,8 @@ public class MainActivity extends AppCompatActivity } if (loadUrl != null) { - webView.stopLoading(); navDrawer.closeDrawers(); - webView.loadUrlNew(loadUrl); + openDiasporaUrl(loadUrl); } } @@ -672,16 +489,21 @@ public class MainActivity extends AppCompatActivity protected void onSaveInstanceState(Bundle outState) { AppLog.v(this, "onSaveInstanceState()"); super.onSaveInstanceState(outState); - AppLog.v(this, "Save WebView state"); - webView.saveState(outState); } @Override protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) { AppLog.v(this, "onRestoreInstanceState()"); super.onRestoreInstanceState(savedInstanceState); - AppLog.v(this, "Restore state of WebView"); - webView.restoreState(savedInstanceState); + } + + private Fragment getTopFragment() { + for(Fragment f : fm.getFragments()) { + if(f.isVisible()) { + return f; + } + } + return null; } @Override @@ -691,10 +513,14 @@ public class MainActivity extends AppCompatActivity navDrawer.closeDrawer(navView); return; } - - if (webView.canGoBack()) { - webView.goBack(); - return; + CustomFragment top = (CustomFragment) getTopFragment(); + if(top != null) { + if(!top.onBackPressed()) { + //TODO: Go back in Fragment backstack + return; + } else { + return; + } } if (!snackbarExitApp.isShown()) { @@ -761,7 +587,7 @@ public class MainActivity extends AppCompatActivity switch (item.getItemId()) { case R.id.action_notifications: { if (WebHelper.isOnline(MainActivity.this)) { - webView.loadUrlNew(urls.getNotificationsUrl()); + openDiasporaUrl(urls.getNotificationsUrl()); return true; } else { snackbarNoInternet.show(); @@ -771,17 +597,7 @@ public class MainActivity extends AppCompatActivity case R.id.action_conversations: { if (WebHelper.isOnline(MainActivity.this)) { - webView.loadUrlNew(urls.getConversationsUrl()); - return true; - } else { - snackbarNoInternet.show(); - return false; - } - } - - case R.id.action_reload: { - if (WebHelper.isOnline(MainActivity.this)) { - webView.reload(); + openDiasporaUrl(urls.getConversationsUrl()); return true; } else { snackbarNoInternet.show(); @@ -795,47 +611,15 @@ public class MainActivity extends AppCompatActivity return true; } - case R.id.action_toggle_desktop_page: { - webView.loadUrlNew(urls.getToggleMobileUrl()); - return true; - } - case R.id.action_compose: { if (WebHelper.isOnline(MainActivity.this)) { - webView.loadUrlNew(urls.getNewPostUrl()); + openDiasporaUrl(urls.getNewPostUrl()); } else { snackbarNoInternet.show(); } return true; } - case R.id.action_go_to_top: { - // Scroll to top (animated) - ObjectAnimator anim = ObjectAnimator.ofInt(webView, "scrollY", webView.getScrollY(), 0); - anim.setDuration(400); - anim.start(); - return true; - } - - case R.id.action_share_link: { - Intent sharingIntent = new Intent(Intent.ACTION_SEND); - sharingIntent.setType("text/plain"); - sharingIntent.putExtra(Intent.EXTRA_SUBJECT, webView.getTitle()); - sharingIntent.putExtra(Intent.EXTRA_TEXT, webView.getUrl()); - startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.action_share_dotdotdot))); - return true; - } - - case R.id.action_take_screenshot: { - makeScreenshotOfWebView(false); - return true; - } - - case R.id.action_share_screenshot: { - makeScreenshotOfWebView(true); - return true; - } - case R.id.action_search: { if (WebHelper.isOnline(MainActivity.this)) { final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); @@ -847,9 +631,9 @@ public class MainActivity extends AppCompatActivity public void onClick(DialogInterface dialogInterface, int which) { String query = input.getText().toString().trim().replaceAll((which == DialogInterface.BUTTON_NEGATIVE ? "\\*" : "\\#"), ""); if (query.equals("")) { - Snackbar.make(contentLayout, R.string.search_alert_bypeople_validate_needsomedata, Snackbar.LENGTH_LONG).show(); + Snackbar.make(fragmentContainer, R.string.search_alert_bypeople_validate_needsomedata, Snackbar.LENGTH_LONG).show(); } else { - webView.loadUrl(which == DialogInterface.BUTTON_NEGATIVE ? urls.getSearchPeopleUrl(query) : urls.getSearchTagsUrl(query)); + openDiasporaUrl(which == DialogInterface.BUTTON_NEGATIVE ? urls.getSearchPeopleUrl(query) : urls.getSearchTagsUrl(query)); } getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); imm.hideSoftInputFromWindow(input.getWindowToken(), 0); @@ -890,88 +674,6 @@ public class MainActivity extends AppCompatActivity return super.onOptionsItemSelected(item); } - @SuppressWarnings("ResultOfMethodCallIgnored") - private boolean makeScreenshotOfWebView(boolean hasToShareScreenshot) { - AppLog.i(this, "makeScreenshotOfWebView()"); - if (android.os.Build.VERSION.SDK_INT >= 23) { - int hasWRITE_EXTERNAL_STORAGE = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE); - if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) { - if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - new AlertDialog.Builder(MainActivity.this) - .setMessage(R.string.permissions_screenshot) - .setNegativeButton(android.R.string.no, null) - .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (android.os.Build.VERSION.SDK_INT >= 23) - requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - REQUEST_CODE_ASK_PERMISSIONS); - } - }) - .show(); - return false; - } - requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - REQUEST_CODE_ASK_PERMISSIONS); - return false; - } - } - - Date dateNow = new Date(); - DateFormat dateFormat = new SimpleDateFormat("yy_MM_dd--HH_mm_ss", Locale.getDefault()); - File fileSaveDirectory = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/Diaspora"); - - String fileSaveName = hasToShareScreenshot ? ".DfA_share.jpg" : String.format("DfA_%s.jpg", dateFormat.format(dateNow)); - if (!fileSaveDirectory.exists()) { - if (!fileSaveDirectory.mkdirs()) { - AppLog.w(this, "Could not mkdir " + fileSaveDirectory.getAbsolutePath()); - } - } - - if (!hasToShareScreenshot) { - Snackbar.make(contentLayout, getString(R.string.share__toast_screenshot) + " " + fileSaveName, Snackbar.LENGTH_LONG).show(); - } - - Bitmap bitmap; - webView.setDrawingCacheEnabled(true); - bitmap = Bitmap.createBitmap(webView.getDrawingCache()); - webView.setDrawingCacheEnabled(false); - - OutputStream bitmapWriter = null; - try { - bitmapWriter = new FileOutputStream(new File(fileSaveDirectory, fileSaveName)); - bitmap.compress(Bitmap.CompressFormat.JPEG, 85, bitmapWriter); - bitmapWriter.flush(); - bitmap.recycle(); - } catch (Exception e) { - return false; - } finally { - if (bitmapWriter != null) { - try { - bitmapWriter.close(); - } catch (IOException _ignSaveored) {/* Nothing */} - } - } - - // Only show share intent when Action Share Screenshot was selected - if (hasToShareScreenshot) { - Intent sharingIntent = new Intent(Intent.ACTION_SEND); - sharingIntent.setType("image/jpeg"); - sharingIntent.putExtra(Intent.EXTRA_SUBJECT, webView.getTitle()); - sharingIntent.putExtra(Intent.EXTRA_TEXT, webView.getUrl()); - Uri bmpUri = Uri.fromFile(new File(fileSaveDirectory, fileSaveName)); - sharingIntent.putExtra(Intent.EXTRA_STREAM, bmpUri); - startActivity(Intent.createChooser(sharingIntent, getString(R.string.action_share_dotdotdot))); - } else { - // Broadcast that this file is indexable - File file = new File(fileSaveDirectory, fileSaveName); - Uri uri = Uri.fromFile(file); - Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri); - sendBroadcast(intent); - } - return true; - } - @Override public void onUserProfileNameChanged(String name) { AppLog.i(this, "onUserProfileNameChanged()"); @@ -991,7 +693,7 @@ public class MainActivity extends AppCompatActivity } catch (Exception e) { AppLog.e(this, e.toString()); } - webView.loadUrlNew(urls.getNewPostUrl()); + openDiasporaUrl(urls.getNewPostUrl()); } private void handleSendText(Intent intent) { @@ -1001,8 +703,8 @@ public class MainActivity extends AppCompatActivity } catch (Exception e) { AppLog.e(this, e.toString()); } - webView.loadUrlNew(urls.getBlankUrl()); - webView.loadUrlNew(urls.getNewPostUrl()); + openDiasporaUrl(urls.getBlankUrl()); + openDiasporaUrl(urls.getNewPostUrl()); } /** @@ -1017,11 +719,12 @@ public class MainActivity extends AppCompatActivity } catch (Exception e) { AppLog.e(this, e.toString()); } - webView.loadUrlNew(urls.getBlankUrl()); //TODO: Necessary? - webView.loadUrlNew(urls.getNewPostUrl()); + openDiasporaUrl(urls.getBlankUrl()); //TODO: Necessary? + openDiasporaUrl(urls.getNewPostUrl()); } /** + * TODO: MOVE * Set sharedText variable to escaped and formatted subject + body. * If subject is null, only the body will be set. Else the subject will be set as header. * Depending on whether the user has the setting isAppendSharedViaApp set, a reference to @@ -1041,10 +744,10 @@ public class MainActivity extends AppCompatActivity if (sharedSubject != null) { AppLog.v(this, "Append subject to shared text"); String escapedSubject = WebHelper.escapeHtmlText(WebHelper.replaceUrlWithMarkdown(sharedSubject)); - textToBeShared = "**" + escapedSubject + "** " + escapedBody; + //textToBeShared = "**" + escapedSubject + "** " + escapedBody; } else { AppLog.v(this, "Set shared text; Subject: \"" + sharedSubject + "\" Body: \"" + sharedBody + "\""); - textToBeShared = escapedBody; + //textToBeShared = escapedBody; } @@ -1079,24 +782,6 @@ public class MainActivity extends AppCompatActivity invalidateOptionsMenu(); } - private class JavaScriptInterface { - @JavascriptInterface - public void setUserProfile(final String webMessage) throws JSONException { - AppLog.spam(this, "JavaScriptInterface.setUserProfile()"); - if (podUserProfile.isRefreshNeeded()) { - AppLog.spam(this, "PodUserProfile needs refresh; Try to parse JSON"); - podUserProfile.parseJson(webMessage); - } else { - AppLog.spam(this, "No PodUserProfile refresh needed"); - } - } - - @JavascriptInterface - public void contentHasBeenShared() { - textToBeShared = null; - } - } - @SuppressWarnings("StatementWithEmptyBody") @Override public boolean onNavigationItemSelected(MenuItem item) { @@ -1105,7 +790,7 @@ public class MainActivity extends AppCompatActivity switch (item.getItemId()) { case R.id.nav_stream: { if (WebHelper.isOnline(MainActivity.this)) { - webView.loadUrlNew(urls.getStreamUrl()); + openDiasporaUrl(urls.getStreamUrl()); } else { snackbarNoInternet.show(); } @@ -1114,16 +799,18 @@ public class MainActivity extends AppCompatActivity case R.id.nav_profile: { if (WebHelper.isOnline(MainActivity.this)) { - webView.loadUrlNew(urls.getProfileUrl()); + openDiasporaUrl(urls.getProfileUrl()); } else { snackbarNoInternet.show(); } } break; + //TODO: Replace with fragment case R.id.nav_followed_tags: { if (WebHelper.isOnline(MainActivity.this)) { - WebHelper.showFollowedTagsList(webView, app); + openDiasporaUrl(urls.getBlankUrl()); + WebHelper.showFollowedTagsList(getStreamFragment().getWebView(), app); setTitle(R.string.nav_followed_tags); } else { snackbarNoInternet.show(); @@ -1131,10 +818,11 @@ public class MainActivity extends AppCompatActivity } break; + //TODO: Replace with fragment case R.id.nav_aspects: { if (WebHelper.isOnline(MainActivity.this)) { - webView.loadUrlNew(DiasporaUrlHelper.URL_BLANK); - WebHelper.showAspectList(webView, app); + openDiasporaUrl(DiasporaUrlHelper.URL_BLANK); + WebHelper.showAspectList(getStreamFragment().getWebView(), app); setTitle(R.string.aspects); } else { snackbarNoInternet.show(); @@ -1144,7 +832,7 @@ public class MainActivity extends AppCompatActivity case R.id.nav_activities: { if (WebHelper.isOnline(MainActivity.this)) { - webView.loadUrlNew(urls.getActivityUrl()); + openDiasporaUrl(urls.getActivityUrl()); } else { snackbarNoInternet.show(); } @@ -1153,7 +841,7 @@ public class MainActivity extends AppCompatActivity case R.id.nav_liked: { if (WebHelper.isOnline(MainActivity.this)) { - webView.loadUrlNew(urls.getLikedPostsUrl()); + openDiasporaUrl(urls.getLikedPostsUrl()); } else { snackbarNoInternet.show(); } @@ -1162,7 +850,7 @@ public class MainActivity extends AppCompatActivity case R.id.nav_commented: { if (WebHelper.isOnline(MainActivity.this)) { - webView.loadUrlNew(urls.getCommentedUrl()); + openDiasporaUrl(urls.getCommentedUrl()); } else { snackbarNoInternet.show(); } @@ -1171,7 +859,7 @@ public class MainActivity extends AppCompatActivity case R.id.nav_mentions: { if (WebHelper.isOnline(MainActivity.this)) { - webView.loadUrlNew(urls.getMentionsUrl()); + openDiasporaUrl(urls.getMentionsUrl()); } else { snackbarNoInternet.show(); } @@ -1180,7 +868,7 @@ public class MainActivity extends AppCompatActivity case R.id.nav_public: { if (WebHelper.isOnline(MainActivity.this)) { - webView.loadUrlNew(urls.getPublicUrl()); + openDiasporaUrl(urls.getPublicUrl()); } else { snackbarNoInternet.show(); } @@ -1226,83 +914,4 @@ public class MainActivity extends AppCompatActivity grantResults); } } - - /** - * Set proxy according to arguments. host must not be "" or null, port must be positive. - * Return true on success and update appSettings' proxy related values. - * - * @param host proxy host (eg. localhost or 127.0.0.1) - * @param port proxy port (eg. 8118) - * @return success - * @throws IllegalArgumentException if arguments do not fit specifications above - */ - private boolean setProxy(final String host, final int port) { - AppLog.v(this, "setProxy()"); - if (host != null && !host.equals("") && port >= 0) { - AppLog.v(this, "Set proxy to " + host + ":" + port); - //Temporary change thread policy - AppLog.v(this, "Set temporary ThreadPolicy"); - StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy(); - StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build(); - StrictMode.setThreadPolicy(tmp); - - AppLog.v(this, "Apply NetCipher proxy settings"); - NetCipher.setProxy(host, port); //Proxy for HttpsUrlConnections - try { - //Proxy for the ui__webview - AppLog.v(this, "Apply Webkit proxy settings"); - WebkitProxy.setProxy(MainActivity.class.getName(), getApplicationContext(), null, host, port); - } catch (Exception e) { - AppLog.e(this, "Could not apply WebKit proxy settings:\n" + e.toString()); - } - AppLog.v(this, "Save changes in appSettings"); - appSettings.setProxyEnabled(true); - appSettings.setProxyWasEnabled(true); - - AppLog.v(this, "Reset old ThreadPolicy"); - StrictMode.setThreadPolicy(old); - AppLog.v(this, "Success! Reload WebView"); - webView.reload(); - return true; - } else { - AppLog.w(this, "Invalid proxy configuration. Host: " + host + " Port: " + port + "\nRefuse to set proxy"); - return false; - } - } - - private boolean setProxy() { - return setProxy(appSettings.getProxyHost(), appSettings.getProxyPort()); - } - - private void resetProxy() { - AppLog.i(this, "resetProxy()"); - AppLog.v(this, "write changes to appSettings"); - appSettings.setProxyEnabled(false); - appSettings.setProxyWasEnabled(false); - - //Temporary change thread policy - AppLog.v(this, "Set temporary ThreadPolicy"); - StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy(); - StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build(); - StrictMode.setThreadPolicy(tmp); - - AppLog.v(this, "clear NetCipher proxy"); - NetCipher.clearProxy(); - try { - AppLog.v(this, "clear WebKit proxy"); - WebkitProxy.resetProxy(MainActivity.class.getName(), this); - } catch (Exception e) { - AppLog.e(this, "Could not clear WebKit proxy:\n" + e.toString()); - } - AppLog.v(this, "Reset old ThreadPolicy"); - StrictMode.setThreadPolicy(old); - - //Restart app - AppLog.i(this, "Success! Restart app due to proxy reset"); - Intent restartActivity = new Intent(this, MainActivity.class); - PendingIntent pendingIntent = PendingIntent.getActivity(this, 12374, restartActivity, PendingIntent.FLAG_CANCEL_CURRENT); - AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE); - mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pendingIntent); - System.exit(0); - } } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionActivity.java index 9729b8e4..57103f6b 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionActivity.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionActivity.java @@ -65,7 +65,7 @@ public class PodSelectionActivity extends AppCompatActivity { @BindView(R.id.podselection__listpods) ListView listPods; - @BindView(R.id.toolbar) + @BindView(R.id.main__topbar) Toolbar toolbar; @Override diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/CustomFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/CustomFragment.java new file mode 100644 index 00000000..b4398d16 --- /dev/null +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/CustomFragment.java @@ -0,0 +1,33 @@ +package com.github.dfa.diaspora_android.fragment; + +import android.support.v4.app.Fragment; +import android.view.Menu; +import android.view.MenuInflater; + +/** + * Customized abstract Fragment class with some useful methods + * Created by vanitas on 21.09.16. + */ + +public abstract class CustomFragment extends Fragment { + /** + * Return the tag used to identify the Fragment. + * @return tag + */ + public abstract String getFragmentTag(); + + /** + * Add fragment-dependent options to the bottom options toolbar + * @param menu bottom menu + * @param inflater inflater + */ + public abstract void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater); + + /** + * Return true if the fragment reacted to a back button press, false else. + * In case the fragment returned false, the parent activity should handle the backPress. + * @return did we react to the back press? + */ + public abstract boolean onBackPressed(); +} + diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java new file mode 100644 index 00000000..cdf28103 --- /dev/null +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java @@ -0,0 +1,141 @@ +package com.github.dfa.diaspora_android.fragment; + +import android.animation.ObjectAnimator; +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ProgressBar; + +import com.github.dfa.diaspora_android.App; +import com.github.dfa.diaspora_android.R; +import com.github.dfa.diaspora_android.ui.ContextMenuWebView; +import com.github.dfa.diaspora_android.util.AppLog; +import com.github.dfa.diaspora_android.util.DiasporaUrlHelper; +import com.github.dfa.diaspora_android.util.WebHelper; + +/** + * Fragment that contains a WebView displaying the stream of the user + * Created by vanitas on 21.09.16. + */ + +public class StreamFragment extends WebViewFragment { + public static final String TAG = "com.github.dfa.diaspora_android.StreamFragment"; + + private DiasporaUrlHelper urls; + private Bundle webViewState; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.stream__fragment, container, false); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + this.webView = (ContextMenuWebView) view.findViewById(R.id.webView); + this.progressBar = (ProgressBar) view.findViewById(R.id.progressBar); + this.appSettings = ((App) getActivity().getApplication()).getSettings(); + this.urls = new DiasporaUrlHelper(appSettings); + + this.setup( + webView, + progressBar, + appSettings); + + if(webView.getUrl() == null) { + loadUrl(urls.getPodUrl()); + } + this.setRetainInstance(true); + } + + @Override + public String getFragmentTag() { + return TAG; + } + + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.stream__menu_top, menu); + super.onCreateOptionsMenu(menu, inflater); + } + + @Override + public void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.stream__menu_bottom, menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + AppLog.d(this, "StreamFragment.onOptionsItemSelected()"); + switch (item.getItemId()) { + case R.id.action_reload: { + if(WebHelper.isOnline(getContext())) { + reloadUrl(); + return true; + } else { + return false; + } + } + + case R.id.action_toggle_desktop_page: { + loadUrl(urls.getToggleMobileUrl()); + return true; + } + + case R.id.action_go_to_top: { + ObjectAnimator anim = ObjectAnimator.ofInt(webView, "scrollY", webView.getScrollY(), 0); + anim.setDuration(400); + anim.start(); + return true; + } + + case R.id.action_share_link: { + Intent sharingIntent = new Intent(Intent.ACTION_SEND); + sharingIntent.setType("text/plain"); + sharingIntent.putExtra(Intent.EXTRA_SUBJECT, webView.getTitle()); + sharingIntent.putExtra(Intent.EXTRA_TEXT, webView.getUrl()); + startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.action_share_dotdotdot))); + return true; + } + + case R.id.action_take_screenshot: { + makeScreenshotOfWebView(false); + return true; + } + + case R.id.action_share_screenshot: { + makeScreenshotOfWebView(true); + return true; + } + } + return super.onOptionsItemSelected(item); + } + + @Override + public void onPause() { + super.onPause(); + webViewState = new Bundle(); + webView.saveState(webViewState); + } + + @Override + public void onResume() { + super.onResume(); + if(webViewState != null) { + webView.restoreState(webViewState); + } + } + + @Override + public boolean onBackPressed() { + if(webView.canGoBack()) { + webView.goBack(); + return true; + } + return false; + } +} diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/WebViewFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/WebViewFragment.java new file mode 100644 index 00000000..bde42f4c --- /dev/null +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/WebViewFragment.java @@ -0,0 +1,430 @@ +package com.github.dfa.diaspora_android.fragment; + +import android.Manifest; +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Bundle; +import android.os.Environment; +import android.os.StrictMode; +import android.support.design.widget.Snackbar; +import android.support.v7.app.AlertDialog; +import android.view.View; +import android.webkit.JavascriptInterface; +import android.webkit.ValueCallback; +import android.webkit.WebChromeClient; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.ProgressBar; +import android.widget.Toast; + +import com.github.dfa.diaspora_android.App; +import com.github.dfa.diaspora_android.R; +import com.github.dfa.diaspora_android.activity.MainActivity; +import com.github.dfa.diaspora_android.data.AppSettings; +import com.github.dfa.diaspora_android.data.PodUserProfile; +import com.github.dfa.diaspora_android.ui.ContextMenuWebView; +import com.github.dfa.diaspora_android.ui.CustomWebViewClient; +import com.github.dfa.diaspora_android.util.AppLog; +import com.github.dfa.diaspora_android.util.WebHelper; + +import org.json.JSONException; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import info.guardianproject.netcipher.NetCipher; +import info.guardianproject.netcipher.webkit.WebkitProxy; + +/** + * Fragment that contains a WebView with a bunch of functionality + * Created by vanitas on 21.09.16. + */ + +public abstract class WebViewFragment extends CustomFragment { + + protected WebSettings webSettings; + protected WebViewClient webViewClient; + protected ContextMenuWebView webView; + protected ProgressBar progressBar; + protected AppSettings appSettings; + + protected String textToBeShared; + + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + } + + protected void setup(ContextMenuWebView webView, final ProgressBar progressBar, AppSettings appSettings) { + this.appSettings = appSettings; + this.webSettings = webView.getSettings(); + this.webView = webView; + this.progressBar = progressBar; + + if (appSettings.isProxyEnabled()) { + if (!setProxy(appSettings.getProxyHost(), appSettings.getProxyPort())) { + AppLog.e(this, "Could not enable Proxy"); + Toast.makeText(getContext(), R.string.toast_set_proxy_failed, Toast.LENGTH_SHORT).show(); + } + } else if (appSettings.wasProxyEnabled()) { + resetProxy(); + } + + webSettings.setJavaScriptEnabled(true); + webSettings.setAllowFileAccess(false); + webSettings.setUseWideViewPort(true); + webSettings.setLoadWithOverviewMode(true); + webSettings.setDomStorageEnabled(true); + webSettings.setMinimumFontSize(appSettings.getMinimumFontSize()); + webSettings.setLoadsImagesAutomatically(appSettings.isLoadImages()); + webSettings.setAppCacheEnabled(true); + + if (android.os.Build.VERSION.SDK_INT >= 21) { + WebView.enableSlowWholeDocumentDraw(); + webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); + } + + this.registerForContextMenu(webView); + //webView.setParentActivity(this); + webView.setOverScrollMode(WebView.OVER_SCROLL_ALWAYS); + + // Setup WebView + webView.addJavascriptInterface(new JavaScriptInterface(), "AndroidBridge"); + + //Set proxy + if (appSettings.isProxyEnabled()) { + if (!setProxy(appSettings.getProxyHost(), appSettings.getProxyPort())) { + AppLog.d(this, "Could not enable Proxy"); + Toast.makeText(getContext(), R.string.toast_set_proxy_failed, Toast.LENGTH_SHORT).show(); + } + } else if (appSettings.wasProxyEnabled()) { + resetProxy(); + } + + /* + * WebViewClient + */ + this.webViewClient = new CustomWebViewClient((App) getActivity().getApplication(), webView); + webView.setWebViewClient(webViewClient); + + /* + * WebChromeClient + */ + webView.setWebChromeClient(new WebChromeClient() { + final ProgressBar pb = progressBar; + + public void onProgressChanged(WebView wv, int progress) { + pb.setProgress(progress); + + if (progress > 0 && progress <= 60) { + WebHelper.getUserProfile(wv); + WebHelper.optimizeMobileSiteLayout(wv); + } + + if (progress > 60) { + WebHelper.optimizeMobileSiteLayout(wv); + + if (textToBeShared != null) { + WebHelper.shareTextIntoWebView(wv, textToBeShared); + } + } + + progressBar.setVisibility(progress == 100 ? View.GONE : View.VISIBLE); + } + + //For Android 4.1/4.2 only. DO NOT REMOVE! + @SuppressWarnings("unused") + protected void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) + { + AppLog.v(this, "openFileChooser(ValCallback, String, String"); + //imageUploadFilePathCallbackOld = uploadMsg; + Intent intent = new Intent(); + intent.setType("image/*"); + intent.setAction(Intent.ACTION_GET_CONTENT); + intent.putExtra("return-data", true); + intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + AppLog.v(this, "startActivityForResult"); + startActivityForResult(Intent.createChooser(intent, "Select Picture"), MainActivity.INPUT_FILE_REQUEST_CODE_OLD); + } + + /* + @Override + public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) { + if(Build.VERSION.SDK_INT >= 23) { + int hasWRITE_EXTERNAL_STORAGE = getActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE); + if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) { + if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + new AlertDialog.Builder(getContext()) + .setMessage(R.string.permissions_image) + .setNegativeButton(android.R.string.no, null) + .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (android.os.Build.VERSION.SDK_INT >= 23) + requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + MainActivity.REQUEST_CODE_ASK_PERMISSIONS); + } + }) + .show(); + return false; + } + requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + MainActivity.REQUEST_CODE_ASK_PERMISSIONS); + return false; + } + } + AppLog.d(this, "onOpenFileChooser"); + if (MainActivity.imageUploadFilePathCallbackNew != null) imageUploadFilePathCallbackNew.onReceiveValue(null); + imageUploadFilePathCallbackNew = filePathCallback; + Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + if (takePictureIntent.resolveActivity(getPackageManager()) != null) { + // Create the File where the photo should go + File photoFile; + try { + photoFile = Helpers.createImageFile(); + takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath); + } catch (IOException ex) { + AppLog.e(this, "ERROR creating temp file: "+ ex.toString()); + // Error occurred while creating the File + Snackbar.make(contentLayout, R.string.unable_to_load_image, Snackbar.LENGTH_LONG).show(); + return false; + } + // Continue only if the File was successfully created + if (photoFile != null) { + mCameraPhotoPath = "file:" + photoFile.getAbsolutePath(); + takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, + Uri.fromFile(photoFile)); + } else { + takePictureIntent = null; + } + } + Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT); + contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE); + contentSelectionIntent.setType("image/*"); + Intent[] intentArray; + if (takePictureIntent != null) { + intentArray = new Intent[]{takePictureIntent}; + } else { + intentArray = new Intent[0]; + } + Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER); + chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent); + chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser"); + chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray); + Log.d(App.TAG,"startActivityForResult"); + startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE_NEW); + return true; + } + */ + }); + + } + + /** + * Set proxy according to arguments. host must not be "" or null, port must be positive. + * Return true on success and update appSettings' proxy related values. + * + * @param host proxy host (eg. localhost or 127.0.0.1) + * @param port proxy port (eg. 8118) + * @return success + * @throws IllegalArgumentException if arguments do not fit specifications above + */ + private boolean setProxy(final String host, final int port) { + AppLog.i(this, "StreamFragment.setProxy()"); + if (host != null && !host.equals("") && port >= 0) { + AppLog.i(this, "Set proxy to "+host+":"+port); + //Temporary change thread policy + AppLog.v(this, "Set temporary ThreadPolicy"); + StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy(); + StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build(); + StrictMode.setThreadPolicy(tmp); + + AppLog.v(this, "Apply NetCipher proxy settings"); + NetCipher.setProxy(host, port); //Proxy for HttpsUrlConnections + try { + //Proxy for the webview + AppLog.v(this, "Apply Webkit proxy settings"); + WebkitProxy.setProxy(MainActivity.class.getName(), getContext().getApplicationContext(), null, host, port); + } catch (Exception e) { + AppLog.e(this, "Could not apply WebKit proxy settings:\n"+e.toString()); + } + AppLog.v(this, "Save changes in appSettings"); + appSettings.setProxyEnabled(true); + appSettings.setProxyWasEnabled(true); + + AppLog.v(this, "Reset old ThreadPolicy"); + StrictMode.setThreadPolicy(old); + AppLog.i(this, "Success! Reload WebView"); + webView.reload(); + return true; + } else { + AppLog.e(this, "Invalid proxy configuration. Host: "+host+" Port: "+port+"\nRefuse to set proxy"); + return false; + } + } + + private boolean setProxy() { + return setProxy(appSettings.getProxyHost(), appSettings.getProxyPort()); + } + + private void resetProxy() { + AppLog.i(this, "StreamFragment.resetProxy()"); + AppLog.v(this, "write changes to appSettings"); + appSettings.setProxyEnabled(false); + appSettings.setProxyWasEnabled(false); + + //Temporary change thread policy + AppLog.v(this, "Set temporary ThreadPolicy"); + StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy(); + StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build(); + StrictMode.setThreadPolicy(tmp); + + AppLog.v(this, "clear NetCipher proxy"); + NetCipher.clearProxy(); + try { + AppLog.v(this, "clear WebKit proxy"); + WebkitProxy.resetProxy(MainActivity.class.getName(), getContext()); + } catch (Exception e) { + AppLog.e(this, "Could not clear WebKit proxy:\n"+e.toString()); + } + AppLog.v(this, "Reset old ThreadPolicy"); + StrictMode.setThreadPolicy(old); + + //Restart app + AppLog.i(this, "Success! Restart app due to proxy reset"); + Intent restartActivity = new Intent(getContext(), MainActivity.class); + PendingIntent pendingIntent = PendingIntent.getActivity(getContext(), 12374, restartActivity, PendingIntent.FLAG_CANCEL_CURRENT); + AlarmManager mgr = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE); + mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pendingIntent); + System.exit(0); + } + + private class JavaScriptInterface { + @JavascriptInterface + public void setUserProfile(final String webMessage) throws JSONException { + PodUserProfile pup = ((App)getActivity().getApplication()).getPodUserProfile(); + AppLog.i(this, "StreamFragment.JavaScriptInterface.setUserProfile()"); + if (pup.isRefreshNeeded()) { + AppLog.v(this, "PodUserProfile needs refresh; Try to parse JSON"); + pup.parseJson(webMessage); + } else { + AppLog.v(this, "No PodUserProfile refresh needed"); + } + } + + @JavascriptInterface + public void contentHasBeenShared() { + textToBeShared = null; + } + } + + @SuppressWarnings("ResultOfMethodCallIgnored") + protected boolean makeScreenshotOfWebView(boolean hasToShareScreenshot) { + AppLog.i(this, "StreamFragment.makeScreenshotOfWebView()"); + if (android.os.Build.VERSION.SDK_INT >= 23) { + int hasWRITE_EXTERNAL_STORAGE = getActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE); + if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) { + if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + new AlertDialog.Builder(getContext()) + .setMessage(R.string.permissions_screenshot) + .setNegativeButton(android.R.string.no, null) + .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (android.os.Build.VERSION.SDK_INT >= 23) + requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + MainActivity.REQUEST_CODE_ASK_PERMISSIONS); + } + }) + .show(); + return false; + } + requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + MainActivity.REQUEST_CODE_ASK_PERMISSIONS); + return false; + } + } + + Date dateNow = new Date(); + DateFormat dateFormat = new SimpleDateFormat("yy_MM_dd--HH_mm_ss", Locale.getDefault()); + File fileSaveDirectory = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/Diaspora"); + + String fileSaveName = hasToShareScreenshot ? ".DfA_share.jpg" : String.format("DfA_%s.jpg", dateFormat.format(dateNow)); + if (!fileSaveDirectory.exists()) { + if(!fileSaveDirectory.mkdirs()) { + AppLog.w(this, "Could not mkdir "+fileSaveDirectory.getAbsolutePath()); + } + } + + if (!hasToShareScreenshot) { + Snackbar.make(webView, getString(R.string.share__toast_screenshot) + " " + fileSaveName, Snackbar.LENGTH_LONG).show(); + } + + Bitmap bitmap; + webView.setDrawingCacheEnabled(true); + bitmap = Bitmap.createBitmap(webView.getDrawingCache()); + webView.setDrawingCacheEnabled(false); + + OutputStream bitmapWriter = null; + try { + bitmapWriter = new FileOutputStream(new File(fileSaveDirectory, fileSaveName)); + bitmap.compress(Bitmap.CompressFormat.JPEG, 85, bitmapWriter); + bitmapWriter.flush(); + bitmap.recycle(); + } catch (Exception e) { + return false; + } finally { + if (bitmapWriter != null) { + try { + bitmapWriter.close(); + } catch (IOException _ignSaveored) {/* Nothing */} + } + } + + // Only show share intent when Action Share Screenshot was selected + if (hasToShareScreenshot) { + Intent sharingIntent = new Intent(Intent.ACTION_SEND); + sharingIntent.setType("image/jpeg"); + sharingIntent.putExtra(Intent.EXTRA_SUBJECT, webView.getTitle()); + sharingIntent.putExtra(Intent.EXTRA_TEXT, webView.getUrl()); + Uri bmpUri = Uri.fromFile(new File(fileSaveDirectory, fileSaveName)); + sharingIntent.putExtra(Intent.EXTRA_STREAM, bmpUri); + startActivity(Intent.createChooser(sharingIntent, getString(R.string.action_share_dotdotdot))); + } else { + // Broadcast that this file is indexable + File file = new File(fileSaveDirectory, fileSaveName); + Uri uri = Uri.fromFile(file); + Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri); + getActivity().sendBroadcast(intent); + } + return true; + } + + public void loadUrl(String url) { + getWebView().loadUrlNew(url); + } + + public String getUrl() { + return getWebView().getUrl(); + } + + public void reloadUrl() { + getWebView().reload(); + } + + public ContextMenuWebView getWebView() { + return this.webView; + } +} diff --git a/app/src/main/java/com/github/dfa/diaspora_android/receivers/OpenExternalLinkReceiver.java b/app/src/main/java/com/github/dfa/diaspora_android/receiver/OpenExternalLinkReceiver.java similarity index 94% rename from app/src/main/java/com/github/dfa/diaspora_android/receivers/OpenExternalLinkReceiver.java rename to app/src/main/java/com/github/dfa/diaspora_android/receiver/OpenExternalLinkReceiver.java index 0ef48e4f..3373d074 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/receivers/OpenExternalLinkReceiver.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/receiver/OpenExternalLinkReceiver.java @@ -1,4 +1,4 @@ -package com.github.dfa.diaspora_android.receivers; +package com.github.dfa.diaspora_android.receiver; import android.app.Activity; import android.content.BroadcastReceiver; @@ -9,7 +9,6 @@ import android.graphics.BitmapFactory; import android.net.Uri; import android.support.customtabs.CustomTabsIntent; -import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.activity.MainActivity; import com.github.dfa.diaspora_android.data.AppSettings; @@ -17,7 +16,6 @@ import com.github.dfa.diaspora_android.util.AppLog; import com.github.dfa.diaspora_android.util.CustomTabHelpers.BrowserFallback; import com.github.dfa.diaspora_android.util.CustomTabHelpers.CustomTabActivityHelper; import com.github.dfa.diaspora_android.util.Helpers; -import com.github.dfa.diaspora_android.util.Log; /** * BroadcastReceiver that opens links in a Chrome CustomTab diff --git a/app/src/main/java/com/github/dfa/diaspora_android/receivers/UpdateTitleReceiver.java b/app/src/main/java/com/github/dfa/diaspora_android/receiver/UpdateTitleReceiver.java similarity index 98% rename from app/src/main/java/com/github/dfa/diaspora_android/receivers/UpdateTitleReceiver.java rename to app/src/main/java/com/github/dfa/diaspora_android/receiver/UpdateTitleReceiver.java index 10ddc5f5..bb30421a 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/receivers/UpdateTitleReceiver.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/receiver/UpdateTitleReceiver.java @@ -1,4 +1,4 @@ -package com.github.dfa.diaspora_android.receivers; +package com.github.dfa.diaspora_android.receiver; import android.content.BroadcastReceiver; import android.content.Context; diff --git a/app/src/main/res/layout/about__activity.xml b/app/src/main/res/layout/about__activity.xml index c686e81e..34de3bfd 100644 --- a/app/src/main/res/layout/about__activity.xml +++ b/app/src/main/res/layout/about__activity.xml @@ -26,7 +26,7 @@ + android:id="@+id/main__topbar"/> - + - + android:layout_centerVertical="true" /> - - - - - - - - - + app:showAsAction="always" + android:orderInCategory="400" + android:title="@string/action_go_to_top" /> - + /> diff --git a/app/src/main/res/menu/main__menu_top.xml b/app/src/main/res/menu/main__menu_top.xml index d6c873b7..73ea3bc7 100644 --- a/app/src/main/res/menu/main__menu_top.xml +++ b/app/src/main/res/menu/main__menu_top.xml @@ -6,19 +6,16 @@ + /> - - + app:showAsAction="always" + android:orderInCategory="200" + android:title="@string/conversations" /> diff --git a/app/src/main/res/menu/stream__menu_bottom.xml b/app/src/main/res/menu/stream__menu_bottom.xml new file mode 100644 index 00000000..f93e1b19 --- /dev/null +++ b/app/src/main/res/menu/stream__menu_bottom.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/stream__menu_top.xml b/app/src/main/res/menu/stream__menu_top.xml new file mode 100644 index 00000000..9d948098 --- /dev/null +++ b/app/src/main/res/menu/stream__menu_top.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 052b2e6a..54903cde 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.3' + classpath 'com.android.tools.build:gradle:2.2.0' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' // NOTE: Do not place your application dependencies here; they belong From 3d2fce6ac0da706a6013637aa7bb155efdf111d6 Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Wed, 21 Sep 2016 21:35:03 +0200 Subject: [PATCH 006/360] Fixed layout issue (webview below topbar --- .../activity/MainActivity.java | 21 +++++++------------ .../fragment/StreamFragment.java | 6 ++++++ app/src/main/res/layout/main__app_bar.xml | 18 +++++++++------- app/src/main/res/layout/stream__fragment.xml | 20 ++++++------------ app/src/main/res/layout/ui__webview.xml | 13 ------------ 5 files changed, 29 insertions(+), 49 deletions(-) delete mode 100644 app/src/main/res/layout/ui__webview.xml 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 8e113f13..86966c4c 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 @@ -183,13 +183,6 @@ public class MainActivity extends AppCompatActivity setContentView(R.layout.main__activity); ButterKnife.bind(this); - fm = getSupportFragmentManager(); - if(fm.findFragmentByTag(StreamFragment.TAG) == null) { - fm.beginTransaction().replace(R.id.fragment_container, new StreamFragment()).commit(); - } else { - fm.beginTransaction().replace(R.id.fragment_container, fm.findFragmentByTag(StreamFragment.TAG)).commit(); - } - if ((app = (App) getApplication()) == null) AppLog.e(this, "App is null!"); if ((appSettings = app.getSettings()) == null) AppLog.e(this, "AppSettings is null!"); if ((podUserProfile = app.getPodUserProfile()) == null) @@ -199,6 +192,11 @@ public class MainActivity extends AppCompatActivity urls = new DiasporaUrlHelper(appSettings); customTabActivityHelper = new CustomTabActivityHelper(); + fm = getSupportFragmentManager(); + StreamFragment sf = getStreamFragment(); + fm.beginTransaction().replace(R.id.fragment_container, sf, StreamFragment.TAG).commit(); + sf.onCreateBottomOptionsMenu(toolbarBottom.getMenu(), getMenuInflater()); + setupUI(savedInstanceState); brOpenExternalLink = new OpenExternalLinkReceiver(this); @@ -256,6 +254,7 @@ public class MainActivity extends AppCompatActivity public void openDiasporaUrl(String url) { StreamFragment streamFragment = getStreamFragment(); if(!streamFragment.isVisible()) { + AppLog.d(this, "StreamFragment not visible"); fm.beginTransaction().replace(R.id.fragment_container, streamFragment, StreamFragment.TAG).commit(); streamFragment.onCreateBottomOptionsMenu(toolbarBottom.getMenu(), getMenuInflater()); } @@ -265,6 +264,7 @@ public class MainActivity extends AppCompatActivity public StreamFragment getStreamFragment() { StreamFragment streamFragment = (StreamFragment) fm.findFragmentByTag(StreamFragment.TAG); if(streamFragment == null) { + AppLog.d(this, "StreamFragment was null"); streamFragment = new StreamFragment(); } return streamFragment; @@ -275,13 +275,6 @@ public class MainActivity extends AppCompatActivity AppLog.i(this, "onConfigurationChanged()"); super.onConfigurationChanged(newConfig); - - // Load the layout resource for the new configuration - setContentView(R.layout.main__activity); - - // Reinitialize the UI - AppLog.v(this, "Rebuild the UI"); - setupUI(null); } private void setupNavigationSlider() { diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java index cdf28103..5a375e35 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java @@ -138,4 +138,10 @@ public class StreamFragment extends WebViewFragment { } return false; } + + @Override + public ContextMenuWebView getWebView() { + AppLog.d(this, "getWebView: "+(this.webView != null)); + return this.webView; + } } diff --git a/app/src/main/res/layout/main__app_bar.xml b/app/src/main/res/layout/main__app_bar.xml index d2b73082..8d217e2b 100644 --- a/app/src/main/res/layout/main__app_bar.xml +++ b/app/src/main/res/layout/main__app_bar.xml @@ -1,10 +1,11 @@ - + + android:layout_width="fill_parent" + android:layout_height="fill_parent" + app:layout_behavior="@string/appbar_scrolling_view_behavior"/> - + + android:layout_height="match_parent" /> + android:progressDrawable="@drawable/progressbar"/> \ No newline at end of file diff --git a/app/src/main/res/layout/ui__webview.xml b/app/src/main/res/layout/ui__webview.xml deleted file mode 100644 index 35d12bc4..00000000 --- a/app/src/main/res/layout/ui__webview.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - \ No newline at end of file From bd8b5381ea5fcfc29cad36aba61cd22084d3e941 Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Wed, 21 Sep 2016 22:49:37 +0200 Subject: [PATCH 007/360] Prewarm customTabs --- .../activity/MainActivity.java | 19 ++++++++++++++++++- .../CustomTabActivityHelper.java | 4 ++++ build.gradle | 2 +- 3 files changed, 23 insertions(+), 2 deletions(-) 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 c736489e..1bc40b64 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 @@ -42,6 +42,8 @@ import android.os.Handler; import android.os.StrictMode; import android.provider.MediaStore; import android.support.annotation.NonNull; +import android.support.customtabs.CustomTabsClient; +import android.support.customtabs.CustomTabsSession; import android.support.design.widget.AppBarLayout; import android.support.design.widget.NavigationView; import android.support.design.widget.Snackbar; @@ -107,7 +109,7 @@ import info.guardianproject.netcipher.NetCipher; import info.guardianproject.netcipher.webkit.WebkitProxy; public class MainActivity extends AppCompatActivity - implements NavigationView.OnNavigationItemSelectedListener, WebUserProfileChangedListener { + implements NavigationView.OnNavigationItemSelectedListener, WebUserProfileChangedListener, CustomTabActivityHelper.ConnectionCallback { private static final int INPUT_FILE_REQUEST_CODE_NEW = 1; @@ -141,6 +143,7 @@ public class MainActivity extends AppCompatActivity private Snackbar snackbarExitApp; private Snackbar snackbarNoInternet; private String textToBeShared = null; + private CustomTabsSession customTabsSession; /** * UI Bindings @@ -196,6 +199,7 @@ public class MainActivity extends AppCompatActivity podUserProfile.setListener(this); urls = new DiasporaUrlHelper(appSettings); customTabActivityHelper = new CustomTabActivityHelper(); + customTabActivityHelper.setConnectionCallback(this); setupUI(savedInstanceState); @@ -1079,6 +1083,19 @@ public class MainActivity extends AppCompatActivity invalidateOptionsMenu(); } + @Override + public void onCustomTabsConnected() { + if(customTabsSession == null) { + AppLog.i(this, "CustomTabs warmup: "+customTabActivityHelper.warmup(0)); + customTabsSession = customTabActivityHelper.getSession(); + } + } + + @Override + public void onCustomTabsDisconnected() { + + } + private class JavaScriptInterface { @JavascriptInterface public void setUserProfile(final String webMessage) throws JSONException { diff --git a/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/CustomTabActivityHelper.java b/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/CustomTabActivityHelper.java index e43ce0b0..2ab3fc3b 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/CustomTabActivityHelper.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/util/CustomTabHelpers/CustomTabActivityHelper.java @@ -118,6 +118,10 @@ public class CustomTabActivityHelper { return session.mayLaunchUrl(uri, extras, otherLikelyBundles); } + public boolean warmup(int flags) { + return mClient.warmup(flags); + } + /** * A Callback for when the service is connected or disconnected. Use those callbacks to * handle UI changes when the service is connected or disconnected diff --git a/build.gradle b/build.gradle index 052b2e6a..54903cde 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.3' + classpath 'com.android.tools.build:gradle:2.2.0' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' // NOTE: Do not place your application dependencies here; they belong From 179fb3e7416f36a3fee697a2b9d2381923c71340 Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Thu, 22 Sep 2016 00:40:35 +0200 Subject: [PATCH 008/360] Removed onPause and onResume in oder to fix issue with image upload --- .../fragment/StreamFragment.java | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java index 512dd7d4..4f735b5c 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java @@ -48,7 +48,6 @@ public class StreamFragment extends WebViewFragment { public static final String TAG = "com.github.dfa.diaspora_android.StreamFragment"; private DiasporaUrlHelper urls; - private Bundle webViewState; private ValueCallback imageUploadFilePathCallbackNew; private ValueCallback imageUploadFilePathCallbackOld; @@ -268,21 +267,6 @@ public class StreamFragment extends WebViewFragment { return super.onOptionsItemSelected(item); } - @Override - public void onPause() { - super.onPause(); - webViewState = new Bundle(); - webView.saveState(webViewState); - } - - @Override - public void onResume() { - super.onResume(); - if(webViewState != null) { - webView.restoreState(webViewState); - } - } - @Override public ContextMenuWebView getWebView() { AppLog.d(this, "getWebView: "+(this.webView != null)); From a1ca8596b80053ee20d938cac169deeb4d9e6e3d Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Thu, 22 Sep 2016 00:54:32 +0200 Subject: [PATCH 009/360] forward clicks on bottom toolbar to fragments onOptionsItemSelected --- .../dfa/diaspora_android/activity/MainActivity.java | 3 ++- .../diaspora_android/fragment/CustomFragment.java | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) 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 f53ac55b..32e9c33e 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 @@ -188,7 +188,8 @@ public class MainActivity extends AppCompatActivity getMenuInflater().inflate(R.menu.main__menu_bottom, toolbarBottom.getMenu()); toolbarBottom.setOnMenuItemClickListener(new ActionMenuView.OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { - return MainActivity.this.onOptionsItemSelected(item); + CustomFragment topFrag = (CustomFragment) getTopFragment(); + return MainActivity.this.onOptionsItemSelected(item) || (topFrag != null && topFrag.onOptionsItemSelected(item)); } }); setTitle(R.string.app_name); diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/CustomFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/CustomFragment.java index b4398d16..255370cc 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/fragment/CustomFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/CustomFragment.java @@ -1,5 +1,6 @@ package com.github.dfa.diaspora_android.fragment; +import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.Menu; import android.view.MenuInflater; @@ -10,6 +11,17 @@ import android.view.MenuInflater; */ public abstract class CustomFragment extends Fragment { + + /** + * We have an optionsMenu + * @param savedInstanceState state + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + /** * Return the tag used to identify the Fragment. * @return tag From 5c41c62c8502766a152e93dab9366bb3c5019a8e Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Thu, 22 Sep 2016 23:20:13 +0200 Subject: [PATCH 010/360] Set windowSoftInputMode to adjustResize, Repair sharing text into app, Repair image sharing on 4.2 --- app/src/main/AndroidManifest.xml | 2 +- .../activity/MainActivity.java | 22 ++++++++++++++----- .../fragment/StreamFragment.java | 22 ++++++++++--------- .../fragment/WebViewFragment.java | 21 ++++++++++++++---- 4 files changed, 46 insertions(+), 21 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2ef6cc59..7b75d8d3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -53,7 +53,7 @@ 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 32e9c33e..c7e39fc1 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 @@ -134,6 +134,8 @@ public class MainActivity extends AppCompatActivity private TextView navheaderDescription; private ImageView navheaderImage; + private String textToBeShared; + /** * END UI Bindings @@ -234,6 +236,7 @@ public class MainActivity extends AppCompatActivity if(streamFragment == null) { AppLog.d(this, "StreamFragment was null"); streamFragment = new StreamFragment(); + fm.beginTransaction().add(streamFragment, StreamFragment.TAG).commit(); } return streamFragment; } @@ -601,11 +604,10 @@ public class MainActivity extends AppCompatActivity AppLog.v(this, "handleSendText()"); try { setSharedTexts(null, intent.getStringExtra(Intent.EXTRA_TEXT)); + openDiasporaUrl(urls.getNewPostUrl()); } catch (Exception e) { AppLog.e(this, e.toString()); } - openDiasporaUrl(urls.getBlankUrl()); - openDiasporaUrl(urls.getNewPostUrl()); } /** @@ -617,11 +619,10 @@ public class MainActivity extends AppCompatActivity AppLog.v(this, "handleSendSubject()"); try { setSharedTexts(intent.getStringExtra(Intent.EXTRA_SUBJECT), intent.getStringExtra(Intent.EXTRA_TEXT)); + openDiasporaUrl(urls.getNewPostUrl()); } catch (Exception e) { AppLog.e(this, e.toString()); } - openDiasporaUrl(urls.getBlankUrl()); //TODO: Necessary? - openDiasporaUrl(urls.getNewPostUrl()); } /** @@ -645,10 +646,11 @@ public class MainActivity extends AppCompatActivity if (sharedSubject != null) { AppLog.v(this, "Append subject to shared text"); String escapedSubject = WebHelper.escapeHtmlText(WebHelper.replaceUrlWithMarkdown(sharedSubject)); - getStreamFragment().setTextToBeShared("**" + escapedSubject + "** " + escapedBody); + AppLog.v(this, "Set shared text; Subject: \"" + escapedSubject + "\" Body: \"" + escapedBody + "\""); + textToBeShared = "**" + escapedSubject + "** " + escapedBody; } else { AppLog.v(this, "Set shared text; Subject: \"" + sharedSubject + "\" Body: \"" + sharedBody + "\""); - getStreamFragment().setTextToBeShared(escapedBody); + textToBeShared = escapedBody; } } @@ -824,4 +826,12 @@ public class MainActivity extends AppCompatActivity grantResults); } } + + public String getTextToBeShared() { + return textToBeShared; + } + + public void setTextToBeShared(String textToBeShared) { + this.textToBeShared = textToBeShared; + } } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java index 4f735b5c..90dba5f8 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java @@ -52,7 +52,6 @@ public class StreamFragment extends WebViewFragment { private ValueCallback imageUploadFilePathCallbackNew; private ValueCallback imageUploadFilePathCallbackOld; private String mCameraPhotoPath; - protected String textToBeShared; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -76,11 +75,19 @@ public class StreamFragment extends WebViewFragment { // Setup WebView webView.addJavascriptInterface(new JavaScriptInterface(), "AndroidBridge"); + setWebChromeClient(); - if(webView.getUrl() == null) { + if(pendingUrl != null) { + loadUrl(pendingUrl); + pendingUrl = null; + } else if (webView.getUrl() == null) { loadUrl(urls.getPodUrl()); } + this.setRetainInstance(true); + } + + private void setWebChromeClient() { //Set WebChromeClient webView.setWebChromeClient(new WebChromeClient() { final ProgressBar pb = progressBar; @@ -96,6 +103,7 @@ public class StreamFragment extends WebViewFragment { if (progress > 60) { WebHelper.optimizeMobileSiteLayout(wv); + String textToBeShared = ((MainActivity)getActivity()).getTextToBeShared(); if (textToBeShared != null) { AppLog.d(this, "Share text into webView"); WebHelper.shareTextIntoWebView(wv, textToBeShared); @@ -110,7 +118,7 @@ public class StreamFragment extends WebViewFragment { protected void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) { AppLog.v(this, "openFileChooser(ValCallback, String, String"); - //imageUploadFilePathCallbackOld = uploadMsg; + imageUploadFilePathCallbackOld = uploadMsg; Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); @@ -188,8 +196,6 @@ public class StreamFragment extends WebViewFragment { return true; } }); - - this.setRetainInstance(true); } @Override @@ -273,10 +279,6 @@ public class StreamFragment extends WebViewFragment { return this.webView; } - public void setTextToBeShared(String text) { - this.textToBeShared = text; - } - public void onImageUploadResult(int requestCode, int resultCode, Intent data) { AppLog.d(this, "onImageUploadResult"); switch (requestCode) { @@ -359,7 +361,7 @@ public class StreamFragment extends WebViewFragment { @JavascriptInterface public void contentHasBeenShared() { - textToBeShared = null; + ((MainActivity)getActivity()).setTextToBeShared(null); } } } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/WebViewFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/WebViewFragment.java index 4f6b9bfb..7127e427 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/fragment/WebViewFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/WebViewFragment.java @@ -54,6 +54,8 @@ public abstract class WebViewFragment extends CustomFragment { protected ProgressBar progressBar; protected AppSettings appSettings; + protected String pendingUrl; + public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); } @@ -279,17 +281,28 @@ public abstract class WebViewFragment extends CustomFragment { } public void loadUrl(String url) { - AppLog.v(this, "loadUrl("+url+")"); - getWebView().loadUrlNew(url); + if(getWebView() != null) { + AppLog.v(this, "loadUrl(): load "+url); + getWebView().loadUrlNew(url); + } else { + AppLog.v(this, "loadUrl(): WebView null: Set pending url to "+url); + pendingUrl = url; + } } public String getUrl() { - return getWebView().getUrl(); + if(getWebView() != null) { + return getWebView().getUrl(); + } else { + return pendingUrl; + } } public void reloadUrl() { AppLog.v(this, "reloadUrl()"); - getWebView().reload(); + if(getWebView() != null) { + getWebView().reload(); + } } public ContextMenuWebView getWebView() { From 2aaddec3a3723997aa2e76362e88117bee39106b Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Thu, 22 Sep 2016 23:40:35 +0200 Subject: [PATCH 011/360] Fix view intent --- .../dfa/diaspora_android/activity/MainActivity.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) 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 c7e39fc1..19add8dd 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 @@ -180,6 +180,7 @@ public class MainActivity extends AppCompatActivity MainActivity.this.setTitle(title); } }); + handleIntent(getIntent()); } private void setupUI(Bundle savedInstanceState) { @@ -218,10 +219,10 @@ public class MainActivity extends AppCompatActivity } AppLog.v(this, "UI successfully set up"); - handleIntent(getIntent()); } public void openDiasporaUrl(String url) { + AppLog.v(this, "openDiasporaUrl()"); StreamFragment streamFragment = getStreamFragment(); if(!streamFragment.isVisible()) { AppLog.d(this, "StreamFragment not visible"); @@ -232,6 +233,7 @@ public class MainActivity extends AppCompatActivity } public StreamFragment getStreamFragment() { + AppLog.v(this, "getStreamFragment()"); StreamFragment streamFragment = (StreamFragment) fm.findFragmentByTag(StreamFragment.TAG); if(streamFragment == null) { AppLog.d(this, "StreamFragment was null"); @@ -345,6 +347,7 @@ public class MainActivity extends AppCompatActivity return; } else { loadUrl = intent.getDataString(); + AppLog.v(this, "Intent has a delicious URL for us: "+loadUrl); } } else if (ACTION_CHANGE_ACCOUNT.equals(action)) { AppLog.v(this, "Reset pod data and animate to PodSelectionActivity"); @@ -416,13 +419,13 @@ public class MainActivity extends AppCompatActivity } CustomFragment top = (CustomFragment) getTopFragment(); if(top != null) { - AppLog.d(this, "Top Fragment is not null"); + AppLog.v(this, "Top Fragment is not null"); if(!top.onBackPressed()) { - AppLog.d(this, "Top Fragment.onBackPressed was false"); - //TODO: Go back in Fragment backstack + AppLog.v(this, "Top Fragment.onBackPressed was false"); + snackbarExitApp.show(); return; } else { - AppLog.d(this, "Top Fragment.onBackPressed was true"); + AppLog.v(this, "Top Fragment.onBackPressed was true"); return; } } From a04e2051a8d89b6eb58d7564149356df357bcb8b Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Mon, 26 Sep 2016 16:28:17 +0200 Subject: [PATCH 012/360] Update TR; Update buildToolsVersion -> 24.0.2 --- .travis.yml | 2 +- app/build.gradle | 4 +- .../res/values-fr/strings-preferences.xml | 1 + .../res/values-it/strings-preferences.xml | 4 ++ .../res/values-ja/strings-preferences.xml | 2 + tools/localization/.gitignore | 1 - tools/localization/downloadLocalizations.sh | 40 ------------------- 7 files changed, 10 insertions(+), 44 deletions(-) delete mode 100755 tools/localization/.gitignore delete mode 100755 tools/localization/downloadLocalizations.sh diff --git a/.travis.yml b/.travis.yml index 74b79b85..41f1aaaa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ android: - tools - tools # TODO https://github.com/travis-ci/travis-ci/issues/6193 - platform-tools - - build-tools-24.0.1 + - build-tools-24.0.2 - android-24 - extra-android-m2repository before_cache: diff --git a/app/build.gradle b/app/build.gradle index 4cb94656..0e7cceec 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,14 +3,14 @@ apply plugin: 'android-apt' android { compileSdkVersion 24 - buildToolsVersion "24.0.1" + buildToolsVersion "24.0.2" defaultConfig { applicationId "com.github.dfa.diaspora_android" minSdkVersion 17 targetSdkVersion 24 versionCode 8 - versionName "0.1.6" + versionName "0.1.6-next" } buildTypes { release { diff --git a/app/src/main/res/values-fr/strings-preferences.xml b/app/src/main/res/values-fr/strings-preferences.xml index 48b8d71d..0406f8e6 100644 --- a/app/src/main/res/values-fr/strings-preferences.xml +++ b/app/src/main/res/values-fr/strings-preferences.xml @@ -21,6 +21,7 @@ Charger les images Désactiver le chargements des images pour préserver la data mobile + Proxy Activer Proxy Serveur Proxy.\n(Nécessite un redémarrage) Hôte diff --git a/app/src/main/res/values-it/strings-preferences.xml b/app/src/main/res/values-it/strings-preferences.xml index 01fbf921..71aa9c99 100644 --- a/app/src/main/res/values-it/strings-preferences.xml +++ b/app/src/main/res/values-it/strings-preferences.xml @@ -21,11 +21,15 @@ Carica immagini Disabilita il caricamento delle immagini per risparmiare la rete dati + Proxy + @string/pref_desc__proxy_enabled Attiva proxy Traffico del proxy di Diaspora per bypassare i firewall.\nPuò essere necessario il riavvio dell\'app Host Porta + Schede personalizzate di Chrome + Apri collegamento esterno nelle schede personalizzate di Chrome. Per usare questa funzione Chromium o Google Chrome deve essere installato Impostazioni personali Apri le impostazioni del tuo account Diaspora diff --git a/app/src/main/res/values-ja/strings-preferences.xml b/app/src/main/res/values-ja/strings-preferences.xml index 909ff218..2d88e3e2 100644 --- a/app/src/main/res/values-ja/strings-preferences.xml +++ b/app/src/main/res/values-ja/strings-preferences.xml @@ -21,6 +21,8 @@ 画像の読み込み 安全なモバイルデータのため、画像の読み込みを無効にします + プロキシ + @string/pref_desc__proxy_enabled プロキシを有効にする Diaspora の通信をプロキシして、ファイアウォールに回避します。\n再起動が必要になることがあります ホスト diff --git a/tools/localization/.gitignore b/tools/localization/.gitignore deleted file mode 100755 index 98626981..00000000 --- a/tools/localization/.gitignore +++ /dev/null @@ -1 +0,0 @@ -crowdin.yaml diff --git a/tools/localization/downloadLocalizations.sh b/tools/localization/downloadLocalizations.sh deleted file mode 100755 index 86fc3252..00000000 --- a/tools/localization/downloadLocalizations.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash -######################################################### -# -# Title -# -# Created by Gregor Santer (gsantner), 2016 -# https://gsantner.github.io/ -# -######################################################### - - -#Pfade -SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -SCRIPTFILE=$(readlink -f $0) -SCRIPTPATH=$(dirname $SCRIPTFILE) -argc=$# - -######################################################### -cd "$SCRIPTDIR" - -if [ ! -f "crowdin.yaml" ] ; then - echo "project_identifier: diaspora-for-android" > 'crowdin.yaml' - echo "base_path: $(realpath '../../')" >>'crowdin.yaml' - echo "api_key: DONT_PUSH_API_KEY" >>'crowdin.yaml' - cat "../../crowdin.yaml" >> "crowdin.yaml" - echo "# Add all non locality languages here" >> "crowdin.yaml" - echo "# (e.g. enUS, enUK, deCH, deAT will automatically go into the right folder)" >> "crowdin.yaml" - echo "# Otherwise e.g. en would get added into the folder enEN (which is wrong)." >> "crowdin.yaml" - echo "# https://crowdin.com/page/api/language-codes contains supported language codes" >> "crowdin.yaml" - echo "# The first listed ones here are diffently managed by crowdin than on android" >> "crowdin.yaml" -fi - -if grep -q "DONT_PUSH" "crowdin.yaml" ; then - echo "Insert API key to crowdin.yaml" - echo "and update folder to the root folder of the repository" - exit -fi - -# Load latest translations -crowdin-cli download -b master From 8a94bf57667362de3a0c1a3f706a384bb2acefe4 Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Mon, 26 Sep 2016 20:53:58 +0200 Subject: [PATCH 013/360] Update ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 8fc720b8..6a7ba75d 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -24,10 +24,10 @@ I have: #### Expected result +**What is the expected output?** -What is the expected output? +**What do you see instead?** -What do you see instead? Upload screenshots via drag&drop if needed and apply resizing: `` From 73895c9ddb051469121822ee295e03d934a98e70 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Mon, 26 Sep 2016 23:01:21 +0200 Subject: [PATCH 014/360] Update README.md --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a2696020..201b7cfa 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ [![F-Droid](https://f-droid.org/wiki/images/0/06/F-Droid-button_get-it-on.png)](https://f-droid.org/repository/browse/?fdid=com.github.dfa.diaspora_android) -[![Build Status](https://travis-ci.org/Diaspora-for-Android/diaspora-android.svg?branch=master)](https://travis-ci.org/Diaspora-for-Android/diaspora-android) +[![Build Status](https://travis-ci.org/Diaspora-for-Android/diaspora-android.svg?branch=master)](https://travis-ci.org/Diaspora-for-Android/diaspora-android) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/diaspora-for-android/localized.svg)](https://crowdin.com/project/diaspora-for-android) -[![Join the chat at https://gitter.im/Diaspora-for-Android/diaspora-android](https://badges.gitter.im/Diaspora-for-Android/diaspora-android.svg)](https://gitter.im/Diaspora-for-Android/diaspora-android?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Chat - FreeNode IRC](https://img.shields.io/badge/chat-on%20freenode-blue.svg)](https://kiwiirc.com/client/irc.freenode.net/?nick=user-dfa|?#diaspora-for-android) +[![Chat - Gitter](https://img.shields.io/badge/chat-on%20gitter-blue.svg)](https://gitter.im/Diaspora-for-Android/diaspora-android) # Diaspora for Android @@ -15,11 +16,11 @@ This is an unofficial webview based client for the community-run, distributed so ## Contributions We are always open for any kind of contribution. (PR's, bug reports, feature requests, translations, ..) -If you got any questions feel free to join our XMPP/Jabber conference at `diaspora-android@conference.jabberhead.tk` or [Gitter](https://gitter.im/Diaspora-for-Android/diaspora-android). -Note that the main project members are mostly busy with their job/university/school and may not react or start coding immediately. +If you got any questions feel free to contact us on IRC, XMPP or Gitter. You can start chatting by clicking on the [blue chat badges](#badgers) listed on top. -We use Crowdin to translate Diaspora for Android. Join our project here: -If your desired language is not listed please contact the maintainers/owner. +We use Crowdin to translate Diaspora for Android. Join our project here: . If your desired language is not listed please contact the maintainers/owner. + +Note that the main project members are working on this project for free during leisure time, are mostly busy with their job/university/school, and may not react or start coding immediately. ### License It's released under GNU GENERAL PUBLIC LICENSE (see [LICENCE](https://github.com/Diaspora-for-Android/diaspora-android/blob/master/LICENSE.md)). @@ -38,5 +39,5 @@ The minimum version supported is Jelly Bean, Android v4.2.0 / API 17 It requires access to the Internet and to external storage to be able to upload photos when creating a new post and for taking screenshots. ## Maintainers -- gsantner ([GitHub](https://github.com/gsantner), [Web](https://gsantner.github.io)) +- gsantner ([GitHub](https://github.com/gsantner), [Web](https://gsantner.github.io), [diaspora*](https://pod.geraspora.de/people/d1cbdd70095301341e834860008dbc6c)) - vanitasvitae ([GitHub](https://github.com/vanitasvitae)) From 4c8602b37da6a951d0a570dc712979596750c826 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Tue, 27 Sep 2016 01:07:40 +0200 Subject: [PATCH 015/360] Switch ic_launcher back to png --- SCREENSHOTS.md | 26 ++++++++++++------ .../main/res/drawable-hdpi/ic_launcher.png | Bin 0 -> 3372 bytes .../main/res/drawable-ldpi/ic_launcher.png | Bin 0 -> 1709 bytes .../main/res/drawable-mdpi/ic_launcher.png | Bin 0 -> 2204 bytes .../main/res/drawable-xhdpi/ic_launcher.png | Bin 0 -> 4611 bytes .../main/res/drawable-xxhdpi/ic_launcher.png | Bin 0 -> 7179 bytes .../main/res/drawable-xxxhdpi/ic_launcher.png | Bin 0 -> 9637 bytes app/src/main/res/drawable/ic_launcher.xml | 6 ---- 8 files changed, 18 insertions(+), 14 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/ic_launcher.png create mode 100644 app/src/main/res/drawable-ldpi/ic_launcher.png create mode 100644 app/src/main/res/drawable-mdpi/ic_launcher.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_launcher.png delete mode 100644 app/src/main/res/drawable/ic_launcher.xml diff --git a/SCREENSHOTS.md b/SCREENSHOTS.md index 368da74a..8f443531 100644 --- a/SCREENSHOTS.md +++ b/SCREENSHOTS.md @@ -1,14 +1,24 @@ - - - - + + + + - - - - + + + + + + + + + + + + + +
diff --git a/app/src/main/res/drawable-hdpi/ic_launcher.png b/app/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..11f95124d64006c472554ab279b048bebd642be3 GIT binary patch literal 3372 zcmV+{4b$?8P)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00006 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 D?xfu} literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_launcher.png b/app/src/main/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..b356e40a1808b9fc9dc08e1ebcfe2c3174e2573d GIT binary patch literal 2204 zcmV;N2xIq&P)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00006 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/app/src/main/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..2001d85829cb034f678ec047588a5fca36e94fe6 GIT binary patch literal 7179 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 JM&2s&e*hhzXJh~X literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_launcher.png b/app/src/main/res/drawable-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..0d77fa66d8f6661995cc5606d97689a83bb7fb51 GIT binary patch literal 9637 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 - - - From 8e9dabe951901adb777bb3694bd606cdae1a768e Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Tue, 27 Sep 2016 01:24:07 +0200 Subject: [PATCH 016/360] Replace blowball image on splash with character --- app/src/main/res/layout/splash__activity.xml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/layout/splash__activity.xml b/app/src/main/res/layout/splash__activity.xml index 5f65f563..5b6d5df3 100644 --- a/app/src/main/res/layout/splash__activity.xml +++ b/app/src/main/res/layout/splash__activity.xml @@ -10,16 +10,17 @@ android:paddingTop="@dimen/activity_vertical_margin" tools:context=".activity.SplashActivity"> - + android:text="*" + android:textAppearance="?android:attr/textAppearanceLarge" + android:textColor="@color/white" + android:textSize="120dp" + android:textStyle="bold"/>
From e4d4305fc119477b7c2a56b22c6fe5585b103baa Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Wed, 28 Sep 2016 21:43:25 +0200 Subject: [PATCH 017/360] Reworked UI using Fragments --- .../activity/AboutActivity.java | 2 +- .../activity/MainActivity.java | 125 +++++--- ...ViewFragment.java => BrowserFragment.java} | 96 +++++-- .../fragment/CustomFragment.java | 2 + ...gment.java => DiasporaStreamFragment.java} | 271 ++++++++---------- .../fragment/TestFragment.java | 39 +++ .../ui/DiasporaStreamWebChromeClient.java | 44 +++ .../ui/FileUploadWebChromeClient.java | 41 +++ .../ui/ProgressBarWebChromeClient.java | 26 ++ .../dfa/diaspora_android/util/WebHelper.java | 2 +- app/src/main/res/layout/about__activity.xml | 2 +- ...am__fragment.xml => browser__fragment.xml} | 0 app/src/main/res/layout/test__fragment.xml | 11 + app/src/main/res/menu/main__menu_bottom.xml | 7 + app/src/main/res/menu/main__navdrawer.xml | 2 +- 15 files changed, 447 insertions(+), 223 deletions(-) rename app/src/main/java/com/github/dfa/diaspora_android/fragment/{WebViewFragment.java => BrowserFragment.java} (84%) rename app/src/main/java/com/github/dfa/diaspora_android/fragment/{StreamFragment.java => DiasporaStreamFragment.java} (54%) create mode 100644 app/src/main/java/com/github/dfa/diaspora_android/fragment/TestFragment.java create mode 100644 app/src/main/java/com/github/dfa/diaspora_android/ui/DiasporaStreamWebChromeClient.java create mode 100644 app/src/main/java/com/github/dfa/diaspora_android/ui/FileUploadWebChromeClient.java create mode 100644 app/src/main/java/com/github/dfa/diaspora_android/ui/ProgressBarWebChromeClient.java rename app/src/main/res/layout/{stream__fragment.xml => browser__fragment.xml} (100%) create mode 100644 app/src/main/res/layout/test__fragment.xml diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/AboutActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/AboutActivity.java index 4d8e2ecd..cc9cf36d 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/AboutActivity.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/AboutActivity.java @@ -65,7 +65,7 @@ public class AboutActivity extends AppCompatActivity { @BindView(R.id.main__topbar) protected Toolbar toolbar; - @BindView(R.id.linearlayout) + @BindView(R.id.appbar_linear_layout) protected LinearLayout linearLayout; @Override 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 19add8dd..244bbc05 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 @@ -62,8 +62,10 @@ import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.data.AppSettings; import com.github.dfa.diaspora_android.data.PodUserProfile; +import com.github.dfa.diaspora_android.fragment.BrowserFragment; import com.github.dfa.diaspora_android.fragment.CustomFragment; -import com.github.dfa.diaspora_android.fragment.StreamFragment; +import com.github.dfa.diaspora_android.fragment.DiasporaStreamFragment; +import com.github.dfa.diaspora_android.fragment.TestFragment; import com.github.dfa.diaspora_android.listener.WebUserProfileChangedListener; import com.github.dfa.diaspora_android.receiver.OpenExternalLinkReceiver; import com.github.dfa.diaspora_android.receiver.UpdateTitleReceiver; @@ -162,10 +164,6 @@ public class MainActivity extends AppCompatActivity customTabActivityHelper.setConnectionCallback(this); fm = getSupportFragmentManager(); - StreamFragment sf = getStreamFragment(); - fm.beginTransaction().replace(R.id.fragment_container, sf, StreamFragment.TAG).commit(); - sf.onCreateBottomOptionsMenu(toolbarBottom.getMenu(), getMenuInflater()); - setupUI(savedInstanceState); brOpenExternalLink = new OpenExternalLinkReceiver(this); @@ -180,7 +178,13 @@ public class MainActivity extends AppCompatActivity MainActivity.this.setTitle(title); } }); - handleIntent(getIntent()); + //Handle intent + Intent intent = getIntent(); + if(intent != null && intent.getAction() != null) { + handleIntent(intent); + } else { + openDiasporaUrl(urls.getStreamUrl()); + } } private void setupUI(Bundle savedInstanceState) { @@ -191,8 +195,8 @@ public class MainActivity extends AppCompatActivity getMenuInflater().inflate(R.menu.main__menu_bottom, toolbarBottom.getMenu()); toolbarBottom.setOnMenuItemClickListener(new ActionMenuView.OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { - CustomFragment topFrag = (CustomFragment) getTopFragment(); - return MainActivity.this.onOptionsItemSelected(item) || (topFrag != null && topFrag.onOptionsItemSelected(item)); + CustomFragment top = getTopFragment(); + return MainActivity.this.onOptionsItemSelected(item) || (top != null && top.onOptionsItemSelected(item)); } }); setTitle(R.string.app_name); @@ -221,26 +225,64 @@ public class MainActivity extends AppCompatActivity AppLog.v(this, "UI successfully set up"); } - public void openDiasporaUrl(String url) { + /** + * Show DiasporaStreamFragment if necessary and load URL url + * @param url URL to load in the DiasporaStreamFragment + */ + protected void openDiasporaUrl(String url) { AppLog.v(this, "openDiasporaUrl()"); - StreamFragment streamFragment = getStreamFragment(); - if(!streamFragment.isVisible()) { - AppLog.d(this, "StreamFragment not visible"); - fm.beginTransaction().replace(R.id.fragment_container, streamFragment, StreamFragment.TAG).commit(); - streamFragment.onCreateBottomOptionsMenu(toolbarBottom.getMenu(), getMenuInflater()); - } + DiasporaStreamFragment streamFragment = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG); + showFragment(streamFragment); streamFragment.loadUrl(url); } - public StreamFragment getStreamFragment() { - AppLog.v(this, "getStreamFragment()"); - StreamFragment streamFragment = (StreamFragment) fm.findFragmentByTag(StreamFragment.TAG); - if(streamFragment == null) { - AppLog.d(this, "StreamFragment was null"); - streamFragment = new StreamFragment(); - fm.beginTransaction().add(streamFragment, StreamFragment.TAG).commit(); + /** + * 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. + * If there is no Fragment with the corresponding Tag, return null. + * @param fragmentTag tag + * @return corresponding Fragment + */ + protected CustomFragment getFragment(String fragmentTag) { + CustomFragment fragment = (CustomFragment) fm.findFragmentByTag(fragmentTag); + if(fragment != null) { + return fragment; + } else { + switch (fragmentTag) { + case DiasporaStreamFragment.TAG: + DiasporaStreamFragment dsf = new DiasporaStreamFragment(); + fm.beginTransaction().add(dsf, fragmentTag).commit(); + return dsf; + case BrowserFragment.TAG: + BrowserFragment bf = new BrowserFragment(); + fm.beginTransaction().add(bf, fragmentTag).commit(); + return bf; + case TestFragment.TAG: + TestFragment tf = new TestFragment(); + fm.beginTransaction().add(tf, fragmentTag).commit(); + return tf; + default: + AppLog.e(this,"Invalid Fragment Tag: "+fragmentTag + +"\nAdd Fragments Tag to getFragment()'s switch case."); + return null; + } + } + } + + /** + * Show the Fragment fragment in R.id.fragment_container. If the fragment was already visible, do nothing. + * @param fragment Fragment to show + */ + protected void showFragment(CustomFragment fragment) { + AppLog.d(this, "showFragment()"); + CustomFragment currentTop = (CustomFragment) fm.findFragmentById(R.id.fragment_container); + if(currentTop == null || !currentTop.getFragmentTag().equals(fragment.getFragmentTag())) { + AppLog.d(this, "Fragment was not visible. Replace it."); + fm.beginTransaction().addToBackStack(null).replace(R.id.fragment_container, fragment, fragment.getFragmentTag()).commit(); + fragment.onCreateBottomOptionsMenu(toolbarBottom.getMenu(), getMenuInflater()); + } else { + AppLog.d(this, "Fragment was already visible. Do nothing."); } - return streamFragment; } @Override @@ -307,7 +349,7 @@ public class MainActivity extends AppCompatActivity navMenu.findItem(R.id.nav_aspects).setVisible(appSettings.isVisibleInNavAspects()); navMenu.findItem(R.id.nav_commented).setVisible(appSettings.isVisibleInNavCommented()); navMenu.findItem(R.id.nav_followed_tags).setVisible(appSettings.isVisibleInNavFollowed_tags()); - navMenu.findItem(R.id.nav_help_license).setVisible(appSettings.isVisibleInNavHelp_license()); + navMenu.findItem(R.id.nav_about).setVisible(appSettings.isVisibleInNavHelp_license()); navMenu.findItem(R.id.nav_liked).setVisible(appSettings.isVisibleInNavLiked()); navMenu.findItem(R.id.nav_mentions).setVisible(appSettings.isVisibleInNavMentions()); navMenu.findItem(R.id.nav_profile).setVisible(appSettings.isVisibleInNavProfile()); @@ -351,11 +393,11 @@ public class MainActivity extends AppCompatActivity } } else if (ACTION_CHANGE_ACCOUNT.equals(action)) { AppLog.v(this, "Reset pod data and animate to PodSelectionActivity"); - app.resetPodData(getStreamFragment().getWebView()); + app.resetPodData(((DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG)).getWebView()); Helpers.animateToActivity(MainActivity.this, PodSelectionActivity.class, true); } else if (ACTION_CLEAR_CACHE.equals(action)) { AppLog.v(this, "Clear WebView cache"); - getStreamFragment().getWebView().clearCache(true); + ((DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG)).getWebView().clearCache(true); } else if (ACTION_RELOAD_ACTIVITY.equals(action)) { AppLog.v(this, "Recreate activity"); recreate(); @@ -401,11 +443,10 @@ public class MainActivity extends AppCompatActivity super.onRestoreInstanceState(savedInstanceState); } - private Fragment getTopFragment() { - for(Fragment f : fm.getFragments()) { - if(f.isVisible()) { - return f; - } + private CustomFragment getTopFragment() { + Fragment top = fm.findFragmentById(R.id.fragment_container); + if(top != null) { + return (CustomFragment) top; } return null; } @@ -417,12 +458,17 @@ public class MainActivity extends AppCompatActivity navDrawer.closeDrawer(navView); return; } - CustomFragment top = (CustomFragment) getTopFragment(); + CustomFragment top = getTopFragment(); if(top != null) { AppLog.v(this, "Top Fragment is not null"); if(!top.onBackPressed()) { AppLog.v(this, "Top Fragment.onBackPressed was false"); - snackbarExitApp.show(); + AppLog.d(this, "BackStackEntryCount: "+fm.getBackStackEntryCount()); + if(fm.getBackStackEntryCount()>0) { + fm.popBackStack(); + } else { + snackbarExitApp.show(); + } return; } else { AppLog.v(this, "Top Fragment.onBackPressed was true"); @@ -518,6 +564,11 @@ public class MainActivity extends AppCompatActivity return true; } + case R.id.action_debug_button: { + showFragment(getFragment(TestFragment.TAG)); + return true; + } + case R.id.action_compose: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getNewPostUrl()); @@ -723,9 +774,10 @@ public class MainActivity extends AppCompatActivity //TODO: Replace with fragment case R.id.nav_followed_tags: { + DiasporaStreamFragment stream = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG); if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getBlankUrl()); - WebHelper.showFollowedTagsList(getStreamFragment().getWebView(), app); + WebHelper.showFollowedTagsList(stream.getWebView(), app); setTitle(R.string.nav_followed_tags); } else { snackbarNoInternet.show(); @@ -735,9 +787,10 @@ public class MainActivity extends AppCompatActivity //TODO: Replace with fragment case R.id.nav_aspects: { + DiasporaStreamFragment stream = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG); if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(DiasporaUrlHelper.URL_BLANK); - WebHelper.showAspectList(getStreamFragment().getWebView(), app); + WebHelper.showAspectList(stream.getWebView(), app); setTitle(R.string.aspects); } else { snackbarNoInternet.show(); @@ -801,7 +854,7 @@ public class MainActivity extends AppCompatActivity } break; - case R.id.nav_help_license: { + case R.id.nav_about: { startActivity(new Intent(MainActivity.this, AboutActivity.class)); } break; diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/WebViewFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java similarity index 84% rename from app/src/main/java/com/github/dfa/diaspora_android/fragment/WebViewFragment.java rename to app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java index 7127e427..01fdb390 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/fragment/WebViewFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java @@ -14,10 +14,13 @@ import android.os.Environment; import android.os.StrictMode; import android.support.design.widget.Snackbar; import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; import android.view.View; +import android.view.ViewGroup; import android.webkit.WebSettings; import android.webkit.WebView; -import android.webkit.WebViewClient; import android.widget.ProgressBar; import android.widget.Toast; @@ -27,6 +30,7 @@ import com.github.dfa.diaspora_android.activity.MainActivity; import com.github.dfa.diaspora_android.data.AppSettings; import com.github.dfa.diaspora_android.ui.ContextMenuWebView; import com.github.dfa.diaspora_android.ui.CustomWebViewClient; +import com.github.dfa.diaspora_android.ui.ProgressBarWebChromeClient; import com.github.dfa.diaspora_android.util.AppLog; import java.io.File; @@ -42,29 +46,49 @@ import info.guardianproject.netcipher.NetCipher; import info.guardianproject.netcipher.webkit.WebkitProxy; /** - * Fragment that contains a WebView with a bunch of functionality - * Created by vanitas on 21.09.16. + * Fragment with a webView and a ProgressBar. + * This Fragment retains its instance. + * Created by vanitas on 26.09.16. */ -public abstract class WebViewFragment extends CustomFragment { +public class BrowserFragment extends CustomFragment { + public static final String TAG = "com.github.dfa.diaspora_android.BrowserFragment"; - protected WebSettings webSettings; - protected WebViewClient webViewClient; + protected View rootLayout; protected ContextMenuWebView webView; protected ProgressBar progressBar; protected AppSettings appSettings; + protected CustomWebViewClient webViewClient; + protected WebSettings webSettings; protected String pendingUrl; - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + AppLog.d(this, "onCreateView()"); + if(rootLayout == null) { + rootLayout = inflater.inflate(R.layout.browser__fragment, container, false); + } + return rootLayout; } - protected void setup(ContextMenuWebView webView, final ProgressBar progressBar, AppSettings appSettings) { - this.appSettings = appSettings; - this.webSettings = webView.getSettings(); - this.webView = webView; - this.progressBar = progressBar; + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + AppLog.d(this, "onViewCreated()"); + super.onViewCreated(view, savedInstanceState); + + if(this.appSettings == null) { + this.appSettings = ((App) getActivity().getApplication()).getSettings(); + } + + if(this.webView == null) { + this.webView = (ContextMenuWebView) view.findViewById(R.id.webView); + this.applyWebViewSettings(); + } + + if(this.progressBar == null) { + this.progressBar = (ProgressBar) view.findViewById(R.id.progressBar); + } if (appSettings.isProxyEnabled()) { if (!setProxy(appSettings.getProxyHost(), appSettings.getProxyPort())) { @@ -75,7 +99,25 @@ public abstract class WebViewFragment extends CustomFragment { resetProxy(); } - webSettings.setJavaScriptEnabled(true); + if(pendingUrl != null) { + loadUrl(pendingUrl); + pendingUrl = null; + } + + this.setRetainInstance(true); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + + if (getRetainInstance() && rootLayout.getParent() instanceof ViewGroup) { + ((ViewGroup) rootLayout.getParent()).removeView(rootLayout); + } + } + + private void applyWebViewSettings() { + this.webSettings = webView.getSettings(); webSettings.setAllowFileAccess(false); webSettings.setUseWideViewPort(true); webSettings.setLoadWithOverviewMode(true); @@ -93,21 +135,9 @@ public abstract class WebViewFragment extends CustomFragment { //webView.setParentActivity(this); webView.setOverScrollMode(WebView.OVER_SCROLL_ALWAYS); - //Set proxy - if (appSettings.isProxyEnabled()) { - if (!setProxy(appSettings.getProxyHost(), appSettings.getProxyPort())) { - AppLog.d(this, "Could not enable Proxy"); - Toast.makeText(getContext(), R.string.toast_set_proxy_failed, Toast.LENGTH_SHORT).show(); - } - } else if (appSettings.wasProxyEnabled()) { - resetProxy(); - } - - /* - * WebViewClient - */ this.webViewClient = new CustomWebViewClient((App) getActivity().getApplication(), webView); webView.setWebViewClient(webViewClient); + webView.setWebChromeClient(new ProgressBarWebChromeClient(webView, progressBar)); } /** @@ -153,6 +183,7 @@ public abstract class WebViewFragment extends CustomFragment { } } + @SuppressWarnings("unused") private boolean setProxy() { return setProxy(appSettings.getProxyHost(), appSettings.getProxyPort()); } @@ -175,7 +206,7 @@ public abstract class WebViewFragment extends CustomFragment { AppLog.v(this, "clear WebKit proxy"); WebkitProxy.resetProxy(MainActivity.class.getName(), getContext()); } catch (Exception e) { - AppLog.e(this, "Could not clear WebKit proxy:\n"+e.toString()); + AppLog.e(this, "Could not clear WebKit proxy:\n"+e.toString()); } AppLog.v(this, "Reset old ThreadPolicy"); StrictMode.setThreadPolicy(old); @@ -272,6 +303,15 @@ public abstract class WebViewFragment extends CustomFragment { } @Override + public String getFragmentTag() { + return TAG; + } + + @Override + public void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater) { + /* Nothing to do here */ + } + public boolean onBackPressed() { if(webView.canGoBack()) { webView.goBack(); diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/CustomFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/CustomFragment.java index 255370cc..5b833e37 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/fragment/CustomFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/CustomFragment.java @@ -12,6 +12,8 @@ import android.view.MenuInflater; public abstract class CustomFragment extends Fragment { + public static final String TAG = "com.github.dfa.diaspora_android.CustomFragment"; + /** * We have an optionsMenu * @param savedInstanceState state diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/DiasporaStreamFragment.java similarity index 54% rename from app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java rename to app/src/main/java/com/github/dfa/diaspora_android/fragment/DiasporaStreamFragment.java index 90dba5f8..8a86243c 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/fragment/StreamFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/DiasporaStreamFragment.java @@ -2,6 +2,7 @@ package com.github.dfa.diaspora_android.fragment; import android.Manifest; import android.animation.ObjectAnimator; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.DialogInterface; import android.content.Intent; @@ -12,23 +13,21 @@ import android.os.Bundle; import android.provider.MediaStore; import android.support.design.widget.Snackbar; import android.support.v7.app.AlertDialog; -import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; import android.webkit.JavascriptInterface; import android.webkit.ValueCallback; import android.webkit.WebChromeClient; import android.webkit.WebView; -import android.widget.ProgressBar; import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.activity.MainActivity; import com.github.dfa.diaspora_android.data.PodUserProfile; -import com.github.dfa.diaspora_android.ui.ContextMenuWebView; +import com.github.dfa.diaspora_android.ui.DiasporaStreamWebChromeClient; +import com.github.dfa.diaspora_android.ui.FileUploadWebChromeClient; import com.github.dfa.diaspora_android.util.AppLog; import com.github.dfa.diaspora_android.util.DiasporaUrlHelper; import com.github.dfa.diaspora_android.util.Helpers; @@ -40,167 +39,34 @@ import java.io.File; import java.io.IOException; /** - * Fragment that contains a WebView displaying the stream of the user - * Created by vanitas on 21.09.16. + * Fragment that displays the Stream of the diaspora* user + * Created by vanitas on 26.09.16. */ -public class StreamFragment extends WebViewFragment { +public class DiasporaStreamFragment extends BrowserFragment { public static final String TAG = "com.github.dfa.diaspora_android.StreamFragment"; - private DiasporaUrlHelper urls; + protected DiasporaUrlHelper urls; private ValueCallback imageUploadFilePathCallbackNew; private ValueCallback imageUploadFilePathCallbackOld; private String mCameraPhotoPath; + private String sharedText; - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - AppLog.d(this, "onCreateView()"); - return inflater.inflate(R.layout.stream__fragment, container, false); - } - + @SuppressLint("SetJavaScriptEnabled") @Override public void onViewCreated(View view, Bundle savedInstanceState) { - AppLog.d(this, "onViewCreated()"); super.onViewCreated(view, savedInstanceState); - this.webView = (ContextMenuWebView) view.findViewById(R.id.webView); - this.progressBar = (ProgressBar) view.findViewById(R.id.progressBar); - this.appSettings = ((App) getActivity().getApplication()).getSettings(); this.urls = new DiasporaUrlHelper(appSettings); + webView.setWebChromeClient(new DiasporaStreamWebChromeClient(webView, progressBar, fileUploadCallback, sharedTextCallback)); - this.setup( - webView, - progressBar, - appSettings); - - // Setup WebView + webView.getSettings().setJavaScriptEnabled(true); webView.addJavascriptInterface(new JavaScriptInterface(), "AndroidBridge"); - setWebChromeClient(); - - if(pendingUrl != null) { - loadUrl(pendingUrl); - pendingUrl = null; - } else if (webView.getUrl() == null) { - loadUrl(urls.getPodUrl()); + if(((MainActivity)getActivity()).getTextToBeShared() != null) { + loadUrl(urls.getNewPostUrl()); + } else if(webView.getUrl() == null) { + loadUrl(urls.getStreamUrl()); } - - this.setRetainInstance(true); - } - - private void setWebChromeClient() { - //Set WebChromeClient - webView.setWebChromeClient(new WebChromeClient() { - final ProgressBar pb = progressBar; - - public void onProgressChanged(WebView wv, int progress) { - pb.setProgress(progress); - - if (progress > 0 && progress <= 60) { - WebHelper.getUserProfile(wv); - WebHelper.optimizeMobileSiteLayout(wv); - } - - if (progress > 60) { - WebHelper.optimizeMobileSiteLayout(wv); - - String textToBeShared = ((MainActivity)getActivity()).getTextToBeShared(); - if (textToBeShared != null) { - AppLog.d(this, "Share text into webView"); - WebHelper.shareTextIntoWebView(wv, textToBeShared); - } - } - - progressBar.setVisibility(progress == 100 ? View.GONE : View.VISIBLE); - } - - //For Android 4.1/4.2 only. DO NOT REMOVE! - @SuppressWarnings("unused") - protected void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) - { - AppLog.v(this, "openFileChooser(ValCallback, String, String"); - imageUploadFilePathCallbackOld = uploadMsg; - Intent intent = new Intent(); - intent.setType("image/*"); - intent.setAction(Intent.ACTION_GET_CONTENT); - intent.putExtra("return-data", true); - intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); - AppLog.v(this, "startActivityForResult"); - startActivityForResult(Intent.createChooser(intent, "Select Picture"), MainActivity.INPUT_FILE_REQUEST_CODE_OLD); - } - - @Override - public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) { - if(Build.VERSION.SDK_INT >= 23) { - int hasWRITE_EXTERNAL_STORAGE = getActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE); - if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) { - if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - new AlertDialog.Builder(getContext()) - .setMessage(R.string.permissions_image) - .setNegativeButton(android.R.string.no, null) - .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (android.os.Build.VERSION.SDK_INT >= 23) - requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - MainActivity.REQUEST_CODE_ASK_PERMISSIONS); - } - }) - .show(); - return false; - } - requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - MainActivity.REQUEST_CODE_ASK_PERMISSIONS); - return false; - } - } - AppLog.d(this, "onOpenFileChooser"); - if (imageUploadFilePathCallbackNew != null) imageUploadFilePathCallbackNew.onReceiveValue(null); - imageUploadFilePathCallbackNew = filePathCallback; - Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - if (takePictureIntent.resolveActivity(getContext().getPackageManager()) != null) { - // Create the File where the photo should go - File photoFile; - try { - photoFile = Helpers.createImageFile(); - takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath); - } catch (IOException ex) { - AppLog.e(this, "ERROR creating temp file: "+ ex.toString()); - // Error occurred while creating the File - Snackbar.make(webView, R.string.unable_to_load_image, Snackbar.LENGTH_LONG).show(); - return false; - } - // Continue only if the File was successfully created - if (photoFile != null) { - mCameraPhotoPath = "file:" + photoFile.getAbsolutePath(); - takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, - Uri.fromFile(photoFile)); - } else { - takePictureIntent = null; - } - } - Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT); - contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE); - contentSelectionIntent.setType("image/*"); - Intent[] intentArray; - if (takePictureIntent != null) { - intentArray = new Intent[]{takePictureIntent}; - } else { - intentArray = new Intent[0]; - } - Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER); - chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent); - chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser"); - chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray); - AppLog.d(this, "startActivityForResult"); - startActivityForResult(chooserIntent, MainActivity.INPUT_FILE_REQUEST_CODE_NEW); - return true; - } - }); - } - - @Override - public String getFragmentTag() { - return TAG; } public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { @@ -273,12 +139,6 @@ public class StreamFragment extends WebViewFragment { return super.onOptionsItemSelected(item); } - @Override - public ContextMenuWebView getWebView() { - AppLog.d(this, "getWebView: "+(this.webView != null)); - return this.webView; - } - public void onImageUploadResult(int requestCode, int resultCode, Intent data) { AppLog.d(this, "onImageUploadResult"); switch (requestCode) { @@ -346,7 +206,102 @@ public class StreamFragment extends WebViewFragment { } } + protected DiasporaStreamWebChromeClient.SharedTextCallback sharedTextCallback = new DiasporaStreamWebChromeClient.SharedTextCallback() { + @Override + public String getSharedText() { + return ((MainActivity)getActivity()).getTextToBeShared(); + } + @Override + public void setSharedText(String shared) { + ((MainActivity)getActivity()).setTextToBeShared(shared); + } + }; + + protected FileUploadWebChromeClient.FileUploadCallback fileUploadCallback = new FileUploadWebChromeClient.FileUploadCallback() { + @Override + public boolean imageUpload(WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { + if(Build.VERSION.SDK_INT >= 23) { + int hasWRITE_EXTERNAL_STORAGE = getActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE); + if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) { + if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + new AlertDialog.Builder(getContext()) + .setMessage(R.string.permissions_image) + .setNegativeButton(android.R.string.no, null) + .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (android.os.Build.VERSION.SDK_INT >= 23) + requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + MainActivity.REQUEST_CODE_ASK_PERMISSIONS); + } + }) + .show(); + return false; + } + requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + MainActivity.REQUEST_CODE_ASK_PERMISSIONS); + return false; + } + } + AppLog.d(this, "onOpenFileChooser"); + if (imageUploadFilePathCallbackNew != null) imageUploadFilePathCallbackNew.onReceiveValue(null); + imageUploadFilePathCallbackNew = filePathCallback; + Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + if (takePictureIntent.resolveActivity(getContext().getPackageManager()) != null) { + // Create the File where the photo should go + File photoFile; + try { + photoFile = Helpers.createImageFile(); + takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath); + } catch (IOException ex) { + AppLog.e(this, "ERROR creating temp file: "+ ex.toString()); + // Error occurred while creating the File + Snackbar.make(webView, R.string.unable_to_load_image, Snackbar.LENGTH_LONG).show(); + return false; + } + // Continue only if the File was successfully created + if (photoFile != null) { + mCameraPhotoPath = "file:" + photoFile.getAbsolutePath(); + takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, + Uri.fromFile(photoFile)); + } else { + takePictureIntent = null; + } + } + Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT); + contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE); + contentSelectionIntent.setType("image/*"); + Intent[] intentArray; + if (takePictureIntent != null) { + intentArray = new Intent[]{takePictureIntent}; + } else { + intentArray = new Intent[0]; + } + Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER); + chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent); + chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser"); + chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray); + AppLog.d(this, "startActivityForResult"); + startActivityForResult(chooserIntent, MainActivity.INPUT_FILE_REQUEST_CODE_NEW); + return true; + } + + @Override + public void legacyImageUpload(ValueCallback uploadMsg, String acceptType, String capture) { + AppLog.v(this, "openFileChooser(ValCallback, String, String"); + imageUploadFilePathCallbackOld = uploadMsg; + Intent intent = new Intent(); + intent.setType("image/*"); + intent.setAction(Intent.ACTION_GET_CONTENT); + intent.putExtra("return-data", true); + intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + AppLog.v(this, "startActivityForResult"); + startActivityForResult(Intent.createChooser(intent, "Select Picture"), MainActivity.INPUT_FILE_REQUEST_CODE_OLD); + } + }; + private class JavaScriptInterface { + @SuppressWarnings("unused") @JavascriptInterface public void setUserProfile(final String webMessage) throws JSONException { PodUserProfile pup = ((App)getActivity().getApplication()).getPodUserProfile(); @@ -359,9 +314,15 @@ public class StreamFragment extends WebViewFragment { } } + @SuppressWarnings("unused") @JavascriptInterface public void contentHasBeenShared() { ((MainActivity)getActivity()).setTextToBeShared(null); } } + + @Override + public String getFragmentTag() { + return TAG; + } } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/TestFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/TestFragment.java new file mode 100644 index 00000000..c8d5a861 --- /dev/null +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/TestFragment.java @@ -0,0 +1,39 @@ +package com.github.dfa.diaspora_android.fragment; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.github.dfa.diaspora_android.R; +import com.github.dfa.diaspora_android.util.AppLog; + +/** + * Created by vanitas on 23.09.16. + */ + +public class TestFragment extends CustomFragment { + + public static final String TAG = "com.github.dfa.diaspora_android.TestFragment"; + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + AppLog.d(this, "onCreateView()"); + return inflater.inflate(R.layout.test__fragment, container, false); + } + + @Override + public String getFragmentTag() { + return TAG; + } + + @Override + public void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater) { + } + + @Override + public boolean onBackPressed() { + return false; + } +} diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/DiasporaStreamWebChromeClient.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/DiasporaStreamWebChromeClient.java new file mode 100644 index 00000000..671075b2 --- /dev/null +++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/DiasporaStreamWebChromeClient.java @@ -0,0 +1,44 @@ +package com.github.dfa.diaspora_android.ui; + +import android.webkit.WebView; +import android.widget.ProgressBar; + +import com.github.dfa.diaspora_android.util.AppLog; +import com.github.dfa.diaspora_android.util.WebHelper; + +/** + * Created by vanitas on 26.09.16. + */ + +public class DiasporaStreamWebChromeClient extends FileUploadWebChromeClient { + protected SharedTextCallback sharedTextCallback; + + public DiasporaStreamWebChromeClient(WebView webView, ProgressBar progressBar, FileUploadCallback fileUploadCallback, SharedTextCallback callback) { + super(webView, progressBar, fileUploadCallback); + this.sharedTextCallback = callback; + } + + @Override + public void onProgressChanged(WebView wv, int progress) { + super.onProgressChanged(wv, progress); + if (progress > 0 && progress <= 60) { + WebHelper.getUserProfile(wv); + WebHelper.optimizeMobileSiteLayout(wv); + } + + if (progress > 60) { + WebHelper.optimizeMobileSiteLayout(wv); + + String textToBeShared = sharedTextCallback.getSharedText(); + if (textToBeShared != null) { + AppLog.d(this, "Share text into webView"); + WebHelper.shareTextIntoWebView(wv, textToBeShared); + } + } + } + + public interface SharedTextCallback { + String getSharedText(); + void setSharedText(String shared); + } +} diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/FileUploadWebChromeClient.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/FileUploadWebChromeClient.java new file mode 100644 index 00000000..6e3172e2 --- /dev/null +++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/FileUploadWebChromeClient.java @@ -0,0 +1,41 @@ +package com.github.dfa.diaspora_android.ui; + +import android.net.Uri; +import android.webkit.ValueCallback; +import android.webkit.WebView; +import android.widget.ProgressBar; + +/** + * Created by vanitas on 26.09.16. + */ + +public class FileUploadWebChromeClient extends ProgressBarWebChromeClient { + protected FileUploadCallback fileUploadCallback; + + public FileUploadWebChromeClient(WebView webView, ProgressBar progressBar, FileUploadCallback fileUploadCallback) { + super(webView, progressBar); + this.fileUploadCallback = fileUploadCallback; + } + + @Override + public void onProgressChanged(WebView wv, int progress) { + super.onProgressChanged(wv, progress); + } + + //For Android 4.1/4.2 only. DO NOT REMOVE! + @SuppressWarnings("unused") + protected void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) + { + fileUploadCallback.legacyImageUpload(uploadMsg, acceptType, capture); + } + + @Override + public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) { + return fileUploadCallback.imageUpload(webView, filePathCallback, fileChooserParams); + } + + public interface FileUploadCallback { + boolean imageUpload(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams); + void legacyImageUpload(ValueCallback uploadMsg, String acceptType, String capture); + } +} diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/ProgressBarWebChromeClient.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/ProgressBarWebChromeClient.java new file mode 100644 index 00000000..1c8e84c3 --- /dev/null +++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/ProgressBarWebChromeClient.java @@ -0,0 +1,26 @@ +package com.github.dfa.diaspora_android.ui; + +import android.view.View; +import android.webkit.WebChromeClient; +import android.webkit.WebView; +import android.widget.ProgressBar; + +/** + * WebChromeClient that connects the ProgressBar and the WebView and updates the progress of the progressBar. + * Created by vanitas on 26.09.16. + */ + +public class ProgressBarWebChromeClient extends WebChromeClient { + protected final ProgressBar progressBar; + protected final WebView webView; + + public ProgressBarWebChromeClient(WebView webView, ProgressBar progressBar) { + this.webView = webView; + this.progressBar = progressBar; + } + + public void onProgressChanged(WebView wv, int progress) { + progressBar.setProgress(progress); + progressBar.setVisibility(progress == 100 ? View.GONE : View.VISIBLE); + } +} diff --git a/app/src/main/java/com/github/dfa/diaspora_android/util/WebHelper.java b/app/src/main/java/com/github/dfa/diaspora_android/util/WebHelper.java index 691481be..ba760d7b 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/util/WebHelper.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/util/WebHelper.java @@ -62,7 +62,7 @@ public class WebHelper { public static void optimizeMobileSiteLayout(final WebView wv) { wv.loadUrl("javascript: ( function() {" + " if (document.documentElement == null || document.documentElement.style == null) { return; }" + - " document.documentElement.style.paddingBottom = '260px';" + + " document.documentElement.style.paddingBottom = '50px';" + " document.getElementById('main').style.paddingTop = '5px';" + " if(document.getElementById('main_nav')) {" + " document.getElementById('main_nav').parentNode.removeChild(" + diff --git a/app/src/main/res/layout/about__activity.xml b/app/src/main/res/layout/about__activity.xml index 34de3bfd..6a8c3568 100644 --- a/app/src/main/res/layout/about__activity.xml +++ b/app/src/main/res/layout/about__activity.xml @@ -17,7 +17,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/main__menu_bottom.xml b/app/src/main/res/menu/main__menu_bottom.xml index 0c973856..063957cf 100644 --- a/app/src/main/res/menu/main__menu_bottom.xml +++ b/app/src/main/res/menu/main__menu_bottom.xml @@ -35,4 +35,11 @@ android:title="@string/action_exit_app" /> + + diff --git a/app/src/main/res/menu/main__navdrawer.xml b/app/src/main/res/menu/main__navdrawer.xml index 25a2f7a9..56323eb8 100644 --- a/app/src/main/res/menu/main__navdrawer.xml +++ b/app/src/main/res/menu/main__navdrawer.xml @@ -61,7 +61,7 @@ android:title="@string/settings" /> From 1baeac1fe561ad861ee72ccf9fb7891c850b974a Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Thu, 29 Sep 2016 00:24:27 +0200 Subject: [PATCH 018/360] Update README.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 201b7cfa..cc8704d6 100644 --- a/README.md +++ b/README.md @@ -23,21 +23,21 @@ We use Crowdin to translate Diaspora for Android. Join our project here: Date: Thu, 29 Sep 2016 19:44:42 +0200 Subject: [PATCH 019/360] Fixed top/bottom menu entry population --- .../activity/MainActivity.java | 20 ++++++++++++------- .../fragment/DiasporaStreamFragment.java | 4 ++-- 2 files changed, 15 insertions(+), 9 deletions(-) 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 244bbc05..e9f12bfd 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 @@ -192,7 +192,6 @@ public class MainActivity extends AppCompatActivity // Setup toolbar setSupportActionBar(toolbarTop); - getMenuInflater().inflate(R.menu.main__menu_bottom, toolbarBottom.getMenu()); toolbarBottom.setOnMenuItemClickListener(new ActionMenuView.OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { CustomFragment top = getTopFragment(); @@ -274,14 +273,14 @@ public class MainActivity extends AppCompatActivity * @param fragment Fragment to show */ protected void showFragment(CustomFragment fragment) { - AppLog.d(this, "showFragment()"); + AppLog.v(this, "showFragment()"); CustomFragment currentTop = (CustomFragment) fm.findFragmentById(R.id.fragment_container); if(currentTop == null || !currentTop.getFragmentTag().equals(fragment.getFragmentTag())) { - AppLog.d(this, "Fragment was not visible. Replace it."); + AppLog.v(this, "Fragment was not visible. Replace it."); fm.beginTransaction().addToBackStack(null).replace(R.id.fragment_container, fragment, fragment.getFragmentTag()).commit(); - fragment.onCreateBottomOptionsMenu(toolbarBottom.getMenu(), getMenuInflater()); + invalidateOptionsMenu(); } else { - AppLog.d(this, "Fragment was already visible. Do nothing."); + AppLog.v(this, "Fragment was already visible. Do nothing."); } } @@ -427,7 +426,7 @@ public class MainActivity extends AppCompatActivity @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - AppLog.d(this, "onActivityResult(): "+requestCode); + AppLog.v(this, "onActivityResult(): "+requestCode); super.onActivityResult(requestCode, resultCode, data); } @@ -463,7 +462,7 @@ public class MainActivity extends AppCompatActivity AppLog.v(this, "Top Fragment is not null"); if(!top.onBackPressed()) { AppLog.v(this, "Top Fragment.onBackPressed was false"); - AppLog.d(this, "BackStackEntryCount: "+fm.getBackStackEntryCount()); + AppLog.v(this, "BackStackEntryCount: "+fm.getBackStackEntryCount()); if(fm.getBackStackEntryCount()>0) { fm.popBackStack(); } else { @@ -514,7 +513,14 @@ public class MainActivity extends AppCompatActivity @Override public boolean onCreateOptionsMenu(Menu menu) { AppLog.v(this, "onCreateOptionsMenu()"); + menu.clear(); getMenuInflater().inflate(R.menu.main__menu_top, menu); + toolbarBottom.getMenu().clear(); + getMenuInflater().inflate(R.menu.main__menu_bottom, toolbarBottom.getMenu()); + CustomFragment top = getTopFragment(); + if(top != null) { + top.onCreateBottomOptionsMenu(toolbarBottom.getMenu(), getMenuInflater()); + } return true; } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/DiasporaStreamFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/DiasporaStreamFragment.java index 8a86243c..2cd70e72 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/fragment/DiasporaStreamFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/DiasporaStreamFragment.java @@ -85,7 +85,7 @@ public class DiasporaStreamFragment extends BrowserFragment { switch (requestCode) { case MainActivity.INPUT_FILE_REQUEST_CODE_NEW: case MainActivity.INPUT_FILE_REQUEST_CODE_OLD: - AppLog.d(this, "INPUT_FILE_REQUEST_CODE: "+requestCode); + AppLog.v(this, "INPUT_FILE_REQUEST_CODE: "+requestCode); onImageUploadResult(requestCode, resultCode, data); return; } @@ -243,7 +243,7 @@ public class DiasporaStreamFragment extends BrowserFragment { return false; } } - AppLog.d(this, "onOpenFileChooser"); + AppLog.v(this, "onOpenFileChooser"); if (imageUploadFilePathCallbackNew != null) imageUploadFilePathCallbackNew.onReceiveValue(null); imageUploadFilePathCallbackNew = filePathCallback; Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); From fec93a06608293e6ad3b645833e5f6b7ffdca2b9 Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Fri, 30 Sep 2016 23:15:10 +0200 Subject: [PATCH 020/360] Added HashtagFragment --- .../activity/MainActivity.java | 18 ++- .../fragment/HashtagListFragment.java | 125 ++++++++++++++++++ .../res/layout/hashtag_list__fragment.xml | 27 ++++ app/src/main/res/layout/main__app_bar.xml | 2 +- .../res/layout/recycler_view__list_item.xml | 23 ++++ app/src/main/res/values/dimens.xml | 1 + 6 files changed, 189 insertions(+), 7 deletions(-) create mode 100644 app/src/main/java/com/github/dfa/diaspora_android/fragment/HashtagListFragment.java create mode 100644 app/src/main/res/layout/hashtag_list__fragment.xml create mode 100644 app/src/main/res/layout/recycler_view__list_item.xml 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 e9f12bfd..ab4b4035 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 @@ -65,6 +65,7 @@ import com.github.dfa.diaspora_android.data.PodUserProfile; import com.github.dfa.diaspora_android.fragment.BrowserFragment; import com.github.dfa.diaspora_android.fragment.CustomFragment; import com.github.dfa.diaspora_android.fragment.DiasporaStreamFragment; +import com.github.dfa.diaspora_android.fragment.HashtagListFragment; import com.github.dfa.diaspora_android.fragment.TestFragment; import com.github.dfa.diaspora_android.listener.WebUserProfileChangedListener; import com.github.dfa.diaspora_android.receiver.OpenExternalLinkReceiver; @@ -228,7 +229,7 @@ public class MainActivity extends AppCompatActivity * Show DiasporaStreamFragment if necessary and load URL url * @param url URL to load in the DiasporaStreamFragment */ - protected void openDiasporaUrl(String url) { + public void openDiasporaUrl(String url) { AppLog.v(this, "openDiasporaUrl()"); DiasporaStreamFragment streamFragment = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG); showFragment(streamFragment); @@ -256,14 +257,17 @@ public class MainActivity extends AppCompatActivity BrowserFragment bf = new BrowserFragment(); fm.beginTransaction().add(bf, fragmentTag).commit(); return bf; + case HashtagListFragment.TAG: + HashtagListFragment hlf = new HashtagListFragment(); + fm.beginTransaction().add(hlf, fragmentTag).commit(); + return hlf; case TestFragment.TAG: - TestFragment tf = new TestFragment(); - fm.beginTransaction().add(tf, fragmentTag).commit(); - return tf; default: AppLog.e(this,"Invalid Fragment Tag: "+fragmentTag +"\nAdd Fragments Tag to getFragment()'s switch case."); - return null; + TestFragment tf = new TestFragment(); + fm.beginTransaction().add(tf, fragmentTag).commit(); + return tf; } } } @@ -780,7 +784,7 @@ public class MainActivity extends AppCompatActivity //TODO: Replace with fragment case R.id.nav_followed_tags: { - DiasporaStreamFragment stream = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG); + /*DiasporaStreamFragment stream = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG); if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getBlankUrl()); WebHelper.showFollowedTagsList(stream.getWebView(), app); @@ -788,6 +792,8 @@ public class MainActivity extends AppCompatActivity } else { snackbarNoInternet.show(); } + */ + showFragment(getFragment(HashtagListFragment.TAG)); } break; diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/HashtagListFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/HashtagListFragment.java new file mode 100644 index 00000000..13ab9669 --- /dev/null +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/HashtagListFragment.java @@ -0,0 +1,125 @@ +package com.github.dfa.diaspora_android.fragment; + +import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.github.dfa.diaspora_android.App; +import com.github.dfa.diaspora_android.R; +import com.github.dfa.diaspora_android.activity.MainActivity; +import com.github.dfa.diaspora_android.util.AppLog; +import com.github.dfa.diaspora_android.util.DiasporaUrlHelper; + +/** + * Fragment that shows a list of the Hashtags the user follows + * Created by vanitas on 29.09.16. + */ + +public class HashtagListFragment extends CustomFragment { + + public static final String TAG = "com.github.dfa.diaspora_android.HashtagListFragment"; + + protected RecyclerView followedTagsRecyclerView; + protected String[] followedTags; + protected App app; + protected DiasporaUrlHelper urls; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + AppLog.d(this, "onCreateView()"); + return inflater.inflate(R.layout.hashtag_list__fragment, container, false); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + this.followedTagsRecyclerView = (RecyclerView) view.findViewById(R.id.fragment_followed_tags__recycler_view); + this.app = (App) getActivity().getApplication(); + this.urls = new DiasporaUrlHelper(app.getSettings()); + + followedTags = app.getPodUserProfile().getFollowedTags(); + followedTagsRecyclerView.setHasFixedSize(true); + followedTagsRecyclerView.setNestedScrollingEnabled(false); + + RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this.getContext()); + followedTagsRecyclerView.setLayoutManager(layoutManager); + + final FollowedTagsAdapter adapter = new FollowedTagsAdapter(followedTags, onHashtagClickListener); + followedTagsRecyclerView.setAdapter(adapter); + } + + @Override + public String getFragmentTag() { + return TAG; + } + + @Override + public void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater) { + /* Nothing to do */ + } + + @Override + public boolean onBackPressed() { + return false; + } + + protected View.OnClickListener onHashtagClickListener = new View.OnClickListener() { + @Override + public void onClick(View view) { + int itemPosition = followedTagsRecyclerView.getChildLayoutPosition(view); + if(itemPosition > -1 && itemPosition < followedTags.length) { + String tag = followedTags[itemPosition]; + ((MainActivity)getActivity()).openDiasporaUrl(urls.getSearchTagsUrl(tag)); + } + } + }; + + public static class FollowedTagsAdapter extends RecyclerView.Adapter { + private String[] followedTagsList; + private View.OnClickListener itemClickListener; + + public static class ViewHolder extends RecyclerView.ViewHolder { + // each data item is just a string in this case + public TextView title; + + public ViewHolder(View v) { + super(v); + title = (TextView) v.findViewById(R.id.recycler_view__list_item__text); + } + } + + // Provide a suitable constructor (depends on the kind of dataset) + public FollowedTagsAdapter(String[] tags, View.OnClickListener itemClickListener) { + this.followedTagsList = tags; + this.itemClickListener = itemClickListener; + } + + @Override + public FollowedTagsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View v = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.recycler_view__list_item, parent, false); + v.setOnClickListener(itemClickListener); + return new ViewHolder(v); + } + + // Replace the contents of a view (invoked by the layout manager) + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + + holder.title.setText(followedTagsList[position]); + + } + + // Return the size of your dataset (invoked by the layout manager) + @Override + public int getItemCount() { + return followedTagsList.length; + } + } +} diff --git a/app/src/main/res/layout/hashtag_list__fragment.xml b/app/src/main/res/layout/hashtag_list__fragment.xml new file mode 100644 index 00000000..94df572b --- /dev/null +++ b/app/src/main/res/layout/hashtag_list__fragment.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/main__app_bar.xml b/app/src/main/res/layout/main__app_bar.xml index 8d217e2b..e71a1997 100644 --- a/app/src/main/res/layout/main__app_bar.xml +++ b/app/src/main/res/layout/main__app_bar.xml @@ -32,7 +32,7 @@ diff --git a/app/src/main/res/layout/recycler_view__list_item.xml b/app/src/main/res/layout/recycler_view__list_item.xml new file mode 100644 index 00000000..764467e7 --- /dev/null +++ b/app/src/main/res/layout/recycler_view__list_item.xml @@ -0,0 +1,23 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 1009fc6a..35131109 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -7,6 +7,7 @@ 16dp 16dp 8dp + 45dp From e06e2f3ba1f55e1db3b053e8893931e3a037c640 Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Sat, 1 Oct 2016 00:24:53 +0200 Subject: [PATCH 021/360] Moved WebClients and ChromeClients to webview package --- .../github/dfa/diaspora_android/activity/MainActivity.java | 7 ------- .../dfa/diaspora_android/fragment/BrowserFragment.java | 4 ++-- .../diaspora_android/fragment/DiasporaStreamFragment.java | 5 ++--- .../dfa/diaspora_android/fragment/HashtagListFragment.java | 3 +++ .../{ui => webview}/CustomWebViewClient.java | 3 ++- .../{ui => webview}/DiasporaStreamWebChromeClient.java | 2 +- .../{ui => webview}/FileUploadWebChromeClient.java | 2 +- .../{ui => webview}/ProgressBarWebChromeClient.java | 2 +- 8 files changed, 12 insertions(+), 16 deletions(-) rename app/src/main/java/com/github/dfa/diaspora_android/{ui => webview}/CustomWebViewClient.java (95%) rename app/src/main/java/com/github/dfa/diaspora_android/{ui => webview}/DiasporaStreamWebChromeClient.java (96%) rename app/src/main/java/com/github/dfa/diaspora_android/{ui => webview}/FileUploadWebChromeClient.java (96%) rename app/src/main/java/com/github/dfa/diaspora_android/{ui => webview}/ProgressBarWebChromeClient.java (94%) 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 ab4b4035..44b06b45 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 @@ -288,13 +288,6 @@ public class MainActivity extends AppCompatActivity } } - @Override - public void onConfigurationChanged(Configuration newConfig) { - AppLog.i(this, "onConfigurationChanged()"); - - super.onConfigurationChanged(newConfig); - } - private void setupNavigationSlider() { ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, navDrawer, toolbarTop, R.string.navigation_drawer_open, R.string.navigation_drawer_close); diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java index 01fdb390..770c853e 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java @@ -29,8 +29,8 @@ import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.activity.MainActivity; import com.github.dfa.diaspora_android.data.AppSettings; import com.github.dfa.diaspora_android.ui.ContextMenuWebView; -import com.github.dfa.diaspora_android.ui.CustomWebViewClient; -import com.github.dfa.diaspora_android.ui.ProgressBarWebChromeClient; +import com.github.dfa.diaspora_android.webview.CustomWebViewClient; +import com.github.dfa.diaspora_android.webview.ProgressBarWebChromeClient; import com.github.dfa.diaspora_android.util.AppLog; import java.io.File; diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/DiasporaStreamFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/DiasporaStreamFragment.java index 2cd70e72..650c8fca 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/fragment/DiasporaStreamFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/DiasporaStreamFragment.java @@ -26,8 +26,8 @@ import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.activity.MainActivity; import com.github.dfa.diaspora_android.data.PodUserProfile; -import com.github.dfa.diaspora_android.ui.DiasporaStreamWebChromeClient; -import com.github.dfa.diaspora_android.ui.FileUploadWebChromeClient; +import com.github.dfa.diaspora_android.webview.DiasporaStreamWebChromeClient; +import com.github.dfa.diaspora_android.webview.FileUploadWebChromeClient; import com.github.dfa.diaspora_android.util.AppLog; import com.github.dfa.diaspora_android.util.DiasporaUrlHelper; import com.github.dfa.diaspora_android.util.Helpers; @@ -51,7 +51,6 @@ public class DiasporaStreamFragment extends BrowserFragment { private ValueCallback imageUploadFilePathCallbackNew; private ValueCallback imageUploadFilePathCallbackOld; private String mCameraPhotoPath; - private String sharedText; @SuppressLint("SetJavaScriptEnabled") @Override diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/HashtagListFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/HashtagListFragment.java index 13ab9669..3cb70c38 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/fragment/HashtagListFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/HashtagListFragment.java @@ -52,6 +52,9 @@ public class HashtagListFragment extends CustomFragment { final FollowedTagsAdapter adapter = new FollowedTagsAdapter(followedTags, onHashtagClickListener); followedTagsRecyclerView.setAdapter(adapter); + + //Set window title + getActivity().setTitle(R.string.nav_followed_tags); } @Override diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/CustomWebViewClient.java b/app/src/main/java/com/github/dfa/diaspora_android/webview/CustomWebViewClient.java similarity index 95% rename from app/src/main/java/com/github/dfa/diaspora_android/ui/CustomWebViewClient.java rename to app/src/main/java/com/github/dfa/diaspora_android/webview/CustomWebViewClient.java index 8e31a15c..914abcbb 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/ui/CustomWebViewClient.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/webview/CustomWebViewClient.java @@ -16,7 +16,7 @@ If not, see . */ -package com.github.dfa.diaspora_android.ui; +package com.github.dfa.diaspora_android.webview; import android.content.Intent; import android.net.Uri; @@ -37,6 +37,7 @@ public class CustomWebViewClient extends WebViewClient { this.webView = webView; } + //Open non-diaspora links in customtab/external browser public boolean shouldOverrideUrlLoading(WebView view, String url) { if (!url.contains(app.getSettings().getPodDomain())) { Intent i = new Intent(MainActivity.ACTION_OPEN_EXTERNAL_URL); diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/DiasporaStreamWebChromeClient.java b/app/src/main/java/com/github/dfa/diaspora_android/webview/DiasporaStreamWebChromeClient.java similarity index 96% rename from app/src/main/java/com/github/dfa/diaspora_android/ui/DiasporaStreamWebChromeClient.java rename to app/src/main/java/com/github/dfa/diaspora_android/webview/DiasporaStreamWebChromeClient.java index 671075b2..22da0d8a 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/ui/DiasporaStreamWebChromeClient.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/webview/DiasporaStreamWebChromeClient.java @@ -1,4 +1,4 @@ -package com.github.dfa.diaspora_android.ui; +package com.github.dfa.diaspora_android.webview; import android.webkit.WebView; import android.widget.ProgressBar; diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/FileUploadWebChromeClient.java b/app/src/main/java/com/github/dfa/diaspora_android/webview/FileUploadWebChromeClient.java similarity index 96% rename from app/src/main/java/com/github/dfa/diaspora_android/ui/FileUploadWebChromeClient.java rename to app/src/main/java/com/github/dfa/diaspora_android/webview/FileUploadWebChromeClient.java index 6e3172e2..a33261cb 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/ui/FileUploadWebChromeClient.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/webview/FileUploadWebChromeClient.java @@ -1,4 +1,4 @@ -package com.github.dfa.diaspora_android.ui; +package com.github.dfa.diaspora_android.webview; import android.net.Uri; import android.webkit.ValueCallback; diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/ProgressBarWebChromeClient.java b/app/src/main/java/com/github/dfa/diaspora_android/webview/ProgressBarWebChromeClient.java similarity index 94% rename from app/src/main/java/com/github/dfa/diaspora_android/ui/ProgressBarWebChromeClient.java rename to app/src/main/java/com/github/dfa/diaspora_android/webview/ProgressBarWebChromeClient.java index 1c8e84c3..b630163c 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/ui/ProgressBarWebChromeClient.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/webview/ProgressBarWebChromeClient.java @@ -1,4 +1,4 @@ -package com.github.dfa.diaspora_android.ui; +package com.github.dfa.diaspora_android.webview; import android.view.View; import android.webkit.WebChromeClient; From 94895f78e0399c3b226935363c60360fb75803df Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Sat, 1 Oct 2016 01:18:42 +0200 Subject: [PATCH 022/360] Removed SplashActivity, migrated PodSelectionActivity to PodSelectionFragment --- app/src/main/AndroidManifest.xml | 50 ++--- .../activity/MainActivity.java | 41 +++- .../activity/SplashActivity.java | 56 ------ .../PodSelectionFragment.java} | 179 +++++++++--------- .../res/layout/podselection__activity.xml | 88 --------- .../res/layout/podselection__fragment.xml | 65 +++++++ app/src/main/res/menu/podselection__menu.xml | 4 +- 7 files changed, 202 insertions(+), 281 deletions(-) delete mode 100644 app/src/main/java/com/github/dfa/diaspora_android/activity/SplashActivity.java rename app/src/main/java/com/github/dfa/diaspora_android/{activity/PodSelectionActivity.java => fragment/PodSelectionFragment.java} (58%) delete mode 100644 app/src/main/res/layout/podselection__activity.xml create mode 100644 app/src/main/res/layout/podselection__fragment.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7b75d8d3..3ee52fa8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,43 +12,26 @@ android:name="com.github.dfa.diaspora_android.App" android:label="@string/app_name" android:theme="@style/AppTheme" > + - - - - - - - - + + - + android:label="@string/settings" /> - - + + + + + + @@ -255,9 +243,7 @@ - + + \ No newline at end of file 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 44b06b45..f0a8995d 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 @@ -66,6 +66,7 @@ import com.github.dfa.diaspora_android.fragment.BrowserFragment; import com.github.dfa.diaspora_android.fragment.CustomFragment; import com.github.dfa.diaspora_android.fragment.DiasporaStreamFragment; import com.github.dfa.diaspora_android.fragment.HashtagListFragment; +import com.github.dfa.diaspora_android.fragment.PodSelectionFragment; import com.github.dfa.diaspora_android.fragment.TestFragment; import com.github.dfa.diaspora_android.listener.WebUserProfileChangedListener; import com.github.dfa.diaspora_android.receiver.OpenExternalLinkReceiver; @@ -179,12 +180,17 @@ public class MainActivity extends AppCompatActivity MainActivity.this.setTitle(title); } }); - //Handle intent - Intent intent = getIntent(); - if(intent != null && intent.getAction() != null) { - handleIntent(intent); + + if(!appSettings.hasPodDomain()) { + showFragment(getFragment(PodSelectionFragment.TAG)); } else { - openDiasporaUrl(urls.getStreamUrl()); + //Handle intent + Intent intent = getIntent(); + if (intent != null && intent.getAction() != null) { + handleIntent(intent); + } else { + openDiasporaUrl(urls.getStreamUrl()); + } } } @@ -261,6 +267,10 @@ public class MainActivity extends AppCompatActivity HashtagListFragment hlf = new HashtagListFragment(); fm.beginTransaction().add(hlf, fragmentTag).commit(); return hlf; + case PodSelectionFragment.TAG: + PodSelectionFragment psf = new PodSelectionFragment(); + fm.beginTransaction().add(psf, fragmentTag).commit(); + return psf; case TestFragment.TAG: default: AppLog.e(this,"Invalid Fragment Tag: "+fragmentTag @@ -388,9 +398,9 @@ public class MainActivity extends AppCompatActivity AppLog.v(this, "Intent has a delicious URL for us: "+loadUrl); } } else if (ACTION_CHANGE_ACCOUNT.equals(action)) { - AppLog.v(this, "Reset pod data and animate to PodSelectionActivity"); + AppLog.v(this, "Reset pod data and show PodSelectionFragment"); app.resetPodData(((DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG)).getWebView()); - Helpers.animateToActivity(MainActivity.this, PodSelectionActivity.class, true); + showFragment(getFragment(PodSelectionFragment.TAG)); } else if (ACTION_CLEAR_CACHE.equals(action)) { AppLog.v(this, "Clear WebView cache"); ((DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG)).getWebView().clearCache(true); @@ -510,13 +520,24 @@ public class MainActivity extends AppCompatActivity @Override public boolean onCreateOptionsMenu(Menu menu) { AppLog.v(this, "onCreateOptionsMenu()"); + //Clear the menus menu.clear(); - getMenuInflater().inflate(R.menu.main__menu_top, menu); toolbarBottom.getMenu().clear(); - getMenuInflater().inflate(R.menu.main__menu_bottom, toolbarBottom.getMenu()); + toolbarBottom.setVisibility(View.VISIBLE); + CustomFragment top = getTopFragment(); if(top != null) { - top.onCreateBottomOptionsMenu(toolbarBottom.getMenu(), getMenuInflater()); + //Are we displaying a Fragment other than PodSelectionFragment? + if(!top.getFragmentTag().equals(PodSelectionFragment.TAG)) { + getMenuInflater().inflate(R.menu.main__menu_top, menu); + getMenuInflater().inflate(R.menu.main__menu_bottom, toolbarBottom.getMenu()); + top.onCreateBottomOptionsMenu(toolbarBottom.getMenu(), getMenuInflater()); + } + //PodSelectionFragment + else { + //Hide bottom toolbar + toolbarBottom.setVisibility(View.GONE); + } } return true; } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/SplashActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/SplashActivity.java deleted file mode 100644 index 0eeccd3c..00000000 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/SplashActivity.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - This file is part of the Diaspora for Android. - - Diaspora for Android 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. - - Diaspora for Android 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 the Diaspora for Android. - - If not, see . - */ - -package com.github.dfa.diaspora_android.activity; - -import android.os.Bundle; -import android.os.Handler; -import android.support.v7.app.AppCompatActivity; - -import com.github.dfa.diaspora_android.App; -import com.github.dfa.diaspora_android.R; -import com.github.dfa.diaspora_android.util.Helpers; - -import butterknife.ButterKnife; - - -public class SplashActivity extends AppCompatActivity { - private App app; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.splash__activity); - ButterKnife.bind(this); - app = (App) getApplication(); - - int delay = getResources().getInteger(R.integer.splash_delay); - new Handler().postDelayed(startActivityRunnable, delay); - } - - private final Runnable startActivityRunnable = new Runnable() { - public void run() { - boolean hasPodDomain = app.getSettings().hasPodDomain(); - Helpers.animateToActivity(SplashActivity.this, - hasPodDomain ? MainActivity.class : PodSelectionActivity.class, - true - ); - } - }; -} diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/PodSelectionFragment.java similarity index 58% rename from app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionActivity.java rename to app/src/main/java/com/github/dfa/diaspora_android/fragment/PodSelectionFragment.java index 57103f6b..d833d271 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionActivity.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/PodSelectionFragment.java @@ -1,22 +1,4 @@ -/* - This file is part of the Diaspora for Android. - - Diaspora for Android 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. - - Diaspora for Android 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 the Diaspora for Android. - - If not, see . - */ -package com.github.dfa.diaspora_android.activity; +package com.github.dfa.diaspora_android.fragment; import android.app.AlertDialog; import android.content.BroadcastReceiver; @@ -28,64 +10,103 @@ import android.os.Build; import android.os.Bundle; import android.support.design.widget.Snackbar; import android.support.v4.content.LocalBroadcastManager; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.Toolbar; import android.text.Editable; import android.text.SpannableString; import android.text.TextWatcher; import android.text.util.Linkify; +import android.view.LayoutInflater; import android.view.Menu; +import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; +import android.view.ViewGroup; import android.webkit.CookieManager; +import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.EditText; +import android.widget.ImageView; import android.widget.ListView; import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.R; +import com.github.dfa.diaspora_android.activity.MainActivity; +import com.github.dfa.diaspora_android.data.AppSettings; import com.github.dfa.diaspora_android.task.GetPodsService; -import com.github.dfa.diaspora_android.util.Helpers; +import com.github.dfa.diaspora_android.util.AppLog; +import com.github.dfa.diaspora_android.util.DiasporaUrlHelper; import com.github.dfa.diaspora_android.util.WebHelper; import java.util.ArrayList; -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import butterknife.OnItemClick; +/** + * Fragment that lets the user choose a Pod + * Created by vanitas on 01.10.16. + */ +public class PodSelectionFragment extends CustomFragment { + public static final String TAG = "com.github.dfa.diaspora_android.PodSelectionFragment"; -public class PodSelectionActivity extends AppCompatActivity { - private App app; + protected EditText editFilter; + protected ListView listPods; + protected ImageView selectPodButton; - @BindView(R.id.podselection__edit_filter) - EditText editFilter; - - @BindView(R.id.podselection__listpods) - ListView listPods; - - @BindView(R.id.main__topbar) - Toolbar toolbar; + protected App app; + protected AppSettings appSettings; @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.podselection__activity); - ButterKnife.bind(this); - app = (App) getApplication(); - setSupportActionBar(toolbar); - - - listPods.setTextFilterEnabled(true); - setListedPods(app.getSettings().getPreviousPodlist()); - LocalBroadcastManager.getInstance(this).registerReceiver(podListReceiver, new IntentFilter(GetPodsService.MESSAGE_PODS_RECEIVED)); - - if (!WebHelper.isOnline(PodSelectionActivity.this)) { - Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show(); - } + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + AppLog.d(this, "onCreateView()"); + return inflater.inflate(R.layout.podselection__fragment, container, false); } + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + this.app = (App) getActivity().getApplication(); + this.appSettings = app.getSettings(); + + this.editFilter = (EditText) view.findViewById(R.id.podselection__edit_filter); + this.listPods = (ListView) view.findViewById(R.id.podselection__listpods); + this.selectPodButton = (ImageView) view.findViewById(R.id.podselection__button_select_pod); + + listPods.setTextFilterEnabled(true); + listPods.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView adapterView, View view, int i, long l) { + showPodConfirmationDialog((String) listPods.getAdapter().getItem(i)); + } + }); + setListedPods(appSettings.getPreviousPodlist()); + LocalBroadcastManager.getInstance(getContext()).registerReceiver(podListReceiver, new IntentFilter(GetPodsService.MESSAGE_PODS_RECEIVED)); + if (!WebHelper.isOnline(getContext())) { + Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show(); + } + selectPodButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (editFilter.getText().length() > 4 && editFilter.getText().toString().contains("")) { + showPodConfirmationDialog(editFilter.getText().toString()); + } else { + Snackbar.make(listPods, R.string.valid_pod, Snackbar.LENGTH_LONG).show(); + } + } + }); + } + + @Override + public String getFragmentTag() { + return TAG; + } + + @Override + public void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater) { + /* Nothing to do */ + } + + @Override + public boolean onBackPressed() { + return false; + } private final BroadcastReceiver podListReceiver = new BroadcastReceiver() { @Override @@ -104,20 +125,11 @@ public class PodSelectionActivity extends AppCompatActivity { } }; - @OnClick(R.id.podselection__button_select_pod) - public void onButtonSelectPodClicked(View view) { - if (editFilter.getText().length() > 4 && editFilter.getText().toString().contains("")) { - showPodConfirmationDialog(editFilter.getText().toString()); - } else { - Snackbar.make(listPods, R.string.valid_pod, Snackbar.LENGTH_LONG).show(); - } - } - @Override - protected void onResume() { + public void onResume() { super.onResume(); - Intent i = new Intent(PodSelectionActivity.this, GetPodsService.class); - startService(i); + Intent i = new Intent(getContext(), GetPodsService.class); + getContext().startService(i); } @@ -128,7 +140,7 @@ public class PodSelectionActivity extends AppCompatActivity { } final ArrayAdapter adapter = new ArrayAdapter<>( - PodSelectionActivity.this, + getContext(), android.R.layout.simple_list_item_1, listedPodsList); @@ -154,24 +166,19 @@ public class PodSelectionActivity extends AppCompatActivity { }); } - @OnItemClick(R.id.podselection__listpods) - public void onListPodsItemClicked(int position) { - showPodConfirmationDialog((String) listPods.getAdapter().getItem(position)); - } - private void showPodConfirmationDialog(final String selectedPod) { // Make a clickable link final SpannableString dialogMessage = new SpannableString(getString(R.string.confirm_pod, selectedPod)); Linkify.addLinks(dialogMessage, Linkify.ALL); // Check if online - if (!WebHelper.isOnline(PodSelectionActivity.this)) { + if (!WebHelper.isOnline(getContext())) { Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show(); return; } // Show dialog - new AlertDialog.Builder(PodSelectionActivity.this) + new AlertDialog.Builder(getContext()) .setTitle(getString(R.string.confirmation)) .setMessage(dialogMessage) .setPositiveButton(android.R.string.yes, @@ -201,40 +208,28 @@ public class PodSelectionActivity extends AppCompatActivity { e.printStackTrace(); } - Helpers.animateToActivity(this, MainActivity.class, true); - } - - - @Override - public void onBackPressed() { - Snackbar.make(listPods, R.string.confirm_exit, Snackbar.LENGTH_LONG) - .setAction(android.R.string.yes, new View.OnClickListener() { - public void onClick(View view) { - finish(); - } - }) - .show(); + ((MainActivity)getActivity()).openDiasporaUrl(new DiasporaUrlHelper(appSettings).getPodUrl()); } @Override - protected void onDestroy() { - LocalBroadcastManager.getInstance(this).unregisterReceiver(podListReceiver); + public void onDestroy() { + LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(podListReceiver); super.onDestroy(); } @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.podselection__menu, menu); - return true; + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.podselection__menu, menu); + super.onCreateOptionsMenu(menu, inflater); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_reload: { - if (WebHelper.isOnline(PodSelectionActivity.this)) { - Intent i = new Intent(PodSelectionActivity.this, GetPodsService.class); - startService(i); + if (WebHelper.isOnline(getContext())) { + Intent i = new Intent(getContext(), GetPodsService.class); + getContext().startService(i); return true; } else { Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show(); diff --git a/app/src/main/res/layout/podselection__activity.xml b/app/src/main/res/layout/podselection__activity.xml deleted file mode 100644 index f93ce7f9..00000000 --- a/app/src/main/res/layout/podselection__activity.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/podselection__fragment.xml b/app/src/main/res/layout/podselection__fragment.xml new file mode 100644 index 00000000..b8e39ac4 --- /dev/null +++ b/app/src/main/res/layout/podselection__fragment.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/podselection__menu.xml b/app/src/main/res/menu/podselection__menu.xml index 1c33e1c9..8b498aa3 100644 --- a/app/src/main/res/menu/podselection__menu.xml +++ b/app/src/main/res/menu/podselection__menu.xml @@ -1,7 +1,5 @@ + xmlns:app="http://schemas.android.com/apk/res-auto"> Date: Sat, 1 Oct 2016 01:30:58 +0200 Subject: [PATCH 023/360] Handle Intent.Action.Main in handleIntent() --- .../github/dfa/diaspora_android/activity/MainActivity.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 f0a8995d..b5d040c8 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 @@ -182,8 +182,10 @@ public class MainActivity extends AppCompatActivity }); if(!appSettings.hasPodDomain()) { + AppLog.d(this, "We have no pod. Show PodSelectionFragment"); showFragment(getFragment(PodSelectionFragment.TAG)); } else { + AppLog.d(this, "Pod found. Handle intents."); //Handle intent Intent intent = getIntent(); if (intent != null && intent.getAction() != null) { @@ -386,7 +388,9 @@ public class MainActivity extends AppCompatActivity String type = intent.getType(); String loadUrl = null; AppLog.v(this, "Action: " + action + " Type: " + type); - if (ACTION_OPEN_URL.equals(action)) { + if (Intent.ACTION_MAIN.equals(action)) { + loadUrl = urls.getStreamUrl(); + } else if (ACTION_OPEN_URL.equals(action)) { loadUrl = intent.getStringExtra(URL_MESSAGE); } else if (Intent.ACTION_VIEW.equals(action) && intent.getDataString() != null) { Uri data = intent.getData(); From 2475c66830f7c1aec8ca5c2126d2c1e20092e6ae Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Sat, 1 Oct 2016 01:47:16 +0200 Subject: [PATCH 024/360] Update strings-about.xml --- app/src/main/res/values-de/strings-about.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-de/strings-about.xml b/app/src/main/res/values-de/strings-about.xml index c2ffbd61..7a85ecae 100644 --- a/app/src/main/res/values-de/strings-about.xml +++ b/app/src/main/res/values-de/strings-about.xml @@ -24,7 +24,7 @@ Diaspora benutzt Markdown-Formatierung für deine Beiträge. Weitere Informationen dazu findest du auf<br> https://wiki.diasporafoundation.org/Markdown_reference_guide <br> <br> - DiasporaForAndroid wird frei wie in Freiheit entwickelt und folgt den Ideen des Diaspora Projektes. <br> + DiasporaForAndroid wird unabhängig und frei wie in Freiheit entwickelt und folgt den Ideen des Diaspora Projektes. <br> Den Quellcode findest du auf Github: <br> https://github.com/Diaspora-for-Android/diaspora-android <br> <br> From 036457117c644ca7784307c43b20dc4d288709e5 Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Sun, 2 Oct 2016 12:42:12 +0200 Subject: [PATCH 025/360] Fixed image sharing to other apps --- .../fragment/BrowserFragment.java | 2 + .../ui/ContextMenuWebView.java | 50 ++++++++++++++----- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java index 770c853e..f790fef8 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java @@ -104,6 +104,8 @@ public class BrowserFragment extends CustomFragment { pendingUrl = null; } + webView.setParentActivity(getActivity()); + this.setRetainInstance(true); } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java index adac6fd2..92394bef 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java @@ -123,22 +123,48 @@ public class ContextMenuWebView extends NestedWebView { case ID_SHARE_IMAGE: if (url != null) { - final Uri local = Uri.parse(Environment.getExternalStorageDirectory() + "/Pictures/Diaspora/" + System.currentTimeMillis() + ".png"); - new ImageDownloadTask(null, local.getPath()) { - @Override - protected void onPostExecute(Bitmap result) { - Uri myUri = Uri.fromFile(new File(local.getPath())); - Intent sharingIntent = new Intent(); - sharingIntent.setAction(Intent.ACTION_SEND); - sharingIntent.putExtra(Intent.EXTRA_STREAM, myUri); - sharingIntent.setType("image/png"); - sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - context.startActivity(Intent.createChooser(sharingIntent, "Share image using")); + boolean writeToStoragePermitted = true; + if (android.os.Build.VERSION.SDK_INT >= 23) { + int hasWRITE_EXTERNAL_STORAGE = parentActivity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE); + if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) { + writeToStoragePermitted = false; + if (!parentActivity.shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + new AlertDialog.Builder(parentActivity) + .setMessage(R.string.permissions_image) + .setPositiveButton(context.getText(android.R.string.yes), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + if (android.os.Build.VERSION.SDK_INT >= 23) + parentActivity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + MainActivity.REQUEST_CODE__ACCESS_EXTERNAL_STORAGE); + } + }) + .setNegativeButton(context.getText(android.R.string.no), null) + .show(); + } + parentActivity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + MainActivity.REQUEST_CODE__ACCESS_EXTERNAL_STORAGE); } - }.execute(url); + } + if (writeToStoragePermitted) { + final Uri local = Uri.parse(Environment.getExternalStorageDirectory() + "/Pictures/Diaspora/" + System.currentTimeMillis() + ".png"); + new ImageDownloadTask(null, local.getPath()) { + @Override + protected void onPostExecute(Bitmap result) { + Uri myUri = Uri.fromFile(new File(local.getPath())); + Intent sharingIntent = new Intent(); + sharingIntent.setAction(Intent.ACTION_SEND); + sharingIntent.putExtra(Intent.EXTRA_STREAM, myUri); + sharingIntent.setType("image/png"); + sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + context.startActivity(Intent.createChooser(sharingIntent, "Share image using")); + } + }.execute(url); + } } else { Toast.makeText(context, "Cannot share image: url is null", Toast.LENGTH_SHORT).show(); } + break; case ID_IMAGE_EXTERNAL_BROWSER: From 7ee5e0f39bc5f587f6dc6269f1bdfd3a4ef87e95 Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Sun, 2 Oct 2016 12:55:05 +0200 Subject: [PATCH 026/360] Get title for image sharing dialog from resources instead of using hardcoded string. Also do not show multiple permission dialogs stacked --- .../github/dfa/diaspora_android/ui/ContextMenuWebView.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java index 92394bef..3be4ce63 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/ContextMenuWebView.java @@ -141,9 +141,10 @@ public class ContextMenuWebView extends NestedWebView { }) .setNegativeButton(context.getText(android.R.string.no), null) .show(); + } else { + parentActivity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + MainActivity.REQUEST_CODE__ACCESS_EXTERNAL_STORAGE); } - parentActivity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - MainActivity.REQUEST_CODE__ACCESS_EXTERNAL_STORAGE); } } if (writeToStoragePermitted) { @@ -157,7 +158,7 @@ public class ContextMenuWebView extends NestedWebView { sharingIntent.putExtra(Intent.EXTRA_STREAM, myUri); sharingIntent.setType("image/png"); sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - context.startActivity(Intent.createChooser(sharingIntent, "Share image using")); + context.startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.action_share_dotdotdot))); } }.execute(url); } From 88e4636e88d46a0282985db864ee74054083f92b Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Sun, 2 Oct 2016 13:36:57 +0200 Subject: [PATCH 027/360] Removed test Fragments and old SplashActivity related stuff --- .../activity/MainActivity.java | 26 +------------ .../fragment/TestFragment.java | 39 ------------------- app/src/main/res/layout/splash__activity.xml | 37 ------------------ app/src/main/res/layout/test__fragment.xml | 11 ------ app/src/main/res/menu/main__menu_bottom.xml | 7 ---- 5 files changed, 2 insertions(+), 118 deletions(-) delete mode 100644 app/src/main/java/com/github/dfa/diaspora_android/fragment/TestFragment.java delete mode 100644 app/src/main/res/layout/splash__activity.xml delete mode 100644 app/src/main/res/layout/test__fragment.xml 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 b5d040c8..80ae786f 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 @@ -25,7 +25,6 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; -import android.content.res.Configuration; import android.graphics.drawable.LayerDrawable; import android.net.Uri; import android.os.Bundle; @@ -67,7 +66,6 @@ import com.github.dfa.diaspora_android.fragment.CustomFragment; import com.github.dfa.diaspora_android.fragment.DiasporaStreamFragment; import com.github.dfa.diaspora_android.fragment.HashtagListFragment; import com.github.dfa.diaspora_android.fragment.PodSelectionFragment; -import com.github.dfa.diaspora_android.fragment.TestFragment; import com.github.dfa.diaspora_android.listener.WebUserProfileChangedListener; import com.github.dfa.diaspora_android.receiver.OpenExternalLinkReceiver; import com.github.dfa.diaspora_android.receiver.UpdateTitleReceiver; @@ -75,7 +73,6 @@ import com.github.dfa.diaspora_android.ui.BadgeDrawable; import com.github.dfa.diaspora_android.util.AppLog; import com.github.dfa.diaspora_android.util.CustomTabHelpers.CustomTabActivityHelper; import com.github.dfa.diaspora_android.util.DiasporaUrlHelper; -import com.github.dfa.diaspora_android.util.Helpers; import com.github.dfa.diaspora_android.util.WebHelper; import butterknife.BindView; @@ -273,13 +270,10 @@ public class MainActivity extends AppCompatActivity PodSelectionFragment psf = new PodSelectionFragment(); fm.beginTransaction().add(psf, fragmentTag).commit(); return psf; - case TestFragment.TAG: default: AppLog.e(this,"Invalid Fragment Tag: "+fragmentTag +"\nAdd Fragments Tag to getFragment()'s switch case."); - TestFragment tf = new TestFragment(); - fm.beginTransaction().add(tf, fragmentTag).commit(); - return tf; + return getTopFragment(); } } } @@ -592,11 +586,6 @@ public class MainActivity extends AppCompatActivity return true; } - case R.id.action_debug_button: { - showFragment(getFragment(TestFragment.TAG)); - return true; - } - case R.id.action_compose: { if (WebHelper.isOnline(MainActivity.this)) { openDiasporaUrl(urls.getNewPostUrl()); @@ -736,13 +725,12 @@ public class MainActivity extends AppCompatActivity } } - //TODO: Implement? + //TODO: Implement some day private void handleSendImage(Intent intent) { AppLog.i(this, "handleSendImage()"); final Uri imageUri = intent.getParcelableExtra(Intent.EXTRA_STREAM); if (imageUri != null) { AppLog.v(this, "imageUri is not null. Handle shared image"); - // TODO: Update UI to reflect text being shared } else { AppLog.w(this, "imageUri is null. Cannot precede."); } @@ -800,17 +788,7 @@ public class MainActivity extends AppCompatActivity } break; - //TODO: Replace with fragment case R.id.nav_followed_tags: { - /*DiasporaStreamFragment stream = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG); - if (WebHelper.isOnline(MainActivity.this)) { - openDiasporaUrl(urls.getBlankUrl()); - WebHelper.showFollowedTagsList(stream.getWebView(), app); - setTitle(R.string.nav_followed_tags); - } else { - snackbarNoInternet.show(); - } - */ showFragment(getFragment(HashtagListFragment.TAG)); } break; diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/TestFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/TestFragment.java deleted file mode 100644 index c8d5a861..00000000 --- a/app/src/main/java/com/github/dfa/diaspora_android/fragment/TestFragment.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.github.dfa.diaspora_android.fragment; - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.github.dfa.diaspora_android.R; -import com.github.dfa.diaspora_android.util.AppLog; - -/** - * Created by vanitas on 23.09.16. - */ - -public class TestFragment extends CustomFragment { - - public static final String TAG = "com.github.dfa.diaspora_android.TestFragment"; - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - AppLog.d(this, "onCreateView()"); - return inflater.inflate(R.layout.test__fragment, container, false); - } - - @Override - public String getFragmentTag() { - return TAG; - } - - @Override - public void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater) { - } - - @Override - public boolean onBackPressed() { - return false; - } -} diff --git a/app/src/main/res/layout/splash__activity.xml b/app/src/main/res/layout/splash__activity.xml deleted file mode 100644 index 5b6d5df3..00000000 --- a/app/src/main/res/layout/splash__activity.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - diff --git a/app/src/main/res/layout/test__fragment.xml b/app/src/main/res/layout/test__fragment.xml deleted file mode 100644 index 7ce8d12a..00000000 --- a/app/src/main/res/layout/test__fragment.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/menu/main__menu_bottom.xml b/app/src/main/res/menu/main__menu_bottom.xml index 063957cf..0c973856 100644 --- a/app/src/main/res/menu/main__menu_bottom.xml +++ b/app/src/main/res/menu/main__menu_bottom.xml @@ -35,11 +35,4 @@ android:title="@string/action_exit_app" /> - - From 68d299f89460f4efc48e5262dcbdb4317976aa4b Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Sun, 2 Oct 2016 22:22:08 +0200 Subject: [PATCH 028/360] Added some documentation to MainActivity --- .../activity/MainActivity.java | 112 +++++++++++++++--- 1 file changed, 95 insertions(+), 17 deletions(-) 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 80ae786f..4efb4611 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 @@ -163,7 +163,7 @@ public class MainActivity extends AppCompatActivity customTabActivityHelper.setConnectionCallback(this); fm = getSupportFragmentManager(); - setupUI(savedInstanceState); + setupUI(); brOpenExternalLink = new OpenExternalLinkReceiver(this); brSetTitle = new UpdateTitleReceiver(app, urls, new UpdateTitleReceiver.TitleCallback() { @@ -193,7 +193,11 @@ public class MainActivity extends AppCompatActivity } } - private void setupUI(Bundle savedInstanceState) { + /** + * Setup the user interface. Set up both toolbars and initialize the snackbars. + * Initialize the navigation drawer and apply intellihide settings. + */ + private void setupUI() { AppLog.i(this, "setupUI()"); // Setup toolbar @@ -244,7 +248,7 @@ public class MainActivity extends AppCompatActivity /** * 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. - * If there is no Fragment with the corresponding Tag, return null. + * If there is no Fragment with the corresponding Tag, return the top fragment. * @param fragmentTag tag * @return corresponding Fragment */ @@ -294,6 +298,9 @@ public class MainActivity extends AppCompatActivity } } + /** + * Initialize the navigation slider + */ private void setupNavigationSlider() { ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, navDrawer, toolbarTop, R.string.navigation_drawer_open, R.string.navigation_drawer_close); @@ -358,19 +365,30 @@ public class MainActivity extends AppCompatActivity navMenu.findItem(R.id.nav_public).setVisible(appSettings.isVisibleInNavPublic_activities()); } + /** + * Forward toolbar clicks to onNavigationItemSelected + * @param view selected view + */ @OnClick(R.id.main__topbar) public void onToolBarClicked(View view) { AppLog.i(this, "onToolBarClicked()"); onNavigationItemSelected(navView.getMenu().findItem(R.id.nav_stream)); } + /** + * Forward incoming intents to handleIntent() + * @param intent incoming + */ @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); - handleIntent(intent); } + /** + * Handle intents and execute intent specific actions + * @param intent intent to get handled + */ private void handleIntent(Intent intent) { AppLog.i(this, "handleIntent()"); if (intent == null) { @@ -420,7 +438,8 @@ public class MainActivity extends AppCompatActivity break; } } else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) { - //TODO: Implement and add filter to manifest + /* TODO: Implement and add filter to manifest */ + return; } if (loadUrl != null) { @@ -429,24 +448,22 @@ public class MainActivity extends AppCompatActivity } } + /** + * Handle activity results + * @param requestCode reqCode + * @param resultCode resCode + * @param data data + */ @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { AppLog.v(this, "onActivityResult(): "+requestCode); super.onActivityResult(requestCode, resultCode, data); } - @Override - protected void onSaveInstanceState(Bundle outState) { - AppLog.v(this, "onSaveInstanceState()"); - super.onSaveInstanceState(outState); - } - - @Override - protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) { - AppLog.v(this, "onRestoreInstanceState()"); - super.onRestoreInstanceState(savedInstanceState); - } - + /** + * Return the fragment which is currently displayed in R.id.fragment_container + * @return top fragment or null if there is none displayed + */ private CustomFragment getTopFragment() { Fragment top = fm.findFragmentById(R.id.fragment_container); if(top != null) { @@ -455,6 +472,9 @@ public class MainActivity extends AppCompatActivity return null; } + /** + * Handle presses on the back button + */ @Override public void onBackPressed() { AppLog.v(this, "onBackPressed()"); @@ -515,6 +535,12 @@ public class MainActivity extends AppCompatActivity LocalBroadcastManager.getInstance(this).registerReceiver(brOpenExternalLink, new IntentFilter(ACTION_OPEN_EXTERNAL_URL)); } + /** + * Clear and repopulate top and bottom toolbar. + * Also add menu items of the displayed fragment + * @param menu top toolbar + * @return boolean + */ @Override public boolean onCreateOptionsMenu(Menu menu) { AppLog.v(this, "onCreateOptionsMenu()"); @@ -540,6 +566,11 @@ public class MainActivity extends AppCompatActivity return true; } + /** + * Set the notification and messages counter in the top toolbar + * @param menu menu + * @return boolean + */ @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuItem item; @@ -556,6 +587,11 @@ public class MainActivity extends AppCompatActivity return super.onPrepareOptionsMenu(menu); } + /** + * Handle clicks on the optionsmenu + * @param item item + * @return boolean + */ @Override public boolean onOptionsItemSelected(MenuItem item) { AppLog.i(this, "onOptionsItemSelected()"); @@ -649,18 +685,30 @@ public class MainActivity extends AppCompatActivity return super.onOptionsItemSelected(item); } + /** + * Update the profile name in the navigation slider + * @param name name + */ @Override public void onUserProfileNameChanged(String name) { AppLog.i(this, "onUserProfileNameChanged()"); navheaderTitle.setText(name); } + /** + * Update the profile picture in the navigation slider + * @param avatarUrl url of the new profile pic + */ @Override public void onUserProfileAvatarChanged(String avatarUrl) { AppLog.i(this, "onUserProfileAvatarChanged()"); app.getAvatarImageLoader().startImageDownload(navheaderImage, avatarUrl); } + /** + * Handle hashtag clicks. Open the new-post-url and inject the clicked hashtag into the post-editor + * @param intent intent + */ private void handleHashtag(Intent intent) { AppLog.v(this, "handleHashtag()"); try { @@ -671,6 +719,10 @@ public class MainActivity extends AppCompatActivity openDiasporaUrl(urls.getNewPostUrl()); } + /** + * Open the new-post-url and inject text that was shared into the app into the post editors text field + * @param intent shareTextIntent + */ private void handleSendText(Intent intent) { AppLog.v(this, "handleSendText()"); try { @@ -725,6 +777,10 @@ public class MainActivity extends AppCompatActivity } } + /** + * Share an image shared to the app via diaspora + * @param intent shareImageIntent + */ //TODO: Implement some day private void handleSendImage(Intent intent) { AppLog.i(this, "handleSendImage()"); @@ -737,6 +793,10 @@ public class MainActivity extends AppCompatActivity Toast.makeText(this, "Not yet implemented.", Toast.LENGTH_SHORT).show(); } + /** + * Invalidate the top toolbar to update the notification counter + * @param notificationCount new notification count + */ @Override public void onNotificationCountChanged(int notificationCount) { AppLog.i(this, "onNotificationCountChanged()"); @@ -744,6 +804,10 @@ public class MainActivity extends AppCompatActivity invalidateOptionsMenu(); } + /** + * Invalidate the top toolbar to update the unread messages counter + * @param unreadMessageCount new unread messages count + */ @Override public void onUnreadMessageCountChanged(int unreadMessageCount) { AppLog.i(this, "onUnreadMessageCountChanged()"); @@ -872,6 +936,12 @@ public class MainActivity extends AppCompatActivity return true; } + /** + * React to results of requestPermission + * @param requestCode resCode + * @param permissions requested permissions + * @param grantResults granted results + */ @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { @@ -891,10 +961,18 @@ public class MainActivity extends AppCompatActivity } } + /** + * Return the string that will be shared into the new-post-editor + * @return String + */ public String getTextToBeShared() { return textToBeShared; } + /** + * Set the string that will be shared into the new-post-editor + * @param textToBeShared + */ public void setTextToBeShared(String textToBeShared) { this.textToBeShared = textToBeShared; } From c005ef744d62d694e27ff10048193891c37a9e33 Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Mon, 3 Oct 2016 18:28:08 +0200 Subject: [PATCH 029/360] Fixed clear webview cache. Thanks @di72nn --- .../dfa/diaspora_android/activity/SettingsActivity.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/SettingsActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/SettingsActivity.java index 88f13171..a92e81d9 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/SettingsActivity.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/SettingsActivity.java @@ -94,8 +94,7 @@ public class SettingsActivity extends AppCompatActivity { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { updatePreference(findPreference(key)); - if (key != null && isAdded() && (key.equals(getString(R.string.pref_key__clear_cache)) || - key.equals(getString(R.string.pref_key__font_size)) || + if (key != null && isAdded() && (key.equals(getString(R.string.pref_key__font_size)) || key.equals(getString(R.string.pref_key__load_images)) || key.equals(getString(R.string.pref_key__intellihide_toolbars)) || key.equals(getString(R.string.pref_key__proxy_enabled)) || @@ -158,6 +157,11 @@ public class SettingsActivity extends AppCompatActivity { .show(); return true; } + case R.string.pref_title__clear_cache: + { + intent.setAction(MainActivity.ACTION_CLEAR_CACHE); + break; + } default: { intent = null; From 91c706ed4a719e81171f39d60d1d51b7b96e8654 Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Mon, 3 Oct 2016 23:04:09 +0200 Subject: [PATCH 030/360] Only set window title depending on webviews content, when DiasporaStreamFragment is displayed (do not overwrite other fragments title when the webview loads in the background) --- .../dfa/diaspora_android/activity/MainActivity.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) 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 4efb4611..0d81096f 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 @@ -169,12 +169,18 @@ public class MainActivity extends AppCompatActivity brSetTitle = new UpdateTitleReceiver(app, urls, new UpdateTitleReceiver.TitleCallback() { @Override public void setTitle(int rId) { - MainActivity.this.setTitle(rId); + CustomFragment top = getTopFragment(); + if(top != null && top.getFragmentTag().equals(DiasporaStreamFragment.TAG)) { + MainActivity.this.setTitle(rId); + } } @Override public void setTitle(String title) { - MainActivity.this.setTitle(title); + CustomFragment top = getTopFragment(); + if(top != null && top.getFragmentTag().equals(DiasporaStreamFragment.TAG)) { + MainActivity.this.setTitle(title); + } } }); From 50207181f97bdd4eed064006c75cc5a80a218195 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Wed, 5 Oct 2016 02:30:10 +0200 Subject: [PATCH 031/360] Let PodService fetch from DfA; PodSelection rework --- .../data/DiasporaPodList.java | 470 ++++++ .../fragment/PodSelectionFragment.java | 160 +- .../diaspora_android/task/GetPodsService.java | 85 +- .../dfa/diaspora_android/util/Helpers.java | 25 +- .../res/layout/podselection__fragment.xml | 59 +- .../res/layout/recycler_view__list_item.xml | 22 +- app/src/main/res/menu/podselection__menu.xml | 7 + app/src/main/res/raw/podlist.json | 1401 +++++++++++++++++ app/src/main/res/values/strings.xml | 2 + 9 files changed, 2050 insertions(+), 181 deletions(-) create mode 100644 app/src/main/java/com/github/dfa/diaspora_android/data/DiasporaPodList.java create mode 100644 app/src/main/res/raw/podlist.json diff --git a/app/src/main/java/com/github/dfa/diaspora_android/data/DiasporaPodList.java b/app/src/main/java/com/github/dfa/diaspora_android/data/DiasporaPodList.java new file mode 100644 index 00000000..194fcf38 --- /dev/null +++ b/app/src/main/java/com/github/dfa/diaspora_android/data/DiasporaPodList.java @@ -0,0 +1,470 @@ +package com.github.dfa.diaspora_android.data; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + + +/** + * Created by gsantner (https://gsantner.github.io/ on 30.09.16. + * DiasporaPodList - List container for DiasporaPod's, with methods to merge with other DiasporaPodLists + * DiasporaPod - Data container for a Pod, can include N DiasporaPodUrl's + * DiasporaPodUrl - A Url of an DiasporaPod + * For all Classes a loading and saving to JSON method is available + */ +public class DiasporaPodList implements Iterable, Serializable { + private List pods = new ArrayList<>(); + private boolean trackMergeChanges = false; + private Integer trackAddedIndexStart = -1; + private List trackUpdatedIndexes = new ArrayList<>(); + + public DiasporaPodList() { + } + + /** + * Load DiasporaPodList from Json + * + * @param json Json Object + */ + public DiasporaPodList fromJson(JSONObject json) throws JSONException { + JSONArray jarr; + pods.clear(); + + if (json.has("pods")) { + jarr = json.getJSONArray("pods"); + for (int i = 0; i < jarr.length(); i++) { + DiasporaPod pod = new DiasporaPod().fromJson(jarr.getJSONObject(i)); + pods.add(pod); + } + } + return this; + } + + /** + * Convert DiasporaPodList to JSON + */ + public JSONObject toJson() throws JSONException { + JSONObject json = new JSONObject(); + JSONArray jpods = new JSONArray(); + for (DiasporaPod pod : pods) { + jpods.put(pod.toJson()); + } + json.put("pods", jpods); + return json; + } + + /** + * Merge newer entries into this podlist + * Will add new pods, and update data of pods with data from the new list + * + * @param newPodList Another podlist + */ + public void mergeWithNewerEntries(final DiasporaPodList newPodList) throws JSONException { + if (isTrackMergeChanges()) { + trackAddedIndexStart = -1; + trackUpdatedIndexes.clear(); + } + for (DiasporaPod newPod : newPodList) { + int index = pods.indexOf(newPod); + if (index >= 0) { + DiasporaPod updatePodBak = new DiasporaPod().fromJson(pods.get(index).toJson()); + DiasporaPod updatePod = pods.get(index); + updatePod.fromJson(newPod.toJson()); + + // Restore Pod id (if was set to zero) + if (updatePodBak.getId() != 0 && updatePod.getId() == 0) { + updatePod.setId(updatePodBak.getId()); + } + if (updatePodBak.getActive6() != 0 && updatePod.getActive6() == 0) { + updatePod.setActive6(updatePodBak.getActive6()); + } + if (updatePodBak.getScore() != 0 && updatePod.getScore() == 0) { + updatePod.setScore(updatePodBak.getScore()); + } + if (isTrackMergeChanges()) { + trackUpdatedIndexes.add(index); + } + } else { + pods.add(newPod); + if (isTrackMergeChanges() && trackAddedIndexStart == -1) { + trackAddedIndexStart = pods.size() - 1; + } + } + } + } + + /** + * Sort the pod list + */ + public void sortPods() { + Collections.sort(pods); + } + + /** + * Iterator for Iterable interface (forEach, ..) + */ + public Iterator iterator() { + return pods.iterator(); + } + + public int size() { + return pods.size(); + } + + public int indexOf(DiasporaPod pod) { + return pods.indexOf(pod); + } + + public List getPods() { + return pods; + } + + public void setPods(List pods) { + this.pods = pods; + } + + public DiasporaPod getPodAt(int index) { + if (index >= 0 && index < pods.size()) { + return pods.get(index); + } + return null; + } + + public boolean isTrackMergeChanges() { + return trackMergeChanges; + } + + public void setTrackMergeChanges(boolean trackMergeChanges) { + this.trackMergeChanges = trackMergeChanges; + } + + public Integer getTrackAddedIndexStart() { + return trackAddedIndexStart; + } + + public List getTrackUpdatedIndexes() { + return trackUpdatedIndexes; + } + + /* ██████╗ ██████╗ ██████╗ + * ██╔══██╗██╔═══██╗██╔══██╗ + * ██████╔╝██║ ██║██║ ██║ + * ██╔═══╝ ██║ ██║██║ ██║ + * ██║ ╚██████╔╝██████╔╝ + * ╚═╝ ╚═════╝ ╚═════╝ */ + public static class DiasporaPod implements Iterable, Comparable, Serializable { + private List podUrls = new ArrayList<>(); + private List mainLangs = new ArrayList<>(); + private String name = ""; + private int score = 0; + private int id = 0; + private long active6 = 0; + + + public DiasporaPod() { + } + + /** + * Load a DiasporaPod from JSON + * + * @param json Json Object + */ + public DiasporaPod fromJson(JSONObject json) throws JSONException { + JSONArray jarr; + + if (json.has("name")) { + name = json.getString("name"); + } + if (json.has("mainLangs")) { + jarr = json.getJSONArray("mainLangs"); + for (int i = 0; i < jarr.length(); i++) { + String val = jarr.getString(i); + if (!mainLangs.contains(val)) { + mainLangs.add(val); + } + } + } + if (json.has("podUrls")) { + jarr = json.getJSONArray("podUrls"); + for (int i = 0; i < jarr.length(); i++) { + DiasporaPodUrl podUrl = new DiasporaPodUrl().fromJson(jarr.getJSONObject(i)); + if (!podUrls.contains(podUrl)) { + podUrls.add(podUrl); + } + } + } + if (json.has("score")) { + score = json.getInt("score"); + } + if (json.has("active6")) { + active6 = json.getLong("active6"); + } + if (json.has("id")) { + id = json.getInt("id"); + } + return this; + } + + /** + * Convert DiasporaPod to JSON + */ + public JSONObject toJson() throws JSONException { + JSONObject json = new JSONObject(); + json.put("name", name); + json.put("score", score); + json.put("active6", active6); + json.put("id", id); + + // Pod urls + JSONArray jarr = new JSONArray(); + for (DiasporaPodUrl value : podUrls) { + jarr.put(value.toJson()); + } + json.put("podUrls", jarr); + + // main langs + jarr = new JSONArray(); + for (String value : mainLangs) { + jarr.put(value); + } + json.put("mainLangs", jarr); + return json; + } + + @Override + public boolean equals(Object o) { + boolean ret = false; + if (o instanceof DiasporaPod) { + DiasporaPod otherPod = (DiasporaPod) o; + + // Check if id is equal + ret = this.id != 0 && this.id == otherPod.id; + + // Check if host is the same (fallback if id is 0) + if (!ret) { + for (DiasporaPodUrl podUrl : podUrls) { + for (DiasporaPodUrl otherPodUrl : otherPod.getPodUrls()) { + if (podUrl.getBaseUrl().equals(otherPodUrl.getBaseUrl())) { + ret = true; + } + } + } + } + } + return ret; + } + + @Override + public int compareTo(DiasporaPod otherPod) { + if (otherPod != null) { + List myPodUrls = getPodUrls(); + List otherPodUrls = otherPod.getPodUrls(); + if (!myPodUrls.isEmpty() && !otherPodUrls.isEmpty()) { + return myPodUrls.get(0).getHost().compareTo(otherPodUrls.get(0).getHost()); + } + } + return name.compareTo(otherPod.getName()); + } + + @Override + public String toString() { + return name + "(" + id + ")"; + } + + /** + * Iterator for Iterable interface (forEach, ..) + */ + public Iterator iterator() { + return podUrls.iterator(); + } + + /* + * Getter & Setter + */ + public List getPodUrls() { + return podUrls; + } + + public DiasporaPod setPodUrls(List podUrls) { + this.podUrls = podUrls; + return this; + } + + public List getMainLangs() { + return mainLangs; + } + + public DiasporaPod setMainLangs(List mainLangs) { + this.mainLangs = mainLangs; + return this; + } + + public DiasporaPod appendMainLangs(String... values) { + for (String mainLang : values) { + this.mainLangs.add(mainLang); + } + return this; + } + + public DiasporaPod appendPodUrls(DiasporaPodUrl... values) { + for (DiasporaPodUrl value : values) { + this.podUrls.add(value); + } + return this; + } + + public String getName() { + return name; + } + + public DiasporaPod setName(String name) { + this.name = name; + return this; + } + + public int getScore() { + return score; + } + + public DiasporaPod setScore(int score) { + this.score = score; + return this; + } + + public long getActive6() { + return active6; + } + + public DiasporaPod setActive6(long active6) { + this.active6 = active6; + return this; + } + + public int getId() { + return id; + } + + public DiasporaPod setId(int id) { + this.id = id; + return this; + } + + /* ██████╗ ██████╗ ██████╗ ██╗ ██╗██████╗ ██╗ + * ██╔══██╗██╔═══██╗██╔══██╗ ██║ ██║██╔══██╗██║ + * ██████╔╝██║ ██║██║ ██║ ██║ ██║██████╔╝██║ + * ██╔═══╝ ██║ ██║██║ ██║ ██║ ██║██╔══██╗██║ + * ██║ ╚██████╔╝██████╔╝ ╚██████╔╝██║ ██║███████╗ + * ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ + */ + public static class DiasporaPodUrl implements Serializable { + private String host = ""; + private String protocol = "https"; + private Integer port = 443; + + public DiasporaPodUrl() { + } + + public DiasporaPodUrl(JSONObject json) throws JSONException { + fromJson(json); + } + + /** + * Get the base url + * + * @return + */ + public String getBaseUrl() { + return protocol + "://" + host + (isPortNeeded() ? port : ""); + } + + /** + * Convert JSON to DiasporaPodList + * + * @param json JSON Object + */ + public DiasporaPodUrl fromJson(JSONObject json) throws JSONException { + if (json.has("host")) { + host = json.getString("host"); + } + if (json.has("protocol")) { + protocol = json.getString("protocol"); + } + if (json.has("port")) { + port = json.getInt("port"); + } + return this; + } + + /*** + * Convert DiasporaPodList to JSON + */ + public JSONObject toJson() throws JSONException { + JSONObject json = new JSONObject(); + json.put("host", host); + if (!protocol.equals("https")) { + json.put("protocol", protocol); + } + if (port != 443) { + json.put("port", port); + } + return json; + } + + /** + * Tells if the ports needs to shown + */ + public boolean isPortNeeded() { + return !((port == 80 && protocol.equals("http")) || (port == 443 && protocol.equals("https"))); + } + + @Override + public String toString() { + return getBaseUrl(); + } + + @Override + public boolean equals(Object o) { + if (o instanceof DiasporaPodUrl) { + return getBaseUrl().equals(((DiasporaPodUrl) o).getBaseUrl()); + } + return false; + } + + /* + * GETTER & SETTER + */ + public String getHost() { + return host; + } + + public DiasporaPodUrl setHost(String host) { + this.host = host; + return this; + } + + public String getProtocol() { + return protocol; + } + + public DiasporaPodUrl setProtocol(String protocol) { + this.protocol = protocol; + return this; + } + + public Integer getPort() { + return port; + } + + public DiasporaPodUrl setPort(Integer port) { + this.port = port; + return this; + } + } + } +} diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/PodSelectionFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/PodSelectionFragment.java index d833d271..accdfff2 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/fragment/PodSelectionFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/PodSelectionFragment.java @@ -10,9 +10,9 @@ import android.os.Build; import android.os.Bundle; import android.support.design.widget.Snackbar; import android.support.v4.content.LocalBroadcastManager; -import android.text.Editable; +import android.support.v4.view.MenuItemCompat; +import android.support.v7.widget.SearchView; import android.text.SpannableString; -import android.text.TextWatcher; import android.text.util.Linkify; import android.view.LayoutInflater; import android.view.Menu; @@ -23,74 +23,94 @@ import android.view.ViewGroup; import android.webkit.CookieManager; import android.widget.AdapterView; import android.widget.ArrayAdapter; -import android.widget.EditText; -import android.widget.ImageView; import android.widget.ListView; import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.activity.MainActivity; import com.github.dfa.diaspora_android.data.AppSettings; +import com.github.dfa.diaspora_android.data.DiasporaPodList; +import com.github.dfa.diaspora_android.data.DiasporaPodList.DiasporaPod; import com.github.dfa.diaspora_android.task.GetPodsService; import com.github.dfa.diaspora_android.util.AppLog; import com.github.dfa.diaspora_android.util.DiasporaUrlHelper; +import com.github.dfa.diaspora_android.util.Helpers; import com.github.dfa.diaspora_android.util.WebHelper; +import org.json.JSONException; +import org.json.JSONObject; + import java.util.ArrayList; +import butterknife.BindView; +import butterknife.ButterKnife; + /** * Fragment that lets the user choose a Pod * Created by vanitas on 01.10.16. */ -public class PodSelectionFragment extends CustomFragment { +public class PodSelectionFragment extends CustomFragment implements SearchView.OnQueryTextListener { public static final String TAG = "com.github.dfa.diaspora_android.PodSelectionFragment"; - protected EditText editFilter; - protected ListView listPods; - protected ImageView selectPodButton; + @BindView(R.id.podselection__listpods) + protected ListView listViewPod; protected App app; protected AppSettings appSettings; + private DiasporaPodList podList; + private ArrayAdapter listViewPodAdapter; + private String filterString = ""; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { AppLog.d(this, "onCreateView()"); - return inflater.inflate(R.layout.podselection__fragment, container, false); + View view = inflater.inflate(R.layout.podselection__fragment, container, false); + ButterKnife.bind(this, view); + return view; } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - this.app = (App) getActivity().getApplication(); - this.appSettings = app.getSettings(); + app = (App) getActivity().getApplication(); + appSettings = app.getSettings(); - this.editFilter = (EditText) view.findViewById(R.id.podselection__edit_filter); - this.listPods = (ListView) view.findViewById(R.id.podselection__listpods); - this.selectPodButton = (ImageView) view.findViewById(R.id.podselection__button_select_pod); + // Load local podlist + podList = new DiasporaPodList(); + mergePodlistWithRessources(podList); + podList.setTrackMergeChanges(true); + updateListedPods(); - listPods.setTextFilterEnabled(true); - listPods.setOnItemClickListener(new AdapterView.OnItemClickListener() { + + listViewPod.setTextFilterEnabled(true); + listViewPod.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView adapterView, View view, int i, long l) { - showPodConfirmationDialog((String) listPods.getAdapter().getItem(i)); + showPodConfirmationDialog((String) listViewPod.getAdapter().getItem(i)); } }); - setListedPods(appSettings.getPreviousPodlist()); LocalBroadcastManager.getInstance(getContext()).registerReceiver(podListReceiver, new IntentFilter(GetPodsService.MESSAGE_PODS_RECEIVED)); - if (!WebHelper.isOnline(getContext())) { - Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show(); + Helpers.showInfoIfUserNotConnectedToInternet(getContext(), listViewPod); + } + + public void mergePodlistWithRessources(DiasporaPodList podlist) { + String sPodlist = Helpers.readTextfileFromRawRessource(getContext(), R.raw.podlist, "", ""); + try { + JSONObject jPodlist = new JSONObject(sPodlist); + podlist.mergeWithNewerEntries(new DiasporaPodList().fromJson(jPodlist)); + } catch (JSONException e) { + e.printStackTrace(); } - selectPodButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (editFilter.getText().length() > 4 && editFilter.getText().toString().contains("")) { - showPodConfirmationDialog(editFilter.getText().toString()); - } else { - Snackbar.make(listPods, R.string.valid_pod, Snackbar.LENGTH_LONG).show(); - } - } - }); + } + + // Called when a pod was clicked (or custom) + public void onPodButtonClicked(View v) { + //if (editFilter.getText().length() > 4 && editFilter.getText().toString().contains("")) { + showPodConfirmationDialog(filterString); + //} else { + // Snackbar.make(listViewPod, R.string.valid_pod, Snackbar.LENGTH_LONG).show(); + //} } @Override @@ -111,15 +131,17 @@ public class PodSelectionFragment extends CustomFragment { private final BroadcastReceiver podListReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - if (intent.hasExtra("pods")) { + if (intent.hasExtra(GetPodsService.EXTRA_PODLIST)) { Bundle extras = intent.getExtras(); - String[] pods = extras.getStringArray("pods"); - if (pods != null && pods.length > 0) { - app.getSettings().setPreviousPodlist(pods); - setListedPods(pods); + DiasporaPodList newPods = (DiasporaPodList) extras.get(GetPodsService.EXTRA_PODLIST); + if (newPods != null && newPods.getPods().size() > 0) { + try { + podList.mergeWithNewerEntries(newPods); + updateListedPods(); + } catch (JSONException ignored) { + } } else { - setListedPods(app.getSettings().getPreviousPodlist()); - Snackbar.make(listPods, R.string.podlist_error, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(listViewPod, R.string.podlist_error, Snackbar.LENGTH_SHORT).show(); } } } @@ -132,38 +154,25 @@ public class PodSelectionFragment extends CustomFragment { getContext().startService(i); } - - private void setListedPods(String[] listedPodsArr) { + private void updateListedPods() { final ArrayList listedPodsList = new ArrayList<>(); - for (String pod : listedPodsArr) { - listedPodsList.add(pod.toLowerCase()); + for (DiasporaPod pod : this.podList) { + listedPodsList.add(pod.getPodUrls().get(0).getHost()); } - final ArrayAdapter adapter = new ArrayAdapter<>( + listViewPodAdapter = new ArrayAdapter<>( getContext(), android.R.layout.simple_list_item_1, listedPodsList); // save index and top position - int index = listPods.getFirstVisiblePosition(); - View v = listPods.getChildAt(0); - int top = (v == null) ? 0 : (v.getTop() - listPods.getPaddingTop()); - listPods.setAdapter(adapter); - listPods.setSelectionFromTop(index, top); + int index = listViewPod.getFirstVisiblePosition(); + View v = listViewPod.getChildAt(0); + int top = (v == null) ? 0 : (v.getTop() - listViewPod.getPaddingTop()); + listViewPod.setAdapter(listViewPodAdapter); + listViewPod.setSelectionFromTop(index, top); - adapter.getFilter().filter(editFilter.getText()); - editFilter.addTextChangedListener(new TextWatcher() { - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - (adapter).getFilter().filter(s.toString()); - } - - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - public void afterTextChanged(Editable s) { - } - }); + listViewPodAdapter.getFilter().filter(filterString); } private void showPodConfirmationDialog(final String selectedPod) { @@ -173,7 +182,7 @@ public class PodSelectionFragment extends CustomFragment { // Check if online if (!WebHelper.isOnline(getContext())) { - Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show(); + Snackbar.make(listViewPod, R.string.no_internet, Snackbar.LENGTH_LONG).show(); return; } @@ -208,7 +217,7 @@ public class PodSelectionFragment extends CustomFragment { e.printStackTrace(); } - ((MainActivity)getActivity()).openDiasporaUrl(new DiasporaUrlHelper(appSettings).getPodUrl()); + ((MainActivity) getActivity()).openDiasporaUrl(new DiasporaUrlHelper(appSettings).getPodUrl()); } @Override @@ -220,6 +229,13 @@ public class PodSelectionFragment extends CustomFragment { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.podselection__menu, menu); + + MenuItem searchItem = menu.findItem(R.id.podselection__action_search); + if (searchItem != null) { + SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem); + searchView.setOnQueryTextListener(this); + } + super.onCreateOptionsMenu(menu, inflater); } @@ -227,16 +243,26 @@ public class PodSelectionFragment extends CustomFragment { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_reload: { - if (WebHelper.isOnline(getContext())) { + if (!Helpers.showInfoIfUserNotConnectedToInternet(getContext(), listViewPod)) { Intent i = new Intent(getContext(), GetPodsService.class); getContext().startService(i); return true; - } else { - Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show(); - return false; } } } return super.onOptionsItemSelected(item); } -} + + @Override + public boolean onQueryTextSubmit(String query) { + return false; + } + + @Override + public boolean onQueryTextChange(String newText) { + if (listViewPodAdapter != null) { + (listViewPodAdapter).getFilter().filter(newText); + } + return true; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/dfa/diaspora_android/task/GetPodsService.java b/app/src/main/java/com/github/dfa/diaspora_android/task/GetPodsService.java index afce5e01..988d3cf0 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/task/GetPodsService.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/task/GetPodsService.java @@ -24,9 +24,11 @@ import android.os.AsyncTask; import android.os.IBinder; import android.support.v4.content.LocalBroadcastManager; +import com.github.dfa.diaspora_android.data.DiasporaPodList; import com.github.dfa.diaspora_android.util.AppLog; import org.json.JSONArray; +import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; @@ -41,7 +43,9 @@ import javax.net.ssl.HttpsURLConnection; import info.guardianproject.netcipher.NetCipher; public class GetPodsService extends Service { + public static final String EXTRA_PODLIST = "pods"; public static final String MESSAGE_PODS_RECEIVED = "com.github.dfa.diaspora.podsreceived"; + public static final String PODDY_PODLIST_URL = "https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/podList/podlist.json"; public GetPodsService() { } @@ -53,75 +57,48 @@ public class GetPodsService extends Service { } private void getPods() { - /* - * Most of the code in this AsyncTask is from the file getPodlistTask.java - * from the app "Diaspora Webclient". - * A few modifications and adaptations were made by me. - * Source: - * https://github.com/voidcode/Diaspora-Webclient/blob/master/src/com/voidcode/diasporawebclient/getPodlistTask.java - * Thanks to Terkel Sørensen ; License : GPLv3 - */ - AsyncTask getPodsAsync = new AsyncTask() { + AsyncTask getPodsAsync = new AsyncTask() { @Override - protected String[] doInBackground(Void... params) { - - // TODO: Update deprecated code - - StringBuilder builder = new StringBuilder(); - //HttpClient client = new DefaultHttpClient(); - List list = null; - HttpsURLConnection connection; - InputStream inStream; + protected DiasporaPodList doInBackground(Void... params) { + StringBuilder sb = new StringBuilder(); + BufferedReader br = null; try { - connection = NetCipher.getHttpsURLConnection("https://podupti.me/api.php?key=4r45tg&format=json"); - int statusCode = connection.getResponseCode(); - if (statusCode == 200) { - inStream = connection.getInputStream(); - BufferedReader reader = new BufferedReader( - new InputStreamReader(inStream)); + HttpsURLConnection con = NetCipher.getHttpsURLConnection(PODDY_PODLIST_URL); + if (con.getResponseCode() == HttpsURLConnection.HTTP_OK) { + br = new BufferedReader(new InputStreamReader(con.getInputStream())); String line; - while ((line = reader.readLine()) != null) { - builder.append(line); + while ((line = br.readLine()) != null) { + sb.append(line); } - try { - inStream.close(); - } catch (IOException e) {/*Nothing to do*/} - - connection.disconnect(); + // Parse JSON & return pod list + JSONObject json = new JSONObject(sb.toString()); + return new DiasporaPodList().fromJson(json); } else { AppLog.e(this, "Failed to download list of pods"); } - } catch (IOException e) { - //TODO handle json buggy feed + } catch (IOException | JSONException e) { e.printStackTrace(); - } - //Parse the JSON Data - try { - JSONObject jsonObjectAll = new JSONObject(builder.toString()); - JSONArray jsonArrayAll = jsonObjectAll.getJSONArray("pods"); - AppLog.d(this, "Number of entries " + jsonArrayAll.length()); - list = new ArrayList<>(); - for (int i = 0; i < jsonArrayAll.length(); i++) { - JSONObject jo = jsonArrayAll.getJSONObject(i); - if (jo.getString("secure").equals("true")) - list.add(jo.getString("domain")); + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException ignored) { + } } - - } catch (Exception e) { - //TODO Handle Parsing errors here - e.printStackTrace(); } - if (list != null) - return list.toArray(new String[list.size()]); - else - return null; + + // Could not fetch list of pods :( + return new DiasporaPodList(); } @Override - protected void onPostExecute(String[] pods) { + protected void onPostExecute(DiasporaPodList pods) { + if (pods == null) { + pods = new DiasporaPodList(); + } Intent broadcastIntent = new Intent(MESSAGE_PODS_RECEIVED); - broadcastIntent.putExtra("pods", pods != null ? pods : new String[0]); + broadcastIntent.putExtra(EXTRA_PODLIST, pods); LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(broadcastIntent); stopSelf(); } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/util/Helpers.java b/app/src/main/java/com/github/dfa/diaspora_android/util/Helpers.java index 830380ec..b31299e2 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/util/Helpers.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/util/Helpers.java @@ -26,8 +26,9 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; +import android.support.design.widget.Snackbar; +import android.view.View; -import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.R; import java.io.BufferedReader; @@ -72,7 +73,7 @@ public class Helpers { // Create an image file name String timeStamp = new SimpleDateFormat("dd-MM-yy_HH-mm", Locale.getDefault()).format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; - AppLog.d(Helpers.class, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath()); + AppLog.d(Helpers.class, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath()); File storageDir = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES); return new File( @@ -116,18 +117,32 @@ public class Helpers { public static void printBundle(Bundle savedInstanceState, String k) { if (savedInstanceState != null) { for (String key : savedInstanceState.keySet()) { - AppLog.d("SAVED", key + " is a key in the bundle " + k); + AppLog.d("SAVED", key + " is a key in the bundle " + k); Object bun = savedInstanceState.get(key); if (bun != null) { if (bun instanceof Bundle) { printBundle((Bundle) bun, k + "." + key); } else if (bun instanceof byte[]) { - AppLog.d("SAVED", "Key: " + k + "." + key + ": " + Arrays.toString((byte[]) bun)); + AppLog.d("SAVED", "Key: " + k + "." + key + ": " + Arrays.toString((byte[]) bun)); } else { - AppLog.d("SAVED", "Key: " + k + "." + key + ": " + bun.toString()); + AppLog.d("SAVED", "Key: " + k + "." + key + ": " + bun.toString()); } } } } } + + /** + * Show Information if user is offline, returns true if is not connected to internet + * + * @param context Context + * @param anchor A view anchor + */ + public static boolean showInfoIfUserNotConnectedToInternet(Context context, View anchor) { + boolean isOnline = WebHelper.isOnline(context); + if (!isOnline) { + Snackbar.make(anchor, R.string.no_internet, Snackbar.LENGTH_LONG).show(); + } + return !isOnline; + } } diff --git a/app/src/main/res/layout/podselection__fragment.xml b/app/src/main/res/layout/podselection__fragment.xml index b8e39ac4..7fabd3b2 100644 --- a/app/src/main/res/layout/podselection__fragment.xml +++ b/app/src/main/res/layout/podselection__fragment.xml @@ -4,62 +4,29 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" + android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" - app:layout_behavior="@string/appbar_scrolling_view_behavior" - tools:showIn="@layout/podselection__fragment"> + app:layout_behavior="@string/appbar_scrolling_view_behavior"> + +