feat: move Settings out of Files into its own searchable app with categories
This commit is contained in:
1 parent
d3e49a925d
commit
8de98f3ab3
33 files changed
+1183
-93
No files matched your search
@@ -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;
|
||||
|
||||
@@ -49,6 +49,12 @@ struct DesktopItem {
|
||||
// File extensions the app opens (manifest files.types): lowercase, no dot,
|
||||
// space-separated with a leading and trailing space, e.g. " jpg jpeg ".
|
||||
char file_types[160];
|
||||
// Settings app metadata (manifest [settings]): the category it is filed
|
||||
// under ("" = not listed unless in the settings section), a one-line
|
||||
// description and extra search words.
|
||||
char settings_category[24];
|
||||
char description[64];
|
||||
char keywords[128];
|
||||
};
|
||||
|
||||
enum LauncherItemKind : uint8_t {
|
||||
@@ -225,8 +231,6 @@ struct DesktopState {
|
||||
SvgIcon icon_apps;
|
||||
SvgIcon icon_apps_lg;
|
||||
SvgIcon icon_system_configuration_menu;
|
||||
SvgIcon icon_system_configuration;
|
||||
SvgIcon icon_system_configuration_lg;
|
||||
|
||||
// Special user folder icons (16x16 and 48x48)
|
||||
static constexpr int SPECIAL_FOLDER_COUNT = gui::SPECIAL_FOLDER_COUNT;
|
||||
|
||||
Reference in new issue
Block a user