From fd1e486f5440665b476d0e9c9ce3c06a1df01821 Mon Sep 17 00:00:00 2001 From: Bharat Date: Fri, 12 Jul 2024 01:03:17 +0530 Subject: [PATCH 1/7] library: Add Language and Category filters Initial implementation to add filters for demos --- src/Library/Library.blp | 36 +++++++++++++++++++++++++++++ src/Library/Library.js | 51 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 81 insertions(+), 6 deletions(-) diff --git a/src/Library/Library.blp b/src/Library/Library.blp index c63bf450f..4e05c1783 100644 --- a/src/Library/Library.blp +++ b/src/Library/Library.blp @@ -59,6 +59,42 @@ Adw.Window window { } } + Box { + DropDown dropdown_language { + halign: end; + margin-end: 12; + hexpand: true; + + model: StringList { + strings [ + "All Languages", + "JavaScript", + "Python", + "Vala", + "Rust" + ] + }; + } + + DropDown dropdown_category { + halign: end; + + model: StringList { + strings [ + "All Categories", + "Tools", + "Network", + "Controls", + "Layout", + "Feedback", + "Navigation", + "User_Interface", + "Platform" + ] + }; + } + } + ListBox library_uncategorized { selection-mode: none; diff --git a/src/Library/Library.js b/src/Library/Library.js index b70358c95..ea0704fee 100644 --- a/src/Library/Library.js +++ b/src/Library/Library.js @@ -19,7 +19,13 @@ import { build } from "../../troll/src/builder.js"; export default function Library({ application }) { const objects = build(resource); - const { window, picture_illustration, search_entry } = objects; + const { + window, + picture_illustration, + search_entry, + dropdown_category, + dropdown_language, + } = objects; window.application = application; picture_illustration.set_resource(illustration); @@ -28,6 +34,8 @@ export default function Library({ application }) { } let last_triggered; + let current_category = "All Categories"; + let current_language = "All Languages"; window.connect("close-request", quitOnLastWindowClose); @@ -51,25 +59,56 @@ export default function Library({ application }) { category_map.set(demo.category, objects[`library_${demo.category}`]); } objects[`library_${demo.category}`].append(entry_row); - widgets_map.set(demo.name, { entry_row, category: demo.category }); + widgets_map.set(demo.name, { + entry_row, + category: demo.category, + languages: demo.languages, + }); }); - search_entry.connect("search-changed", () => { + function updateVisibility() { const search_term = search_entry.get_text().toLowerCase(); const visible_categories = new Set(); - widgets_map.forEach(({ entry_row, category }, demo_name) => { - const is_match = demo_name.toLowerCase().includes(search_term); + widgets_map.forEach(({ entry_row, category, languages }, demo_name) => { + const category_match = + current_category === "All Categories" || + category.includes(current_category.toLowerCase()); + const language_match = + current_language === "All Languages" || + languages.includes(current_language.toLowerCase()); + const search_match = demo_name.toLowerCase().includes(search_term); + const is_match = + category_match && + language_match && + (search_term === "" || search_match); entry_row.visible = is_match; if (is_match) visible_categories.add(category); }); category_map.forEach((category_widget, category_name) => { const label = objects[`label_${category_name}`]; - if (label) label.visible = search_term === ""; + if (label) + label.visible = + current_category === "All Categories" && + current_language === "All Languages" && + search_term === ""; category_widget.visible = visible_categories.has(category_name); }); + } + + search_entry.connect("search-changed", updateVisibility); + + dropdown_category.connect("notify::selected", () => { + current_category = dropdown_category.get_selected_item().get_string(); + updateVisibility(); }); + + dropdown_language.connect("notify::selected", () => { + current_language = dropdown_language.get_selected_item().get_string(); + updateVisibility(); + }); + const action_library = new Gio.SimpleAction({ name: "library", parameter_type: null, From ed1a05f54752b240589f4ae49ebe1b91ebe8420e Mon Sep 17 00:00:00 2001 From: Bharat Date: Mon, 22 Jul 2024 12:10:25 +0530 Subject: [PATCH 2/7] minor change: rename function --- src/Library/Library.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Library/Library.js b/src/Library/Library.js index ea0704fee..adbfc043b 100644 --- a/src/Library/Library.js +++ b/src/Library/Library.js @@ -66,7 +66,7 @@ export default function Library({ application }) { }); }); - function updateVisibility() { + function updateList() { const search_term = search_entry.get_text().toLowerCase(); const visible_categories = new Set(); @@ -97,16 +97,16 @@ export default function Library({ application }) { }); } - search_entry.connect("search-changed", updateVisibility); + search_entry.connect("search-changed", updateList); dropdown_category.connect("notify::selected", () => { current_category = dropdown_category.get_selected_item().get_string(); - updateVisibility(); + updateList(); }); dropdown_language.connect("notify::selected", () => { current_language = dropdown_language.get_selected_item().get_string(); - updateVisibility(); + updateList(); }); const action_library = new Gio.SimpleAction({ From a0fc66ecfd714f973bdcc835c03fb1f1790a6a04 Mon Sep 17 00:00:00 2001 From: Bharat Date: Wed, 24 Jul 2024 21:28:49 +0530 Subject: [PATCH 3/7] improvements: Set dropdown to flat style Construct dropdown values from JavaScript Logic change for filtering, make use of index values instead of strings --- src/Library/Library.blp | 24 ------------- src/Library/Library.js | 74 ++++++++++++++++++++++++++++------------- 2 files changed, 51 insertions(+), 47 deletions(-) diff --git a/src/Library/Library.blp b/src/Library/Library.blp index 4e05c1783..33e4e1942 100644 --- a/src/Library/Library.blp +++ b/src/Library/Library.blp @@ -64,34 +64,10 @@ Adw.Window window { halign: end; margin-end: 12; hexpand: true; - - model: StringList { - strings [ - "All Languages", - "JavaScript", - "Python", - "Vala", - "Rust" - ] - }; } DropDown dropdown_category { halign: end; - - model: StringList { - strings [ - "All Categories", - "Tools", - "Network", - "Controls", - "Layout", - "Feedback", - "Navigation", - "User_Interface", - "Platform" - ] - }; } } diff --git a/src/Library/Library.js b/src/Library/Library.js index adbfc043b..55dc3fc26 100644 --- a/src/Library/Library.js +++ b/src/Library/Library.js @@ -1,9 +1,11 @@ import Gio from "gi://Gio"; +import Gtk from "gi://Gtk"; import { decode, demos_dir, getLanguage, + makeDropdownFlat, settings as global_settings, quitOnLastWindowClose, } from "../util.js"; @@ -28,21 +30,42 @@ export default function Library({ application }) { } = objects; window.application = application; picture_illustration.set_resource(illustration); + makeDropdownFlat(dropdown_category); + makeDropdownFlat(dropdown_language); if (__DEV__) { window.add_css_class("devel"); } let last_triggered; - let current_category = "All Categories"; - let current_language = "All Languages"; + let current_category = 0; + let current_language = 0; window.connect("close-request", quitOnLastWindowClose); const demos = getDemos(); const widgets_map = new Map(); const category_map = new Map(); + const language_model = new Gtk.StringList(); + const category_model = new Gtk.StringList(); + language_model.append("All Languages"); + category_model.append("All Categories"); + const language_check = ["All Languages"]; + const category_check = ["All Categories"]; + demos.forEach((demo) => { + demo.languages.forEach((lang) => { + if (!language_check.includes(lang)) { + language_check.push(lang); + language_model.append(lang); + } + }); + + if (!category_check.includes(demo.category)) { + category_check.push(demo.category); + category_model.append(demo.category); + } + const entry_row = new EntryRow({ demo: demo }); if (demo.name === "Welcome") last_triggered = entry_row; @@ -61,37 +84,42 @@ export default function Library({ application }) { objects[`library_${demo.category}`].append(entry_row); widgets_map.set(demo.name, { entry_row, - category: demo.category, - languages: demo.languages, + category_index: category_check.indexOf(demo.category), + languages_index: demo.languages.map((lang) => + language_check.indexOf(lang), + ), }); }); + dropdown_language.set_model(language_model); + dropdown_category.set_model(category_model); + function updateList() { const search_term = search_entry.get_text().toLowerCase(); const visible_categories = new Set(); - widgets_map.forEach(({ entry_row, category, languages }, demo_name) => { - const category_match = - current_category === "All Categories" || - category.includes(current_category.toLowerCase()); - const language_match = - current_language === "All Languages" || - languages.includes(current_language.toLowerCase()); - const search_match = demo_name.toLowerCase().includes(search_term); - const is_match = - category_match && - language_match && - (search_term === "" || search_match); - entry_row.visible = is_match; - if (is_match) visible_categories.add(category); - }); + widgets_map.forEach( + ({ entry_row, category_index, languages_index }, demo_name) => { + const category_match = + current_category === 0 || category_index === current_category; + const language_match = + current_language === 0 || languages_index.includes(current_language); + const search_match = demo_name.toLowerCase().includes(search_term); + const is_match = + category_match && + language_match && + (search_term === "" || search_match); + entry_row.visible = is_match; + if (is_match) visible_categories.add(category_check[category_index]); + }, + ); category_map.forEach((category_widget, category_name) => { const label = objects[`label_${category_name}`]; if (label) label.visible = - current_category === "All Categories" && - current_language === "All Languages" && + current_category === 0 && + current_language === 0 && search_term === ""; category_widget.visible = visible_categories.has(category_name); }); @@ -100,12 +128,12 @@ export default function Library({ application }) { search_entry.connect("search-changed", updateList); dropdown_category.connect("notify::selected", () => { - current_category = dropdown_category.get_selected_item().get_string(); + current_category = dropdown_category.get_selected(); updateList(); }); dropdown_language.connect("notify::selected", () => { - current_language = dropdown_language.get_selected_item().get_string(); + current_language = dropdown_language.get_selected(); updateList(); }); From 84afab8e7c3e335e58357b301537a8a9c1ca2082 Mon Sep 17 00:00:00 2001 From: Bharat Date: Thu, 25 Jul 2024 14:27:54 +0530 Subject: [PATCH 4/7] minor addition: Add No results label on no match --- src/Library/Library.blp | 8 ++++++++ src/Library/Library.js | 9 +++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Library/Library.blp b/src/Library/Library.blp index 33e4e1942..b19dfae93 100644 --- a/src/Library/Library.blp +++ b/src/Library/Library.blp @@ -227,6 +227,14 @@ Adw.Window window { halign: center; margin-bottom: 24; margin-top: 12; + orientation: vertical; + + Label results_empty { + visible: false; + margin-top: 46; + margin-bottom: 70; + label: _("No results"); + } Label { label: _("All examples are dedicated to the public domain\nand can be used freely under the terms of CC0 1.0"); diff --git a/src/Library/Library.js b/src/Library/Library.js index 55dc3fc26..c59469a11 100644 --- a/src/Library/Library.js +++ b/src/Library/Library.js @@ -27,6 +27,7 @@ export default function Library({ application }) { search_entry, dropdown_category, dropdown_language, + results_empty, } = objects; window.application = application; picture_illustration.set_resource(illustration); @@ -97,7 +98,7 @@ export default function Library({ application }) { function updateList() { const search_term = search_entry.get_text().toLowerCase(); const visible_categories = new Set(); - + let results_found = false; widgets_map.forEach( ({ entry_row, category_index, languages_index }, demo_name) => { const category_match = @@ -110,7 +111,10 @@ export default function Library({ application }) { language_match && (search_term === "" || search_match); entry_row.visible = is_match; - if (is_match) visible_categories.add(category_check[category_index]); + if (is_match) { + results_found = true; + visible_categories.add(category_check[category_index]); + } }, ); @@ -123,6 +127,7 @@ export default function Library({ application }) { search_term === ""; category_widget.visible = visible_categories.has(category_name); }); + results_empty.set_visible(!results_found); } search_entry.connect("search-changed", updateList); From 9bd062b96eae6cc544b46dbfac34e65558bdc3f3 Mon Sep 17 00:00:00 2001 From: Bharat Date: Sun, 28 Jul 2024 12:30:46 +0530 Subject: [PATCH 5/7] improvements: Use translated strings for filters Static maps for all category and Language filter strings style change for "No results" label --- src/Library/Library.blp | 4 ++++ src/Library/Library.js | 25 +++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/Library/Library.blp b/src/Library/Library.blp index b19dfae93..55fe55b2a 100644 --- a/src/Library/Library.blp +++ b/src/Library/Library.blp @@ -234,6 +234,10 @@ Adw.Window window { margin-top: 46; margin-bottom: 70; label: _("No results"); + + styles [ + "title-4" + ] } Label { diff --git a/src/Library/Library.js b/src/Library/Library.js index c59469a11..0ed8a32e2 100644 --- a/src/Library/Library.js +++ b/src/Library/Library.js @@ -16,6 +16,7 @@ import { createSessionFromDemo } from "../sessions.js"; import EntryRow from "./EntryRow.js"; import illustration from "./library.svg"; +import { gettext as _ } from "gettext"; import { build } from "../../troll/src/builder.js"; @@ -54,17 +55,37 @@ export default function Library({ application }) { const language_check = ["All Languages"]; const category_check = ["All Categories"]; + const language_labels = { + javascript: _("JavaScript"), + python: _("Python"), + rust: _("Rust"), + vala: _("Vala"), + typescript: _("TypeScript"), + }; + + const category_labels = { + user_interface: _("User Interface"), + platform: _("Platform APIs"), + controls: _("Controls"), + feedback: _("Feedback"), + layout: _("Layout"), + network: _("Network"), + navigation: _("Navigation"), + tools: _("Tools"), + uncategorized: _("Uncategorized"), + }; + demos.forEach((demo) => { demo.languages.forEach((lang) => { if (!language_check.includes(lang)) { language_check.push(lang); - language_model.append(lang); + language_model.append(language_labels[lang]); } }); if (!category_check.includes(demo.category)) { category_check.push(demo.category); - category_model.append(demo.category); + category_model.append(category_labels[demo.category]); } const entry_row = new EntryRow({ demo: demo }); From 78fe765a3ebe0984bf50a535c0ff8566a59294d8 Mon Sep 17 00:00:00 2001 From: Bharat Date: Thu, 1 Aug 2024 13:22:21 +0530 Subject: [PATCH 6/7] minor fix: localize All Category & Language string --- src/Library/Library.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Library/Library.js b/src/Library/Library.js index 0ed8a32e2..2a82d670d 100644 --- a/src/Library/Library.js +++ b/src/Library/Library.js @@ -50,10 +50,10 @@ export default function Library({ application }) { const category_map = new Map(); const language_model = new Gtk.StringList(); const category_model = new Gtk.StringList(); - language_model.append("All Languages"); - category_model.append("All Categories"); - const language_check = ["All Languages"]; - const category_check = ["All Categories"]; + language_model.append(_("All Languages")); + category_model.append(_("All Categories")); + const language_check = [_("All Languages")]; + const category_check = [_("All Categories")]; const language_labels = { javascript: _("JavaScript"), From 7d0aa6c1d43cc99f553a4b25df05124b0ab3b1d1 Mon Sep 17 00:00:00 2001 From: Sonny Piers Date: Mon, 23 Sep 2024 14:23:54 +0200 Subject: [PATCH 7/7] fixup --- build-aux/wip/run.js | 42 ++++++++++++++++--------------- src/Library/Library.blp | 52 ++++++++++++++++++++++---------------- src/Library/Library.js | 56 +++++++++++++++++++---------------------- 3 files changed, 79 insertions(+), 71 deletions(-) diff --git a/build-aux/wip/run.js b/build-aux/wip/run.js index 26bbf440f..da4d6a5e6 100755 --- a/build-aux/wip/run.js +++ b/build-aux/wip/run.js @@ -66,28 +66,30 @@ if (!exists(`${path}/.flatpak/repo`)) { } if (!exists(`${path}/.flatpak/flatpak-builder`)) { - const module_name = app_module.name; - - const manifest_relative_path = - Gio.File.new_for_path(path).get_relative_path(manifest_file); - - const prefix = [ - "flatpak-builder", - "--ccache", - "--force-clean", - "--disable-updates", - ]; - - const suffix = [ - `--state-dir=${path}/.flatpak/flatpak-builder`, - `--stop-at=${module_name}`, - `${path}/.flatpak/repo`, - manifest_relative_path, - ]; + await downloadSources(); + await buildModules(); +} - // downloads sources (de-initializes) +const prefix = [ + "flatpak-builder", + "--ccache", + "--force-clean", + "--disable-updates", +]; +const suffix = [ + `--state-dir=${path}/.flatpak/flatpak-builder`, + `--stop-at=${app_module.name}`, + `${path}/.flatpak/repo`, + Gio.File.new_for_path(path).get_relative_path(manifest_file), +]; + +// de-initializes +async function downloadSources() { await run([...prefix, "--download-only", ...suffix]); - // builds modules (de-initializes) +} + +// de-initializes +async function buildModules() { await run([ ...prefix, "--disable-download", diff --git a/src/Library/Library.blp b/src/Library/Library.blp index 55fe55b2a..f4ccfc72d 100644 --- a/src/Library/Library.blp +++ b/src/Library/Library.blp @@ -50,24 +50,24 @@ Adw.Window window { ] } - SearchEntry search_entry { - search-delay: 100; - placeholder-text: _("Search demos"); - activates-default: true; - width-request: 400; - margin-top: 32; - } - } + Box { + spacing: 6; + + SearchEntry search_entry { + search-delay: 100; + placeholder-text: _("Search demos"); + activates-default: true; + hexpand: true; + margin-top: 32; + } - Box { - DropDown dropdown_language { - halign: end; - margin-end: 12; - hexpand: true; - } + DropDown dropdown_language { + valign: end; + } - DropDown dropdown_category { - halign: end; + DropDown dropdown_category { + valign: end; + } } } @@ -229,15 +229,25 @@ Adw.Window window { margin-top: 12; orientation: vertical; - Label results_empty { + Box results_empty { + orientation: vertical; visible: false; margin-top: 46; margin-bottom: 70; - label: _("No results"); + spacing: 6; - styles [ - "title-4" - ] + Label { + label: _("No results"); + + styles [ + "title-4" + ] + } + + Button button_reset { + label: _("Reset filters"); + halign: center; + } } Label { diff --git a/src/Library/Library.js b/src/Library/Library.js index 2a82d670d..6f2f7c7ee 100644 --- a/src/Library/Library.js +++ b/src/Library/Library.js @@ -5,7 +5,6 @@ import { decode, demos_dir, getLanguage, - makeDropdownFlat, settings as global_settings, quitOnLastWindowClose, } from "../util.js"; @@ -29,32 +28,27 @@ export default function Library({ application }) { dropdown_category, dropdown_language, results_empty, + button_reset, } = objects; window.application = application; picture_illustration.set_resource(illustration); - makeDropdownFlat(dropdown_category); - makeDropdownFlat(dropdown_language); if (__DEV__) { window.add_css_class("devel"); } let last_triggered; - let current_category = 0; - let current_language = 0; window.connect("close-request", quitOnLastWindowClose); const demos = getDemos(); const widgets_map = new Map(); const category_map = new Map(); - const language_model = new Gtk.StringList(); - const category_model = new Gtk.StringList(); - language_model.append(_("All Languages")); - category_model.append(_("All Categories")); - const language_check = [_("All Languages")]; - const category_check = [_("All Categories")]; + const language_model = new Gtk.StringList(); + language_model.append(_("Any Language")); + dropdown_language.set_model(language_model); + const language_check = [_("Any Language")]; const language_labels = { javascript: _("JavaScript"), python: _("Python"), @@ -62,30 +56,34 @@ export default function Library({ application }) { vala: _("Vala"), typescript: _("TypeScript"), }; + Object.values(language_labels).forEach((str) => language_model.push(str)); + const category_model = new Gtk.StringList(); + category_model.append(_("Any Category")); + dropdown_category.set_model(category_model); + const category_check = [_("Any Category")]; const category_labels = { - user_interface: _("User Interface"), - platform: _("Platform APIs"), + uncategorized: _("Uncategorized"), + tools: _("Tools"), + network: _("Network"), controls: _("Controls"), - feedback: _("Feedback"), layout: _("Layout"), - network: _("Network"), + feedback: _("Feedback"), navigation: _("Navigation"), - tools: _("Tools"), - uncategorized: _("Uncategorized"), + user_interface: _("User Interface"), + platform: _("Platform APIs"), }; + Object.values(category_labels).forEach((str) => category_model.push(str)); demos.forEach((demo) => { demo.languages.forEach((lang) => { if (!language_check.includes(lang)) { language_check.push(lang); - language_model.append(language_labels[lang]); } }); if (!category_check.includes(demo.category)) { category_check.push(demo.category); - category_model.append(category_labels[demo.category]); } const entry_row = new EntryRow({ demo: demo }); @@ -113,10 +111,10 @@ export default function Library({ application }) { }); }); - dropdown_language.set_model(language_model); - dropdown_category.set_model(category_model); - function updateList() { + const current_category = dropdown_category.get_selected(); + const current_language = dropdown_language.get_selected(); + const search_term = search_entry.get_text().toLowerCase(); const visible_categories = new Set(); let results_found = false; @@ -152,15 +150,13 @@ export default function Library({ application }) { } search_entry.connect("search-changed", updateList); + dropdown_category.connect("notify::selected", updateList); + dropdown_language.connect("notify::selected", updateList); - dropdown_category.connect("notify::selected", () => { - current_category = dropdown_category.get_selected(); - updateList(); - }); - - dropdown_language.connect("notify::selected", () => { - current_language = dropdown_language.get_selected(); - updateList(); + button_reset.connect("clicked", () => { + search_entry.text = ""; + dropdown_category.selected = 0; + dropdown_language.selected = 0; }); const action_library = new Gio.SimpleAction({