From daa4689f44ecd87fbf4e34bb1f7deeb6be027e8f Mon Sep 17 00:00:00 2001 From: Jeff Shelley Date: Tue, 28 Oct 2025 09:45:49 -0500 Subject: [PATCH] Allow adding newly developed UI Components to existing custom layouts. Fixes #2176. --- .../opentracks/settings/PreferencesUtils.java | 15 +++++++++++ .../RecordingLayoutIO.java | 26 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/main/java/de/dennisguse/opentracks/settings/PreferencesUtils.java b/src/main/java/de/dennisguse/opentracks/settings/PreferencesUtils.java index 79f5d4f7f..263cfcce4 100644 --- a/src/main/java/de/dennisguse/opentracks/settings/PreferencesUtils.java +++ b/src/main/java/de/dennisguse/opentracks/settings/PreferencesUtils.java @@ -52,6 +52,7 @@ import de.dennisguse.opentracks.io.file.TrackFileFormat; import de.dennisguse.opentracks.io.file.TrackFilenameGenerator; import de.dennisguse.opentracks.sensors.SensorType; import de.dennisguse.opentracks.ui.customRecordingLayout.CsvLayoutUtils; +import de.dennisguse.opentracks.ui.customRecordingLayout.DataField; import de.dennisguse.opentracks.ui.customRecordingLayout.RecordingLayout; import de.dennisguse.opentracks.ui.customRecordingLayout.RecordingLayoutIO; @@ -850,6 +851,20 @@ public class PreferencesUtils { return resources.getString(R.string.stats_custom_layout_default_layout); } + /** + * @return List of all available field keys with their default visibility settings + */ + @SuppressLint("ResourceType") + public static List getAllAvailableFields() { + List fieldsArrays = getLayoutDataFields(); + return fieldsArrays.stream() + .map(i -> { + String fieldKey = i.getString(0); + return new DataField(fieldKey, false, false, fieldKey.equals(resources.getString(R.string.stats_custom_layout_coordinates_key))); + }) + .toList(); + } + /** * @return custom layout selected or the first one if any has been selected or the one selected is not exists anymore. */ diff --git a/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/RecordingLayoutIO.java b/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/RecordingLayoutIO.java index fd30e6610..e85fff22f 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/RecordingLayoutIO.java +++ b/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/RecordingLayoutIO.java @@ -6,6 +6,7 @@ import android.util.Log; import androidx.annotation.NonNull; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import de.dennisguse.opentracks.R; @@ -34,9 +35,34 @@ public class RecordingLayoutIO { } recordingLayout.addField(fromCSV(fieldParts, resources)); } + + // Add any new fields that have been added to the codebase since this layout was saved + addAllInvisibleDataFields(recordingLayout, resources); + return recordingLayout; } + /** + * Adds any missing fields to the layout as hidden fields. + * This ensures that new fields added to the codebase appear in existing layouts. + */ + private static void addAllInvisibleDataFields(@NonNull RecordingLayout recordingLayout, @NonNull Resources resources) { + // Get all field keys currently in the layout + Set existingFieldKeys = recordingLayout.getFields().stream() + .map(DataField::getKey) + .collect(Collectors.toSet()); + + // Get all available fields from the codebase + List allAvailableFields = PreferencesUtils.getAllAvailableFields(); + + // Add any missing fields as hidden + for (DataField dataField : allAvailableFields) { + if (!existingFieldKeys.contains(dataField.getKey())) { + recordingLayout.addField(dataField); + } + } + } + public static String toCSV(List recordingLayouts) { return recordingLayouts.stream().map(RecordingLayout::toCsv).collect(Collectors.joining(CsvLayoutUtils.LINE_SEPARATOR)); }