Settings: Install updates, when asked or by itself

Off by default: what runs on the device changes only when its owner
said it may (issue #52).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0162FokPdvY2KsS4NBfwyWPk
This commit is contained in:
2026-10-11 17:49:09 +02:00
co-authored by Claude Opus 5.5
parent 17651cb911
commit 8ba0102910
5 changed files with 18 additions and 2 deletions
+3
View File
@@ -48,6 +48,7 @@ const Member kRows[] = {
{3, {Row::Wifi, Kind::Page, "Wi-Fi"}}, {3, {Row::Wifi, Kind::Page, "Wi-Fi"}},
{3, {Row::Vpn, Kind::Page, "VPN"}}, {3, {Row::Vpn, Kind::Page, "VPN"}},
{4, {Row::CheckUpdates, Kind::Toggle, "Check for updates"}}, {4, {Row::CheckUpdates, Kind::Toggle, "Check for updates"}},
{4, {Row::InstallUpdates, Kind::Toggle, "Install updates"}},
{4, {Row::Firmware, Kind::Page, "Firmware"}}, {4, {Row::Firmware, Kind::Page, "Firmware"}},
{4, {Row::DebugConsole, Kind::Page, "Debug Console"}}, {4, {Row::DebugConsole, Kind::Page, "Debug Console"}},
{4, {Row::About, Kind::Page, "About"}}, {4, {Row::About, Kind::Page, "About"}},
@@ -152,6 +153,7 @@ std::string SettingsMenu::value(int i) const {
case Row::Gnss: return settings_.getBool(Setting::GnssEnabled) ? "On" : "Off"; case Row::Gnss: return settings_.getBool(Setting::GnssEnabled) ? "On" : "Off";
case Row::GnssQuiet: return settings_.getBool(Setting::GnssQuietForLora) ? "On" : "Off"; case Row::GnssQuiet: return settings_.getBool(Setting::GnssQuietForLora) ? "On" : "Off";
case Row::CheckUpdates: return settings_.getBool(Setting::CheckUpdates) ? "Daily" : "Off"; case Row::CheckUpdates: return settings_.getBool(Setting::CheckUpdates) ? "Daily" : "Off";
case Row::InstallUpdates: return settings_.getBool(Setting::InstallUpdates) ? "By itself" : "When asked";
case Row::Coordinates: return settings_.getBool(Setting::CoordinatesDms) ? "Deg min sec" : "Decimal"; case Row::Coordinates: return settings_.getBool(Setting::CoordinatesDms) ? "Deg min sec" : "Decimal";
case Row::ProbeMacs: return settings_.getBool(Setting::ProbeMacRaw) ? "Raw" : "Pseudonymised"; case Row::ProbeMacs: return settings_.getBool(Setting::ProbeMacRaw) ? "Raw" : "Pseudonymised";
case Row::Wifi: return settings_.getBool(Setting::WifiEnabled) ? "On" : "Off"; case Row::Wifi: return settings_.getBool(Setting::WifiEnabled) ? "On" : "Off";
@@ -210,6 +212,7 @@ void SettingsMenu::toggle(int i) {
if (row(i) == Row::Gnss) settings_.setBool(Setting::GnssEnabled, !settings_.getBool(Setting::GnssEnabled)); if (row(i) == Row::Gnss) settings_.setBool(Setting::GnssEnabled, !settings_.getBool(Setting::GnssEnabled));
if (row(i) == Row::GnssQuiet) settings_.setBool(Setting::GnssQuietForLora, !settings_.getBool(Setting::GnssQuietForLora)); if (row(i) == Row::GnssQuiet) settings_.setBool(Setting::GnssQuietForLora, !settings_.getBool(Setting::GnssQuietForLora));
if (row(i) == Row::CheckUpdates) settings_.setBool(Setting::CheckUpdates, !settings_.getBool(Setting::CheckUpdates)); if (row(i) == Row::CheckUpdates) settings_.setBool(Setting::CheckUpdates, !settings_.getBool(Setting::CheckUpdates));
if (row(i) == Row::InstallUpdates) settings_.setBool(Setting::InstallUpdates, !settings_.getBool(Setting::InstallUpdates));
if (row(i) == Row::Coordinates) settings_.setBool(Setting::CoordinatesDms, !settings_.getBool(Setting::CoordinatesDms)); if (row(i) == Row::Coordinates) settings_.setBool(Setting::CoordinatesDms, !settings_.getBool(Setting::CoordinatesDms));
if (row(i) == Row::ProbeMacs) settings_.setBool(Setting::ProbeMacRaw, !settings_.getBool(Setting::ProbeMacRaw)); if (row(i) == Row::ProbeMacs) settings_.setBool(Setting::ProbeMacRaw, !settings_.getBool(Setting::ProbeMacRaw));
} }
+1 -1
View File
@@ -12,7 +12,7 @@ namespace roro {
// Rendering and navigation live in the App. Every index is into what is listed now. // Rendering and navigation live in the App. Every index is into what is listed now.
class SettingsMenu { class SettingsMenu {
public: public:
enum class Row { LongName, ShortName, Region, Timezone, Brightness, DimTimeout, OffTimeout, Launcher, Theme, ThemeLight, Sound, Gnss, GnssQuiet, Coordinates, ProbeMacs, Wifi, CheckUpdates, Firmware, Vpn, DebugConsole, About, enum class Row { LongName, ShortName, Region, Timezone, Brightness, DimTimeout, OffTimeout, Launcher, Theme, ThemeLight, Sound, Gnss, GnssQuiet, Coordinates, ProbeMacs, Wifi, CheckUpdates, InstallUpdates, Firmware, Vpn, DebugConsole, About,
GroupDevice, GroupDisplay, GroupPosition, GroupNetwork, GroupSystem }; GroupDevice, GroupDisplay, GroupPosition, GroupNetwork, GroupSystem };
enum class Kind { Text, Choice, Toggle, Slider, Page, Group }; enum class Kind { Text, Choice, Toggle, Slider, Page, Group };
+1
View File
@@ -56,6 +56,7 @@ const Definition kDefinitions[] = {
{"launcher_list", Kind::Bool, 0, nullptr, 0, 1}, // off: the grid {"launcher_list", Kind::Bool, 0, nullptr, 0, 1}, // off: the grid
{"theme", Kind::Int, 0, nullptr, 0, 6}, // roro9stack's own; ui::kThemeCount of them {"theme", Kind::Int, 0, nullptr, 0, 6}, // roro9stack's own; ui::kThemeCount of them
{"theme_light", Kind::Bool, 0, nullptr, 0, 1}, {"theme_light", Kind::Bool, 0, nullptr, 0, 1},
{"auto_install", Kind::Bool, 0, nullptr, 0, 1}, // off: what runs here changes only when someone says so
}; };
static_assert(sizeof(kDefinitions) / sizeof(kDefinitions[0]) == static_cast<size_t>(Setting::Count), static_assert(sizeof(kDefinitions) / sizeof(kDefinitions[0]) == static_cast<size_t>(Setting::Count),
"every Setting needs a definition"); "every Setting needs a definition");
+1
View File
@@ -44,6 +44,7 @@ enum class Setting : uint8_t {
LauncherList, // bool: the Launcher is a list of names instead of a grid of icons (issue #9) LauncherList, // bool: the Launcher is a list of names instead of a grid of icons (issue #9)
Theme, // int: the colour theme, an index into ui::palette (issue #10) Theme, // int: the colour theme, an index into ui::palette (issue #10)
ThemeLight, // bool: its light side instead of its dark one ThemeLight, // bool: its light side instead of its dark one
InstallUpdates, // bool: a newer release found by the daily check is installed without being asked for (issue #52)
Count Count
}; };
+12 -1
View File
@@ -67,7 +67,7 @@ void test_every_setting_is_in_one_group() {
total += f.menu.count(); total += f.menu.count();
f.menu.close(); f.menu.close();
} }
TEST_ASSERT_EQUAL(21, total); TEST_ASSERT_EQUAL(22, total);
int i = -1; int i = -1;
TEST_ASSERT_TRUE(f.menu.reveal(SettingsMenu::Row::Vpn, i)); TEST_ASSERT_TRUE(f.menu.reveal(SettingsMenu::Row::Vpn, i));
TEST_ASSERT_EQUAL_STRING("Network", f.menu.title().c_str()); TEST_ASSERT_EQUAL_STRING("Network", f.menu.title().c_str());
@@ -204,6 +204,16 @@ void test_pause_gnss_for_lora_is_off_by_default() {
// R1, Q165: the device looks for a newer release once a day. It installs nothing by itself, so it // R1, Q165: the device looks for a newer release once a day. It installs nothing by itself, so it
// is on unless switched off. // is on unless switched off.
void test_installing_updates_by_itself_is_off_by_default() {
Fixture f;
int row = f.row(SettingsMenu::Row::InstallUpdates);
TEST_ASSERT_EQUAL_STRING("Install updates", f.menu.label(row).c_str());
TEST_ASSERT_EQUAL_STRING("When asked", f.menu.value(row).c_str());
f.menu.toggle(row);
TEST_ASSERT_TRUE(f.settings.getBool(Setting::InstallUpdates));
TEST_ASSERT_EQUAL_STRING("By itself", f.menu.value(row).c_str());
}
void test_check_for_updates_is_on_by_default() { void test_check_for_updates_is_on_by_default() {
Fixture f; Fixture f;
int row = f.row(SettingsMenu::Row::CheckUpdates); int row = f.row(SettingsMenu::Row::CheckUpdates);
@@ -245,6 +255,7 @@ int main() {
RUN_TEST(test_names_are_text_rows_with_their_byte_limits); RUN_TEST(test_names_are_text_rows_with_their_byte_limits);
RUN_TEST(test_pause_gnss_for_lora_is_off_by_default); RUN_TEST(test_pause_gnss_for_lora_is_off_by_default);
RUN_TEST(test_check_for_updates_is_on_by_default); RUN_TEST(test_check_for_updates_is_on_by_default);
RUN_TEST(test_installing_updates_by_itself_is_off_by_default);
RUN_TEST(test_gnss_and_coordinate_rows_toggle); RUN_TEST(test_gnss_and_coordinate_rows_toggle);
RUN_TEST(test_the_debug_console_is_a_page_that_says_off); RUN_TEST(test_the_debug_console_is_a_page_that_says_off);
return UNITY_END(); return UNITY_END();