Recording stats layout customizable.

Users can select the order, visibility and importance (primary or secondary) of all stats for recording layout from the Settings.
Also, users can select the number of columns per row in the recording layout: 1, 2 or 3.
Finally, show altitude/coordinate from settings have been removed (not needed anymore).
Fixes #659.
Fixes #302.
Fixes #820.
This commit is contained in:
Román Martínez
2021-06-19 21:29:06 +02:00
parent 7f10ae5c3f
commit 9c4c8131f5
93 changed files with 2146 additions and 1126 deletions
@@ -16,9 +16,11 @@
package de.dennisguse.opentracks.util;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.res.TypedArray;
import android.net.Uri;
import android.util.Log;
@@ -26,8 +28,16 @@ import androidx.annotation.VisibleForTesting;
import androidx.documentfile.provider.DocumentFile;
import androidx.preference.PreferenceManager;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.content.data.DataField;
import de.dennisguse.opentracks.content.data.Distance;
import de.dennisguse.opentracks.content.data.Layout;
import de.dennisguse.opentracks.io.file.TrackFileFormat;
/**
@@ -44,7 +54,9 @@ public class PreferencesUtils {
@Deprecated //Should only be used to get a sharedPreference for more than one interaction!
public static SharedPreferences getSharedPreferences(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
PreferencesOpenHelper.newInstance(context, sharedPreferences).checkForUpgrade();
return sharedPreferences;
}
public static String getDefaultActivity(SharedPreferences sharedPreferences, Context context) {
@@ -80,7 +92,7 @@ public class PreferencesUtils {
return sharedPreferences.getBoolean(getKey(context, keyId), defaultValue);
}
private static int getInt(SharedPreferences sharedPreferences, Context context, int keyId, int defaultValue) {
static int getInt(SharedPreferences sharedPreferences, Context context, int keyId, int defaultValue) {
try {
return sharedPreferences.getInt(getKey(context, keyId), defaultValue);
} catch (ClassCastException e) {
@@ -123,6 +135,12 @@ public class PreferencesUtils {
editor.apply();
}
static void setInt(SharedPreferences sharedPreferences, Context context, int keyId, int value) {
Editor editor = sharedPreferences.edit();
editor.putInt(getKey(context, keyId), value);
editor.apply();
}
public static boolean isMetricUnits(SharedPreferences sharedPreferences, Context context) {
final String STATS_UNIT = context.getString(R.string.stats_units_default);
return STATS_UNIT.equals(getString(sharedPreferences, context, R.string.stats_units_key, STATS_UNIT));
@@ -196,16 +214,6 @@ public class PreferencesUtils {
return getBoolean(sharedPreferences, context, R.string.stats_fullscreen_while_recording_key, DEFAULT);
}
public static boolean isShowStatsAltitude(SharedPreferences sharedPreferences, Context context) {
final boolean STATS_SHOW_ALTITUDE = context.getResources().getBoolean(R.bool.stats_show_altitude_default);
return getBoolean(sharedPreferences, context, R.string.stats_show_grade_altitude_key, STATS_SHOW_ALTITUDE);
}
public static boolean isStatsShowCoordinate(SharedPreferences sharedPreferences, Context context) {
final boolean STATS_SHOW_COORDINATE = context.getResources().getBoolean(R.bool.stats_show_coordinate_default);
return getBoolean(sharedPreferences, context, R.string.stats_show_coordinate_key, STATS_SHOW_COORDINATE);
}
public static int getVoiceFrequency(SharedPreferences sharedPreferences, Context context) {
final int VOICE_FREQUENCY_DEFAULT = Integer.parseInt(context.getResources().getString(R.string.voice_frequency_default));
return getInt(sharedPreferences, context, R.string.voice_frequency_key, VOICE_FREQUENCY_DEFAULT);
@@ -318,4 +326,78 @@ public class PreferencesUtils {
public static boolean isDefaultExportDirectoryUri(SharedPreferences sharedPreferences, Context context) {
return getDefaultExportDirectoryUri(sharedPreferences, context) != null;
}
public static int getLayoutColumns(SharedPreferences sharedPreferences, Context context) {
return getInt(sharedPreferences, context, R.string.stats_custom_layout_columns_key, context.getResources().getInteger(R.integer.stats_custom_layout_columns_default));
}
public static void setLayoutColumns(SharedPreferences sharedPreferences, Context context, int columns) {
setInt(sharedPreferences, context, R.string.stats_custom_layout_columns_key, columns);
}
private static List<TypedArray> getMultiTypedArray(Context context, String key) {
List<TypedArray> typedArrays = new ArrayList<>();
try {
Class<R.array> resource = R.array.class;
Field field;
int i = 0;
do {
field = resource.getField(key + context.getString(R.string.stats_custom_layout_fields_default_value_separator) + i);
typedArrays.add(context.getResources().obtainTypedArray(field.getInt(null)));
i++;
} while (field != null);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
}
return typedArrays;
}
@SuppressLint("ResourceType")
static String buildDefaultLayout(Context context) {
List<TypedArray> fieldsArrays = getMultiTypedArray(context, "stats_custom_layout_fields_default_value");
return context.getString(R.string.default_activity_default) + CsvConstants.LINE_SEPARATOR
+ fieldsArrays.stream().map(i -> i.getString(0) + CsvConstants.ITEM_SEPARATOR + i.getString(1)).collect(Collectors.joining(CsvConstants.LINE_SEPARATOR))
+ CsvConstants.LINE_SEPARATOR;
}
public static Layout getCustomLayout(SharedPreferences sharedPreferences, Context context) {
String csvCustomLayout = getString(sharedPreferences, context, R.string.stats_custom_layout_fields_key, buildDefaultLayout(context));
List<String> csvParts = Arrays.asList(csvCustomLayout.split(CsvConstants.LINE_SEPARATOR));
Layout layout = new Layout(csvParts.get(0));
for (int i = 1; i < csvParts.size(); i++) {
String[] fieldParts = csvParts.get(i).split(CsvConstants.ITEM_SEPARATOR);
layout.addField(fieldParts[0], DataField.getTitleByKey(context, fieldParts[0]), fieldParts[1].equals(DataField.YES_VALUE), fieldParts[2].equals(DataField.YES_VALUE), fieldParts[0].equals(context.getString(R.string.stats_custom_layout_coordinates_key)));
}
return layout;
}
public static void setCustomLayout(SharedPreferences sharedPreferences, Context context, Layout layout) {
List<DataField> fields = layout.getFields();
if (fields.isEmpty()) {
return;
}
String csv = layout.getProfile() + CsvConstants.LINE_SEPARATOR
+ fields.stream().map(DataField::toCsv).collect(Collectors.joining(CsvConstants.LINE_SEPARATOR)) + CsvConstants.LINE_SEPARATOR;
setString(sharedPreferences, context, R.string.stats_custom_layout_fields_key, csv);
}
public static void resetCustomLayoutPreferences(Context context) {
SharedPreferences settings = getSharedPreferences(context);
if (settings.contains(context.getString(R.string.stats_custom_layout_fields_key))) {
SharedPreferences.Editor editor = settings.edit();
editor.remove(context.getString(R.string.stats_custom_layout_fields_key));
editor.commit();
}
if (settings.contains(context.getString(R.string.stats_custom_layout_columns_key))) {
SharedPreferences.Editor editor = settings.edit();
editor.remove(context.getString(R.string.stats_custom_layout_columns_key));
editor.commit();
}
}
}