/* 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 . */ 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. *

* 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. *

* There can be an arbitrary number of nested sub-screens, as long as they are all mapped by key in the * subScreens map. *

* See the XiaomiCoordinator and ZeppOsCoordinator for example usages. */ public class DeviceSpecificSettings implements Parcelable { private final List rootScreens = new ArrayList<>(); private final Map> 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 addRootScreen(final DeviceSpecificSettingsScreen screen) { if (!rootScreens.contains(screen.getXml())) { rootScreens.add(screen.getXml()); } return addSubScreen(screen, screen.getXml()); } public List addRootScreen(final DeviceSpecificSettingsScreen screen, final int... subScreens) { final List 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 addSubScreen(final DeviceSpecificSettingsScreen rootScreen, final int... screens) { return addSubScreen(rootScreen.getKey(), screens); } private List addSubScreen(final String key, final int... screens) { if (!subScreens.containsKey(key)) { subScreens.put(key, new ArrayList<>()); } final List 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> 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 getRootScreens() { return rootScreens; } @Nullable public List getScreen(@NonNull final String key) { return subScreens.get(key); } public List getAllScreens() { final List allScreens = new ArrayList<>(rootScreens); for (final List screens : subScreens.values()) { allScreens.addAll(screens); } return allScreens; } public static final Creator CREATOR = new Creator() { @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> e : subScreens.entrySet()) { dest.writeString(e.getKey()); dest.writeInt(e.getValue().size()); for (final Integer s : e.getValue()) { dest.writeInt(s); } } } }