diff --git a/.gitignore b/.gitignore index f03203d..3ef9291 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,10 @@ captures/ .idea/dictionaries .idea/libraries .idea/caches +.idea/modules.xml +.idea/compiler.xml +.idea/misc.xml +.idea/**/shelf # Keystore files # Uncomment the following line if you do not want to check your keystore files in. @@ -65,4 +69,3 @@ fastlane/test_output fastlane/readme.md .idea/workspace.xml___jb_old___ .idea/misc.xml -.idea/misc.xml diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index af360d1..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index fe37581..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index ae625a5..47e1330 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,8 +6,8 @@ android { applicationId "com.layoutxml.twelveish" minSdkVersion 23 targetSdkVersion 29 - versionCode 267 - versionName "2.3.2" + versionCode 358 + versionName "2.4.0" multiDexEnabled true } buildTypes { @@ -20,12 +20,12 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.google.android.support:wearable:2.7.0' + implementation 'com.google.android.support:wearable:2.8.1' implementation 'com.google.android.gms:play-services-wearable:17.0.0' implementation 'androidx.percentlayout:percentlayout:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.2.0-alpha03' implementation 'androidx.wear:wear:1.0.0' - compileOnly 'com.google.android.wearable:wearable:2.7.0' + compileOnly 'com.google.android.wearable:wearable:2.8.1' implementation "androidx.constraintlayout:constraintlayout:1.1.3" } diff --git a/app/src/main/java/com/layoutxml/twelveish/MyWatchFace.java b/app/src/main/java/com/layoutxml/twelveish/MyWatchFace.java index 7107e1b..fd881b0 100644 --- a/app/src/main/java/com/layoutxml/twelveish/MyWatchFace.java +++ b/app/src/main/java/com/layoutxml/twelveish/MyWatchFace.java @@ -59,6 +59,7 @@ import java.lang.ref.WeakReference; import java.util.Calendar; import java.util.Locale; +import java.util.Map; import java.util.TimeZone; import java.util.concurrent.TimeUnit; @@ -70,13 +71,20 @@ public class MyWatchFace extends CanvasWatchFaceService { private static final String TAG = "MyWatchFace"; private final String path = "/twelveish"; private final String DATA_KEY = "rokas-twelveish"; - private final String HANDSHAKE_KEY = "rokas-twelveish-hs"; + // private final String HANDSHAKE_KEY = "rokas-twelveish-hs"; + private final String HANDSHAKE_REQUEST = "rokas-twelveish-hs-req"; + private final String HANDSHAKE_RESPONSE = "rokas-twelveish-hs-res"; private final String GOODBYE_KEY = "rokas-twelveish-gb"; private final String DATA_REQUEST_KEY = "rokas-twelveish-dr"; private final String DATA_REQUEST_KEY2 = "rokas-twelveish-dr2"; private final String CONFIG_REQUEST_KEY = "rokas-twelveish-cr"; private final String CONFIG_REQUEST_KEY2 = "rokas-twelveish-cr2"; private final String PREFERENCES_KEY = "rokas-twelveish-pr"; + + private final String PING_FIRE = "rokas-twelveish-fire"; // Request ping + private final String PING_ICE = "rokas-twelveish-ice"; // Ping response + private final String TIMESTAMP = "rokas-twelveish-timestamp"; + private static Typeface NORMAL_TYPEFACE = Typeface.create("sans-serif-light", Typeface.NORMAL); private static final long INTERACTIVE_UPDATE_RATE_MS = TimeUnit.SECONDS.toMillis(1); private static final int MSG_UPDATE_TIME = 0; @@ -755,8 +763,8 @@ public void onVisibilityChanged(boolean visible) { Wearable.getDataClient(getApplicationContext()).addListener(this); final PutDataMapRequest mPutDataMapRequest = PutDataMapRequest.create(path); - mPutDataMapRequest.getDataMap().putLong("Timestamp", System.currentTimeMillis()); - mPutDataMapRequest.getDataMap().putBoolean(HANDSHAKE_KEY, true); + mPutDataMapRequest.getDataMap().putLong(TIMESTAMP, System.currentTimeMillis()); + mPutDataMapRequest.getDataMap().putBoolean(HANDSHAKE_REQUEST, true); mPutDataMapRequest.setUrgent(); PutDataRequest mPutDataRequest = mPutDataMapRequest.asPutDataRequest(); Wearable.getDataClient(getApplicationContext()).putDataItem(mPutDataRequest); @@ -1184,11 +1192,44 @@ private void processData(DataItem dataItem) { getDate(); //forces date refresh in case it is changed significantTimeChange = true; } - boolean handshake = mDataMapItem.getDataMap().getBoolean(HANDSHAKE_KEY); - if (!handshake) { + if (array!=null && array.length > 3){ // We're receiving multiple preferences at once + for(int i = 0; i < array.length; i+=3){ + switch(array[i + 2]){ + case "String": + prefs.edit().putString(array[i], array[i+1]).apply(); + break; + case "Integer": + try { + int newPref = Integer.parseInt(array[1]); + prefs.edit().putInt(array[i],newPref).apply(); + } catch (NumberFormatException e) { + Toast.makeText(getApplicationContext(), "Preference error", Toast.LENGTH_SHORT).show(); + } + break; + case "Boolean": + if (array[i + 1].equalsIgnoreCase("true") || array[i+1].equalsIgnoreCase("false")){ + boolean newPref2 = Boolean.parseBoolean(array[i+1]); + prefs.edit().putBoolean(array[i], newPref2).apply(); + } else { + Toast.makeText(getApplicationContext(), "Preference error", Toast.LENGTH_SHORT).show(); + Log.d(TAG, "processData: Boolean was neither true nor false! Key: " + array[i]); + } + break; + default: + Log.d(TAG, "Unkown type in processData. Index: " + i); + } + } + + loadPreferences(); + getDate(); //forces date refresh in case it is changed + significantTimeChange = true; + + } + boolean handshake = mDataMapItem.getDataMap().getBoolean(HANDSHAKE_REQUEST); + if (handshake) { final PutDataMapRequest mPutDataMapRequest = PutDataMapRequest.create(path); - mPutDataMapRequest.getDataMap().putLong("Timestamp", System.currentTimeMillis()); - mPutDataMapRequest.getDataMap().putBoolean(HANDSHAKE_KEY, true); + mPutDataMapRequest.getDataMap().putLong(TIMESTAMP, System.currentTimeMillis()); + mPutDataMapRequest.getDataMap().putBoolean(HANDSHAKE_RESPONSE, true); mPutDataMapRequest.setUrgent(); PutDataRequest mPutDataRequest = mPutDataMapRequest.asPutDataRequest(); Wearable.getDataClient(getApplicationContext()).putDataItem(mPutDataRequest); @@ -1202,48 +1243,21 @@ public void run() { } boolean preferences = mDataMapItem.getDataMap().getBoolean(DATA_REQUEST_KEY); if (preferences) { - String[] preferencesToSend = new String[38]; - preferencesToSend[0] = "militaryTime"; - preferencesToSend[1] = militaryTime ? "true" : "false"; - preferencesToSend[2] = "militaryTextTime"; - preferencesToSend[3] = militaryTextTime ? "true" : "false"; - preferencesToSend[4] = "ampm"; - preferencesToSend[5] = "false"; //TODO: remove - preferencesToSend[6] = "showSecondary"; - preferencesToSend[7] = showSecondary ? "true" : "false"; - preferencesToSend[8] = "showSecondaryActive"; - preferencesToSend[9] = showSecondaryActive ? "true" : "false"; - preferencesToSend[10] = "showSecondaryCalendar"; - preferencesToSend[11] = showSecondaryCalendar ? "true" : "false"; - preferencesToSend[12] = "showSecondaryCalendarActive"; - preferencesToSend[13] = showSecondaryCalendarActive ? "true" : "false"; - preferencesToSend[14] = "showSuffixes"; - preferencesToSend[15] = "true"; - preferencesToSend[16] = "showBattery"; - preferencesToSend[17] = showBattery ? "true" : "false"; - preferencesToSend[18] = "showBatteryAmbient"; - preferencesToSend[19] = showBatteryAmbient ? "true" : "false"; - preferencesToSend[20] = "showWords"; - preferencesToSend[21] = "true"; - preferencesToSend[22] = "showWordsAmbient"; - preferencesToSend[23] = "true"; - preferencesToSend[24] = "showSeconds"; - preferencesToSend[25] = showSeconds ? "true" : "false"; - preferencesToSend[26] = "showComplication"; - preferencesToSend[27] = showComplication ? "true" : "false"; - preferencesToSend[28] = "showComplicationAmbient"; - preferencesToSend[29] = showComplicationAmbient ? "true" : "false"; - preferencesToSend[30] = "showDay"; - preferencesToSend[31] = showDay ? "true" : "false"; - preferencesToSend[32] = "showDayAmbient"; - preferencesToSend[33] = showDayAmbient ? "true" : "false"; - preferencesToSend[34] = "disableComplicationTap"; - preferencesToSend[35] = disableComplicationTap ? "true" : "false"; - preferencesToSend[36] = "legacyWords"; - preferencesToSend[37] = "false"; + Map prefMap = prefs.getAll(); + int index = 0; + String[] preferencesToSend = new String[prefMap.size() * 2]; + + for(Map.Entry entry : prefMap.entrySet()){ + String key = entry.getKey(); + String value = entry.getValue().toString(); + + preferencesToSend[index] = key; + preferencesToSend[index+1] = value; + index += 2; + } final PutDataMapRequest mPutDataMapRequest = PutDataMapRequest.create(path); - mPutDataMapRequest.getDataMap().putLong("Timestamp", System.currentTimeMillis()); + mPutDataMapRequest.getDataMap().putLong(TIMESTAMP, System.currentTimeMillis()); mPutDataMapRequest.getDataMap().putStringArray(PREFERENCES_KEY, preferencesToSend); mPutDataMapRequest.getDataMap().putBoolean(DATA_REQUEST_KEY, false); mPutDataMapRequest.getDataMap().putBoolean(DATA_REQUEST_KEY2, true); @@ -1267,7 +1281,7 @@ public void run() { configToSend[2] = complicationRightSet ? "true" : "false"; final PutDataMapRequest mPutDataMapRequest = PutDataMapRequest.create(path); - mPutDataMapRequest.getDataMap().putLong("Timestamp", System.currentTimeMillis()); + mPutDataMapRequest.getDataMap().putLong(TIMESTAMP, System.currentTimeMillis()); mPutDataMapRequest.getDataMap().putStringArray(PREFERENCES_KEY, configToSend); mPutDataMapRequest.getDataMap().putBoolean(CONFIG_REQUEST_KEY, false); mPutDataMapRequest.getDataMap().putBoolean(CONFIG_REQUEST_KEY2, true); @@ -1282,6 +1296,23 @@ public void run() { } }, 5000); } + boolean ping = mDataMapItem.getDataMap().getBoolean(PING_FIRE); + if(ping){ + final PutDataMapRequest mPutDataMapRequest = PutDataMapRequest.create(path); + mPutDataMapRequest.getDataMap().putLong(TIMESTAMP, System.currentTimeMillis()); + mPutDataMapRequest.getDataMap().putBoolean(PING_FIRE, false); + mPutDataMapRequest.getDataMap().putBoolean(PING_ICE, true); + mPutDataMapRequest.setUrgent(); + PutDataRequest mPutDataRequest = mPutDataMapRequest.asPutDataRequest(); + Wearable.getDataClient(getApplicationContext()).putDataItem(mPutDataRequest); + final Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + mPutDataMapRequest.getDataMap().clear(); + } + }, 5000); + } } } } diff --git a/app/src/main/java/com/layoutxml/twelveish/WordClockTask.java b/app/src/main/java/com/layoutxml/twelveish/WordClockTask.java index 274da72..49e224f 100644 --- a/app/src/main/java/com/layoutxml/twelveish/WordClockTask.java +++ b/app/src/main/java/com/layoutxml/twelveish/WordClockTask.java @@ -369,7 +369,22 @@ private String capitalise0(int hours, int minutes, int index) { String mainPrefix = ""; StringBuilder prefix; if ((minutes > 0) && (!Prefixes[index].equals("")) && (Prefixes[index] != null)) { - String[] prefixArray = Prefixes[index].split(" "); + + //Split the prefix with non-break spaces and capitalise each word + StringBuilder preString = new StringBuilder(); + String[] preArray = Prefixes[index].split("\\u00A0"); + + for (String word : preArray){ + if(preString.length() != 0) + preString.append("\u00A0"); + + String capitalised = word.substring(0, 1).toUpperCase() + word.substring(1); + preString.append(capitalised); + } + + // Do the same with spaces + + String[] prefixArray = preString.toString().split(" "); prefix = new StringBuilder(); for (String word : prefixArray) { if (prefix.length() != 0) @@ -403,8 +418,21 @@ private String capitalise0(int hours, int minutes, int index) { if (showSuffixes) { StringBuilder suffix; if ((minutes > 0) && (!Suffixes[index].equals("")) && (Suffixes[index] != null)) { + + //We first need to replace non-break spaces with regular spaces + StringBuilder suffString = new StringBuilder(); + String[] suffArray = Suffixes[index].split("\\u00A0"); + + for (String word : suffArray){ + if(suffString.length() != 0) + suffString.append("\u00A0"); + + String capitalised = word.substring(0, 1).toUpperCase() + word.substring(1); + suffString.append(capitalised); + } + if (SuffixNewLine[index]) { - String[] suffixArray = Suffixes[index].split(" "); + String[] suffixArray = suffString.toString().split(" "); suffix = new StringBuilder(); for (String word : suffixArray) { if (suffix.length() != 0) @@ -414,7 +442,7 @@ private String capitalise0(int hours, int minutes, int index) { } mainSuffix = suffix.toString(); } else { - mainSuffix = Suffixes[index].toLowerCase(); + mainSuffix = suffString.toString().toLowerCase(); } } } @@ -478,7 +506,7 @@ private String capitalise2(int hours, int minutes, int index) { + middle + ((minutes > 0) ? (SuffixNewLine[index] ? " " : "") : "") + ((showSuffixes) ? ((minutes > 0) ? Suffixes[index] : "") : ""); - return arrangeWords(text); + return arrangeWords(text).toLowerCase(); } } @@ -498,7 +526,7 @@ private String capitalise3(int hours, int minutes, int index) { + middle + ((minutes > 0) ? (SuffixNewLine[index] ? "\n" : "") : "") + ((showSuffixes) ? ((minutes > 0) ? Suffixes[index] : "") : ""); - return text20.substring(0, 1).toUpperCase() + text20.substring(1).toLowerCase(); + return text20.substring(0, 1).toUpperCase() + text20.substring(1); } else { String text20 = ((minutes > 0) ? Prefixes[index] : "") @@ -506,7 +534,7 @@ private String capitalise3(int hours, int minutes, int index) { + middle + ((minutes > 0) ? (SuffixNewLine[index] ? " " : "") : "") + ((showSuffixes) ? ((minutes > 0) ? Suffixes[index] : "") : ""); - return arrangeWords(text20.substring(0, 1).toUpperCase() + text20.substring(1).toLowerCase()); + return arrangeWords(text20.substring(0, 1).toUpperCase() + text20.substring(1)); } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 651eeb5..b9d4fb6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -15,7 +15,7 @@ secondaryColorActive secondaryColor militaryTime - militarytextTime + militaryTextTime dateOrder stringOption capitalisation @@ -332,15 +332,15 @@ kurz nach - bald viertel\u00A0nach - fast viertel\u00A0nach - viertel\u00A0nach + bald Viertel\u00A0nach + fast Viertel\u00A0nach + Viertel\u00A0nach bald halb kurz vor halb kurz nach halb - bald viertel\u00A0vor - fast viertel\u00A0vor - viertel\u00A0vor + bald Viertel\u00A0vor + fast Viertel\u00A0vor + Viertel\u00A0vor bald fast diff --git a/phone/build.gradle b/phone/build.gradle index 77ff4f0..0a60234 100644 --- a/phone/build.gradle +++ b/phone/build.gradle @@ -13,8 +13,8 @@ android { applicationId "com.layoutxml.twelveish" minSdkVersion 21 targetSdkVersion 29 - versionCode 266 - versionName "2.3.2" + versionCode 357 + versionName "2.4.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -33,6 +33,7 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.3.0-alpha01' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'com.google.code.gson:gson:2.8.5' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' diff --git a/phone/src/main/AndroidManifest.xml b/phone/src/main/AndroidManifest.xml index 70f3335..c2a3a85 100644 --- a/phone/src/main/AndroidManifest.xml +++ b/phone/src/main/AndroidManifest.xml @@ -1,14 +1,7 @@ - - - @@ -22,21 +15,25 @@ android:supportsRtl="true" android:theme="@style/AppTheme" tools:ignore="GoogleAppIndexingWarning"> - + - + + + \ No newline at end of file diff --git a/phone/src/main/java/com/layoutxml/twelveish/Communicator.java b/phone/src/main/java/com/layoutxml/twelveish/Communicator.java index dcfb428..0f4611b 100644 --- a/phone/src/main/java/com/layoutxml/twelveish/Communicator.java +++ b/phone/src/main/java/com/layoutxml/twelveish/Communicator.java @@ -1,8 +1,6 @@ package com.layoutxml.twelveish; -import android.app.Activity; import android.content.Context; -import android.net.Uri; import android.os.Handler; import android.util.Log; import android.widget.Toast; @@ -14,12 +12,16 @@ import com.google.android.gms.wearable.PutDataMapRequest; import com.google.android.gms.wearable.PutDataRequest; import com.google.android.gms.wearable.Wearable; +import com.google.gson.Gson; import com.layoutxml.twelveish.objects.WatchPreviewView; import androidx.annotation.NonNull; +import java.io.FileWriter; +import java.io.IOException; import java.lang.ref.WeakReference; -import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import javax.inject.Inject; import javax.inject.Singleton; @@ -29,13 +31,19 @@ public class Communicator implements DataClient.OnDataChangedListener { private final String path = "/twelveish"; private final String DATA_KEY = "rokas-twelveish"; - private final String HANDSHAKE_KEY = "rokas-twelveish-hs"; + private final String HANDSHAKE_REQUEST = "rokas-twelveish-hs-req"; + private final String HANDSHAKE_RESPONSE = "rokas-twelveish-hs-res"; private final String GOODBYE_KEY = "rokas-twelveish-gb"; private final String DATA_REQUEST_KEY = "rokas-twelveish-dr"; private final String DATA_REQUEST_KEY2 = "rokas-twelveish-dr2"; private final String PREFERENCES_KEY = "rokas-twelveish-pr"; private final String CONFIG_REQUEST_KEY = "rokas-twelveish-cr"; private final String CONFIG_REQUEST_KEY2 = "rokas-twelveish-cr2"; + + private final String PING_FIRE = "rokas-twelveish-fire"; // Request ping + private final String PING_ICE = "rokas-twelveish-ice"; // Ping response + private final String TIMESTAMP = "rokas-twelveish-timestamp"; + private PutDataMapRequest mPutDataMapRequest; private Context applicationContext; private boolean currentStatus = true; //temporary value for waiting period if watch not found to not create false negatives @@ -43,6 +51,9 @@ public class Communicator implements DataClient.OnDataChangedListener { public boolean isWatchConnected = false; private static final String TAG = "Communicator"; private WeakReference previewListener; + private WeakReference preferenceListener; + private long lastPing = 0; + @Inject public Communicator(Context context) { @@ -56,7 +67,7 @@ public void initiateHandshake() { setCurrentStatus(false); mPutDataMapRequest.getDataMap().putLong("Timestamp", System.currentTimeMillis()); - mPutDataMapRequest.getDataMap().putBoolean(HANDSHAKE_KEY, false); + mPutDataMapRequest.getDataMap().putBoolean(HANDSHAKE_REQUEST, true); mPutDataMapRequest.setUrgent(); PutDataRequest mPutDataRequest = mPutDataMapRequest.asPutDataRequest(); Wearable.getDataClient(applicationContext).putDataItem(mPutDataRequest); @@ -101,6 +112,21 @@ public void run() { } } + public void ping(){ + mPutDataMapRequest.getDataMap().putBoolean(PING_FIRE, true); + mPutDataMapRequest.getDataMap().putLong(TIMESTAMP, System.currentTimeMillis()); + mPutDataMapRequest.setUrgent(); + final PutDataRequest mPutDataRequest = mPutDataMapRequest.asPutDataRequest(); + Wearable.getDataClient(applicationContext).putDataItem(mPutDataRequest); + final Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + mPutDataMapRequest.getDataMap().clear(); + } + }, 5000); + } + public void sendPreference(String key, String value, String type, Context context) { String[] array = new String[3]; array[0] = key; @@ -120,21 +146,83 @@ public void run() { }, 5000); //deleting as described in google's documentation does not actually work, so I have to resolve to clearing with delay } -// public void requestBooleanPreferences(Context context, WeakReference listenerActivity) { -// mPutDataMapRequest.getDataMap().putLong("Timestamp", System.currentTimeMillis()); -// mPutDataMapRequest.getDataMap().putBoolean(DATA_REQUEST_KEY, true); -// mPutDataMapRequest.setUrgent(); -// PutDataRequest mPutDataRequest = mPutDataMapRequest.asPutDataRequest(); -// Wearable.getDataClient(context).putDataItem(mPutDataRequest); -// booleanActivity = listenerActivity; -// final Handler handler = new Handler(); -// handler.postDelayed(new Runnable() { -// @Override -// public void run() { -// mPutDataMapRequest.getDataMap().clear(); -// } -// }, 5000); -// } + public void sendWatchFace(SettingsManager settingsManager, Context context){ + String[] preferencesToSend = new String[(settingsManager.booleanHashmap.size() + settingsManager.integerHashmap.size() + settingsManager.stringHashmap.size())*3]; + + int index = 0; + for(Map.Entry preference : settingsManager.stringHashmap.entrySet()){ + String key = preference.getKey(); + String value = preference.getValue(); + String type = "String"; + + preferencesToSend[index] = key; + preferencesToSend[index + 1] = value; + preferencesToSend[index + 2] = type; + index += 3; + } + + for(Map.Entry preference : settingsManager.integerHashmap.entrySet()){ + String key = preference.getKey(); + int value = preference.getValue(); + String type = "Integer"; + + preferencesToSend[index] = key; + preferencesToSend[index + 1] = String.valueOf(value); + preferencesToSend[index + 2] = type; + index += 3; + } + + for(Map.Entry preference : settingsManager.booleanHashmap.entrySet()){ + String key = preference.getKey(); + boolean value = preference.getValue(); + String type = "Boolean"; + + preferencesToSend[index] = key; + preferencesToSend[index + 1] = value ? "true" : "false"; + preferencesToSend[index + 2] = type; + index += 3; + } + + + if(preferencesToSend != null){ + Log.d(TAG, "Preferences found"); + } + + mPutDataMapRequest.getDataMap().putLong("Timestamp", System.currentTimeMillis()); + mPutDataMapRequest.getDataMap().putStringArray(DATA_KEY, preferencesToSend); + mPutDataMapRequest.setUrgent(); + PutDataRequest mPutDataRequest = mPutDataMapRequest.asPutDataRequest(); + Wearable.getDataClient(context).putDataItem(mPutDataRequest); + final Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + mPutDataMapRequest.getDataMap().clear(); + } + }, 5000); //deleting as described in google's documentation does not actually work, so I have to resolve to clearing with delay + + } + + public void requestPreferences(Context context, WeakReference listenerActivity) { + mPutDataMapRequest.getDataMap().putLong("Timestamp", System.currentTimeMillis()); + mPutDataMapRequest.getDataMap().putBoolean(DATA_REQUEST_KEY, true); + mPutDataMapRequest.setUrgent(); + PutDataRequest mPutDataRequest = mPutDataMapRequest.asPutDataRequest(); + Wearable.getDataClient(context).putDataItem(mPutDataRequest); + preferenceListener = listenerActivity; + final Handler handler = new Handler(); + handler.postDelayed(new Runnable() { + @Override + public void run() { + mPutDataMapRequest.getDataMap().clear(); + } + }, 5000); + } + + /* public void requestPreferences(Context context, WeakReference listenerActivity){ + mPutDataMapRequest.getDataMap().putLong("Timestamp", System.currentTimeMillis()); + mPutDataMapRequest.getDataMap().putBoolean(); + }*/ public void requestConfig(Context context, WeakReference listenerActivity) { Log.d(TAG, "requestConfig"); @@ -159,14 +247,35 @@ public void onDataChanged(@NonNull DataEventBuffer dataEventBuffer) { if (event.getType()==DataEvent.TYPE_CHANGED && event.getDataItem().getUri().getPath()!=null && event.getDataItem().getUri().getPath().equals(path)) { Log.d(TAG, "onDataChanged: received something"); DataMapItem mDataMapItem = DataMapItem.fromDataItem(event.getDataItem()); - boolean handshake = mDataMapItem.getDataMap().getBoolean(HANDSHAKE_KEY); + boolean handshake = mDataMapItem.getDataMap().getBoolean(HANDSHAKE_RESPONSE); boolean goodbye = mDataMapItem.getDataMap().getBoolean(GOODBYE_KEY); boolean config = mDataMapItem.getDataMap().getBoolean(CONFIG_REQUEST_KEY2); + boolean preferences = mDataMapItem.getDataMap().getBoolean(DATA_REQUEST_KEY2); + boolean ping = mDataMapItem.getDataMap().getBoolean(PING_ICE); if (handshake) { Log.d(TAG,"handshake received"); setCurrentStatus(true); if (!isWatchConnected) { Toast.makeText(applicationContext, "Watch connected", Toast.LENGTH_SHORT).show(); + lastPing = mDataMapItem.getDataMap().getLong(TIMESTAMP); + final Handler pingHandler = new Handler(){}; + pingHandler.postDelayed(new Runnable() { + @Override + public void run() { + if(isWatchConnected) { + ping(); + Long timeSincePing = System.currentTimeMillis() - lastPing; + if(timeSincePing > 15000){ + Toast.makeText(applicationContext, "Watch disconnected, retrying", Toast.LENGTH_SHORT).show(); + isWatchConnected = false; + initiateHandshake(); + lastPing = 0; + } + pingHandler.postDelayed(this, 5000); + } + + } + }, 5000); } isWatchConnected = true; } @@ -174,7 +283,48 @@ public void onDataChanged(@NonNull DataEventBuffer dataEventBuffer) { Toast.makeText(applicationContext, "Watch disconnected", Toast.LENGTH_SHORT).show(); isWatchConnected=false; initiateHandshake(); + lastPing = 0; } + + if(preferences){ + Log.d(TAG, "onDataChanged: preferences"); + String[] newPreferences = mDataMapItem.getDataMap().getStringArray(PREFERENCES_KEY); + SettingsManager settingsManager = new SettingsManager(applicationContext); + settingsManager.initializeDefaultBooleans(); + settingsManager.initializeDefaultIntegers(); + settingsManager.initializeDefaultStrings(); + if(newPreferences != null){ + for(int i = 0; i < newPreferences.length; i+=2){ + if(settingsManager.stringHashmap.containsKey(newPreferences[i])){ + settingsManager.stringHashmap.put(newPreferences[i], newPreferences[i+1]); + } else if(settingsManager.integerHashmap.containsKey(newPreferences[i])){ + settingsManager.integerHashmap.put(newPreferences[i], Integer.valueOf(newPreferences[i+1])); + } else if(settingsManager.booleanHashmap.containsKey(newPreferences[i])){ + settingsManager.booleanHashmap.put(newPreferences[i], Boolean.valueOf(newPreferences[i+1])); + } else { + Log.d(TAG, "Unknown preference key: " + newPreferences[i]); + } + } + + WatchPreviewView previewView = preferenceListener.get(); + Gson gson = new Gson(); + HashMap settingMap = new HashMap<>(); + settingMap.put("stringHashMap", settingsManager.stringHashmap); + settingMap.put("booleanHashMap", settingsManager.booleanHashmap); + settingMap.put("integerHashMap", settingsManager.integerHashmap); + + try { + String fileName = previewView.getContext().getFilesDir().toString() + "/test.json"; + FileWriter writer = new FileWriter(fileName); + gson.toJson(settingMap, writer); + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + previewView.loadSettings(settingsManager); + } + } + if (config) { Log.d(TAG, "onDataChanged: config"); String[] booleanPreferencesTemp = mDataMapItem.getDataMap().getStringArray(PREFERENCES_KEY); @@ -191,6 +341,10 @@ public void onDataChanged(@NonNull DataEventBuffer dataEventBuffer) { } } } + + if(ping){ + lastPing = mPutDataMapRequest.getDataMap().getLong(TIMESTAMP); + } } } } diff --git a/phone/src/main/java/com/layoutxml/twelveish/CustomizationScreen.java b/phone/src/main/java/com/layoutxml/twelveish/CustomizationScreen.java index f580e80..e947440 100644 --- a/phone/src/main/java/com/layoutxml/twelveish/CustomizationScreen.java +++ b/phone/src/main/java/com/layoutxml/twelveish/CustomizationScreen.java @@ -1,9 +1,12 @@ package com.layoutxml.twelveish; import android.os.Bundle; +import android.provider.Settings; +import android.util.JsonReader; import android.util.Log; import android.view.View; import android.widget.ImageButton; +import android.widget.Toast; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; @@ -14,15 +17,29 @@ import com.google.android.gms.wearable.Wearable; import com.google.android.material.tabs.TabLayout; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; import com.layoutxml.twelveish.adapters.OptionsPagerAdapter; import com.layoutxml.twelveish.dagger.App; import com.layoutxml.twelveish.dagger.DaggerSettingsManagerComponent; import com.layoutxml.twelveish.dagger.SettingsManagerComponent; import com.layoutxml.twelveish.fragments.PreviewFragment; -public class CustomizationScreen extends AppCompatActivity { +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.List; - private SettingsManagerComponent settingsManagerComponent; +import javax.inject.Inject; + + +public class CustomizationScreen extends AppCompatActivity implements View.OnClickListener { + + @Inject + SettingsManagerComponent settingsManagerComponent; private Communicator communicator; private static final String TAG = "CustomizationScreen"; private boolean isInAmoledMode = false; @@ -39,6 +56,44 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { settingsManagerComponent = DaggerSettingsManagerComponent.factory().create(getApplicationContext()); + + final SettingsManager testSettings = settingsManagerComponent.getSettingsManager(); + try { + JsonReader reader = new JsonReader(new FileReader(this.getFilesDir().toString() + "/test.json")); + reader.beginObject(); + while(reader.hasNext()){ + String nameToRead = reader.nextName(); + if(nameToRead.equals("stringHashMap")){ + reader.beginObject(); + while(reader.hasNext()){ + String firstString = reader.nextName(); + String secondString = reader.nextString(); + testSettings.stringHashmap.put(firstString, secondString); + } + reader.endObject(); + } else if (nameToRead.equals("booleanHashMap")){ + reader.beginObject(); + while (reader.hasNext()){ + testSettings.booleanHashmap.put(reader.nextName(), reader.nextBoolean()); + } + reader.endObject(); + } else if(nameToRead.equals("integerHashMap")){ + reader.beginObject(); + while(reader.hasNext()){ + testSettings.integerHashmap.put(reader.nextName(), reader.nextInt()); + } + reader.endObject(); + } + } + + reader.endObject(); + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); @@ -70,6 +125,12 @@ public void onClick(View v) { invalidatePreview(); } }); + + ImageButton saveButton = findViewById(R.id.saveButton); + saveButton.setOnClickListener(this); + + ImageButton sendButton = findViewById(R.id.sendButton); + sendButton.setOnClickListener(this); } @Override @@ -90,8 +151,39 @@ public SettingsManagerComponent getSettingsManagerComponent() { return settingsManagerComponent; } + @Override + public void onClick(View view) { + SettingsManager settingsManager = settingsManagerComponent.getSettingsManager(); + switch (view.getId()){ + case R.id.saveButton: + + Gson gson = new Gson(); + HashMap settingMap = new HashMap<>(); + settingMap.put("stringHashMap", settingsManager.stringHashmap); + settingMap.put("booleanHashMap", settingsManager.booleanHashmap); + settingMap.put("integerHashMap", settingsManager.integerHashmap); + + try { + String fileName = this.getFilesDir().toString() + "/test.json"; + FileWriter writer = new FileWriter(fileName); + gson.toJson(settingMap, writer); + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + break; + case R.id.sendButton: + Toast.makeText(getApplicationContext(), "Applying watchface", Toast.LENGTH_LONG).show(); + communicator.sendWatchFace(settingsManager, getApplicationContext()); + break; + default: + throw new IllegalStateException("Unexpected value: " + view.getId()); + } + + } + public interface AmoledChange { - public void ambientModeChange(boolean value); + void ambientModeChange(boolean value); } public void invalidatePreview() { diff --git a/phone/src/main/java/com/layoutxml/twelveish/WordClockTask.java b/phone/src/main/java/com/layoutxml/twelveish/WordClockTask.java index a1cfe23..bb18cd7 100644 --- a/phone/src/main/java/com/layoutxml/twelveish/WordClockTask.java +++ b/phone/src/main/java/com/layoutxml/twelveish/WordClockTask.java @@ -368,7 +368,22 @@ private String capitalise0(int hours, int minutes, int index) { String mainPrefix = ""; StringBuilder prefix; if ((minutes > 0) && (!Prefixes[index].equals("")) && (Prefixes[index] != null)) { - String[] prefixArray = Prefixes[index].split(" "); + + // Split the prefix with non-break spaces and capitalise each word + StringBuilder preString = new StringBuilder(); + String[] preArray = Prefixes[index].split("\\u00A0"); + + for (String word : preArray){ + if(preString.length() != 0) + preString.append("\u00A0"); + + String capitalised = word.substring(0,1).toUpperCase() + word.substring(1); + preString.append(capitalised); + } + + // Do the same with spaces + + String[] prefixArray = preString.toString().split(" "); prefix = new StringBuilder(); for (String word : prefixArray) { if (prefix.length() != 0) @@ -402,8 +417,21 @@ private String capitalise0(int hours, int minutes, int index) { if (showSuffixes) { StringBuilder suffix; if ((minutes > 0) && (!Suffixes[index].equals("")) && (Suffixes[index] != null)) { + + // Split the prefix with non-break spaces and capitalise each word + StringBuilder suffString = new StringBuilder(); + String[] suffArray = Prefixes[index].split("\\u00A0"); + + for (String word : suffArray){ + if(suffString.length() != 0) // No suffix has more than two parts separated by a non-break space + suffString.append("\u00A0"); + + String capitalised = word.substring(0,1).toUpperCase() + word.substring(1); + suffString.append(capitalised); + } + if (SuffixNewLine[index]) { - String[] suffixArray = Suffixes[index].split(" "); + String[] suffixArray = suffString.toString().split(" "); suffix = new StringBuilder(); for (String word : suffixArray) { if (suffix.length() != 0) @@ -413,7 +441,7 @@ private String capitalise0(int hours, int minutes, int index) { } mainSuffix = suffix.toString(); } else { - mainSuffix = Suffixes[index].toLowerCase(); + mainSuffix = suffString.toString().toLowerCase(); } } } @@ -477,7 +505,7 @@ private String capitalise2(int hours, int minutes, int index) { + middle + ((minutes > 0) ? (SuffixNewLine[index] ? " " : "") : "") + ((showSuffixes) ? ((minutes > 0) ? Suffixes[index] : "") : ""); - return arrangeWords(text); + return arrangeWords(text).toLowerCase(); } } @@ -497,7 +525,7 @@ private String capitalise3(int hours, int minutes, int index) { + middle + ((minutes > 0) ? (SuffixNewLine[index] ? "\n" : "") : "") + ((showSuffixes) ? ((minutes > 0) ? Suffixes[index] : "") : ""); - return text20.substring(0, 1).toUpperCase() + text20.substring(1).toLowerCase(); + return text20.substring(0, 1).toUpperCase() + text20.substring(1); } else { String text20 = ((minutes > 0) ? Prefixes[index] : "") @@ -505,7 +533,7 @@ private String capitalise3(int hours, int minutes, int index) { + middle + ((minutes > 0) ? (SuffixNewLine[index] ? " " : "") : "") + ((showSuffixes) ? ((minutes > 0) ? Suffixes[index] : "") : ""); - return arrangeWords(text20.substring(0, 1).toUpperCase() + text20.substring(1).toLowerCase()); + return arrangeWords(text20.substring(0, 1).toUpperCase() + text20.substring(1)); } } diff --git a/phone/src/main/java/com/layoutxml/twelveish/activities/LanguageSelectionActivity.java b/phone/src/main/java/com/layoutxml/twelveish/activities/LanguageSelectionActivity.java new file mode 100644 index 0000000..dac6ad1 --- /dev/null +++ b/phone/src/main/java/com/layoutxml/twelveish/activities/LanguageSelectionActivity.java @@ -0,0 +1,59 @@ +package com.layoutxml.twelveish.activities; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Pair; +import android.view.View; + +import com.layoutxml.twelveish.R; +import com.layoutxml.twelveish.adapters.TextviewRecyclerViewAdapter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +public class LanguageSelectionActivity extends AppCompatActivity implements TextviewRecyclerViewAdapter.ItemClickListener { + + private TextviewRecyclerViewAdapter adapter; + private List> settingOptions; + private String settingsName = "languageSelectionList"; + private String[] availableLanguages; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.color_selection_activity); + + generateLanguageList(); + + + RecyclerView recyclerView = findViewById(R.id.colorList); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + adapter = new TextviewRecyclerViewAdapter(this, settingOptions, settingsName); + adapter.setClickListener(this); + recyclerView.setAdapter(adapter); + } + + private void generateLanguageList(){ + availableLanguages = getResources().getStringArray(R.array.AvailableLanguages); + settingOptions = new ArrayList<>(); + for(String lang : availableLanguages){ + Locale mLocale = new Locale(lang); + settingOptions.add(new Pair(mLocale.getDisplayLanguage(mLocale), mLocale.getDisplayLanguage(new Locale("en")))); + } + } + + @Override + public void onItemClick(View view, int position, String name) { + Intent returnIntent = new Intent(); + String newLanguage = availableLanguages[position]; + returnIntent.putExtra("newLanguage", newLanguage); + setResult(Activity.RESULT_OK, returnIntent); + finish(); + } +} \ No newline at end of file diff --git a/phone/src/main/java/com/layoutxml/twelveish/activities/TextSelectionActivity.java b/phone/src/main/java/com/layoutxml/twelveish/activities/TextSelectionActivity.java new file mode 100644 index 0000000..17bfffc --- /dev/null +++ b/phone/src/main/java/com/layoutxml/twelveish/activities/TextSelectionActivity.java @@ -0,0 +1,144 @@ +package com.layoutxml.twelveish.activities; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Pair; +import android.view.View; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.layoutxml.twelveish.R; +import com.layoutxml.twelveish.SettingsManager; +import com.layoutxml.twelveish.adapters.TextviewRecyclerViewAdapter; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.Locale; + +public class TextSelectionActivity extends AppCompatActivity implements TextviewRecyclerViewAdapter.ItemClickListener { + + private TextviewRecyclerViewAdapter adapter; + private List> settingOptions; + private String settingsName = "languageSelectionList"; + private String[] availableLanguages; + private int settingType; + + public static int LANGUAGE_SELECTION = 0; + public static int CAPITALIZATION = 1; + public static int FONT_SELECTION = 2; + public static int DATE_ORDER = 3; + public static int SEPARATOR_SYMBOL = 4; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.color_selection_activity); + + settingType = getIntent().getIntExtra("SETTING_TYPE", 0); + + if(settingType == LANGUAGE_SELECTION){ + generateLanguageList(); + } else if(settingType == FONT_SELECTION){ + generateFontList(); + } else if(settingType == SEPARATOR_SYMBOL){ + generateSeparatorList(); + } else if(settingType == CAPITALIZATION){ + generateCapitalizationList(); + } else if(settingType == DATE_ORDER){ + generateDateOrderList(); + } + + RecyclerView recyclerView = findViewById(R.id.colorList); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + adapter = new TextviewRecyclerViewAdapter(this, settingOptions, settingsName); + adapter.setClickListener(this); + recyclerView.setAdapter(adapter); + } + + private void generateFontList() { + settingOptions = new ArrayList<>(); + settingOptions.add(new Pair("Roboto Light", "robotolight")); + settingOptions.add(new Pair("Alegreya", "alegreya")); + settingOptions.add(new Pair("Cabin", "cabin")); + settingOptions.add(new Pair("IBMplex Sans", "ibmplexsans")); + settingOptions.add(new Pair("Inconsolata", "inconsolata")); + settingOptions.add(new Pair("Merriweather", "merriweather")); + settingOptions.add(new Pair("Nunito", "nunito")); + settingOptions.add(new Pair("Pacifico", "pacifico")); + settingOptions.add(new Pair("Quattro Cento", "quattrocento")); + + } + + private void generateSeparatorList() { + settingOptions = new ArrayList<>(); + settingOptions.add(new Pair("Slash", "/")); + settingOptions.add(new Pair("Period", ".")); + settingOptions.add(new Pair("Hyphen", "-")); + settingOptions.add(new Pair("Space", " ")); + } + + private void generateCapitalizationList(){ + settingOptions = new ArrayList<>(); + settingOptions.add(new Pair("All words title case", "The Quick Brown Fox Jumped Over The Lazy Dog")); + settingOptions.add(new Pair("All uppercase","THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG")); + settingOptions.add(new Pair("All lowercase","the quick brown fox jumped over the lazy dog")); + settingOptions.add(new Pair("First word title case","The quick brown fox jumped over the lazy dog")); + settingOptions.add(new Pair("First word in every line title case","The quick brown fox jumped over the lazy dog")); + } + + private void generateLanguageList(){ + availableLanguages = getResources().getStringArray(R.array.AvailableLanguages); + settingOptions = new ArrayList<>(); + for(String lang : availableLanguages){ + Locale mLocale = new Locale(lang); + settingOptions.add(new Pair(mLocale.getDisplayLanguage(mLocale), mLocale.getDisplayLanguage(new Locale("en")))); + } + } + + private void generateDateOrderList(){ + Calendar mCalendar = Calendar.getInstance(); + settingOptions = new ArrayList<>(); + + int day = mCalendar.get(Calendar.DAY_OF_MONTH); + int month = mCalendar.get(Calendar.MONTH) + 1; + int year = mCalendar.get(Calendar.YEAR); + + String dateStrings[] = new String[4]; + dateStrings[0] = String.format(Locale.UK, "%02d" + "-" + "%02d" + "-" + "%04d", month, day, year); + dateStrings[1] = String.format(Locale.UK, "%02d" + "-" + "%02d" + "-" + "%04d", day, month, year); + dateStrings[2] = String.format(Locale.UK, "%04d" + "-" + "%02d" + "-" + "%02d", year, month, day); + dateStrings[3] = String.format(Locale.UK, "%04d" + "-" + "%02d" + "-" + "%02d", year, day, month); + + settingOptions.add(new Pair("Month-Day-Year", dateStrings[0])); + settingOptions.add(new Pair("Day-Month-Year", dateStrings[1])); + settingOptions.add(new Pair("Year-Month-Day", dateStrings[2])); + settingOptions.add(new Pair("Year-Day-Month", dateStrings[3])); + } + + @Override + public void onItemClick(View view, int position, String name) { + Intent returnIntent = new Intent(); + + if(settingType == LANGUAGE_SELECTION){ + String newLanguage = availableLanguages[position]; + returnIntent.putExtra("newLanguage", newLanguage); + + } else if(settingType == FONT_SELECTION){ + returnIntent.putExtra("newFont", settingOptions.get(position).second); + } else if(settingType == SEPARATOR_SYMBOL){ + returnIntent.putExtra("newSeparator", settingOptions.get(position).second); + } else if(settingType == CAPITALIZATION){ + returnIntent.putExtra("newCapitalization", position); + } else if(settingType == DATE_ORDER){ + returnIntent.putExtra("newDateOrder", position); + } + + setResult(Activity.RESULT_OK, returnIntent); + finish(); + } +} \ No newline at end of file diff --git a/phone/src/main/java/com/layoutxml/twelveish/adapters/ImageRecyclerViewAdapter.java b/phone/src/main/java/com/layoutxml/twelveish/adapters/ImageRecyclerViewAdapter.java index 27e987e..45847ad 100644 --- a/phone/src/main/java/com/layoutxml/twelveish/adapters/ImageRecyclerViewAdapter.java +++ b/phone/src/main/java/com/layoutxml/twelveish/adapters/ImageRecyclerViewAdapter.java @@ -64,7 +64,7 @@ public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickL @Override public void onClick(View view) { if (mClickListener != null) { - mClickListener.onItemClickImage(view, getAdapterPosition(), mData.get(getAdapterPosition()).second, name); + mClickListener.onItemClickImage(view, getBindingAdapterPosition(), mData.get(getBindingAdapterPosition()).second, name); } } } diff --git a/phone/src/main/java/com/layoutxml/twelveish/adapters/SeekerRecyclerViewAdapter.java b/phone/src/main/java/com/layoutxml/twelveish/adapters/SeekerRecyclerViewAdapter.java new file mode 100644 index 0000000..64ce2ad --- /dev/null +++ b/phone/src/main/java/com/layoutxml/twelveish/adapters/SeekerRecyclerViewAdapter.java @@ -0,0 +1,102 @@ +package com.layoutxml.twelveish.adapters; + +import android.content.Context; +import android.os.Build; +import android.util.Pair; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.SeekBar; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.layoutxml.twelveish.R; +import com.layoutxml.twelveish.objects.Triple; + +import java.util.List; + +public class SeekerRecyclerViewAdapter extends RecyclerView.Adapter { + + private List> mData; + private LayoutInflater mInflater; + private ItemClickListener mClickListener; + private SeekBar.OnSeekBarChangeListener mSeekBarListener; + private String name=""; //adapter name + + public SeekerRecyclerViewAdapter(Context context, List> data, String name) { + this.mInflater = LayoutInflater.from(context); + this.mData = data; + this.name = name; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = mInflater.inflate(R.layout.slider_item, parent, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + String title = mData.get(position).first; + int value = mData.get(position).second; + int maxValue = mData.get(position).third; + holder.myTextView.setText(title); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + holder.mySeekBar.setMin(0); + } + holder.mySeekBar.setMax(maxValue); + holder.mySeekBar.setProgress(value); + } + + @Override + public int getItemCount() { + return mData.size(); + } + + public class ViewHolder extends RecyclerView.ViewHolder implements SeekBar.OnSeekBarChangeListener { + TextView myTextView; + SeekBar mySeekBar; + + ViewHolder(View itemView) { + super(itemView); + myTextView = itemView.findViewById(R.id.titleTextView); + mySeekBar = itemView.findViewById(R.id.seekBar); + mySeekBar.setOnSeekBarChangeListener(this); + } + + + @Override + public void onProgressChanged(SeekBar seekBar, int value, boolean fromUser) { + if(mSeekBarListener != null) + mSeekBarListener.onProgressChanged(seekBar, value, fromUser); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + if(mSeekBarListener != null) + mSeekBarListener.onStartTrackingTouch(seekBar); + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + if(mSeekBarListener != null) + mSeekBarListener.onStopTrackingTouch(seekBar); + } + } + + String getItem(int id) { + return mData.get(id).first; + } + + public void setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener listener){ + this.mSeekBarListener = listener; + } + + public interface ItemClickListener { + void onItemClick(View view, int position, String name); + } +} \ No newline at end of file diff --git a/phone/src/main/java/com/layoutxml/twelveish/adapters/SwitchRecyclerViewAdapter.java b/phone/src/main/java/com/layoutxml/twelveish/adapters/SwitchRecyclerViewAdapter.java index 56319b8..af49a16 100644 --- a/phone/src/main/java/com/layoutxml/twelveish/adapters/SwitchRecyclerViewAdapter.java +++ b/phone/src/main/java/com/layoutxml/twelveish/adapters/SwitchRecyclerViewAdapter.java @@ -65,14 +65,14 @@ public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickL @Override public void onClick(View view) { if (mClickListener != null) { - String key = mData.get(getAdapterPosition()).second; - if (key.equals("showDay") || key.equals("showDayAmbient") || key.equals("showSecondaryCalendarActive") || key.equals("showSecondaryCalendar") || key.equals("militarytextTime")) { + String key = mData.get(getBindingAdapterPosition()).second; + if (key.equals("showDay") || key.equals("showDayAmbient") || key.equals("showSecondaryCalendarActive") || key.equals("showSecondaryCalendar") || key.equals("militaryTextTime")) { settingsManager.significantTimeChange = true; } boolean newValue = !settingsManager.booleanHashmap.get(key); settingsManager.booleanHashmap.put(key,newValue); mySwtich.setChecked(newValue); - mClickListener.onItemClickSwitch(view, getAdapterPosition(), newValue, name); + mClickListener.onItemClickSwitch(view, getBindingAdapterPosition(), newValue, name); } } } diff --git a/phone/src/main/java/com/layoutxml/twelveish/adapters/TextviewRecyclerViewAdapter.java b/phone/src/main/java/com/layoutxml/twelveish/adapters/TextviewRecyclerViewAdapter.java index 1e2f61b..f29ded0 100644 --- a/phone/src/main/java/com/layoutxml/twelveish/adapters/TextviewRecyclerViewAdapter.java +++ b/phone/src/main/java/com/layoutxml/twelveish/adapters/TextviewRecyclerViewAdapter.java @@ -59,7 +59,7 @@ public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickL @Override public void onClick(View view) { - if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition(), name); + if (mClickListener != null) mClickListener.onItemClick(view, getBindingAdapterPosition(), name); } } diff --git a/phone/src/main/java/com/layoutxml/twelveish/dagger/App.java b/phone/src/main/java/com/layoutxml/twelveish/dagger/App.java index ffe4b09..dc30b27 100644 --- a/phone/src/main/java/com/layoutxml/twelveish/dagger/App.java +++ b/phone/src/main/java/com/layoutxml/twelveish/dagger/App.java @@ -2,9 +2,12 @@ import android.app.Application; +import javax.inject.Inject; + public class App extends Application { - private CommunicatorComponent component; + @Inject + CommunicatorComponent component; @Override public void onCreate() { diff --git a/phone/src/main/java/com/layoutxml/twelveish/fragments/ComplicationSettingsFragment.java b/phone/src/main/java/com/layoutxml/twelveish/fragments/ComplicationSettingsFragment.java index 6110d4b..d2618f1 100644 --- a/phone/src/main/java/com/layoutxml/twelveish/fragments/ComplicationSettingsFragment.java +++ b/phone/src/main/java/com/layoutxml/twelveish/fragments/ComplicationSettingsFragment.java @@ -39,19 +39,22 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c activity = (CustomizationScreen) getContext(); settingsManager = activity.getSettingsManagerComponent().getSettingsManager(); - List> optionsSC = new ArrayList>(); + // Commented out until implemented + /*List> optionsSC = new ArrayList>(); optionsSC.add(new Pair("Left Complication","Click to launch menu on your watch")); optionsSC.add(new Pair("Right Complication","Click to launch menu on your watch")); - optionsSC.add(new Pair("Bottom Complication","Click to launch menu on your watch")); + optionsSC.add(new Pair("Bottom Complication","Click to launch menu on your watch"));*/ List> optionsBO = new ArrayList<>(); optionsBO.add(new Pair("Disable complication tap actions",getString(R.string.preference_tap_complications))); + optionsBO.add(new Pair("Show complications", getResources().getString(R.string.preference_show_complications))); + optionsBO.add(new Pair("Show complications in ambient", getResources().getString(R.string.preference_show_complications_ambient))); - RecyclerView recyclerViewSC = view.findViewById(R.id.setComplicationsRV); + /*RecyclerView recyclerViewSC = view.findViewById(R.id.setComplicationsRV); recyclerViewSC.setLayoutManager(new LinearLayoutManager(getContext())); adapterSC = new TextviewRecyclerViewAdapter(getContext(),optionsSC, complicationSCName); adapterSC.setClickListener(this); - recyclerViewSC.setAdapter(adapterSC); + recyclerViewSC.setAdapter(adapterSC);*/ RecyclerView recyclerViewBO = view.findViewById(R.id.complicationsSwitchRV); recyclerViewBO.setLayoutManager(new LinearLayoutManager(getContext())); diff --git a/phone/src/main/java/com/layoutxml/twelveish/fragments/MainTextSettingsFragment.java b/phone/src/main/java/com/layoutxml/twelveish/fragments/MainTextSettingsFragment.java index b27c9f7..1ac8bbc 100644 --- a/phone/src/main/java/com/layoutxml/twelveish/fragments/MainTextSettingsFragment.java +++ b/phone/src/main/java/com/layoutxml/twelveish/fragments/MainTextSettingsFragment.java @@ -9,6 +9,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.SeekBar; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -21,25 +22,39 @@ import com.layoutxml.twelveish.SettingsManager; import com.layoutxml.twelveish.activities.AboutActivityP; import com.layoutxml.twelveish.activities.ColorSelectionActivity; +import com.layoutxml.twelveish.activities.TextSelectionActivity; import com.layoutxml.twelveish.adapters.ImageRecyclerViewAdapter; +import com.layoutxml.twelveish.adapters.SeekerRecyclerViewAdapter; import com.layoutxml.twelveish.adapters.SwitchRecyclerViewAdapter; import com.layoutxml.twelveish.adapters.TextviewRecyclerViewAdapter; +import com.layoutxml.twelveish.objects.Triple; import java.util.ArrayList; import java.util.List; -public class MainTextSettingsFragment extends Fragment implements ImageRecyclerViewAdapter.ItemClickImageListener, TextviewRecyclerViewAdapter.ItemClickListener, SwitchRecyclerViewAdapter.ItemClickSwitchListener{ +public class MainTextSettingsFragment extends Fragment implements ImageRecyclerViewAdapter.ItemClickImageListener, TextviewRecyclerViewAdapter.ItemClickListener, SwitchRecyclerViewAdapter.ItemClickSwitchListener, SeekBar.OnSeekBarChangeListener { private ImageRecyclerViewAdapter adapterMI; private TextviewRecyclerViewAdapter adapterMT; private SwitchRecyclerViewAdapter adapterMS; + private SeekerRecyclerViewAdapter adapterMSB; private final String settingsMIName = "settingsMI"; private final String settingsMTName = "settingsMT"; private final String settingsMSName = "settingsMS"; + private final String settingsMSBName = "settingsMSB"; private SettingsManager settingsManager; private CustomizationScreen activity; private List> optionsTI; private static final String TAG = "MainTextSettingsFragmen"; + private List> optionsTT; + + + // Set up request codes for option picker activities + private final int reqColorActive = 0; + private final int reqColorAmbient = 1; + private final int reqFont = 2; + private final int reqCapitalization = 3; + @Nullable @Override @@ -52,14 +67,16 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c optionsTI = new ArrayList<>(); generateColorOptions(); - List> optionsTT = new ArrayList<>(); - optionsTT.add(new Pair("Font","Currently set "+settingsManager.stringHashmap.get(getResources().getString(R.string.preference_font)))); - optionsTT.add(new Pair("Capitalization","Currently set "+settingsManager.integerHashmap.get(getResources().getString(R.string.preference_capitalisation)))); - optionsTT.add(new Pair("Text Size Offset","Currently set "+settingsManager.integerHashmap.get(getResources().getString(R.string.main_text_size_offset)))); + optionsTT = new ArrayList<>(); + generateTextOptions(); + List> optionsTS = new ArrayList<>(); optionsTS.add(new Pair("24h Format",getResources().getString(R.string.preference_military_text_time))); + List> optionsTSB = new ArrayList<>(); + optionsTSB.add(new Triple("Text Size Offset", settingsManager.integerHashmap.get(getString(R.string.secondary_text_size_offset)), 5)); + RecyclerView recyclerViewTI = view.findViewById(R.id.topImageRV); recyclerViewTI.setLayoutManager(new LinearLayoutManager(getContext())); adapterMI = new ImageRecyclerViewAdapter(getContext(),optionsTI, settingsMIName); @@ -72,6 +89,12 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c adapterMT.setClickListener(this); recyclerViewTT.setAdapter(adapterMT); + RecyclerView recyclerViewMSB = view.findViewById(R.id.topSeekRV); + recyclerViewMSB.setLayoutManager(new LinearLayoutManager(getContext())); + adapterMSB = new SeekerRecyclerViewAdapter(getContext(), optionsTSB, settingsMSBName); + adapterMSB.setOnSeekBarChangeListener(this); + recyclerViewMSB.setAdapter(adapterMSB); + RecyclerView recyclerViewTS = view.findViewById(R.id.topSwitchRV); recyclerViewTS.setLayoutManager(new LinearLayoutManager(getContext())); adapterMS = new SwitchRecyclerViewAdapter(getContext(),optionsTS, settingsMSName, settingsManager); @@ -87,6 +110,15 @@ private void generateColorOptions() { optionsTI.add(new Pair("Text Color in Ambient",settingsManager.integerHashmap.get(getResources().getString(R.string.preference_main_text_color_ambient)))); } + private void generateTextOptions(){ + optionsTT.clear(); + + int capitalization = settingsManager.integerHashmap.get(getResources().getString(R.string.preference_capitalisation)); + String[] capitalizationString = {"all words title case", "all uppercase", "all lowercase", "first world title case", "first word in every line title case"}; + optionsTT.add(new Pair("Font","Currently set to "+settingsManager.stringHashmap.get(getResources().getString(R.string.preference_font)))); + optionsTT.add(new Pair("Capitalization","Currently set to "+capitalizationString[capitalization])); + } + @Override public void onItemClickSwitch(View view, int position, boolean newValue, String name) { if (name.equals(settingsMSName)) { @@ -102,6 +134,30 @@ public void onItemClickImage(View view, int position, Integer currentColor, Stri @Override public void onItemClick(View view, int position, String name){ + if(name.equals(settingsMTName)){ + Intent intent; + switch (position){ + case 0: + intent = new Intent(getContext(), TextSelectionActivity.class); + intent.putExtra("SETTING_TYPE", TextSelectionActivity.FONT_SELECTION); + startActivityForResult(intent, reqFont); + break; + case 1: + intent = new Intent(getContext(), TextSelectionActivity.class); + intent.putExtra("SETTING_TYPE", TextSelectionActivity.CAPITALIZATION); + startActivityForResult(intent, reqCapitalization); + break; + } + } + } + + @Override + public void onProgressChanged(SeekBar seekBar, int newValue, boolean fromUser) { + if(fromUser){ + settingsManager.integerHashmap.put(getString(R.string.main_text_size_offset), newValue * 7); + settingsManager.significantTimeChange = true; + activity.invalidatePreview(); + } } @Override @@ -110,20 +166,50 @@ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent d if (resultCode==Activity.RESULT_OK) { Log.d(TAG, "onActivityResult: result is for "+requestCode); switch (requestCode) { - case 0: + case reqColorActive: settingsManager.integerHashmap.put(getResources().getString(R.string.preference_main_text_color), data.getIntExtra("newColor", Color.parseColor("#000000"))); generateColorOptions(); adapterMI.notifyDataSetChanged(); break; - case 1: + case reqColorAmbient: settingsManager.integerHashmap.put(getResources().getString(R.string.preference_main_text_color_ambient), data.getIntExtra("newColor", Color.parseColor("#000000"))); generateColorOptions(); adapterMI.notifyDataSetChanged(); break; + case reqFont: + settingsManager.stringHashmap.put(getResources().getString(R.string.preference_font), data.getStringExtra("newFont")); + + settingsManager.significantTimeChange = true; + + optionsTT.clear(); + generateTextOptions(); + adapterMT.notifyDataSetChanged(); + break; + case reqCapitalization: + settingsManager.integerHashmap.put(getResources().getString(R.string.preference_capitalisation), data.getIntExtra("newCapitalization", 0)); + + settingsManager.significantTimeChange = true; + + generateTextOptions(); + adapterMT.notifyDataSetChanged(); + activity.invalidatePreview(); + break; default: break; } } } + + + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + + } } diff --git a/phone/src/main/java/com/layoutxml/twelveish/fragments/SharedSettingsFragment.java b/phone/src/main/java/com/layoutxml/twelveish/fragments/SharedSettingsFragment.java index ff52057..ef19f5d 100644 --- a/phone/src/main/java/com/layoutxml/twelveish/fragments/SharedSettingsFragment.java +++ b/phone/src/main/java/com/layoutxml/twelveish/fragments/SharedSettingsFragment.java @@ -19,12 +19,15 @@ import com.layoutxml.twelveish.R; import com.layoutxml.twelveish.SettingsManager; import com.layoutxml.twelveish.activities.ColorSelectionActivity; +import com.layoutxml.twelveish.activities.LanguageSelectionActivity; +import com.layoutxml.twelveish.activities.TextSelectionActivity; import com.layoutxml.twelveish.adapters.ImageRecyclerViewAdapter; import com.layoutxml.twelveish.adapters.SwitchRecyclerViewAdapter; import com.layoutxml.twelveish.adapters.TextviewRecyclerViewAdapter; import java.util.ArrayList; import java.util.List; +import java.util.Locale; public class SharedSettingsFragment extends Fragment implements ImageRecyclerViewAdapter.ItemClickImageListener, TextviewRecyclerViewAdapter.ItemClickListener{ @@ -35,6 +38,10 @@ public class SharedSettingsFragment extends Fragment implements ImageRecyclerVie private SettingsManager settingsManager; private CustomizationScreen activity; private List> optionsTI; + private List> optionsTT; + private int colorSelectionRequestCode = 0; + private int languageSelectionRequestCode = 1; + RecyclerView recyclerViewTT; @Nullable @Override @@ -47,8 +54,8 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c optionsTI = new ArrayList<>(); generateColorOptions(); - List> optionsTT = new ArrayList<>(); - optionsTT.add(new Pair("Language","Currently set "+settingsManager.stringHashmap.get(getResources().getString(R.string.preference_language)))); + optionsTT = new ArrayList<>(); + generateLanguageOptions(); RecyclerView recyclerViewTI = view.findViewById(R.id.topImageRV); recyclerViewTI.setLayoutManager(new LinearLayoutManager(getContext())); @@ -56,7 +63,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c adapterMI.setClickListener(this); recyclerViewTI.setAdapter(adapterMI); - RecyclerView recyclerViewTT = view.findViewById(R.id.topTextRV); + recyclerViewTT = view.findViewById(R.id.topTextRV); recyclerViewTT.setLayoutManager(new LinearLayoutManager(getContext())); adapterMT = new TextviewRecyclerViewAdapter(getContext(),optionsTT, settingsMTName); adapterMT.setClickListener(this); @@ -70,14 +77,26 @@ private void generateColorOptions() { optionsTI.add(new Pair("Background Color",settingsManager.integerHashmap.get(getResources().getString(R.string.preference_background_color)))); } + private void generateLanguageOptions(){ + optionsTT.clear(); + String chosenLanguage = new Locale(settingsManager.stringHashmap.get(getString(R.string.preference_language))) + .getDisplayLanguage(new Locale("en")); // return the name of the chosen language in English + optionsTT.add(new Pair("Language","Currently set to "+chosenLanguage)); + + } + @Override public void onItemClickImage(View view, int position, Integer currentColor, String name) { Intent intent = new Intent(getContext(), ColorSelectionActivity.class); - startActivityForResult(intent, position); + startActivityForResult(intent, colorSelectionRequestCode); } @Override - public void onItemClick(View view, int position, String name){} + public void onItemClick(View view, int position, String name){ + Intent intent = new Intent(getContext(), LanguageSelectionActivity.class); + intent.putExtra("SETTING_TYPE", TextSelectionActivity.LANGUAGE_SELECTION); + startActivityForResult(intent, languageSelectionRequestCode); + } @Override @@ -89,6 +108,16 @@ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent d generateColorOptions(); adapterMI.notifyDataSetChanged(); break; + case 1: + settingsManager.stringHashmap.put(getResources().getString(R.string.preference_language), data.getStringExtra("newLanguage")); + + settingsManager.significantTimeChange = true; + activity.invalidatePreview(); + + optionsTT.clear(); + generateLanguageOptions(); + adapterMT.notifyDataSetChanged(); + break; default: break; } diff --git a/phone/src/main/java/com/layoutxml/twelveish/fragments/TopSettingsFragment.java b/phone/src/main/java/com/layoutxml/twelveish/fragments/TopSettingsFragment.java index f75f9d0..a23aba0 100644 --- a/phone/src/main/java/com/layoutxml/twelveish/fragments/TopSettingsFragment.java +++ b/phone/src/main/java/com/layoutxml/twelveish/fragments/TopSettingsFragment.java @@ -9,6 +9,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.SeekBar; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -20,24 +21,36 @@ import com.layoutxml.twelveish.R; import com.layoutxml.twelveish.SettingsManager; import com.layoutxml.twelveish.activities.ColorSelectionActivity; +import com.layoutxml.twelveish.activities.TextSelectionActivity; import com.layoutxml.twelveish.adapters.ImageRecyclerViewAdapter; +import com.layoutxml.twelveish.adapters.SeekerRecyclerViewAdapter; import com.layoutxml.twelveish.adapters.SwitchRecyclerViewAdapter; import com.layoutxml.twelveish.adapters.TextviewRecyclerViewAdapter; +import com.layoutxml.twelveish.objects.Triple; import java.util.ArrayList; import java.util.List; -public class TopSettingsFragment extends Fragment implements ImageRecyclerViewAdapter.ItemClickImageListener, TextviewRecyclerViewAdapter.ItemClickListener, SwitchRecyclerViewAdapter.ItemClickSwitchListener{ +public class TopSettingsFragment extends Fragment implements ImageRecyclerViewAdapter.ItemClickImageListener, TextviewRecyclerViewAdapter.ItemClickListener, SwitchRecyclerViewAdapter.ItemClickSwitchListener, SeekBar.OnSeekBarChangeListener { private ImageRecyclerViewAdapter adapterTI; private TextviewRecyclerViewAdapter adapterTT; private SwitchRecyclerViewAdapter adapterTS; + private SeekerRecyclerViewAdapter adapterTSB; private final String settingsTIName = "settingsTI"; private final String settingsTTName = "settingsTT"; private final String settingsTSName = "settingsTS"; + private final String settingsTSBName = "settingsTSB"; private SettingsManager settingsManager; private CustomizationScreen activity; private List> optionsTI; + private List> optionsTT; + + private final int reqSecColorActive = 0; + private final int reqSecColorAmbient = 1; + private final int reqFont = 2; + private final int reqDateOrder = 3; + private final int reqDateSymbol = 4; @Nullable @Override @@ -50,11 +63,8 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c optionsTI = new ArrayList<>(); generateColorOptions(); - List> optionsTT = new ArrayList<>(); - optionsTT.add(new Pair("Font","Currently set "+settingsManager.stringHashmap.get(getResources().getString(R.string.preference_font_secondary)))); //TODO - optionsTT.add(new Pair("Date Order","Currently set "+settingsManager.integerHashmap.get(getResources().getString(R.string.preference_date_order)))); - optionsTT.add(new Pair("Date Separator Symbol","Currently set "+settingsManager.stringHashmap.get(getResources().getString(R.string.preference_date_separator)))); - optionsTT.add(new Pair("Text Size Offset","Currently set "+settingsManager.integerHashmap.get(getResources().getString(R.string.secondary_text_size_offset)))); + optionsTT = new ArrayList<>(); + generateTextOptions(); List> optionsTS = new ArrayList<>(); optionsTS.add(new Pair("Digital Clock",getString(R.string.preference_show_digital_clock))); @@ -68,6 +78,9 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c optionsTS.add(new Pair("24h Format",getResources().getString(R.string.preference_military_time))); optionsTS.add(new Pair("Show Seconds in Active",getResources().getString(R.string.preference_show_seconds))); + List> optionsTSB = new ArrayList<>(); + optionsTSB.add(new Triple("Text Size Offset", settingsManager.integerHashmap.get(getString(R.string.secondary_text_size_offset)), 5)); + RecyclerView recyclerViewTI = view.findViewById(R.id.topImageRV); recyclerViewTI.setLayoutManager(new LinearLayoutManager(getContext())); adapterTI = new ImageRecyclerViewAdapter(getContext(),optionsTI,settingsTIName); @@ -80,6 +93,13 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c adapterTT.setClickListener(this); recyclerViewTT.setAdapter(adapterTT); + RecyclerView recyclerViewTSB = view.findViewById(R.id.topSeekRV); + recyclerViewTSB.setLayoutManager(new LinearLayoutManager(getContext())); + adapterTSB = new SeekerRecyclerViewAdapter(getContext(), optionsTSB, settingsTSBName); + adapterTSB.setOnSeekBarChangeListener(this); + recyclerViewTSB.setAdapter(adapterTSB); + + RecyclerView recyclerViewTS = view.findViewById(R.id.topSwitchRV); recyclerViewTS.setLayoutManager(new LinearLayoutManager(getContext())); adapterTS = new SwitchRecyclerViewAdapter(getContext(),optionsTS,settingsTSName, settingsManager); @@ -95,6 +115,18 @@ private void generateColorOptions() { optionsTI.add(new Pair("Text Color in Ambient",settingsManager.integerHashmap.get(getResources().getString(R.string.preference_secondary_text_color_ambient)))); } + private void generateTextOptions(){ + optionsTT.clear(); + + int dateOrder = settingsManager.integerHashmap.get(getResources().getString(R.string.preference_date_order)); + String[] dateOrderString = {"Month-Day-Year", "Day-Month-Year", "Year-Month-Day", "Year-Day-Month"}; + + // TODO: Implement font selection for the top text on the watch. + // optionsTT.add(new Pair("Font","Currently set to "+settingsManager.stringHashmap.get(getResources().getString(R.string.preference_font_secondary)))); + optionsTT.add(new Pair("Date Order","Currently set to "+dateOrderString[dateOrder])); + optionsTT.add(new Pair("Date Separator Symbol","Currently set to "+settingsManager.stringHashmap.get(getResources().getString(R.string.preference_date_separator)))); + } + @Override public void onItemClickSwitch(View view, int position, boolean newValue, String name) { if (name.equals(settingsTSName)) { @@ -109,25 +141,77 @@ public void onItemClickImage(View view, int position, Integer currentColor, Stri } @Override - public void onItemClick(View view, int position, String name){} + public void onItemClick(View view, int position, String name){ + if(name.equals(settingsTTName)){ + Intent intent = new Intent(getContext(), TextSelectionActivity.class); + intent.putExtra("SETTING_TYPE", position + 3); + startActivityForResult(intent,position + 3); + } + } + + @Override + public void onProgressChanged(SeekBar seekBar, int newValue, boolean fromUser) { + if(fromUser){ + settingsManager.integerHashmap.put(getString(R.string.secondary_text_size_offset), newValue * 3); + settingsManager.significantTimeChange = true; + activity.invalidatePreview(); + } + } @Override public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { if (resultCode== Activity.RESULT_OK) { switch (requestCode) { - case 0: + case reqSecColorActive: settingsManager.integerHashmap.put(getResources().getString(R.string.preference_secondary_text_color), data.getIntExtra("newColor", Color.parseColor("#000000"))); generateColorOptions(); adapterTI.notifyDataSetChanged(); break; - case 1: + case reqSecColorAmbient: settingsManager.integerHashmap.put(getResources().getString(R.string.preference_secondary_text_color_ambient), data.getIntExtra("newColor", Color.parseColor("#000000"))); generateColorOptions(); adapterTI.notifyDataSetChanged(); break; + case reqFont: + settingsManager.stringHashmap.put(activity.getString(R.string.preference_font_secondary), data.getStringExtra("newFont")); + + settingsManager.significantTimeChange = true; + generateTextOptions(); + adapterTT.notifyDataSetChanged(); + break; + case reqDateOrder: + settingsManager.integerHashmap.put(activity.getString(R.string.preference_date_order), data.getIntExtra("newDateOrder", 0)); + + generateTextOptions(); + settingsManager.significantTimeChange = true; + + adapterTT.notifyDataSetChanged(); + activity.invalidatePreview(); + break; + case reqDateSymbol: + settingsManager.stringHashmap.put(getString(R.string.preference_date_separator), data.getStringExtra("newSeparator")); + + generateTextOptions(); + settingsManager.significantTimeChange = true; + + adapterTT.notifyDataSetChanged(); + activity.invalidatePreview(); + break; default: break; } } } + + + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + + } } diff --git a/phone/src/main/java/com/layoutxml/twelveish/objects/Triple.java b/phone/src/main/java/com/layoutxml/twelveish/objects/Triple.java new file mode 100644 index 0000000..f3235cd --- /dev/null +++ b/phone/src/main/java/com/layoutxml/twelveish/objects/Triple.java @@ -0,0 +1,14 @@ +package com.layoutxml.twelveish.objects; + +public class Triple { + + public final T first; + public final T1 second; + public final T2 third; + + public Triple(T first, T1 second, T2 third) { + this.first = first; + this.second = second; + this.third = third; + } +} diff --git a/phone/src/main/java/com/layoutxml/twelveish/objects/WatchPreviewView.java b/phone/src/main/java/com/layoutxml/twelveish/objects/WatchPreviewView.java index a9f70e6..82226e6 100644 --- a/phone/src/main/java/com/layoutxml/twelveish/objects/WatchPreviewView.java +++ b/phone/src/main/java/com/layoutxml/twelveish/objects/WatchPreviewView.java @@ -32,11 +32,12 @@ import java.lang.ref.WeakReference; import java.util.Calendar; import java.util.Locale; +import java.util.Map; public class WatchPreviewView extends View implements WordClockListener { - private final int secondaryTextOffset = 0; //TODO - private final int mainTextOffset = 0; //TODO + private int secondaryTextOffset = 0; + private int mainTextOffset = 0; private int height = 0; private Paint paint; private Paint paintFrame; @@ -71,11 +72,15 @@ public class WatchPreviewView extends View implements WordClockListener { private int secondaryTextSizeDP = 14; private int batteryLevel = 100; private int previousHight = 0; + private Context activity; + private String oldLanguage = ""; public WatchPreviewView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); paint = new Paint(); paintFrame = new Paint(); + activity = context; + try { CustomizationScreen activity = (CustomizationScreen) getContext(); settingsManager = activity.getSettingsManagerComponent().getSettingsManager(); @@ -84,18 +89,22 @@ public WatchPreviewView(Context context, @Nullable AttributeSet attrs) { Log.d(TAG, "communicatorID" + communicator); Log.d(TAG, "WatchPreviewView: from customization"); } catch (Exception e) { - Log.d(TAG, "WatchPreviewView: from home screen"); SettingsManagerComponent settingsManagerComponent = DaggerSettingsManagerComponent.factory().create(getContext()); settingsManager = settingsManagerComponent.getSettingsManager(); + HomeScreen activity = (HomeScreen) getContext(); + communicator = ((App) activity.getApplication()).getCommunicatorComponent().getCommunicator(); + communicator.requestPreferences(getContext(), new WeakReference(this)); + Log.d(TAG, "WatchPreviewView: from home screen"); + Log.d(TAG, "communicatorID: " + communicator); } mTextPaint = new Paint(); - mTextPaint.setTypeface(NORMAL_TYPEFACE); + mTextPaint.setTypeface(getFont(settingsManager.stringHashmap.get(getResources().getString(R.string.preference_font_secondary)))); mTextPaint.setAntiAlias(true); mTextPaint.setTextAlign(Paint.Align.CENTER); mTextPaint2 = new Paint(); - mTextPaint2.setTypeface(NORMAL_TYPEFACE); + mTextPaint2.setTypeface(getFont(settingsManager.stringHashmap.get(getResources().getString(R.string.preference_font)))); mTextPaint2.setAntiAlias(true); mTextPaint2.setTextAlign(Paint.Align.CENTER); @@ -105,59 +114,36 @@ public WatchPreviewView(Context context, @Nullable AttributeSet attrs) { mTextPaint.setTextSize(22 + secondaryTextOffset); //secondary text mTextPaint2.setTextSize(24 + mainTextOffset); - Typeface NORMAL_TYPEFACE2; - switch (settingsManager.stringHashmap.get(context.getString(R.string.preference_font))) { - case "robotolight": - NORMAL_TYPEFACE2 = Typeface.create("sans-serif-light", Typeface.NORMAL); - mTextPaint2.setTypeface(NORMAL_TYPEFACE2); - break; - case "alegreya": - NORMAL_TYPEFACE2 = ResourcesCompat.getFont(context, R.font.alegreya); - mTextPaint2.setTypeface(NORMAL_TYPEFACE2); - break; - case "cabin": - NORMAL_TYPEFACE2 = ResourcesCompat.getFont(context, R.font.cabin); - mTextPaint2.setTypeface(NORMAL_TYPEFACE2); - break; - case "ibmplexsans": - NORMAL_TYPEFACE2 = ResourcesCompat.getFont(context, R.font.ibmplexsans); - mTextPaint2.setTypeface(NORMAL_TYPEFACE2); - break; - case "inconsolata": - NORMAL_TYPEFACE2 = ResourcesCompat.getFont(context, R.font.inconsolata); - mTextPaint2.setTypeface(NORMAL_TYPEFACE2); - break; - case "merriweather": - NORMAL_TYPEFACE2 = ResourcesCompat.getFont(context, R.font.merriweather); - mTextPaint2.setTypeface(NORMAL_TYPEFACE2); - break; - case "nunito": - NORMAL_TYPEFACE2 = ResourcesCompat.getFont(context, R.font.nunito); - mTextPaint2.setTypeface(NORMAL_TYPEFACE2); - break; - case "pacifico": - NORMAL_TYPEFACE2 = ResourcesCompat.getFont(context, R.font.pacifico); - mTextPaint2.setTypeface(NORMAL_TYPEFACE2); - break; - case "quattrocento": - NORMAL_TYPEFACE2 = ResourcesCompat.getFont(context, R.font.quattrocento); - mTextPaint2.setTypeface(NORMAL_TYPEFACE2); - break; - case "quicksand": - NORMAL_TYPEFACE2 = ResourcesCompat.getFont(context, R.font.quicksand); - mTextPaint2.setTypeface(NORMAL_TYPEFACE2); - break; - case "rubik": - NORMAL_TYPEFACE2 = ResourcesCompat.getFont(context, R.font.rubik); - mTextPaint2.setTypeface(NORMAL_TYPEFACE2); - break; - default: - NORMAL_TYPEFACE2 = Typeface.create("sans-serif-light", Typeface.NORMAL); - mTextPaint2.setTypeface(NORMAL_TYPEFACE2); - break; - } - switch (settingsManager.stringHashmap.get(context.getString(R.string.preference_language))) { + + generateAffixes(); // Fetch the prefixes and suffixes for the chosen language + + final Handler handler = new Handler(Looper.getMainLooper()); + Runnable reDrawer = new Runnable(){ + public void run(){ + invalidate(); + handler.postDelayed(this,1000); + } + }; + reDrawer.run(); + + getContext().registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + batteryLevel = (int) (100 * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) / ((float) (intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)))); + text1 = (batteryLevel + "%"); + } + }, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + height = MeasureSpec.getSize(heightMeasureSpec); + } + + private void generateAffixes(){ + switch (settingsManager.stringHashmap.get(activity.getString(R.string.preference_language))) { case "nl": Prefixes = getResources().getStringArray(R.array.PrefixesNL); Suffixes = getResources().getStringArray(R.array.SuffixesNL); @@ -280,28 +266,7 @@ public WatchPreviewView(Context context, @Nullable AttributeSet attrs) { break; } - final Handler handler = new Handler(Looper.getMainLooper()); - Runnable reDrawer = new Runnable(){ - public void run(){ - invalidate(); - handler.postDelayed(this,1000); - } - }; - reDrawer.run(); - - getContext().registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - batteryLevel = (int) (100 * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) / ((float) (intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)))); - text1 = (batteryLevel + "%"); - } - }, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - height = MeasureSpec.getSize(heightMeasureSpec); + oldLanguage = settingsManager.stringHashmap.get(activity.getString(R.string.preference_language)); } @Override @@ -311,6 +276,16 @@ protected void onDraw(Canvas canvas) { int y = getHeight()/2; paint.setColor(Color.parseColor("#000000")); + if(!oldLanguage.equals(settingsManager.stringHashmap.get(activity.getString(R.string.preference_language)))) // The language has been changed, update our prefixes and suffixes + generateAffixes(); + + mTextPaint.setTypeface(getFont(settingsManager.stringHashmap.get(getResources().getString(R.string.preference_font_secondary)))); + + // Update the size offsets + mainTextOffset = settingsManager.integerHashmap.get(getResources().getString(R.string.main_text_size_offset)); + secondaryTextOffset = settingsManager.integerHashmap.get(getResources().getString(R.string.secondary_text_size_offset)); + + if (mAmbient) paintFrame.setColor(Color.parseColor("#333333")); else @@ -350,6 +325,8 @@ protected void onDraw(Canvas canvas) { : String.format(Locale.UK, "%d:%02d:%02d" + ampmSymbols, hourDigital, minutes, seconds); //Draw digital clock, date, battery percentage and day of the week + + mTextPaint.setTypeface(getFont(settingsManager.stringHashmap.get(getResources().getString(R.string.preference_font_secondary)))); // Set the font for our digital clock. float firstSeparator = 60.0f; if ((mAmbient && !settingsManager.booleanHashmap.get(getContext().getString(R.string.preference_show_digital_clock_ambient))) || (!mAmbient && !settingsManager.booleanHashmap.get(getContext().getString(R.string.preference_show_digital_clock)))) { text = ""; @@ -408,6 +385,7 @@ protected void onDraw(Canvas canvas) { //Draw text clock if (significantTimeChange) { + mTextPaint2.setTypeface(getFont(settingsManager.stringHashmap.get(getResources().getString(R.string.preference_font)))); mTextPaint.setTextSize(getHeight() * 0.06f + secondaryTextOffset); //secondary text getDate(); lastSignificantMinutes = minutes; @@ -453,6 +431,62 @@ else if (hourText > 12 && !settingsManager.booleanHashmap.get(getContext().getSt //TODO placeholder } + private Typeface getFont(String newFont){ + Typeface NORMAL_TYPEFACE2; + switch (newFont) { + case "robotolight": + NORMAL_TYPEFACE2 = Typeface.create("sans-serif-light", Typeface.NORMAL); + // mTextPaint2.setTypeface(NORMAL_TYPEFACE2); + break; + case "alegreya": + NORMAL_TYPEFACE2 = ResourcesCompat.getFont(activity, R.font.alegreya); + // mTextPaint2.setTypeface(NORMAL_TYPEFACE2); + break; + case "cabin": + NORMAL_TYPEFACE2 = ResourcesCompat.getFont(activity, R.font.cabin); + // mTextPaint2.setTypeface(NORMAL_TYPEFACE2); + break; + case "ibmplexsans": + NORMAL_TYPEFACE2 = ResourcesCompat.getFont(activity, R.font.ibmplexsans); + // mTextPaint2.setTypeface(NORMAL_TYPEFACE2); + break; + case "inconsolata": + NORMAL_TYPEFACE2 = ResourcesCompat.getFont(activity, R.font.inconsolata); + // mTextPaint2.setTypeface(NORMAL_TYPEFACE2); + break; + case "merriweather": + NORMAL_TYPEFACE2 = ResourcesCompat.getFont(activity, R.font.merriweather); + // mTextPaint2.setTypeface(NORMAL_TYPEFACE2); + break; + case "nunito": + NORMAL_TYPEFACE2 = ResourcesCompat.getFont(activity, R.font.nunito); + // mTextPaint2.setTypeface(NORMAL_TYPEFACE2); + break; + case "pacifico": + NORMAL_TYPEFACE2 = ResourcesCompat.getFont(activity, R.font.pacifico); + // mTextPaint2.setTypeface(NORMAL_TYPEFACE2); + break; + case "quattrocento": + NORMAL_TYPEFACE2 = ResourcesCompat.getFont(activity, R.font.quattrocento); + // mTextPaint2.setTypeface(NORMAL_TYPEFACE2); + break; + case "quicksand": + NORMAL_TYPEFACE2 = ResourcesCompat.getFont(activity, R.font.quicksand); + // mTextPaint2.setTypeface(NORMAL_TYPEFACE2); + break; + case "rubik": + NORMAL_TYPEFACE2 = ResourcesCompat.getFont(activity, R.font.rubik); + // mTextPaint2.setTypeface(NORMAL_TYPEFACE2); + break; + default: + NORMAL_TYPEFACE2 = Typeface.create("sans-serif-light", Typeface.NORMAL); + // mTextPaint2.setTypeface(NORMAL_TYPEFACE2); + break; + } + + return NORMAL_TYPEFACE2; + } + private void getDate() { //Get date int first, second, third; @@ -524,4 +558,29 @@ public void changeAmbientMode(boolean value) { significantTimeChange = true; Log.d(TAG, "changeAmbientMode: "+value); } + + public void loadSettings(SettingsManager newSettings){ + for(Map.Entry preference : newSettings.stringHashmap.entrySet()){ + String key = preference.getKey(); + String value = preference.getValue(); + if(value != null) + this.settingsManager.stringHashmap.put(key, value); + } + + for(Map.Entry preference : newSettings.booleanHashmap.entrySet()){ + String key = preference.getKey(); + boolean value = preference.getValue(); + this.settingsManager.booleanHashmap.put(key, value); + } + + for(Map.Entry preference : newSettings.integerHashmap.entrySet()){ + String key = preference.getKey(); + int value = preference.getValue(); + + this.settingsManager.integerHashmap.put(key, value); + } + + settingsManager.significantTimeChange = true; + invalidate(); + } } diff --git a/phone/src/main/res/layout/customize_screen.xml b/phone/src/main/res/layout/customize_screen.xml index a910206..03238fb 100644 --- a/phone/src/main/res/layout/customize_screen.xml +++ b/phone/src/main/res/layout/customize_screen.xml @@ -72,12 +72,13 @@ diff --git a/phone/src/main/res/layout/home_screen.xml b/phone/src/main/res/layout/home_screen.xml index 597eea9..4a14dd0 100644 --- a/phone/src/main/res/layout/home_screen.xml +++ b/phone/src/main/res/layout/home_screen.xml @@ -28,7 +28,7 @@ android:layout_marginStart="16dp" android:layout_marginEnd="16dp" android:layout_marginBottom="32dp" - android:text="New" + android:text="Edit" app:layout_constraintBottom_toTopOf="@+id/buttonInstall" app:layout_constraintEnd_toStartOf="@+id/guideline" app:layout_constraintStart_toStartOf="parent" diff --git a/phone/src/main/res/layout/slider_item.xml b/phone/src/main/res/layout/slider_item.xml new file mode 100644 index 0000000..93572c5 --- /dev/null +++ b/phone/src/main/res/layout/slider_item.xml @@ -0,0 +1,33 @@ + + + + + + + + + + \ No newline at end of file diff --git a/phone/src/main/res/layout/top_settings_fragment.xml b/phone/src/main/res/layout/top_settings_fragment.xml index 096fc15..cdc2520 100644 --- a/phone/src/main/res/layout/top_settings_fragment.xml +++ b/phone/src/main/res/layout/top_settings_fragment.xml @@ -23,8 +23,15 @@ android:id="@+id/topTextRV" android:layout_width="match_parent" android:layout_height="wrap_content"> + + + secondaryColorActive secondaryColor militaryTime - militarytextTime + militaryTextTime dateOrder stringOption capitalisation @@ -46,6 +46,23 @@ secondaryTextSizeOffset mainTextSizeReal + + nl + en + fi + fr + de + el + hu + it + lt + no + pt + ru + es + sv + + twelve one @@ -73,8 +90,8 @@ twenty three - - + + a\u00A0quarter past a quarter past almost\u00A0half past @@ -89,16 +106,16 @@ ish or\u00A0so - + or\u00A0so - - + + ish or\u00A0so - + or\u00A0so - - + + Su @@ -151,18 +168,18 @@ apie - - + + su\u00A0ketvirčiu su\u00A0ketvirčiu su\u00A0puse su\u00A0puse su\u00A0puse su\u00A0puse - - - - + + + + Se @@ -215,18 +232,18 @@ lähes - - - - - - - - - - - - + + + + + + + + + + + + Su @@ -265,21 +282,21 @@ двадцать три - - + + почти - + почти - - - + + + почти\u00A0без четверти без четверти почти - + - + или\u00A0около того с\u00A0четвертью с\u00A0четвертью @@ -287,10 +304,10 @@ с\u00A0половиной с\u00A0половиной с\u00A0половиной - - - - + + + + Вс @@ -330,31 +347,31 @@ kurz nach - bald viertel\u00A0nach - fast viertel\u00A0nach - viertel\u00A0nach + bald Viertel\u00A0nach + fast Viertel\u00A0nach + Viertel\u00A0nach bald halb kurz vor halb kurz nach halb - bald viertel\u00A0vor - fast viertel\u00A0vor - viertel\u00A0vor + bald Viertel\u00A0vor + fast Viertel\u00A0vor + Viertel\u00A0vor bald fast - - - + + + oder\u00A0so - - - - - + + + + + oder\u00A0so - - + + So @@ -393,8 +410,8 @@ huszonhárom - - + + negyed negyed lassan fél @@ -403,22 +420,22 @@ fél háromnegyed háromnegyed - + mindjárt múlt körül lesz - - + + lesz - + múlt - + múlt lesz - + Va @@ -457,8 +474,8 @@ le undici - - + + quasi circa quasi @@ -466,7 +483,7 @@ circa poco più\u00A0che quasi - + quasi pressapoco @@ -481,8 +498,8 @@ e mezza meno un quarto meno qualcosa - - + + Do @@ -521,21 +538,21 @@ las once - - + + casi - - + + casi - - - - - + + + + + casi - + y cinco y cuarto y cuarto