mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-12-01 06:22:55 +01:00
Add rtl support
This commit is contained in:
parent
0e4fb0f5b8
commit
5697ebc8ea
@ -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);
|
mContext.startService(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import android.content.Context;
|
|||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
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.FetchActivityOperation;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.FetchSportsSummaryOperation;
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.FetchSportsSummaryOperation;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.NotificationStrategy;
|
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.Prefs;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.Version;
|
import nodomain.freeyourgadget.gadgetbridge.util.Version;
|
||||||
@ -85,13 +87,18 @@ public class AmazfitBipSupport extends HuamiSupport {
|
|||||||
String senderOrTiltle = StringUtils.getFirstOf(notificationSpec.sender, notificationSpec.title);
|
String senderOrTiltle = StringUtils.getFirstOf(notificationSpec.sender, notificationSpec.title);
|
||||||
|
|
||||||
String message = StringUtils.truncate(senderOrTiltle, 32) + "\0";
|
String message = StringUtils.truncate(senderOrTiltle, 32) + "\0";
|
||||||
|
Log.d("ROIGR", "senderOrTiltle: " + senderOrTiltle);
|
||||||
if (notificationSpec.subject != null) {
|
if (notificationSpec.subject != null) {
|
||||||
message += StringUtils.truncate(notificationSpec.subject, 128) + "\n\n";
|
message += StringUtils.truncate(notificationSpec.subject, 128) + "\n\n";
|
||||||
|
Log.d("ROIGR", "subject: " + notificationSpec.subject);
|
||||||
}
|
}
|
||||||
if (notificationSpec.body != null) {
|
if (notificationSpec.body != null) {
|
||||||
message += StringUtils.truncate(notificationSpec.body, 128);
|
message += StringUtils.truncate(notificationSpec.body, 128);
|
||||||
|
Log.d("ROIGR", "body: " + notificationSpec.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// message = LanguageUtils.fixRtl(message, message.length());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
TransactionBuilder builder = performInitialized("new notification");
|
TransactionBuilder builder = performInitialized("new notification");
|
||||||
|
|
||||||
|
@ -17,11 +17,19 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
package nodomain.freeyourgadget.gadgetbridge.util;
|
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 org.apache.commons.lang3.text.WordUtils;
|
||||||
|
|
||||||
import java.text.Normalizer;
|
import java.text.Normalizer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
|
|
||||||
@ -150,4 +158,171 @@ public class LanguageUtils {
|
|||||||
string = Normalizer.normalize(string, Normalizer.Form.NFD);
|
string = Normalizer.normalize(string, Normalizer.Form.NFD);
|
||||||
return string.replaceAll("\\p{M}", "");
|
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<Character, Character> directionSignsMap = new HashMap<Character, Character>(){
|
||||||
|
{
|
||||||
|
put('(', ')'); put(')', '('); put('[', ']'); put(']', '['); put('{','}'); put('}','{');
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//transliteration map with english equivalent for unsupported chars
|
||||||
|
private static ArrayList <Pair<Character, Character>> rtlRange = new ArrayList<Pair<Character, Character>>() {
|
||||||
|
{
|
||||||
|
add(new Pair<Character, Character>('\u0590', '\u05F4'));
|
||||||
|
add(new Pair<Character, Character>('\uFB1D', '\uFB4F'));
|
||||||
|
add(new Pair<Character, Character>('\u0600', '\u06FF'));
|
||||||
|
add(new Pair<Character, Character>('\u0750', '\u077F'));
|
||||||
|
add(new Pair<Character, Character>('\u08A0', '\u08FF'));
|
||||||
|
add(new Pair<Character, Character>('\uFB50', '\uFDFF'));
|
||||||
|
add(new Pair<Character, Character>('\uFE70', '\uFEFF'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static Boolean isRtl(char c){
|
||||||
|
for (Pair<Character, Character> rang: rtlRange) {
|
||||||
|
if (rang.first <= c && c <= rang.second) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ArrayList <Pair<Character, Character>> stsRange = new ArrayList<Pair<Character, Character>>() {
|
||||||
|
{
|
||||||
|
add(new Pair<Character, Character>('\u0021', '\u002F'));
|
||||||
|
add(new Pair<Character, Character>('\u003A', '\u0040'));
|
||||||
|
add(new Pair<Character, Character>('\u005B', '\u0060'));
|
||||||
|
add(new Pair<Character, Character>('\u007B', '\u007E'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static Boolean isSts(char c){
|
||||||
|
for (Pair<Character, Character> rang: stsRange) {
|
||||||
|
if (rang.first <= c && c <= rang.second) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ArrayList<Character> endSigns = new ArrayList<Character>() {
|
||||||
|
{
|
||||||
|
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<String> 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,14 @@
|
|||||||
package nodomain.freeyourgadget.gadgetbridge.util;
|
package nodomain.freeyourgadget.gadgetbridge.util;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class StringUtils {
|
public class StringUtils {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public static String truncate(String s, int maxLength){
|
public static String truncate(String s, int maxLength){
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
@ -27,7 +32,7 @@ public class StringUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int length = Math.min(s.length(), maxLength);
|
int length = Math.min(s.length(), maxLength);
|
||||||
if(length < 0) {
|
if(length <= 0) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,6 +104,11 @@
|
|||||||
<string name="pref_title_transliteration">Transliteration</string>
|
<string name="pref_title_transliteration">Transliteration</string>
|
||||||
<string name="pref_summary_transliteration">Enable this if your device has no support for your language\'s font</string>
|
<string name="pref_summary_transliteration">Enable this if your device has no support for your language\'s font</string>
|
||||||
|
|
||||||
|
<string name="pref_title_rtl">Right-To-Left</string>
|
||||||
|
<string name="pref_summary_rtl">Enable this if your device has no support in right-to-left languages</string>
|
||||||
|
<string name="pref_rtl_max_line_length">Right-To-Left Max Line Length</string>
|
||||||
|
<string name="pref_rtl_max_line_length_summary">When Right-To-Left is enable, the text is separated to lines. Change tjis value if the lines are to long/short.</string>
|
||||||
|
|
||||||
<string name="always">Always</string>
|
<string name="always">Always</string>
|
||||||
<string name="when_screen_off">When screen is off</string>
|
<string name="when_screen_off">When screen is off</string>
|
||||||
<string name="never">Never</string>
|
<string name="never">Never</string>
|
||||||
@ -626,4 +631,5 @@
|
|||||||
<string name="watch9_calibration_button">Calibrate</string>
|
<string name="watch9_calibration_button">Calibrate</string>
|
||||||
<string name="title_activity_watch9_pairing">Watch 9 pairing</string>
|
<string name="title_activity_watch9_pairing">Watch 9 pairing</string>
|
||||||
<string name="title_activity_watch9_calibration">Watch 9 calibration</string>
|
<string name="title_activity_watch9_calibration">Watch 9 calibration</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -163,14 +163,30 @@
|
|||||||
android:title="@string/pref_title_notifications_timeout"
|
android:title="@string/pref_title_notifications_timeout"
|
||||||
android:summary="%s" />
|
android:summary="%s" />
|
||||||
|
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:layout="@layout/preference_checkbox"
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="transliteration"
|
||||||
|
android:summary="@string/pref_summary_transliteration"
|
||||||
|
android:title="@string/pref_title_transliteration"
|
||||||
|
/>
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:layout="@layout/preference_checkbox"
|
android:layout="@layout/preference_checkbox"
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="transliteration"
|
android:key="rtl"
|
||||||
android:summary="@string/pref_summary_transliteration"
|
android:summary="@string/pref_summary_rtl"
|
||||||
android:title="@string/pref_title_transliteration"
|
android:title="@string/pref_title_rtl"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<EditTextPreference
|
||||||
|
android:inputType="number"
|
||||||
|
android:key="rtl_max_line_length"
|
||||||
|
android:defaultValue="20"
|
||||||
|
android:maxLength="159"
|
||||||
|
android:title="@string/pref_rtl_max_line_length"
|
||||||
|
android:summary="@string/pref_rtl_max_line_length_summary"/>
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:layout="@layout/preference_checkbox"
|
android:layout="@layout/preference_checkbox"
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
@ -598,7 +614,7 @@
|
|||||||
android:title="@string/pref_title_screentime"/>
|
android:title="@string/pref_title_screentime"/>
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:layout="@layout/preference_checkbox"
|
android:layout="@layout/preference_checkbox"
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
android:key="hplus_alldayhr"
|
android:key="hplus_alldayhr"
|
||||||
android:title="@string/prefs_title_all_day_heart_rate" />
|
android:title="@string/prefs_title_all_day_heart_rate" />
|
||||||
|
@ -6,7 +6,7 @@ buildscript {
|
|||||||
google()
|
google()
|
||||||
}
|
}
|
||||||
dependencies {
|
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
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
Loading…
Reference in New Issue
Block a user