daily-focus 2.0.0-dev.18 → 2.0.0-dev.20
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/SETUP.md +20 -12
- package/dist/cli.js +1 -1
- package/dist/{server-FFRNYEAO.js → server-V44HFRLA.js} +17 -3
- package/package.json +2 -2
- package/public/app.js +33 -0
package/SETUP.md
CHANGED
|
@@ -431,22 +431,30 @@ Download `Daily-Focus.dmg` from the [latest release](https://github.com/watson/d
|
|
|
431
431
|
open it and drag the app to Applications, then open it from there.
|
|
432
432
|
It has no window and no Dock icon: look for it in the menu bar.
|
|
433
433
|
|
|
434
|
-
The app keeps itself up to date without a new disk image. **
|
|
435
|
-
shows two versions, the app's and the dashboard's, and which
|
|
436
|
-
**Stable Releases**, or **Development Builds**, a build of every
|
|
437
|
-
it is merged. A few times a day the app asks npm for the newest
|
|
438
|
-
it finds one, it posts a notification and the menu offers
|
|
439
|
-
Updating fetches only what the release changed. Most
|
|
440
|
-
dashboard, a few hundred kilobytes, and the dashboard
|
|
434
|
+
The app keeps itself up to date without a new disk image. **About Daily Focus** in
|
|
435
|
+
the menu shows two versions, the app's and the dashboard's, and **Updates** which
|
|
436
|
+
releases to take: **Stable Releases**, or **Development Builds**, a build of every
|
|
437
|
+
change as soon as it is merged. A few times a day the app asks npm for the newest
|
|
438
|
+
release, and when it finds one, it posts a notification and the menu offers
|
|
439
|
+
**Update Daily Focus**. Updating fetches only what the release changed. Most
|
|
440
|
+
releases change only the dashboard, a few hundred kilobytes, and the dashboard
|
|
441
|
+
restarts into it; if it
|
|
441
442
|
doesn't start, the app goes back to the one it had and says so. When a release
|
|
442
443
|
changes the app itself, the app downloads the new app, about 40 MB, puts it in its
|
|
443
444
|
own place and opens it again, and the new app carries the new dashboard. Either
|
|
444
445
|
way it installs nothing that isn't signed by the same developer as the app, with
|
|
445
|
-
nothing in it changed
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
446
|
+
nothing in it changed. It waits until the morning agent, the assistant and the
|
|
447
|
+
setup screen aren't at work; pressing **Update** while one is asks whether to wait
|
|
448
|
+
for it or stop it. An app that can't change the folder it is in, such as one
|
|
449
|
+
opened straight from the disk image, links to the new disk image instead, and
|
|
450
|
+
still updates its dashboard on its own. A dashboard that `daily-focus service` or
|
|
451
|
+
a terminal runs is updated the way it was installed, not by the app.
|
|
452
|
+
|
|
453
|
+
Updates install only when you ask, unless you turn on **Update Automatically**
|
|
454
|
+
under **Updates**; the app asks once, when setup is finished. Then an update goes
|
|
455
|
+
in on its own once nobody has used the dashboard for half an hour, never while
|
|
456
|
+
anything in it is at work. Using it means clicking, typing or scrolling in a tab
|
|
457
|
+
you can see, from whichever computer you read it on.
|
|
450
458
|
|
|
451
459
|
To build it yourself from a checkout:
|
|
452
460
|
|
package/dist/cli.js
CHANGED
|
@@ -68,7 +68,7 @@ async function demo(open, profile) {
|
|
|
68
68
|
);
|
|
69
69
|
}
|
|
70
70
|
async function start(open, onStarted, options = {}) {
|
|
71
|
-
const { runServer } = await import("./server-
|
|
71
|
+
const { runServer } = await import("./server-V44HFRLA.js");
|
|
72
72
|
await runServer({
|
|
73
73
|
...options,
|
|
74
74
|
onStarted: (url) => {
|
|
@@ -4989,7 +4989,7 @@ function configure(sources) {
|
|
|
4989
4989
|
return { config: loadConfig(layerSettings(sources, {})), warnings };
|
|
4990
4990
|
}
|
|
4991
4991
|
}
|
|
4992
|
-
function statusOf(state, config,
|
|
4992
|
+
function statusOf(state, config, busyWith, usedAt) {
|
|
4993
4993
|
const last = state.agentRun.last;
|
|
4994
4994
|
return {
|
|
4995
4995
|
version: VERSION2,
|
|
@@ -4997,7 +4997,9 @@ function statusOf(state, config, busy) {
|
|
|
4997
4997
|
profile: config.profile,
|
|
4998
4998
|
setupNeeded: state.setup.needed,
|
|
4999
4999
|
restartPending: state.restart !== null,
|
|
5000
|
-
busy,
|
|
5000
|
+
busy: busyWith.length > 0,
|
|
5001
|
+
busyWith,
|
|
5002
|
+
usedAt: usedAt.toISOString(),
|
|
5001
5003
|
brief: {
|
|
5002
5004
|
generatedAt: state.brief.generatedAt,
|
|
5003
5005
|
ageHours: state.brief.ageHours,
|
|
@@ -5072,6 +5074,7 @@ async function startServer(env, options = {}) {
|
|
|
5072
5074
|
restartWhenIdle();
|
|
5073
5075
|
}
|
|
5074
5076
|
});
|
|
5077
|
+
let usedAt = /* @__PURE__ */ new Date();
|
|
5075
5078
|
const onboarding = new Onboarding(config, {
|
|
5076
5079
|
onChange: () => {
|
|
5077
5080
|
void broadcast();
|
|
@@ -5660,7 +5663,18 @@ ${entry.source}`)).map(({ title, source }) => ({ title, source })).sort((a, b) =
|
|
|
5660
5663
|
return;
|
|
5661
5664
|
}
|
|
5662
5665
|
if (path === "/api/status" && req.method === "GET") {
|
|
5663
|
-
|
|
5666
|
+
const busyWith = [
|
|
5667
|
+
...agent.busy ? ["agent"] : [],
|
|
5668
|
+
...assistant.busy ? ["assistant"] : [],
|
|
5669
|
+
...onboarding.busy ? ["setup"] : []
|
|
5670
|
+
];
|
|
5671
|
+
sendJSON(res, 200, statusOf(await buildState(), config, busyWith, usedAt));
|
|
5672
|
+
return;
|
|
5673
|
+
}
|
|
5674
|
+
if (path === "/api/presence" && req.method === "POST") {
|
|
5675
|
+
usedAt = /* @__PURE__ */ new Date();
|
|
5676
|
+
res.writeHead(204, { "cache-control": "no-store" });
|
|
5677
|
+
res.end();
|
|
5664
5678
|
return;
|
|
5665
5679
|
}
|
|
5666
5680
|
if (path === "/api/health" && req.method === "GET") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "daily-focus",
|
|
3
|
-
"version": "2.0.0-dev.
|
|
3
|
+
"version": "2.0.0-dev.20",
|
|
4
4
|
"description": "An interactive dashboard of what you should focus on today at work",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dashboard",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"daily-focus": {
|
|
43
43
|
"appInterface": 1,
|
|
44
|
-
"appSource": "
|
|
44
|
+
"appSource": "0df3059a46d460871b08ddea9dd9a793f20cf9f5"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"start": "node src/server.ts",
|
package/public/app.js
CHANGED
|
@@ -1052,6 +1052,14 @@ function subscribe(onState, onError) {
|
|
|
1052
1052
|
function postTimeZone(timeZone) {
|
|
1053
1053
|
return post("/api/timezone", { timeZone });
|
|
1054
1054
|
}
|
|
1055
|
+
async function postPresence() {
|
|
1056
|
+
const res = await fetch("/api/presence", {
|
|
1057
|
+
method: "POST",
|
|
1058
|
+
headers: { "content-type": "application/json" },
|
|
1059
|
+
body: "{}"
|
|
1060
|
+
});
|
|
1061
|
+
if (!res.ok) throw new Error(`POST /api/presence returned ${res.status}`);
|
|
1062
|
+
}
|
|
1055
1063
|
function postBoardRefresh() {
|
|
1056
1064
|
return post("/api/board/refresh");
|
|
1057
1065
|
}
|
|
@@ -5746,6 +5754,21 @@ function installKeyboard(handlers2) {
|
|
|
5746
5754
|
});
|
|
5747
5755
|
}
|
|
5748
5756
|
|
|
5757
|
+
// client/presence.ts
|
|
5758
|
+
var PRESENCE_EVERY_MS = 6e4;
|
|
5759
|
+
function watchPresence(deps) {
|
|
5760
|
+
let last = -Infinity;
|
|
5761
|
+
return {
|
|
5762
|
+
noticed() {
|
|
5763
|
+
if (!deps.visible()) return;
|
|
5764
|
+
const now = deps.now();
|
|
5765
|
+
if (now - last < PRESENCE_EVERY_MS) return;
|
|
5766
|
+
last = now;
|
|
5767
|
+
deps.send().catch((err) => console.warn("[daily-focus] could not tell the dashboard it is in use:", err));
|
|
5768
|
+
}
|
|
5769
|
+
};
|
|
5770
|
+
}
|
|
5771
|
+
|
|
5749
5772
|
// client/main.ts
|
|
5750
5773
|
ui.theme.value = stampedTheme();
|
|
5751
5774
|
j3(() => setCalendarZone(state.value?.timeZone));
|
|
@@ -5797,6 +5820,16 @@ zone.look();
|
|
|
5797
5820
|
document.addEventListener("visibilitychange", () => zone.look());
|
|
5798
5821
|
window.addEventListener("focus", () => zone.look());
|
|
5799
5822
|
setInterval(() => zone.check(), ZONE_CHECK_MS);
|
|
5823
|
+
var presence = watchPresence({
|
|
5824
|
+
visible: () => document.visibilityState === "visible",
|
|
5825
|
+
now: Date.now,
|
|
5826
|
+
send: postPresence
|
|
5827
|
+
});
|
|
5828
|
+
presence.noticed();
|
|
5829
|
+
for (const event of ["pointerdown", "keydown", "wheel", "touchstart"]) {
|
|
5830
|
+
window.addEventListener(event, () => presence.noticed(), { capture: true, passive: true });
|
|
5831
|
+
}
|
|
5832
|
+
document.addEventListener("visibilitychange", () => presence.noticed());
|
|
5800
5833
|
followLocation();
|
|
5801
5834
|
window.addEventListener("popstate", followLocation);
|
|
5802
5835
|
window.addEventListener("hashchange", followLocation);
|