getStringList(@StringRes int keyResourceId, final SharedPreferences... pref) {
return getStringListOne(rstr(keyResourceId), gp(pref));
}
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 23a9212d..b7d60918 100644
--- a/app/src/main/java/net/gsantner/opoc/util/ActivityUtils.java
+++ b/app/src/main/java/net/gsantner/opoc/util/ActivityUtils.java
@@ -32,6 +32,7 @@ import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebView;
+import android.widget.ScrollView;
@SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue", "SpellCheckingInspection"})
@@ -115,18 +116,18 @@ public class ActivityUtils extends net.gsantner.opoc.util.ContextUtils {
}
public void showDialogWithHtmlTextView(@StringRes int resTitleId, String text, boolean isHtml, DialogInterface.OnDismissListener dismissedListener) {
+ ScrollView scroll = new ScrollView(_context);
AppCompatTextView textView = new AppCompatTextView(_context);
- int padding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16,
- _context.getResources().getDisplayMetrics());
- textView.setMovementMethod(new LinkMovementMethod());
- textView.setPadding(padding, 0, padding, 0);
+ int padding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, _context.getResources().getDisplayMetrics());
+ scroll.setPadding(padding, 0, padding, 0);
+ scroll.addView(textView);
+ textView.setMovementMethod(new LinkMovementMethod());
textView.setText(isHtml ? new SpannableString(Html.fromHtml(text)) : text);
+
AlertDialog.Builder dialog = new AlertDialog.Builder(_context)
- .setPositiveButton(android.R.string.ok, null)
- .setOnDismissListener(dismissedListener)
- .setTitle(resTitleId)
- .setView(textView);
+ .setPositiveButton(android.R.string.ok, null).setOnDismissListener(dismissedListener)
+ .setTitle(resTitleId).setView(scroll);
dialog.show();
}
@@ -164,7 +165,7 @@ public class ActivityUtils extends net.gsantner.opoc.util.ContextUtils {
_activity.startActivity(goToMarket);
} catch (ActivityNotFoundException e) {
_activity.startActivity(new Intent(Intent.ACTION_VIEW,
- Uri.parse("http://play.google.com/store/apps/" + pkgId)));
+ Uri.parse("https://play.google.com/store/apps/" + pkgId)));
}
}
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 ed90becb..8e7fae98 100644
--- a/app/src/main/java/net/gsantner/opoc/util/ContextUtils.java
+++ b/app/src/main/java/net/gsantner/opoc/util/ContextUtils.java
@@ -15,6 +15,7 @@ import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
@@ -37,6 +38,7 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
+import android.os.SystemClock;
import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
@@ -47,6 +49,7 @@ import android.support.graphics.drawable.VectorDrawableCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.text.Html;
+import android.text.InputFilter;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
@@ -55,6 +58,9 @@ import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.webkit.MimeTypeMap;
import android.widget.ImageView;
import android.widget.TextView;
@@ -67,6 +73,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
+import java.text.SimpleDateFormat;
import java.util.Locale;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -235,7 +242,7 @@ public class ContextUtils {
* Get this apps package name, returns the flavor specific package name.
*/
public String getPackageIdReal() {
- return _context.getPackageName();
+ return _context.getPackageName();
}
/**
@@ -509,6 +516,17 @@ public class ContextUtils {
return dp * _context.getResources().getDisplayMetrics().density;
}
+ /**
+ * Get the private directory for the current package (usually /data/data/package.name/)
+ */
+ public String getAppDataDir() {
+ try {
+ return _context.getPackageManager().getPackageInfo(getPackageIdReal(), 0).applicationInfo.dataDir;
+ } catch (PackageManager.NameNotFoundException e) {
+ return _context.getFilesDir().getParent();
+ }
+ }
+
/**
* Request the givens paths to be scanned by MediaScanner
*
@@ -694,9 +712,13 @@ public class ContextUtils {
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);
- if (item.hasSubMenu() && recurse) {
- tintMenuItems(item.getSubMenu(), recurse, iconColor);
+ try {
+ tintDrawable(item.getIcon(), iconColor);
+ if (item.hasSubMenu() && recurse) {
+ tintMenuItems(item.getSubMenu(), recurse, iconColor);
+ }
+ } catch (Exception ignored) {
+ // This should not happen at all, but may in bad menu.xml configuration
}
}
}
@@ -734,4 +756,104 @@ public class ContextUtils {
}
}
}
+
+
+ public String getLocalizedDateFormat() {
+ return ((SimpleDateFormat) android.text.format.DateFormat.getDateFormat(_context)).toPattern();
+ }
+
+ public String getLocalizedTimeFormat() {
+ return ((SimpleDateFormat) android.text.format.DateFormat.getTimeFormat(_context)).toPattern();
+ }
+
+ public String getLocalizedDateTimeFormat() {
+ return getLocalizedDateFormat() + " " + getLocalizedTimeFormat();
+ }
+
+ /**
+ * A {@link InputFilter} for filenames
+ */
+ @SuppressWarnings("Convert2Lambda")
+ public static final InputFilter INPUTFILTER_FILENAME = new InputFilter() {
+ public CharSequence filter(CharSequence src, int start, int end, Spanned dest, int dstart, int dend) {
+ if (src.length() < 1) return null;
+ char last = src.charAt(src.length() - 1);
+ String illegal = "|\\?*<\":>+[]/'";
+ if (illegal.indexOf(last) > -1) return src.subSequence(0, src.length() - 1);
+ return null;
+ }
+ };
+
+ /**
+ * A simple {@link Runnable} which does a touch event on a view.
+ * This pops up e.g. the keyboard on a {@link android.widget.EditText}
+ *
+ * Example: new Handler().postDelayed(new DoTouchView(editView), 200);
+ */
+ public static class DoTouchView implements Runnable {
+ View _view;
+
+ public DoTouchView(View view) {
+ _view = view;
+ }
+
+ @Override
+ public void run() {
+ _view.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 0, 0, 0));
+ _view.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 0, 0, 0));
+ }
+ }
+
+
+ public String getMimeType(File file) {
+ return getMimeType(Uri.fromFile(file));
+ }
+
+ /**
+ * Detect MimeType of given file
+ * Android/Java's own MimeType map is very very small and detection barely works at all
+ * Hence use custom map for some file extensions
+ */
+ public String getMimeType(Uri uri) {
+ String mimeType = null;
+ if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
+ ContentResolver cr = _context.getContentResolver();
+ mimeType = cr.getType(uri);
+ } else {
+ String ext = MimeTypeMap.getFileExtensionFromUrl(uri.toString());
+ mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext.toLowerCase());
+
+ // Try to guess if the recommended methods fail
+ if (TextUtils.isEmpty(mimeType)) {
+ switch (ext) {
+ case "md":
+ case "markdown":
+ case "mkd":
+ case "mdown":
+ case "mkdn":
+ case "mdwn":
+ case "rmd":
+ mimeType = "text/markdown";
+ break;
+ case "yaml":
+ case "yml":
+ mimeType = "text/yaml";
+ break;
+ case "json":
+ mimeType = "text/json";
+ break;
+ case "txt":
+ mimeType = "text/plain";
+ break;
+ }
+ }
+ }
+
+ if (TextUtils.isEmpty(mimeType)) {
+ mimeType = "*/*";
+ }
+ return mimeType;
+ }
}
+
+
diff --git a/app/src/main/java/net/gsantner/opoc/util/ShareUtil.java b/app/src/main/java/net/gsantner/opoc/util/ShareUtil.java
index 4b4368cf..13c2589c 100644
--- a/app/src/main/java/net/gsantner/opoc/util/ShareUtil.java
+++ b/app/src/main/java/net/gsantner/opoc/util/ShareUtil.java
@@ -11,6 +11,7 @@
package net.gsantner.opoc.util;
import android.app.Activity;
+import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.Context;
@@ -210,7 +211,7 @@ public class ShareUtil {
/**
* Start calendar application to add new event, with given details prefilled
*/
- public void createCalendarAppointment(@Nullable String title, @Nullable String description, @Nullable String location, @Nullable Long... startAndEndTime) {
+ public boolean createCalendarAppointment(@Nullable String title, @Nullable String description, @Nullable String location, @Nullable Long... startAndEndTime) {
Intent intent = new Intent(Intent.ACTION_INSERT).setData(CalendarContract.Events.CONTENT_URI);
if (title != null) {
intent.putExtra(CalendarContract.Events.TITLE, title);
@@ -230,7 +231,13 @@ public class ShareUtil {
intent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, startAndEndTime[1]);
}
}
- _context.startActivity(intent);
+
+ try {
+ _context.startActivity(intent);
+ return true;
+ } catch (ActivityNotFoundException e) {
+ return false;
+ }
}
/**
@@ -762,4 +769,57 @@ public class ShareUtil {
}
return null;
}
+
+ /**
+ * By default Chrome Custom Tabs only uses Chrome Stable to open links
+ * There are also other packages (like Chrome Beta, Chromium, Firefox, ..)
+ * which implement the Chrome Custom Tab interface. This method changes
+ * the customtab intent to use an available compatible browser, if available.
+ */
+ public void enableChromeCustomTabsForOtherBrowsers(Intent customTabIntent) {
+ String[] checkpkgs = new String[]{
+ "com.android.chrome", "com.chrome.beta", "com.chrome.dev", "com.google.android.apps.chrome", "org.chromium.chrome",
+ "org.mozilla.fennec_fdroid", "org.mozilla.firefox", "org.mozilla.firefox_beta", "org.mozilla.fennec_aurora",
+ "org.mozilla.klar", "org.mozilla.focus",
+ };
+
+ // Get all intent handlers for web links
+ PackageManager pm = _context.getPackageManager();
+ Intent urlIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.example.com"));
+ List browsers = new ArrayList<>();
+ for (ResolveInfo ri : pm.queryIntentActivities(urlIntent, 0)) {
+ Intent i = new Intent("android.support.customtabs.action.CustomTabsService");
+ i.setPackage(ri.activityInfo.packageName);
+ if (pm.resolveService(i, 0) != null) {
+ browsers.add(ri.activityInfo.packageName);
+ }
+ }
+
+ // Check if the user has a "default browser" selected
+ ResolveInfo ri = pm.resolveActivity(urlIntent, 0);
+ String userDefaultBrowser = (ri == null) ? null : ri.activityInfo.packageName;
+
+ // Select which browser to use out of all installed customtab supporting browsers
+ String pkg = null;
+ if (browsers.isEmpty()) {
+ pkg = null;
+ } else if (browsers.size() == 1) {
+ pkg = browsers.get(0);
+ } else if (!TextUtils.isEmpty(userDefaultBrowser) && browsers.contains(userDefaultBrowser)) {
+ pkg = userDefaultBrowser;
+ } else {
+ for (String checkpkg : checkpkgs) {
+ if (browsers.contains(checkpkg)) {
+ pkg = checkpkg;
+ break;
+ }
+ }
+ if (pkg == null && !browsers.isEmpty()) {
+ pkg = browsers.get(0);
+ }
+ }
+ if (pkg != null && customTabIntent != null) {
+ customTabIntent.setPackage(pkg);
+ }
+ }
}
diff --git a/build.gradle b/build.gradle
index 937b7fc1..25e4f2b8 100644
--- a/build.gradle
+++ b/build.gradle
@@ -7,37 +7,40 @@
* https://www.apache.org/licenses/LICENSE-2.0
*
#########################################################*/
-import java.text.SimpleDateFormat
-
// Top-level build file where you can add configuration options common to all sub-projects/modules.
-buildscript {
- ext.version_setup_compileSdk = 27
- ext.version_setup_minSdk = 17
- ext.version_setup_targetSdk = ext.version_setup_compileSdk
- ext.version_setup_buildTools = "27.0.3" // Specifying optional
+import java.text.SimpleDateFormat
- // https://developer.android.com/studio/releases/gradle-plugin.html
- ext.version_gradle_tools = "3.1.0"
- // https://developer.android.com/topic/libraries/support-library/revisions.html
- ext.version_library_appcompat = "27.1.1"
- // https://github.com/JakeWharton/butterknife/releases
- ext.version_library_butterknife = "8.8.1"
- // 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
- ext.version_plugin_kotlin = "1.2.21"
- ext.enable_plugin_kotlin = false
+buildscript {
+ ext {
+ version_gradle_tools = "3.2.1"
+ version_plugin_kotlin = "1.3.11"
+ enable_plugin_kotlin = false
+
+ version_compileSdk = 28
+ version_buildTools = "28.0.3"
+ version_minSdk = 17
+
+ // https://developer.android.com/topic/libraries/support-library/
+ version_library_appcompat = "28.0.0" //androidx
+ // https://github.com/JakeWharton/butterknife/releases
+ version_library_butterknife = "8.8.1" //9.0.0-rc2
+ // https://github.com/guardianproject/NetCipher/releases
+ version_library_netcipher = "2.0.0-alpha1"
+ }
repositories {
- google()
+ maven { url 'https://maven.google.com' }
jcenter()
+ maven { url "https://jitpack.io" }
+ mavenCentral()
}
+
dependencies {
- classpath "com.android.tools.build:gradle:$version_gradle_tools"
- classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
+ classpath "com.android.tools.build:gradle:${version_gradle_tools}"
+ classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
if (project.enable_plugin_kotlin) {
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$version_plugin_kotlin"
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${version_plugin_kotlin}"
}
// NOTE: Do not place your application dependencies here; they belong
@@ -47,10 +50,10 @@ buildscript {
allprojects {
repositories {
- google()
+ maven { url 'https://maven.google.com' }
jcenter()
- mavenCentral()
maven { url "https://jitpack.io" }
+ mavenCentral()
}
tasks.matching { task -> task.name.matches('.*generate.*Resources') }.all {
@@ -99,6 +102,7 @@ ext.getGitHash = { ->
return 'unknown'
}
}
+
@SuppressWarnings(["UnnecessaryQualifiedReference", "SpellCheckingInspection", "GroovyUnusedDeclaration"])
// Returns the build date in a RFC3339 compatible format. TZ is always converted to UTC
static String getBuildDate() {
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 18a0cf95..0682df5e 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,5 @@
-#Sun Apr 08 08:39:15 CEST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip
From b833311353179d867dff963479674ccc74f1d6c0 Mon Sep 17 00:00:00 2001
From: Gregor Santner
Date: Fri, 11 Jan 2019 02:43:53 +0100
Subject: [PATCH 7/7] Release v1.2.5
---
CHANGELOG.md | 3 +++
app/build.gradle | 4 ++--
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 70f0600b..f6049f2d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,6 @@
+### v1.2.5
+Make youtube links open external/in youtube app (optional)
+
### v1.2.3
**Improved:**
- More supported languages, more complete translations!
diff --git a/app/build.gradle b/app/build.gradle
index beab3f7e..e0565339 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.2.3"
- versionCode 36
+ versionName "1.2.5"
+ versionCode 40
vectorDrawables.useSupportLibrary = true
}