diff options
| author | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-03-04 23:26:05 +1100 |
|---|---|---|
| committer | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-03-05 11:41:20 +1100 |
| commit | 35364193e3d24d47a8c2d970f70f696f2247e3bb (patch) | |
| tree | 03ad351e37e040eabe666d6f4921971545a1fb17 | |
| parent | popdowns: buttons change colour when disabled (diff) | |
| download | caelestia-shell-35364193e3d24d47a8c2d970f70f696f2247e3bb.tar.gz caelestia-shell-35364193e3d24d47a8c2d970f70f696f2247e3bb.tar.bz2 caelestia-shell-35364193e3d24d47a8c2d970f70f696f2247e3bb.zip | |
launcher: math mode
| -rw-r--r-- | scss/launcher.scss | 14 | ||||
| -rw-r--r-- | src/modules/launcher/index.tsx | 7 | ||||
| -rw-r--r-- | src/modules/launcher/modes.tsx | 80 | ||||
| -rw-r--r-- | src/services/math.ts | 2 |
4 files changed, 95 insertions, 8 deletions
diff --git a/scss/launcher.scss b/scss/launcher.scss index 983f362..87854f4 100644 --- a/scss/launcher.scss +++ b/scss/launcher.scss @@ -9,6 +9,10 @@ color: $colour; } + .separator { + background-color: color.change($colour, $alpha: 0.7); + } + .search-bar { .mode { @include lib.border($colour, $width: 2); @@ -126,6 +130,16 @@ } } + .math { + .preview > * { + margin-bottom: lib.s(10); + } + + .result { + @include lib.spacing(10); + } + } + .swatches { @include lib.spacing(3); } diff --git a/src/modules/launcher/index.tsx b/src/modules/launcher/index.tsx index 2821050..8287187 100644 --- a/src/modules/launcher/index.tsx +++ b/src/modules/launcher/index.tsx @@ -121,9 +121,10 @@ export default class Launcher extends PopupWindow { this.hook(entry, "changed", () => (isAction(entry.get_text()) ? actions : content[mode.get()]).updateContent(entry.get_text()) ); - this.hook(entry, "activate", () => - (isAction(entry.get_text()) ? actions : content[mode.get()]).handleActivate(entry.get_text()) - ); + this.hook(entry, "activate", () => { + (isAction(entry.get_text()) ? actions : content[mode.get()]).handleActivate(entry.get_text()); + entry.set_text(""); // Clear search on activate + }); // Clear search on hide if not in math mode or creating a todo this.connect("hide", () => mode.get() !== "math" && !entry.text.startsWith(">todo") && entry.set_text("")); diff --git a/src/modules/launcher/modes.tsx b/src/modules/launcher/modes.tsx index 4d54ad2..3f6e03e 100644 --- a/src/modules/launcher/modes.tsx +++ b/src/modules/launcher/modes.tsx @@ -1,8 +1,9 @@ import { Apps as AppsService } from "@/services/apps"; +import MathService, { type HistoryItem } from "@/services/math"; import { getAppCategoryIcon } from "@/utils/icons"; import { launch } from "@/utils/system"; import { type FlowBox, setupCustomTooltip } from "@/utils/widgets"; -import { execAsync, Gio, register } from "astal"; +import { bind, execAsync, Gio, register, Variable } from "astal"; import { Astal, Gtk, Widget } from "astal/gtk3"; import { launcher as config } from "config"; import type AstalApps from "gi://AstalApps"; @@ -71,6 +72,28 @@ const FileResult = ({ path }: { path: string }) => ( </Gtk.FlowBoxChild> ); +const MathResult = ({ icon, equation, result }: HistoryItem) => ( + <Gtk.FlowBoxChild visible canFocus={false}> + <button + className="result" + cursor="pointer" + onClicked={() => { + execAsync(["wl-copy", "--", result]).catch(console.error); + close(); + }} + setup={self => setupCustomTooltip(self, `${equation} -> ${result}`)} + > + <box> + <label className="icon" label={icon} /> + <box vertical className="has-sublabel"> + <label truncate xalign={0} label={equation} /> + <label truncate xalign={0} label={result} className="sublabel" /> + </box> + </box> + </button> + </Gtk.FlowBoxChild> +); + @register() class Apps extends Widget.Box implements LauncherContent { #content: FlowBox; @@ -133,16 +156,65 @@ class Files extends Widget.Box implements LauncherContent { @register() class Math extends Widget.Box implements LauncherContent { + #showResult: Variable<boolean>; + #result: Variable<HistoryItem>; + #content: FlowBox; + constructor() { - super({ name: "math", className: "math" }); + super({ name: "math", className: "math", vertical: true }); + + this.#showResult = Variable(false); + this.#result = Variable({ equation: "", result: "", icon: "" }); + this.#content = (<ContentBox />) as FlowBox; + + this.add( + <revealer + transitionType={Gtk.RevealerTransitionType.SLIDE_DOWN} + transitionDuration={150} + revealChild={bind(this.#showResult)} + > + <box vertical className="preview"> + <box className="result"> + <label className="icon" label={bind(this.#result).as(r => r.icon)} /> + <box vertical> + <label xalign={0} label="Result" /> + <label + truncate + xalign={0} + className="sublabel" + label={bind(this.#result).as(r => r.result)} + /> + </box> + </box> + <box className="separator" /> + </box> + </revealer> + ); + this.add( + <scrollable expand hscroll={Gtk.PolicyType.NEVER}> + {this.#content} + </scrollable> + ); } updateContent(search: string): void { - throw new Error("Method not implemented."); + this.#showResult.set(search.length > 0); + this.#result.set(MathService.get_default().evaluate(search)); + + this.#content.foreach(c => c.destroy()); + for (const item of limitLength(MathService.get_default().history, config.math)) + this.#content.add(<MathResult {...item} />); } handleActivate(search: string): void { - throw new Error("Method not implemented."); + if (!search) return; + MathService.get_default().commit(); + const res = this.#result.get(); + // Copy and close if not assignment, help or error + if (!["equal", "help", "error"].includes(res.icon)) { + execAsync(["wl-copy", "--", res.result]).catch(console.error); + close(); + } } } diff --git a/src/services/math.ts b/src/services/math.ts index f5807ef..0cddf1b 100644 --- a/src/services/math.ts +++ b/src/services/math.ts @@ -103,7 +103,7 @@ export default class Math extends GObject.Object { } else if (equation.includes("=")) { const [left, right] = equation.split("="); try { - this.#variables[left.trim()] = simplify(right).toString(); + this.#variables[left.trim()] = simplify(right, this.#variables).toString(); } catch { this.#variables[left.trim()] = right.trim(); } |