launcher: better math
This commit is contained in:
parent
a313624734
commit
cb487aefb1
7 changed files with 338 additions and 51 deletions
|
|
@ -3,8 +3,8 @@ import { Astal, Gtk, Widget } from "astal/gtk3";
|
|||
import fuzzysort from "fuzzysort";
|
||||
import type AstalApps from "gi://AstalApps";
|
||||
import AstalHyprland from "gi://AstalHyprland";
|
||||
import Mexp from "math-expression-evaluator";
|
||||
import { Apps } from "../services/apps";
|
||||
import Math, { type HistoryItem } from "../services/math";
|
||||
import { getAppCategoryIcon } from "../utils/icons";
|
||||
import { launch } from "../utils/system";
|
||||
import { PopupWindow, setupCustomTooltip, TransitionType } from "../utils/widgets";
|
||||
|
|
@ -104,7 +104,6 @@ const SearchEntry = ({ entry }: { entry: Widget.Entry }) => (
|
|||
</stack>
|
||||
);
|
||||
|
||||
// TODO: description field
|
||||
const Result = ({
|
||||
icon,
|
||||
materialIcon,
|
||||
|
|
@ -167,6 +166,25 @@ const AppResult = ({ app }: { app: AstalApps.Application }) => (
|
|||
/>
|
||||
);
|
||||
|
||||
const MathResult = ({ math, isHistory, entry }: { math: HistoryItem; isHistory?: boolean; entry: Widget.Entry }) => (
|
||||
<Result
|
||||
materialIcon={math.icon}
|
||||
label={math.equation}
|
||||
sublabel={math.result}
|
||||
onClicked={() => {
|
||||
if (isHistory) {
|
||||
Math.get_default().select(math);
|
||||
entry.set_text(math.equation);
|
||||
entry.grab_focus();
|
||||
entry.set_position(-1);
|
||||
} else {
|
||||
execAsync(`wl-copy -- ${math.result}`).catch(console.error);
|
||||
entry.set_text("");
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
const Results = ({ entry, mode }: { entry: Widget.Entry; mode: Variable<Mode> }) => {
|
||||
const empty = Variable(true);
|
||||
|
||||
|
|
@ -198,10 +216,10 @@ const Results = ({ entry, mode }: { entry: Widget.Entry; mode: Variable<Mode> })
|
|||
description: "Search for files",
|
||||
command: () => mode.set("files"),
|
||||
},
|
||||
calc: {
|
||||
math: {
|
||||
icon: "calculate",
|
||||
name: "Calculator",
|
||||
description: "A calculator...",
|
||||
name: "Math",
|
||||
description: "Do math calculations",
|
||||
command: () => mode.set("math"),
|
||||
},
|
||||
todo: {
|
||||
|
|
@ -214,7 +232,6 @@ const Results = ({ entry, mode }: { entry: Widget.Entry; mode: Variable<Mode> })
|
|||
},
|
||||
};
|
||||
const subcommandList = Object.keys(subcommands);
|
||||
const mexp = new Mexp();
|
||||
|
||||
const appSearch = () => {
|
||||
const apps = Apps.fuzzy_query(entry.text);
|
||||
|
|
@ -224,27 +241,24 @@ const Results = ({ entry, mode }: { entry: Widget.Entry; mode: Variable<Mode> })
|
|||
};
|
||||
|
||||
const calculate = () => {
|
||||
// TODO: allow defs, history
|
||||
let math = null;
|
||||
try {
|
||||
math = mexp.eval(entry.text);
|
||||
} catch (e) {
|
||||
// Ignore
|
||||
if (entry.text) {
|
||||
self.add(<MathResult math={Math.get_default().evaluate(entry.text)} entry={entry} />);
|
||||
self.add(<box className="separator" />);
|
||||
}
|
||||
if (math !== null)
|
||||
self.add(
|
||||
<Result
|
||||
materialIcon="calculate"
|
||||
label={entry.text}
|
||||
sublabel={String(math)}
|
||||
onClicked={() => execAsync(`wl-copy -- ${math}`).catch(console.error)}
|
||||
/>
|
||||
);
|
||||
for (const item of Math.get_default().history)
|
||||
self.add(<MathResult isHistory math={item} entry={entry} />);
|
||||
};
|
||||
|
||||
self.hook(entry, "activate", () => entry.text && self.get_children()[0].activate());
|
||||
self.hook(entry, "changed", () => {
|
||||
self.hook(entry, "activate", () => {
|
||||
if (!entry.text) return;
|
||||
if (mode.get() === "math") {
|
||||
if (entry.text.startsWith("clear")) Math.get_default().clear();
|
||||
else Math.get_default().commit();
|
||||
}
|
||||
self.get_children()[0]?.activate();
|
||||
});
|
||||
self.hook(entry, "changed", () => {
|
||||
if (!entry.text && mode.get() === "apps") return;
|
||||
self.foreach(ch => ch.destroy());
|
||||
|
||||
if (entry.text.startsWith(">")) {
|
||||
|
|
@ -268,7 +282,15 @@ const Results = ({ entry, mode }: { entry: Widget.Entry; mode: Variable<Mode> })
|
|||
);
|
||||
};
|
||||
|
||||
const LauncherContent = ({ mode, entry }: { mode: Variable<Mode>; entry: Widget.Entry }) => (
|
||||
const LauncherContent = ({
|
||||
mode,
|
||||
showResults,
|
||||
entry,
|
||||
}: {
|
||||
mode: Variable<Mode>;
|
||||
showResults: Variable<boolean>;
|
||||
entry: Widget.Entry;
|
||||
}) => (
|
||||
<box
|
||||
vertical
|
||||
className={bind(mode).as(m => `launcher ${m}`)}
|
||||
|
|
@ -280,14 +302,14 @@ const LauncherContent = ({ mode, entry }: { mode: Variable<Mode>; entry: Widget.
|
|||
<label className="icon" label={bind(mode).as(getIconFromMode)} />
|
||||
</box>
|
||||
<revealer
|
||||
revealChild={bind(entry, "textLength").as(t => t === 0)}
|
||||
revealChild={bind(showResults).as(s => !s)}
|
||||
transitionType={Gtk.RevealerTransitionType.SLIDE_DOWN}
|
||||
transitionDuration={150}
|
||||
>
|
||||
<PinnedApps />
|
||||
</revealer>
|
||||
<revealer
|
||||
revealChild={bind(entry, "textLength").as(t => t > 0)}
|
||||
revealChild={bind(showResults)}
|
||||
transitionType={Gtk.RevealerTransitionType.SLIDE_UP}
|
||||
transitionDuration={150}
|
||||
>
|
||||
|
|
@ -303,6 +325,7 @@ export default class Launcher extends PopupWindow {
|
|||
constructor() {
|
||||
const entry = (<entry name="entry" />) as Widget.Entry;
|
||||
const mode = Variable<Mode>("apps");
|
||||
const showResults = Variable.derive([bind(entry, "textLength"), mode], (t, m) => t > 0 || m !== "apps");
|
||||
|
||||
super({
|
||||
name: "launcher",
|
||||
|
|
@ -323,12 +346,13 @@ export default class Launcher extends PopupWindow {
|
|||
transitionType: TransitionType.SLIDE_DOWN,
|
||||
halign: Gtk.Align.CENTER,
|
||||
valign: Gtk.Align.START,
|
||||
child: <LauncherContent mode={mode} entry={entry} />,
|
||||
child: <LauncherContent mode={mode} showResults={showResults} entry={entry} />,
|
||||
});
|
||||
|
||||
this.mode = mode;
|
||||
|
||||
this.connect("hide", () => entry.set_text(""));
|
||||
// Clear search on hide if not in math mode
|
||||
this.connect("hide", () => mode.get() !== "math" && entry.set_text(""));
|
||||
}
|
||||
|
||||
open(mode: Mode) {
|
||||
|
|
|
|||
110
package-lock.json
generated
110
package-lock.json
generated
|
|
@ -6,12 +6,24 @@
|
|||
"": {
|
||||
"dependencies": {
|
||||
"fuzzysort": "^3.1.0",
|
||||
"math-expression-evaluator": "^2.0.6"
|
||||
"mathjs": "^14.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"esbuild": "0.24.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz",
|
||||
"integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.14.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz",
|
||||
|
|
@ -437,6 +449,25 @@
|
|||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/complex.js": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.4.2.tgz",
|
||||
"integrity": "sha512-qtx7HRhPGSCBtGiST4/WGHuW+zeaND/6Ld+db6PbrulIB1i2Ev/2UPiqcmpQNPSyfBKraC0EOvOKCB5dGZKt3g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/rawify"
|
||||
}
|
||||
},
|
||||
"node_modules/decimal.js": {
|
||||
"version": "10.4.3",
|
||||
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
|
||||
"integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.24.2",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz",
|
||||
|
|
@ -478,17 +509,86 @@
|
|||
"@esbuild/win32-x64": "0.24.2"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-latex": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz",
|
||||
"integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fraction.js": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.2.1.tgz",
|
||||
"integrity": "sha512-Ah6t/7YCYjrPUFUFsOsRLMXAdnYM+aQwmojD2Ayb/Ezr82SwES0vuyQ8qZ3QO8n9j7W14VJuVZZet8U3bhSdQQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/rawify"
|
||||
}
|
||||
},
|
||||
"node_modules/fuzzysort": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fuzzysort/-/fuzzysort-3.1.0.tgz",
|
||||
"integrity": "sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/math-expression-evaluator": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-2.0.6.tgz",
|
||||
"integrity": "sha512-DRung1qNcKbgkhFeQ0fBPUFB6voRUMY7KyRyp1TRQ2v95Rp2egC823xLRooM1mDx1rmbkY7ym6ZWmpaE/VimOA==",
|
||||
"node_modules/javascript-natural-sort": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz",
|
||||
"integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/mathjs": {
|
||||
"version": "14.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mathjs/-/mathjs-14.0.1.tgz",
|
||||
"integrity": "sha512-yyJgLwC6UXuve724np8tHRMYaTtb5UqiOGQkjwbSXgH8y1C/LcJ0pvdNDZLI2LT7r+iExh2Y5HwfAY+oZFtGIQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.25.7",
|
||||
"complex.js": "^2.2.5",
|
||||
"decimal.js": "^10.4.3",
|
||||
"escape-latex": "^1.2.0",
|
||||
"fraction.js": "^5.2.1",
|
||||
"javascript-natural-sort": "^0.7.1",
|
||||
"seedrandom": "^3.0.5",
|
||||
"tiny-emitter": "^2.1.0",
|
||||
"typed-function": "^4.2.1"
|
||||
},
|
||||
"bin": {
|
||||
"mathjs": "bin/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.14.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
||||
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/seedrandom": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
|
||||
"integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tiny-emitter": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
|
||||
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/typed-function": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/typed-function/-/typed-function-4.2.1.tgz",
|
||||
"integrity": "sha512-EGjWssW7Tsk4DGfE+5yluuljS1OGYWiI1J6e8puZz9nTMM51Oug8CD5Zo4gWMsOhq5BI+1bF+rWTm4Vbj3ivRA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"fuzzysort": "^3.1.0",
|
||||
"math-expression-evaluator": "^2.0.6"
|
||||
"mathjs": "^14.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"esbuild": "0.24.2"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,19 @@
|
|||
@use "lib";
|
||||
@use "font";
|
||||
|
||||
@mixin launcher($mode, $colour) {
|
||||
&.#{$mode} {
|
||||
label.icon {
|
||||
color: $colour;
|
||||
}
|
||||
|
||||
.separator {
|
||||
background-color: $colour;
|
||||
margin: lib.s(5) 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.launcher-wrapper {
|
||||
@include lib.ease-in-out;
|
||||
|
||||
|
|
@ -21,6 +34,10 @@
|
|||
color: scheme.$text;
|
||||
padding: lib.s(10) lib.s(14);
|
||||
|
||||
@include launcher(apps, scheme.$sapphire);
|
||||
@include launcher(files, scheme.$peach);
|
||||
@include launcher(math, scheme.$green);
|
||||
|
||||
.search-bar {
|
||||
margin-bottom: lib.s(5);
|
||||
font-size: lib.s(16);
|
||||
|
|
@ -87,16 +104,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.apps label.icon {
|
||||
color: scheme.$sapphire;
|
||||
}
|
||||
|
||||
&.files label.icon {
|
||||
color: scheme.$peach;
|
||||
}
|
||||
|
||||
&.math label.icon {
|
||||
color: scheme.$green;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
159
services/math.ts
Normal file
159
services/math.ts
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
import { GLib, GObject, property, readFile, register, writeFileAsync } from "astal";
|
||||
import {
|
||||
create,
|
||||
derivativeDependencies,
|
||||
evaluateDependencies,
|
||||
rationalizeDependencies,
|
||||
simplifyDependencies,
|
||||
type MathNode,
|
||||
} from "mathjs/number";
|
||||
import { CACHE_DIR } from "../utils/constants";
|
||||
|
||||
export interface HistoryItem {
|
||||
equation: string;
|
||||
result: string;
|
||||
icon: string;
|
||||
}
|
||||
|
||||
@register({ GTypeName: "Math" })
|
||||
export default class Math extends GObject.Object {
|
||||
static instance: Math;
|
||||
static get_default() {
|
||||
if (!this.instance) this.instance = new Math();
|
||||
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
static math = create({
|
||||
simplifyDependencies,
|
||||
derivativeDependencies,
|
||||
rationalizeDependencies,
|
||||
evaluateDependencies,
|
||||
});
|
||||
|
||||
readonly #maxHistory = 20;
|
||||
readonly #path = `${CACHE_DIR}/math-history.json`;
|
||||
readonly #history: HistoryItem[] = [];
|
||||
|
||||
#variables: Record<string, number | MathNode> = {};
|
||||
#lastExpression: HistoryItem | null = null;
|
||||
|
||||
@property(Object)
|
||||
get history() {
|
||||
return this.#history;
|
||||
}
|
||||
|
||||
#save() {
|
||||
writeFileAsync(this.#path, JSON.stringify(this.#history)).catch(console.error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits the last evaluated expression to the history
|
||||
*/
|
||||
commit() {
|
||||
if (!this.#lastExpression) return;
|
||||
|
||||
// Try select first to prevent duplicates, if it fails, add it
|
||||
if (!this.select(this.#lastExpression)) {
|
||||
this.#history.unshift(this.#lastExpression);
|
||||
if (this.#history.length > this.#maxHistory) this.#history.pop();
|
||||
this.notify("history");
|
||||
this.#save();
|
||||
}
|
||||
this.#lastExpression = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves an item in the history to the top
|
||||
* @param item The item to select
|
||||
* @returns If the item was successfully selected
|
||||
*/
|
||||
select(item: HistoryItem) {
|
||||
const idx = this.#history.indexOf(item);
|
||||
if (idx >= 0) {
|
||||
this.#history.splice(idx, 1);
|
||||
this.#history.unshift(item);
|
||||
this.notify("history");
|
||||
this.#save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the history and variables
|
||||
*/
|
||||
clear() {
|
||||
if (this.#history.length > 0) {
|
||||
this.#history.length = 0;
|
||||
this.notify("history");
|
||||
this.#save();
|
||||
}
|
||||
this.#lastExpression = null;
|
||||
this.#variables = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates an equation and adds it to the history
|
||||
* @param equation The equation to evaluate
|
||||
* @returns A {@link HistoryItem} representing the result of the equation
|
||||
*/
|
||||
evaluate(equation: string): HistoryItem {
|
||||
if (equation.startsWith("clear"))
|
||||
return {
|
||||
equation: "Clear history",
|
||||
result: "Delete history and previously set variables",
|
||||
icon: "delete_forever",
|
||||
};
|
||||
|
||||
let result: string, icon: string;
|
||||
try {
|
||||
if (equation.includes("=")) {
|
||||
const [left, right] = equation.split("=");
|
||||
try {
|
||||
this.#variables[left] = Math.math.simplify(right);
|
||||
} catch {
|
||||
this.#variables[left] = parseFloat(right);
|
||||
}
|
||||
result = this.#variables[left].toString();
|
||||
icon = "equal";
|
||||
} else if (equation.startsWith("simplify")) {
|
||||
result = Math.math.simplify(equation.slice(8), this.#variables).toString();
|
||||
icon = "function";
|
||||
} else if (equation.startsWith("derive")) {
|
||||
const respectTo = equation.slice(6).split(" ")[0];
|
||||
result = Math.math.derivative(equation.slice(7 + respectTo.length), respectTo).toString();
|
||||
icon = "function";
|
||||
} else if (equation.startsWith("rationalize")) {
|
||||
result = Math.math.rationalize(equation.slice(11), this.#variables).toString();
|
||||
icon = "function";
|
||||
} else {
|
||||
result = Math.math.evaluate(equation, this.#variables).toString();
|
||||
icon = "calculate";
|
||||
}
|
||||
} catch {
|
||||
result = equation;
|
||||
icon = "error";
|
||||
equation = "Invalid equation";
|
||||
}
|
||||
|
||||
return (this.#lastExpression = { equation, result, icon });
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
// Load history
|
||||
if (GLib.file_test(this.#path, GLib.FileTest.EXISTS)) {
|
||||
try {
|
||||
this.#history = JSON.parse(readFile(this.#path));
|
||||
// Init eval to create variables and last expression
|
||||
for (const item of this.#history) this.evaluate(item.equation);
|
||||
} catch (e) {
|
||||
console.error("Math - Unable to load history", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { execAsync, GLib, GObject, property, readFile, register, writeFileAsync } from "astal";
|
||||
import { GLib, GObject, property, readFile, register, writeFileAsync } from "astal";
|
||||
import AstalMpris from "gi://AstalMpris";
|
||||
import { CACHE_DIR } from "../utils/constants";
|
||||
import { isRealPlayer } from "../utils/mpris";
|
||||
|
|
@ -89,9 +89,7 @@ export default class Players extends GObject.Object {
|
|||
}
|
||||
|
||||
#save() {
|
||||
execAsync(`mkdir -p ${CACHE_DIR}`)
|
||||
.then(() => writeFileAsync(this.#path, this.#players.map(p => p.busName).join("\n")).catch(console.error))
|
||||
.catch(console.error);
|
||||
writeFileAsync(this.#path, this.#players.map(p => p.busName).join("\n")).catch(console.error);
|
||||
}
|
||||
|
||||
#connectPlayerSignals(player: AstalMpris.Player) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { GLib } from "astal";
|
||||
import { exec, GLib } from "astal";
|
||||
|
||||
export const CACHE_DIR = GLib.get_user_cache_dir() + "/caelestia";
|
||||
exec(`mkdir -p '${CACHE_DIR}'`);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue