aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/companion
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-23 15:10:19 +0200
committerDanilo M. <danix@danix.xyz>2026-10-23 15:10:19 +0200
commit5e506270a8e5c891070672b60b7a397a4b1aec1e (patch)
tree29f876246c1317b28e8e50a63c47343f6efc60ec /desktop/companion
parenta162d1263692626e4731354764c53d37ad03fb28 (diff)
downloadquickshell-5e506270a8e5c891070672b60b7a397a4b1aec1e.tar.gz
quickshell-5e506270a8e5c891070672b60b7a397a4b1aec1e.zip
companion: shoved for a moment, then mad beside the balloon
The shoved frame held for as long as a balloon stayed, which read as her stumbling for ten seconds. It now lasts T.shoveHold (1.2 s), then she is mad beside the balloon until it goes. shovedAt is reset to 0 when the shove ends and 0 reads as the shove's first instant, so the binding cannot show mad for a tick before the handler stamps the time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'desktop/companion')
-rw-r--r--desktop/companion/Companion.qml7
-rw-r--r--desktop/companion/Mood.js4
-rw-r--r--desktop/companion/test_mood.js9
3 files changed, 15 insertions, 5 deletions
diff --git a/desktop/companion/Companion.qml b/desktop/companion/Companion.qml
index 7f740a3..0a1360f 100644
--- a/desktop/companion/Companion.qml
+++ b/desktop/companion/Companion.qml
@@ -143,12 +143,17 @@ PanelWindow {
return (Notify.queue || []).some(n => NC.shown(Notify.config, n, Notify.dnd,
Notify.drawerOpen, Notify.snoozeUntil, root.now));
}
- onShovedChanged: if (root.shoved) root.say("shoved")
+ property double shovedAt: 0
+ onShovedChanged: {
+ root.shovedAt = root.shoved ? Date.now() : 0;
+ if (root.shoved) root.say("shoved");
+ }
// --- state ----------------------------------------------------------
readonly property var mood: Mood.pick({
now: root.now, destructAt: root.destructAt, dodging: root.dodging, shoved: root.shoved,
+ shovedAt: root.shovedAt,
recording: root.asst.recording, busy: root.asst.busy, repliedAt: root.repliedAt,
clicks: root.clicks, mockAt: root.mockAt, typingAt: root.typingAt, wakeAt: root.wakeAt,
monologue: root.monologue, idle: root.idle,
diff --git a/desktop/companion/Mood.js b/desktop/companion/Mood.js
index f3a4133..584b4d6 100644
--- a/desktop/companion/Mood.js
+++ b/desktop/companion/Mood.js
@@ -19,6 +19,7 @@ var T = {
burstGap: 1500, // a click burst ends after this long without a click
clickHold: 2000, // a click reaction lasts this long after the last click
mockHold: 2500,
+ shoveHold: 1200, // knocked off balance, before she turns mad at the balloon
mockCooldown: 20000,
typingHold: 2000,
waveHold: 3000,
@@ -54,7 +55,8 @@ function pick(s) {
if (since < T.destruct) return st("destruct", "base");
if (since < T.destruct + T.scorched) return st("scorched", "scorched");
if (s.dodging) return st("dodge", "base");
- if (s.shoved) return st("shoved", "shoved");
+ // shovedAt 0 is the instant before Companion.qml stamps it.
+ if (s.shoved) return st("shoved", s.shovedAt && s.now - s.shovedAt >= T.shoveHold ? "mad" : "shoved");
if (s.recording) return st("listen", "listen");
if (s.busy) return st("think", "think");
if (s.now - s.repliedAt < T.waveHold) return st("wave", "wave");
diff --git a/desktop/companion/test_mood.js b/desktop/companion/test_mood.js
index abdb348..90ebdd6 100644
--- a/desktop/companion/test_mood.js
+++ b/desktop/companion/test_mood.js
@@ -24,7 +24,7 @@ const M = new Function(src +
const NOW = 10000000;
// A snapshot with nothing going on, overridden per case.
const calm = over => Object.assign({
- now: NOW, destructAt: 0, dodging: false, shoved: false, recording: false, busy: false,
+ now: NOW, destructAt: 0, dodging: false, shoved: false, shovedAt: 0, recording: false, busy: false,
repliedAt: 0, clicks: { count: 0, at: 0 }, mockAt: 0, typingAt: 0, wakeAt: 0,
monologue: false, idle: 0,
}, over);
@@ -56,8 +56,11 @@ for (let i = 0; i < ladder.length; i++) {
assert.strictEqual(state(all), ladder[i][0], "everything from " + ladder[i][0] + " down");
}
-// Shoved has a frame of its own: knocked off balance, glaring at the balloon.
-assert.deepStrictEqual(M.pick(calm({ shoved: true })), { state: "shoved", frame: "shoved" });
+// Shoved: knocked off balance for a moment, then mad beside the balloon
+// for as long as it stays.
+assert.deepStrictEqual(M.pick(calm({ shoved: true, shovedAt: NOW - 10 })), { state: "shoved", frame: "shoved" });
+assert.deepStrictEqual(M.pick(calm({ shoved: true, shovedAt: NOW - M.T.shoveHold })), { state: "shoved", frame: "mad" });
+assert.strictEqual(frame({ shoved: true, shovedAt: 0 }), "shoved");
// Idle levels and their frames.
assert.deepStrictEqual(M.pick(calm({ idle: 1 })), { state: "bored", frame: "sleepy" });