Added profiles for custom layouts.

Users can add severals custom layouts and select one of them in recording fragment. The last selected layout is the one that will be use in the next recording.
Fixes #938.
This commit is contained in:
Román Martínez
2021-10-23 10:04:02 +02:00
parent 02cec48ae4
commit 7f9057c519
28 changed files with 1408 additions and 119 deletions
@@ -0,0 +1,93 @@
package de.dennisguse.opentracks.util;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import junit.framework.TestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class CsvLayoutUtilsTest extends TestCase {
@Test
public void testGetCsvLineParts() {
// given
String csvLineOk = "Layout Name;2;distance,1,1;speed,1,1;";
String csvLineWrong1 = "Layout Name;distance,1,1;speed,1,1;";
String csvLineWrong2 = "Layout Name;1;";
// when
List<String> partsOk = CsvLayoutUtils.getCsvLineParts(csvLineOk);
List<String> partsWrong1 = CsvLayoutUtils.getCsvLineParts(csvLineWrong1);
List<String> partsWrong2 = CsvLayoutUtils.getCsvLineParts(csvLineWrong2);
// then
assertNotNull(partsOk);
assertEquals(partsOk.size(), 4);
assertEquals(partsOk.get(0), "Layout Name");
assertEquals(partsOk.get(1), "2");
assertEquals(partsOk.get(2), "distance,1,1");
assertEquals(partsOk.get(3), "speed,1,1");
assertNull(partsWrong1);
assertNull(partsWrong2);
}
@Test
public void testGetCsvFieldParts() {
// given
String csvFieldOk1 = "distance,0,0";
String csvFieldOk2 = "speed,0,1";
String csvFieldOk3 = "time,1,0";
String csvFieldOk4 = "moving time,1,1";
String csvFieldOk5 = ";moving time,1,1";
String csvLineWrong1 = "";
String csvLineWrong2 = "distance,speed,time";
String csvLineWrong3 = "distance,0,1o";
String csvLineWrong4 = "distance,0z,1";
String csvLineWrong5 = "distance";
String csvLineWrong6 = "distance,0";
String csvLineWrong7 = "distance,1,1;";
// when
String[] ok1 = CsvLayoutUtils.getCsvFieldParts(csvFieldOk1);
String[] ok2 = CsvLayoutUtils.getCsvFieldParts(csvFieldOk2);
String[] ok3 = CsvLayoutUtils.getCsvFieldParts(csvFieldOk3);
String[] ok4 = CsvLayoutUtils.getCsvFieldParts(csvFieldOk4);
String[] ok5 = CsvLayoutUtils.getCsvFieldParts(csvFieldOk5);
String[] wrong1 = CsvLayoutUtils.getCsvFieldParts(csvLineWrong1);
String[] wrong2 = CsvLayoutUtils.getCsvFieldParts(csvLineWrong2);
String[] wrong3 = CsvLayoutUtils.getCsvFieldParts(csvLineWrong3);
String[] wrong4 = CsvLayoutUtils.getCsvFieldParts(csvLineWrong4);
String[] wrong5 = CsvLayoutUtils.getCsvFieldParts(csvLineWrong5);
String[] wrong6 = CsvLayoutUtils.getCsvFieldParts(csvLineWrong6);
String[] wrong7 = CsvLayoutUtils.getCsvFieldParts(csvLineWrong7);
// then
assertNotNull(ok1);
assertNotNull(ok2);
assertNotNull(ok3);
assertNotNull(ok4);
assertNotNull(ok5);
assertFieldOk(ok1, "distance", "0", "0");
assertFieldOk(ok2, "speed", "0", "1");
assertFieldOk(ok3, "time", "1", "0");
assertFieldOk(ok4, "moving time", "1", "1");
assertFieldOk(ok5, ";moving time", "1", "1");
assertNull(wrong1);
assertNull(wrong2);
assertNull(wrong3);
assertNull(wrong4);
assertNull(wrong5);
assertNull(wrong6);
assertNull(wrong7);
}
private void assertFieldOk(String[] ok, String name, String val1, String val2) {
assertEquals(ok[0], name);
assertEquals(ok[1], val1);
assertEquals(ok[2], val2);
}
}
@@ -2,6 +2,7 @@ package de.dennisguse.opentracks.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import androidx.preference.PreferenceManager;
import androidx.test.core.app.ApplicationProvider;
@@ -21,10 +22,14 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
@RunWith(AndroidJUnit4.class)
public class PreferencesUtilsTest {
private final Context context = ApplicationProvider.getApplicationContext();
private final Resources resources = ApplicationProvider.getApplicationContext().getResources();
@Test
public void ExportTrackFileFormat_ok() {
@@ -72,6 +77,24 @@ public class PreferencesUtilsTest {
assertEquals(TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA, trackFileFormat);
}
@Test
public void testGetAllCustomLayouts_default() {
// given
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.clear();
editor.commit();
// when
List<Layout> layouts = PreferencesUtils.getAllCustomLayouts();
// then
assertEquals(layouts.size(), 1);
assertTrue(layouts.get(0).getFields().size() > 0);
assertEquals(layouts.get(0).getName(), context.getString(R.string.stats_custom_layout_default_layout));
assertTrue(layouts.get(0).getFields().stream().anyMatch(DataField::isVisible));
}
@Test
public void testGetCustomLayout_default() {
// given
@@ -85,7 +108,7 @@ public class PreferencesUtilsTest {
// then
assertTrue(layout.getFields().size() > 0);
assertEquals(layout.getProfile(), context.getString(R.string.default_activity_default));
assertEquals(layout.getName(), context.getString(R.string.stats_custom_layout_default_layout));
assertTrue(layout.getFields().stream().anyMatch(DataField::isVisible));
}
@@ -95,8 +118,8 @@ public class PreferencesUtilsTest {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(
context.getString(R.string.stats_custom_layout_fields_key),
"run;"
context.getString(R.string.stats_custom_layouts_key),
"run;2;"
+ context.getString(R.string.stats_custom_layout_moving_time_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_distance_key) + ",1,0;"
+ context.getString(R.string.stats_custom_layout_average_moving_speed_key) + ",0,1;"
@@ -108,7 +131,8 @@ public class PreferencesUtilsTest {
// then
assertEquals(layout.getFields().size(), 4);
assertEquals(layout.getProfile(), "run");
assertEquals(layout.getName(), "run");
assertEquals(layout.getColumnsPerRow(), 2);
assertEquals(layout.getFields().get(0).getKey(), context.getString(R.string.stats_custom_layout_moving_time_key));
assertTrue(layout.getFields().get(0).isVisible());
@@ -133,8 +157,8 @@ public class PreferencesUtilsTest {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(
context.getString(R.string.stats_custom_layout_fields_key),
"walking;"
context.getString(R.string.stats_custom_layouts_key),
"walking;2;"
+ context.getString(R.string.stats_custom_layout_moving_time_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_distance_key) + ",1,0;"
+ context.getString(R.string.stats_custom_layout_coordinates_key) + ",0,1;"
@@ -146,7 +170,8 @@ public class PreferencesUtilsTest {
// then
assertEquals(layout.getFields().size(), 4);
assertEquals(layout.getProfile(), "walking");
assertEquals(layout.getName(), "walking");
assertEquals(layout.getColumnsPerRow(), 2);
assertEquals(layout.getFields().get(0).getKey(), context.getString(R.string.stats_custom_layout_moving_time_key));
assertTrue(layout.getFields().get(0).isVisible());
@@ -177,20 +202,22 @@ public class PreferencesUtilsTest {
layoutSrc.addField(new DataField(context.getString(R.string.stats_custom_layout_speed_key), context.getString(R.string.stats_speed), false, false, false));
// when
PreferencesUtils.setCustomLayout(layoutSrc);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(context.getString(R.string.stats_custom_layouts_key), layoutSrc.toCsv());
editor.commit();
// then
String csv = sharedPreferences.getString(context.getString(R.string.stats_custom_layout_fields_key), null);
String csv = sharedPreferences.getString(context.getString(R.string.stats_custom_layouts_key), null);
assertNotNull(csv);
assertEquals(csv,
"road cycling;"
+ context.getString(R.string.stats_custom_layout_moving_time_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_distance_key) + ",1,0;"
+ context.getString(R.string.stats_custom_layout_average_moving_speed_key) + ",0,1;"
+ context.getString(R.string.stats_custom_layout_speed_key) + ",0,0;");
"road cycling;" + PreferencesUtils.getLayoutColumnsByDefault() + ";"
+ context.getString(R.string.stats_custom_layout_moving_time_key) + ",1,1,0;"
+ context.getString(R.string.stats_custom_layout_distance_key) + ",1,0,0;"
+ context.getString(R.string.stats_custom_layout_average_moving_speed_key) + ",0,1,0;"
+ context.getString(R.string.stats_custom_layout_speed_key) + ",0,0,0;");
Layout layoutDst = PreferencesUtils.getCustomLayout();
assertEquals(layoutSrc.getProfile(), layoutDst.getProfile());
assertEquals(layoutSrc.getName(), layoutDst.getName());
assertEquals(layoutSrc.getFields().size(), layoutDst.getFields().size());
for (int i = 0; i < layoutSrc.getFields().size(); i++) {
assertEquals(layoutSrc.getFields().get(i).getKey(), layoutDst.getFields().get(i).getKey());
@@ -198,4 +225,122 @@ public class PreferencesUtilsTest {
assertEquals(layoutSrc.getFields().get(i).isPrimary(), layoutDst.getFields().get(i).isPrimary());
}
}
@Test
public void testEditCustomLayouts() {
// update all custom layouts
// given a custom layout with two profiles
String cyclingProfile = "cycling;2;"
+ context.getString(R.string.stats_custom_layout_moving_time_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_distance_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_average_moving_speed_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_speed_key) + ",1,1;";
String runningProfile = "running;2;"
+ context.getString(R.string.stats_custom_layout_moving_time_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_distance_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_average_pace_key) + ",0,0;"
+ context.getString(R.string.stats_custom_layout_pace_key) + ",0,0;";
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(context.getString(R.string.stats_custom_layouts_key), cyclingProfile + "\n" + runningProfile);
editor.apply();
List<Layout> layoutsBefore = PreferencesUtils.getAllCustomLayouts();
// when cyling profile is updated
String cyclingProfileUpdated = "cycling;2;"
+ context.getString(R.string.stats_custom_layout_moving_time_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_distance_key) + ",0,0;"
+ context.getString(R.string.stats_custom_layout_average_moving_speed_key) + ",0,0;"
+ context.getString(R.string.stats_custom_layout_speed_key) + ",0,0;";
List<Layout> layoutsToBeUpdated = new ArrayList<>();
layoutsToBeUpdated.add(Layout.fromCsv(cyclingProfileUpdated, resources));
layoutsToBeUpdated.add(Layout.fromCsv(runningProfile, resources));
PreferencesUtils.updateCustomLayouts(layoutsToBeUpdated);
// then only updated profile is modified in the custom layouts
List<Layout> layoutsAfter = PreferencesUtils.getAllCustomLayouts();
assertEquals(layoutsBefore.size(), 2);
assertEquals(layoutsAfter.size(), 2);
assertEquals(layoutsBefore.get(0).getFields().stream().filter(DataField::isVisible).count(), 4);
assertEquals(layoutsAfter.get(0).getFields().stream().filter(DataField::isVisible).count(), 1);
}
@Test
public void testEditCustomLayout() {
// Update only one custom layout
// given a custom layout with two profiles
String cyclingProfile = "cycling;2;"
+ context.getString(R.string.stats_custom_layout_moving_time_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_distance_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_average_moving_speed_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_speed_key) + ",1,1;";
String runningProfile = "running;2;"
+ context.getString(R.string.stats_custom_layout_moving_time_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_distance_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_average_pace_key) + ",0,0;"
+ context.getString(R.string.stats_custom_layout_pace_key) + ",0,0;";
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(context.getString(R.string.stats_custom_layouts_key), cyclingProfile + "\n" + runningProfile);
editor.apply();
List<Layout> layoutsBefore = PreferencesUtils.getAllCustomLayouts();
// when cyling profile is updated
String cyclingProfileUpdated = "cycling;2;"
+ context.getString(R.string.stats_custom_layout_moving_time_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_distance_key) + ",0,0;"
+ context.getString(R.string.stats_custom_layout_average_moving_speed_key) + ",0,0;"
+ context.getString(R.string.stats_custom_layout_speed_key) + ",0,0;";
Layout layoutToBeUpdated = Layout.fromCsv(cyclingProfileUpdated, resources);
PreferencesUtils.updateCustomLayout(layoutToBeUpdated);
// then only updated profile is modified in the custom layouts
List<Layout> layoutsAfter = PreferencesUtils.getAllCustomLayouts();
assertEquals(layoutsBefore.size(), 2);
assertEquals(layoutsAfter.size(), 2);
assertEquals(layoutsBefore.get(0).getFields().stream().filter(DataField::isVisible).count(), 4);
assertEquals(layoutsAfter.get(0).getFields().stream().filter(DataField::isVisible).count(), 1);
}
@Test
public void testGetCustomLayout_whenSelectedOneNotExists() {
// given a custom layout with two profiles and not existing custom layout selected
String cyclingProfile = "cycling;2;"
+ context.getString(R.string.stats_custom_layout_moving_time_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_distance_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_average_moving_speed_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_speed_key) + ",1,1;";
String runningProfile = "running;2;"
+ context.getString(R.string.stats_custom_layout_moving_time_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_distance_key) + ",1,1;"
+ context.getString(R.string.stats_custom_layout_average_pace_key) + ",0,0;"
+ context.getString(R.string.stats_custom_layout_pace_key) + ",0,0;";
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(context.getString(R.string.stats_custom_layouts_key), cyclingProfile + "\n" + runningProfile);
editor.putString(context.getString(R.string.stats_custom_layout_selected_layout_key), "Not Exists");
editor.apply();
// when it gets the custom layout
Layout layout = PreferencesUtils.getCustomLayout();
// then the first one was returned
assertEquals(layout.getName(), "cycling");
}
}