feat: move Settings out of Files into its own searchable app with categories

This commit is contained in:
daniel committed 2026-10-24 13:26:47 +02:00
1 parent d3e49a925d
commit 8de98f3ab3
33 files changed
+1183 -93

No files matched your search

+74 -3
View File
@@ -1,7 +1,9 @@
/*
* app_catalog.hpp
* The app catalog shared by the desktop and Files: installed app manifests
* (0:/apps/<dir>/manifest.toml) plus the desktop's built-in settings pages
* (0:/apps/<dir>/manifest.toml) plus the desktop's built-in settings pages,
* and the category, description and search keywords the Settings app
* shows for each settings page
* Copyright (c) 2026 Daniel Hammer
*/
@@ -17,24 +19,61 @@
namespace gui {
// Settings app categories, in display order. A manifest may name any other
// [settings] category; the Settings app lists those after these, by name.
inline constexpr const char* kSettingsCategories[] = {
"Personalization", "Network", "Devices", "Time & Language",
"Accounts", "Privacy & Security", "System",
};
inline constexpr const char* kSettingsDefaultCategory = "System";
// Built-in settings pages the desktop implements itself. Other processes
// list them by id and open them with a WIN_REQ_LAUNCH_ITEM request.
struct CatalogBuiltinPage {
const char* id;
const char* label;
const char* icon_path;
const char* category;
const char* description;
const char* keywords;
};
inline constexpr CatalogBuiltinPage kCatalogDesktopSettings = {
"desktop-settings", "Desktop Settings", "0:/os/icons/preferences-desktop-apps.svg"
"desktop-settings", "Desktop Settings", "0:/os/icons/preferences-desktop-apps.svg",
"Personalization", "Wallpaper, accent color, panel and clock",
"background wallpaper image accent color colour theme appearance panel "
"shadows clock 24-hour scale"
};
inline constexpr CatalogBuiltinPage kCatalogUserManagement = {
"user-management", "User Management", "0:/os/icons/user-home.svg"
"user-management", "User Management", "0:/os/icons/user-home.svg",
"Accounts", "Add, remove and edit user accounts",
"users accounts password login admin administrator role display name"
};
inline constexpr const CatalogBuiltinPage* kCatalogBuiltinPages[] = {
&kCatalogDesktopSettings, &kCatalogUserManagement,
};
inline const CatalogBuiltinPage* app_catalog_builtin_page(const char* id) {
for (const CatalogBuiltinPage* page : kCatalogBuiltinPages) {
if (id && montauk::streq(page->id, id)) return page;
}
return nullptr;
}
// Copy a built-in page's Settings app metadata onto its catalog item.
inline void app_catalog_apply_page_info(DesktopItem* item, const CatalogBuiltinPage* page) {
if (!item || !page) return;
montauk::strncpy(item->settings_category, page->category, sizeof(item->settings_category));
montauk::strncpy(item->description, page->description, sizeof(item->description));
montauk::strncpy(item->keywords, page->keywords, sizeof(item->keywords));
}
// True if the Settings app lists the item: every settings-section item, plus
// any other app whose manifest names a [settings] category.
inline bool app_catalog_in_settings(const DesktopItem& item) {
return item.section == DESKTOP_ITEM_SECTION_SETTINGS || item.settings_category[0];
}
// out = a + b + c (+ d + e), truncated to out_max.
inline void app_catalog_join(char* out, int out_max, const char* a, const char* b,
const char* c, const char* d = "", const char* e = "") {
@@ -137,6 +176,11 @@ inline void app_catalog_add_manifest_apps(DesktopState* ds) {
bool launch_with_home = doc.get_bool("launch.pass_home_dir", true);
const char* section_name = doc.get_string("desktop.section", "apps");
bool admin_only = doc.get_bool("desktop.admin_only", false);
// How the Settings app files and finds the item (see
// app_catalog_in_settings).
const char* settings_category = doc.get_string("settings.category", "");
const char* description = doc.get_string("settings.description", "");
const char* keywords = doc.get_string("settings.keywords", "");
if (id[0] == '\0' || binary[0] == '\0') {
montauk::print("app catalog: skipping app manifest with missing id or binary\n");
doc.destroy();
@@ -183,6 +227,12 @@ inline void app_catalog_add_manifest_apps(DesktopState* ds) {
item->launch_kind = DESKTOP_ITEM_LAUNCH_EXECUTABLE;
item->builtin_id = -1;
item->section = section;
if (!settings_category[0] && section == DESKTOP_ITEM_SECTION_SETTINGS)
settings_category = kSettingsDefaultCategory;
montauk::strncpy(item->settings_category, settings_category,
sizeof(item->settings_category));
montauk::strncpy(item->description, description, sizeof(item->description));
montauk::strncpy(item->keywords, keywords, sizeof(item->keywords));
// Build full binary path: 0:/apps/<dir>/<binary>
app_catalog_join(item->binary_path, sizeof(item->binary_path),
@@ -225,6 +275,27 @@ inline void app_catalog_add_manifest_apps(DesktopState* ds) {
}
}
// The built-in settings pages as catalog items, for processes other than the
// desktop (which builds its own from its registry). icon_size 0 skips
// loading icons.
inline void app_catalog_add_builtin_pages(DesktopState* ds, int icon_size) {
for (const CatalogBuiltinPage* page : kCatalogBuiltinPages) {
DesktopItem* item = app_catalog_next_slot(ds);
if (!item) return;
montauk::memset(item, 0, sizeof(*item));
montauk::strncpy(item->id, page->id, sizeof(item->id));
montauk::strncpy(item->name, page->label, sizeof(item->name));
montauk::strncpy(item->icon_path, page->icon_path, sizeof(item->icon_path));
if (icon_size > 0)
item->icon = svg_load(page->icon_path, icon_size, icon_size, colors::ICON_COLOR);
item->section = DESKTOP_ITEM_SECTION_SETTINGS;
item->launch_kind = DESKTOP_ITEM_LAUNCH_BUILTIN;
item->builtin_id = -1;
app_catalog_apply_page_info(item, page);
ds->desktop_item_count++;
}
}
inline int app_catalog_compare_ci(const char* a, const char* b) {
while (*a && *b) {
char ca = (*a >= 'A' && *a <= 'Z') ? (*a + 32) : *a;