Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

library: Add Language and Category filters #967

Merged
merged 9 commits into from
Sep 23, 2024
42 changes: 22 additions & 20 deletions build-aux/wip/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
46 changes: 40 additions & 6 deletions src/Library/Library.blp
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +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;
}

DropDown dropdown_language {
valign: end;
}

DropDown dropdown_category {
valign: end;
}
}
}

Expand Down Expand Up @@ -215,6 +227,28 @@ Adw.Window window {
halign: center;
margin-bottom: 24;
margin-top: 12;
orientation: vertical;

Box results_empty {
orientation: vertical;
visible: false;
margin-top: 46;
margin-bottom: 70;
spacing: 6;

Label {
label: _("No results");

styles [
"title-4"
]
}

Button button_reset {
label: _("Reset filters");
halign: center;
}
}

Label {
label: _("All examples are dedicated to the public domain\nand <b>can be used freely</b> under the terms of <a href=\"https://creativecommons.org/publicdomain/zero/1.0/\">CC0 1.0</a>");
Expand Down
109 changes: 99 additions & 10 deletions src/Library/Library.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Gio from "gi://Gio";
import Gtk from "gi://Gtk";

import {
decode,
Expand All @@ -14,12 +15,21 @@ 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";

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,
results_empty,
button_reset,
} = objects;
window.application = application;
picture_illustration.set_resource(illustration);

Expand All @@ -34,7 +44,48 @@ export default function Library({ application }) {
const demos = getDemos();
const widgets_map = new Map();
const category_map = new Map();

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"),
rust: _("Rust"),
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 = {
uncategorized: _("Uncategorized"),
tools: _("Tools"),
network: _("Network"),
controls: _("Controls"),
layout: _("Layout"),
feedback: _("Feedback"),
navigation: _("Navigation"),
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);
}
});

if (!category_check.includes(demo.category)) {
category_check.push(demo.category);
}

const entry_row = new EntryRow({ demo: demo });
if (demo.name === "Welcome") last_triggered = entry_row;

Expand All @@ -51,25 +102,63 @@ 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_index: category_check.indexOf(demo.category),
languages_index: demo.languages.map((lang) =>
language_check.indexOf(lang),
),
});
});

search_entry.connect("search-changed", () => {
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();

widgets_map.forEach(({ entry_row, category }, demo_name) => {
const is_match = demo_name.toLowerCase().includes(search_term);
entry_row.visible = is_match;
if (is_match) visible_categories.add(category);
});
let results_found = false;
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) {
results_found = true;
visible_categories.add(category_check[category_index]);
}
},
);

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 === 0 &&
current_language === 0 &&
search_term === "";
category_widget.visible = visible_categories.has(category_name);
});
results_empty.set_visible(!results_found);
}

search_entry.connect("search-changed", updateList);
dropdown_category.connect("notify::selected", updateList);
dropdown_language.connect("notify::selected", updateList);

button_reset.connect("clicked", () => {
search_entry.text = "";
dropdown_category.selected = 0;
dropdown_language.selected = 0;
});

const action_library = new Gio.SimpleAction({
name: "library",
parameter_type: null,
Expand Down
Loading