@hirohsu/user-web-feedback 2.8.9 → 2.8.11
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.
- package/README.md +953 -953
- package/dist/cli.cjs +33309 -46041
- package/dist/index.cjs +35773 -48507
- package/dist/static/app.js +385 -385
- package/dist/static/components/navbar.css +406 -406
- package/dist/static/components/navbar.html +49 -49
- package/dist/static/components/navbar.js +211 -211
- package/dist/static/dashboard.css +495 -495
- package/dist/static/dashboard.html +95 -95
- package/dist/static/dashboard.js +540 -540
- package/dist/static/favicon.svg +27 -27
- package/dist/static/index.html +541 -541
- package/dist/static/logs.html +376 -376
- package/dist/static/logs.js +442 -442
- package/dist/static/mcp-settings.html +797 -797
- package/dist/static/mcp-settings.js +884 -884
- package/dist/static/modules/app-core.js +124 -124
- package/dist/static/modules/conversation-panel.js +247 -247
- package/dist/static/modules/feedback-handler.js +1420 -1420
- package/dist/static/modules/image-handler.js +155 -155
- package/dist/static/modules/log-viewer.js +296 -296
- package/dist/static/modules/mcp-manager.js +474 -474
- package/dist/static/modules/prompt-manager.js +364 -364
- package/dist/static/modules/settings-manager.js +299 -299
- package/dist/static/modules/socket-manager.js +170 -170
- package/dist/static/modules/state-manager.js +352 -352
- package/dist/static/modules/timer-controller.js +243 -243
- package/dist/static/modules/ui-helpers.js +246 -246
- package/dist/static/settings.html +426 -426
- package/dist/static/settings.js +767 -767
- package/dist/static/style.css +2156 -2156
- package/dist/static/terminals.html +357 -357
- package/dist/static/terminals.js +321 -321
- package/package.json +95 -95
|
@@ -1,155 +1,155 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* image-handler.js
|
|
3
|
-
* 圖片處理模組
|
|
4
|
-
* 包含圖片上傳、預覽、移除等功能
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
getCurrentImages,
|
|
9
|
-
addImage,
|
|
10
|
-
removeImageAt,
|
|
11
|
-
clearImages as clearImageState,
|
|
12
|
-
} from "./state-manager.js";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* 處理檔案選擇事件
|
|
16
|
-
* @param {Event} e - 檔案選擇事件
|
|
17
|
-
*/
|
|
18
|
-
export function handleFileSelect(e) {
|
|
19
|
-
handleFileDrop(e.target.files);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* 處理檔案拖放
|
|
24
|
-
* @param {FileList} files - 檔案列表
|
|
25
|
-
*/
|
|
26
|
-
export function handleFileDrop(files) {
|
|
27
|
-
Array.from(files).forEach((file) => {
|
|
28
|
-
if (file.type.startsWith("image/")) {
|
|
29
|
-
readImageFile(file);
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* 處理貼上事件
|
|
36
|
-
* @param {ClipboardEvent} e - 貼上事件
|
|
37
|
-
*/
|
|
38
|
-
export function handlePaste(e) {
|
|
39
|
-
const items = e.clipboardData.items;
|
|
40
|
-
|
|
41
|
-
for (let item of items) {
|
|
42
|
-
if (item.type.startsWith("image/")) {
|
|
43
|
-
const file = item.getAsFile();
|
|
44
|
-
readImageFile(file);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* 讀取圖片檔案
|
|
51
|
-
* @param {File} file - 圖片檔案
|
|
52
|
-
*/
|
|
53
|
-
export function readImageFile(file) {
|
|
54
|
-
const reader = new FileReader();
|
|
55
|
-
|
|
56
|
-
reader.onload = (e) => {
|
|
57
|
-
const imageData = {
|
|
58
|
-
name: file.name,
|
|
59
|
-
data: e.target.result.split(",")[1],
|
|
60
|
-
size: file.size,
|
|
61
|
-
type: file.type,
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
addImage(imageData);
|
|
65
|
-
const currentImages = getCurrentImages();
|
|
66
|
-
addImagePreview(e.target.result, currentImages.length - 1);
|
|
67
|
-
updateImageCount();
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
reader.readAsDataURL(file);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* 新增圖片預覽
|
|
75
|
-
* @param {string} dataUrl - 圖片 Data URL
|
|
76
|
-
* @param {number} index - 圖片索引
|
|
77
|
-
*/
|
|
78
|
-
export function addImagePreview(dataUrl, index) {
|
|
79
|
-
const container = document.getElementById("imagePreviewContainer");
|
|
80
|
-
const dropZone = document.getElementById("imageDropZone");
|
|
81
|
-
const currentImages = getCurrentImages();
|
|
82
|
-
|
|
83
|
-
if (currentImages.length > 0) {
|
|
84
|
-
dropZone.style.display = "none";
|
|
85
|
-
container.style.display = "flex";
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const preview = document.createElement("div");
|
|
89
|
-
preview.className = "image-preview";
|
|
90
|
-
preview.innerHTML = `
|
|
91
|
-
<img src="${dataUrl}" alt="Preview">
|
|
92
|
-
<button class="image-preview-remove" onclick="removeImage(${index})">✖</button>
|
|
93
|
-
`;
|
|
94
|
-
|
|
95
|
-
container.appendChild(preview);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* 移除圖片
|
|
100
|
-
* @param {number} index - 圖片索引
|
|
101
|
-
*/
|
|
102
|
-
export function removeImage(index) {
|
|
103
|
-
removeImageAt(index);
|
|
104
|
-
|
|
105
|
-
const container = document.getElementById("imagePreviewContainer");
|
|
106
|
-
container.innerHTML = "";
|
|
107
|
-
|
|
108
|
-
const currentImages = getCurrentImages();
|
|
109
|
-
currentImages.forEach((img, i) => {
|
|
110
|
-
const dataUrl = `data:${img.type};base64,${img.data}`;
|
|
111
|
-
addImagePreview(dataUrl, i);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
updateImageCount();
|
|
115
|
-
|
|
116
|
-
if (currentImages.length === 0) {
|
|
117
|
-
document.getElementById("imageDropZone").style.display = "flex";
|
|
118
|
-
container.style.display = "none";
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* 清除所有圖片
|
|
124
|
-
*/
|
|
125
|
-
export function clearImages() {
|
|
126
|
-
clearImageState();
|
|
127
|
-
document.getElementById("imagePreviewContainer").innerHTML = "";
|
|
128
|
-
document.getElementById("imageDropZone").style.display = "flex";
|
|
129
|
-
document.getElementById("imagePreviewContainer").style.display = "none";
|
|
130
|
-
updateImageCount();
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* 更新圖片數量顯示
|
|
135
|
-
*/
|
|
136
|
-
export function updateImageCount() {
|
|
137
|
-
const countEl = document.getElementById("imageCount");
|
|
138
|
-
if (countEl) {
|
|
139
|
-
countEl.textContent = getCurrentImages().length;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// 暴露到 window 供 HTML onclick 使用
|
|
144
|
-
window.removeImage = removeImage;
|
|
145
|
-
|
|
146
|
-
export default {
|
|
147
|
-
handleFileSelect,
|
|
148
|
-
handleFileDrop,
|
|
149
|
-
handlePaste,
|
|
150
|
-
readImageFile,
|
|
151
|
-
addImagePreview,
|
|
152
|
-
removeImage,
|
|
153
|
-
clearImages,
|
|
154
|
-
updateImageCount,
|
|
155
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* image-handler.js
|
|
3
|
+
* 圖片處理模組
|
|
4
|
+
* 包含圖片上傳、預覽、移除等功能
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
getCurrentImages,
|
|
9
|
+
addImage,
|
|
10
|
+
removeImageAt,
|
|
11
|
+
clearImages as clearImageState,
|
|
12
|
+
} from "./state-manager.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 處理檔案選擇事件
|
|
16
|
+
* @param {Event} e - 檔案選擇事件
|
|
17
|
+
*/
|
|
18
|
+
export function handleFileSelect(e) {
|
|
19
|
+
handleFileDrop(e.target.files);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 處理檔案拖放
|
|
24
|
+
* @param {FileList} files - 檔案列表
|
|
25
|
+
*/
|
|
26
|
+
export function handleFileDrop(files) {
|
|
27
|
+
Array.from(files).forEach((file) => {
|
|
28
|
+
if (file.type.startsWith("image/")) {
|
|
29
|
+
readImageFile(file);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 處理貼上事件
|
|
36
|
+
* @param {ClipboardEvent} e - 貼上事件
|
|
37
|
+
*/
|
|
38
|
+
export function handlePaste(e) {
|
|
39
|
+
const items = e.clipboardData.items;
|
|
40
|
+
|
|
41
|
+
for (let item of items) {
|
|
42
|
+
if (item.type.startsWith("image/")) {
|
|
43
|
+
const file = item.getAsFile();
|
|
44
|
+
readImageFile(file);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 讀取圖片檔案
|
|
51
|
+
* @param {File} file - 圖片檔案
|
|
52
|
+
*/
|
|
53
|
+
export function readImageFile(file) {
|
|
54
|
+
const reader = new FileReader();
|
|
55
|
+
|
|
56
|
+
reader.onload = (e) => {
|
|
57
|
+
const imageData = {
|
|
58
|
+
name: file.name,
|
|
59
|
+
data: e.target.result.split(",")[1],
|
|
60
|
+
size: file.size,
|
|
61
|
+
type: file.type,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
addImage(imageData);
|
|
65
|
+
const currentImages = getCurrentImages();
|
|
66
|
+
addImagePreview(e.target.result, currentImages.length - 1);
|
|
67
|
+
updateImageCount();
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
reader.readAsDataURL(file);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 新增圖片預覽
|
|
75
|
+
* @param {string} dataUrl - 圖片 Data URL
|
|
76
|
+
* @param {number} index - 圖片索引
|
|
77
|
+
*/
|
|
78
|
+
export function addImagePreview(dataUrl, index) {
|
|
79
|
+
const container = document.getElementById("imagePreviewContainer");
|
|
80
|
+
const dropZone = document.getElementById("imageDropZone");
|
|
81
|
+
const currentImages = getCurrentImages();
|
|
82
|
+
|
|
83
|
+
if (currentImages.length > 0) {
|
|
84
|
+
dropZone.style.display = "none";
|
|
85
|
+
container.style.display = "flex";
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const preview = document.createElement("div");
|
|
89
|
+
preview.className = "image-preview";
|
|
90
|
+
preview.innerHTML = `
|
|
91
|
+
<img src="${dataUrl}" alt="Preview">
|
|
92
|
+
<button class="image-preview-remove" onclick="removeImage(${index})">✖</button>
|
|
93
|
+
`;
|
|
94
|
+
|
|
95
|
+
container.appendChild(preview);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 移除圖片
|
|
100
|
+
* @param {number} index - 圖片索引
|
|
101
|
+
*/
|
|
102
|
+
export function removeImage(index) {
|
|
103
|
+
removeImageAt(index);
|
|
104
|
+
|
|
105
|
+
const container = document.getElementById("imagePreviewContainer");
|
|
106
|
+
container.innerHTML = "";
|
|
107
|
+
|
|
108
|
+
const currentImages = getCurrentImages();
|
|
109
|
+
currentImages.forEach((img, i) => {
|
|
110
|
+
const dataUrl = `data:${img.type};base64,${img.data}`;
|
|
111
|
+
addImagePreview(dataUrl, i);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
updateImageCount();
|
|
115
|
+
|
|
116
|
+
if (currentImages.length === 0) {
|
|
117
|
+
document.getElementById("imageDropZone").style.display = "flex";
|
|
118
|
+
container.style.display = "none";
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* 清除所有圖片
|
|
124
|
+
*/
|
|
125
|
+
export function clearImages() {
|
|
126
|
+
clearImageState();
|
|
127
|
+
document.getElementById("imagePreviewContainer").innerHTML = "";
|
|
128
|
+
document.getElementById("imageDropZone").style.display = "flex";
|
|
129
|
+
document.getElementById("imagePreviewContainer").style.display = "none";
|
|
130
|
+
updateImageCount();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* 更新圖片數量顯示
|
|
135
|
+
*/
|
|
136
|
+
export function updateImageCount() {
|
|
137
|
+
const countEl = document.getElementById("imageCount");
|
|
138
|
+
if (countEl) {
|
|
139
|
+
countEl.textContent = getCurrentImages().length;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// 暴露到 window 供 HTML onclick 使用
|
|
144
|
+
window.removeImage = removeImage;
|
|
145
|
+
|
|
146
|
+
export default {
|
|
147
|
+
handleFileSelect,
|
|
148
|
+
handleFileDrop,
|
|
149
|
+
handlePaste,
|
|
150
|
+
readImageFile,
|
|
151
|
+
addImagePreview,
|
|
152
|
+
removeImage,
|
|
153
|
+
clearImages,
|
|
154
|
+
updateImageCount,
|
|
155
|
+
};
|