@hirohsu/user-web-feedback 2.8.8 → 2.8.9

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.
Files changed (34) hide show
  1. package/README.md +953 -953
  2. package/dist/cli.cjs +35073 -22235
  3. package/dist/index.cjs +39829 -26989
  4. package/dist/static/app.js +385 -385
  5. package/dist/static/components/navbar.css +406 -406
  6. package/dist/static/components/navbar.html +49 -49
  7. package/dist/static/components/navbar.js +211 -211
  8. package/dist/static/dashboard.css +495 -495
  9. package/dist/static/dashboard.html +95 -95
  10. package/dist/static/dashboard.js +540 -540
  11. package/dist/static/favicon.svg +27 -27
  12. package/dist/static/index.html +541 -541
  13. package/dist/static/logs.html +376 -376
  14. package/dist/static/logs.js +442 -442
  15. package/dist/static/mcp-settings.html +797 -797
  16. package/dist/static/mcp-settings.js +884 -884
  17. package/dist/static/modules/app-core.js +124 -124
  18. package/dist/static/modules/conversation-panel.js +247 -247
  19. package/dist/static/modules/feedback-handler.js +1420 -1420
  20. package/dist/static/modules/image-handler.js +155 -155
  21. package/dist/static/modules/log-viewer.js +296 -296
  22. package/dist/static/modules/mcp-manager.js +474 -474
  23. package/dist/static/modules/prompt-manager.js +364 -364
  24. package/dist/static/modules/settings-manager.js +299 -299
  25. package/dist/static/modules/socket-manager.js +170 -170
  26. package/dist/static/modules/state-manager.js +352 -352
  27. package/dist/static/modules/timer-controller.js +243 -243
  28. package/dist/static/modules/ui-helpers.js +246 -246
  29. package/dist/static/settings.html +426 -426
  30. package/dist/static/settings.js +767 -767
  31. package/dist/static/style.css +2156 -2156
  32. package/dist/static/terminals.html +357 -357
  33. package/dist/static/terminals.js +321 -321
  34. package/package.json +95 -95
