1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-06-17 10:30:03 +02:00

Allow for device settings sub-screens (#3620)

Reviewed-on: https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/3620
Co-authored-by: José Rebelo <joserebelo@outlook.com>
Co-committed-by: José Rebelo <joserebelo@outlook.com>
This commit is contained in:
José Rebelo 2024-03-16 17:21:42 +00:00 committed by José Rebelo
parent fcc930749e
commit 9db60f16d1
18 changed files with 527 additions and 180 deletions

View File

@ -0,0 +1,184 @@
/* Copyright (C) 2024 José Rebelo
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 <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.activities.devicesettings;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.XmlRes;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* A class that contains the device-specific settings screens for a device. All the integers in this
* class correspond to xml resources for preferences.
* <p>
* This class contains 2 types of screens:
* - Root screens - the ones that are displayed in the first page of the device settings activity. These can be
* normal preference screens / preferences, or dummy root screens (see {@link DeviceSpecificSettingsScreen}.
* - Sub-screens - a screen that is opened when one of the {@link DeviceSpecificSettingsScreen} is clicked.
* <p>
* There can be an arbitrary number of nested sub-screens, as long as they are all mapped by key in the
* subScreens map.
* <p>
* See the XiaomiCoordinator and ZeppOsCoordinator for example usages.
*/
public class DeviceSpecificSettings implements Parcelable {
private final List<Integer> rootScreens = new ArrayList<>();
private final Map<String, List<Integer>> subScreens = new LinkedHashMap<>();
public DeviceSpecificSettings() {
}
public DeviceSpecificSettings(final int[] rootScreens) {
for (final int setting : rootScreens) {
this.rootScreens.add(setting);
}
}
public void addRootScreen(@XmlRes final int screen) {
if (!rootScreens.contains(screen)) {
rootScreens.add(screen);
}
}
public List<Integer> addRootScreen(final DeviceSpecificSettingsScreen screen) {
if (!rootScreens.contains(screen.getXml())) {
rootScreens.add(screen.getXml());
}
return addSubScreen(screen, screen.getXml());
}
public List<Integer> addRootScreen(final DeviceSpecificSettingsScreen screen, final int... subScreens) {
final List<Integer> subScreenScreens = addRootScreen(screen);
for (final int subScreen : subScreens) {
subScreenScreens.add(subScreen);
}
return subScreenScreens;
}
public void addRootScreen(final int index, @XmlRes final int screen) {
rootScreens.add(index, screen);
}
public List<Integer> addSubScreen(final DeviceSpecificSettingsScreen rootScreen, final int... screens) {
return addSubScreen(rootScreen.getKey(), screens);
}
private List<Integer> addSubScreen(final String key, final int... screens) {
if (!subScreens.containsKey(key)) {
subScreens.put(key, new ArrayList<>());
}
final List<Integer> subscreenPages = Objects.requireNonNull(subScreens.get(key));
for (final int screen : screens) {
if (!subscreenPages.contains(screen)) {
subscreenPages.add(screen);
}
}
return subscreenPages;
}
public void mergeFrom(final DeviceSpecificSettings deviceSpecificSettings) {
for (final Integer rootScreen : deviceSpecificSettings.rootScreens) {
addRootScreen(rootScreen);
}
for (final Map.Entry<String, List<Integer>> e : deviceSpecificSettings.subScreens.entrySet()) {
if (!subScreens.containsKey(e.getKey())) {
subScreens.put(e.getKey(), new ArrayList<>());
}
for (final int screen : e.getValue()) {
Objects.requireNonNull(subScreens.get(e.getKey())).add(screen);
}
}
}
public List<Integer> getRootScreens() {
return rootScreens;
}
@Nullable
public List<Integer> getScreen(@NonNull final String key) {
return subScreens.get(key);
}
public List<Integer> getAllScreens() {
final List<Integer> allScreens = new ArrayList<>(rootScreens);
for (final List<Integer> screens : subScreens.values()) {
allScreens.addAll(screens);
}
return allScreens;
}
public static final Creator<DeviceSpecificSettings> CREATOR = new Creator<DeviceSpecificSettings>() {
@Override
public DeviceSpecificSettings createFromParcel(final Parcel in) {
final DeviceSpecificSettings deviceSpecificSettings = new DeviceSpecificSettings();
final int numRootScreens = in.readInt();
for (int i = 0; i < numRootScreens; i++) {
deviceSpecificSettings.addRootScreen(in.readInt());
}
final int numSubScreens = in.readInt();
for (int i = 0; i < numSubScreens; i++) {
final String key = in.readString();
final int numScreens = in.readInt();
final int[] screens = new int[numScreens];
for (int j = 0; j < numScreens; j++) {
screens[j] = in.readInt();
}
deviceSpecificSettings.addSubScreen(key, screens);
}
return deviceSpecificSettings;
}
@Override
public DeviceSpecificSettings[] newArray(final int size) {
return new DeviceSpecificSettings[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull final Parcel dest, final int flags) {
dest.writeInt(rootScreens.size());
for (final Integer rootScreen : rootScreens) {
dest.writeInt(rootScreen);
}
dest.writeInt(subScreens.size());
for (final Map.Entry<String, List<Integer>> e : subScreens.entrySet()) {
dest.writeString(e.getKey());
dest.writeInt(e.getValue().size());
for (final Integer s : e.getValue()) {
dest.writeInt(s);
}
}
}
}

View File

@ -25,19 +25,19 @@ import android.media.AudioManager;
import android.os.Bundle; import android.os.Bundle;
import android.text.InputType; import android.text.InputType;
import androidx.annotation.NonNull;
import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.preference.ListPreference; import androidx.preference.ListPreference;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
@ -59,7 +59,6 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec; import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs; import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.*; import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.*;
@ -96,10 +95,15 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
private GBDevice device; private GBDevice device;
private void setSettingsFileSuffix(String settingsFileSuffix, @NonNull int[] supportedSettings) { private void setSettingsFileSuffix(String settingsFileSuffix) {
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString("settingsFileSuffix", settingsFileSuffix); args.putString("settingsFileSuffix", settingsFileSuffix);
args.putIntArray("supportedSettings", supportedSettings); setArguments(args);
}
private void setDeviceSpecificSettings(final DeviceSpecificSettings deviceSpecificSettings) {
final Bundle args = getArguments() != null ? getArguments() : new Bundle();
args.putParcelable("deviceSpecificSettings", deviceSpecificSettings);
setArguments(args); setArguments(args);
} }
@ -122,12 +126,11 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
return; return;
} }
String settingsFileSuffix = arguments.getString("settingsFileSuffix", null); String settingsFileSuffix = arguments.getString("settingsFileSuffix", null);
int[] supportedSettings = arguments.getIntArray("supportedSettings"); DeviceSpecificSettings deviceSpecificSettings = arguments.getParcelable("deviceSpecificSettings");
String[] supportedLanguages = arguments.getStringArray("supportedLanguages");
this.deviceSpecificSettingsCustomizer = arguments.getParcelable("deviceSpecificSettingsCustomizer"); this.deviceSpecificSettingsCustomizer = arguments.getParcelable("deviceSpecificSettingsCustomizer");
this.device = arguments.getParcelable("device"); this.device = arguments.getParcelable("device");
if (settingsFileSuffix == null || supportedSettings == null) { if (settingsFileSuffix == null || deviceSpecificSettings == null) {
return; return;
} }
@ -136,7 +139,7 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
if (rootKey == null) { if (rootKey == null) {
// we are the main preference screen // we are the main preference screen
boolean first = true; boolean first = true;
for (int setting : supportedSettings) { for (int setting : deviceSpecificSettings.getRootScreens()) {
if (first) { if (first) {
setPreferencesFromResource(setting, null); setPreferencesFromResource(setting, null);
first = false; first = false;
@ -145,16 +148,47 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
} }
} }
} else { } else {
// Now, this is ugly: search all the xml files for the rootKey // First attempt to find a known screen for this key
for (int setting : supportedSettings) { final List<Integer> screenSettings = deviceSpecificSettings.getScreen(rootKey);
try { if (screenSettings != null) {
setPreferencesFromResource(setting, rootKey); boolean first = true;
} catch (Exception ignore) { for (int setting : screenSettings) {
continue; if (first) {
// Use the root key here to set the root screen, so that the actionbar title gets updated
setPreferencesFromResource(setting, rootKey);
first = false;
} else {
addPreferencesFromResource(setting);
}
}
} else {
// Now, this is ugly: search all the xml files for the rootKey
// This means that this device is using the deprecated getSupportedDeviceSpecificSettings,
// or that we're on a sub-screen
final List<Integer> allScreens = deviceSpecificSettings.getAllScreens();
for (int setting : allScreens) {
try {
setPreferencesFromResource(setting, rootKey);
} catch (Exception ignore) {
continue;
}
break;
} }
break;
} }
} }
// Since all root preference screens are empty, clicking them will not do anything
// add on-click listeners
for (final DeviceSpecificSettingsScreen value : DeviceSpecificSettingsScreen.values()) {
final PreferenceScreen prefScreen = findPreference(value.getKey());
if (prefScreen != null) {
prefScreen.setOnPreferenceClickListener(p -> {
onNavigateToScreen(prefScreen);
return true;
});
}
}
setChangeListener(); setChangeListener();
} }
@ -1023,53 +1057,56 @@ public class DeviceSpecificSettingsFragment extends AbstractPreferenceFragment i
} }
} }
static private void addElementsToList(ArrayList<Integer> list, int[]... elements){
for(int[] array : elements){
for(int item : array){
list.add(item);
}
}
}
static DeviceSpecificSettingsFragment newInstance(GBDevice device, DeviceSettingsActivity.MENU_ENTRY_POINTS applicationSpecificSettings) { static DeviceSpecificSettingsFragment newInstance(GBDevice device, DeviceSettingsActivity.MENU_ENTRY_POINTS applicationSpecificSettings) {
final DeviceCoordinator coordinator = device.getDeviceCoordinator(); final DeviceCoordinator coordinator = device.getDeviceCoordinator();
ArrayList<Integer> supportedSettings = new ArrayList<>();
String[] supportedLanguages = null; final DeviceSpecificSettings deviceSpecificSettings = new DeviceSpecificSettings();
if (applicationSpecificSettings.equals(DeviceSettingsActivity.MENU_ENTRY_POINTS.AUTH_SETTINGS)) { //auth settings screen if (applicationSpecificSettings.equals(DeviceSettingsActivity.MENU_ENTRY_POINTS.AUTH_SETTINGS)) { //auth settings screen
supportedSettings.add(R.xml.devicesettings_pairingkey_explanation); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_pairingkey_explanation);
addElementsToList(supportedSettings, coordinator.getSupportedDeviceSpecificAuthenticationSettings()); for (final int s : coordinator.getSupportedDeviceSpecificAuthenticationSettings()) {
deviceSpecificSettings.addRootScreen(s);
}
} else { //device/application settings } else { //device/application settings
if (coordinator.getSupportedLanguageSettings(device) != null) { if (coordinator.getSupportedLanguageSettings(device) != null) {
supportedSettings.add(R.xml.devicesettings_language_generic); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_language_generic);
}
DeviceSpecificSettings coordinatorDeviceSettings = coordinator.getDeviceSpecificSettings(device);
if (coordinatorDeviceSettings != null) {
deviceSpecificSettings.mergeFrom(coordinatorDeviceSettings);
} }
addElementsToList(supportedSettings, coordinator.getSupportedDeviceSpecificSettings(device));
final int[] supportedAuthSettings = coordinator.getSupportedDeviceSpecificAuthenticationSettings(); final int[] supportedAuthSettings = coordinator.getSupportedDeviceSpecificAuthenticationSettings();
if (supportedAuthSettings != null && supportedAuthSettings.length > 0) { if (supportedAuthSettings != null && supportedAuthSettings.length > 0) {
supportedSettings.add(R.xml.devicesettings_header_authentication); deviceSpecificSettings.addRootScreen(
addElementsToList(supportedSettings, supportedAuthSettings); DeviceSpecificSettingsScreen.AUTHENTICATION,
supportedAuthSettings
);
} }
addElementsToList( deviceSpecificSettings.addRootScreen(
supportedSettings, DeviceSpecificSettingsScreen.CONNECTION,
coordinator.getSupportedDeviceSpecificConnectionSettings(), coordinator.getSupportedDeviceSpecificConnectionSettings()
coordinator.getSupportedDeviceSpecificApplicationSettings()); );
if (coordinator.supportsActivityTracking()) { if (coordinator.supportsActivityTracking()) {
supportedSettings.addAll(Arrays.asList( deviceSpecificSettings.addRootScreen(
R.xml.devicesettings_activity_info_header, DeviceSpecificSettingsScreen.ACTIVITY_INFO,
R.xml.devicesettings_chartstabs, R.xml.devicesettings_chartstabs,
R.xml.devicesettings_device_card_activity_card_preferences R.xml.devicesettings_device_card_activity_card_preferences
)); );
} }
supportedSettings.add(R.xml.devicesettings_settings_third_party_apps);
}
int[] supportedSettingsInts = ArrayUtils.toPrimitive(supportedSettings.toArray(new Integer[0])); deviceSpecificSettings.addRootScreen(
DeviceSpecificSettingsScreen.DEVELOPER,
R.xml.devicesettings_settings_third_party_apps
);
}
final DeviceSpecificSettingsCustomizer deviceSpecificSettingsCustomizer = coordinator.getDeviceSpecificSettingsCustomizer(device); final DeviceSpecificSettingsCustomizer deviceSpecificSettingsCustomizer = coordinator.getDeviceSpecificSettingsCustomizer(device);
final String settingsFileSuffix = device.getAddress(); final String settingsFileSuffix = device.getAddress();
final DeviceSpecificSettingsFragment fragment = new DeviceSpecificSettingsFragment(); final DeviceSpecificSettingsFragment fragment = new DeviceSpecificSettingsFragment();
fragment.setSettingsFileSuffix(settingsFileSuffix, supportedSettingsInts); fragment.setSettingsFileSuffix(settingsFileSuffix);
fragment.setDeviceSpecificSettings(deviceSpecificSettings);
fragment.setDeviceSpecificSettingsCustomizer(deviceSpecificSettingsCustomizer); fragment.setDeviceSpecificSettingsCustomizer(deviceSpecificSettingsCustomizer);
fragment.setDevice(device); fragment.setDevice(device);

