@gjermundgaraba/upup 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -7
- package/dist/{Tui-BiTtZ1EF.mjs → Tui-DV_6wbrQ.mjs} +42 -37
- package/dist/main.mjs +706 -287
- package/native/dist/upup-sparkle.json +1 -1
- package/native/dist/upup-sparkle.zip +0 -0
- package/package.json +16 -17
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Understand, audit and update system tools and project dependencies from one TUI.
|
|
|
8
8
|
npm install -g @gjermundgaraba/upup
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Requires Node 26.
|
|
11
|
+
Requires Node 26.13 or newer. The TUI is built on [OpenTUI](https://github.com/anomalyco/opentui), which runs through Node's FFI.
|
|
12
12
|
|
|
13
13
|
## Usage
|
|
14
14
|
|
|
@@ -18,19 +18,21 @@ upup system # tools installed on this machine
|
|
|
18
18
|
upup project [dir] # dependencies of the project containing dir
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
**System** lists operating-system updates from macOS Software Update and apt, macOS apps that update themselves, and tools from Homebrew (formulae and casks), npm, pnpm and Vite+ globals, Vite+ itself, `cargo install`, `go install` and `uv tool`. Only the package managers on your `PATH` are asked.
|
|
21
|
+
**System** lists operating-system updates from macOS Software Update and apt, macOS apps that update themselves, and tools from Homebrew (formulae and casks), npm, pnpm and Vite+ globals, Vite+ itself and its environment defaults, `cargo install`, `go install` and `uv tool`. Only the package managers on your `PATH` are asked.
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Vite+ environment rows show configured global defaults for Node.js, npm, pnpm, Yarn and Bun. Exact Node.js defaults update within their current major. Yarn Classic stays on Yarn 1, since modern Yarn is a different published package; migrating to it is left to you. Other package managers update to their latest stable release. Floating defaults such as `latest` and `lts` show their configured selector and stay under Vite+’s automatic version selection. Updating installs the selected version and changes that tool’s default, preserving project pins and cached versions. Each default is checked immediately before updating, checked again after downloading and before switching, and verified afterward.
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
**Project** lists the registry dependencies declared across the workspace that contains the directory: Go modules, Cargo workspaces, and npm or pnpm projects including pnpm catalogs, among them a catalog entry only an override uses when it names an exact version. A Cargo dependency is listed whatever features turn it on. Path, Git and workspace references are not listed, nor is one module of a `go.work` that another requires, or a module its `replace` covers. Yarn and Bun projects are reported as unsupported.
|
|
26
|
+
|
|
27
|
+
In a git repository it also lists every project below the directory that a `package.json`, `go.mod` or `Cargo.toml` git tracks or doesn't ignore belongs to, each once, its provider named with where it is (`npm clients/voice`). A `package.json` with a lockfile beside it is a project of its own, and so is a Go module its `go.work` doesn't use. Folders under `node_modules`, subtrees vendored in with `git subtree`, and Go modules in the folders the go command skips (`testdata`, and those starting with `_` or `.`) are left out. Node projects below the directory that have no lockfile yet, or use Yarn or Bun, are named together in one notice; a workspace names the folders in it that its lockfile doesn't list. A Cargo workspace with no `Cargo.lock` yet is named in a notice too. A Go workspace whose member module paths cannot be read is reported as unavailable; unrelated projects remain listed. upup runs cargo with `RUSTUP_AUTO_INSTALL=0`, so rustup doesn't install the toolchain a Cargo workspace pins (releases of rustup too old to know the setting still do); a missing one fails with rustup's message.
|
|
26
28
|
|
|
27
29
|
It also lists the GitHub Actions and reusable workflows that the repository's workflows (`.github/workflows`), its own `action.yml` and its composite actions (under `.github/actions`, and any local action a workflow uses) use, once per action and release however many files say it. Their tags are read with `git ls-remote`: first from the server the repository's `origin` is on, when that isn't github.com, since a GitHub Enterprise Server runs its own copy of an action before github.com's; then from github.com, a private repository's with your own git config. An update moves to the newest release tag written like the current one: as precise, and with or without the `v`. So `@v4` moves to `@v5` once the action tags `v5`, and `@v4.1.2` to the newest full release. A commit pin is read as the release tag that points at it (the one its comment names, such as `# v4.1.2`, else the most precise) and moves to the commit of the newest tag like that one, its comment's version moving with it; upup says when a comment names a tag that points elsewhere. Local (`./`) actions are read rather than listed, Docker actions are not listed, and branches such as `@main` are listed without an update. Removing an action is left to you.
|
|
28
30
|
|
|
29
31
|
It also lists the Node.js versions pinned exactly, once per version however many files pin it: `node-version` in the `actions/setup-node` steps of every workflow and action upup reads for GitHub Actions, and the first line that isn't blank or a comment in the `.node-version` and `.nvmrc` files of the directory, the folders below it and those between it and the repository's top that git tracks or doesn't ignore. An update moves to the newest release on the same major line from nodejs.org, keeping each file's `v` or quotes, since moving to another major line is a migration rather than an update. `22` and `lts/*` already follow their line and aren't listed; matrix entries, expressions and Dockerfile `FROM node:` images aren't read yet. Like OS updates, these aren't audited.
|
|
30
32
|
|
|
31
|
-
The package manager a Node project declares, in `packageManager` (`pnpm@12.5.1`) or `devEngines.packageManager`, is listed too, each field as a row of its own, and moves like a dependency
|
|
33
|
+
The package manager a Node project declares, in `packageManager` (`pnpm@12.5.1`) or `devEngines.packageManager`, is listed too, each field as a row of its own, and moves like a dependency. Its current version is the one pnpm locked, or else the declared one; a range with no locked version isn't listed. Corepack's sha512 hash moves with the version, worked out from the registry's integrity for the release; a pin with another kind of hash is listed without an offer. Neither field can be removed from upup.
|
|
32
34
|
|
|
33
|
-
Current versions come from the package manager or lockfile. An offered update is the newest stable release. Updating a declared range keeps its style (`^1.2.0` becomes `^1.4.0`), and the lockfile is reconciled and checked afterwards. Removing a project dependency edits the manifest and reconciles the same way.
|
|
35
|
+
Current versions come from the package manager or lockfile. An offered update is the newest stable release; in a Node project, no newer than the one the registry tags `latest` and older than the project's minimum release age. When the registry can't be reached, the project's dependencies are listed without offers and one notice says why. Updating a declared range keeps its style (`^1.2.0` becomes `^1.4.0`), and the lockfile is reconciled and checked afterwards. Removing a project dependency edits the manifest and reconciles the same way.
|
|
34
36
|
|
|
35
37
|
## OS updates
|
|
36
38
|
|
|
@@ -113,7 +115,7 @@ Each update run is also logged to `updates/` in the user cache directory, one JS
|
|
|
113
115
|
|
|
114
116
|
## Development
|
|
115
117
|
|
|
116
|
-
Requires Node 26.
|
|
118
|
+
Requires Node 26.13 or newer and [Vite+](https://viteplus.dev).
|
|
117
119
|
|
|
118
120
|
Run `mise install` once to get the Go toolchain `mise.toml` pins; a binary-audit test reads its build info and is skipped without Go.
|
|
119
121
|
|
|
@@ -3,7 +3,7 @@ import { Deferred, Effect, FiberSet, Stream } from "effect";
|
|
|
3
3
|
import { spawn } from "node:child_process";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import semver from "semver";
|
|
6
|
-
import { createComponent, createElement, createTextNode, effect, insert, insertNode, memo, render, setProp, use, useKeyboard, usePaste, useTerminalDimensions } from "@opentui/solid";
|
|
6
|
+
import { createComponent, createElement, createTextNode, effect, insert, insertNode, memo, onAnimationTick, render, setProp, use, useKeyboard, usePaste, useTerminalDimensions } from "@opentui/solid";
|
|
7
7
|
import { TextAttributes, createCliRenderer } from "@opentui/core";
|
|
8
8
|
import { For, Match, Show, Switch, createEffect, createMemo, createRenderEffect, createSignal, on, onCleanup, untrack } from "solid-js/dist/solid.js";
|
|
9
9
|
// src/tui/text.ts
|
|
@@ -614,11 +614,8 @@ const frames = [
|
|
|
614
614
|
];
|
|
615
615
|
const Spinner = (props) => {
|
|
616
616
|
const [frame, setFrame] = createSignal(0);
|
|
617
|
-
|
|
617
|
+
onAnimationTick(12.5, () => {
|
|
618
618
|
setFrame((at) => (at + 1) % frames.length);
|
|
619
|
-
}, 80);
|
|
620
|
-
onCleanup(() => {
|
|
621
|
-
clearInterval(timer);
|
|
622
619
|
});
|
|
623
620
|
return (() => {
|
|
624
621
|
var _el$ = createElement("text");
|
|
@@ -1281,6 +1278,7 @@ const providerLabels = /* @__PURE__ */ new Map([
|
|
|
1281
1278
|
["pnpm-global", "pnpm -g"],
|
|
1282
1279
|
["vp-global", "Vite+ global"],
|
|
1283
1280
|
["vp-self", "Vite+"],
|
|
1281
|
+
["vp-env", "Vite+ environment"],
|
|
1284
1282
|
["cargo-install", "cargo install"],
|
|
1285
1283
|
["go-install", "go install"],
|
|
1286
1284
|
["uv-tool", "uv tool"],
|
|
@@ -1352,7 +1350,7 @@ const lines = (grouped) => {
|
|
|
1352
1350
|
const reachable = (grouped) => grouped.flatMap(visibleRows);
|
|
1353
1351
|
const unauditedLabels = {
|
|
1354
1352
|
app: "app update",
|
|
1355
|
-
runtime: "runtime
|
|
1353
|
+
runtime: "Node.js runtime",
|
|
1356
1354
|
os: "OS update"
|
|
1357
1355
|
};
|
|
1358
1356
|
const parts = (version) => version.replace(/^v/u, "").split(/(?<separator>[._+-])/u);
|
|
@@ -1776,7 +1774,7 @@ const ConfirmPopup = (props) => {
|
|
|
1776
1774
|
get children() {
|
|
1777
1775
|
var _el$6 = createElement("text");
|
|
1778
1776
|
setProp(_el$6, "wrapMode", "word");
|
|
1779
|
-
insert(_el$6, () => pending().rows.some((row) => unauditedKind(row.pkg) === "runtime") ? "upup does not audit
|
|
1777
|
+
insert(_el$6, () => pending().rows.some((row) => unauditedKind(row.pkg) === "runtime") ? "upup does not audit Node.js runtimes: confirming updates the selected versions as offered." : "upup does not audit operating-system or app updates: confirming installs them as the vendor offers them, and upup asks for your password if sudo needs it.");
|
|
1780
1778
|
effect((_$p) => setProp(_el$6, "fg", theme.muted, _$p));
|
|
1781
1779
|
return _el$6;
|
|
1782
1780
|
}
|
|
@@ -4008,6 +4006,9 @@ const SettingsPopup = (props) => {
|
|
|
4008
4006
|
const [entry, setEntry] = createSignal("");
|
|
4009
4007
|
const [picked, setPicked] = createSignal(0);
|
|
4010
4008
|
props.run(props.session.loadCatalogue);
|
|
4009
|
+
onCleanup(() => {
|
|
4010
|
+
if (props.state.signIn.value === "Prompted") props.run(props.session.closeSignIn);
|
|
4011
|
+
});
|
|
4011
4012
|
const catalogue = () => props.state.catalogue?._tag === "Ready" ? props.state.catalogue.value : [];
|
|
4012
4013
|
const setup = () => props.state.preferences.setup;
|
|
4013
4014
|
const current = createMemo(() => catalogue().find((choice) => choice.provider === setup()?.provider && choice.modelId === setup()?.modelId));
|
|
@@ -4038,7 +4039,8 @@ const SettingsPopup = (props) => {
|
|
|
4038
4039
|
};
|
|
4039
4040
|
createEffect(() => {
|
|
4040
4041
|
const now = mode();
|
|
4041
|
-
|
|
4042
|
+
const { signIn } = props.state;
|
|
4043
|
+
if (now._tag !== "SigningIn" || signIn.value !== "SignedIn" || signIn.context.provider !== now.choice.provider) return;
|
|
4042
4044
|
const signedIn = catalogue().find((choice) => choice.provider === now.choice.provider && choice.modelId === now.choice.modelId);
|
|
4043
4045
|
if (signedIn?.signedIn === true) choose(signedIn);
|
|
4044
4046
|
});
|
|
@@ -4110,7 +4112,7 @@ const SettingsPopup = (props) => {
|
|
|
4110
4112
|
_tag: "SigningIn",
|
|
4111
4113
|
choice
|
|
4112
4114
|
});
|
|
4113
|
-
props.run(props.session.signIn(choice.provider));
|
|
4115
|
+
props.run(props.session.closeSignIn.pipe(Effect.andThen(props.session.signIn(choice.provider))));
|
|
4114
4116
|
}
|
|
4115
4117
|
};
|
|
4116
4118
|
const onEntry = (key, submit, cancel) => {
|
|
@@ -4127,11 +4129,11 @@ const SettingsPopup = (props) => {
|
|
|
4127
4129
|
setMode({ _tag: "Picker" });
|
|
4128
4130
|
};
|
|
4129
4131
|
const onSignIn = (key, signIn) => {
|
|
4130
|
-
if (signIn
|
|
4132
|
+
if (signIn.value !== "Prompted") {
|
|
4131
4133
|
if (key.name === "escape") cancel();
|
|
4132
4134
|
return;
|
|
4133
4135
|
}
|
|
4134
|
-
const { prompt } = signIn;
|
|
4136
|
+
const { prompt } = signIn.context;
|
|
4135
4137
|
if (prompt.type === "select") {
|
|
4136
4138
|
if (key.name === "escape") cancel();
|
|
4137
4139
|
else if (key.name === "down") setPicked((index) => Math.min(prompt.options.length - 1, index + 1));
|
|
@@ -4162,7 +4164,7 @@ const SettingsPopup = (props) => {
|
|
|
4162
4164
|
case "Key":
|
|
4163
4165
|
onEntry(key, (text) => {
|
|
4164
4166
|
if (text.trim() === "") return;
|
|
4165
|
-
props.run(props.session.saveKey(now.choice.provider, text.trim()));
|
|
4167
|
+
props.run(props.session.closeSignIn.pipe(Effect.andThen(props.session.saveKey(now.choice.provider, text.trim()))));
|
|
4166
4168
|
setEntry("");
|
|
4167
4169
|
setMode({
|
|
4168
4170
|
_tag: "SigningIn",
|
|
@@ -4236,9 +4238,12 @@ const SettingsPopup = (props) => {
|
|
|
4236
4238
|
const now = mode();
|
|
4237
4239
|
return now._tag === "SigningIn" ? now : void 0;
|
|
4238
4240
|
};
|
|
4239
|
-
const
|
|
4240
|
-
const failure = () =>
|
|
4241
|
-
|
|
4241
|
+
const notices = () => props.state.signIn.context.notices ?? [];
|
|
4242
|
+
const failure = () => {
|
|
4243
|
+
const { signIn } = props.state;
|
|
4244
|
+
return signIn.value === "Failed" ? signIn.context : void 0;
|
|
4245
|
+
};
|
|
4246
|
+
const prompt = createMemo(() => props.state.signIn.context.prompt);
|
|
4242
4247
|
const selecting = () => {
|
|
4243
4248
|
const asked = prompt();
|
|
4244
4249
|
return asked?.type === "select" ? asked : void 0;
|
|
@@ -4444,7 +4449,7 @@ const SettingsPopup = (props) => {
|
|
|
4444
4449
|
setProp(_el$10, "flexDirection", "column");
|
|
4445
4450
|
insert(_el$10, createComponent(Show, {
|
|
4446
4451
|
get when() {
|
|
4447
|
-
return memo(() => (
|
|
4452
|
+
return memo(() => notices().length === 0)() && prompt() === void 0;
|
|
4448
4453
|
},
|
|
4449
4454
|
get children() {
|
|
4450
4455
|
var _el$11 = createElement("text");
|
|
@@ -4455,7 +4460,7 @@ const SettingsPopup = (props) => {
|
|
|
4455
4460
|
}), null);
|
|
4456
4461
|
insert(_el$10, createComponent(For, {
|
|
4457
4462
|
get each() {
|
|
4458
|
-
return
|
|
4463
|
+
return notices();
|
|
4459
4464
|
},
|
|
4460
4465
|
children: (notice) => (() => {
|
|
4461
4466
|
var _el$13 = createElement("text");
|
|
@@ -4657,6 +4662,7 @@ const App = (props) => {
|
|
|
4657
4662
|
createEffect(() => {
|
|
4658
4663
|
if (anchor() !== void 0) anchorAt(cursor());
|
|
4659
4664
|
});
|
|
4665
|
+
const operating = () => props.state.operation.value !== "Idle";
|
|
4660
4666
|
const question = () => questionOf(props.state);
|
|
4661
4667
|
const deciding = () => question() !== void 0;
|
|
4662
4668
|
const finding = () => overlay()._tag === "Find" && !deciding();
|
|
@@ -4670,7 +4676,7 @@ const App = (props) => {
|
|
|
4670
4676
|
const selectedRows = createMemo(() => everyRow().filter((row) => props.state.selected.includes(row.key)));
|
|
4671
4677
|
const notices = createMemo(() => {
|
|
4672
4678
|
const discovery = props.state.discoveryError;
|
|
4673
|
-
|
|
4679
|
+
const found = [
|
|
4674
4680
|
...discovery === void 0 ? [] : [{
|
|
4675
4681
|
color: theme.danger,
|
|
4676
4682
|
message: `✗ ${describeError(discovery)}`
|
|
@@ -4683,7 +4689,12 @@ const App = (props) => {
|
|
|
4683
4689
|
color: theme.warn,
|
|
4684
4690
|
message: `! ${providerLabel(entry.name)}: ${notice.message}`
|
|
4685
4691
|
})))
|
|
4686
|
-
]
|
|
4692
|
+
];
|
|
4693
|
+
if (found.length <= noticeLimit) return found;
|
|
4694
|
+
return [...found.slice(0, 3), {
|
|
4695
|
+
color: theme.muted,
|
|
4696
|
+
message: `+${found.length - noticeLimit + 1} more notices`
|
|
4697
|
+
}];
|
|
4687
4698
|
});
|
|
4688
4699
|
const natural = createMemo(() => naturalColumns(everyRow(), props.state));
|
|
4689
4700
|
const fullList = () => Math.max(tableWidth(natural()) + 4, listMin);
|
|
@@ -4786,16 +4797,12 @@ const App = (props) => {
|
|
|
4786
4797
|
readTo.clear();
|
|
4787
4798
|
} else if (before !== void 0 && scroller !== void 0) readTo.set(before[1], scroller.scrollTop);
|
|
4788
4799
|
if (now === "transcript" || scroller === void 0) return;
|
|
4789
|
-
scroller.
|
|
4790
|
-
const saved = readTo.get(now);
|
|
4791
|
-
if (saved !== void 0 && saved > 0) setTimeout(() => {
|
|
4792
|
-
if (scroller !== void 0 && tab() === now) scroller.scrollTop = saved;
|
|
4793
|
-
}, 30);
|
|
4800
|
+
scroller.scrollTo(readTo.get(now) ?? 0);
|
|
4794
4801
|
}));
|
|
4795
4802
|
createEffect(on(transcript, (file) => {
|
|
4796
4803
|
if (file !== void 0) fire(props.session.readTranscript(file));
|
|
4797
4804
|
}));
|
|
4798
|
-
createEffect(on(
|
|
4805
|
+
createEffect(on(operating, (now, before) => {
|
|
4799
4806
|
if (before !== true || now) return;
|
|
4800
4807
|
const last = untrack(run);
|
|
4801
4808
|
if (last === void 0) return;
|
|
@@ -4848,6 +4855,7 @@ const App = (props) => {
|
|
|
4848
4855
|
});
|
|
4849
4856
|
const scrollDetails = (direction) => scroller?.scrollBy(direction * Math.max(1, Math.floor(contentHeight() / 2)));
|
|
4850
4857
|
const confirm = (action) => {
|
|
4858
|
+
if (action !== "audit" && operating()) return;
|
|
4851
4859
|
if (action === "audit" || action === "update" && props.state.preferences.auditFirst) fire(props.session.loadCatalogue);
|
|
4852
4860
|
const focusedRow = focused();
|
|
4853
4861
|
if (selectedRows().length === 0 && focusedRow !== void 0 && props.state.removed[focusedRow.key] !== void 0) {
|
|
@@ -4917,7 +4925,7 @@ const App = (props) => {
|
|
|
4917
4925
|
}
|
|
4918
4926
|
};
|
|
4919
4927
|
const quit = () => {
|
|
4920
|
-
if (!
|
|
4928
|
+
if (!operating()) {
|
|
4921
4929
|
props.quit();
|
|
4922
4930
|
return;
|
|
4923
4931
|
}
|
|
@@ -4967,10 +4975,7 @@ const App = (props) => {
|
|
|
4967
4975
|
const count = changedFiles();
|
|
4968
4976
|
if (count === 0) return;
|
|
4969
4977
|
setFileAt((at) => (Math.min(at, count - 1) + by + count) % count);
|
|
4970
|
-
|
|
4971
|
-
const head = scroller?.content.findDescendantById(diffHead);
|
|
4972
|
-
if (scroller !== void 0 && head !== void 0) scroller.scrollBy(head.y - scroller.viewport.y);
|
|
4973
|
-
}, 30);
|
|
4978
|
+
scroller?.scrollChildIntoView(diffHead, { align: "start" });
|
|
4974
4979
|
};
|
|
4975
4980
|
const browse = () => {
|
|
4976
4981
|
const row = focused();
|
|
@@ -5040,7 +5045,7 @@ const App = (props) => {
|
|
|
5040
5045
|
else if (matches(keys.browse, key)) browse();
|
|
5041
5046
|
else if (matches(keys.stop, key)) fire(props.session.stop);
|
|
5042
5047
|
else if (matches(keys.quit, key)) quit();
|
|
5043
|
-
else if (matches(keys.switchMode, key) && !
|
|
5048
|
+
else if (matches(keys.switchMode, key) && !operating()) {
|
|
5044
5049
|
const mode = otherMode(props.state.mode);
|
|
5045
5050
|
places.set(props.state.mode, {
|
|
5046
5051
|
key: focused()?.key,
|
|
@@ -5102,8 +5107,8 @@ const App = (props) => {
|
|
|
5102
5107
|
const auditing = () => Object.values(props.state.audits).filter((audit) => audit._tag === "Running").length;
|
|
5103
5108
|
const summary = () => {
|
|
5104
5109
|
if (quitting()) return "Stopping; upup quits once the running update finishes";
|
|
5105
|
-
if (props.state.stopping) return "Stopping after the targets already started";
|
|
5106
|
-
if (
|
|
5110
|
+
if (props.state.operation.context.stopping) return "Stopping after the targets already started";
|
|
5111
|
+
if (operating()) return progress();
|
|
5107
5112
|
const all = rows();
|
|
5108
5113
|
const selected = selectedRows().length;
|
|
5109
5114
|
const hidden = selectedRows().filter((row) => !all.some((visible) => visible.key === row.key)).length;
|
|
@@ -5124,7 +5129,7 @@ const App = (props) => {
|
|
|
5124
5129
|
};
|
|
5125
5130
|
const hints = () => {
|
|
5126
5131
|
if (finding()) return [[keys.keepFilter, 0], [keys.clearFilter, 0]];
|
|
5127
|
-
if (
|
|
5132
|
+
if (operating()) return [
|
|
5128
5133
|
[keys.stop, 0],
|
|
5129
5134
|
[keys.up, 3],
|
|
5130
5135
|
[keys.quit, 2]
|
|
@@ -5192,7 +5197,7 @@ const App = (props) => {
|
|
|
5192
5197
|
const latest = toast();
|
|
5193
5198
|
return latest === void 0 ? summary() : `${summary()} ${latest.text}`;
|
|
5194
5199
|
};
|
|
5195
|
-
const busy = () =>
|
|
5200
|
+
const busy = () => operating() || auditing() > 0;
|
|
5196
5201
|
const footerRoom = () => dimensions().width - 2 - (busy() ? 2 : 0);
|
|
5197
5202
|
const fitted = () => overlay()._tag !== "None" && !finding() ? [] : fitFooterHints(hints(), footerRoom(), graphemes(`${footnote()} `).length);
|
|
5198
5203
|
const statusRoom = () => footerRoom() - hintsWidth(fitted());
|
|
@@ -5435,7 +5440,7 @@ const App = (props) => {
|
|
|
5435
5440
|
setProp(_el$21, "paddingRight", 1);
|
|
5436
5441
|
insert(_el$21, createComponent(Show, {
|
|
5437
5442
|
get when() {
|
|
5438
|
-
return
|
|
5443
|
+
return busy();
|
|
5439
5444
|
},
|
|
5440
5445
|
get children() {
|
|
5441
5446
|
return [createComponent(Spinner, { get color() {
|
|
@@ -5725,7 +5730,7 @@ const App = (props) => {
|
|
|
5725
5730
|
})
|
|
5726
5731
|
}), null);
|
|
5727
5732
|
effect((_p$) => {
|
|
5728
|
-
var _v$3 = theme.onAccent, _v$4 = theme.accent, _v$5 = TextAttributes.BOLD, _v$6 = theme.muted, _v$7 =
|
|
5733
|
+
var _v$3 = theme.onAccent, _v$4 = theme.accent, _v$5 = TextAttributes.BOLD, _v$6 = theme.muted, _v$7 = operating() ? theme.text : theme.muted;
|
|
5729
5734
|
_v$3 !== _p$.e && (_p$.e = setProp(_el$3, "fg", _v$3, _p$.e));
|
|
5730
5735
|
_v$4 !== _p$.t && (_p$.t = setProp(_el$3, "bg", _v$4, _p$.t));
|
|
5731
5736
|
_v$5 !== _p$.a && (_p$.a = setProp(_el$3, "attributes", _v$5, _p$.a));
|