1
0
Fork 0
mirror of https://github.com/gsantner/dandelion synced 2024-11-26 06:12:08 +01:00

Compare commits

...

5 commits

Author SHA1 Message Date
Gregor Santner
88a4bd75b7 [ci skip] Crowdin translation bot: New translations for Sinhala 2021-02-28 22:52:54 +01:00
Gregor Santner
b15c39b35b [ci skip] Crowdin translation bot: New translations for Sinhala 2021-02-28 22:11:24 +01:00
Gregor Santner
c9c10a6fd4
Add language Sinhala (Sri Lanka) 2021-02-28 22:09:03 +01:00
Gregor Santner
e5866ffb2b
Update opoc 2021-01-18 21:32:50 +01:00
Gregor Santner
97d9bf434e
Various additions & improvements to opoc utils 2021-01-12 20:23:10 +01:00
9 changed files with 212 additions and 57 deletions

View file

@ -26,6 +26,7 @@ import android.support.design.widget.Snackbar;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.support.v7.widget.AppCompatEditText; import android.support.v7.widget.AppCompatEditText;
import android.text.Editable; import android.text.Editable;
import android.text.InputType;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.TextUtils; import android.text.TextUtils;
@ -75,7 +76,7 @@ public class SearchOrCustomTextDialog {
public int dialogWidthDp = WindowManager.LayoutParams.MATCH_PARENT; public int dialogWidthDp = WindowManager.LayoutParams.MATCH_PARENT;
public int dialogHeightDp = WindowManager.LayoutParams.WRAP_CONTENT; public int dialogHeightDp = WindowManager.LayoutParams.WRAP_CONTENT;
public int gravity = Gravity.NO_GRAVITY; public int gravity = Gravity.NO_GRAVITY;
public int searchInputType = 0; public int searchInputType = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
public boolean searchIsRegex = false; public boolean searchIsRegex = false;
public Callback.a1<Spannable> highlighter; public Callback.a1<Spannable> highlighter;
public String extraFilter = null; public String extraFilter = null;
@ -99,21 +100,20 @@ public class SearchOrCustomTextDialog {
} }
private static class WithPositionAdapter extends ArrayAdapter<Pair<String, Integer>> { private static class WithPositionAdapter extends ArrayAdapter<Pair<String, Integer>> {
@LayoutRes
final int _layout;
final LayoutInflater _inflater;
final DialogOptions _dopt;
final List<Pair<String, Integer>> _filteredItems;
final Pattern _extraPattern;
final LayoutInflater mInflater; WithPositionAdapter(Context c_context, @LayoutRes int c_layout, List<Pair<String, Integer>> c_filteredItems, DialogOptions c_dopt) {
final @LayoutRes super(c_context, c_layout, c_filteredItems);
int mLayout; _inflater = LayoutInflater.from(c_context);
final DialogOptions dopt; _layout = c_layout;
final List<Pair<String, Integer>> filteredItems; _dopt = c_dopt;
final Pattern extraPattern; _filteredItems = c_filteredItems;
_extraPattern = (c_dopt.extraFilter == null ? null : Pattern.compile(c_dopt.extraFilter));
WithPositionAdapter(Context context, @LayoutRes int layout, List<Pair<String, Integer>> filteredItems, DialogOptions dopt) {
super(context, layout, filteredItems);
mInflater = LayoutInflater.from(context);
mLayout = layout;
this.dopt = dopt;
this.filteredItems = filteredItems;
extraPattern = dopt.extraFilter == null ? null : Pattern.compile(dopt.extraFilter);
} }
@NonNull @NonNull
@ -125,30 +125,30 @@ public class SearchOrCustomTextDialog {
final TextView textView; final TextView textView;
if (convertView == null) { if (convertView == null) {
textView = (TextView) mInflater.inflate(mLayout, parent, false); textView = (TextView) _inflater.inflate(_layout, parent, false);
} else { } else {
textView = (TextView) convertView; textView = (TextView) convertView;
} }
if (posInOriginalList >= 0 && dopt.iconsForData != null && posInOriginalList < dopt.iconsForData.size() && dopt.iconsForData.get(posInOriginalList) != 0) { if (posInOriginalList >= 0 && _dopt.iconsForData != null && posInOriginalList < _dopt.iconsForData.size() && _dopt.iconsForData.get(posInOriginalList) != 0) {
textView.setCompoundDrawablesWithIntrinsicBounds(dopt.iconsForData.get(posInOriginalList), 0, 0, 0); textView.setCompoundDrawablesWithIntrinsicBounds(_dopt.iconsForData.get(posInOriginalList), 0, 0, 0);
textView.setCompoundDrawablePadding(32); textView.setCompoundDrawablePadding(32);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
textView.setCompoundDrawableTintList(ColorStateList.valueOf(dopt.isDarkDialog ? Color.WHITE : Color.BLACK)); textView.setCompoundDrawableTintList(ColorStateList.valueOf(_dopt.isDarkDialog ? Color.WHITE : Color.BLACK));
} }
} else { } else {
textView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); textView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
} }
if (dopt.highlightData != null) { if (_dopt.highlightData != null) {
final boolean hl = dopt.highlightData.contains(text); final boolean hl = _dopt.highlightData.contains(text);
textView.setTextColor(hl ? dopt.highlightColor : dopt.textColor); textView.setTextColor(hl ? _dopt.highlightColor : _dopt.textColor);
textView.setTypeface(null, hl ? Typeface.BOLD : Typeface.NORMAL); textView.setTypeface(null, hl ? Typeface.BOLD : Typeface.NORMAL);
} }
if (dopt.highlighter != null) { if (_dopt.highlighter != null) {
Spannable s = new SpannableString(text); Spannable s = new SpannableString(text);
dopt.highlighter.callback(s); _dopt.highlighter.callback(s);
textView.setText(s); textView.setText(s);
} else { } else {
textView.setText(text); textView.setText(text);
@ -163,8 +163,8 @@ public class SearchOrCustomTextDialog {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
protected void publishResults(final CharSequence constraint, final FilterResults results) { protected void publishResults(final CharSequence constraint, final FilterResults results) {
filteredItems.clear(); _filteredItems.clear();
filteredItems.addAll((List<Pair<String, Integer>>) results.values); _filteredItems.addAll((List<Pair<String, Integer>>) results.values);
notifyDataSetChanged(); notifyDataSetChanged();
} }
@ -172,14 +172,14 @@ public class SearchOrCustomTextDialog {
protected FilterResults performFiltering(final CharSequence constraint) { protected FilterResults performFiltering(final CharSequence constraint) {
final ArrayList<Pair<CharSequence, Integer>> resList = new ArrayList<>(); final ArrayList<Pair<CharSequence, Integer>> resList = new ArrayList<>();
if (dopt.data != null) { if (_dopt.data != null) {
final String fil = constraint.toString(); final String fil = constraint.toString();
final boolean emptySearch = fil.isEmpty(); final boolean emptySearch = fil.isEmpty();
for (int i = 0; i < dopt.data.size(); i++) { for (int i = 0; i < _dopt.data.size(); i++) {
final CharSequence str = dopt.data.get(i); final CharSequence str = _dopt.data.get(i);
final boolean matchExtra = (extraPattern == null) || extraPattern.matcher(str).find(); final boolean matchExtra = (_extraPattern == null) || _extraPattern.matcher(str).find();
final boolean matchNormal = str.toString().toLowerCase(Locale.getDefault()).contains(fil.toLowerCase(Locale.getDefault())); final boolean matchNormal = str.toString().toLowerCase(Locale.getDefault()).contains(fil.toLowerCase(Locale.getDefault()));
final boolean matchRegex = dopt.searchIsRegex && (str.toString().matches(fil)); final boolean matchRegex = _dopt.searchIsRegex && (str.toString().matches(fil));
if (matchExtra && (matchNormal || matchRegex || emptySearch)) { if (matchExtra && (matchNormal || matchRegex || emptySearch)) {
resList.add(new Pair<>(str, i)); resList.add(new Pair<>(str, i));
} }

View file

@ -11,6 +11,7 @@
package net.gsantner.opoc.util; package net.gsantner.opoc.util;
import android.app.Activity; import android.app.Activity;
import android.app.ActivityManager;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
@ -38,8 +39,10 @@ import android.view.inputmethod.InputMethodManager;
import android.webkit.WebView; import android.webkit.WebView;
import android.widget.ScrollView; import android.widget.ScrollView;
import java.util.List;
@SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue", "SpellCheckingInspection"})
@SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue", "SpellCheckingInspection", "rawtypes", "UnusedReturnValue"})
public class ActivityUtils extends net.gsantner.opoc.util.ContextUtils { public class ActivityUtils extends net.gsantner.opoc.util.ContextUtils {
//######################## //########################
//## Members, Constructors //## Members, Constructors
@ -239,13 +242,22 @@ public class ActivityUtils extends net.gsantner.opoc.util.ContextUtils {
} }
public ActivityUtils setLauncherActivityEnabled(Class activityClass, boolean enable) { public ActivityUtils setLauncherActivityEnabled(Class activityClass, boolean enable) {
Context context = _context.getApplicationContext(); try {
PackageManager pkg = context.getPackageManager(); ComponentName component = new ComponentName(_context, activityClass);
ComponentName component = new ComponentName(context, activityClass); _context.getPackageManager().setComponentEnabledSetting(component, enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
pkg.setComponentEnabledSetting(component, enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); } catch (Exception ignored) {
}
return this; return this;
} }
public boolean isLauncherEnabled(Class activityClass) {
try {
ComponentName component = new ComponentName(_context, activityClass);
return _context.getPackageManager().getComponentEnabledSetting(component) != PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
} catch (Exception ignored) {
}
return false;
}
@ColorInt @ColorInt
public Integer getCurrentPrimaryColor() { public Integer getCurrentPrimaryColor() {
@ -316,4 +328,20 @@ public class ActivityUtils extends net.gsantner.opoc.util.ContextUtils {
} catch (Exception ignored) { } catch (Exception ignored) {
} }
} }
// Make activity/app not show up in the recents history - call before finish / System.exit
public ActivityUtils removeActivityFromHistory() {
try {
ActivityManager am = (ActivityManager) _activity.getSystemService(Context.ACTIVITY_SERVICE);
if (am != null && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
List<ActivityManager.AppTask> tasks = am.getAppTasks();
if (tasks != null && !tasks.isEmpty()) {
tasks.get(0).setExcludeFromRecents(true);
}
}
} catch (Exception ignored) {
}
return this;
}
} }

View file

@ -46,8 +46,9 @@ import java.util.Set;
/** /**
* Simple Host-Based AdBlocker * Simple Host-Based AdBlocker
*/ */
@SuppressWarnings({"WeakerAccess", "SpellCheckingInspection", "unused"}) @SuppressWarnings({"WeakerAccess", "SpellCheckingInspection", "unused", "TryFinallyCanBeTryWithResources"})
public class AdBlock { public class AdBlock {
private static final Object synchronizeObj = new Object();
private static final AdBlock instance = new AdBlock(); private static final AdBlock instance = new AdBlock();
public static AdBlock getInstance() { public static AdBlock getInstance() {
@ -61,7 +62,9 @@ public class AdBlock {
//######################## //########################
private final Set<String> _adblockHostsFromRaw = new HashSet<>(); private final Set<String> _adblockHostsFromRaw = new HashSet<>();
private final Set<String> _adblockHosts = new HashSet<>(); private final Set<String> _adblockHosts = new HashSet<>();
private boolean _isLoaded; private final List<Callback.b3<URI, String, String>> _customBlockCallbacks = new ArrayList<>();
private boolean _isLoaded = false;
private boolean _isAdblockLogging = false;
//######################## //########################
//## //##
@ -72,25 +75,47 @@ public class AdBlock {
} }
public boolean isAdHost(String urlS) { public boolean isAdHost(String urlS) {
boolean block = false;
if (urlS != null && !urlS.isEmpty() && urlS.startsWith("http")) { if (urlS != null && !urlS.isEmpty() && urlS.startsWith("http")) {
try { try {
URI url = new URI(urlS); URI url;
try {
url = new URI(urlS);
} catch (Exception e) {
url = new URI(urlS.replaceFirst("[?].*", ""));
}
String host = url.getHost().trim(); String host = url.getHost().trim();
if (host.startsWith("www.") && host.length() >= 4) { if (host.startsWith("www.") && host.length() >= 4) {
host = host.substring(4); host = host.substring(4);
} }
return _adblockHosts.contains(host) || _adblockHosts.contains("www." + host); block = _adblockHosts.contains(host) || _adblockHosts.contains("www." + host);
for (Callback.b3<URI, String, String> cb : _customBlockCallbacks) {
if (block) {
break;
}
try {
block = cb.callback(url, urlS, host);
} catch (Exception ignored) {
}
}
} catch (URISyntaxException e) { } catch (URISyntaxException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
return false;
if (_isAdblockLogging) {
Log.d(getClass().getSimpleName(), "UrlAllowed-" + (block ? "N" : "Y") + " " + urlS);
}
return block;
} }
public AdBlock reset() { public AdBlock reset() {
_adblockHosts.clear(); synchronized (synchronizeObj) {
_adblockHosts.addAll(_adblockHostsFromRaw); _adblockHosts.clear();
_adblockHosts.addAll(_adblockHostsFromRaw);
_customBlockCallbacks.clear();
}
return this; return this;
} }
@ -102,7 +127,7 @@ public class AdBlock {
return new WebResourceResponse("text/plain", "utf-8", new ByteArrayInputStream("".getBytes())); return new WebResourceResponse("text/plain", "utf-8", new ByteArrayInputStream("".getBytes()));
} }
public void addBlockedHosts(String... hosts) { public AdBlock addBlockedHosts(String... hosts) {
for (String host : hosts) { for (String host : hosts) {
if (host != null) { if (host != null) {
host = host.trim(); host = host.trim();
@ -110,23 +135,29 @@ public class AdBlock {
host = host.substring(4); host = host.substring(4);
} }
if (!host.startsWith("#") && !host.startsWith("\"")) { if (!host.startsWith("#") && !host.startsWith("\"")) {
_adblockHosts.add(host); synchronized (synchronizeObj) {
_adblockHosts.add(host);
}
} }
} }
} }
return this;
} }
public void loadHostsFromRawAssetsAsync(final Context context) { public void loadHostsFromRawAssetsAsync(final Context context, final boolean... debugIgnoreAssets) {
new Thread(new Runnable() { if (debugIgnoreAssets != null && debugIgnoreAssets.length > 0 && debugIgnoreAssets[0]) {
@Override _isLoaded = true;
public void run() { return;
try { }
new Thread(() -> {
try {
synchronized (synchronizeObj) {
loadHostsFromRawAssets(context); loadHostsFromRawAssets(context);
_isLoaded = true; _isLoaded = true;
} catch (IOException e) {
e.printStackTrace();
} }
} catch (IOException e) {
e.printStackTrace();
} }
}).start(); }).start();
} }
@ -172,4 +203,17 @@ public class AdBlock {
} }
return adblockResIds; return adblockResIds;
} }
// URI uri, String url, String host
public AdBlock addCustomBlockCallback(Callback.b3<URI, String, String> cb) {
synchronized (synchronizeObj) {
_customBlockCallbacks.add(cb);
}
return this;
}
public AdBlock setLogEnabled(boolean isAdblockLogging) {
_isAdblockLogging = isAdblockLogging;
return this;
}
} }

View file

@ -67,7 +67,9 @@ import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.Surface;
import android.view.View; import android.view.View;
import android.view.WindowManager;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
@ -90,7 +92,7 @@ import static android.content.Context.VIBRATOR_SERVICE;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.graphics.Bitmap.CompressFormat; import static android.graphics.Bitmap.CompressFormat;
@SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue", "ObsoleteSdkInt", "deprecation", "SpellCheckingInspection", "TryFinallyCanBeTryWithResources", "UnusedAssignment"}) @SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue", "ObsoleteSdkInt", "deprecation", "SpellCheckingInspection", "TryFinallyCanBeTryWithResources", "UnusedAssignment", "UnusedReturnValue"})
public class ContextUtils { public class ContextUtils {
// //
// Members, Constructors // Members, Constructors
@ -257,7 +259,7 @@ public class ContextUtils {
* Send a {@link Intent#ACTION_VIEW} Intent with given paramter * Send a {@link Intent#ACTION_VIEW} Intent with given paramter
* If the parameter is an string a browser will get triggered * If the parameter is an string a browser will get triggered
*/ */
public void openWebpageInExternalBrowser(final String url) { public ContextUtils openWebpageInExternalBrowser(final String url) {
try { try {
Uri uri = Uri.parse(url); Uri uri = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, uri); Intent intent = new Intent(Intent.ACTION_VIEW, uri);
@ -266,6 +268,7 @@ public class ContextUtils {
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
return this;
} }
/** /**
@ -1011,6 +1014,25 @@ public class ContextUtils {
vibrator.vibrate(ms_v); vibrator.vibrate(ms_v);
} }
} }
/*
Check if Wifi is connected. Requires these permissions in AndroidManifest:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
*/
@SuppressLint("MissingPermission")
public boolean isWifiConnected(boolean... enabledOnly) {
final boolean doEnabledCheckOnly = enabledOnly != null && enabledOnly.length > 0 && enabledOnly[0];
final ConnectivityManager connectivityManager = (ConnectivityManager) _context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo wifiInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return wifiInfo != null && (doEnabledCheckOnly ? wifiInfo.isAvailable() : wifiInfo.isConnected());
}
// Returns if the device is currently in portrait orientation (landscape=false)
public boolean isDeviceOrientationPortrait() {
final int rotation = ((WindowManager) _context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getOrientation();
return (rotation == Surface.ROTATION_0) || (rotation == Surface.ROTATION_180);
}
} }

View file

@ -501,4 +501,11 @@ public class FileUtils {
return String.format(Locale.getDefault(), "%.2f%s", (bytes / 1000000000f), "TB"); return String.format(Locale.getDefault(), "%.2f%s", (bytes / 1000000000f), "TB");
} }
} }
public static File join(File file, String... childSegments) {
for (final String s : childSegments != null ? childSegments : new String[0]) {
file = new File(file, s);
}
return file;
}
} }

View file

@ -24,7 +24,6 @@ import java.net.URL;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -222,4 +221,14 @@ public class NetworkUtils {
return result; return result;
} }
public static void httpGetAsync(final String url, final Callback.a1<String> callback) {
new Thread(() -> {
try {
String c = NetworkUtils.performCall(url, GET);
callback.callback(c);
} catch (Exception ignored) {
}
}).start();
}
} }

View file

@ -1148,7 +1148,7 @@ public class ShareUtil {
if (isDirectory) { if (isDirectory) {
// Nothing to do // Nothing to do
} else { } else {
pfd = _context.getContentResolver().openFileDescriptor(dof.getUri(), "rw"); pfd = _context.getContentResolver().openFileDescriptor(dof.getUri(), "rwt");
fileOutputStream = new FileOutputStream(pfd.getFileDescriptor()); fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
} }
} }

View file

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Application -->
<string name="close">වසන්න</string>
<string name="cancel">අවලංගු</string>
<!-- Common Words -->
<string name="settings">සැකසුම්</string>
<string name="notifications">දැනුම්දීම්</string>
<string name="conversations">සංවාද</string>
<string name="profile">පැතිකඩ</string>
<string name="search">සොයන්න</string>
<!-- Notifications dropdown menu -->
<!-- Pod Activity -->
<!-- Drawer, Menu, Toolbar, ContextMenu -->
<!-- More from MainActivity -->
<!-- Permissions -->
<string name="protocol">කෙටුම්පත</string>
<!-- Operability -->
<!-- Category Titles -->
<string name="network">ජාලය</string>
<!-- Visuals -->
<!-- Navigiation Slider -->
<string name="user">පරිශීලක</string>
<!-- Themes -->
<!-- Notifications dropdown -->
<string name="language">භාෂාව</string>
<!-- Font size -->
<string name="normal">සාමාන්‍ය</string>
<!-- Load images -->
<!-- Screen rotation -->
<!-- Proxy -->
<string name="proxy">පෙරකලාසිය</string>
<string name="enable_proxy">පෙරකලාසිය සබල කරන්න</string>
<!-- Chrome custom tabs -->
<!-- Diaspora Settings -->
<string name="change_account">ගිණුම වෙනස් කරන්න</string>
<!-- More -->
<string name="about">පිලිබඳව</string>
<string name="license">බලපත්‍රය</string>
<string name="application">යෙදුම</string>
<string name="device">උපාංගය</string>
<!-- License & help (large amount of text) -->
<string name="donate">පරිත්‍යාග</string>
</resources>

View file

@ -57,4 +57,5 @@ files:
ta: ta # Tamil (Asian) ta: ta # Tamil (Asian)
sq: sq # Albanian sq: sq # Albanian
mk: mk # Macedonian mk: mk # Macedonian
si-LK: si # Sinhala (Sri Lanka)
translate_attributes: 0 translate_attributes: 0