View File

@ -0,0 +1,51 @@
/* Copyright (C) 2024 José Rebelo
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 <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.activities.devicesettings;
import androidx.annotation.XmlRes;
import nodomain.freeyourgadget.gadgetbridge.R;
public enum DeviceSpecificSettingsScreen {
ACTIVITY_INFO("pref_screen_activity_info", R.xml.devicesettings_root_activity_info),
AUTHENTICATION("pref_screen_authentication", R.xml.devicesettings_root_authentication),
CALENDAR("pref_screen_calendar", R.xml.devicesettings_root_calendar),
CONNECTION("pref_screen_connection", R.xml.devicesettings_root_connection),
DEVELOPER("pref_screen_developer", R.xml.devicesettings_root_developer),
DISPLAY("pref_screen_display", R.xml.devicesettings_root_display),
NOTIFICATIONS("pref_screen_notifications", R.xml.devicesettings_root_notifications),
DATE_TIME("pref_screen_date_time", R.xml.devicesettings_root_date_time),
WORKOUT("pref_screen_workout", R.xml.devicesettings_root_workout),
;
private final String key;
@XmlRes
private final int xml;
DeviceSpecificSettingsScreen(final String key, final int xml) {
this.key = key;
this.xml = xml;
}
public String getKey() {
return key;
}
public int getXml() {
return xml;
}
}

View File

@ -51,6 +51,7 @@ import de.greenrobot.dao.query.QueryBuilder;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.GBException; import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer; import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.capabilities.HeartRateCapability; import nodomain.freeyourgadget.gadgetbridge.capabilities.HeartRateCapability;
import nodomain.freeyourgadget.gadgetbridge.capabilities.password.PasswordCapabilityImpl; import nodomain.freeyourgadget.gadgetbridge.capabilities.password.PasswordCapabilityImpl;
@ -590,13 +591,18 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
} }
@Override @Override
public int[] getSupportedDeviceSpecificApplicationSettings() { public int[] getSupportedDeviceSpecificSettings(GBDevice device) {
return new int[0]; return new int[0];
} }
@Override @Override
public int[] getSupportedDeviceSpecificSettings(GBDevice device) { public DeviceSpecificSettings getDeviceSpecificSettings(GBDevice device) {
return new int[0]; final int[] settings = getSupportedDeviceSpecificSettings(device);
if (settings == null || settings.length == 0) {
return null;
}
return new DeviceSpecificSettings(settings);
} }
@Override @Override

View File

@ -36,6 +36,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import nodomain.freeyourgadget.gadgetbridge.GBException; import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer; import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.capabilities.HeartRateCapability; import nodomain.freeyourgadget.gadgetbridge.capabilities.HeartRateCapability;
import nodomain.freeyourgadget.gadgetbridge.capabilities.password.PasswordCapabilityImpl; import nodomain.freeyourgadget.gadgetbridge.capabilities.password.PasswordCapabilityImpl;
@ -561,13 +562,6 @@ public interface DeviceCoordinator {
*/ */
int[] getSupportedDeviceSpecificConnectionSettings(); int[] getSupportedDeviceSpecificConnectionSettings();
/**
* Returns device specific settings related to the application itself
* charts settings and so on
* @return int[]
*/
int[] getSupportedDeviceSpecificApplicationSettings();
/** /**
* Returns device specific settings related to the Auth key * Returns device specific settings related to the Auth key
* @return int[] * @return int[]
@ -576,9 +570,19 @@ public interface DeviceCoordinator {
/** /**
* Indicates which device specific settings the device supports (not per device type or family, but unique per device). * Indicates which device specific settings the device supports (not per device type or family, but unique per device).
*
* @deprecated use getDeviceSpecificSettings
*/ */
@Deprecated
int[] getSupportedDeviceSpecificSettings(GBDevice device); int[] getSupportedDeviceSpecificSettings(GBDevice device);
/**
* Returns the device-specific settings supported by this specific device. See
* {@link DeviceSpecificSettings} for more information
*/
@Nullable
DeviceSpecificSettings getDeviceSpecificSettings(GBDevice device);
/** /**
* Returns the {@link DeviceSpecificSettingsCustomizer}, allowing for the customization of the devices specific settings screen. * Returns the {@link DeviceSpecificSettingsCustomizer}, allowing for the customization of the devices specific settings screen.
*/ */

