From a56d18053131c972b38499f25332ff62ce6a3e8b Mon Sep 17 00:00:00 2001
From: Daniel Dakhno <dakhnod@gmail.com>
Date: Wed, 20 Nov 2019 18:59:13 +0100
Subject: [PATCH] added second timezone button function

---
 .../devices/qhybrid/ConfigActivity.java       | 58 ++++++++++++++++++-
 .../devices/qhybrid/QHybridSupport.java       | 13 +++++
 .../devices/qhybrid/adapter/WatchAdapter.java |  1 +
 .../adapter/fossil/FossilWatchAdapter.java    | 13 +++++
 .../adapter/misfit/MisfitWatchAdapter.java    |  5 ++
 .../qhybrid/buttonconfig/ConfigPayload.java   |  5 ++
 .../ConfigurationGetRequest.java              |  2 +
 .../ConfigurationPutRequest.java              | 12 ++++
 .../res/layout/activity_qhybrid_settings.xml  | 18 ++++++
 9 files changed, 126 insertions(+), 1 deletion(-)

diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/ConfigActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/ConfigActivity.java
index 8c6435ed7..5ab1a4900 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/ConfigActivity.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/qhybrid/ConfigActivity.java
@@ -74,7 +74,7 @@ public class ConfigActivity extends AbstractGBActivity {
 
     SharedPreferences prefs;
 
-    TextView timeOffsetView;
+    TextView timeOffsetView, timezoneOffsetView;
 
     GBDevice device;
 
@@ -136,6 +136,51 @@ public class ConfigActivity extends AbstractGBActivity {
         });
         updateTimeOffset();
 
+
+        timezoneOffsetView = findViewById(R.id.timezoneOffset);
+        timezoneOffsetView.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                int timeOffset = prefs.getInt("QHYBRID_TIMEZONE_OFFSET", 0);
+                LinearLayout layout2 = new LinearLayout(ConfigActivity.this);
+                layout2.setOrientation(LinearLayout.HORIZONTAL);
+
+                final NumberPicker hourPicker = new NumberPicker(ConfigActivity.this);
+                hourPicker.setMinValue(0);
+                hourPicker.setMaxValue(23);
+                hourPicker.setValue(timeOffset / 60);
+
+                final NumberPicker minPicker = new NumberPicker(ConfigActivity.this);
+                minPicker.setMinValue(0);
+                minPicker.setMaxValue(59);
+                minPicker.setValue(timeOffset % 60);
+
+                layout2.addView(hourPicker);
+                TextView tw = new TextView(ConfigActivity.this);
+                tw.setText(":");
+                layout2.addView(tw);
+                layout2.addView(minPicker);
+
+                layout2.setGravity(Gravity.CENTER);
+
+                new AlertDialog.Builder(ConfigActivity.this)
+                        .setTitle("offset timezone by")
+                        .setView(layout2)
+                        .setPositiveButton("ok", new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialogInterface, int i) {
+                                prefs.edit().putInt("QHYBRID_TIMEZONE_OFFSET", hourPicker.getValue() * 60 + minPicker.getValue()).apply();
+                                updateTimezoneOffset();
+                                LocalBroadcastManager.getInstance(ConfigActivity.this).sendBroadcast(new Intent(QHybridSupport.QHYBRID_COMMAND_UPDATE_TIMEZONE));
+                                Toast.makeText(ConfigActivity.this, "change might take some seconds...", Toast.LENGTH_SHORT).show();
+                            }
+                        })
+                        .setNegativeButton("cancel", null)
+                        .show();
+            }
+        });
+        updateTimezoneOffset();
+
         setTitle(R.string.preferences_qhybrid_settings);
 
         ListView appList = findViewById(R.id.qhybrid_appList);
@@ -263,6 +308,17 @@ public class ConfigActivity extends AbstractGBActivity {
         );
     }
 
