diff --git a/.github/workflows/CI.yaml b/.github/workflows/CI.yaml
index f40fd98db..ea35e732e 100644
--- a/.github/workflows/CI.yaml
+++ b/.github/workflows/CI.yaml
@@ -5,6 +5,7 @@ name: CI
on:
pull_request:
branches: [main]
+ workflow_dispatch:
jobs:
CI:
diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml
index 72a148ca6..7468c4acd 100644
--- a/.github/workflows/deploy.yaml
+++ b/.github/workflows/deploy.yaml
@@ -1,7 +1,10 @@
+name: Deploy
+
on:
push:
branches: [main]
-name: Deploy
+ workflow_dispatch:
+
jobs:
flatpak:
name: "Flatpak"
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e5c428cf6..7883f3db7 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -32,7 +32,7 @@ We provide a couple of tools to make the development process pleasant.
# sudo dnf install flatpak flatpak-builder nodejs make gcc gcc-c++
cd Workbench
-make setup
+make
```
Before submitting a PR, we recommend running tests locally with
diff --git a/Makefile b/Makefile
index 87224e76b..90fa3fde0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,19 +1,27 @@
SHELL:=/bin/bash -O globstar
.PHONY: setup build lint unit test ci sandbox flatpak
-.DEFAULT_GOAL := test
+.DEFAULT_GOAL := setup
setup:
flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
flatpak install --or-update --user --noninteractive flathub org.gnome.Sdk//46 org.flatpak.Builder org.freedesktop.Sdk.Extension.rust-stable//23.08 org.freedesktop.Sdk.Extension.vala//23.08 org.freedesktop.Sdk.Extension.llvm16//23.08 org.freedesktop.Sdk.Extension.node18//23.08 org.freedesktop.Sdk.Extension.typescript//23.08
-# flatpak remote-add --user --if-not-exists flathub-beta https://flathub.org/beta-repo/flathub-beta.flatpakrepo
+ flatpak remote-add --user --if-not-exists flathub-beta https://flathub.org/beta-repo/flathub-beta.flatpakrepo
+ flatpak install --or-update --user --noninteractive flathub-beta org.freedesktop.Sdk.Extension.rust-stable//24.08beta org.freedesktop.Sdk.Extension.vala//24.08beta org.freedesktop.Sdk.Extension.llvm18//24.08beta
+# org.freedesktop.Sdk.Extension.node18//24.08beta org.freedesktop.Sdk.Extension.typescript//24.08beta
flatpak remote-add --user --if-not-exists gnome-nightly https://nightly.gnome.org/gnome-nightly.flatpakrepo
flatpak install --or-update --user --noninteractive gnome-nightly org.gnome.Sdk//master
- npm install
- make build
+ git submodule update --init
+ npm install --no-fund
+ @echo " ✅ You can use make stable or make devel to build Workbench"
-build:
+stable:
+ flatpak-builder --delete-build-dirs --disable-updates --build-only --ccache --force-clean flatpak build-aux/re.sonny.Workbench.json
+
+devel:
flatpak-builder --delete-build-dirs --disable-updates --build-only --ccache --force-clean flatpak build-aux/re.sonny.Workbench.Devel.json
+build: devel
+
cli:
./troll/gjspack/bin/gjspack src/cli/main.js --appid=re.sonny.Workbench.cli --prefix=/re/sonny/Workbench --resource-root=src/ --no-executable flatpak/files/share/re.sonny.Workbench.cli/
cp src/cli/bin.js flatpak/files/bin/workbench-cli
diff --git a/README.md b/README.md
index 0c89cb47a..50c496e79 100644
--- a/README.md
+++ b/README.md
@@ -30,14 +30,14 @@ Among other things, Workbench comes with
| | Formatter | Linter | Library demos[1] |
| ---------- | --------- | ------ | ---------------- |
-| JavaScript | ✅ | ✅ | 100 |
+| JavaScript | ✅ | ✅ | 99 |
| Python | ✅ | ✅ | 92 |
-| Vala | ✅ | ✅ | 67 |
+| Vala | ✅ | ✅ | 92 |
| Rust | ✅ | ✅ | 45 |
| Blueprint | ✅ | ✅ | |
| CSS | ✅ | ✅ | |
-[1] As of 2024-04-28
+[1] As of 2024-06-16
## Tips and tricks
diff --git a/demos b/demos
index bb5df9b69..0db011334 160000
--- a/demos
+++ b/demos
@@ -1 +1 @@
-Subproject commit bb5df9b69152334e67dc79a31db4e7f0ba884141
+Subproject commit 0db011334ad15bfc60ef4aaca6c90a1dec7d705c
diff --git a/src/Library/EntryRow.blp b/src/Library/EntryRow.blp
index 84e37b83e..35c9488ce 100644
--- a/src/Library/EntryRow.blp
+++ b/src/Library/EntryRow.blp
@@ -1,20 +1,20 @@
using Gtk 4.0;
using Adw 1;
-template $EntryRow: Adw.PreferencesRow {
+template $EntryRow: Adw.ActionRow {
+ activatable: true;
+
accessibility {
labelled-by: title_label;
described-by: description_label;
}
- title: bind title_label.label;
-
+ [prefix]
Box contents {
orientation: horizontal;
Box labels_box {
margin-top: 6;
- margin-start: 12;
margin-bottom: 6;
spacing: 3;
orientation: vertical;
@@ -43,13 +43,13 @@ template $EntryRow: Adw.PreferencesRow {
margin-top: 3;
}
}
+ }
- Image {
- icon-name: "go-next-symbolic";
- margin-end: 12;
- margin-start: 6;
- hexpand: true;
- halign: end;
- }
+ [suffix]
+ Image {
+ icon-name: "go-next-symbolic";
+ margin-start: 6;
+ hexpand: true;
+ halign: end;
}
}
diff --git a/src/Library/EntryRow.js b/src/Library/EntryRow.js
index 9eb9d9827..e40e6963a 100644
--- a/src/Library/EntryRow.js
+++ b/src/Library/EntryRow.js
@@ -6,7 +6,7 @@ import GObject from "gi://GObject";
import { getLanguage } from "../util.js";
import Template from "./EntryRow.blp" with { type: "uri" };
-class EntryRow extends Adw.PreferencesRow {
+class EntryRow extends Adw.ActionRow {
constructor({ demo, ...params } = {}) {
super(params);
@@ -22,7 +22,7 @@ class EntryRow extends Adw.PreferencesRow {
});
activate_action.connect("activate", () => {
- this.emit("activated", null);
+ this.emit("triggered", null);
});
action_group.add_action(activate_action);
@@ -47,7 +47,7 @@ class EntryRow extends Adw.PreferencesRow {
});
button.connect("clicked", () => {
- this.emit("activated", language);
+ this.emit("triggered", language);
});
return button;
@@ -68,7 +68,7 @@ export default GObject.registerClass(
),
},
Signals: {
- activated: {
+ triggered: {
param_types: [GObject.TYPE_JSOBJECT],
},
},
diff --git a/src/Library/Library.blp b/src/Library/Library.blp
index 240898c9a..a218402bf 100644
--- a/src/Library/Library.blp
+++ b/src/Library/Library.blp
@@ -1,75 +1,97 @@
using Gtk 4.0;
using Adw 1;
-Adw.PreferencesWindow window {
+Adw.Window window {
hide-on-close: true;
modal: false;
title: _("Workbench — Library");
default-height: 700;
default-width: 700;
- Adw.PreferencesPage {
- Adw.PreferencesGroup {
- Picture picture_illustration {
- can-shrink: false;
- margin-bottom: 32;
- }
-
- Label {
- label: _("Learn, Test, Remix");
+ Adw.ToolbarView toolbar_view {
+ [top]
+ Adw.HeaderBar header_bar {
+ title-widget: Adw.WindowTitle {
+ title: _("Workbench — Library");
+ };
+ }
- styles [
- "title-1"
- ]
+ content: Adw.PreferencesPage {
+ Adw.PreferencesGroup {
+ Box {
+ halign: center;
+ vexpand: false;
+
+ Picture picture_illustration {
+ can-shrink: false;
+ margin-bottom: 32;
+ }
+ }
+
+ Label {
+ label: _("Learn, Test, Remix");
+
+ styles [
+ "title-1"
+ ]
+ }
+
+ SearchEntry search_entry {
+ search-delay: 100;
+ placeholder-text: _("Search demos");
+ activates-default: true;
+ width-request: 400;
+ margin-top: 32;
+ }
}
- }
- Adw.PreferencesGroup library_uncategorized {}
+ Adw.PreferencesGroup library_uncategorized {}
- Adw.PreferencesGroup library_tools {
- title: _("Tools");
- }
+ Adw.PreferencesGroup library_tools {
+ title: _("Tools");
+ }
- Adw.PreferencesGroup library_network {
- title: _("Network");
- }
+ Adw.PreferencesGroup library_network {
+ title: _("Network");
+ }
- Adw.PreferencesGroup library_controls {
- title: _("Controls");
- }
+ Adw.PreferencesGroup library_controls {
+ title: _("Controls");
+ }
- Adw.PreferencesGroup library_layout {
- title: _("Layout");
- }
+ Adw.PreferencesGroup library_layout {
+ title: _("Layout");
+ }
- Adw.PreferencesGroup library_feedback {
- title: _("Feedback");
- }
+ Adw.PreferencesGroup library_feedback {
+ title: _("Feedback");
+ }
- Adw.PreferencesGroup library_navigation {
- title: _("Navigation");
- }
+ Adw.PreferencesGroup library_navigation {
+ title: _("Navigation");
+ }
- Adw.PreferencesGroup library_user_interface {
- title: _("User Interface");
- }
+ Adw.PreferencesGroup library_user_interface {
+ title: _("User Interface");
+ }
- Adw.PreferencesGroup library_platform {
- title: _("Platform APIs");
- }
+ Adw.PreferencesGroup library_platform {
+ title: _("Platform APIs");
+ }
- Adw.PreferencesGroup {
- vexpand: true;
- valign: end;
+ Adw.PreferencesGroup {
+ vexpand: true;
+ valign: end;
- Label {
- label: _('All examples are dedicated to the public domain\nand can be used freely under the terms of CC0 1.0');
- use-markup: true;
+ Label {
+ label: _("All examples are dedicated to the public domain\nand can be used freely under the terms of CC0 1.0");
+ use-markup: true;
- styles [
- "caption"
- ]
+ styles [
+ "caption"
+ ]
+ }
}
- }
+ };
}
}
diff --git a/src/Library/Library.js b/src/Library/Library.js
index 7267f36e4..ed0973d03 100644
--- a/src/Library/Library.js
+++ b/src/Library/Library.js
@@ -19,7 +19,7 @@ import { build } from "../../troll/src/builder.js";
export default function Library({ application }) {
const objects = build(resource);
- const { window, picture_illustration } = objects;
+ const { window, picture_illustration, search_entry } = objects;
window.application = application;
picture_illustration.set_resource(illustration);
@@ -27,17 +27,19 @@ export default function Library({ application }) {
window.add_css_class("devel");
}
- let last_selected;
+ let last_triggered;
window.connect("close-request", quitOnLastWindowClose);
const demos = getDemos();
+ const widgets_map = new Map();
+ const category_map = new Map();
demos.forEach((demo) => {
- const widget = new EntryRow({ demo: demo });
- if (demo.name === "Welcome") last_selected = widget;
+ const entry_row = new EntryRow({ demo: demo });
+ if (demo.name === "Welcome") last_triggered = entry_row;
- widget.connect("activated", (_self, language) => {
- last_selected = widget;
+ entry_row.connect("triggered", (_self, language) => {
+ last_triggered = entry_row;
openDemo({
application,
@@ -45,17 +47,34 @@ export default function Library({ application }) {
language,
}).catch(console.error);
});
-
- objects[`library_${demo.category}`].add(widget);
+ if (!category_map.has(demo.category)) {
+ category_map.set(demo.category, objects[`library_${demo.category}`]);
+ }
+ objects[`library_${demo.category}`].add(entry_row);
+ widgets_map.set(demo.name, { entry_row, category: demo.category });
});
+ search_entry.connect("search-changed", () => {
+ 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);
+ });
+
+ category_map.forEach((category_widget, category_name) => {
+ category_widget.visible = visible_categories.has(category_name);
+ });
+ });
const action_library = new Gio.SimpleAction({
name: "library",
parameter_type: null,
});
action_library.connect("activate", () => {
window.present();
- last_selected?.grab_focus();
+ last_triggered?.grab_focus();
});
application.add_action(action_library);
application.set_accels_for_action("app.library", ["O"]);
@@ -86,9 +105,9 @@ async function openDemo({ application, demo_name, language }) {
session.settings.set_int("code-language", language.index);
global_settings.set_int("recent-code-language", language.index);
- // If the user explictely requested to open the demo
+ // If the user explicitly requested to open the demo
// in a specific language then that's probably what they are interested in
- // therefor override the demo default and force show the code panel
+ // therefore override the demo default and force show the code panel
session.settings.set_boolean("show-code", true);
}