diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-29 10:12:17 +0100 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-29 10:12:17 +0100 |
| commit | 0a7db3b48cce5f064c20f280e345a8bf1feb5ecb (patch) | |
| tree | eaf9c4be1a832893acf327019ef71a352d9d6647 /desktop/companion/Mood.js | |
| parent | 28beb8a9600b6e74cab454401cc94c664d90bfe5 (diff) | |
| download | quickshell-0a7db3b48cce5f064c20f280e345a8bf1feb5ecb.tar.gz quickshell-0a7db3b48cce5f064c20f280e345a8bf1feb5ecb.zip | |
companion: remove from the tree, archived as tag archive/companion
The chibi 2B companion is retired for now. Its last state is kept in the
signed tag archive/companion (the commit before this one), so it can be
revisited with `git checkout archive/companion`; hypr-theme carries a tag
of the same name for its compositor hooks (typing/delete events and the
SUPER+\ bind).
Removed with it, since nothing else used them: the Companion, phrases
and artists settings pages, the five companion prefs in Prefs.qml and
Prefs.ready, the wallpaper heart (Admired.qml's list), the assistant's
replied() signal and cardTop, and the keybinds reminder's name for the
code:49 bind. The design specs and plans under docs/ stay as history.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'desktop/companion/Mood.js')
| -rw-r--r-- | desktop/companion/Mood.js | 123 |
1 files changed, 0 insertions, 123 deletions
diff --git a/desktop/companion/Mood.js b/desktop/companion/Mood.js deleted file mode 100644 index be514d7..0000000 --- a/desktop/companion/Mood.js +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (C) 2026 Danilo M. <danix@danix.xyz> -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 2 as -// published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -.pragma library - -// Which state the companion is in, from a snapshot of her inputs. Pure, so -// test_mood.js drives it with plain objects and a fake clock. Companion.qml -// owns the inputs and the timers; this only decides. Times in milliseconds. - -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: 500, // knocked off balance, before she turns mad at the balloon - mockCooldown: 20000, - typingHold: 2000, - waveHold: 3000, - singHold: 4000, // her singing reaction to the headphones connecting - djHold: 6000, // behind the decks when a track starts or changes - wakeHold: 1500, // the stretch after idling - lineCooldown: 30000, - monologueCooldown: 3600000, - destruct: 1000, // the glow and the flash; the sprite is hidden under it - scorched: 3000, - goodbye: 2000, // waving goodbye with a line, enough to read it - goodbyeSilent: 1000, // waving goodbye with nothing to read - admireLook: 1500, // turned to the wallpaper, before the blush - admireBlush: 3000, - admireCooldown: 180000, -}; - -function st(state, frame) { return { state: state, frame: frame }; } - -// The burst after a click at now. -function click(prev, now) { - if (prev.count > 0 && now - prev.at <= T.burstGap) return { count: prev.count + 1, at: now }; - return { count: 1, at: now }; -} - -// Click 1 smiles; 2 to 6 blush harder, in three steps. The 7th is the -// self-destruct, which Companion.qml starts rather than shows. -function clickFrame(count) { - if (count <= 1) return "smile"; - if (count <= 3) return "blush1"; - if (count <= 5) return "blush2"; - return "blush3"; -} - -// The spec's priority table, top to bottom: the first that applies wins. -// idle is 0 awake, 1 bored, 2 yawning, 3 lying down. -function pick(s) { - // The user hid her: the goodbye outranks whatever she was doing. The - // frame here is a placeholder; Companion.qml cycles the wave frames. - if (s.leaving) return st("bye", "wave"); - const since = s.destructAt ? s.now - s.destructAt : Infinity; - 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"); - // 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"); - if (s.now - s.singAt < T.singHold) return st("sing", "sing"); - if (s.now - s.djAt < T.djHold) return st("dj", "dj"); - if (s.clicks.count > 0 && s.now - s.clicks.at < T.clickHold) - return st("clicks", clickFrame(s.clicks.count)); - if (s.now - s.admireAt < T.admireLook + T.admireBlush) - return st("admire", s.now - s.admireAt < T.admireLook ? "watch" : "blush3"); - if (s.now - s.mockAt < T.mockHold) - return st("mock", s.now - s.mockAt < T.mockHold / 2 ? "point" : "smirk"); - if (s.now - s.typingAt < T.typingHold) return st("watch", "watch"); - if (s.now - s.wakeAt < T.wakeHold) return st("stretch", "stretch"); - if (s.monologue) return st("muse", "muse"); - if (s.idle >= 3) return st("lying", "lying"); - if (s.idle === 2) return st("yawn", "yawn"); - // Music turns boredom into a groove picked by Companion.qml; the - // deeper idle stages still win, so music does not keep her awake. - if (s.idle === 1) return s.music ? st("groove", s.groove || "whistle") : st("bored", "sleepy"); - return st("base", "base"); -} - -// The self-destruct takes the skirt off once the flash is over, for the -// scorched moment and skirtless ms after it (Prefs.companionSkirtless), -// or with 0 until she is shown again, which sets destructAt back to 0 and -// also restores it early. -function outfit(destructAt, now, skirtless) { - if (!destructAt) return "dress"; - const since = now - destructAt; - if (since < T.destruct) return "dress"; - return skirtless === 0 || since < T.destruct + T.scorched + skirtless ? "leotard" : "dress"; -} - -function mockAllowed(lastMockAt, now) { return now - lastMockAt >= T.mockCooldown; } - -function admireAllowed(lastAt, now) { return now - lastAt >= T.admireCooldown; } - -function canSpeak(lastLineAt, now) { return now - lastLineAt >= T.lineCooldown; } - -// Seated on the assistant's tall card (Companion.qml, sitting): the frames -// with a sitting version show it, everything else the plain sit. Typing's -// watch becomes the lean over the card, reading. -var SEAT = { - watch: "sit-read", point: "sit-point", smirk: "sit-smirk", think: "sit-think", - listen: "sit-listen", wave: "sit-wave", "wave-l": "sit-wave", "wave-r": "sit-wave", -}; -function seatFrame(frame) { return SEAT[frame] || "sit"; } - -// Whether the opening monologue plays: a chance per trigger, and never -// twice within the hour. roll is Math.random(), passed in for the test. -function monologue(trigger, lastAt, now, roll) { - if (now - lastAt < T.monologueCooldown) return false; - const chance = trigger === "bored" ? 1 / 4 : trigger === "shown" ? 1 / 3 : 0; - return roll < chance; -} |
