Fossil Q: Move time offsets to device preferences

This commit is contained in:
Arjan Schrijver
2026-04-05 14:18:10 +02:00
committed by Arjan Schrijver
parent 30aa847fa1
commit efd2c626a5
5 changed files with 144 additions and 174 deletions
@@ -17,7 +17,6 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.devices.qhybrid;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -29,27 +28,18 @@ import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.NumberPicker;
import android.widget.PopupMenu;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
@@ -66,7 +56,6 @@ import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
@@ -96,8 +85,6 @@ public class QHybridConfigActivity extends AbstractGBActivity {
SharedPreferences prefs;
TextView timeOffsetView, timezoneOffsetView;
GBDevice device;
@Override
@@ -114,102 +101,13 @@ public class QHybridConfigActivity extends AbstractGBActivity {
setContentView(R.layout.activity_qhybrid_settings);
findViewById(R.id.buttonOverwriteButtons).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
LocalBroadcastManager.getInstance(QHybridConfigActivity.this).sendBroadcast(new Intent(QHybridSupport.QHYBRID_COMMAND_OVERWRITE_BUTTONS));
}
});
// findViewById(R.id.buttonOverwriteButtons).setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View view) {
// LocalBroadcastManager.getInstance(QHybridConfigActivity.this).sendBroadcast(new Intent(QHybridSupport.QHYBRID_COMMAND_OVERWRITE_BUTTONS));
// }
// });
prefs = GBApplication.getDeviceSpecificSharedPrefs(device.getAddress());
timeOffsetView = findViewById(R.id.qhybridTimeOffset);
timeOffsetView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int timeOffset = prefs.getInt("QHYBRID_TIME_OFFSET", 0);
LinearLayout layout2 = new LinearLayout(QHybridConfigActivity.this);
layout2.setOrientation(LinearLayout.HORIZONTAL);
final NumberPicker hourPicker = new NumberPicker(QHybridConfigActivity.this);
hourPicker.setMinValue(0);
hourPicker.setMaxValue(23);
hourPicker.setValue(timeOffset / 60);
final NumberPicker minPicker = new NumberPicker(QHybridConfigActivity.this);
minPicker.setMinValue(0);
minPicker.setMaxValue(59);
minPicker.setValue(timeOffset % 60);
layout2.addView(hourPicker);
TextView tw = new TextView(QHybridConfigActivity.this);
tw.setText(":");
layout2.addView(tw);
layout2.addView(minPicker);
layout2.setGravity(Gravity.CENTER);
new MaterialAlertDialogBuilder(QHybridConfigActivity.this)
.setTitle(getString(R.string.qhybrid_offset_time_by))
.setView(layout2)
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
prefs.edit().putInt("QHYBRID_TIME_OFFSET", hourPicker.getValue() * 60 + minPicker.getValue()).apply();
updateTimeOffset();
LocalBroadcastManager.getInstance(QHybridConfigActivity.this).sendBroadcast(new Intent(QHybridSupport.QHYBRID_COMMAND_UPDATE));
GB.toast(getString(R.string.qhybrid_changes_delay_prompt), Toast.LENGTH_SHORT, GB.INFO);
}
})
.setNegativeButton("cancel", null)
.show();
}
});
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(QHybridConfigActivity.this);
layout2.setOrientation(LinearLayout.HORIZONTAL);
final NumberPicker hourPicker = new NumberPicker(QHybridConfigActivity.this);
hourPicker.setMinValue(0);
hourPicker.setMaxValue(23);
hourPicker.setValue(timeOffset / 60);
final NumberPicker minPicker = new NumberPicker(QHybridConfigActivity.this);
minPicker.setMinValue(0);
minPicker.setMaxValue(59);
minPicker.setValue(timeOffset % 60);
layout2.addView(hourPicker);
TextView tw = new TextView(QHybridConfigActivity.this);
tw.setText(":");
layout2.addView(tw);
layout2.addView(minPicker);
layout2.setGravity(Gravity.CENTER);
new MaterialAlertDialogBuilder(QHybridConfigActivity.this)
.setTitle(getString(R.string.qhybrid_offset_timezone))
.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(QHybridConfigActivity.this).sendBroadcast(new Intent(QHybridSupport.QHYBRID_COMMAND_UPDATE_TIMEZONE));
GB.toast(getString(R.string.qhybrid_changes_delay_prompt), Toast.LENGTH_SHORT, GB.INFO);
}
})
.setNegativeButton("cancel", null)
.show();
}
});
updateTimezoneOffset();
setTitle(R.string.preferences_qhybrid_settings);
@@ -292,25 +190,6 @@ public class QHybridConfigActivity extends AbstractGBActivity {
}
}
private void updateTimeOffset() {
int timeOffset = prefs.getInt("QHYBRID_TIME_OFFSET", 0);
DecimalFormat format = new DecimalFormat("00");
timeOffsetView.setText(
format.format(timeOffset / 60) + ":" +
format.format(timeOffset % 60)
);
}
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)
);
}
@NonNull
private String getDeviceInfoDetails(final String name) {
ItemWithDetails deviceInfo = device.getDeviceInfo(name);
@@ -342,7 +221,7 @@ public class QHybridConfigActivity extends AbstractGBActivity {
LinearLayout buttonLayout = findViewById(R.id.buttonConfigLayout);
buttonLayout.removeAllViews();
findViewById(R.id.buttonOverwriteButtons).setVisibility(View.GONE);
// findViewById(R.id.buttonOverwriteButtons).setVisibility(View.GONE);
final ConfigPayload[] payloads = ConfigPayload.values();
final String[] names = new String[payloads.length];
for (int i = 0; i < payloads.length; i++)
@@ -266,10 +266,11 @@ public class QHybridCoordinator extends AbstractBLEDeviceCoordinator {
final DeviceSpecificSettings deviceSpecificSettings = new DeviceSpecificSettings();
// Q Hybrid watches, without eInk screen
if (!isHybridHR(device)) {
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_fossilqhybrid_legacy);
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_qhybrid);
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_fossilhybridhr_vibration);
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_fossilhybridhr_calibration);
final List<Integer> generic = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.GENERIC);
generic.add(R.xml.devicesettings_fossilqhybrid_legacy);
generic.add(R.xml.devicesettings_qhybrid);
generic.add(R.xml.devicesettings_fossilhybridhr_vibration);
generic.add(R.xml.devicesettings_fossilhybridhr_calibration);
final List<Integer> developer = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.DEVELOPER);
developer.add(R.xml.devicesettings_fossilhybrids_dev);
return deviceSpecificSettings;
@@ -2,19 +2,34 @@ package nodomain.freeyourgadget.gadgetbridge.devices.qhybrid;
import android.content.Intent;
import android.os.Parcel;
import android.view.Gravity;
import android.widget.LinearLayout;
import android.widget.NumberPicker;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.preference.Preference;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.text.DecimalFormat;
import java.util.Collections;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class QHybridSettingsCustomizer implements DeviceSpecificSettingsCustomizer {
private Preference timeOffsetPref;
private Preference timeZoneOffsetPref;
@Override
public void onPreferenceChange(final Preference preference, final DeviceSpecificSettingsHandler handler) {
}
@@ -32,6 +47,90 @@ public class QHybridSettingsCustomizer implements DeviceSpecificSettingsCustomiz
return true;
});
}
timeOffsetPref = handler.findPreference("time_offset");
if (timeOffsetPref != null) {
timeOffsetPref.setOnPreferenceClickListener(preference -> {
int timeOffset = prefs.getInt("QHYBRID_TIME_OFFSET", 0);
LinearLayout layout2 = new LinearLayout(handler.getContext());
layout2.setOrientation(LinearLayout.HORIZONTAL);
final NumberPicker hourPicker = new NumberPicker(handler.getContext());
hourPicker.setMinValue(0);
hourPicker.setMaxValue(23);
hourPicker.setValue(timeOffset / 60);
final NumberPicker minPicker = new NumberPicker(handler.getContext());
minPicker.setMinValue(0);
minPicker.setMaxValue(59);
minPicker.setValue(timeOffset % 60);
layout2.addView(hourPicker);
TextView tw = new TextView(handler.getContext());
tw.setText(":");
layout2.addView(tw);
layout2.addView(minPicker);
layout2.setGravity(Gravity.CENTER);
new MaterialAlertDialogBuilder(handler.getContext())
.setTitle(handler.getContext().getString(R.string.qhybrid_offset_time_by))
.setView(layout2)
.setPositiveButton(handler.getContext().getString(R.string.ok), (dialogInterface, i) -> {
int value = hourPicker.getValue() * 60 + minPicker.getValue();
prefs.getPreferences().edit().putInt("QHYBRID_TIME_OFFSET", value).apply();
updateTimeOffsetSummary(value);
LocalBroadcastManager.getInstance(handler.getContext()).sendBroadcast(new Intent(QHybridSupport.QHYBRID_COMMAND_UPDATE));
GB.toast(handler.getContext().getString(R.string.qhybrid_changes_delay_prompt), Toast.LENGTH_SHORT, GB.INFO);
})
.setNegativeButton(handler.getContext().getString(R.string.fossil_hr_new_action_cancel), null)
.show();
return true;
});
updateTimeOffsetSummary(prefs.getInt("QHYBRID_TIME_OFFSET", 0));
}
timeZoneOffsetPref = handler.findPreference("second_tz_offset");
if (timeZoneOffsetPref != null) {
timeZoneOffsetPref.setOnPreferenceClickListener(preference -> {
int timeOffset = prefs.getInt("QHYBRID_TIMEZONE_OFFSET", 0);
LinearLayout layout2 = new LinearLayout(handler.getContext());
layout2.setOrientation(LinearLayout.HORIZONTAL);
final NumberPicker hourPicker = new NumberPicker(handler.getContext());
hourPicker.setMinValue(0);
hourPicker.setMaxValue(23);
hourPicker.setValue(timeOffset / 60);
final NumberPicker minPicker = new NumberPicker(handler.getContext());
minPicker.setMinValue(0);
minPicker.setMaxValue(59);
minPicker.setValue(timeOffset % 60);
layout2.addView(hourPicker);
TextView tw = new TextView(handler.getContext());
tw.setText(":");
layout2.addView(tw);
layout2.addView(minPicker);
layout2.setGravity(Gravity.CENTER);
new MaterialAlertDialogBuilder(handler.getContext())
.setTitle(handler.getContext().getString(R.string.qhybrid_offset_timezone))
.setView(layout2)
.setPositiveButton(handler.getContext().getString(R.string.ok), (dialogInterface, i) -> {
int value = hourPicker.getValue() * 60 + minPicker.getValue();
prefs.getPreferences().edit().putInt("QHYBRID_TIMEZONE_OFFSET", value).apply();
updateTimezoneOffsetSummary(value);
LocalBroadcastManager.getInstance(handler.getContext()).sendBroadcast(new Intent(QHybridSupport.QHYBRID_COMMAND_UPDATE_TIMEZONE));
GB.toast(handler.getContext().getString(R.string.qhybrid_changes_delay_prompt), Toast.LENGTH_SHORT, GB.INFO);
})
.setNegativeButton(handler.getContext().getString(R.string.fossil_hr_new_action_cancel), null)
.show();
return true;
});
updateTimezoneOffsetSummary(prefs.getInt("QHYBRID_TIMEZONE_OFFSET", 0));
}
}
@Override
@@ -59,4 +158,20 @@ public class QHybridSettingsCustomizer implements DeviceSpecificSettingsCustomiz
@Override
public void writeToParcel(@NonNull final Parcel dest, final int flags) {
}
private void updateTimeOffsetSummary(int timeOffset) {
DecimalFormat format = new DecimalFormat("00");
timeOffsetPref.setSummary(
format.format(timeOffset / 60) + ":" +
format.format(timeOffset % 60)
);
}
private void updateTimezoneOffsetSummary(int timeZoneOffset) {
DecimalFormat format = new DecimalFormat("00");
timeZoneOffsetPref.setSummary(
format.format(timeZoneOffset / 60) + ":" +
format.format(timeZoneOffset % 60)
);
}
}
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/qhybridMain"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -14,47 +13,11 @@
android:id="@+id/settingsLayout"
android:focusableInTouchMode="true" >
<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="@string/qhybrid_time_shift" />
<TextView
android:id="@+id/qhybridTimeOffset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true" />
</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="@string/qhybrid_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"
android:layout_height="wrap_content"
android:text="@string/qhybrid_overwrite_buttons" />
<!-- <Button-->
<!-- android:id="@+id/buttonOverwriteButtons"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:text="@string/qhybrid_overwrite_buttons" />-->
<LinearLayout
android:layout_width="match_parent"
@@ -8,4 +8,16 @@
android:title="@string/qhybrid_use_activity_hand_as_notification_counter"
android:icon="@drawable/ic_timer" />
<Preference
android:defaultValue="00:00"
android:key="time_offset"
android:title="@string/qhybrid_time_shift"
android:icon="@drawable/ic_timer" />
<Preference
android:defaultValue="00:00"
android:key="second_tz_offset"
android:title="@string/qhybrid_second_timezone_offset_relative_to_utc"
android:icon="@drawable/ic_timer" />
</androidx.preference.PreferenceScreen>