From 5921549a9c6d76c130dc7f2004eec83d114ef476 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Mon, 5 Mar 2018 23:37:24 +0100 Subject: [PATCH 01/19] Fix secondlion BuildConfig, githash --- app/build.gradle | 4 +- .../activity/AspectListFragment.java | 2 +- .../activity/TagListFragment.java | 2 +- .../ui/theme/ThemedColorPickerPreference.java | 2 +- .../nonsupport/LanguagePreference.java | 2 +- .../net/gsantner/opoc/util/ContextUtils.java | 50 +++++++++++++------ build.gradle | 9 ++-- 7 files changed, 48 insertions(+), 23 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 82a4c23a..eb3165e8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,8 +14,9 @@ android { targetSdkVersion version_setup_targetSdk buildConfigField "boolean", "IS_TEST_BUILD", "false" buildConfigField "boolean", "IS_GPLAY_BUILD", "false" - buildConfigField "String[]", "APPLICATION_LANGUAGES", "${getUsedAndroidLanguages()}" + buildConfigField "String[]", "DETECTED_ANDROID_LOCALES", "${findUsedAndroidLocales()}" buildConfigField "String", "GITHASH", "\"${getGitHash()}\"" + resValue "string", "manifest_package_id", "com.github.dfa.diaspora_android" applicationId "com.github.dfa.diaspora_android" versionName "1.1.0" @@ -53,6 +54,7 @@ android { flavorGplay { buildConfigField "boolean", "IS_GPLAY_BUILD", "true" }*/ + flavorTest { applicationId "com.github.dfa.secondlion" resValue 'string', 'app_name', "secondlion*" diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/AspectListFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/AspectListFragment.java index 5e615f2a..9da6a6de 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/AspectListFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/AspectListFragment.java @@ -167,7 +167,7 @@ public class AspectListFragment extends ThemedFragment implements OnSomethingCli final DiasporaAspect aspect = aspectList[position]; holder.title.setText(aspect.name); if (position % 2 == 1) { - holder.root.setBackgroundColor(isAmoledColorMode ? Color.BLACK : ContextUtils.get().color(R.color.alternate_row_color)); + holder.root.setBackgroundColor(isAmoledColorMode ? Color.BLACK : ContextUtils.get().rcolor(R.color.alternate_row_color)); holder.title.setTextColor(isAmoledColorMode ? Color.GRAY : Color.BLACK); } else { holder.root.setBackgroundColor(isAmoledColorMode ? Color.BLACK : Color.WHITE); diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/TagListFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/TagListFragment.java index 8502be10..7e6cb353 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/TagListFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/TagListFragment.java @@ -166,7 +166,7 @@ public class TagListFragment extends ThemedFragment implements OnSomethingClickL final String tag = followedTagsList[position]; holder.title.setText(tag); if (position % 2 == 1) { - holder.root.setBackgroundColor(isAmoledColorMode ? Color.BLACK : ContextUtils.get().color(R.color.alternate_row_color)); + holder.root.setBackgroundColor(isAmoledColorMode ? Color.BLACK : ContextUtils.get().rcolor(R.color.alternate_row_color)); holder.title.setTextColor(isAmoledColorMode ? Color.GRAY : Color.BLACK); } else { holder.root.setBackgroundColor(isAmoledColorMode ? Color.BLACK : Color.WHITE); diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedColorPickerPreference.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedColorPickerPreference.java index 6b61210e..524c1b65 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedColorPickerPreference.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedColorPickerPreference.java @@ -50,7 +50,7 @@ public class ThemedColorPickerPreference extends Preference implements Themeable AppSettings appSettings = AppSettings.get(); String key = getKey(); - int color = ContextUtils.get().color(R.color.primary); + int color = ContextUtils.get().rcolor(R.color.primary); if ((appSettings.isKeyEqual(key, R.string.pref_key__primary_color_shade))) { color = appSettings.getPrimaryColor(); } else if ((appSettings.isKeyEqual(key, R.string.pref_key__accent_color_shade))) { diff --git a/app/src/main/java/net/gsantner/opoc/preference/nonsupport/LanguagePreference.java b/app/src/main/java/net/gsantner/opoc/preference/nonsupport/LanguagePreference.java index a47a1a8d..7b4616b1 100644 --- a/app/src/main/java/net/gsantner/opoc/preference/nonsupport/LanguagePreference.java +++ b/app/src/main/java/net/gsantner/opoc/preference/nonsupport/LanguagePreference.java @@ -114,7 +114,7 @@ public class LanguagePreference extends ListPreference { // Fetch readable details ContextUtils contextUtils = new ContextUtils(context); List languages = new ArrayList<>(); - Object bcof = contextUtils.getBuildConfigValue("APPLICATION_LANGUAGES"); + Object bcof = contextUtils.getBuildConfigValue("DETECTED_ANDROID_LOCALES"); if (bcof instanceof String[]) { for (String langId : (String[]) bcof) { Locale locale = contextUtils.getLocaleByAndroidCode(langId); diff --git a/app/src/main/java/net/gsantner/opoc/util/ContextUtils.java b/app/src/main/java/net/gsantner/opoc/util/ContextUtils.java index efbd8423..a37102bc 100644 --- a/app/src/main/java/net/gsantner/opoc/util/ContextUtils.java +++ b/app/src/main/java/net/gsantner/opoc/util/ContextUtils.java @@ -100,18 +100,23 @@ public class ContextUtils { public static final String ARRAY = "array"; public static final String DIMEN = "dimen"; public static final String MENU = "menu"; + public static final String BOOL = "bool"; public static final String RAW = "raw"; } - public String str(@StringRes int strResId) { + public String rstr(@StringRes int strResId) { return _context.getString(strResId); } - public Drawable drawable(@DrawableRes int resId) { + public String rstr(String strResKey) { + return rstr(getResId(ResType.STRING, strResKey)); + } + + public Drawable rdrawable(@DrawableRes int resId) { return ContextCompat.getDrawable(_context, resId); } - public int color(@ColorRes int resId) { + public int rcolor(@ColorRes int resId) { return ContextCompat.getColor(_context, resId); } @@ -159,14 +164,23 @@ public class ContextUtils { } /** - * Get field from PackageId.BuildConfig + * Get field from ${applicationId}.BuildConfig * May be helpful in libraries, where a access to * BuildConfig would only get values of the library - * rather than the app ones + * rather than the app ones. It awaits a string resource + * of the package set in manifest (root element). + * Falls back to applicationId of the app which may differ from manifest. */ public Object getBuildConfigValue(String fieldName) { + String pkg; try { - Class c = Class.forName(_context.getPackageName() + ".BuildConfig"); + pkg = rstr("manifest_package_id"); + } catch (Resources.NotFoundException ex) { + pkg = _context.getPackageName(); + } + pkg += ".BuildConfig"; + try { + Class c = Class.forName(pkg); return c.getField(fieldName).get(null); } catch (Exception e) { e.printStackTrace(); @@ -174,7 +188,7 @@ public class ContextUtils { } } - public boolean getBuildConfigBoolean(String fieldName, boolean defaultValue) { + public boolean bcbool(String fieldName, boolean defaultValue) { Object field = getBuildConfigValue(fieldName); if (field != null && field instanceof Boolean) { return (Boolean) field; @@ -182,27 +196,35 @@ public class ContextUtils { return defaultValue; } + public String bcstr(String fieldName, String defaultValue) { + Object field = getBuildConfigValue(fieldName); + if (field != null && field instanceof String) { + return (String) field; + } + return defaultValue; + } + public boolean isGooglePlayBuild() { - return getBuildConfigBoolean("IS_GPLAY_BUILD", true); + return bcbool("IS_GPLAY_BUILD", true); } public boolean isFossBuild() { - return getBuildConfigBoolean("IS_FOSS_BUILD", false); + return bcbool("IS_FOSS_BUILD", false); } // Requires donate__bitcoin_* resources (see below) to be available as string resource public void showDonateBitcoinRequest(@StringRes final int strResBitcoinId, @StringRes final int strResBitcoinAmount, @StringRes final int strResBitcoinMessage, @StringRes final int strResAlternativeDonateUrl) { if (!isGooglePlayBuild()) { String btcUri = String.format("bitcoin:%s?amount=%s&label=%s&message=%s", - str(strResBitcoinId), str(strResBitcoinAmount), - str(strResBitcoinMessage), str(strResBitcoinMessage)); + rstr(strResBitcoinId), rstr(strResBitcoinAmount), + rstr(strResBitcoinMessage), rstr(strResBitcoinMessage)); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(btcUri)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { _context.startActivity(intent); } catch (ActivityNotFoundException e) { - openWebpageInExternalBrowser(str(strResAlternativeDonateUrl)); + openWebpageInExternalBrowser(rstr(strResAlternativeDonateUrl)); } } } @@ -239,7 +261,7 @@ public class ContextUtils { @SuppressWarnings("RestrictedApi") public void setTintColorOfButton(AppCompatButton button, @ColorRes int resColor) { button.setSupportBackgroundTintList(ColorStateList.valueOf( - color(resColor) + rcolor(resColor) )); } @@ -272,7 +294,7 @@ public class ContextUtils { return new SimpleMarkdownParser() .parse(_context.getResources().openRawResource(rawMdFile), prepend, SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW) - .replaceColor("#000001", color(getResId(ResType.COLOR, "accent"))) + .replaceColor("#000001", rcolor(getResId(ResType.COLOR, "accent"))) .removeMultiNewlines().replaceBulletCharacter("*").getHtml(); } catch (IOException e) { e.printStackTrace(); diff --git a/build.gradle b/build.gradle index f86d3bbf..3f0532f1 100644 --- a/build.gradle +++ b/build.gradle @@ -63,7 +63,7 @@ task copyRepoFiles(type: Copy) { @SuppressWarnings(["UnnecessaryQualifiedReference", "SpellCheckingInspection", "GroovyUnusedDeclaration"]) // Returns used android languages as a buildConfig array: {'de', 'it', ..}" -static String getUsedAndroidLanguages() { +static String findUsedAndroidLocales() { Set langs = new HashSet<>() new File('.').eachFileRecurse(groovy.io.FileType.DIRECTORIES) { final foldername = it.name @@ -80,12 +80,13 @@ static String getUsedAndroidLanguages() { ext.getGitHash = { -> try { - def stdout = new ByteArrayOutputStream() exec { + def stdout = new ByteArrayOutputStream() + exec { commandLine 'git', 'rev-parse', 'HEAD' standardOutput = stdout } return stdout.toString().trim() - } catch (Exception e) { - return '???' + } catch (Exception ignored) { + return 'unknown' } } From 6cac47763c00d3f9e11969e721ebb372ebe4084f Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Mon, 5 Mar 2018 23:45:10 +0100 Subject: [PATCH 02/19] Release v1.1.1 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index eb3165e8..3838b62b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -19,8 +19,8 @@ android { resValue "string", "manifest_package_id", "com.github.dfa.diaspora_android" applicationId "com.github.dfa.diaspora_android" - versionName "1.1.0" - versionCode 29 + versionName "1.1.1" + versionCode 30 vectorDrawables.useSupportLibrary = true From 43a2ad25bcb101e721bf71d9da42cf9f256f448e Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Mon, 12 Mar 2018 00:05:53 +0100 Subject: [PATCH 03/19] Update opoc license headers --- .../activity/MainActivity.java | 8 +- .../diaspora_android/ui/BadgeDrawable.java | 2 +- .../format/markdown/SimpleMarkdownParser.java | 23 +- .../nonsupport/LanguagePreference.java | 21 +- .../net/gsantner/opoc/util/ActivityUtils.java | 19 +- .../java/net/gsantner/opoc/util/AdBlock.java | 19 +- .../gsantner/opoc/util/AppSettingsBase.java | 19 +- .../net/gsantner/opoc/util/ContextUtils.java | 210 ++++++++++-------- .../gsantner/opoc/util/PropertyBackend.java | 19 +- 9 files changed, 177 insertions(+), 163 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 1b71a177..348643db 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 @@ -693,10 +693,10 @@ public class MainActivity extends ThemedActivity } } - final boolean darkBg = ContextUtils.get().shouldColorOnTopBeLight(AppSettings.get().getPrimaryColor()); - ContextUtils.get() - .tintMenuItems(menu, true, ContextCompat.getColor(this, darkBg ? R.color.white : R.color.black)) - .setSubMenuIconsVisiblity(menu, true); + ContextUtils cu = ContextUtils.get(); + final boolean darkBg = cu.get().shouldColorOnTopBeLight(AppSettings.get().getPrimaryColor()); + cu.tintMenuItems(menu, true, ContextCompat.getColor(this, darkBg ? R.color.white : R.color.black)); + cu.setSubMenuIconsVisiblity(menu, true); return true; } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/BadgeDrawable.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/BadgeDrawable.java index 5d3ddbee..39701d29 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/ui/BadgeDrawable.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/BadgeDrawable.java @@ -71,7 +71,7 @@ public class BadgeDrawable extends Drawable { Rect bounds = getBounds(); float width = bounds.right - bounds.left; float height = bounds.bottom - bounds.top; - float oneDp = ContextUtils.get().dp2px(1); + float oneDp = ContextUtils.get().convertDpToPx(1); // Position the badge in the top-right quadrant of the icon. float radius = ((Math.max(width, height) / 2)) / 2; diff --git a/app/src/main/java/net/gsantner/opoc/format/markdown/SimpleMarkdownParser.java b/app/src/main/java/net/gsantner/opoc/format/markdown/SimpleMarkdownParser.java index 3907cb47..089910c0 100644 --- a/app/src/main/java/net/gsantner/opoc/format/markdown/SimpleMarkdownParser.java +++ b/app/src/main/java/net/gsantner/opoc/format/markdown/SimpleMarkdownParser.java @@ -1,20 +1,15 @@ -/* - * ------------------------------------------------------------------------------ - * Gregor Santner wrote this. You can do whatever you want - * with it. If we meet some day, and you think it is worth it, you can buy me a - * coke in return. Provided as is without any kind of warranty. Do not blame or - * sue me if something goes wrong. No attribution required. - Gregor Santner +/*####################################################### * - * License: Creative Commons Zero (CC0 1.0) - * http://creativecommons.org/publicdomain/zero/1.0/ - * ---------------------------------------------------------------------------- - */ + * Maintained by Gregor Santner, 2016- + * https://gsantner.net/ + * + * License: Apache 2.0 + * https://github.com/gsantner/opoc/#licensing + * https://www.apache.org/licenses/LICENSE-2.0 + * +#########################################################*/ /* - * Get updates: - * https://github.com/gsantner/onePieceOfCode/blob/master/java/SimpleMarkdownParser.java - * Apply to TextView: - * See https://github.com/gsantner/onePieceOfCode/blob/master/android/ContextUtils.java * Parses most common markdown tags. Only inline tags are supported, multiline/block syntax * is not supported (citation, multiline code, ..). This is intended to stay as easy as possible. * diff --git a/app/src/main/java/net/gsantner/opoc/preference/nonsupport/LanguagePreference.java b/app/src/main/java/net/gsantner/opoc/preference/nonsupport/LanguagePreference.java index 7b4616b1..52dfc3d1 100644 --- a/app/src/main/java/net/gsantner/opoc/preference/nonsupport/LanguagePreference.java +++ b/app/src/main/java/net/gsantner/opoc/preference/nonsupport/LanguagePreference.java @@ -1,14 +1,13 @@ -/* - * ------------------------------------------------------------------------------ - * Gregor Santner wrote this. You can do whatever you want - * with it. If we meet some day, and you think it is worth it, you can buy me a - * coke in return. Provided as is without any kind of warranty. Do not blame or - * sue me if something goes wrong. No attribution required. - Gregor Santner +/*####################################################### * - * License: Creative Commons Zero (CC0 1.0) - * http://creativecommons.org/publicdomain/zero/1.0/ - * ---------------------------------------------------------------------------- - */ + * Maintained by Gregor Santner, 2017- + * https://gsantner.net/ + * + * License: Apache 2.0 + * https://github.com/gsantner/opoc/#licensing + * https://www.apache.org/licenses/LICENSE-2.0 + * +#########################################################*/ /* * Requires: @@ -186,4 +185,4 @@ public class LanguagePreference extends ListPreference { _defaultLanguageCode = defaultLanguageCode; loadLangs(getContext()); } -} \ No newline at end of file +} diff --git a/app/src/main/java/net/gsantner/opoc/util/ActivityUtils.java b/app/src/main/java/net/gsantner/opoc/util/ActivityUtils.java index 677700be..53a86cc1 100644 --- a/app/src/main/java/net/gsantner/opoc/util/ActivityUtils.java +++ b/app/src/main/java/net/gsantner/opoc/util/ActivityUtils.java @@ -1,14 +1,13 @@ -/* - * ------------------------------------------------------------------------------ - * Gregor Santner wrote this. You can do whatever you want - * with it. If we meet some day, and you think it is worth it, you can buy me a - * coke in return. Provided as is without any kind of warranty. Do not blame or - * sue me if something goes wrong. No attribution required. - Gregor Santner +/*####################################################### * - * License: Creative Commons Zero (CC0 1.0) - * http://creativecommons.org/publicdomain/zero/1.0/ - * ---------------------------------------------------------------------------- - */ + * Maintained by Gregor Santner, 2016- + * https://gsantner.net/ + * + * License: Apache 2.0 + * https://github.com/gsantner/opoc/#licensing + * https://www.apache.org/licenses/LICENSE-2.0 + * +#########################################################*/ package net.gsantner.opoc.util; import android.app.Activity; diff --git a/app/src/main/java/net/gsantner/opoc/util/AdBlock.java b/app/src/main/java/net/gsantner/opoc/util/AdBlock.java index 6c61038c..304a4b85 100644 --- a/app/src/main/java/net/gsantner/opoc/util/AdBlock.java +++ b/app/src/main/java/net/gsantner/opoc/util/AdBlock.java @@ -1,14 +1,13 @@ -/* - * ---------------------------------------------------------------------------- * - * Gregor Santner wrote this file. You can do whatever - * you want with this stuff. If we meet some day, and you think this stuff is - * worth it, you can buy me a coke in return. Provided as is without any kind - * of warranty. No attribution required. - Gregor Santner +/*####################################################### * - * License of this file: Creative Commons Zero (CC0 1.0) - * http://creativecommons.org/publicdomain/zero/1.0/ - * ---------------------------------------------------------------------------- - */ + * Maintained by Gregor Santner, 2017- + * https://gsantner.net/ + * + * License: Apache 2.0 + * https://github.com/gsantner/opoc/#licensing + * https://www.apache.org/licenses/LICENSE-2.0 + * +#########################################################*/ /* * Place adblock hosts file in raw: src/main/res/raw/adblock_domains__xyz.txt diff --git a/app/src/main/java/net/gsantner/opoc/util/AppSettingsBase.java b/app/src/main/java/net/gsantner/opoc/util/AppSettingsBase.java index a78dfdb8..755e320d 100644 --- a/app/src/main/java/net/gsantner/opoc/util/AppSettingsBase.java +++ b/app/src/main/java/net/gsantner/opoc/util/AppSettingsBase.java @@ -1,14 +1,13 @@ -/* - * ------------------------------------------------------------------------------ - * Gregor Santner wrote this. You can do whatever you want - * with it. If we meet some day, and you think it is worth it, you can buy me a - * coke in return. Provided as is without any kind of warranty. Do not blame or - * sue me if something goes wrong. No attribution required. - Gregor Santner +/*####################################################### * - * License: Creative Commons Zero (CC0 1.0) - * http://creativecommons.org/publicdomain/zero/1.0/ - * ---------------------------------------------------------------------------- - */ + * Maintained by Gregor Santner, 2016- + * https://gsantner.net/ + * + * License: Apache 2.0 + * https://github.com/gsantner/opoc/#licensing + * https://www.apache.org/licenses/LICENSE-2.0 + * +#########################################################*/ /* * This is a wrapper for settings based on SharedPreferences diff --git a/app/src/main/java/net/gsantner/opoc/util/ContextUtils.java b/app/src/main/java/net/gsantner/opoc/util/ContextUtils.java index a37102bc..79cc1686 100644 --- a/app/src/main/java/net/gsantner/opoc/util/ContextUtils.java +++ b/app/src/main/java/net/gsantner/opoc/util/ContextUtils.java @@ -1,14 +1,13 @@ -/* - * ------------------------------------------------------------------------------ - * Gregor Santner wrote this. You can do whatever you want - * with it. If we meet some day, and you think it is worth it, you can buy me a - * coke in return. Provided as is without any kind of warranty. Do not blame or - * sue me if something goes wrong. No attribution required. - Gregor Santner +/*####################################################### * - * License: Creative Commons Zero (CC0 1.0) - * http://creativecommons.org/publicdomain/zero/1.0/ - * ---------------------------------------------------------------------------- - */ + * Maintained by Gregor Santner, 2016- + * https://gsantner.net/ + * + * License: Apache 2.0 + * https://github.com/gsantner/opoc/#licensing + * https://www.apache.org/licenses/LICENSE-2.0 + * +#########################################################*/ package net.gsantner.opoc.util; import android.annotation.SuppressLint; @@ -20,7 +19,6 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; @@ -46,19 +44,17 @@ import android.support.annotation.StringRes; import android.support.graphics.drawable.VectorDrawableCompat; import android.support.v4.content.ContextCompat; import android.support.v4.graphics.drawable.DrawableCompat; -import android.support.v7.widget.AppCompatButton; import android.text.Html; import android.text.SpannableString; import android.text.Spanned; import android.text.TextUtils; import android.text.method.LinkMovementMethod; import android.util.DisplayMetrics; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; -import android.view.View; import android.widget.ImageView; import android.widget.TextView; -import android.widget.Toast; import net.gsantner.opoc.format.markdown.SimpleMarkdownParser; @@ -69,11 +65,14 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.graphics.Bitmap.CompressFormat; -@SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue", "SpellCheckingInspection", "deprecation", "ObsoleteSdkInt", "ConstantConditions", "UnusedReturnValue"}) +@SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue", "ObsoleteSdkInt", "deprecation", "SpellCheckingInspection"}) public class ContextUtils { //######################## //## Members, Constructors @@ -155,7 +154,7 @@ public class ContextUtils { public void openWebpageInExternalBrowser(final String url) { Uri uri = Uri.parse(url); Intent intent = new Intent(Intent.ACTION_VIEW, uri); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags(FLAG_ACTIVITY_NEW_TASK); try { _context.startActivity(intent); } catch (ActivityNotFoundException e) { @@ -220,7 +219,7 @@ public class ContextUtils { rstr(strResBitcoinMessage), rstr(strResBitcoinMessage)); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(btcUri)); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags(FLAG_ACTIVITY_NEW_TASK); try { _context.startActivity(intent); } catch (ActivityNotFoundException e) { @@ -257,36 +256,43 @@ public class ContextUtils { return sb.toString(); } - @SuppressLint("RestrictedApi") - @SuppressWarnings("RestrictedApi") - public void setTintColorOfButton(AppCompatButton button, @ColorRes int resColor) { - button.setSupportBackgroundTintList(ColorStateList.valueOf( - rcolor(resColor) - )); - } - - @SuppressLint("MissingPermission") // ACCESS_NETWORK_STATE required + /** + * Get internet connection state - the permission ACCESS_NETWORK_STATE is required + * + * @return True if internet connection available + */ public boolean isConnectedToInternet() { - ConnectivityManager con = (ConnectivityManager) _context.getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo activeNetInfo = con == null ? null : con.getActiveNetworkInfo(); - return activeNetInfo != null && activeNetInfo.isConnectedOrConnecting(); + try { + ConnectivityManager con = (ConnectivityManager) _context.getSystemService(Context.CONNECTIVITY_SERVICE); + @SuppressLint("MissingPermission") NetworkInfo activeNetInfo = + con == null ? null : con.getActiveNetworkInfo(); + return activeNetInfo != null && activeNetInfo.isConnectedOrConnecting(); + } catch (Exception ignored) { + throw new RuntimeException("Error: Developer forgot to declare a permission"); + } } - public boolean isConnectedToInternet(@Nullable @StringRes Integer warnMessageStringRes) { - final boolean result = isConnectedToInternet(); - if (!result && warnMessageStringRes != null) - Toast.makeText(_context, _context.getString(warnMessageStringRes), Toast.LENGTH_SHORT).show(); - - return result; + public boolean isAppInstalled(String packageName) { + PackageManager pm = _context.getApplicationContext().getPackageManager(); + try { + pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES); + return true; + } catch (PackageManager.NameNotFoundException e) { + return false; + } } - public void restartApp(Class classToStartupWith) { - Intent restartIntent = new Intent(_context, classToStartupWith); - PendingIntent restartIntentP = PendingIntent.getActivity(_context, 555, - restartIntent, PendingIntent.FLAG_CANCEL_CURRENT); + public void restartApp(Class classToStart) { + Intent inte = new Intent(_context, classToStart); + PendingIntent inteP = PendingIntent.getActivity(_context, 555, inte, PendingIntent.FLAG_CANCEL_CURRENT); AlarmManager mgr = (AlarmManager) _context.getSystemService(Context.ALARM_SERVICE); - mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, restartIntentP); - System.exit(0); + if (mgr != null) { + mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, inteP); + } else { + inte.addFlags(FLAG_ACTIVITY_NEW_TASK); + _context.startActivity(inte); + } + Runtime.getRuntime().exit(0); } public String loadMarkdownForTextViewFromRaw(@RawRes int rawMdFile, String prepend) { @@ -348,7 +354,6 @@ public class ContextUtils { + (0.114 * Color.blue(colorOnBottomInt))))); } - @SuppressWarnings("deprecation") public Spanned htmlToSpanned(String html) { Spanned result; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { @@ -359,41 +364,53 @@ public class ContextUtils { return result; } - public void setClipboard(String text) { + public boolean setClipboard(String text) { if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) { - ((android.text.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE)).setText(text); + android.text.ClipboardManager cm = ((android.text.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE)); + if (cm != null) { + cm.setText(text); + return true; + } } else { - ClipData clip = ClipData.newPlainText(_context.getPackageName(), text); - ((android.content.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE)).setPrimaryClip(clip); - } - } - - public String[] getClipboard() { - String[] ret; - if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) { - ret = new String[]{((android.text.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE)).getText().toString()}; - } else { - ClipData data = ((android.content.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE)).getPrimaryClip(); - ret = new String[data.getItemCount()]; - for (int i = 0; i < data.getItemCount() && i < ret.length; i++) { - ret[i] = data.getItemAt(i).getText().toString(); + android.content.ClipboardManager cm = ((android.content.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE)); + if (cm != null) { + ClipData clip = ClipData.newPlainText(_context.getPackageName(), text); + cm.setPrimaryClip(clip); + return true; } } - return ret; + return false; } - public float px2dp(final float px) { + public List getClipboard() { + List clipper = new ArrayList<>(); + if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) { + android.text.ClipboardManager cm = ((android.text.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE)); + if (cm != null) { + clipper.add(cm.getText().toString()); + } + + } else { + android.content.ClipboardManager cm = ((android.content.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE)); + if (cm != null && cm.hasPrimaryClip()) { + ClipData data = cm.getPrimaryClip(); + for (int i = 0; i < data.getItemCount() && i < data.getItemCount(); i++) { + clipper.add(data.getItemAt(i).getText().toString()); + } + } + + } + return clipper; + } + + public float convertPxToDp(final float px) { return px / _context.getResources().getDisplayMetrics().density; } - public float dp2px(final float dp) { + public float convertDpToPx(final float dp) { return dp * _context.getResources().getDisplayMetrics().density; } - public void setViewVisible(View view, boolean visible) { - view.setVisibility(visible ? View.VISIBLE : View.GONE); - } - public static void setDrawableWithColorToImageView(ImageView imageView, @DrawableRes int drawableResId, @ColorRes int colorResId) { imageView.setImageResource(drawableResId); imageView.setColorFilter(ContextCompat.getColor(imageView.getContext(), colorResId)); @@ -453,31 +470,40 @@ public class ContextUtils { return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); } - public File writeImageToFileJpeg(File imageFile, Bitmap image) { + public boolean writeImageToFileJpeg(File imageFile, Bitmap image) { return writeImageToFile(imageFile, image, Bitmap.CompressFormat.JPEG, 95); } - - public File writeImageToFileDetectFormat(File imageFile, Bitmap image, int quality) { - CompressFormat format = CompressFormat.JPEG; - String lc = imageFile.getAbsolutePath().toLowerCase(Locale.ROOT); - if (lc.endsWith(".png")) { - format = CompressFormat.PNG; + /** + * Write bitmap to the filesystem + * + * @param targetFile The file to be written in + * @param image The image as android {@link Bitmap} + * @param format One format of {@link CompressFormat}, null will determine based on filename + * @param quality Quality level, defaults to 95 + * @return True if writing was successful + */ + public boolean writeImageToFile(File targetFile, Bitmap image, CompressFormat format, Integer quality) { + File folder = new File(targetFile.getParent()); + if (quality == null || quality < 0 || quality > 100) { + quality = 95; } - if (lc.endsWith(".webp")) { - format = CompressFormat.WEBP; + if (format == null) { + format = CompressFormat.JPEG; + String lc = targetFile.getAbsolutePath().toLowerCase(Locale.ROOT); + if (lc.endsWith(".png")) { + format = CompressFormat.PNG; + } + if (lc.endsWith(".webp")) { + format = CompressFormat.WEBP; + } } - return writeImageToFile(imageFile, image, format, quality); - } - - public File writeImageToFile(File imageFile, Bitmap image, CompressFormat format, int quality) { - File folder = new File(imageFile.getParent()); if (folder.exists() || folder.mkdirs()) { FileOutputStream stream = null; try { - stream = new FileOutputStream(imageFile); // overwrites this image every time + stream = new FileOutputStream(targetFile); // overwrites this image every time image.compress(format, quality, stream); - return imageFile; + return true; } catch (FileNotFoundException ignored) { } finally { try { @@ -488,13 +514,13 @@ public class ContextUtils { } } } - return null; + return false; } - public Bitmap drawTextToDrawable(@DrawableRes int resId, String text, int textSize) { + public Bitmap drawTextOnDrawable(@DrawableRes int resId, String text, int textSize) { Resources resources = _context.getResources(); float scale = resources.getDisplayMetrics().density; - Bitmap bitmap = getBitmapFromDrawable(resId); + Bitmap bitmap = bitmapToDrawable(resId); bitmap = bitmap.copy(bitmap.getConfig(), true); Canvas canvas = new Canvas(bitmap); @@ -512,7 +538,7 @@ public class ContextUtils { return bitmap; } - public Bitmap getBitmapFromDrawable(int drawableId) { + public Bitmap bitmapToDrawable(@DrawableRes int drawableId) { Bitmap bitmap = null; Drawable drawable = ContextCompat.getDrawable(_context, drawableId); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && (drawable instanceof VectorDrawable || drawable instanceof VectorDrawableCompat)) { @@ -520,8 +546,7 @@ public class ContextUtils { drawable = (DrawableCompat.wrap(drawable)).mutate(); } - bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), - drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); + bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); @@ -531,7 +556,8 @@ public class ContextUtils { return bitmap; } - public ContextUtils tintMenuItems(Menu menu, boolean recurse, @ColorInt int iconColor) { + @SuppressWarnings("ConstantConditions") + public void tintMenuItems(Menu menu, boolean recurse, @ColorInt int iconColor) { for (int i = 0; i < menu.size(); i++) { MenuItem item = menu.getItem(i); tintDrawable(item.getIcon(), iconColor); @@ -539,7 +565,6 @@ public class ContextUtils { tintMenuItems(item.getSubMenu(), recurse, iconColor); } } - return this; } public Drawable tintDrawable(@DrawableRes int drawableRes, @ColorInt int color) { @@ -554,16 +579,15 @@ public class ContextUtils { return drawable; } - @SuppressLint("PrivateApi") - public ContextUtils setSubMenuIconsVisiblity(Menu menu, boolean visible) { + public void setSubMenuIconsVisiblity(Menu menu, boolean visible) { if (menu.getClass().getSimpleName().equals("MenuBuilder")) { try { - Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE); + @SuppressLint("PrivateApi") Method m = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE); m.setAccessible(true); m.invoke(menu, visible); } catch (Exception ignored) { + Log.d(getClass().getName(), "Error: 'setSubMenuIconsVisiblity' not supported on this device"); } } - return this; } } diff --git a/app/src/main/java/net/gsantner/opoc/util/PropertyBackend.java b/app/src/main/java/net/gsantner/opoc/util/PropertyBackend.java index b6758fbf..d618955e 100644 --- a/app/src/main/java/net/gsantner/opoc/util/PropertyBackend.java +++ b/app/src/main/java/net/gsantner/opoc/util/PropertyBackend.java @@ -1,14 +1,13 @@ -/* - * ------------------------------------------------------------------------------ - * Gregor Santner wrote this. You can do whatever you want - * with it. If we meet some day, and you think it is worth it, you can buy me a - * coke in return. Provided as is without any kind of warranty. Do not blame or - * sue me if something goes wrong. No attribution required. - Gregor Santner +/*####################################################### * - * License: Creative Commons Zero (CC0 1.0) - * http://creativecommons.org/publicdomain/zero/1.0/ - * ---------------------------------------------------------------------------- - */ + * Maintained by Gregor Santner, 2018- + * https://gsantner.net/ + * + * License: Apache 2.0 + * https://github.com/gsantner/opoc/#licensing + * https://www.apache.org/licenses/LICENSE-2.0 + * +#########################################################*/ package net.gsantner.opoc.util; import java.util.List; From 586875e32ba2eca98a704e18078115ac6f4b2946 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Fri, 30 Mar 2018 00:14:54 +0200 Subject: [PATCH 04/19] Update gsantner-opoc to latest state --- .../diaspora_android/util/AppSettings.java | 4 +- .../format/markdown/SimpleMarkdownParser.java | 2 +- .../{util => preference}/PropertyBackend.java | 4 +- .../SharedPreferencesPropertyBackend.java} | 86 ++--- .../net/gsantner/opoc/util/ContextUtils.java | 311 +++++++++++------- 5 files changed, 233 insertions(+), 174 deletions(-) rename app/src/main/java/net/gsantner/opoc/{util => preference}/PropertyBackend.java (94%) rename app/src/main/java/net/gsantner/opoc/{util/AppSettingsBase.java => preference/SharedPreferencesPropertyBackend.java} (89%) diff --git a/app/src/main/java/com/github/dfa/diaspora_android/util/AppSettings.java b/app/src/main/java/com/github/dfa/diaspora_android/util/AppSettings.java index 28914097..1b3d2bff 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/util/AppSettings.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/util/AppSettings.java @@ -26,7 +26,7 @@ import com.github.dfa.diaspora_android.data.DiasporaAspect; import com.github.dfa.diaspora_android.data.DiasporaPodList.DiasporaPod; import com.github.dfa.diaspora_android.web.ProxyHandler; -import net.gsantner.opoc.util.AppSettingsBase; +import net.gsantner.opoc.preference.SharedPreferencesPropertyBackend; import org.json.JSONException; import org.json.JSONObject; @@ -38,7 +38,7 @@ import java.util.List; * Created by gsantner (http://gsantner.net/) on 20.03.16. Part of dandelion*. */ @SuppressWarnings("ConstantConditions") -public class AppSettings extends AppSettingsBase { +public class AppSettings extends SharedPreferencesPropertyBackend { private final SharedPreferences _prefPod; private DiasporaPod currentPod0Cached; diff --git a/app/src/main/java/net/gsantner/opoc/format/markdown/SimpleMarkdownParser.java b/app/src/main/java/net/gsantner/opoc/format/markdown/SimpleMarkdownParser.java index 089910c0..744bd0b4 100644 --- a/app/src/main/java/net/gsantner/opoc/format/markdown/SimpleMarkdownParser.java +++ b/app/src/main/java/net/gsantner/opoc/format/markdown/SimpleMarkdownParser.java @@ -33,7 +33,7 @@ import java.io.InputStreamReader; /** * Simple Markdown Parser */ -@SuppressWarnings({"WeakerAccess", "CaughtExceptionImmediatelyRethrown", "SameParameterValue", "unused", "SpellCheckingInspection", "RepeatedSpace", "SingleCharAlternation"}) +@SuppressWarnings({"WeakerAccess", "CaughtExceptionImmediatelyRethrown", "SameParameterValue", "unused", "SpellCheckingInspection", "RepeatedSpace", "SingleCharAlternation", "Convert2Lambda"}) public class SimpleMarkdownParser { //######################## //## Statics diff --git a/app/src/main/java/net/gsantner/opoc/util/PropertyBackend.java b/app/src/main/java/net/gsantner/opoc/preference/PropertyBackend.java similarity index 94% rename from app/src/main/java/net/gsantner/opoc/util/PropertyBackend.java rename to app/src/main/java/net/gsantner/opoc/preference/PropertyBackend.java index d618955e..c27d9bce 100644 --- a/app/src/main/java/net/gsantner/opoc/util/PropertyBackend.java +++ b/app/src/main/java/net/gsantner/opoc/preference/PropertyBackend.java @@ -8,11 +8,11 @@ * https://www.apache.org/licenses/LICENSE-2.0 * #########################################################*/ -package net.gsantner.opoc.util; +package net.gsantner.opoc.preference; import java.util.List; -@SuppressWarnings({"UnusedReturnValue", "SpellCheckingInspection"}) +@SuppressWarnings({"UnusedReturnValue", "SpellCheckingInspection", "unused", "SameParameterValue"}) public interface PropertyBackend { String getString(TKEY key, String defaultValue); diff --git a/app/src/main/java/net/gsantner/opoc/util/AppSettingsBase.java b/app/src/main/java/net/gsantner/opoc/preference/SharedPreferencesPropertyBackend.java similarity index 89% rename from app/src/main/java/net/gsantner/opoc/util/AppSettingsBase.java rename to app/src/main/java/net/gsantner/opoc/preference/SharedPreferencesPropertyBackend.java index 755e320d..275d88a5 100644 --- a/app/src/main/java/net/gsantner/opoc/util/AppSettingsBase.java +++ b/app/src/main/java/net/gsantner/opoc/preference/SharedPreferencesPropertyBackend.java @@ -31,7 +31,7 @@ } */ -package net.gsantner.opoc.util; +package net.gsantner.opoc.preference; import android.annotation.SuppressLint; import android.content.Context; @@ -48,36 +48,36 @@ import java.util.List; /** - * Wrapper for settings based on SharedPreferences with keys in resources + * Wrapper for settings based on SharedPreferences, optionally with keys in resources * Default SharedPreference (_prefApp) will be taken if no SP is specified, else the first one */ @SuppressWarnings({"WeakerAccess", "unused", "SpellCheckingInspection", "SameParameterValue"}) -public class AppSettingsBase implements PropertyBackend { +public class SharedPreferencesPropertyBackend implements PropertyBackend { protected static final String ARRAY_SEPARATOR = "%%%"; protected static final String ARRAY_SEPARATOR_SUBSTITUTE = "§§§"; public static final String SHARED_PREF_APP = "app"; - //######################## - //## Members, Constructors - //######################## + // + // Members, Constructors + // protected final SharedPreferences _prefApp; protected final String _prefAppName; protected final Context _context; - public AppSettingsBase(final Context context) { + public SharedPreferencesPropertyBackend(final Context context) { this(context, SHARED_PREF_APP); } - public AppSettingsBase(final Context context, final String prefAppName) { + public SharedPreferencesPropertyBackend(final Context context, final String prefAppName) { _context = context.getApplicationContext(); _prefAppName = TextUtils.isEmpty(prefAppName) ? _context.getPackageName() + "_preferences" : prefAppName; _prefApp = _context.getSharedPreferences(_prefAppName, Context.MODE_PRIVATE); } - //##################### - //## Methods - //##################### + // + // Methods + // public Context getContext() { return _context; } @@ -136,9 +136,9 @@ public class AppSettingsBase implements PropertyBackend return (pref != null && pref.length > 0 ? pref[0] : _prefApp); } - //################################# - //## Getter for resources - //################################# + // + // Getter for resources + // public String rstr(@StringRes int stringKeyResourceId) { return _context.getString(stringKeyResourceId); } @@ -148,9 +148,9 @@ public class AppSettingsBase implements PropertyBackend } - //################################# - //## Getter & Setter for String - //################################# + // + // Getter & Setter for String + // public void setString(@StringRes int keyResourceId, String value, final SharedPreferences... pref) { gp(pref).edit().putString(rstr(keyResourceId), value).apply(); } @@ -235,9 +235,9 @@ public class AppSettingsBase implements PropertyBackend return getStringListOne(key, gp(pref)); } - //################################# - //## Getter & Setter for integer - //################################# + // + // Getter & Setter for integer + // public void setInt(@StringRes int keyResourceId, int value, final SharedPreferences... pref) { gp(pref).edit().putInt(rstr(keyResourceId), value).apply(); } @@ -319,9 +319,9 @@ public class AppSettingsBase implements PropertyBackend } - //################################# - //## Getter & Setter for Long - //################################# + // + // Getter & Setter for Long + // public void setLong(@StringRes int keyResourceId, long value, final SharedPreferences... pref) { gp(pref).edit().putLong(rstr(keyResourceId), value).apply(); } @@ -338,9 +338,9 @@ public class AppSettingsBase implements PropertyBackend return gp(pref).getLong(key, defaultValue); } - //################################# - //## Getter & Setter for Float - //################################# + // + // Getter & Setter for Float + // public void setFloat(@StringRes int keyResourceId, float value, final SharedPreferences... pref) { gp(pref).edit().putFloat(rstr(keyResourceId), value).apply(); } @@ -357,9 +357,9 @@ public class AppSettingsBase implements PropertyBackend return gp(pref).getFloat(key, defaultValue); } - //################################# - //## Getter & Setter for Double - //################################# + // + // Getter & Setter for Double + // public void setDouble(@StringRes int keyResourceId, double value, final SharedPreferences... pref) { setLong(rstr(keyResourceId), Double.doubleToRawLongBits(value)); } @@ -376,9 +376,9 @@ public class AppSettingsBase implements PropertyBackend return Double.longBitsToDouble(getLong(key, Double.doubleToRawLongBits(defaultValue), gp(pref))); } - //################################# - //## Getter & Setter for boolean - //################################# + // + // Getter & Setter for boolean + // public void setBool(@StringRes int keyResourceId, boolean value, final SharedPreferences... pref) { gp(pref).edit().putBoolean(rstr(keyResourceId), value).apply(); } @@ -395,9 +395,9 @@ public class AppSettingsBase implements PropertyBackend return gp(pref).getBoolean(key, defaultValue); } - //################################# - //## Getter & Setter for Color - //################################# + // + // Getter & Setter for Color + // public int getColor(String key, @ColorRes int defaultColor, final SharedPreferences... pref) { return gp(pref).getInt(key, rcolor(defaultColor)); } @@ -450,49 +450,49 @@ public class AppSettingsBase implements PropertyBackend } @Override - public AppSettingsBase setString(String key, String value) { + public SharedPreferencesPropertyBackend setString(String key, String value) { setString(key, value, _prefApp); return this; } @Override - public AppSettingsBase setInt(String key, int value) { + public SharedPreferencesPropertyBackend setInt(String key, int value) { setInt(key, value, _prefApp); return this; } @Override - public AppSettingsBase setLong(String key, long value) { + public SharedPreferencesPropertyBackend setLong(String key, long value) { setLong(key, value, _prefApp); return this; } @Override - public AppSettingsBase setBool(String key, boolean value) { + public SharedPreferencesPropertyBackend setBool(String key, boolean value) { setBool(key, value, _prefApp); return this; } @Override - public AppSettingsBase setFloat(String key, float value) { + public SharedPreferencesPropertyBackend setFloat(String key, float value) { setFloat(key, value, _prefApp); return this; } @Override - public AppSettingsBase setDouble(String key, double value) { + public SharedPreferencesPropertyBackend setDouble(String key, double value) { setDouble(key, value, _prefApp); return this; } @Override - public AppSettingsBase setIntList(String key, List value) { + public SharedPreferencesPropertyBackend setIntList(String key, List value) { setIntListOne(key, value, _prefApp); return this; } @Override - public AppSettingsBase setStringList(String key, List value) { + public SharedPreferencesPropertyBackend setStringList(String key, List value) { setStringListOne(key, value, _prefApp); return this; } diff --git a/app/src/main/java/net/gsantner/opoc/util/ContextUtils.java b/app/src/main/java/net/gsantner/opoc/util/ContextUtils.java index 79cc1686..68c0c4d7 100644 --- a/app/src/main/java/net/gsantner/opoc/util/ContextUtils.java +++ b/app/src/main/java/net/gsantner/opoc/util/ContextUtils.java @@ -14,7 +14,6 @@ import android.annotation.SuppressLint; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.ActivityNotFoundException; -import android.content.ClipData; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; @@ -28,6 +27,7 @@ import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Rect; +import android.graphics.drawable.AdaptiveIconDrawable; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.VectorDrawable; @@ -65,8 +65,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; import java.util.Locale; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; @@ -74,9 +72,9 @@ import static android.graphics.Bitmap.CompressFormat; @SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue", "ObsoleteSdkInt", "deprecation", "SpellCheckingInspection"}) public class ContextUtils { - //######################## - //## Members, Constructors - //######################## + // + // Members, Constructors + // protected Context _context; public ContextUtils(Context context) { @@ -87,57 +85,81 @@ public class ContextUtils { return _context; } - //######################## - //## Resources - //######################## - static class ResType { - public static final String DRAWABLE = "drawable"; - public static final String STRING = "string"; - public static final String PLURAL = "plural"; - public static final String COLOR = "color"; - public static final String STYLE = "style"; - public static final String ARRAY = "array"; - public static final String DIMEN = "dimen"; - public static final String MENU = "menu"; - public static final String BOOL = "bool"; - public static final String RAW = "raw"; + + // + // Class Methods + // + public enum ResType { + ID, BOOL, INTEGER, COLOR, STRING, ARRAY, DRAWABLE, PLURALS, + ANIM, ATTR, DIMEN, LAYOUT, MENU, RAW, STYLE, XML, } + /** + * Find out the nuermical ressource id by given {@link ResType} + * + * @return A valid id if the id could be found, else 0 + */ + public int getResId(ResType resType, final String name) { + return _context.getResources().getIdentifier(name, resType.name().toLowerCase(), _context.getPackageName()); + } + + /** + * Get String by given string ressource id (nuermic) + */ public String rstr(@StringRes int strResId) { return _context.getString(strResId); } + /** + * Get String by given string ressource identifier (textual) + */ public String rstr(String strResKey) { - return rstr(getResId(ResType.STRING, strResKey)); + try { + return rstr(getResId(ResType.STRING, strResKey)); + } catch (Resources.NotFoundException e) { + return null; + } } + /** + * Get drawable from given ressource identifier + */ public Drawable rdrawable(@DrawableRes int resId) { return ContextCompat.getDrawable(_context, resId); } + /** + * Get color by given color ressource id + */ public int rcolor(@ColorRes int resId) { return ContextCompat.getColor(_context, resId); } - public int getResId(final String type, final String name) { - return _context.getResources().getIdentifier(name, type, _context.getPackageName()); - } - - public boolean areResIdsAvailable(final String type, final String... names) { - for (String name : names) { - if (getResId(type, name) == 0) { + /** + * Checks if all given (textual) ressource ids are available + * + * @param resType A {@link ResType} + * @param resIdsTextual A (textual) identifier to be awaited at R.restype.resIdsTextual + * @return True if all given ids are available + */ + public boolean areRessourcesAvailable(final ResType resType, final String... resIdsTextual) { + for (String name : resIdsTextual) { + if (getResId(resType, name) == 0) { return false; } } return true; } - //######################## - //## Methods - //######################## - - public String colorToHexString(int intColor) { - return String.format("#%06X", 0xFFFFFF & intColor); + /** + * Convert an int color to a hex string. Optionally including alpha value. + * + * @param intColor The color coded in int + * @param withAlpha Optional; Set first bool parameter to true to also include alpha value + */ + public String colorToHexString(int intColor, boolean... withAlpha) { + boolean a = withAlpha != null && withAlpha.length >= 1 && withAlpha[0]; + return String.format(a ? "#%08X" : "#%06X", (a ? 0xFFFFFFFF : 0xFFFFFF) & intColor); } public String getAppVersionName() { @@ -151,6 +173,10 @@ public class ContextUtils { } } + /** + * Send a {@link Intent#ACTION_VIEW} Intent with given paramter + * If the parameter is an string a browser will get triggered + */ public void openWebpageInExternalBrowser(final String url) { Uri uri = Uri.parse(url); Intent intent = new Intent(Intent.ACTION_VIEW, uri); @@ -171,13 +197,8 @@ public class ContextUtils { * Falls back to applicationId of the app which may differ from manifest. */ public Object getBuildConfigValue(String fieldName) { - String pkg; - try { - pkg = rstr("manifest_package_id"); - } catch (Resources.NotFoundException ex) { - pkg = _context.getPackageName(); - } - pkg += ".BuildConfig"; + String pkg = rstr("manifest_package_id"); + pkg = (pkg != null ? pkg : _context.getPackageName()) + ".BuildConfig"; try { Class c = Class.forName(pkg); return c.getField(fieldName).get(null); @@ -187,7 +208,10 @@ public class ContextUtils { } } - public boolean bcbool(String fieldName, boolean defaultValue) { + /** + * Get a BuildConfig bool value + */ + public Boolean bcbool(String fieldName, Boolean defaultValue) { Object field = getBuildConfigValue(fieldName); if (field != null && field instanceof Boolean) { return (Boolean) field; @@ -195,6 +219,9 @@ public class ContextUtils { return defaultValue; } + /** + * Get a BuildConfig string value + */ public String bcstr(String fieldName, String defaultValue) { Object field = getBuildConfigValue(fieldName); if (field != null && field instanceof String) { @@ -203,27 +230,36 @@ public class ContextUtils { return defaultValue; } + /** + * Check if this is a gplay build (requires BuildConfig field) + */ public boolean isGooglePlayBuild() { return bcbool("IS_GPLAY_BUILD", true); } + /** + * Check if this is a foss build (requires BuildConfig field) + */ public boolean isFossBuild() { return bcbool("IS_FOSS_BUILD", false); } - // Requires donate__bitcoin_* resources (see below) to be available as string resource - public void showDonateBitcoinRequest(@StringRes final int strResBitcoinId, @StringRes final int strResBitcoinAmount, @StringRes final int strResBitcoinMessage, @StringRes final int strResAlternativeDonateUrl) { + /** + * Request a bitcoin donation with given details. + * All parameters are awaited as string resource ids + */ + public void showDonateBitcoinRequest(@StringRes final int srBitcoinId, @StringRes final int srBitcoinAmount, @StringRes final int srBitcoinMessage, @StringRes final int srAlternativeDonateUrl) { if (!isGooglePlayBuild()) { String btcUri = String.format("bitcoin:%s?amount=%s&label=%s&message=%s", - rstr(strResBitcoinId), rstr(strResBitcoinAmount), - rstr(strResBitcoinMessage), rstr(strResBitcoinMessage)); + rstr(srBitcoinId), rstr(srBitcoinAmount), + rstr(srBitcoinMessage), rstr(srBitcoinMessage)); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(btcUri)); intent.addFlags(FLAG_ACTIVITY_NEW_TASK); try { _context.startActivity(intent); } catch (ActivityNotFoundException e) { - openWebpageInExternalBrowser(rstr(strResAlternativeDonateUrl)); + openWebpageInExternalBrowser(rstr(srAlternativeDonateUrl)); } } } @@ -272,6 +308,9 @@ public class ContextUtils { } } + /** + * Check if app with given {@code packageName} is installed + */ public boolean isAppInstalled(String packageName) { PackageManager pm = _context.getApplicationContext().getPackageManager(); try { @@ -282,6 +321,9 @@ public class ContextUtils { } } + /** + * Restart the current app. Supply the class to start on startup + */ public void restartApp(Class classToStart) { Intent inte = new Intent(_context, classToStart); PendingIntent inteP = PendingIntent.getActivity(_context, 555, inte, PendingIntent.FLAG_CANCEL_CURRENT); @@ -295,6 +337,10 @@ public class ContextUtils { Runtime.getRuntime().exit(0); } + /** + * Load a markdown file from a {@link RawRes}, prepend each line with {@code prepend} text + * and convert markdown to html using {@link SimpleMarkdownParser} + */ public String loadMarkdownForTextViewFromRaw(@RawRes int rawMdFile, String prepend) { try { return new SimpleMarkdownParser() @@ -308,52 +354,74 @@ public class ContextUtils { } } + /** + * Load html into a {@link Spanned} object and set the + * {@link TextView}'s text using {@link TextView#setText(CharSequence)} + */ public void setHtmlToTextView(TextView textView, String html) { textView.setMovementMethod(LinkMovementMethod.getInstance()); textView.setText(new SpannableString(htmlToSpanned(html))); } + /** + * Estimate this device's screen diagonal size in inches + */ public double getEstimatedScreenSizeInches() { DisplayMetrics dm = _context.getResources().getDisplayMetrics(); - double density = dm.density * 160; - double x = Math.pow(dm.widthPixels / density, 2); - double y = Math.pow(dm.heightPixels / density, 2); - double screenInches = Math.sqrt(x + y) * 1.16; // 1.16 = est. Nav/Statusbar - screenInches = screenInches < 4.0 ? 4.0 : screenInches; - screenInches = screenInches > 12.0 ? 12.0 : screenInches; - return screenInches; + double calc = dm.density * 160d; + double x = Math.pow(dm.widthPixels / calc, 2); + double y = Math.pow(dm.heightPixels / calc, 2); + calc = Math.sqrt(x + y) * 1.16; // 1.16 = est. Nav/Statusbar + return Math.min(12, Math.max(4, calc)); } + /** + * Check if the device is currently in portrait orientation + */ public boolean isInPortraitMode() { return _context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; } - public Locale getLocaleByAndroidCode(String code) { - if (!TextUtils.isEmpty(code)) { - return code.contains("-r") - ? new Locale(code.substring(0, 2), code.substring(4, 6)) // de-rAt - : new Locale(code); // de + /** + * Get an {@link Locale} out of a android language code + * The {@code androidLC} may be in any of the forms: de, en, de-rAt + */ + public Locale getLocaleByAndroidCode(String androidLC) { + if (!TextUtils.isEmpty(androidLC)) { + return androidLC.contains("-r") + ? new Locale(androidLC.substring(0, 2), androidLC.substring(4, 6)) // de-rAt + : new Locale(androidLC); // de } return Resources.getSystem().getConfiguration().locale; } - // en/de/de-rAt ; Empty string -> default locale - public void setAppLanguage(String androidLocaleString) { - Locale locale = getLocaleByAndroidCode(androidLocaleString); + /** + * Set the apps language + * {@code androidLC} may be in any of the forms: en, de, de-rAt + * If given an empty string, the default (system) locale gets loaded + */ + public void setAppLanguage(String androidLC) { + Locale locale = getLocaleByAndroidCode(androidLC); Configuration config = _context.getResources().getConfiguration(); - config.locale = (locale != null && !androidLocaleString.isEmpty()) + config.locale = (locale != null && !androidLC.isEmpty()) ? locale : Resources.getSystem().getConfiguration().locale; _context.getResources().updateConfiguration(config, null); } - // Find out if color above the given color should be light or dark. true if light + /** + * Try to guess if the color on top of the given {@code colorOnBottomInt} + * should be light or dark. Returns true if top color should be light + */ public boolean shouldColorOnTopBeLight(@ColorInt int colorOnBottomInt) { return 186 > (((0.299 * Color.red(colorOnBottomInt)) + ((0.587 * Color.green(colorOnBottomInt)) + (0.114 * Color.blue(colorOnBottomInt))))); } + /** + * Convert a html string to an android {@link Spanned} object + */ public Spanned htmlToSpanned(String html) { Spanned result; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { @@ -364,61 +432,34 @@ public class ContextUtils { return result; } - public boolean setClipboard(String text) { - if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) { - android.text.ClipboardManager cm = ((android.text.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE)); - if (cm != null) { - cm.setText(text); - return true; - } - } else { - android.content.ClipboardManager cm = ((android.content.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE)); - if (cm != null) { - ClipData clip = ClipData.newPlainText(_context.getPackageName(), text); - cm.setPrimaryClip(clip); - return true; - } - } - return false; - } - - public List getClipboard() { - List clipper = new ArrayList<>(); - if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) { - android.text.ClipboardManager cm = ((android.text.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE)); - if (cm != null) { - clipper.add(cm.getText().toString()); - } - - } else { - android.content.ClipboardManager cm = ((android.content.ClipboardManager) _context.getSystemService(Context.CLIPBOARD_SERVICE)); - if (cm != null && cm.hasPrimaryClip()) { - ClipData data = cm.getPrimaryClip(); - for (int i = 0; i < data.getItemCount() && i < data.getItemCount(); i++) { - clipper.add(data.getItemAt(i).getText().toString()); - } - } - - } - return clipper; - } - + /** + * Convert pixel unit do android dp unit + */ public float convertPxToDp(final float px) { return px / _context.getResources().getDisplayMetrics().density; } + /** + * Convert android dp unit to pixel unit + */ public float convertDpToPx(final float dp) { return dp * _context.getResources().getDisplayMetrics().density; } + /** + * Load an image into a {@link ImageView} and apply a color filter + */ public static void setDrawableWithColorToImageView(ImageView imageView, @DrawableRes int drawableResId, @ColorRes int colorResId) { imageView.setImageResource(drawableResId); imageView.setColorFilter(ContextCompat.getColor(imageView.getContext(), colorResId)); } + /** + * Get a {@link Bitmap} out of a {@link Drawable} + */ public Bitmap drawableToBitmap(Drawable drawable) { Bitmap bitmap = null; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && (drawable instanceof VectorDrawable || drawable instanceof VectorDrawableCompat)) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && (drawable instanceof VectorDrawable || drawable instanceof VectorDrawableCompat || drawable instanceof AdaptiveIconDrawable)) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { drawable = (DrawableCompat.wrap(drawable)).mutate(); } @@ -434,6 +475,18 @@ public class ContextUtils { return bitmap; } + /** + * Get a {@link Bitmap} out of a {@link DrawableRes} + */ + public Bitmap drawableToBitmap(@DrawableRes int drawableId) { + return drawableToBitmap(ContextCompat.getDrawable(_context, drawableId)); + } + + /** + * Get a {@link Bitmap} from a given {@code imagePath} on the filesystem + * Specifying a {@code maxDimen} is also possible and a value below 2000 + * is recommended, otherwise a {@link OutOfMemoryError} may occur + */ public Bitmap loadImageFromFilesystem(File imagePath, int maxDimen) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; @@ -462,6 +515,10 @@ public class ContextUtils { return inSampleSize; } + /** + * Scale the bitmap so both dimensions are lower or equal to {@code maxDimen} + * This keeps the aspect ratio + */ public Bitmap scaleBitmap(Bitmap bitmap, int maxDimen) { int picSize = Math.min(bitmap.getHeight(), bitmap.getWidth()); float scale = 1.f * maxDimen / picSize; @@ -470,12 +527,15 @@ public class ContextUtils { return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); } + /** + * Write the given {@link Bitmap} to {@code imageFile}, in {@link CompressFormat#JPEG} format + */ public boolean writeImageToFileJpeg(File imageFile, Bitmap image) { return writeImageToFile(imageFile, image, Bitmap.CompressFormat.JPEG, 95); } /** - * Write bitmap to the filesystem + * Write the given {@link Bitmap} to filesystem * * @param targetFile The file to be written in * @param image The image as android {@link Bitmap} @@ -517,10 +577,14 @@ public class ContextUtils { return false; } - public Bitmap drawTextOnDrawable(@DrawableRes int resId, String text, int textSize) { + /** + * Draw text in the center of the given {@link DrawableRes} + * This may be useful for e.g. badge counts + */ + public Bitmap drawTextOnDrawable(@DrawableRes int drawableRes, String text, int textSize) { Resources resources = _context.getResources(); float scale = resources.getDisplayMetrics().density; - Bitmap bitmap = bitmapToDrawable(resId); + Bitmap bitmap = drawableToBitmap(drawableRes); bitmap = bitmap.copy(bitmap.getConfig(), true); Canvas canvas = new Canvas(bitmap); @@ -538,24 +602,9 @@ public class ContextUtils { return bitmap; } - public Bitmap bitmapToDrawable(@DrawableRes int drawableId) { - Bitmap bitmap = null; - Drawable drawable = ContextCompat.getDrawable(_context, drawableId); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && (drawable instanceof VectorDrawable || drawable instanceof VectorDrawableCompat)) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { - drawable = (DrawableCompat.wrap(drawable)).mutate(); - } - - bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); - drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); - drawable.draw(canvas); - } else if (drawable instanceof BitmapDrawable) { - bitmap = ((BitmapDrawable) drawable).getBitmap(); - } - return bitmap; - } - + /** + * Try to tint all {@link Menu}s {@link MenuItem}s with given color + */ @SuppressWarnings("ConstantConditions") public void tintMenuItems(Menu menu, boolean recurse, @ColorInt int iconColor) { for (int i = 0; i < menu.size(); i++) { @@ -567,10 +616,16 @@ public class ContextUtils { } } + /** + * Loads {@link Drawable} by given {@link DrawableRes} and applies a color + */ public Drawable tintDrawable(@DrawableRes int drawableRes, @ColorInt int color) { - return tintDrawable(_context.getResources().getDrawable(drawableRes), color); + return tintDrawable(rdrawable(drawableRes), color); } + /** + * Tint a {@link Drawable} with given {@code color} + */ public Drawable tintDrawable(@Nullable Drawable drawable, @ColorInt int color) { if (drawable != null) { drawable = DrawableCompat.wrap(drawable); @@ -579,6 +634,10 @@ public class ContextUtils { return drawable; } + /** + * Try to make icons in Toolbar/ActionBars SubMenus visible + * This may not work on some devices and it maybe won't work on future android updates + */ public void setSubMenuIconsVisiblity(Menu menu, boolean visible) { if (menu.getClass().getSimpleName().equals("MenuBuilder")) { try { From a88dc5d13ca8aa1a6d92b6bd9b26a8350670710a Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Fri, 30 Mar 2018 00:24:52 +0200 Subject: [PATCH 05/19] . --- .../activity/MainActivity.java | 24 +++++++++---------- .../ui/theme/ThemedFragment.java | 7 ++++++ .../opoc/activity}/CustomFragment.java | 8 ++----- 3 files changed, 21 insertions(+), 18 deletions(-) rename app/src/main/java/{com/github/dfa/diaspora_android/ui/theme => net/gsantner/opoc/activity}/CustomFragment.java (88%) 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 348643db..f0ea1d11 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 @@ -71,10 +71,10 @@ 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.PodSelectionDialog; -import com.github.dfa.diaspora_android.ui.theme.CustomFragment; import com.github.dfa.diaspora_android.ui.theme.ThemeHelper; import com.github.dfa.diaspora_android.ui.theme.ThemedActivity; import com.github.dfa.diaspora_android.ui.theme.ThemedAlertDialogBuilder; +import com.github.dfa.diaspora_android.ui.theme.ThemedFragment; import com.github.dfa.diaspora_android.util.ActivityUtils; import com.github.dfa.diaspora_android.util.AndroidBug5497Workaround; import com.github.dfa.diaspora_android.util.AppLog; @@ -199,7 +199,7 @@ public class MainActivity extends ThemedActivity brOpenExternalLink = new OpenExternalLinkReceiver(this); brSetTitle = new UpdateTitleReceiver(app, urls, new UpdateTitleReceiver.TitleCallback() { public void setTitle(String url, int resId) { - CustomFragment top = getTopFragment(); + ThemedFragment top = getTopFragment(); if (top != null && top.getFragmentTag().equals(DiasporaStreamFragment.TAG)) { MainActivity.this.setTitle(resId); showLastVisitedTimestampMessageIfNeeded(url); @@ -207,7 +207,7 @@ public class MainActivity extends ThemedActivity } public void setTitle(String url, String title) { - CustomFragment top = getTopFragment(); + ThemedFragment top = getTopFragment(); if (top != null && top.getFragmentTag().equals(DiasporaStreamFragment.TAG)) { MainActivity.this.setTitle(title); } @@ -292,15 +292,15 @@ public class MainActivity extends ThemedActivity } /** - * Get an instance of the CustomFragment with the tag fragmentTag. + * Get an instance of the ThemedFragment 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 the top fragment. * * @param fragmentTag tag * @return corresponding Fragment */ - protected CustomFragment getFragment(String fragmentTag) { - CustomFragment fragment = (CustomFragment) fm.findFragmentByTag(fragmentTag); + protected ThemedFragment getFragment(String fragmentTag) { + ThemedFragment fragment = (ThemedFragment) fm.findFragmentByTag(fragmentTag); if (fragment != null) { return fragment; } else { @@ -358,9 +358,9 @@ public class MainActivity extends ThemedActivity * * @param fragment Fragment to show */ - protected void showFragment(CustomFragment fragment) { + protected void showFragment(ThemedFragment fragment) { AppLog.v(this, "showFragment()"); - CustomFragment currentTop = (CustomFragment) fm.findFragmentById(R.id.fragment_container); + ThemedFragment currentTop = (ThemedFragment) fm.findFragmentById(R.id.fragment_container); if (currentTop == null || !currentTop.getFragmentTag().equals(fragment.getFragmentTag())) { AppLog.v(this, "Fragment was not visible. Replace it."); fm.beginTransaction().addToBackStack(null).replace(R.id.fragment_container, fragment, fragment.getFragmentTag()).commit(); @@ -591,8 +591,8 @@ public class MainActivity extends ThemedActivity * * @return top fragment or null if there is none displayed */ - private CustomFragment getTopFragment() { - return (CustomFragment) fm.findFragmentById(R.id.fragment_container); + private ThemedFragment getTopFragment() { + return (ThemedFragment) fm.findFragmentById(R.id.fragment_container); } /** @@ -605,7 +605,7 @@ public class MainActivity extends ThemedActivity navDrawer.closeDrawer(navView); return; } - CustomFragment top = getTopFragment(); + ThemedFragment top = getTopFragment(); if (top != null) { AppLog.v(this, "Top Fragment is not null"); if (!top.onBackPressed()) { @@ -683,7 +683,7 @@ public class MainActivity extends ThemedActivity //Clear the menus menu.clear(); - CustomFragment top = getTopFragment(); + ThemedFragment top = getTopFragment(); if (top != null) { if (!top.getFragmentTag().equals(PodSelectionFragment.TAG)) { cache = _appSettings.isExtendedNotificationsActivated(); diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedFragment.java index b68da449..6bda3814 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedFragment.java @@ -21,6 +21,8 @@ package com.github.dfa.diaspora_android.ui.theme; import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.util.AppSettings; +import net.gsantner.opoc.activity.CustomFragment; + /** * Fragment that supports color schemes * Created by vanitas on 06.10.16. @@ -39,4 +41,9 @@ public abstract class ThemedFragment extends CustomFragment { ThemeHelper.getInstance(getAppSettings()); applyColorToViews(); } + + + public boolean isAllowedIntellihide() { + return true; + } } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/CustomFragment.java b/app/src/main/java/net/gsantner/opoc/activity/CustomFragment.java similarity index 88% rename from app/src/main/java/com/github/dfa/diaspora_android/ui/theme/CustomFragment.java rename to app/src/main/java/net/gsantner/opoc/activity/CustomFragment.java index 82dcf93c..e6d50c75 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/CustomFragment.java +++ b/app/src/main/java/net/gsantner/opoc/activity/CustomFragment.java @@ -16,7 +16,7 @@ If not, see . */ -package com.github.dfa.diaspora_android.ui.theme; +package net.gsantner.opoc.activity; import android.os.Bundle; import android.support.v4.app.Fragment; @@ -28,7 +28,7 @@ import android.support.v4.app.Fragment; public abstract class CustomFragment extends Fragment { - public static final String TAG = "com.github.dfa.diaspora_android.ui.theme.CustomFragment"; + public static final String TAG = "net.gsantner.opoc.activity.CustomFragment"; /** * We have an optionsMenu @@ -55,9 +55,5 @@ public abstract class CustomFragment extends Fragment { * @return did we react to the back press? */ public abstract boolean onBackPressed(); - - public boolean isAllowedIntellihide() { - return true; - } } From 08242760bbf95d5f081d9fe238a1327b79fb1c77 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Fri, 30 Mar 2018 00:38:31 +0200 Subject: [PATCH 06/19] Migrate to opoc/basefragment; Fix redundant casts --- .../activity/AboutActivity.java | 28 ++-- .../activity/AspectListFragment.java | 8 +- .../activity/MainActivity.java | 2 +- .../activity/PodSelectionFragment.java | 10 +- .../activity/SettingsActivity.java | 8 +- .../activity/TagListFragment.java | 5 +- .../ui/theme/ThemedCheckBoxPreference.java | 2 +- .../ui/theme/ThemedColorPickerPreference.java | 2 +- .../ui/theme/ThemedFragment.java | 4 +- .../ui/theme/ThemedPreferenceCategory.java | 2 +- .../ui/theme/ThemedVisibilityPreference.java | 2 +- .../util/AndroidBug5497Workaround.java | 2 +- .../diaspora_android/web/BrowserFragment.java | 22 +-- .../opoc/activity/CustomFragment.java | 59 -------- .../opoc/activity/GsFragmentBase.java | 129 ++++++++++++++++++ 15 files changed, 176 insertions(+), 109 deletions(-) delete mode 100644 app/src/main/java/net/gsantner/opoc/activity/CustomFragment.java create mode 100644 app/src/main/java/net/gsantner/opoc/activity/GsFragmentBase.java 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 03fb1155..f587f1bd 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 @@ -26,6 +26,8 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.design.widget.AppBarLayout; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; @@ -157,10 +159,14 @@ public class AboutActivity extends ThemedActivity } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.about__fragment_about, container, false); - ButterKnife.bind(this, rootView); + protected int getLayoutResId() { + return R.layout.about__fragment_about; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + ButterKnife.bind(this, view); if (isAdded()) { try { PackageInfo pInfo = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0); @@ -170,7 +176,6 @@ public class AboutActivity extends ThemedActivity e.printStackTrace(); } } - return rootView; } @Override @@ -244,10 +249,14 @@ public class AboutActivity extends ThemedActivity } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.about__fragment_license, container, false); - ButterKnife.bind(this, rootView); - final Context context = rootView.getContext(); + protected int getLayoutResId() { + return R.layout.about__fragment_license; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + ButterKnife.bind(this, view); accentColor = ContextUtils.get().colorToHexString(ThemeHelper.getAccentColor()); maintainers.setTextFormatted(getString(R.string.fragment_license__maintainers_text, @@ -256,7 +265,6 @@ public class AboutActivity extends ThemedActivity ContextUtils.get().loadMarkdownForTextViewFromRaw(R.raw.contributors, ""))); thirdPartyLibs.setTextFormatted( ContextUtils.get().loadMarkdownForTextViewFromRaw(R.raw.license_third_party, "")); - return rootView; } @OnClick({R.id.fragment_license__leafpic_button, R.id.fragment_license__license_button}) diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/AspectListFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/AspectListFragment.java index 9da6a6de..6884974f 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/AspectListFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/AspectListFragment.java @@ -22,6 +22,7 @@ import android.content.Context; import android.graphics.Color; import android.graphics.PorterDuff; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v7.widget.AppCompatImageView; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; @@ -68,13 +69,12 @@ public class AspectListFragment extends ThemedFragment implements OnSomethingCli protected DiasporaUrlHelper urls; @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - AppLog.d(this, "onCreateView()"); - return inflater.inflate(R.layout.recycler_list__fragment, container, false); + protected int getLayoutResId() { + return R.layout.recycler_list__fragment; } @Override - public void onViewCreated(View view, Bundle savedInstanceState) { + public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ButterKnife.bind(this, view); app = (App) getActivity().getApplication(); 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 f0ea1d11..b15e1dc4 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 @@ -835,7 +835,7 @@ public class MainActivity extends ThemedActivity final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); @SuppressLint("InflateParams") 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 EditText input = layout.findViewById(R.id.dialog_search__input); input.setMaxLines(1); input.setSingleLine(true); ThemeHelper.updateEditTextColor(input); diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionFragment.java index 9207beea..59908a59 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionFragment.java @@ -92,16 +92,14 @@ public class PodSelectionFragment extends ThemedFragment implements SearchView.O private String filterString = ""; @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - AppLog.d(this, "onCreateView()"); - View view = inflater.inflate(R.layout.podselection__fragment, container, false); - ButterKnife.bind(this, view); - return view; + protected int getLayoutResId() { + return R.layout.podselection__fragment; } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + ButterKnife.bind(this, view); app = (App) getActivity().getApplication(); appSettings = app.getSettings(); @@ -204,7 +202,7 @@ public class PodSelectionFragment extends ThemedFragment implements SearchView.O @Override public View getView(int position, View convertView, ViewGroup parent) { View view = super.getView(position, convertView, parent); - TextView textView = (TextView) view.findViewById(android.R.id.text1); + TextView textView = view.findViewById(android.R.id.text1); textView.setTextColor(appSettings.isAmoledColorMode() ? Color.GRAY : Color.BLACK); return view; } 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 de5cae55..943dbfcc 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 @@ -305,10 +305,10 @@ public class SettingsActivity extends ThemedActivity implements SharedPreference final ThemedAlertDialogBuilder builder = new ThemedAlertDialogBuilder(context, appSettings); builder.setView(dialogLayout); - final FrameLayout titleBackground = (FrameLayout) dialogLayout.findViewById(R.id.color_picker_dialog__title_background); - final TextView title = (TextView) dialogLayout.findViewById(R.id.color_picker_dialog__title); - final LineColorPicker base = (LineColorPicker) dialogLayout.findViewById(R.id.color_picker_dialog__base_picker); - final LineColorPicker shade = (LineColorPicker) dialogLayout.findViewById(R.id.color_picker_dialog__shade_picker); + final FrameLayout titleBackground = dialogLayout.findViewById(R.id.color_picker_dialog__title_background); + final TextView title = dialogLayout.findViewById(R.id.color_picker_dialog__title); + final LineColorPicker base = dialogLayout.findViewById(R.id.color_picker_dialog__base_picker); + final LineColorPicker shade = dialogLayout.findViewById(R.id.color_picker_dialog__shade_picker); title.setText(type == 1 ? R.string.pref_title__primary_color : R.string.pref_title__accent_color); title.setTextColor(getResources().getColor(R.color.white)); diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/TagListFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/TagListFragment.java index 7e6cb353..576fb1b1 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/TagListFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/TagListFragment.java @@ -67,9 +67,8 @@ public class TagListFragment extends ThemedFragment implements OnSomethingClickL protected DiasporaUrlHelper urls; @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - AppLog.d(this, "onCreateView()"); - return inflater.inflate(R.layout.recycler_list__fragment, container, false); + protected int getLayoutResId() { + return R.layout.recycler_list__fragment; } @Override diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedCheckBoxPreference.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedCheckBoxPreference.java index ed4f1400..0c829342 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedCheckBoxPreference.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedCheckBoxPreference.java @@ -41,7 +41,7 @@ public class ThemedCheckBoxPreference extends CheckBoxPreference implements Them @Override public void setColors() { - CheckBox checkBox = (CheckBox) rootLayout.findViewById(android.R.id.checkbox); + CheckBox checkBox = rootLayout.findViewById(android.R.id.checkbox); ThemeHelper.getInstance(AppSettings.get()); ThemeHelper.updateCheckBoxColor(checkBox); } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedColorPickerPreference.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedColorPickerPreference.java index 524c1b65..c335d929 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedColorPickerPreference.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedColorPickerPreference.java @@ -38,7 +38,7 @@ public class ThemedColorPickerPreference extends Preference implements Themeable @Override protected void onBindView(View view) { super.onBindView(view); - colorPreview = (ImageView) view.findViewById(android.R.id.icon); + colorPreview = view.findViewById(android.R.id.icon); setColors(); } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedFragment.java index 6bda3814..6158a4a9 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedFragment.java @@ -21,14 +21,14 @@ package com.github.dfa.diaspora_android.ui.theme; import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.util.AppSettings; -import net.gsantner.opoc.activity.CustomFragment; +import net.gsantner.opoc.activity.GsFragmentBase; /** * Fragment that supports color schemes * Created by vanitas on 06.10.16. */ -public abstract class ThemedFragment extends CustomFragment { +public abstract class ThemedFragment extends GsFragmentBase { protected AppSettings getAppSettings() { return ((App) getActivity().getApplication()).getSettings(); } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedPreferenceCategory.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedPreferenceCategory.java index 28b97142..5df13fda 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedPreferenceCategory.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedPreferenceCategory.java @@ -36,7 +36,7 @@ public class ThemedPreferenceCategory extends PreferenceCategory implements Them @Override protected View onCreateView(ViewGroup parent) { View rootLayout = super.onCreateView(parent); - this.titleTextView = (TextView) rootLayout.findViewById(android.R.id.title); + this.titleTextView = rootLayout.findViewById(android.R.id.title); setColors(); return rootLayout; } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedVisibilityPreference.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedVisibilityPreference.java index 8e94dac4..6bd8c186 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedVisibilityPreference.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedVisibilityPreference.java @@ -27,7 +27,7 @@ public class ThemedVisibilityPreference extends ThemedCheckBoxPreference { @Override public void setColors() { - CheckBox checkBox = (CheckBox) rootLayout.findViewById(android.R.id.checkbox); + CheckBox checkBox = rootLayout.findViewById(android.R.id.checkbox); checkBox.setButtonDrawable(R.drawable.ic_visibility_selector); ThemeHelper.getInstance(AppSettings.get()); ThemeHelper.updateCheckBoxColor(checkBox); diff --git a/app/src/main/java/com/github/dfa/diaspora_android/util/AndroidBug5497Workaround.java b/app/src/main/java/com/github/dfa/diaspora_android/util/AndroidBug5497Workaround.java index 4a9afbda..98017bde 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/util/AndroidBug5497Workaround.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/util/AndroidBug5497Workaround.java @@ -22,7 +22,7 @@ public class AndroidBug5497Workaround { private FrameLayout.LayoutParams frameLayoutParams; private AndroidBug5497Workaround(Activity activity) { - FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); + FrameLayout content = activity.findViewById(android.R.id.content); mChildOfContent = content.getChildAt(0); mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { public void onGlobalLayout() { diff --git a/app/src/main/java/com/github/dfa/diaspora_android/web/BrowserFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/web/BrowserFragment.java index 98b5c186..14478c07 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/web/BrowserFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/web/BrowserFragment.java @@ -64,7 +64,6 @@ import java.util.Locale; public class BrowserFragment extends ThemedFragment { public static final String TAG = "com.github.dfa.diaspora_android.BrowserFragment"; - protected View rootLayout; protected ContextMenuWebView webView; protected ProgressBar progressBar; protected AppSettings appSettings; @@ -74,18 +73,11 @@ public class BrowserFragment extends ThemedFragment { protected String pendingUrl; @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - AppLog.d(this, "onCreateView()"); - if (rootLayout == null) { - LayoutInflater inflater1 = inflater.cloneInContext(new MutableContextWrapper(getContext())); - rootLayout = inflater1.inflate(R.layout.browser__fragment, container, false); - } else { - MutableContextWrapper context = (MutableContextWrapper) rootLayout.getContext(); - context.setBaseContext(getContext()); - } - return rootLayout; + protected int getLayoutResId() { + return R.layout.browser__fragment; } + @Override public void onViewCreated(View view, Bundle savedInstanceState) { AppLog.d(this, "onViewCreated()"); @@ -96,7 +88,7 @@ public class BrowserFragment extends ThemedFragment { } if (this.webView == null) { - this.webView = (ContextMenuWebView) view.findViewById(R.id.webView); + this.webView = view.findViewById(R.id.webView); getActivity().runOnUiThread(new Runnable() { @Override public void run() { @@ -108,7 +100,7 @@ public class BrowserFragment extends ThemedFragment { } if (this.progressBar == null) { - this.progressBar = (ProgressBar) view.findViewById(R.id.progressBar); + this.progressBar = view.findViewById(R.id.progressBar); } if (pendingUrl != null) { @@ -125,8 +117,8 @@ public class BrowserFragment extends ThemedFragment { public void onDestroyView() { super.onDestroyView(); - if (getRetainInstance() && rootLayout.getParent() instanceof ViewGroup) { - ((ViewGroup) rootLayout.getParent()).removeView(rootLayout); + if (getRetainInstance() && getView() != null && getView().getParent() instanceof ViewGroup) { + ((ViewGroup) getView().getParent()).removeView(getView()); } } diff --git a/app/src/main/java/net/gsantner/opoc/activity/CustomFragment.java b/app/src/main/java/net/gsantner/opoc/activity/CustomFragment.java deleted file mode 100644 index e6d50c75..00000000 --- a/app/src/main/java/net/gsantner/opoc/activity/CustomFragment.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - This file is part of the dandelion*. - - dandelion* 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. - - dandelion* 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 dandelion*. - - If not, see . - */ -package net.gsantner.opoc.activity; - -import android.os.Bundle; -import android.support.v4.app.Fragment; - -/** - * Customized abstract Fragment class with some useful methods - * Created by vanitas on 21.09.16. - */ - -public abstract class CustomFragment extends Fragment { - - public static final String TAG = "net.gsantner.opoc.activity.CustomFragment"; - - /** - * 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 - */ - public abstract String getFragmentTag(); - - /** - * 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/net/gsantner/opoc/activity/GsFragmentBase.java b/app/src/main/java/net/gsantner/opoc/activity/GsFragmentBase.java new file mode 100644 index 00000000..93019ce9 --- /dev/null +++ b/app/src/main/java/net/gsantner/opoc/activity/GsFragmentBase.java @@ -0,0 +1,129 @@ +/*####################################################### + * + * Maintained by Gregor Santner, 2017- + * https://gsantner.net/ + * + * License: Apache 2.0 + * https://github.com/gsantner/opoc/#licensing + * https://www.apache.org/licenses/LICENSE-2.0 + * +#########################################################*/ +package net.gsantner.opoc.activity; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.LayoutRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import net.gsantner.opoc.util.ContextUtils; + +import butterknife.ButterKnife; + +/** + * A common base fragment to extend from + */ +public abstract class GsFragmentBase extends Fragment { + private boolean _fragmentFirstTimeVisible = true; + private final Object _fragmentFirstTimeVisibleSync = new Object(); + + protected ContextUtils _cu; + protected Bundle _savedInstanceState = null; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + /** + * Inflate the fragments layout. Don't override this method, just supply the needed + * {@link LayoutRes} via abstract method {@link #getLayoutResId()}, super does the rest + */ + @Deprecated + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + _cu = new ContextUtils(inflater.getContext()); + _cu.setAppLanguage(getAppLanguage()); + _savedInstanceState = savedInstanceState; + View view = inflater.inflate(getLayoutResId(), container, false); + ButterKnife.bind(this, view); + return view; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + view.postDelayed(() -> { + synchronized (_fragmentFirstTimeVisibleSync) { + if (getUserVisibleHint() && isVisible() && _fragmentFirstTimeVisible) { + _fragmentFirstTimeVisible = false; + onFragmentFirstTimeVisible(); + } + } + }, 1); + } + + /** + * Get a tag from the fragment, allows faster distinction + * + * @return This fragments tag + */ + public abstract String getFragmentTag(); + + + /** + * Get the layout to be inflated in the fragment + * + * @return Layout resource id + */ + @LayoutRes + protected abstract int getLayoutResId(); + + /** + * Event to be called when the back button was pressed + * True should be returned when this was handled by the fragment + * and no further handling in the view hierarchy is needed + * + * @return True if back handled by fragment + */ + public boolean onBackPressed() { + return false; + } + + /** + * Set the language to be used in this fragment + * Defaults to resolve the language from sharedpreferences: pref_key__language + * + * @return Empty string for system language, or an android locale code + */ + public String getAppLanguage() { + if (getContext() != null) { + return getContext().getSharedPreferences("app", Context.MODE_PRIVATE) + .getString("pref_key__language", ""); + } + return ""; + } + + /** + * This will be called when this fragment gets the first time visible + */ + public void onFragmentFirstTimeVisible() { + } + + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + synchronized (_fragmentFirstTimeVisibleSync) { + if (isVisibleToUser && _fragmentFirstTimeVisible) { + _fragmentFirstTimeVisible = false; + onFragmentFirstTimeVisible(); + } + } + } +} From 618f3eaaba55ff5e92e17eec900387fde9cd2205 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Fri, 30 Mar 2018 01:41:43 +0200 Subject: [PATCH 07/19] Fix webview-js dialog not dismissing correctly --- .../web/ContextMenuWebView.java | 1 + .../web/DiasporaStreamWebChromeClient.java | 22 ++++++------------- build.gradle | 2 -- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/github/dfa/diaspora_android/web/ContextMenuWebView.java b/app/src/main/java/com/github/dfa/diaspora_android/web/ContextMenuWebView.java index caa2f68a..d450a51f 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/web/ContextMenuWebView.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/web/ContextMenuWebView.java @@ -100,6 +100,7 @@ public class ContextMenuWebView extends NestedWebView { MainActivity.REQUEST_CODE__ACCESS_EXTERNAL_STORAGE); } }) + .setCancelable(false) .setNegativeButton(context.getText(android.R.string.no), null) .show(); } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/web/DiasporaStreamWebChromeClient.java b/app/src/main/java/com/github/dfa/diaspora_android/web/DiasporaStreamWebChromeClient.java index 60a8f8cc..1dc21836 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/web/DiasporaStreamWebChromeClient.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/web/DiasporaStreamWebChromeClient.java @@ -18,7 +18,6 @@ */ package com.github.dfa.diaspora_android.web; -import android.content.DialogInterface; import android.webkit.JsResult; import android.webkit.WebView; import android.widget.ProgressBar; @@ -65,20 +64,13 @@ public class DiasporaStreamWebChromeClient extends FileUploadWebChromeClient { ThemedAlertDialogBuilder builder = new ThemedAlertDialogBuilder(view.getContext(), AppSettings.get()); builder.setTitle(view.getContext().getString(R.string.confirmation)) .setMessage(message) - .setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - result.confirm(); - } - }) - .setNegativeButton(android.R.string.cancel, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - result.cancel(); - } - }) - .create() - .show(); + .setPositiveButton(android.R.string.ok, (dialog, which) -> result.confirm()) + .setNegativeButton(android.R.string.cancel, (dialog, which) -> result.cancel()) + .setOnCancelListener(dialog -> { + result.cancel(); + dialog.dismiss(); + }) + .create().show(); return true; } diff --git a/build.gradle b/build.gradle index 3f0532f1..b84d2d90 100644 --- a/build.gradle +++ b/build.gradle @@ -12,8 +12,6 @@ buildscript { ext.version_library_appcompat = "27.1.0" // https://github.com/JakeWharton/butterknife/releases ext.version_library_butterknife = "8.8.1" - // https://github.com/atlassian/commonmark-java/releases - ext.version_library_commonmark = "0.10.0" // https://github.com/guardianproject/NetCipher/releases ext.version_library_netcipher = "2.0.0-alpha1" // https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-gradle-plugin#LookAtCentral From b48dc5dcaccdf63f14d3ea42690a0e0873be5ca5 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Fri, 30 Mar 2018 02:46:44 +0200 Subject: [PATCH 08/19] Fix loading non-pod links outside customtab/external browser --- .../activity/AboutActivity.java | 1 - .../activity/AspectListFragment.java | 1 - .../activity/DiasporaStreamFragment.java | 37 ++++++++++++------- .../activity/MainActivity.java | 21 ++++++++--- .../activity/PodSelectionFragment.java | 2 - .../activity/TagListFragment.java | 1 - .../ui/theme/ThemedActivity.java | 3 -- .../diaspora_android/util/ActivityUtils.java | 5 ++- .../diaspora_android/util/AppSettings.java | 2 +- .../diaspora_android/web/BrowserFragment.java | 3 +- .../web/custom_tab/CustomTabsHelper.java | 8 +++- 11 files changed, 51 insertions(+), 33 deletions(-) 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 f587f1bd..4ea2d1f5 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 @@ -20,7 +20,6 @@ package com.github.dfa.diaspora_android.activity; import android.content.ClipData; import android.content.ClipboardManager; -import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/AspectListFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/AspectListFragment.java index 6884974f..50cf66af 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/AspectListFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/AspectListFragment.java @@ -37,7 +37,6 @@ import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.data.DiasporaAspect; import com.github.dfa.diaspora_android.listener.OnSomethingClickListener; import com.github.dfa.diaspora_android.ui.theme.ThemedFragment; -import com.github.dfa.diaspora_android.util.AppLog; import com.github.dfa.diaspora_android.util.AppSettings; import com.github.dfa.diaspora_android.util.ContextUtils; import com.github.dfa.diaspora_android.util.DiasporaUrlHelper; diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/DiasporaStreamFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/DiasporaStreamFragment.java index 08882d5d..8e21e113 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/DiasporaStreamFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/DiasporaStreamFragment.java @@ -325,21 +325,30 @@ public class DiasporaStreamFragment extends BrowserFragment { @SuppressWarnings("unused") @JavascriptInterface public void setUserProfile(final String webMessage) throws JSONException { - App app = ((App) getActivity().getApplication()); - final DiasporaUserProfile pup = app.getDiasporaUserProfile(); - if (pup.isRefreshNeeded()) { - try { - // Try to very fail-safe check if user information gets really loaded from correct pod - if (!webView.getUrl().startsWith(app.getSettings().getPod().getPodUrl().getBaseUrl())) { - return; - } - } catch (Exception ignored) { - } - AppLog.v(this, "DiasporaUserProfile needs refresh; Try to parse JSON"); - pup.parseJson(webMessage); - getActivity().runOnUiThread(new Runnable() { + final Activity activity = getActivity(); + if (activity != null) { + activity.runOnUiThread(new Runnable() { + @Override public void run() { - pup.analyzeUrl(webView.getUrl()); + App app = ((App) activity.getApplication()); + final DiasporaUserProfile pup = app.getDiasporaUserProfile(); + if (pup.isRefreshNeeded()) { + try { + // Try to very fail-safe check if user information gets really loaded from correct pod + if (!webView.getUrl().startsWith(app.getSettings().getPod().getPodUrl().getBaseUrl())) { + return; + } + } catch (Exception ignored) { + return; + } + AppLog.v(this, "DiasporaUserProfile needs refresh; Try to parse JSON"); + pup.parseJson(webMessage); + getActivity().runOnUiThread(new Runnable() { + public void run() { + pup.analyzeUrl(webView.getUrl()); + } + }); + } } }); } 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 b15e1dc4..24369f1d 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 @@ -338,12 +338,23 @@ public class MainActivity extends ThemedActivity * * @param url URL to load in the DiasporaStreamFragment */ - public void openDiasporaUrl(String url) { + public void openDiasporaUrl(final String url) { AppLog.v(this, "openDiasporaUrl()"); - DiasporaStreamFragment streamFragment = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG); - showFragment(streamFragment); - showLastVisitedTimestampMessageIfNeeded(url); - streamFragment.loadUrl(url); + if (url.startsWith(_appSettings.getPod().getPodUrl().getBaseUrl()) && !url.startsWith("https://dia.so/")) { + DiasporaStreamFragment streamFragment = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG); + showFragment(streamFragment); + showLastVisitedTimestampMessageIfNeeded(url); + streamFragment.loadUrl(url); + } else { + toolbarTop.postDelayed(new Runnable() { + @Override + public void run() { + Intent i = new Intent(ACTION_OPEN_EXTERNAL_URL); + i.putExtra(EXTRA_URL, url); + LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i); + } + }, 1000); + } } public void showLastVisitedTimestampMessageIfNeeded(String url) { diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionFragment.java index 59908a59..ab247974 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionFragment.java @@ -32,7 +32,6 @@ import android.support.v4.content.LocalBroadcastManager; import android.support.v4.view.MenuItemCompat; import android.support.v7.widget.AppCompatButton; import android.support.v7.widget.SearchView; -import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -53,7 +52,6 @@ import com.github.dfa.diaspora_android.service.FetchPodsService; import com.github.dfa.diaspora_android.ui.PodSelectionDialog; import com.github.dfa.diaspora_android.ui.theme.ThemedFragment; import com.github.dfa.diaspora_android.util.ActivityUtils; -import com.github.dfa.diaspora_android.util.AppLog; import com.github.dfa.diaspora_android.util.AppSettings; import com.github.dfa.diaspora_android.util.ContextUtils; import com.github.dfa.diaspora_android.util.DiasporaUrlHelper; diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/TagListFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/TagListFragment.java index 576fb1b1..adb832c5 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/TagListFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/TagListFragment.java @@ -35,7 +35,6 @@ import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.listener.OnSomethingClickListener; import com.github.dfa.diaspora_android.ui.theme.ThemedFragment; -import com.github.dfa.diaspora_android.util.AppLog; import com.github.dfa.diaspora_android.util.AppSettings; import com.github.dfa.diaspora_android.util.ContextUtils; import com.github.dfa.diaspora_android.util.DiasporaUrlHelper; diff --git a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedActivity.java index bec88c4e..d8651bb5 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedActivity.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/ui/theme/ThemedActivity.java @@ -19,10 +19,7 @@ package com.github.dfa.diaspora_android.ui.theme; import android.annotation.TargetApi; -import android.app.ActivityManager; import android.content.pm.ActivityInfo; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; import android.os.Build; import android.support.v7.app.AppCompatActivity; diff --git a/app/src/main/java/com/github/dfa/diaspora_android/util/ActivityUtils.java b/app/src/main/java/com/github/dfa/diaspora_android/util/ActivityUtils.java index e998cd13..f99172f5 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/util/ActivityUtils.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/util/ActivityUtils.java @@ -77,10 +77,11 @@ public class ActivityUtils extends net.gsantner.opoc.util.ActivityUtils { /** * This method creates file sharing uri by using FileProvider + * * @return */ - public static Uri getFileSharingUri(Context context,File file) { + public static Uri getFileSharingUri(Context context, File file) { - return FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID,file); + return FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, file); } } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/util/AppSettings.java b/app/src/main/java/com/github/dfa/diaspora_android/util/AppSettings.java index 1b3d2bff..0c8999a0 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/util/AppSettings.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/util/AppSettings.java @@ -46,7 +46,7 @@ public class AppSettings extends SharedPreferencesPropertyBackend { return new AppSettings(App.get()); } - private AppSettings(Context context) { + public AppSettings(Context context) { super(context); _prefPod = _context.getSharedPreferences("pod0", Context.MODE_PRIVATE); } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/web/BrowserFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/web/BrowserFragment.java index 14478c07..538523ed 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/web/BrowserFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/web/BrowserFragment.java @@ -30,7 +30,6 @@ import android.os.Bundle; import android.os.Environment; import android.support.design.widget.Snackbar; import android.support.v7.app.AlertDialog; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.webkit.WebSettings; @@ -222,7 +221,7 @@ public class BrowserFragment extends ThemedFragment { // Only show share intent when Action Share Screenshot was selected if (hasToShareScreenshot) { - Uri bmpUri = ActivityUtils.getFileSharingUri(getContext(),new File(fileSaveDirectory, fileSaveName)); + Uri bmpUri = ActivityUtils.getFileSharingUri(getContext(), new File(fileSaveDirectory, fileSaveName)); Intent sharingIntent = new Intent(Intent.ACTION_SEND); sharingIntent.setType("image/jpeg"); diff --git a/app/src/main/java/com/github/dfa/diaspora_android/web/custom_tab/CustomTabsHelper.java b/app/src/main/java/com/github/dfa/diaspora_android/web/custom_tab/CustomTabsHelper.java index 50481fd3..d42bafaa 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/web/custom_tab/CustomTabsHelper.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/web/custom_tab/CustomTabsHelper.java @@ -41,6 +41,8 @@ public class CustomTabsHelper { static final String BETA_PACKAGE = "com.chrome.beta"; static final String DEV_PACKAGE = "com.chrome.dev"; static final String LOCAL_PACKAGE = "com.google.android.apps.chrome"; + static final String CHROMIUM = "org.chromium.chrome"; + static final String FENNEC = "org.mozilla.fennec_fdroid"; private static final String EXTRA_CUSTOM_TABS_KEEP_ALIVE = "android.support.customtabs.extra.KEEP_ALIVE"; @@ -101,6 +103,10 @@ public class CustomTabsHelper { sPackageNameToUse = DEV_PACKAGE; } else if (packagesSupportingCustomTabs.contains(LOCAL_PACKAGE)) { sPackageNameToUse = LOCAL_PACKAGE; + } else if (packagesSupportingCustomTabs.contains(CHROMIUM)) { + sPackageNameToUse = CHROMIUM; + } else if (packagesSupportingCustomTabs.contains(FENNEC)) { + sPackageNameToUse = FENNEC; } return sPackageNameToUse; } @@ -137,6 +143,6 @@ public class CustomTabsHelper { * @return All possible chrome package names that provide custom tabs feature. */ public static String[] getPackages() { - return new String[]{"", STABLE_PACKAGE, BETA_PACKAGE, DEV_PACKAGE, LOCAL_PACKAGE}; + return new String[]{"", STABLE_PACKAGE, BETA_PACKAGE, DEV_PACKAGE, LOCAL_PACKAGE, CHROMIUM, FENNEC}; } } From dcc87281719bda93b7f5f38c7b56115f2573a015 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Fri, 30 Mar 2018 02:52:20 +0200 Subject: [PATCH 09/19] Update changelog * fixes #180 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e49e3c8a..2eed665c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### v1.1.2 +- Fix: loading non-pod links outside customtab/external browser +- Fix: webview-js dialog not dismissing correctly + ### v1.1.0 - Added: App shortcuts (Android 7+) - Updated: podlist From 80f8f10bf90369d2fc7cbba682ffe373bb6a41e4 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Fri, 30 Mar 2018 03:03:19 +0200 Subject: [PATCH 10/19] Release v1.1.2 --- README.md | 5 ++--- app/build.gradle | 4 ++-- app/src/main/res/values/strings-preferences.xml | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8efb06ce..bcdadee7 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,8 @@ [![Build Status](https://travis-ci.org/Diaspora-for-Android/dandelion.svg?branch=master)](https://travis-ci.org/Diaspora-for-Android/dandelion) [![Translate - with Stringlate](https://img.shields.io/badge/stringlate-translate-green.svg)](https://lonamiwebs.github.io/stringlate/translate?git=https%3A%2F%2Fgithub.com%2Fdiaspora-for-android%2Fdandelion.git&mail=gro.xobliam@@rentnasg) [![Chat - Matrix](https://img.shields.io/badge/chat-on%20matrix-blue.svg)](https://matrix.to/#/#dandelion:matrix.org) [![Chat - FreeNode IRC](https://img.shields.io/badge/chat-on%20irc-blue.svg)](https://kiwiirc.com/client/irc.freenode.net/?nick=dandelion-anon|?##dandelion) -[![Donate Bitcoin](https://img.shields.io/badge/donate-bitcoin-orange.svg)](http://gsantner.net/#donate) +[![Donate Bitcoin](https://img.shields.io/badge/donate-bitcoin-orange.svg)](https://gsantner.net/supportme/?project=dandelion&source=readme) [![Donate LiberaPay](https://img.shields.io/badge/donate-liberapay-orange.svg)](https://liberapay.com/gsantner/donate) -[![Donate GratiPay](https://img.shields.io/gratipay/team/dandelion.svg)](https://gratipay.com/dandelion/) # dandelion\* @@ -79,7 +78,7 @@ For more licensing informations, see [`3rd party licenses`](/app/src/main/res/ra ### Notice #### Maintainers -- gsantner ([GitHub](https://github.com/gsantner), [Web](http://gsantner.net), [diaspora*](https://pod.geraspora.de/people/d1cbdd70095301341e834860008dbc6c)) +- gsantner ([GitHub](https://github.com/gsantner), [Web](https://gsantner.net), [diaspora*](https://pod.geraspora.de/people/d1cbdd70095301341e834860008dbc6c)) - Bitcoin: [1B9ZyYdQoY9BxMe9dRUEKaZbJWsbQqfXU5](http://gsantner.net/donate/#donate) - vanitasvitae ([GitHub](https://github.com/vanitasvitae), [diaspora*](https://pod.geraspora.de/people/bbd7af90fbec013213e34860008dbc6c)) - Bitcoin: 1Ao3W6NaQv3xKppviB7RSFKjHo6PGd8RTy diff --git a/app/build.gradle b/app/build.gradle index 3838b62b..f11ef202 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -19,8 +19,8 @@ android { resValue "string", "manifest_package_id", "com.github.dfa.diaspora_android" applicationId "com.github.dfa.diaspora_android" - versionName "1.1.1" - versionCode 30 + versionName "1.1.2" + versionCode 31 vectorDrawables.useSupportLibrary = true diff --git a/app/src/main/res/values/strings-preferences.xml b/app/src/main/res/values/strings-preferences.xml index cf3860c3..4fd9f112 100644 --- a/app/src/main/res/values/strings-preferences.xml +++ b/app/src/main/res/values/strings-preferences.xml @@ -71,7 +71,7 @@ - Open external links with Chrome Custom Tabs. Chromium or Google Chrome needs to be installed in order to use this feature. \nIMPORTANT NOTE: Chrome Custom Tabs do not use configured proxy servers! + Open external links with Chrome Custom Tabs. Chromium, Firefox or Google Chrome needs to be installed in order to use this feature. \nIMPORTANT NOTE: Chrome Custom Tabs do not use configured proxy servers! Personal settings From f6ab146fd75fdab006b0bb561ad10ba02845c198 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Tue, 3 Apr 2018 23:23:16 +0200 Subject: [PATCH 11/19] Update github templates --- .github/ISSUE_TEMPLATE.md | 32 +++++++++++++++++--------------- .github/PULL_REQUEST_TEMPLATE | 8 ++++++++ 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index d9892f4a..1cfcaa79 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,25 +1,27 @@ #### General information - - - * **App version:** * **System:** * **Pod:** #### Description -What this is about, what happens and how. What needs to be done for it to happen. #### Log - + + diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE index 4028d569..863cd426 100644 --- a/.github/PULL_REQUEST_TEMPLATE +++ b/.github/PULL_REQUEST_TEMPLATE @@ -6,6 +6,14 @@ Del billede Åben i ekstern browser… - Kopier link-adresse til udklipsholder + Kopier link-adresse til udklipsholder diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index bbf94f0a..239ae35f 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -57,7 +57,7 @@ Bild speichern Bild teilen In externem Browser öffnen… - Link-Adresse kopieren + Link-Adresse kopieren Bild-Adresse kopieren Konnte Bild nicht laden… diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 6969ce9f..2d83a51b 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -57,7 +57,7 @@ Guardar imagen Compartir imagen Abrir en navegador externo… - Copiar dirección del enlace al portapapeles + Copiar dirección del enlace al portapapeles Copiar dirección de imagen al portapapeles No se pudo cargar la imagen diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index ceba8114..bb0866d0 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -57,7 +57,7 @@ Enregistrer l\'image Partager l\'image Ouvrir dans un navigateur externe… - Copier le lien dans le presse-papier + Copier le lien dans le presse-papier Copier le lien de l\'image dans le presse-papiers Impossible de récupérer l\'image diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 50fec360..ed7041cb 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -57,7 +57,7 @@ Gardar imaxe Compartir imaxe Abrir nun navegador externo… - Copiar ligazón ao portapapeis + Copiar ligazón ao portapapeis Copia enderezo da imaxe ao portapapeis Non se cargou a imaxe diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 378ea528..3d04a9c0 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -57,7 +57,7 @@ Kép mentése Kép megosztása Megnyitás külső böngészőben… - Link címének másolása a vágólapra + Link címének másolása a vágólapra Kép címének másolása a vágólapra Nem lehet betölteni a képet diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 00117c36..d5b5885f 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -57,7 +57,7 @@ Salva immagine Condividi immagine Apri nel browser… - Copia link negli appunti + Copia link negli appunti Copia indirizzo dell\'immagine negli appunti Impossibile caricare immagine diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 0ee47968..6b7ace50 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -57,7 +57,7 @@ 画像を保存 画像をシェア 外部ブラウザーで開く… - リンクアドレスをクリップボードへコピー + リンクアドレスをクリップボードへコピー 画像のアドレスをクリップボードへコピー 画像を読み込むことができません diff --git a/app/src/main/res/values-kab/strings.xml b/app/src/main/res/values-kab/strings.xml index 92c2885b..4e6fe374 100644 --- a/app/src/main/res/values-kab/strings.xml +++ b/app/src/main/res/values-kab/strings.xml @@ -57,7 +57,7 @@ Sekles tugna Bḍu tugna Ldi deg iminig azɣaray… - Nɣel aseɣwen ɣef afus + Nɣel aseɣwen ɣef afus Nɣel tugna ɣef afus Ur izmir ara ad d-isali tugna diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml index 4aebdff8..bb300a60 100644 --- a/app/src/main/res/values-ml/strings.xml +++ b/app/src/main/res/values-ml/strings.xml @@ -57,7 +57,7 @@ ചിത്രം സംരക്ഷിക്കുക ചിത്രം പങ്കുവയ്ക്കുക പുറമെയുള്ള ബ്രൗസറിൽ തുറക്കുക… - ലിങ്ക് വിലാസം ക്ലിപ്ബോർഡിലേക്ക് പകർത്തുക + ലിങ്ക് വിലാസം ക്ലിപ്ബോർഡിലേക്ക് പകർത്തുക ചിത്രത്തിന്റെ വിലാസം ക്ലിപ്ബോർഡിലേക്ക് പകർത്തുക ചിത്രം ലോഡ് ചെയ്യാൻ സാധിക്കുന്നില്ല diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 22a36fb8..481ce9f1 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -57,7 +57,7 @@ Afbeelding opslaan Deel afbeelding Geopend in externe browser… - Link-adres kopiëren naar Klembord + Link-adres kopiëren naar Klembord Afbeelding kopiëren naar Klembord Niet in staat om afbeelding te laden diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 7b5cdc34..2c3e8e68 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -57,7 +57,7 @@ Zapisz obraz Udostępnij obraz Otwórz w zewnętrznej przeglądarce… - Skopiuj adres odnośnika do schowka + Skopiuj adres odnośnika do schowka Skopiuj adres obrazu do schowka Nie udało się wczytać obrazu diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 6a54eeec..1720bd5f 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -59,7 +59,7 @@ Salvar imagem Compartilhar imagem Abrir em navegador externo… - Copiar endereço à área de transferência + Copiar endereço à área de transferência Copiar endereço de imagem à área de transferência Impossível carregar a imagem diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index a0271522..0073f07c 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -57,7 +57,7 @@ Сохранить изображение Поделиться изображением Открыть во внешнем браузере… - Скопировать адрес ссылки в буфер обмена + Скопировать адрес ссылки в буфер обмена Скопировать адрес изображения в буфер обмена Не удаётся загрузить изображение diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index 72b3bbd8..b7ca8fc1 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -71,7 +71,7 @@ Sarva s\'immàgine Cumpartzi s\'immàgine Aberi in un\'esploradore (browser) esternu… - Còpia su ligàmenes in sos apuntos + Còpia su ligàmenes in sos apuntos Còpia s\'indiritzu de s\'immàgine in sos apuntos diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 5664fd09..5eb05d34 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -57,7 +57,7 @@ Spara bild Dela bild Öppna i en extern webbläsare… - Kopiera länkadress + Kopiera länkadress Kopiera bildadressen Kunde inte ladda bilden diff --git a/app/src/main/res/values-uk-rUA/strings.xml b/app/src/main/res/values-uk-rUA/strings.xml index b7a2d304..25c3ad87 100644 --- a/app/src/main/res/values-uk-rUA/strings.xml +++ b/app/src/main/res/values-uk-rUA/strings.xml @@ -57,7 +57,7 @@ Зберегти зображення Поділитися зображенням Відкрити у зовнішньому браузері… - Копіювати адресу посилання у буфер обміну + Копіювати адресу посилання у буфер обміну Копіювати зображення у буфер обміну Не вдалося завантажити зображення diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 79671b48..e5b84697 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -57,7 +57,7 @@ 儲存圖片 分享圖片 用外部瀏覽器開啟… - 將連結網址複製到剪貼簿 + 將連結網址複製到剪貼簿 將圖片網址複製到剪貼簿 無法載入圖片 diff --git a/app/src/main/res/values/strings-not_translatable.xml b/app/src/main/res/values/strings-not_translatable.xml index 4ec47306..4e210a01 100644 --- a/app/src/main/res/values/strings-not_translatable.xml +++ b/app/src/main/res/values/strings-not_translatable.xml @@ -127,4 +127,5 @@ pref_key__is_overview_statusbar_hidden pref_key__recreate_main_activity pref_key__show_title + PDF diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index db79e82c..7a40626b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -70,7 +70,7 @@ Save image Share image Open in external browser… - Copy link address to clipboard + Copy link address to clipboard Copy image address to clipboard @@ -98,4 +98,5 @@ Hide statusbar Show title in the main view Show title + Launcher shortcut diff --git a/metadata/en-US/full_description.txt b/metadata/en-US/full_description.txt index 120c4be9..651f7602 100644 --- a/metadata/en-US/full_description.txt +++ b/metadata/en-US/full_description.txt @@ -3,16 +3,16 @@ It adds useful features to your networking experience: ⚡ Quick access to most diaspora* features 👉 Share content to and from the app -🌎 Proxy support +🌎 Proxy support (Tor/Orbot supported) 📰 In-app-browser to view articles 🎨 Customizeable colors 🌆 Night/AMOLED mode 🈴 Localized in many languages ✔️ Allows system independent language - Support the project:Translate using StringlateJoin discussion on MatrixMore information about contributions + ✋ Android Contribution Guide (gsantner blog)Support main developer From 68be2f3a4a541bf94040c4c73b06ebe0b2144074 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Sun, 8 Apr 2018 18:05:56 +0200 Subject: [PATCH 15/19] Load README when ow pod URL gets called and no pod selected , fixes #193 --- .../activity/MainActivity.java | 23 ++++++++++++------- .../web/custom_tab/CustomTabsHelper.java | 2 ++ 2 files changed, 17 insertions(+), 8 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 d6a35aed..099d505f 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 @@ -333,19 +333,26 @@ public class MainActivity extends ThemedActivity */ public void openDiasporaUrl(final String url) { AppLog.v(this, "openDiasporaUrl()"); - if (url.startsWith(_appSettings.getPod().getPodUrl().getBaseUrl()) && !url.startsWith("https://dia.so/")) { + if (url != null && url.startsWith("http://127.0.0.1")) { + // This URL seems to be called somehow, but it doesn't make sense ;) + toolbarTop.postDelayed(() -> { + Intent i = new Intent(ACTION_OPEN_EXTERNAL_URL); + i.putExtra(EXTRA_URL, "https://github.com/Diaspora-for-Android/dandelion/blob/master/README.md"); + LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i); + }, 1000); + return; + } + if (_appSettings.getPod() != null && _appSettings.getPod().getPodUrl() != null && _appSettings.getPod().getPodUrl().getBaseUrl() != null + && url.startsWith(_appSettings.getPod().getPodUrl().getBaseUrl()) && !url.startsWith("https://dia.so/")) { DiasporaStreamFragment streamFragment = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG); showFragment(streamFragment); showLastVisitedTimestampMessageIfNeeded(url); streamFragment.loadUrl(url); } else { - toolbarTop.postDelayed(new Runnable() { - @Override - public void run() { - Intent i = new Intent(ACTION_OPEN_EXTERNAL_URL); - i.putExtra(EXTRA_URL, url); - LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i); - } + toolbarTop.postDelayed(() -> { + Intent i = new Intent(ACTION_OPEN_EXTERNAL_URL); + i.putExtra(EXTRA_URL, url); + LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i); }, 1000); } } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/web/custom_tab/CustomTabsHelper.java b/app/src/main/java/com/github/dfa/diaspora_android/web/custom_tab/CustomTabsHelper.java index c2e66a72..29ea60bb 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/web/custom_tab/CustomTabsHelper.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/web/custom_tab/CustomTabsHelper.java @@ -108,6 +108,8 @@ public class CustomTabsHelper { sPackageNameToUse = CHROMIUM; } else if (packagesSupportingCustomTabs.contains(FENNEC)) { sPackageNameToUse = FENNEC; + }else if (packagesSupportingCustomTabs.contains(KLAR)) { + sPackageNameToUse = KLAR; } return sPackageNameToUse; } From 38cf36b46c3d7b9d29ad1aa319b6b3d46e4cbbde Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Sun, 8 Apr 2018 19:11:12 +0200 Subject: [PATCH 16/19] Improve sharing *a lot* +GIF - add support for multiple filetypes * now supporting GIFs too ;) * Create connection over netcipher --- .../service/AvatarImageLoader.java | 6 +- .../service/ImageDownloadTask.java | 98 ------------ .../web/ContextMenuWebView.java | 145 +++++------------- .../web/custom_tab/CustomTabsHelper.java | 2 +- .../format/markdown/SimpleMarkdownParser.java | 2 +- .../nonsupport/LanguagePreference.java | 2 +- .../net/gsantner/opoc/util/DownloadTask.java | 57 +++++++ .../net/gsantner/opoc/util/NetworkUtils.java | 9 +- 8 files changed, 112 insertions(+), 209 deletions(-) delete mode 100644 app/src/main/java/com/github/dfa/diaspora_android/service/ImageDownloadTask.java create mode 100644 app/src/main/java/net/gsantner/opoc/util/DownloadTask.java diff --git a/app/src/main/java/com/github/dfa/diaspora_android/service/AvatarImageLoader.java b/app/src/main/java/com/github/dfa/diaspora_android/service/AvatarImageLoader.java index 20f0a4f9..ab975326 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/service/AvatarImageLoader.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/service/AvatarImageLoader.java @@ -24,6 +24,8 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.widget.ImageView; +import net.gsantner.opoc.util.DownloadTask; + import java.io.File; public class AvatarImageLoader { @@ -52,7 +54,9 @@ public class AvatarImageLoader { public void startImageDownload(ImageView imageView, String avatarUrl) { if (!avatarUrl.equals("")) { - new ImageDownloadTask(imageView, avatarFile.getAbsolutePath()).execute(avatarUrl); + new DownloadTask(new File(avatarFile.getAbsolutePath()), (ok, file) -> { + loadToImageView(imageView); + }).execute(avatarUrl); } } } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/service/ImageDownloadTask.java b/app/src/main/java/com/github/dfa/diaspora_android/service/ImageDownloadTask.java deleted file mode 100644 index 5a3fd465..00000000 --- a/app/src/main/java/com/github/dfa/diaspora_android/service/ImageDownloadTask.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - This file is part of the dandelion*. - - dandelion* 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. - - dandelion* 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 dandelion*. - - If not, see . - */ -package com.github.dfa.diaspora_android.service; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.os.AsyncTask; -import android.support.annotation.Nullable; -import android.widget.ImageView; - -import com.github.dfa.diaspora_android.util.AppLog; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; - -import javax.net.ssl.HttpsURLConnection; - -import info.guardianproject.netcipher.NetCipher; - -/** - * Task that can be used to download images from URLs and store them in storage - * Created by gsantner (http://gsantner.net/) on 24.03.16. - */ -public class ImageDownloadTask extends AsyncTask { - private final ImageView imageView; - private String savePath; - - /** - * Download image from URL - * - * @param imageView ImageView to set image to (null = don't set) - * @param savePath Save image to file (null = don't save) - */ - public ImageDownloadTask(@Nullable ImageView imageView, @Nullable String savePath) { - this.imageView = imageView; - this.savePath = savePath; - } - - protected Bitmap doInBackground(String... urls) { - String url = urls[0]; - Bitmap bitmap = null; - FileOutputStream out = null; - InputStream inStream; - HttpsURLConnection connection; - try { - connection = NetCipher.getHttpsURLConnection(url); - inStream = connection.getInputStream(); - bitmap = BitmapFactory.decodeStream(inStream); - - // Save to file if not null - if (savePath != null) { - out = new FileOutputStream(savePath); - bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); - } - - try { - inStream.close(); - } catch (IOException e) {/*Nothing*/} - - connection.disconnect(); - - } catch (Exception e) { - AppLog.e(this, e.getMessage()); - } finally { - try { - if (out != null) { - out.close(); - } - } catch (IOException ignored) { - } - } - return bitmap; - } - - protected void onPostExecute(Bitmap result) { - // Display on imageview if not null - if (imageView != null) { - imageView.setImageBitmap(result); - } - } -} diff --git a/app/src/main/java/com/github/dfa/diaspora_android/web/ContextMenuWebView.java b/app/src/main/java/com/github/dfa/diaspora_android/web/ContextMenuWebView.java index 9e10a218..6cb85c8f 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/web/ContextMenuWebView.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/web/ContextMenuWebView.java @@ -18,30 +18,27 @@ */ package com.github.dfa.diaspora_android.web; -import android.Manifest; import android.app.Activity; -import android.app.AlertDialog; -import android.app.DownloadManager; import android.content.ClipData; import android.content.ClipboardManager; 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.Environment; import android.util.AttributeSet; import android.view.ContextMenu; import android.view.MenuItem; import android.widget.Toast; +import com.github.dfa.diaspora_android.BuildConfig; import com.github.dfa.diaspora_android.R; -import com.github.dfa.diaspora_android.activity.MainActivity; -import com.github.dfa.diaspora_android.service.ImageDownloadTask; -import com.github.dfa.diaspora_android.util.ActivityUtils; +import com.github.dfa.diaspora_android.util.AppSettings; + +import net.gsantner.opoc.util.DownloadTask; +import net.gsantner.opoc.util.PermissionChecker; +import net.gsantner.opoc.util.ShareUtil; import java.io.File; +import java.util.Date; /** * Subclass of WebView which adds a context menu for long clicks on images or links to share, save @@ -81,108 +78,46 @@ public class ContextMenuWebView extends NestedWebView { public boolean onMenuItemClick(MenuItem item) { HitTestResult result = getHitTestResult(); String url = result.getExtra(); + final ShareUtil shu = new ShareUtil(context).setFileProviderAuthority(BuildConfig.APPLICATION_ID); + final PermissionChecker permc = new PermissionChecker(parentActivity); + final AppSettings appSettings = new AppSettings(context); + switch (item.getItemId()) { //Save image to external memory case ID_SAVE_IMAGE: { - 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); - } - }) - .setCancelable(false) - .setNegativeButton(context.getText(android.R.string.no), null) - .show(); - } - parentActivity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - MainActivity.REQUEST_CODE__ACCESS_EXTERNAL_STORAGE); - } - } - if (writeToStoragePermitted) { - //Make sure, Diaspora Folder exists - File destinationFolder = new File(Environment.getExternalStorageDirectory() + "/Pictures/Diaspora"); - if (!destinationFolder.exists()) { - destinationFolder.mkdirs(); - } - - if (url != null) { - Uri source = Uri.parse(url); + if (permc.doIfExtStoragePermissionGranted(context.getString(R.string.permissions_image))) { + File fileSaveDirectory = appSettings.getAppSaveDirectory(); + if (permc.mkdirIfStoragePermissionGranted(fileSaveDirectory)) { + String filename = "dandelion-" + ShareUtil.SDF_SHORT.format(new Date()) + url.substring(url.lastIndexOf(".")); + /*Uri source = Uri.parse(url); DownloadManager.Request request = new DownloadManager.Request(source); - File destinationFile = new File(Environment.getExternalStorageDirectory() + "/Pictures/Diaspora/" + System.currentTimeMillis() + ".png"); - - request.setDestinationUri(Uri.fromFile(destinationFile)); - ((DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE)).enqueue(request); - - Toast.makeText(context, context.getText(R.string.share__toast_saved_image_to_location) + " " + - destinationFile.getAbsolutePath(), Toast.LENGTH_LONG).show(); + request.setDestinationUri(Uri.fromFile(new File(fileSaveDirectory, filename))); + ((DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE)).enqueue(request);*/ + new DownloadTask(new File(fileSaveDirectory, filename), (ok, dlfile) -> { + if (ok) { + Toast.makeText(context, context.getText(R.string.share__toast_saved_image_to_location) + " " + dlfile.getName(), Toast.LENGTH_LONG).show(); + } + }).execute(url); } } - } - break; - - case ID_SHARE_IMAGE: - if (url != null) { - 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(); - } else { - parentActivity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - MainActivity.REQUEST_CODE__ACCESS_EXTERNAL_STORAGE); - } - } - } - if (writeToStoragePermitted) { - //Make sure, Diaspora Folder exists - File destinationFolder = new File(Environment.getExternalStorageDirectory() + "/Pictures/Diaspora"); - if (!destinationFolder.exists()) { - destinationFolder.mkdirs(); - } - - 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 = ActivityUtils.getFileSharingUri(context, 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, getResources().getString(R.string.action_share_dotdotdot))); - } - }.execute(url); - } - } else { - Toast.makeText(context, "Cannot share image: url is null", Toast.LENGTH_SHORT).show(); - } - break; + } + + case ID_SHARE_IMAGE: { + if (permc.doIfExtStoragePermissionGranted(context.getString(R.string.permissions_image))) { + File fileSaveDirectory = appSettings.getAppSaveDirectory(); + if (permc.mkdirIfStoragePermissionGranted(fileSaveDirectory)) { + String filename = ".dandelion-shared" + url.substring(url.lastIndexOf(".")); + new DownloadTask(new File(fileSaveDirectory, filename), (ok, dlfile) -> { + if (ok) { + Toast.makeText(context, context.getText(R.string.share__toast_saved_image_to_location) + " " + dlfile.getName(), Toast.LENGTH_LONG).show(); + shu.shareStream(dlfile, "image/" + dlfile.getAbsolutePath().lastIndexOf(".") + 1); + } + }).execute(url); + } + } + break; + } case ID_IMAGE_EXTERNAL_BROWSER: if (url != null) { diff --git a/app/src/main/java/com/github/dfa/diaspora_android/web/custom_tab/CustomTabsHelper.java b/app/src/main/java/com/github/dfa/diaspora_android/web/custom_tab/CustomTabsHelper.java index 29ea60bb..aaa89f06 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/web/custom_tab/CustomTabsHelper.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/web/custom_tab/CustomTabsHelper.java @@ -108,7 +108,7 @@ public class CustomTabsHelper { sPackageNameToUse = CHROMIUM; } else if (packagesSupportingCustomTabs.contains(FENNEC)) { sPackageNameToUse = FENNEC; - }else if (packagesSupportingCustomTabs.contains(KLAR)) { + } else if (packagesSupportingCustomTabs.contains(KLAR)) { sPackageNameToUse = KLAR; } return sPackageNameToUse; diff --git a/app/src/main/java/net/gsantner/opoc/format/markdown/SimpleMarkdownParser.java b/app/src/main/java/net/gsantner/opoc/format/markdown/SimpleMarkdownParser.java index d42c73e5..adaafa3b 100644 --- a/app/src/main/java/net/gsantner/opoc/format/markdown/SimpleMarkdownParser.java +++ b/app/src/main/java/net/gsantner/opoc/format/markdown/SimpleMarkdownParser.java @@ -9,7 +9,7 @@ * #########################################################*/ - /* +/* * Parses most common markdown tags. Only inline tags are supported, multiline/block syntax * is not supported (citation, multiline code, ..). This is intended to stay as easy as possible. * diff --git a/app/src/main/java/net/gsantner/opoc/preference/nonsupport/LanguagePreference.java b/app/src/main/java/net/gsantner/opoc/preference/nonsupport/LanguagePreference.java index 52dfc3d1..76284a11 100644 --- a/app/src/main/java/net/gsantner/opoc/preference/nonsupport/LanguagePreference.java +++ b/app/src/main/java/net/gsantner/opoc/preference/nonsupport/LanguagePreference.java @@ -48,8 +48,8 @@ package net.gsantner.opoc.preference.nonsupport; import android.annotation.TargetApi; import android.content.Context; import android.os.Build; -import android.support.annotation.Nullable; import android.preference.ListPreference; +import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.AttributeSet; diff --git a/app/src/main/java/net/gsantner/opoc/util/DownloadTask.java b/app/src/main/java/net/gsantner/opoc/util/DownloadTask.java new file mode 100644 index 00000000..aec5b868 --- /dev/null +++ b/app/src/main/java/net/gsantner/opoc/util/DownloadTask.java @@ -0,0 +1,57 @@ +/* + This file is part of the dandelion*. + + dandelion* 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. + + dandelion* 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 dandelion*. + + If not, see . + */ +package net.gsantner.opoc.util; + +import android.os.AsyncTask; +import android.support.annotation.Nullable; + +import java.io.File; +import java.io.IOException; + +import javax.net.ssl.HttpsURLConnection; + +import info.guardianproject.netcipher.NetCipher; + +public class DownloadTask extends AsyncTask { + private File _targetFile; + private Callback.a2 _callback; + + public DownloadTask(File targetFile, @Nullable Callback.a2 callback) { + _targetFile = targetFile; + _callback = callback; + } + + protected Boolean doInBackground(String... urls) { + if (urls != null && urls.length > 0 && urls[0] != null) { + try { + HttpsURLConnection connection = NetCipher.getHttpsURLConnection(urls[0]); + return NetworkUtils.downloadFile(null, _targetFile, connection, null); + } catch (IOException e) { + e.printStackTrace(); + } + } + return false; + } + + protected void onPostExecute(Boolean result) { + if (_callback != null) { + _callback.callback(result, _targetFile); + } + } +} diff --git a/app/src/main/java/net/gsantner/opoc/util/NetworkUtils.java b/app/src/main/java/net/gsantner/opoc/util/NetworkUtils.java index f4586d7b..ebd7c31d 100644 --- a/app/src/main/java/net/gsantner/opoc/util/NetworkUtils.java +++ b/app/src/main/java/net/gsantner/opoc/util/NetworkUtils.java @@ -53,11 +53,16 @@ public class NetworkUtils { } public static boolean downloadFile(final URL url, final File outFile, final Callback.a1 progressCallback) { + return downloadFile(url, outFile, null, progressCallback); + } + + public static boolean downloadFile(final URL url, final File outFile, HttpURLConnection connection, final Callback.a1 progressCallback) { InputStream input = null; OutputStream output = null; - HttpURLConnection connection = null; try { - connection = (HttpURLConnection) url.openConnection(); + if (connection == null) { + connection = (HttpURLConnection) url.openConnection(); + } connection.connect(); input = connection.getInputStream(); From 9da1a910b32d5f23afe43af694c84446c2f20843 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Sun, 8 Apr 2018 20:12:51 +0200 Subject: [PATCH 17/19] Add existingconnection to opoc:networkutils:performCall --- .../net/gsantner/opoc/util/NetworkUtils.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/net/gsantner/opoc/util/NetworkUtils.java b/app/src/main/java/net/gsantner/opoc/util/NetworkUtils.java index ebd7c31d..5212e5b7 100644 --- a/app/src/main/java/net/gsantner/opoc/util/NetworkUtils.java +++ b/app/src/main/java/net/gsantner/opoc/util/NetworkUtils.java @@ -64,7 +64,9 @@ public class NetworkUtils { connection = (HttpURLConnection) url.openConnection(); } connection.connect(); - input = connection.getInputStream(); + input = connection.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST + ? connection.getInputStream() : connection.getErrorStream(); + if (!outFile.getParentFile().isDirectory()) if (!outFile.getParentFile().mkdirs()) @@ -145,20 +147,28 @@ public class NetworkUtils { } private static String performCall(final URL url, final String method, final String data) { + return performCall(url, method, data, null); + } + + private static String performCall(final URL url, final String method, final String data, final HttpURLConnection existingConnection) { try { - final HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setRequestMethod(method); - conn.setDoInput(true); + final HttpURLConnection connection = existingConnection != null + ? existingConnection : (HttpURLConnection) url.openConnection(); + connection.setRequestMethod(method); + connection.setDoInput(true); if (data != null && !data.isEmpty()) { - conn.setDoOutput(true); - final OutputStream output = conn.getOutputStream(); + connection.setDoOutput(true); + final OutputStream output = connection.getOutputStream(); output.write(data.getBytes(Charset.forName(UTF8))); output.flush(); output.close(); } - return FileUtils.readCloseTextStream(conn.getInputStream()); + InputStream input = connection.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST + ? connection.getInputStream() : connection.getErrorStream(); + + return FileUtils.readCloseTextStream(connection.getInputStream()); } catch (Exception e) { e.printStackTrace(); } From cebf0f473b2422441e68f6300d1108dc4b62c17e Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Sun, 8 Apr 2018 22:08:21 +0200 Subject: [PATCH 18/19] Fix podselection custom button color --- .../diaspora_android/activity/PodSelectionFragment.java | 9 ++++----- app/src/main/res/values/strings-not_translatable.xml | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionFragment.java index ab247974..8f6c5ad5 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/PodSelectionFragment.java @@ -173,11 +173,10 @@ public class PodSelectionFragment extends ThemedFragment implements SearchView.O rootView.setBackgroundColor(appSettings.isAmoledColorMode() ? Color.BLACK : Color.WHITE); listViewPod.setDivider(new ColorDrawable(Color.GRAY)); listViewPod.setDividerHeight(dividerHeight); - if (appSettings.isAmoledColorMode()) { - buttonUseCustomPod.setTextColor(Color.WHITE); - } else { - buttonUseCustomPod.setTextColor(ContextUtils.get().shouldColorOnTopBeLight(appSettings.getAccentColor()) ? Color.WHITE : Color.BLACK); - } + int bgcolor = appSettings.isAmoledColorMode() ? Color.BLACK : appSettings.getAccentColor(); + buttonUseCustomPod.setBackgroundColor(bgcolor); + buttonUseCustomPod.setTextColor(_cu.shouldColorOnTopBeLight(bgcolor) ? Color.WHITE : Color.BLACK); + } @Override diff --git a/app/src/main/res/values/strings-not_translatable.xml b/app/src/main/res/values/strings-not_translatable.xml index 4e210a01..4dc1878f 100644 --- a/app/src/main/res/values/strings-not_translatable.xml +++ b/app/src/main/res/values/strings-not_translatable.xml @@ -5,7 +5,7 @@ \n\n\n_________________________\n **Tags:** #dandelíon \n\n - *via [dandelion*](/people?q=dandelion00%40diasp.org) client / [GitHub](https://github.com/Diaspora-for-Android/dandelion)* + *via [dandelion*](/people?q=dandelion00%40diasp.org) client [(Source)](https://github.com/Diaspora-for-Android/dandelion)* Tor From 2cc74ea6136ada5e90a6c21e4bbd112d132cf011 Mon Sep 17 00:00:00 2001 From: Gregor Santner Date: Sun, 8 Apr 2018 22:10:53 +0200 Subject: [PATCH 19/19] Release v1.1.3 --- CHANGELOG.md | 6 ++++++ app/build.gradle | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2eed665c..5e8072e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +### v1.1.3 +- Improve sharing *a lot*, add support for multiple filetypes +- Support for downloading GIFs ;) +- Rework screenshot saving and sharing; add new share options: +- Merge license and changelog dialog on first start + ### v1.1.2 - Fix: loading non-pod links outside customtab/external browser - Fix: webview-js dialog not dismissing correctly diff --git a/app/build.gradle b/app/build.gradle index f11ef202..a11ef9b9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -19,8 +19,8 @@ android { resValue "string", "manifest_package_id", "com.github.dfa.diaspora_android" applicationId "com.github.dfa.diaspora_android" - versionName "1.1.2" - versionCode 31 + versionName "1.1.3" + versionCode 32 vectorDrawables.useSupportLibrary = true