(function () { 'use strict'; const petEl = document.getElementById('pet'); const chest = document.getElementById('chest'); const ctxMenu = document.getElementById('context-menu'); const invoke = window.__TAURI__?.core?.invoke; let dragStartX = 0, dragStartY = 0; let pressTimer = null; let isDragging = false; const CHEST_HOLD_MS = 5000; let chestTimer = null; // ── 右键菜单 ────────────────────────────── petEl.addEventListener('contextmenu', function (e) { e.preventDefault(); const x = Math.min(e.clientX, window.innerWidth - 130); const y = Math.min(e.clientY, window.innerHeight - 100); ctxMenu.style.left = x + 'px'; ctxMenu.style.top = y + 'px'; ctxMenu.style.display = 'block'; }); document.addEventListener('click', function (e) { if (!ctxMenu.contains(e.target)) ctxMenu.style.display = 'none'; }); document.addEventListener('keydown', function (e) { if (e.key === 'Escape') ctxMenu.style.display = 'none'; }); ctxMenu.addEventListener('click', function (e) { const item = e.target.closest('.item'); if (!item) return; const action = item.dataset.action; ctxMenu.style.display = 'none'; if (action === 'settings') invoke?.('open_settings'); else if (action === 'quit') { try { invoke?.('quit_app'); } catch (_) { window.close(); } } }); // ── 点击 / 长按 / 拖拽 ─────────────────── petEl.addEventListener('mousedown', function (e) { if (window.__petPerched) return; // 站手跟随中:窗口由 Rust 驱动,禁用原生拖拽 dragStartX = e.clientX; dragStartY = e.clientY; isDragging = false; pressTimer = setTimeout(() => { localReact('pet'); if (backendEnabled()) notifyInteract('pet', {}); }, 1500); }); petEl.addEventListener('mousemove', function (e) { const dx = e.clientX - dragStartX; const dy = e.clientY - dragStartY; if (Math.abs(dx) > 4 || Math.abs(dy) > 4) { isDragging = true; clearTimeout(pressTimer); notifyDragStart(); } }); petEl.addEventListener('mouseup', function (e) { clearTimeout(pressTimer); if (!isDragging) { localReact('click'); // 未登录 / 离线时不打后端,避免只剩「打卡失败」噪音,仅保留本地互动反馈。 if (backendEnabled()) notifyInteract('click', {}); } else { notifyDragEnd(); } }); // ── 胸部悬停 5s → 站手跟随 ──────────────── if (chest) { chest.addEventListener('mouseenter', function () { if (window.__petPerched) return; clearChestTimer(); chestTimer = setTimeout(function () { chestTimer = null; if (window.__petPerched) return; window.__petPerched = true; // 乐观置位;Rust 会回发 pet://perch 确认 try { window.cfcHost.startPerch(); } catch (_) { /* noop */ } try { window.cfcPetAPI.showBubble('飞到你手上~', 2000); } catch (_) { /* noop */ } }, CHEST_HOLD_MS); }); // 悬停未满 5s 就移开 → 取消;站手后窗口跟随光标会使指针移出胸部,此处仅为清理(无害) chest.addEventListener('mouseleave', clearChestTimer); } function clearChestTimer() { if (chestTimer) { clearTimeout(chestTimer); chestTimer = null; } } // 本地即时反馈:不依赖后端也能看到宠物对点击的响应。 function localReact(kind) { try { if (window.cfcPetAPI && window.cfcPetAPI.react) window.cfcPetAPI.react(kind); } catch (_) { /* noop */ } } // 是否已连后端(有令牌)。默认允许,bridge 拉到设置后按 hasToken 修正。 function backendEnabled() { return window.__petHasToken !== false; } function notifyInteract(action, data) { try { window.cfcHost.onInteract(action, JSON.stringify(data)); } catch (err) { console.log('[interaction]', action, data); } } function notifyDragStart() { try { window.cfcHost.onDragStart(); } catch (e) { /* noop */ } } function notifyDragEnd() { try { window.cfcHost.onDragEnd(); } catch (e) { /* noop */ } } })();