+
+    private void updateTimezoneOffset() {
+        int timeOffset = prefs.getInt("QHYBRID_TIMEZONE_OFFSET", 0);
+        DecimalFormat format = new DecimalFormat("00");
+        timezoneOffsetView.setText(
+                format.format(timeOffset / 60) + ":" +
+                        format.format(timeOffset % 60)
+        );
+    }
+
+
     private void setSettingsEnabled(boolean enables) {
         findViewById(R.id.settingsLayout).setAlpha(enables ? 1f : 0.2f);
     }
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/QHybridSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/QHybridSupport.java
index a96009718..ccd4f10f8 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/QHybridSupport.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/QHybridSupport.java
@@ -61,6 +61,7 @@ public class QHybridSupport extends QHybridBaseSupport {
     public static final String QHYBRID_COMMAND_SET = "qhybrid_command_set";
     public static final String QHYBRID_COMMAND_VIBRATE = "qhybrid_command_vibrate";
     public static final String QHYBRID_COMMAND_UPDATE = "qhybrid_command_update";
+    public static final String QHYBRID_COMMAND_UPDATE_TIMEZONE = "qhybrid_command_update_timezone";
     public static final String QHYBRID_COMMAND_NOTIFICATION = "qhybrid_command_notification";
     public static final String QHYBRID_COMMAND_UPDATE_SETTINGS = "nodomain.freeyourgadget.gadgetbridge.Q_UPDATE_SETTINGS";
     public static final String QHYBRID_COMMAND_OVERWRITE_BUTTONS = "nodomain.freeyourgadget.gadgetbridge.Q_OVERWRITE_BUTTONS";
@@ -82,6 +83,7 @@ public class QHybridSupport extends QHybridBaseSupport {
     public static final String ITEM_HAS_ACTIVITY_HAND = "HAS_ACTIVITY_HAND";
     public static final String ITEM_USE_ACTIVITY_HAND = "USE_ACTIVITY_HAND";
     public static final String ITEM_LAST_HEARTBEAT = "LAST_HEARTBEAT";
+    public static final String ITEM_TIMEZONE_OFFSET = "STEPTIMEZONE_OFFSET_COUNT";
 
     private static final Logger logger = LoggerFactory.getLogger(QHybridSupport.class);
 
@@ -106,6 +108,7 @@ public class QHybridSupport extends QHybridBaseSupport {
         commandFilter.addAction(QHYBRID_COMMAND_SET);
         commandFilter.addAction(QHYBRID_COMMAND_VIBRATE);
         commandFilter.addAction(QHYBRID_COMMAND_UPDATE);
+        commandFilter.addAction(QHYBRID_COMMAND_UPDATE_TIMEZONE);
         commandFilter.addAction(QHYBRID_COMMAND_NOTIFICATION);
         commandFilter.addAction(QHYBRID_COMMAND_UPDATE_SETTINGS);
         commandFilter.addAction(QHYBRID_COMMAND_OVERWRITE_BUTTONS);
@@ -149,6 +152,10 @@ public class QHybridSupport extends QHybridBaseSupport {
                         onSetTime();
                         break;
                     }
+                    case QHYBRID_COMMAND_UPDATE_TIMEZONE:{
+                        loadTimezoneOffset();
+                        break;
+                    }
                     case QHYBRID_COMMAND_UPDATE_SETTINGS: {
                         String newSetting = intent.getStringExtra("EXTRA_SETTING");
                         switch (newSetting) {
@@ -240,6 +247,12 @@ public class QHybridSupport extends QHybridBaseSupport {
         timeOffset = getContext().getSharedPreferences(getContext().getPackageName(), Context.MODE_PRIVATE).getInt("QHYBRID_TIME_OFFSET", 0);
     }
 
+    private void loadTimezoneOffset(){
+        short offset = (short) getContext().getSharedPreferences(getContext().getPackageName(), Context.MODE_PRIVATE).getInt("QHYBRID_TIMEZONE_OFFSET", 0);
+
+        this.watchAdapter.setTimezoneOffsetMinutes(offset);
+    }
+
     public long getTimeOffset(){
         return this.timeOffset;
     }
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/WatchAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/WatchAdapter.java
index 2e7205a1d..99a85b325 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/WatchAdapter.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/WatchAdapter.java
@@ -42,6 +42,7 @@ public abstract class WatchAdapter {
     public abstract void setVibrationStrength(short strength);
     public abstract void syncNotificationSettings();
     public abstract void onTestNewFunction();
+    public abstract void setTimezoneOffsetMinutes(short offset);
 
     public abstract boolean supportsFindDevice();
     public abstract boolean supportsExtendedVibration();
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil/FossilWatchAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil/FossilWatchAdapter.java
index ae73a2fab..1bed86745 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil/FossilWatchAdapter.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil/FossilWatchAdapter.java
@@ -261,6 +261,19 @@ public class FossilWatchAdapter extends WatchAdapter {
         );
     }
 
+    @Override
+    public void setTimezoneOffsetMinutes(short offset) {
+        queueWrite(new ConfigurationPutRequest(new ConfigurationPutRequest.TimezoneOffsetConfigItem(offset), this){
+            @Override
+            public void onFilePut(boolean success) {
+                super.onFilePut(success);
+
+                if(success) GB.toast("successfully updated timezone", Toast.LENGTH_SHORT, GB.INFO);
+                else GB.toast("error updating timezone", Toast.LENGTH_SHORT, GB.ERROR);
+            }
+        });
+    }
+
     @Override
     public boolean supportsFindDevice() {
         return false;
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/misfit/MisfitWatchAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/misfit/MisfitWatchAdapter.java
index 807fae0bb..da84b3b64 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/misfit/MisfitWatchAdapter.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/misfit/MisfitWatchAdapter.java
@@ -401,6 +401,11 @@ public class MisfitWatchAdapter extends WatchAdapter {
 
     }
 
+    @Override
+    public void setTimezoneOffsetMinutes(short offset) {
+        GB.toast("old firmware does't support timezones", Toast.LENGTH_LONG, GB.ERROR);
+    }
+
     @Override
     public boolean supportsFindDevice() {
         return supportsExtendedVibration();
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/buttonconfig/ConfigPayload.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/buttonconfig/ConfigPayload.java
index 3763ed0fb..5e3cea6d6 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/buttonconfig/ConfigPayload.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/buttonconfig/ConfigPayload.java
@@ -30,6 +30,11 @@ public enum ConfigPayload {
             new byte[]{(byte) 0x01, (byte) 0x01, (byte) 0x18, (byte) 0x00},
             new byte[]{(byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x18, (byte) 0x2F, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x16, (byte) 0x00, (byte) 0x89, (byte) 0x05, (byte) 0x01, (byte) 0x07, (byte) 0xB0, (byte) 0x02, (byte) 0x00, (byte) 0xB0, (byte) 0x02, (byte) 0x00, (byte) 0xB0, (byte) 0x02, (byte) 0x00, (byte) 0x08, (byte) 0x01, (byte) 0x50, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x6B, (byte) 0x9D, (byte) 0x55, (byte) 0x3A}
     ),
+    SECOND_TIMEZONE(
+            "show second timezone",
+            new byte[]{0x01, (byte) 0x01, (byte) 0x16, (byte) 0x00},
+            new byte[]{0x01, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x16, (byte) 0x2F, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x07, (byte) 0x02, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x16, (byte) 0x00, (byte) 0x89, (byte) 0x05, (byte) 0x01, (byte) 0x07, (byte) 0xB0, (byte) 0x01, (byte) 0x00, (byte) 0xB0, (byte) 0x01, (byte) 0x00, (byte) 0xB0, (byte) 0x01, (byte) 0x00, (byte) 0x08, (byte) 0x01, (byte) 0x50, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x3D, (byte) 0x07, (byte) 0x28, (byte) 0x01}
+    )
     /* PLAY_PAUSE(
             "play/pause music",
             new byte[]{(byte) 0x01, (byte) 0x06, (byte) 0x12, (byte) 0x00},
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/configuration/ConfigurationGetRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/configuration/ConfigurationGetRequest.java
index cd9382d8c..69a9c72f0 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/configuration/ConfigurationGetRequest.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/configuration/ConfigurationGetRequest.java
@@ -29,6 +29,8 @@ public class ConfigurationGetRequest extends FileLookupAndGetRequest {
                 device.addDeviceInfo(new GenericItem(QHybridSupport.ITEM_STEP_GOAL, String.valueOf(((ConfigurationPutRequest.DailyStepGoalConfigItem) item).getValue())));
             }else if(item instanceof ConfigurationPutRequest.CurrentStepCountConfigItem){
                 device.addDeviceInfo(new GenericItem(QHybridSupport.ITEM_STEP_COUNT, String.valueOf(((ConfigurationPutRequest.CurrentStepCountConfigItem) item).getValue())));
+            }else if(item instanceof ConfigurationPutRequest.TimezoneOffsetConfigItem) {
+                device.addDeviceInfo(new GenericItem(QHybridSupport.ITEM_TIMEZONE_OFFSET, String.valueOf(((ConfigurationPutRequest.TimezoneOffsetConfigItem) item).getValue())));
             }
         }
 
diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/configuration/ConfigurationPutRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/configuration/ConfigurationPutRequest.java
index d212511f6..bdd390921 100644
--- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/configuration/ConfigurationPutRequest.java
+++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/configuration/ConfigurationPutRequest.java
@@ -109,6 +109,8 @@ public class ConfigurationPutRequest extends FilePutRequest {
             switch (value.getClass().getName()) {
                 case "java.lang.Byte":
                     return 1;
+                case "java.lang.Short":
+                    return 2;
                 case "java.lang.Integer":
                     return 4;
                 case "java.lang.Long":
@@ -139,6 +141,10 @@ public class ConfigurationPutRequest extends FilePutRequest {
                     buffer.putLong((Long) this.value);
                     break;
                 }
+                case "java.lang.Short": {
+                    buffer.putShort((Short) this.value);
+                    break;
+                }
             }
             return buffer.array();
         }
@@ -175,6 +181,12 @@ public class ConfigurationPutRequest extends FilePutRequest {
         }
     }
 
+    static public class TimezoneOffsetConfigItem extends GenericConfigItem<Short> {
+        public TimezoneOffsetConfigItem(Short value) {
+            super((short) 17, value);
+        }
+    }
+
     static public class VibrationStrengthConfigItem extends GenericConfigItem<Byte> {
         public VibrationStrengthConfigItem(){
             this((byte) -1);
diff --git a/app/src/main/res/layout/activity_qhybrid_settings.xml b/app/src/main/res/layout/activity_qhybrid_settings.xml
index bd9a45223..e2da61eac 100644
--- a/app/src/main/res/layout/activity_qhybrid_settings.xml
+++ b/app/src/main/res/layout/activity_qhybrid_settings.xml
@@ -64,6 +64,24 @@
 
         </RelativeLayout>
 
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentStart="true"
+                android:text="second timezone offset relative to UTC" />
+
+            <TextView
+                android:id="@+id/timezoneOffset"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentEnd="true" />
+
+        </RelativeLayout>
+
         <Button
             android:id="@+id/buttonOverwriteButtons"
             android:layout_width="match_parent"