View File

@ -22,8 +22,6 @@ import android.net.Uri;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.apache.commons.lang3.ArrayUtils;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -37,6 +35,8 @@ import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.appmanager.AppManagerActivity; import nodomain.freeyourgadget.gadgetbridge.activities.appmanager.AppManagerActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsUtils; import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsUtils;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsScreen;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer; import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.capabilities.HeartRateCapability; import nodomain.freeyourgadget.gadgetbridge.capabilities.HeartRateCapability;
import nodomain.freeyourgadget.gadgetbridge.capabilities.password.PasswordCapabilityImpl; import nodomain.freeyourgadget.gadgetbridge.capabilities.password.PasswordCapabilityImpl;
@ -350,150 +350,142 @@ public abstract class ZeppOsCoordinator extends HuamiCoordinator {
* by {@link ZeppOsSettingsCustomizer}. * by {@link ZeppOsSettingsCustomizer}.
*/ */
@Override @Override
public int[] getSupportedDeviceSpecificSettings(final GBDevice device) { public DeviceSpecificSettings getDeviceSpecificSettings(final GBDevice device) {
final List<Integer> settings = new ArrayList<>(); final DeviceSpecificSettings deviceSpecificSettings = new DeviceSpecificSettings();
// //
// Apps // Apps
// TODO: These should go somewhere else // TODO: These should go somewhere else
// //
settings.add(R.xml.devicesettings_header_apps);
if (ZeppOsLoyaltyCardService.isSupported(getPrefs(device))) { if (ZeppOsLoyaltyCardService.isSupported(getPrefs(device))) {
settings.add(R.xml.devicesettings_loyalty_cards); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_loyalty_cards);
} }
// //
// Time // Time
// //
settings.add(R.xml.devicesettings_header_time); final List<Integer> dateTime = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.DATE_TIME);
//settings.add(R.xml.devicesettings_timeformat); //dateTime.add(R.xml.devicesettings_timeformat);
settings.add(R.xml.devicesettings_dateformat_2); dateTime.add(R.xml.devicesettings_dateformat_2);
if (getWorldClocksSlotCount() > 0) { if (getWorldClocksSlotCount() > 0) {
settings.add(R.xml.devicesettings_world_clocks); dateTime.add(R.xml.devicesettings_world_clocks);
} }
// //
// Display // Display
// //
settings.add(R.xml.devicesettings_header_display); final List<Integer> display = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.DISPLAY);
settings.add(R.xml.devicesettings_huami2021_displayitems); display.add(R.xml.devicesettings_huami2021_displayitems);
settings.add(R.xml.devicesettings_huami2021_shortcuts); display.add(R.xml.devicesettings_huami2021_shortcuts);
if (supportsControlCenter()) { if (supportsControlCenter()) {
settings.add(R.xml.devicesettings_huami2021_control_center); display.add(R.xml.devicesettings_huami2021_control_center);
} }
if (supportsShortcutCards(device)) { if (supportsShortcutCards(device)) {
settings.add(R.xml.devicesettings_huami2021_shortcut_cards); display.add(R.xml.devicesettings_huami2021_shortcut_cards);
} }
settings.add(R.xml.devicesettings_nightmode); display.add(R.xml.devicesettings_nightmode);
settings.add(R.xml.devicesettings_sleep_mode); display.add(R.xml.devicesettings_sleep_mode);
settings.add(R.xml.devicesettings_liftwrist_display_sensitivity_with_smart); display.add(R.xml.devicesettings_liftwrist_display_sensitivity_with_smart);
settings.add(R.xml.devicesettings_password); display.add(R.xml.devicesettings_password);
settings.add(R.xml.devicesettings_huami2021_watchface); display.add(R.xml.devicesettings_huami2021_watchface);
settings.add(R.xml.devicesettings_always_on_display); display.add(R.xml.devicesettings_always_on_display);
settings.add(R.xml.devicesettings_screen_timeout); display.add(R.xml.devicesettings_screen_timeout);
if (supportsAutoBrightness(device)) { if (supportsAutoBrightness(device)) {
settings.add(R.xml.devicesettings_screen_brightness_withauto); display.add(R.xml.devicesettings_screen_brightness_withauto);
} else { } else {
settings.add(R.xml.devicesettings_screen_brightness); display.add(R.xml.devicesettings_screen_brightness);
} }
// //
// Health // Health
// //
settings.add(R.xml.devicesettings_header_health); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_heartrate_sleep_alert_activity_stress_spo2);
settings.add(R.xml.devicesettings_heartrate_sleep_alert_activity_stress_spo2); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_inactivity_dnd_no_threshold);
settings.add(R.xml.devicesettings_inactivity_dnd_no_threshold); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_goal_notification);
settings.add(R.xml.devicesettings_goal_notification);
// //
// Workout // Workout
// //
settings.add(R.xml.devicesettings_header_workout); final List<Integer> workout = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.WORKOUT);
if (hasGps(device)) { if (hasGps(device)) {
settings.add(R.xml.devicesettings_gps_agps); workout.add(R.xml.devicesettings_gps_agps);
} else { } else {
// If the device has GPS, it doesn't report workout start/end to the phone // If the device has GPS, it doesn't report workout start/end to the phone
settings.add(R.xml.devicesettings_workout_start_on_phone); workout.add(R.xml.devicesettings_workout_start_on_phone);
settings.add(R.xml.devicesettings_workout_send_gps_to_band); workout.add(R.xml.devicesettings_workout_send_gps_to_band);
} }
settings.add(R.xml.devicesettings_workout_keep_screen_on); workout.add(R.xml.devicesettings_workout_keep_screen_on);
settings.add(R.xml.devicesettings_workout_detection); workout.add(R.xml.devicesettings_workout_detection);
// //
// Notifications // Notifications
// //
settings.add(R.xml.devicesettings_header_notifications); final List<Integer> notifications = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.NOTIFICATIONS);
if (supportsBluetoothPhoneCalls(device)) { if (supportsBluetoothPhoneCalls(device)) {
settings.add(R.xml.devicesettings_phone_calls_watch_pair); notifications.add(R.xml.devicesettings_phone_calls_watch_pair);
} else { } else {
settings.add(R.xml.devicesettings_display_caller); notifications.add(R.xml.devicesettings_display_caller);
} }
settings.add(R.xml.devicesettings_sound_and_vibration); notifications.add(R.xml.devicesettings_sound_and_vibration);
settings.add(R.xml.devicesettings_vibrationpatterns); notifications.add(R.xml.devicesettings_vibrationpatterns);
settings.add(R.xml.devicesettings_donotdisturb_withauto_and_always); notifications.add(R.xml.devicesettings_donotdisturb_withauto_and_always);
settings.add(R.xml.devicesettings_send_app_notifications); notifications.add(R.xml.devicesettings_send_app_notifications);
settings.add(R.xml.devicesettings_screen_on_on_notifications); notifications.add(R.xml.devicesettings_screen_on_on_notifications);
settings.add(R.xml.devicesettings_autoremove_notifications); notifications.add(R.xml.devicesettings_autoremove_notifications);
settings.add(R.xml.devicesettings_canned_reply_16); notifications.add(R.xml.devicesettings_canned_reply_16);
settings.add(R.xml.devicesettings_transliteration); notifications.add(R.xml.devicesettings_transliteration);
// //
// Calendar // Calendar
// //
settings.add(R.xml.devicesettings_header_calendar); deviceSpecificSettings.addRootScreen(
settings.add(R.xml.devicesettings_sync_calendar); DeviceSpecificSettingsScreen.CALENDAR,
R.xml.devicesettings_sync_calendar
);
// //
// Other // Other
// //
settings.add(R.xml.devicesettings_header_other);
if (getContactsSlotCount(device) > 0) { if (getContactsSlotCount(device) > 0) {
settings.add(R.xml.devicesettings_contacts); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_contacts);
} }
settings.add(R.xml.devicesettings_offline_voice); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_offline_voice);
settings.add(R.xml.devicesettings_device_actions_without_not_wear); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_device_actions_without_not_wear);
settings.add(R.xml.devicesettings_phone_silent_mode); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_phone_silent_mode);
settings.add(R.xml.devicesettings_buttonactions_upper_long); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_buttonactions_upper_long);
settings.add(R.xml.devicesettings_buttonactions_lower_short); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_buttonactions_lower_short);
settings.add(R.xml.devicesettings_weardirection); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_weardirection);
settings.add(R.xml.devicesettings_camera_remote); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_camera_remote);
settings.add(R.xml.devicesettings_morning_updates); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_morning_updates);
// //
// Connection // Connection
// //
settings.add(R.xml.devicesettings_header_connection); final List<Integer> connection = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.CONNECTION);
settings.add(R.xml.devicesettings_expose_hr_thirdparty); connection.add(R.xml.devicesettings_expose_hr_thirdparty);
settings.add(R.xml.devicesettings_bt_connected_advertisement); connection.add(R.xml.devicesettings_bt_connected_advertisement);
settings.add(R.xml.devicesettings_high_mtu); connection.add(R.xml.devicesettings_high_mtu);
// //
// Developer // Developer
// //
settings.add(R.xml.devicesettings_header_developer); final List<Integer> developer = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.DEVELOPER);
if (ZeppOsLogsService.isSupported(getPrefs(device))) { if (ZeppOsLogsService.isSupported(getPrefs(device))) {
settings.add(R.xml.devicesettings_app_logs_start_stop); developer.add(R.xml.devicesettings_app_logs_start_stop);
} }
if (supportsAlexa(device)) { if (supportsAlexa(device)) {
settings.add(R.xml.devicesettings_huami2021_alexa); developer.add(R.xml.devicesettings_huami2021_alexa);
} }
if (supportsWifiHotspot(device)) { if (supportsWifiHotspot(device)) {
settings.add(R.xml.devicesettings_wifi_hotspot); developer.add(R.xml.devicesettings_wifi_hotspot);
} }
if (supportsFtpServer(device)) { if (supportsFtpServer(device)) {
settings.add(R.xml.devicesettings_ftp_server); developer.add(R.xml.devicesettings_ftp_server);
} }
settings.add(R.xml.devicesettings_keep_activity_data_on_device); developer.add(R.xml.devicesettings_keep_activity_data_on_device);
settings.add(R.xml.devicesettings_huami2021_fetch_operation_time_unit); developer.add(R.xml.devicesettings_huami2021_fetch_operation_time_unit);
return ArrayUtils.toPrimitive(settings.toArray(new Integer[0])); return deviceSpecificSettings;
}
@Override
public int[] getSupportedDeviceSpecificAuthenticationSettings() {
return new int[]{
R.xml.devicesettings_pairingkey
};
} }
@Override @Override