@@ -1,243 +1,243 @@
1
- /**
2
- * timer-controller.js
3
- * 計時器管理模組
4
- * 包含對話超時、關閉倒數、自動回覆等計時器功能
5
- */
6
-
7
- import {
8
- getDialogTimeoutSeconds,
9
- getAutoReplyTimerSeconds,
10
- getAutoReplyTimerRemaining,
11
- setAutoReplyTimerRemaining,
12
- isAutoReplyTimerPaused,
13
- setAutoReplyTimerPaused,
14
- isAutoReplyPausedByFocus,
15
- setAutoReplyPausedByFocus,
16
- getDialogTimeoutInterval,
17
- setDialogTimeoutInterval,
18
- getCloseCountdownInterval,
19
- setCloseCountdownInterval,
20
- getAutoReplyTimerInterval,
21
- setAutoReplyTimerInterval,
22
- getAutoReplyCountdownInterval,
23
- setAutoReplyCountdownInterval,
24
- getAutoReplyWarningTimeout,
25
- setAutoReplyWarningTimeout,
26
- getAutoReplyConfirmationTimeout,
27
- setAutoReplyConfirmationTimeout,
28
- } from "./state-manager.js";
29
-
30
- // 使用動態導入打破循環依賴
31
- let triggerAutoAIReplyFn = null;
32
- async function loadTriggerAutoAIReply() {
33
- if (!triggerAutoAIReplyFn) {
34
- const module = await import("./feedback-handler.js");
35
- triggerAutoAIReplyFn = module.triggerAutoAIReply;
36
- }
37
- return triggerAutoAIReplyFn;
38
- }
39
-
40
- /**
41
- * 停止所有計時器
42
- */
43
- export function stopAllTimers() {
44
- const dialogTimeout = getDialogTimeoutInterval();
45
- if (dialogTimeout) {
46
- clearInterval(dialogTimeout);
47
- setDialogTimeoutInterval(null);
48
- }
49
-
50
- const closeCountdown = getCloseCountdownInterval();
51
- if (closeCountdown) {
52
- clearInterval(closeCountdown);
53
- setCloseCountdownInterval(null);
54
- }
55
- const countdownEl = document.getElementById("close-cd");
56
- if (countdownEl) {
57
- countdownEl.style.display = "none";
58
- }
59
-
60
- const autoReplyTimer = getAutoReplyTimerInterval();
61
- if (autoReplyTimer) {
62
- clearInterval(autoReplyTimer);
63
- setAutoReplyTimerInterval(null);
64
- }
65
-
66
- // 隱藏自動回覆計時器
67
- const autoReplyTimerEl = document.getElementById("auto-reply-timer");
68
- if (autoReplyTimerEl) {
69
- autoReplyTimerEl.classList.remove("active", "paused");
70
- autoReplyTimerEl.style.display = "none";
71
- }
72
-
73
- const confirmationTimeout = getAutoReplyConfirmationTimeout();
74
- if (confirmationTimeout) {
75
- clearInterval(confirmationTimeout);
76
- setAutoReplyConfirmationTimeout(null);
77
- }
78
- }
79
-
80
- /**
81
- * 開始關閉頁面倒數計時(提交成功後 3 秒關閉)
82
- */
83
- export function startCloseCountdown() {
84
- const countdownEl = document.getElementById("close-cd");
85
- if (!countdownEl) {
86
- console.warn("關閉倒數計時器元素 (close-cd) 未找到");
87
- return;
88
- }
89
-
90
- const existingInterval = getCloseCountdownInterval();
91
- if (existingInterval) {
92
- clearInterval(existingInterval);
93
- }
94
-
95
- // 固定 3 秒倒數
96
- let remaining = 3;
97
- countdownEl.style.display = "inline-flex";
98
- countdownEl.textContent = remaining;
99
-
100
- console.log(`開始關閉頁面倒數計時: ${remaining} 秒`);
101
-
102
- const intervalId = setInterval(() => {
103
- remaining--;
104
- countdownEl.textContent = remaining;
105
-
106
- if (remaining <= 0) {
107
- clearInterval(intervalId);
108
- setCloseCountdownInterval(null);
109
- console.log("倒數結束,關閉頁面");
110
- window.close();
111
- }
112
- }, 1000);
113
-
114
- setCloseCountdownInterval(intervalId);
115
- }
116
-
117
- /**
118
- * 取得計時器元素(使用連接狀態區塊內的計時器)
119
- */
120
- function getTimerElements() {
121
- // 使用連接狀態區塊內的計時器
122
- let timerEl = document.getElementById("auto-reply-timer");
123
- let secondsEl = document.getElementById("auto-reply-seconds");
124
-
125
- return { timerEl, secondsEl };
126
- }
127
-
128
- /**
129
- * 開始自動回應倒數計時(300 秒)
130
- */
131
- export function startAutoReplyTimer() {
132
- const { timerEl, secondsEl } = getTimerElements();
133
-
134
- if (!timerEl || !secondsEl) {
135
- console.warn("自動回應計時器元素未找到");
136
- return;
137
- }
138
-
139
- setAutoReplyTimerRemaining(getAutoReplyTimerSeconds());
140
- timerEl.style.display = "inline-flex";
141
- timerEl.classList.add("active");
142
- timerEl.classList.remove("paused");
143
-
144
- const existingInterval = getAutoReplyTimerInterval();
145
- if (existingInterval) {
146
- clearInterval(existingInterval);
147
- }
148
-
149
- const updateCountdown = async () => {
150
- const { secondsEl: currentSecondsEl } = getTimerElements();
151
- if (!currentSecondsEl) return;
152
-
153
- if (isAutoReplyTimerPaused()) {
154
- currentSecondsEl.textContent = getAutoReplyTimerRemaining();
155
- return;
156
- }
157
-
158
- const remaining = getAutoReplyTimerRemaining();
159
- if (remaining > 0) {
160
- currentSecondsEl.textContent = remaining;
161
- setAutoReplyTimerRemaining(remaining - 1);
162
- } else {
163
- const interval = getAutoReplyTimerInterval();
164
- if (interval) {
165
- clearInterval(interval);
166
- setAutoReplyTimerInterval(null);
167
- }
168
- console.log("自動回應時間已到,啟動 AI 回應");
169
- // 動態載入並執行
170
- const triggerFn = await loadTriggerAutoAIReply();
171
- if (triggerFn) triggerFn();
172
- }
173
- };
174
-
175
- secondsEl.textContent = getAutoReplyTimerRemaining();
176
- if (!isAutoReplyTimerPaused()) {
177
- setAutoReplyTimerRemaining(getAutoReplyTimerRemaining() - 1);
178
- }
179
-
180
- const intervalId = setInterval(updateCountdown, 1000);
181
- setAutoReplyTimerInterval(intervalId);
182
- }
183
-
184
- /**
185
- * 暫停自動回覆計時器
186
- * @param {boolean} byFocus - 是否由焦點事件引起的暫停
187
- */
188
- export function pauseAutoReplyTimer(byFocus = false) {
189
- setAutoReplyTimerPaused(true);
190
- if (byFocus) setAutoReplyPausedByFocus(true);
191
-
192
- const { timerEl } = getTimerElements();
193
- if (timerEl) timerEl.classList.add("paused");
194
- }
195
-
196
- /**
197
- * 恢復自動回覆計時器
198
- */
199
- export function resumeAutoReplyTimer() {
200
- setAutoReplyTimerPaused(false);
201
- setAutoReplyPausedByFocus(false);
202
-
203
- const { timerEl } = getTimerElements();
204
- if (timerEl) timerEl.classList.remove("paused");
205
- }
206
-
207
- /**
208
- * 停止自動回覆倒數計時
209
- */
210
- export function stopAutoReplyCountdown() {
211
- const interval = getAutoReplyCountdownInterval();
212
- if (interval) {
213
- clearInterval(interval);
214
- setAutoReplyCountdownInterval(null);
215
- }
216
- }
217
-
218
- /**
219
- * 顯示自動回覆警告(已棄用,改用底部計時器)
220
- * @deprecated
221
- */
222
- export function showAutoReplyWarning(seconds) {
223
- // 不再使用警告彈窗,計時器會常駐在底部
224
- }
225
-
226
- /**
227
- * 隱藏自動回覆警告(已棄用)
228
- * @deprecated
229
- */
230
- export function hideAutoReplyWarning() {
231
- // 不再使用警告彈窗
232
- }
233
-
234
- export default {
235
- stopAllTimers,
236
- startCloseCountdown,
237
- startAutoReplyTimer,
238
- pauseAutoReplyTimer,
239
- resumeAutoReplyTimer,
240
- stopAutoReplyCountdown,
241
- showAutoReplyWarning,
242
- hideAutoReplyWarning,
243
- };
1
+ /**
2
+ * timer-controller.js
3
+ * 計時器管理模組
4
+ * 包含對話超時、關閉倒數、自動回覆等計時器功能
5
+ */
6
+
7
+ import {
8
+ getDialogTimeoutSeconds,
9
+ getAutoReplyTimerSeconds,
10
+ getAutoReplyTimerRemaining,
11
+ setAutoReplyTimerRemaining,
12
+ isAutoReplyTimerPaused,
13
+ setAutoReplyTimerPaused,
14
+ isAutoReplyPausedByFocus,
15
+ setAutoReplyPausedByFocus,
16
+ getDialogTimeoutInterval,
17
+ setDialogTimeoutInterval,
18
+ getCloseCountdownInterval,
19
+ setCloseCountdownInterval,
20
+ getAutoReplyTimerInterval,
21
+ setAutoReplyTimerInterval,
22
+ getAutoReplyCountdownInterval,
23
+ setAutoReplyCountdownInterval,
24
+ getAutoReplyWarningTimeout,
25
+ setAutoReplyWarningTimeout,
26
+ getAutoReplyConfirmationTimeout,
27
+ setAutoReplyConfirmationTimeout,
28
+ } from "./state-manager.js";
29
+
30
+ // 使用動態導入打破循環依賴
31
+ let triggerAutoAIReplyFn = null;
32
+ async function loadTriggerAutoAIReply() {
33
+ if (!triggerAutoAIReplyFn) {
34
+ const module = await import("./feedback-handler.js");
35
+ triggerAutoAIReplyFn = module.triggerAutoAIReply;
36
+ }
37
+ return triggerAutoAIReplyFn;
38
+ }
39
+
40
+ /**
41
+ * 停止所有計時器
42
+ */
43
+ export function stopAllTimers() {
44
+ const dialogTimeout = getDialogTimeoutInterval();
45
+ if (dialogTimeout) {
46
+ clearInterval(dialogTimeout);
47
+ setDialogTimeoutInterval(null);
48
+ }
49
+
50
+ const closeCountdown = getCloseCountdownInterval();
51
+ if (closeCountdown) {
52
+ clearInterval(closeCountdown);
53
+ setCloseCountdownInterval(null);
54
+ }
55
+ const countdownEl = document.getElementById("close-cd");
56
+ if (countdownEl) {
57
+ countdownEl.style.display = "none";
58
+ }
59
+
60
+ const autoReplyTimer = getAutoReplyTimerInterval();
61
+ if (autoReplyTimer) {
62
+ clearInterval(autoReplyTimer);
63
+ setAutoReplyTimerInterval(null);
64
+ }
65
+
66
+ // 隱藏自動回覆計時器
67
+ const autoReplyTimerEl = document.getElementById("auto-reply-timer");
68
+ if (autoReplyTimerEl) {
69
+ autoReplyTimerEl.classList.remove("active", "paused");
70
+ autoReplyTimerEl.style.display = "none";
71
+ }
72
+
73
+ const confirmationTimeout = getAutoReplyConfirmationTimeout();
74
+ if (confirmationTimeout) {
75
+ clearInterval(confirmationTimeout);
76
+ setAutoReplyConfirmationTimeout(null);
77
+ }
78
+ }
79
+
80
+ /**
81
+ * 開始關閉頁面倒數計時(提交成功後 3 秒關閉)
82
+ */
83
+ export function startCloseCountdown() {
84
+ const countdownEl = document.getElementById("close-cd");
85
+ if (!countdownEl) {
86
+ console.warn("關閉倒數計時器元素 (close-cd) 未找到");
87
+ return;
88
+ }
89
+
90
+ const existingInterval = getCloseCountdownInterval();
91
+ if (existingInterval) {
92
+ clearInterval(existingInterval);
93
+ }
94
+
95
+ // 固定 3 秒倒數
96
+ let remaining = 3;
97
+ countdownEl.style.display = "inline-flex";
98
+ countdownEl.textContent = remaining;
99
+
100
+ console.log(`開始關閉頁面倒數計時: ${remaining} 秒`);
101
+
102
+ const intervalId = setInterval(() => {
103
+ remaining--;
104
+ countdownEl.textContent = remaining;
105
+
106
+ if (remaining <= 0) {
107
+ clearInterval(intervalId);
108
+ setCloseCountdownInterval(null);
109
+ console.log("倒數結束,關閉頁面");
110
+ window.close();
111
+ }
112
+ }, 1000);
113
+
114
+ setCloseCountdownInterval(intervalId);
115
+ }
116
+
117
+ /**
118
+ * 取得計時器元素(使用連接狀態區塊內的計時器)
119
+ */
120
+ function getTimerElements() {
121
+ // 使用連接狀態區塊內的計時器
122
+ let timerEl = document.getElementById("auto-reply-timer");
123
+ let secondsEl = document.getElementById("auto-reply-seconds");
124
+
125
+ return { timerEl, secondsEl };
126
+ }
127
+
128
+ /**
129
+ * 開始自動回應倒數計時(300 秒)
130
+ */
131
+ export function startAutoReplyTimer() {
132
+ const { timerEl, secondsEl } = getTimerElements();
133
+
134
+ if (!timerEl || !secondsEl) {
135
+ console.warn("自動回應計時器元素未找到");
136
+ return;
137
+ }
138
+
139
+ setAutoReplyTimerRemaining(getAutoReplyTimerSeconds());
140
+ timerEl.style.display = "inline-flex";
141
+ timerEl.classList.add("active");
142
+ timerEl.classList.remove("paused");
143
+
144
+ const existingInterval = getAutoReplyTimerInterval();
145
+ if (existingInterval) {
146
+ clearInterval(existingInterval);
147
+ }
148
+
149
+ const updateCountdown = async () => {
150
+ const { secondsEl: currentSecondsEl } = getTimerElements();
151
+ if (!currentSecondsEl) return;
152
+
153
+ if (isAutoReplyTimerPaused()) {
154
+ currentSecondsEl.textContent = getAutoReplyTimerRemaining();
155
+ return;
156
+ }
157
+
158
+ const remaining = getAutoReplyTimerRemaining();
159
+ if (remaining > 0) {
160
+ currentSecondsEl.textContent = remaining;
161
+ setAutoReplyTimerRemaining(remaining - 1);
162
+ } else {
163
+ const interval = getAutoReplyTimerInterval();
164
+ if (interval) {
165
+ clearInterval(interval);
166
+ setAutoReplyTimerInterval(null);
167
+ }
168
+ console.log("自動回應時間已到,啟動 AI 回應");
169
+ // 動態載入並執行
170
+ const triggerFn = await loadTriggerAutoAIReply();
171
+ if (triggerFn) triggerFn();
172
+ }
173
+ };
174
+
175
+ secondsEl.textContent = getAutoReplyTimerRemaining();
176
+ if (!isAutoReplyTimerPaused()) {
177
+ setAutoReplyTimerRemaining(getAutoReplyTimerRemaining() - 1);
178
+ }
179
+
180
+ const intervalId = setInterval(updateCountdown, 1000);
181
+ setAutoReplyTimerInterval(intervalId);
182
+ }
183
+
184
+ /**
185
+ * 暫停自動回覆計時器
186
+ * @param {boolean} byFocus - 是否由焦點事件引起的暫停
187
+ */
188
+ export function pauseAutoReplyTimer(byFocus = false) {
189
+ setAutoReplyTimerPaused(true);
190
+ if (byFocus) setAutoReplyPausedByFocus(true);
191
+
192
+ const { timerEl } = getTimerElements();
193
+ if (timerEl) timerEl.classList.add("paused");
194
+ }
195
+
196
+ /**
197
+ * 恢復自動回覆計時器
198
+ */
199
+ export function resumeAutoReplyTimer() {
200
+ setAutoReplyTimerPaused(false);
201
+ setAutoReplyPausedByFocus(false);
202
+
203
+ const { timerEl } = getTimerElements();
204
+ if (timerEl) timerEl.classList.remove("paused");
205
+ }
206
+
207
+ /**
208
+ * 停止自動回覆倒數計時
209
+ */
210
+ export function stopAutoReplyCountdown() {
211
+ const interval = getAutoReplyCountdownInterval();
212
+ if (interval) {
213
+ clearInterval(interval);
214
+ setAutoReplyCountdownInterval(null);
215
+ }
216
+ }
217
+
218
+ /**
219
+ * 顯示自動回覆警告(已棄用,改用底部計時器)
220
+ * @deprecated
221
+ */
222
+ export function showAutoReplyWarning(seconds) {
223
+ // 不再使用警告彈窗,計時器會常駐在底部
224
+ }
225
+
226
+ /**
227
+ * 隱藏自動回覆警告(已棄用)
228
+ * @deprecated
229
+ */
230
+ export function hideAutoReplyWarning() {
231
+ // 不再使用警告彈窗
232
+ }
233
+
234
+ export default {
235
+ stopAllTimers,
236
+ startCloseCountdown,
237
+ startAutoReplyTimer,
238
+ pauseAutoReplyTimer,
239
+ resumeAutoReplyTimer,
240
+ stopAutoReplyCountdown,
241
+ showAutoReplyWarning,
242
+ hideAutoReplyWarning,
243
+ };