/* Copyright (C) 2019-2020 Andreas Shimokawa, Cre3per This file is part of Gadgetbridge. Gadgetbridge is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Gadgetbridge is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.activities.devicesettings; import android.os.Bundle; import android.text.InputType; import android.widget.EditText; import androidx.annotation.NonNull; import androidx.fragment.app.DialogFragment; import androidx.preference.EditTextPreference; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Objects; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst; import nodomain.freeyourgadget.gadgetbridge.devices.makibeshr3.MakibesHR3Constants; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst; import nodomain.freeyourgadget.gadgetbridge.util.Prefs; import nodomain.freeyourgadget.gadgetbridge.util.XTimePreference; import nodomain.freeyourgadget.gadgetbridge.util.XTimePreferenceFragment; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_ALTITUDE_CALIBRATE; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BUTTON_1_FUNCTION; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BUTTON_2_FUNCTION; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BUTTON_3_FUNCTION; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BUTTON_BP_CALIBRATE; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DATEFORMAT; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DISCONNECTNOTIF_NOSHED; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_DO_NOT_DISTURB_NOAUTO; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HYBRID_HR_DRAW_WIDGET_CIRCLES; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HYBRID_HR_FORCE_WHITE_COLOR; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_HYBRID_HR_SAVE_RAW_ACTIVITY_FILES; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LANGUAGE; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LIFTWRIST_NOSHED; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LONGSIT_PERIOD; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_LONGSIT_SWITCH; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_POWER_MODE; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_SCREEN_ORIENTATION; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_TIMEFORMAT; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_VIBRATION_STRENGH_PERCENTAGE; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_WEARLOCATION; import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_ACTIVATE_DISPLAY_ON_LIFT; import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DISCONNECT_NOTIFICATION; import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DISCONNECT_NOTIFICATION_END; import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DISCONNECT_NOTIFICATION_START; import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DISPLAY_ITEMS; import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DISPLAY_ON_LIFT_END; import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_DISPLAY_ON_LIFT_START; import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst.PREF_EXPOSE_HR_THIRDPARTY; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_DO_NOT_DISTURB; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_DO_NOT_DISTURB_END; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_DO_NOT_DISTURB_OFF; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_DO_NOT_DISTURB_SCHEDULED; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_DO_NOT_DISTURB_START; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_DATEFORMAT; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MI2_ROTATE_WRIST_TO_SWITCH_INFO; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE_END; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE_OFF; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE_SCHEDULED; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_NIGHT_MODE_START; import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_SWIPE_UNLOCK; public class DeviceSpecificSettingsFragment extends PreferenceFragmentCompat { private static final Logger LOG = LoggerFactory.getLogger(DeviceSpecificSettingsFragment.class); static final String FRAGMENT_TAG = "DEVICE_SPECIFIC_SETTINGS_FRAGMENT"; private void setSettingsFileSuffix(String settingsFileSuffix, @NonNull int[] supportedSettings) { Bundle args = new Bundle(); args.putString("settingsFileSuffix", settingsFileSuffix); args.putIntArray("supportedSettings", supportedSettings); setArguments(args); } @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { Bundle arguments = getArguments(); if (arguments == null) { return; } String settingsFileSuffix = arguments.getString("settingsFileSuffix", null); int[] supportedSettings = arguments.getIntArray("supportedSettings"); if (settingsFileSuffix == null || supportedSettings == null) { return; } getPreferenceManager().setSharedPreferencesName("devicesettings_" + settingsFileSuffix); if (rootKey == null) { // we are the main preference screen boolean first = true; for (int setting : supportedSettings) { if (first) { setPreferencesFromResource(setting, null); first = false; } else { addPreferencesFromResource(setting); } } } else { // Now, this is ugly: search all the xml files for the rootKey for (int setting : supportedSettings) { try { setPreferencesFromResource(setting, rootKey); } catch (Exception ignore) { continue; } break; } } setChangeListener(); } /* * delayed execution so that the preferences are applied first */ private void invokeLater(Runnable runnable) { getListView().post(runnable); } private void setChangeListener() { Prefs prefs = new Prefs(getPreferenceManager().getSharedPreferences()); String disconnectNotificationState = prefs.getString(PREF_DISCONNECT_NOTIFICATION, PREF_DO_NOT_DISTURB_OFF); boolean disconnectNotificationScheduled = disconnectNotificationState.equals(PREF_DO_NOT_DISTURB_SCHEDULED); final Preference disconnectNotificationStart = findPreference(PREF_DISCONNECT_NOTIFICATION_START); if (disconnectNotificationStart != null) { disconnectNotificationStart.setEnabled(disconnectNotificationScheduled); disconnectNotificationStart.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newVal) { invokeLater(new Runnable() { @Override public void run() { GBApplication.deviceService().onSendConfiguration(PREF_DISCONNECT_NOTIFICATION_START); } }); return true; } }); } final Preference disconnectNotificationEnd = findPreference(PREF_DISCONNECT_NOTIFICATION_END); if (disconnectNotificationEnd != null) { disconnectNotificationEnd.setEnabled(disconnectNotificationScheduled); disconnectNotificationEnd.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newVal) { invokeLater(new Runnable() { @Override public void run() { GBApplication.deviceService().onSendConfiguration(PREF_DISCONNECT_NOTIFICATION_END); } }); return true; } }); } final Preference disconnectNotification = findPreference(PREF_DISCONNECT_NOTIFICATION); if (disconnectNotification != null) { disconnectNotification.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newVal) { final boolean scheduled = PREF_DO_NOT_DISTURB_SCHEDULED.equals(newVal.toString()); Objects.requireNonNull(disconnectNotificationStart).setEnabled(scheduled); Objects.requireNonNull(disconnectNotificationEnd).setEnabled(scheduled); invokeLater(new Runnable() { @Override public void run() { GBApplication.deviceService().onSendConfiguration(PREF_DISCONNECT_NOTIFICATION); } }); return true; } }); } String nightModeState = prefs.getString(MiBandConst.PREF_NIGHT_MODE, PREF_NIGHT_MODE_OFF); boolean nightModeScheduled = nightModeState.equals(PREF_NIGHT_MODE_SCHEDULED); final Preference nightModeStart = findPreference(PREF_NIGHT_MODE_START); if (nightModeStart != null) { nightModeStart.setEnabled(nightModeScheduled); nightModeStart.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newVal) { invokeLater(new Runnable() { @Override public void run() { GBApplication.deviceService().onSendConfiguration(PREF_NIGHT_MODE_START); } }); return true; } }); } final Preference nightModeEnd = findPreference(PREF_NIGHT_MODE_END); if (nightModeEnd != null) { nightModeEnd.setEnabled(nightModeScheduled); nightModeEnd.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newVal) { invokeLater(new Runnable() { @Override public void run() { GBApplication.deviceService().onSendConfiguration(PREF_NIGHT_MODE_END); } }); return true; } }); } final Preference nightMode = findPreference(PREF_NIGHT_MODE); if (nightMode != null) { nightMode.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newVal) { final boolean scheduled = PREF_NIGHT_MODE_SCHEDULED.equals(newVal.toString()); Objects.requireNonNull(nightModeStart).setEnabled(scheduled); Objects.requireNonNull(nightModeEnd).setEnabled(scheduled); invokeLater(new Runnable() { @Override public void run() { GBApplication.deviceService().onSendConfiguration(PREF_NIGHT_MODE); } }); return true; } }); } String doNotDisturbState = prefs.getString(MiBandConst.PREF_DO_NOT_DISTURB, PREF_DO_NOT_DISTURB_OFF); boolean doNotDisturbScheduled = doNotDisturbState.equals(PREF_DO_NOT_DISTURB_SCHEDULED); final Preference doNotDisturbStart = findPreference(PREF_DO_NOT_DISTURB_START); if (doNotDisturbStart != null) { doNotDisturbStart.setEnabled(doNotDisturbScheduled); doNotDisturbStart.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newVal) { invokeLater(new Runnable() { @Override public void run() { GBApplication.deviceService().onSendConfiguration(PREF_DO_NOT_DISTURB_START); } }); return true; } }); } final Preference doNotDisturbEnd = findPreference(PREF_DO_NOT_DISTURB_END); if (doNotDisturbEnd != null) { doNotDisturbEnd.setEnabled(doNotDisturbScheduled); doNotDisturbEnd.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newVal) { invokeLater(new Runnable() { @Override public void run() { GBApplication.deviceService().onSendConfiguration(PREF_DO_NOT_DISTURB_END); } }); return true; } }); } final Preference doNotDisturb = findPreference(PREF_DO_NOT_DISTURB); if (doNotDisturb != null) { doNotDisturb.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newVal) { final boolean scheduled = PREF_DO_NOT_DISTURB_SCHEDULED.equals(newVal.toString()); Objects.requireNonNull(doNotDisturbStart).setEnabled(scheduled); Objects.requireNonNull(doNotDisturbEnd).setEnabled(scheduled); invokeLater(new Runnable() { @Override public void run() { GBApplication.deviceService().onSendConfiguration(PREF_DO_NOT_DISTURB); } }); return true; } }); } addPreferenceHandlerFor(PREF_SWIPE_UNLOCK); addPreferenceHandlerFor(PREF_MI2_DATEFORMAT); addPreferenceHandlerFor(PREF_DATEFORMAT); addPreferenceHandlerFor(PREF_DISPLAY_ITEMS); addPreferenceHandlerFor(PREF_LANGUAGE); addPreferenceHandlerFor(PREF_EXPOSE_HR_THIRDPARTY); addPreferenceHandlerFor(PREF_WEARLOCATION); addPreferenceHandlerFor(PREF_SCREEN_ORIENTATION); addPreferenceHandlerFor(PREF_TIMEFORMAT); addPreferenceHandlerFor(PREF_BUTTON_1_FUNCTION); addPreferenceHandlerFor(PREF_BUTTON_2_FUNCTION); addPreferenceHandlerFor(PREF_BUTTON_3_FUNCTION); addPreferenceHandlerFor(PREF_VIBRATION_STRENGH_PERCENTAGE); addPreferenceHandlerFor(PREF_POWER_MODE); addPreferenceHandlerFor(PREF_LIFTWRIST_NOSHED); addPreferenceHandlerFor(PREF_DISCONNECTNOTIF_NOSHED); addPreferenceHandlerFor(PREF_BUTTON_BP_CALIBRATE); addPreferenceHandlerFor(PREF_ALTITUDE_CALIBRATE); addPreferenceHandlerFor(PREF_LONGSIT_PERIOD); addPreferenceHandlerFor(PREF_LONGSIT_SWITCH); addPreferenceHandlerFor(PREF_DO_NOT_DISTURB_NOAUTO); addPreferenceHandlerFor(PREF_HYBRID_HR_DRAW_WIDGET_CIRCLES); addPreferenceHandlerFor(PREF_HYBRID_HR_FORCE_WHITE_COLOR); addPreferenceHandlerFor(PREF_HYBRID_HR_SAVE_RAW_ACTIVITY_FILES); String displayOnLiftState = prefs.getString(PREF_ACTIVATE_DISPLAY_ON_LIFT, PREF_DO_NOT_DISTURB_OFF); boolean displayOnLiftScheduled = displayOnLiftState.equals(PREF_DO_NOT_DISTURB_SCHEDULED); final Preference rotateWristCycleInfo = findPreference(PREF_MI2_ROTATE_WRIST_TO_SWITCH_INFO); if (rotateWristCycleInfo != null) { rotateWristCycleInfo.setEnabled(!PREF_DO_NOT_DISTURB_OFF.equals(displayOnLiftState)); rotateWristCycleInfo.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newVal) { invokeLater(new Runnable() { @Override public void run() { GBApplication.deviceService().onSendConfiguration(PREF_MI2_ROTATE_WRIST_TO_SWITCH_INFO); } }); return true; } }); } final Preference displayOnLiftStart = findPreference(PREF_DISPLAY_ON_LIFT_START); if (displayOnLiftStart != null) { displayOnLiftStart.setEnabled(displayOnLiftScheduled); displayOnLiftStart.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newVal) { invokeLater(new Runnable() { @Override public void run() { GBApplication.deviceService().onSendConfiguration(PREF_DISPLAY_ON_LIFT_START); } }); return true; } }); } final Preference displayOnLiftEnd = findPreference(PREF_DISPLAY_ON_LIFT_END); if (displayOnLiftEnd != null) { displayOnLiftEnd.setEnabled(displayOnLiftScheduled); displayOnLiftEnd.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newVal) { invokeLater(new Runnable() { @Override public void run() { GBApplication.deviceService().onSendConfiguration(PREF_DISPLAY_ON_LIFT_END); } }); return true; } }); } final Preference displayOnLift = findPreference(PREF_ACTIVATE_DISPLAY_ON_LIFT); if (displayOnLift != null) { displayOnLift.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newVal) { final boolean scheduled = PREF_DO_NOT_DISTURB_SCHEDULED.equals(newVal.toString()); Objects.requireNonNull(displayOnLiftStart).setEnabled(scheduled); Objects.requireNonNull(displayOnLiftEnd).setEnabled(scheduled); if (rotateWristCycleInfo != null) { rotateWristCycleInfo.setEnabled(!PREF_DO_NOT_DISTURB_OFF.equals(newVal.toString())); } invokeLater(new Runnable() { @Override public void run() { GBApplication.deviceService().onSendConfiguration(PREF_ACTIVATE_DISPLAY_ON_LIFT); } }); return true; } }); } setInputTypeFor(HuamiConst.PREF_BUTTON_ACTION_BROADCAST_DELAY, InputType.TYPE_CLASS_NUMBER); setInputTypeFor(HuamiConst.PREF_BUTTON_ACTION_PRESS_MAX_INTERVAL, InputType.TYPE_CLASS_NUMBER); setInputTypeFor(HuamiConst.PREF_BUTTON_ACTION_PRESS_COUNT, InputType.TYPE_CLASS_NUMBER); setInputTypeFor(MiBandConst.PREF_MIBAND_DEVICE_TIME_OFFSET_HOURS, InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED); setInputTypeFor(MakibesHR3Constants.PREF_FIND_PHONE_DURATION, InputType.TYPE_CLASS_NUMBER); setInputTypeFor(DeviceSettingsPreferenceConst.PREF_RESERVER_ALARMS_CALENDAR, InputType.TYPE_CLASS_NUMBER); } static DeviceSpecificSettingsFragment newInstance(String settingsFileSuffix, @NonNull int[] supportedSettings) { DeviceSpecificSettingsFragment fragment = new DeviceSpecificSettingsFragment(); fragment.setSettingsFileSuffix(settingsFileSuffix, supportedSettings); return fragment; } @Override public void onDisplayPreferenceDialog(Preference preference) { DialogFragment dialogFragment; if (preference instanceof XTimePreference) { dialogFragment = new XTimePreferenceFragment(); Bundle bundle = new Bundle(1); bundle.putString("key", preference.getKey()); dialogFragment.setArguments(bundle); dialogFragment.setTargetFragment(this, 0); if (getFragmentManager() != null) { dialogFragment.show(getFragmentManager(), "androidx.preference.PreferenceFragment.DIALOG"); } } else { super.onDisplayPreferenceDialog(preference); } } private void addPreferenceHandlerFor(final String preferenceKey) { Preference pref = findPreference(preferenceKey); if (pref != null) { pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { public boolean onPreferenceChange(Preference preference, Object newVal) { invokeLater(new Runnable() { @Override public void run() { GBApplication.deviceService().onSendConfiguration(preferenceKey); } }); return true; } }); } } private void setInputTypeFor(final String preferenceKey, final int editTypeFlags) { EditTextPreference textPreference = findPreference(preferenceKey); if (textPreference != null) { textPreference.setOnBindEditTextListener(new EditTextPreference.OnBindEditTextListener() { @Override public void onBindEditText(@NonNull EditText editText) { editText.setInputType(editTypeFlags); } }); } } }