View File

@ -269,6 +269,7 @@ public class QHybridCoordinator extends AbstractBLEDeviceCoordinator {
if (getFirmwareVersion() != null && getFirmwareVersion().smallerThan(new Version("2.20"))) { if (getFirmwareVersion() != null && getFirmwareVersion().smallerThan(new Version("2.20"))) {
supportedSettings = ArrayUtils.insert(1, supportedSettings, R.xml.devicesettings_fossilhybridhr_pre_fw220); supportedSettings = ArrayUtils.insert(1, supportedSettings, R.xml.devicesettings_fossilhybridhr_pre_fw220);
} }
supportedSettings = ArrayUtils.add(supportedSettings, R.xml.devicesettings_custom_deviceicon);
return supportedSettings; return supportedSettings;
} }
@ -285,13 +286,6 @@ public class QHybridCoordinator extends AbstractBLEDeviceCoordinator {
}; };
} }
@Override
public int[] getSupportedDeviceSpecificApplicationSettings() {
return new int[]{
R.xml.devicesettings_custom_deviceicon,
};
}
private boolean isHybridHR() { private boolean isHybridHR() {
List<GBDevice> devices = GBApplication.app().getDeviceManager().getSelectedDevices(); List<GBDevice> devices = GBApplication.app().getDeviceManager().getSelectedDevices();
for(GBDevice device : devices){ for(GBDevice device : devices){

View File

@ -464,13 +464,6 @@ public class TestDeviceCoordinator extends AbstractDeviceCoordinator {
return super.getSupportedDeviceSpecificConnectionSettings(); return super.getSupportedDeviceSpecificConnectionSettings();
} }
@Override
public int[] getSupportedDeviceSpecificApplicationSettings() {
return new int[]{
R.xml.devicesettings_custom_deviceicon,
};
}
@Override @Override
public int[] getSupportedDeviceSpecificSettings(final GBDevice device) { public int[] getSupportedDeviceSpecificSettings(final GBDevice device) {
final List<Integer> settings = new ArrayList<>(); final List<Integer> settings = new ArrayList<>();

View File

@ -38,6 +38,8 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.GBException; import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.appmanager.AppManagerActivity; import nodomain.freeyourgadget.gadgetbridge.activities.appmanager.AppManagerActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsScreen;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer; import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.capabilities.HeartRateCapability; import nodomain.freeyourgadget.gadgetbridge.capabilities.HeartRateCapability;
import nodomain.freeyourgadget.gadgetbridge.capabilities.password.PasswordCapabilityImpl; import nodomain.freeyourgadget.gadgetbridge.capabilities.password.PasswordCapabilityImpl;
@ -370,117 +372,120 @@ public abstract class XiaomiCoordinator extends AbstractBLEDeviceCoordinator {
} }
@Override @Override
public int[] getSupportedDeviceSpecificSettings(final GBDevice device) { public DeviceSpecificSettings getDeviceSpecificSettings(final GBDevice device) {
final List<Integer> settings = new ArrayList<>(); final DeviceSpecificSettings deviceSpecificSettings = new DeviceSpecificSettings();
if (supports(device, FEAT_WEAR_MODE)) { if (supports(device, FEAT_WEAR_MODE)) {
// TODO we should be able to get this from the band - right now it must be changed // TODO we should be able to get this from the band - right now it must be changed
// at least once from the band itself // at least once from the band itself
settings.add(R.xml.devicesettings_wearmode); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_wearmode);
} }
// //
// Time // Time
// //
settings.add(R.xml.devicesettings_header_time); final List<Integer> dateTime = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.DATE_TIME);
settings.add(R.xml.devicesettings_timeformat); dateTime.add(R.xml.devicesettings_timeformat);
if (getWorldClocksSlotCount() > 0) { if (getWorldClocksSlotCount() > 0) {
settings.add(R.xml.devicesettings_world_clocks); dateTime.add(R.xml.devicesettings_world_clocks);
} }
// //
// Display // Display
// //
settings.add(R.xml.devicesettings_header_display); final List<Integer> display = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.DISPLAY);
if (supports(device, FEAT_DISPLAY_ITEMS)) { if (supports(device, FEAT_DISPLAY_ITEMS)) {
settings.add(R.xml.devicesettings_xiaomi_displayitems); display.add(R.xml.devicesettings_xiaomi_displayitems);
} }
if (this.supportsWidgets(device)) { if (this.supportsWidgets(device)) {
settings.add(R.xml.devicesettings_widgets); display.add(R.xml.devicesettings_widgets);
} }
if (supports(device, FEAT_PASSWORD)) { if (supports(device, FEAT_PASSWORD)) {
settings.add(R.xml.devicesettings_password); display.add(R.xml.devicesettings_password);
} }
// //
// Health // Health
// //
settings.add(R.xml.devicesettings_header_health);
if (supportsStressMeasurement() && supports(device, FEAT_STRESS) && supportsSpo2() && supports(device, FEAT_SPO2)) { if (supportsStressMeasurement() && supports(device, FEAT_STRESS) && supportsSpo2() && supports(device, FEAT_SPO2)) {
settings.add(R.xml.devicesettings_heartrate_sleep_alert_activity_stress_spo2); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_heartrate_sleep_alert_activity_stress_spo2);
} else if (supportsStressMeasurement() && supports(device, FEAT_STRESS)) { } else if (supportsStressMeasurement() && supports(device, FEAT_STRESS)) {
settings.add(R.xml.devicesettings_heartrate_sleep_alert_activity_stress); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_heartrate_sleep_alert_activity_stress);
} else { } else {
settings.add(R.xml.devicesettings_heartrate_sleep_activity); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_heartrate_sleep_activity);
} }
if (supports(device, FEAT_INACTIVITY)) { if (supports(device, FEAT_INACTIVITY)) {
settings.add(R.xml.devicesettings_inactivity_dnd_no_threshold); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_inactivity_dnd_no_threshold);
} }
if (supports(device, FEAT_SLEEP_MODE_SCHEDULE)) { if (supports(device, FEAT_SLEEP_MODE_SCHEDULE)) {
settings.add(R.xml.devicesettings_sleep_mode_schedule); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_sleep_mode_schedule);
} }
if (supports(device, FEAT_GOAL_NOTIFICATION)) { if (supports(device, FEAT_GOAL_NOTIFICATION)) {
settings.add(R.xml.devicesettings_goal_notification); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_goal_notification);
} }
if (supports(device, FEAT_GOAL_SECONDARY)) { if (supports(device, FEAT_GOAL_SECONDARY)) {
settings.add(R.xml.devicesettings_goal_secondary); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_goal_secondary);
} }
if (supports(device, FEAT_VITALITY_SCORE)) { if (supports(device, FEAT_VITALITY_SCORE)) {
settings.add(R.xml.devicesettings_vitality_score); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_vitality_score);
} }
// //
// Workout // Workout
// //
settings.add(R.xml.devicesettings_header_workout); final List<Integer> workout = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.WORKOUT);
settings.add(R.xml.devicesettings_workout_start_on_phone); workout.add(R.xml.devicesettings_workout_start_on_phone);
settings.add(R.xml.devicesettings_workout_send_gps_to_band); workout.add(R.xml.devicesettings_workout_send_gps_to_band);
// //
// Notifications // Notifications
// //
settings.add(R.xml.devicesettings_header_notifications); final List<Integer> notifications = deviceSpecificSettings.addRootScreen(DeviceSpecificSettingsScreen.NOTIFICATIONS);
// TODO not implemented settings.add(R.xml.devicesettings_vibrationpatterns); // TODO not implemented settings.add(R.xml.devicesettings_vibrationpatterns);
// TODO not implemented settings.add(R.xml.devicesettings_donotdisturb_withauto_and_always); // TODO not implemented settings.add(R.xml.devicesettings_donotdisturb_withauto_and_always);
settings.add(R.xml.devicesettings_send_app_notifications); notifications.add(R.xml.devicesettings_send_app_notifications);
if (supports(device, FEAT_SCREEN_ON_ON_NOTIFICATIONS)) { if (supports(device, FEAT_SCREEN_ON_ON_NOTIFICATIONS)) {
settings.add(R.xml.devicesettings_screen_on_on_notifications); notifications.add(R.xml.devicesettings_screen_on_on_notifications);
} }
settings.add(R.xml.devicesettings_autoremove_notifications); notifications.add(R.xml.devicesettings_autoremove_notifications);
if (getCannedRepliesSlotCount(device) > 0) { if (getCannedRepliesSlotCount(device) > 0) {
settings.add(R.xml.devicesettings_canned_dismisscall_16); notifications.add(R.xml.devicesettings_canned_dismisscall_16);
} }
// //
// Calendar // Calendar
// //
if (supportsCalendarEvents()) { if (supportsCalendarEvents()) {
settings.add(R.xml.devicesettings_header_calendar); deviceSpecificSettings.addRootScreen(
settings.add(R.xml.devicesettings_sync_calendar); DeviceSpecificSettingsScreen.CALENDAR,
R.xml.devicesettings_header_calendar,
R.xml.devicesettings_sync_calendar
);
} }
// //
// Other // Other
// //
settings.add(R.xml.devicesettings_header_other);
if (getContactsSlotCount(device) > 0) { if (getContactsSlotCount(device) > 0) {
settings.add(R.xml.devicesettings_contacts); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_contacts);
} }
if (supports(device, FEAT_CAMERA_REMOTE)) { if (supports(device, FEAT_CAMERA_REMOTE)) {
settings.add(R.xml.devicesettings_camera_remote); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_camera_remote);
} }
if (supports(device, FEAT_DEVICE_ACTIONS)) { if (supports(device, FEAT_DEVICE_ACTIONS)) {
settings.add(R.xml.devicesettings_device_actions); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_device_actions);
} }
settings.add(R.xml.devicesettings_phone_silent_mode); deviceSpecificSettings.addRootScreen(R.xml.devicesettings_phone_silent_mode);
// //
// Developer // Developer
// //
settings.add(R.xml.devicesettings_header_developer); deviceSpecificSettings.addRootScreen(
settings.add(R.xml.devicesettings_keep_activity_data_on_device); DeviceSpecificSettingsScreen.DEVELOPER,
R.xml.devicesettings_keep_activity_data_on_device
);
return ArrayUtils.toPrimitive(settings.toArray(new Integer[0])); return deviceSpecificSettings;
} }
@Override @Override

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
android:icon="@drawable/ic_activity_unknown_small"
android:key="pref_screen_activity_info"
android:persistent="false"
android:title="@string/activity_info">
</PreferenceScreen>
</androidx.preference.PreferenceScreen>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
android:icon="@drawable/ic_vpn_key"
android:key="pref_screen_authentication"
android:persistent="false"
android:title="@string/pref_header_authentication">
</PreferenceScreen>
</androidx.preference.PreferenceScreen>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
android:icon="@drawable/ic_calendar_today"
android:key="pref_screen_calendar"
android:persistent="false"
android:title="@string/pref_header_calendar">
</PreferenceScreen>
</androidx.preference.PreferenceScreen>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
android:icon="@drawable/ic_mtu"
android:key="pref_screen_connection"
android:persistent="false"
android:title="@string/pref_header_connection">
</PreferenceScreen>
</androidx.preference.PreferenceScreen>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
android:icon="@drawable/ic_timer"
android:key="pref_screen_date_time"
android:persistent="false"
android:title="@string/dateformat_date_time">
</PreferenceScreen>
</androidx.preference.PreferenceScreen>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
android:icon="@drawable/ic_developer_mode"
android:key="pref_screen_developer"
android:persistent="false"
android:title="@string/pref_title_developer_settings">
</PreferenceScreen>
</androidx.preference.PreferenceScreen>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
android:icon="@drawable/ic_watch"
android:key="pref_screen_display"
android:persistent="false"
android:title="@string/pref_header_display">
</PreferenceScreen>
</androidx.preference.PreferenceScreen>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
android:icon="@drawable/ic_notifications"
android:key="pref_screen_notifications"
android:persistent="false"
android:title="@string/pref_header_notifications">
</PreferenceScreen>
</androidx.preference.PreferenceScreen>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
android:icon="@drawable/ic_activity_unknown_small"
android:key="pref_screen_workout"
android:persistent="false"
android:title="@string/menuitem_workout">
</PreferenceScreen>
</androidx.preference.PreferenceScreen>