From 8503507828cc2e05266cef05cb94441a8955ede6 Mon Sep 17 00:00:00 2001 From: Roi Date: Tue, 21 Aug 2018 21:27:00 +0300 Subject: [PATCH] Add rtl support --- .../gadgetbridge/impl/GBDeviceService.java | 8 + .../huami/amazfitbip/AmazfitBipSupport.java | 7 + .../gadgetbridge/util/LanguageUtils.java | 175 ++++++++++++++++++ .../gadgetbridge/util/StringUtils.java | 7 +- app/src/main/res/values/strings.xml | 6 + app/src/main/res/xml/preferences.xml | 24 ++- build.gradle | 2 +- 7 files changed, 223 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java index a2589679b..07078baf9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java @@ -81,6 +81,14 @@ public class GBDeviceService implements DeviceService { } } + if (LanguageUtils.rtlSupport()) { + for (String extra : transliterationExtras) { + if (intent.hasExtra(extra)) { + intent.putExtra(extra, LanguageUtils.fixRtl(intent.getStringExtra(extra))); + } + } + } + mContext.startService(intent); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/AmazfitBipSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/AmazfitBipSupport.java index 58d9270d3..dd615a883 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/AmazfitBipSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/AmazfitBipSupport.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.net.Uri; +import android.util.Log; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -58,6 +59,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitbip.ope import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.FetchActivityOperation; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.FetchSportsSummaryOperation; import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.NotificationStrategy; +import nodomain.freeyourgadget.gadgetbridge.util.LanguageUtils; import nodomain.freeyourgadget.gadgetbridge.util.Prefs; import nodomain.freeyourgadget.gadgetbridge.util.StringUtils; import nodomain.freeyourgadget.gadgetbridge.util.Version; @@ -85,13 +87,18 @@ public class AmazfitBipSupport extends HuamiSupport { String senderOrTiltle = StringUtils.getFirstOf(notificationSpec.sender, notificationSpec.title); String message = StringUtils.truncate(senderOrTiltle, 32) + "\0"; + Log.d("ROIGR", "senderOrTiltle: " + senderOrTiltle); if (notificationSpec.subject != null) { message += StringUtils.truncate(notificationSpec.subject, 128) + "\n\n"; + Log.d("ROIGR", "subject: " + notificationSpec.subject); } if (notificationSpec.body != null) { message += StringUtils.truncate(notificationSpec.body, 128); + Log.d("ROIGR", "body: " + notificationSpec.body); } +// message = LanguageUtils.fixRtl(message, message.length()); + try { TransactionBuilder builder = performInitialized("new notification"); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/LanguageUtils.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/LanguageUtils.java index 808848eb1..134cab59a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/LanguageUtils.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/LanguageUtils.java @@ -17,11 +17,19 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.util; +import android.text.TextUtils; +import android.util.Log; +import android.util.Pair; + import org.apache.commons.lang3.text.WordUtils; import java.text.Normalizer; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Set; import nodomain.freeyourgadget.gadgetbridge.GBApplication; @@ -150,4 +158,171 @@ public class LanguageUtils { string = Normalizer.normalize(string, Normalizer.Form.NFD); return string.replaceAll("\\p{M}", ""); } + + /** + * Checks the status of transliteration option + * @return true if transliterate option is On, and false, if Off or not exist + */ + public static boolean rtlSupport() + { + return GBApplication.getPrefs().getBoolean("rtl", false); + } + + //transliteration map with english equivalent for unsupported chars + private static Map directionSignsMap = new HashMap(){ + { + put('(', ')'); put(')', '('); put('[', ']'); put(']', '['); put('{','}'); put('}','{'); + + + } + }; + + //transliteration map with english equivalent for unsupported chars + private static ArrayList > rtlRange = new ArrayList>() { + { + add(new Pair('\u0590', '\u05F4')); + add(new Pair('\uFB1D', '\uFB4F')); + add(new Pair('\u0600', '\u06FF')); + add(new Pair('\u0750', '\u077F')); + add(new Pair('\u08A0', '\u08FF')); + add(new Pair('\uFB50', '\uFDFF')); + add(new Pair('\uFE70', '\uFEFF')); + } + }; + + private static Boolean isRtl(char c){ + for (Pair rang: rtlRange) { + if (rang.first <= c && c <= rang.second) { + return true; + } + } + return false; + } + + private static ArrayList > stsRange = new ArrayList>() { + { + add(new Pair('\u0021', '\u002F')); + add(new Pair('\u003A', '\u0040')); + add(new Pair('\u005B', '\u0060')); + add(new Pair('\u007B', '\u007E')); + } + }; + + private static Boolean isSts(char c){ + for (Pair rang: stsRange) { + if (rang.first <= c && c <= rang.second) { + return true; + } + } + return false; + } + + private static ArrayList endSigns = new ArrayList() { + { + add('\0'); + add('\n'); + add(' '); + } + }; + + private static Boolean isEndSign(char c){ + for (char sign: endSigns){ + if (c == sign){ + return true; + } + } + + return false; + } + + private static String reverse(String a) { + int j = a.length(); + int startWithSpace = 0; + char[] newWord = new char[j]; + + if (j == 0) { + return a; + } + + if (isEndSign(a.charAt(a.length() - 1))){ + startWithSpace = 1; + newWord[--j] = a.charAt(a.length() - 1); + } + + for (int i = 0; i < a.length() - startWithSpace; i++) { + if (LanguageUtils.directionSignsMap.containsKey(a.charAt(i))) { + newWord[--j] = LanguageUtils.directionSignsMap.get(a.charAt(i)); + } else { + newWord[--j] = a.charAt(i); + } + } + return new String(newWord); + } + + public static String fixRtl(String s) { + if (s == null || s.isEmpty()){ + return s; + } + int length = s.length(); + String oldString = s.substring(0, length); + String newString = ""; + List lines = new ArrayList<>(); + char[] newWord = new char[length]; + int line_max_size = GBApplication.getPrefs().getInt("rtl_max_line_length", 20);; + + int startPos = 0; + int endPos = 0; + Boolean isRtlState = LanguageUtils.isRtl(oldString.charAt(0)); + char c; + String line = ""; + for (int i = 0; i < length; i++) { + c = oldString.charAt(i); + Log.d("ROIGR", String.format("%s: i %x i", c, (int) c)); + if ((LanguageUtils.isRtl(c) == isRtlState || LanguageUtils.isSts(c)) && i < length - 1) { + endPos++; + } else { + String word; + + if (isEndSign(c)){ + endPos++; + } + + if (i == length - 1){ + endPos = length; + } + if (isRtlState) { + word = reverse(oldString.substring(startPos, endPos)); + } else { + word = (oldString.substring(startPos, endPos)); + } + Log.d("ROIGR", String.format("|%s| is now |%s|", oldString.substring(startPos, endPos), word)); + if (line.length() + word.length() > line_max_size) { + lines.add(line + "\n"); + line = ""; + } + line = String.format("%s%s", word, line); + if (line.endsWith("\0") || line.endsWith("\n")) { + lines.add(line); + line = ""; + } + startPos = endPos; + if (!isEndSign(c)){ + endPos++; + isRtlState = !isRtlState; + } + } + } + + lines.add(line); + + newString = TextUtils.join("", lines); + Log.d("ROIGR", "lines:\n\n" + lines); + Log.d("ROIGR", "final messege:\n\n" + newString); +// if (LanguageUtils.isRtl(s.charAt(0))){ +// newString = reverse(s); +// } else { +// newString = s; +// } + return newString; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/StringUtils.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/StringUtils.java index 641773a4c..e362eee8b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/StringUtils.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/StringUtils.java @@ -17,9 +17,14 @@ package nodomain.freeyourgadget.gadgetbridge.util; import android.support.annotation.NonNull; +import android.util.Log; + +import java.util.ArrayList; public class StringUtils { + + @NonNull public static String truncate(String s, int maxLength){ if (s == null) { @@ -27,7 +32,7 @@ public class StringUtils { } int length = Math.min(s.length(), maxLength); - if(length < 0) { + if(length <= 0) { return ""; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b0e9ca866..0c23712e2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -103,6 +103,11 @@ Transliteration Enable this if your device has no support for your language\'s font + Right-To-Left + Enable this if your device has no support in right-to-left languages + Right-To-Left Max Line Length + When Right-To-Left is enable, the text is separated to lines. Change tjis value if the lines are to long/short. + Always When screen is off Never @@ -616,4 +621,5 @@ Calibrate Watch 9 pairing Watch 9 calibration + diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index f63e066af..ec55146a8 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -155,14 +155,30 @@ android:key="notifications_generic_whenscreenon" android:title="@string/pref_title_whenscreenon" /> + + + + diff --git a/build.gradle b/build.gradle index ea23aab55..a29379cb8 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.4' + classpath 'com.android.tools.build:gradle:3.2.0-beta05' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files