Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion po/POTFILES
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,6 @@ src/Extensions/Extensions.js
src/Manuals/DocumentationViewer.blp
src/Manuals/Shortcuts.blp
src/Manuals/Shortcuts.js
src/Manuals/DocumentationViewer.js
src/Manuals/DocumentationViewer.js
src/Library/EntryRow.blp
src/Library/EntryRow.js
49 changes: 49 additions & 0 deletions src/Library/EntryRow.blp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using Gtk 4.0;
using Adw 1;

template $EntryRow : Adw.PreferencesRow {
accessibility {
labelled-by: title_label;
described-by: description_label;
}
title: bind title_label.label;

Box contents {
orientation: horizontal;

Box labels_box {
margin-top: 6;
margin-start: 12;
margin-bottom: 6;
spacing: 3;
orientation: vertical;

Label title_label {
xalign: 0;
wrap: true;
wrap-mode: word_char;
}
Label description_label {
styles ["dim-label", "caption"]
xalign: 0;
wrap: true;
wrap-mode: word_char;
natural-wrap-mode: none;
}

Box languages_box {
orientation: horizontal;
spacing: 3;
margin-top: 3;
}
}

Image {
icon-name: "go-next-symbolic";
margin-end: 12;
margin-start: 6;
hexpand: true;
halign: end;
}
}
}
82 changes: 82 additions & 0 deletions src/Library/EntryRow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import Adw from "gi://Adw";
import Gtk from "gi://Gtk";
import Gio from "gi://Gio";
import GObject from "gi://GObject";

import { demoSupportsLanguage, getLanguage } from "../util.js";
import Template from "./EntryRow.blp" with { type: "uri" };

class EntryRow extends Adw.PreferencesRow {
constructor({ demo, ...params } = {}) {
super(params);

this._title_label.label = demo.name;
this._description_label.label = demo.description;

this.#createLanguageTags(demo);

const action_group = new Gio.SimpleActionGroup();
const activate_action = new Gio.SimpleAction({
name: "activate",
parameter_type: null,
});

activate_action.connect("activate", () => {
this.emit("activated", null);
});
action_group.add_action(activate_action);

this.insert_action_group("demo-row", action_group);
this.action_name = "demo-row.activate";
}

#createLanguageTags(demo) {
const language = getLanguage("javascript");
const language_tag = this.#createLanguageTag(language);
this._languages_box.append(language_tag);

["vala", "rust"].forEach((id) => {
const language = getLanguage(id);
if (!demoSupportsLanguage(demo, language.id)) return;
const language_tag = this.#createLanguageTag(language);
this._languages_box.append(language_tag);
});
}

#createLanguageTag(language) {
const button = new Gtk.Button({
label: language.name,
valign: Gtk.Align.CENTER,
css_classes: ["pill", "small"],
});

button.connect("clicked", () => {
this.emit("activated", language.id);
});

return button;
}
}

export default GObject.registerClass(
{
GTypeName: "EntryRow",
Template,
Properties: {
demo: GObject.ParamSpec.jsobject(
"demo",
"",
"",
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
null,
),
},
Signals: {
activated: {
param_types: [GObject.TYPE_STRING],
},
},
InternalChildren: ["title_label", "description_label", "languages_box"],
},
EntryRow,
);
43 changes: 28 additions & 15 deletions src/Library/Library.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import Gio from "gi://Gio";
import Adw from "gi://Adw";
import Gtk from "gi://Gtk";

import { demos_dir, getDemo } from "../util.js";
import { demos_dir, getDemo, settings as global_settings } from "../util.js";
import Window from "../window.js";

import resource from "./Library.blp";
import { createSessionFromDemo } from "../sessions.js";
import EntryRow from "./EntryRow.js";

import illustration from "./library.svg";

Expand All @@ -21,21 +21,17 @@ export default function Library({ application }) {

const demos = getDemos();
demos.forEach((demo) => {
const widget = new Adw.ActionRow({
title: demo.name,
subtitle: demo.description,
activatable: true,
});
const widget = new EntryRow({ demo: demo });
if (demo.name === "Welcome") last_selected = widget;
widget.add_suffix(
new Gtk.Image({
icon_name: "go-next-symbolic",
}),
);
widget.connect("activated", () => {

widget.connect("activated", (_self, language_name) => {
last_selected = widget;

openDemo({ application, demo_name: demo.name }).catch(console.error);
openDemo({
application,
demo_name: demo.name,
language_name,
}).catch(console.error);
});

builder.get_object(`library_${demo.category}`).add(widget);
Expand Down Expand Up @@ -77,10 +73,27 @@ function getDemos() {
return demos;
}

async function openDemo({ application, demo_name }) {
async function openDemo({ application, demo_name, language_name }) {
const demo = getDemo(demo_name);
const session = await createSessionFromDemo(demo);

if (language_name) {
switch (language_name.toLowerCase()) {
case "javascript":
session.settings.set_int("code-language", 0);
global_settings.set_int("recent-code-language", 0);
break;
case "vala":
session.settings.set_int("code-language", 1);
global_settings.set_int("recent-code-language", 1);
break;
case "rust":
session.settings.set_int("code-language", 2);
global_settings.set_int("recent-code-language", 2);
break;
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well done 👍

const is_js = session.settings.get_int("code-language") === 0;

const { load } = Window({ application, session });
Expand Down
12 changes: 12 additions & 0 deletions src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@
border: 1px solid @borders;
}

/*
* From Builder's stylesheet:
* https://gitlab.gnome.org/GNOME/gnome-builder/-/blob/45d4ec9b6f1aa2236c9bb7dfb846b35f9b959618/src/libide/gui/style.css#L33
* Used to style the language tags for the demo entries in the Library
*/
button.pill.small {
font-size: 0.83333em;
border-radius: 99px;
margin: 0;
padding: 1px 12px;
}

#panel_code,
#panel_style,
#panel_ui {
Expand Down
9 changes: 9 additions & 0 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export const languages = [
extensions: [".js", ".mjs"],
types: ["text/javascript", "application/javascript"],
document: null,
default_file: "main.js",
},
{
id: "css",
Expand All @@ -78,6 +79,7 @@ export const languages = [
types: ["text/x-vala"],
document: null,
placeholder: "// Sorry, this demo is not available in Vala yet.",
default_file: "main.vala",
},
{
id: "rust",
Expand All @@ -87,6 +89,7 @@ export const languages = [
types: ["text/x-rust"],
document: null,
placeholder: "// Sorry, this demo is not available in Rust yet.",
default_file: "code.rs",
},
];

Expand Down Expand Up @@ -186,6 +189,12 @@ export function getDemo(name) {
return demo;
}

export function demoSupportsLanguage(demo, id) {
const language = getLanguage(id);
const demo_dir = demos_dir.get_child(demo.name);
return demo_dir.get_child(language.default_file).query_exists(null);
}
Comment on lines +192 to +196
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For each demo (> 100) this checks twice if a file exist
that's > 200 blocking fs operations

It's not ideal. The Library should already open faster.
I've wanted to optimize it anyway so I can take care of it later 👍

What I have in mind is to build a Library index at build time so there is no need to query file system to build the Library window.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was also worried about all the I/O, and although it did not seem to slow it down that much, with a hundred more demos it will likely be a problem.

I thought about adding the languages available in each .json file but it is something that can be easily forgotten when adding/porting a demo. Doing it in build time is definitely better.


export function getNowForFilename() {
return new GLib.DateTime().format("%Y-%m-%d %H-%M-%S");
}