diff --git a/README.md b/README.md
index 6c5c6e2..9a33cc8 100644
--- a/README.md
+++ b/README.md
@@ -87,7 +87,6 @@ npm run autostart:install # (可選)開機自動啟動
| 左鍵點一下 | 揮手(若有非固定的氣泡,先關閉氣泡) |
| 左鍵拖曳 | 搬家;往左播 running-left、往右播 running-right;放開後位置寫入設定檔 |
| 右鍵 / 系統匣左鍵 | 開啟選單 |
-| 滑鼠靠近(40 px 內) | 她縮到 0.9、往下讓出位置,上方出現選單鈕;離開 56 px 外才復原(Codex 的 hover 版面) |
| 滑鼠靠近 | 盯著游標看(選單開啟「跟著游標看」後才有) |
**選單功能**
@@ -125,7 +124,6 @@ npm run autostart:install # (可選)開機自動啟動
| `SessionEnd` | | 移除該 session | 最後一個結束時 👋 掰掰 |
| (無事件) | 游標移動(追視開啟時) | 16 方向 `look`,覆蓋所有狀態 | |
| (無事件) | 拖曳 | 單次位移 ≥ 4 px 才決定 `running-left` / `running-right` | |
-| (無事件) | 游標靠近 40 px 內 | 動畫不變;人物縮 0.9、顯示選單鈕 | |
規則:
@@ -259,7 +257,7 @@ Claude Code ──hook(stdin JSON)──▶ hook/claude-pet-hook.js ──PO
| `review` | turn 完成且未讀,直到使用者回到該 thread | 直到該 session 下一個動作 |
| `waving` | 只在 first-awake(每隻寵物一次,8 秒) | 相同(記在設定檔 `greetedPetIds`) |
| `jumping` | 只在 `respondToHover`,而整個 app 沒人開啟它 | 只在選單「動作測試」 |
-| hover | 40 px 內進入、56 px 外退出;人物縮 0.9、下移 14 px、上方 24 px 控制鈕、200 ms | 相同;控制鈕是選單 |
+| hover | 40 px 內進入、56 px 外退出;人物縮 0.9、下移 14 px、上方 24 px 控制鈕、200 ms | 未採用——控制鈕的功能就是選單,右鍵已經有了 |
| 追視 | 看 quick chat 文字游標/computer-use 游標,死區 1 px,覆蓋所有狀態 | 沒有對應來源;改為**選配**看滑鼠,預設關 |
| 拖曳方向 | 單次取樣水平位移 ≥ 4 px | 相同 |
| 拖曳放開 | 彈簧回彈(spring 220 / damping 26) | 無(直接停在放開處) |
diff --git a/package.json b/package.json
index 8128dcc..817d4fe 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "claude-pet",
- "version": "0.1.0",
+ "version": "2.0.0",
"description": "Codex Pets 相容的 Claude Code 桌面寵物(spriteVersionNumber 2:9 個動作列 + 16 方向追視)",
"main": "main.js",
"private": true,
diff --git a/renderer/index.html b/renderer/index.html
index e076041..f9a858d 100644
--- a/renderer/index.html
+++ b/renderer/index.html
@@ -9,7 +9,6 @@
diff --git a/renderer/renderer.js b/renderer/renderer.js
index 761fc32..3e5cac8 100644
--- a/renderer/renderer.js
+++ b/renderer/renderer.js
@@ -54,18 +54,12 @@ const EXPIRY = { failed: 3600e3, waiting: 1440 * 60e3, review: 10080 * 60e3 };
const RUNNING_SILENCE = 30 * 60e3;
const IDLE_PRUNE = 30 * 60e3; // idle 的 session 閒置多久後從清單移除(純清理,不影響顯示)
-// hover 版面,數值與 Codex 的 petControlsAppearance 相同
-const HOVER_SCALE = 0.9; // H_:游標靠近時人物縮到 0.9
-const HOVER_OFFSET_Y = 10 + 8 / 2; // hoverOffsetY + hoverControlGap / 2:人物往下移,讓出上方放控制鈕
-const PROXIMITY_ENTER = 40; // proximityEnterDistance:游標離人物多近算「靠近」
-const PROXIMITY_EXIT = 56; // proximityExitDistance:離多遠才算離開(遲滯,避免邊界抖動)
const GREETING_MS = 8000; // first-awake 問候通知的存活時間(Pi = 8 s)
const canvas = document.getElementById("sprite");
const ctx = canvas.getContext("2d", { willReadFrequently: true });
const bubble = document.getElementById("bubble");
const bubbleText = document.getElementById("bubble-text");
-const controls = document.getElementById("controls");
let sheet = null;
let petInfo = null;
@@ -130,7 +124,6 @@ function startAnim(anim, now) {
let bubbleTimer = null;
let bubbleSticky = false;
let ignoringMouse = true;
-let near = false; // 游標是否在人物附近(Codex 的 proximity)
let pressed = null;
let lastReported = "";
@@ -166,10 +159,6 @@ function applyScale(s) {
canvas.height = Math.round(PET_H * s);
canvas.style.width = `${canvas.width}px`;
canvas.style.height = `${canvas.height}px`;
- // 控制鈕底邊 = 縮小後人物的頂端再往上 8 px(hoverControlGap)。
- // 人物以中心縮到 0.9 再往下移 HOVER_OFFSET_Y,頂端會下移 h*(1-0.9)/2 + HOVER_OFFSET_Y。
- const shiftedTop = canvas.height * (1 - HOVER_SCALE) / 2 + HOVER_OFFSET_Y;
- controls.style.bottom = `${8 + canvas.height - shiftedTop + 8}px`;
}
// 量一格的人物輪廓(用來偵測圖檔裡整列被畫小的缺陷)
@@ -563,31 +552,6 @@ function overSprite(x, y) {
}
}
-function overControls(x, y) {
- if (!near) return false;
- const r = controls.getBoundingClientRect();
- return x >= r.left && x <= r.right && y >= r.top && y <= r.bottom;
-}
-
-function distanceToRect(x, y, r) {
- const dx = Math.max(r.left - x, 0, x - r.right);
- const dy = Math.max(r.top - y, 0, y - r.bottom);
- return Math.hypot(dx, dy);
-}
-
-// Codex 的 hover:游標進到離人物 40 px 內就切到 hover 版面——人物縮到 0.9、往下移 14 px、
-// 上方出現 24 px 的控制鈕(200 ms 過渡);離開超過 56 px 才退出。動畫狀態本身不變。
-function updateProximity(x, y) {
- const d = distanceToRect(x, y, canvas.getBoundingClientRect());
- setNear(near ? d <= PROXIMITY_EXIT : d <= PROXIMITY_ENTER);
-}
-
-function setNear(on) {
- if (on === near) return;
- near = on;
- document.body.classList.toggle("near", on);
-}
-
function setIgnore(ignore) {
if (ignore === ignoringMouse) return;
ignoringMouse = ignore;
@@ -605,18 +569,15 @@ window.addEventListener("mousemove", (e) => {
}
return;
}
- updateProximity(e.clientX, e.clientY);
- setIgnore(!(overSprite(e.clientX, e.clientY) || overBubble(e.clientX, e.clientY) || overControls(e.clientX, e.clientY)));
+ setIgnore(!(overSprite(e.clientX, e.clientY) || overBubble(e.clientX, e.clientY)));
});
document.addEventListener("mouseout", (e) => {
if (e.relatedTarget || pressed) return;
- setNear(false);
setIgnore(true);
});
window.addEventListener("mousedown", (e) => {
- if (e.target instanceof Element && e.target.closest("#controls")) return;
if (e.button === 0) {
pressed = { x: e.clientX, y: e.clientY, sx: e.screenX, sy: e.screenY, moved: false };
} else if (e.button === 2) {
@@ -667,11 +628,6 @@ window.pet.on("pet:settings", (st) => {
});
window.pet.on("pet:event", handleEvent);
-document.getElementById("menu-btn").addEventListener("click", (e) => {
- e.stopPropagation();
- window.pet.send("pet:context-menu");
-});
-
// 系統的「減少動態效果」切換時,讓目前的動畫重新開始(Codex 的 effect 也把 reducedMotion 列為相依)
reducedMotionQuery.addEventListener("change", () => { if (player.anim) startAnim(player.anim, performance.now()); });
diff --git a/renderer/style.css b/renderer/style.css
index 783f556..55a8cc3 100644
--- a/renderer/style.css
+++ b/renderer/style.css
@@ -56,53 +56,6 @@ html, body {
#sprite {
display: block;
- /* Codex 的 hover 版面:以中心縮到 0.9 並往下移,200 ms 過渡(transitionDurationMs) */
- transform-origin: 50% 50%;
- transition: transform 200ms ease;
-}
-
-body.near #sprite {
- transform: translateY(14px) scale(0.9);
-}
-
-/* 靠近時氣泡讓開控制鈕 */
-body.near #bubble:not(.hidden) {
- transform: translateY(-22px);
-}
-
-/* 控制鈕:24 px(hoverControlSize),靠近時才出現 */
-#controls {
- position: absolute;
- left: 50%;
- transform: translateX(-50%);
- display: flex;
- gap: 8px;
- opacity: 0;
- pointer-events: none;
- transition: opacity 200ms ease;
-}
-
-body.near #controls {
- opacity: 1;
- pointer-events: auto;
-}
-
-#controls button {
- width: 24px;
- height: 24px;
- padding: 0;
- border: none;
- border-radius: 50%;
- background: rgba(255, 255, 255, 0.97);
- color: #222;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28);
- font-size: 13px;
- line-height: 24px;
- cursor: pointer;
-}
-
-#controls button:hover {
- background: #fff;
}
#sprite.grab {