vzcode 2.15.0 → 2.17.0
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/dist/assets/{bindings_wasm_bg-9w8E-TmY.wasm → bindings_wasm_bg-D9vNLG9F.wasm} +0 -0
- package/dist/assets/buildWorker-DL4wXpRr.js +695 -0
- package/dist/assets/index-BiPmUreW.js +474 -0
- package/dist/assets/{index-DLm5FQ0E.css → index-BvGPtSrr.css} +1 -1
- package/dist/assets/worker-RJ-cjbld.js +327 -0
- package/dist/index.html +2 -2
- package/dist/server/aiChatHandler/chatOperations.js +168 -35
- package/dist/server/aiChatHandler/index.js +11 -30
- package/dist/server/aiChatHandler/llmStreaming.js +105 -118
- package/package.json +11 -11
- package/src/client/AIAssist/AIAssistWidget/index.tsx +12 -1
- package/src/client/App/useShareDB.ts +1 -1
- package/src/client/CodeEditor/index.tsx +9 -10
- package/src/client/VZCodeContext/types.ts +3 -1
- package/src/client/VZCodeContext/useVZCodeState.ts +7 -5
- package/src/client/VZRight.tsx +10 -2
- package/src/client/VZSidebar/AIChat/ChatInput.tsx +1 -7
- package/src/client/VZSidebar/AIChat/DiffView.scss +1 -0
- package/src/client/VZSidebar/AIChat/DiffView.tsx +72 -29
- package/src/client/VZSidebar/AIChat/FileEditingIndicator.tsx +89 -0
- package/src/client/VZSidebar/AIChat/IndividualFileDiff.tsx +86 -0
- package/src/client/VZSidebar/AIChat/JumpToLatestButton.tsx +64 -0
- package/src/client/VZSidebar/AIChat/Message.tsx +124 -56
- package/src/client/VZSidebar/AIChat/MessageList.tsx +155 -114
- package/src/client/VZSidebar/AIChat/ThinkingScratchpad.tsx +4 -118
- package/src/client/VZSidebar/AIChat/index.tsx +59 -19
- package/src/client/VZSidebar/AIChat/styles.scss +190 -43
- package/src/client/VZSidebar/Item.tsx +2 -2
- package/src/client/VZSidebar/Search.tsx +13 -6
- package/src/client/VZSidebar/VisualEditor/VisualEditor.tsx +39 -23
- package/src/client/VZSidebar/VisualEditor/utils.ts +1 -1
- package/src/client/VZSidebar/index.tsx +12 -10
- package/src/client/VZSidebar/useDragAndDrop.tsx +225 -214
- package/src/client/featureFlags.ts +3 -0
- package/src/client/hooks/useAutoScroll.ts +328 -0
- package/src/client/tabsSearchParameters.ts +1 -17
- package/src/client/useFileCRUD.ts +5 -2
- package/src/client/useKeyboardShortcuts.ts +7 -0
- package/src/client/useOpenDirectories.ts +2 -1
- package/src/client/usePrettier/index.ts +1 -1
- package/src/client/useURLSync.ts +1 -0
- package/src/client/utils/scrollUtils.ts +170 -0
- package/src/client/vzReducer/searchReducer.ts +6 -3
- package/src/server/aiChatHandler/chatOperations.ts +224 -43
- package/src/server/aiChatHandler/index.ts +8 -48
- package/src/server/aiChatHandler/llmStreaming.ts +149 -170
- package/src/types.ts +81 -1
- package/dist/assets/buildWorker-Bi6wsfQk.js +0 -695
- package/dist/assets/index-BpUpNto4.js +0 -461
- package/dist/assets/worker-BSzbM0Uo.js +0 -330
- package/src/client/VZSidebar/AIChat/StreamingMessage.tsx +0 -35
|
@@ -18,6 +18,44 @@ interface FileSystemDirectoryReader {
|
|
|
18
18
|
|
|
19
19
|
const DEBUG = false;
|
|
20
20
|
|
|
21
|
+
const isTextFile = (file: File): boolean => {
|
|
22
|
+
// Add more text file types as needed
|
|
23
|
+
const textTypes = [
|
|
24
|
+
'text/',
|
|
25
|
+
'application/json',
|
|
26
|
+
'application/javascript',
|
|
27
|
+
'application/typescript',
|
|
28
|
+
'application/xml',
|
|
29
|
+
'application/x-httpd-php',
|
|
30
|
+
];
|
|
31
|
+
const isText =
|
|
32
|
+
textTypes.some((type) => file.type.startsWith(type)) ||
|
|
33
|
+
file.name.match(
|
|
34
|
+
/\.(txt|js|jsx|ts|tsx|md|css|scss|html|xml|json|php|py|rb|java|c|cpp|h|hpp)$/i,
|
|
35
|
+
) !== null;
|
|
36
|
+
|
|
37
|
+
DEBUG &&
|
|
38
|
+
console.log(
|
|
39
|
+
`[useDragAndDrop] File ${file.name} is${isText ? '' : ' not'} a text file`,
|
|
40
|
+
);
|
|
41
|
+
return isText;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const isImageFile = (file: File): boolean => {
|
|
45
|
+
const imageTypes = ['image/'];
|
|
46
|
+
const isImage =
|
|
47
|
+
imageTypes.some((type) => file.type.startsWith(type)) ||
|
|
48
|
+
file.name.match(
|
|
49
|
+
/\.(png|jpg|jpeg|gif|bmp|svg|webp)$/i,
|
|
50
|
+
) !== null;
|
|
51
|
+
|
|
52
|
+
DEBUG &&
|
|
53
|
+
console.log(
|
|
54
|
+
`[useDragAndDrop] File ${file.name} is${isImage ? '' : ' not'} an image file`,
|
|
55
|
+
);
|
|
56
|
+
return isImage;
|
|
57
|
+
};
|
|
58
|
+
|
|
21
59
|
export const useDragAndDrop = () => {
|
|
22
60
|
const [isDragOver, setIsDragOver] = useState(false);
|
|
23
61
|
const [isProcessing, setIsProcessing] = useState(false);
|
|
@@ -53,269 +91,237 @@ export const useDragAndDrop = () => {
|
|
|
53
91
|
[],
|
|
54
92
|
);
|
|
55
93
|
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
'text/',
|
|
60
|
-
'application/json',
|
|
61
|
-
'application/javascript',
|
|
62
|
-
'application/typescript',
|
|
63
|
-
'application/xml',
|
|
64
|
-
'application/x-httpd-php',
|
|
65
|
-
];
|
|
66
|
-
const isText =
|
|
67
|
-
textTypes.some((type) =>
|
|
68
|
-
file.type.startsWith(type),
|
|
69
|
-
) ||
|
|
70
|
-
file.name.match(
|
|
71
|
-
/\.(txt|js|jsx|ts|tsx|md|css|scss|html|xml|json|php|py|rb|java|c|cpp|h|hpp)$/i,
|
|
72
|
-
) !== null;
|
|
73
|
-
|
|
74
|
-
DEBUG &&
|
|
75
|
-
console.log(
|
|
76
|
-
`[useDragAndDrop] File ${file.name} is${isText ? '' : ' not'} a text file`,
|
|
77
|
-
);
|
|
78
|
-
return isText;
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const isImageFile = (file: File): boolean => {
|
|
82
|
-
const imageTypes = ['image/'];
|
|
83
|
-
const isImage =
|
|
84
|
-
imageTypes.some((type) =>
|
|
85
|
-
file.type.startsWith(type),
|
|
86
|
-
) ||
|
|
87
|
-
file.name.match(
|
|
88
|
-
/\.(png|jpg|jpeg|gif|bmp|svg|webp)$/i,
|
|
89
|
-
) !== null;
|
|
90
|
-
|
|
91
|
-
DEBUG &&
|
|
92
|
-
console.log(
|
|
93
|
-
`[useDragAndDrop] File ${file.name} is${isImage ? '' : ' not'} an image file`,
|
|
94
|
-
);
|
|
95
|
-
return isImage;
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
const readFileAsText = (file: File): Promise<string> => {
|
|
99
|
-
return new Promise((resolve, reject) => {
|
|
100
|
-
DEBUG &&
|
|
101
|
-
console.log(
|
|
102
|
-
`[useDragAndDrop] Reading file: ${file.name}`,
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
if (!isTextFile(file)) {
|
|
94
|
+
const readFileAsText = useCallback(
|
|
95
|
+
(file: File): Promise<string> => {
|
|
96
|
+
return new Promise((resolve, reject) => {
|
|
106
97
|
DEBUG &&
|
|
107
98
|
console.log(
|
|
108
|
-
`[useDragAndDrop]
|
|
99
|
+
`[useDragAndDrop] Reading file: ${file.name}`,
|
|
109
100
|
);
|
|
110
|
-
reject(
|
|
111
|
-
new Error(`File ${file.name} is not a text file`),
|
|
112
|
-
);
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
101
|
|
|
116
|
-
|
|
117
|
-
reader.onload = (e) => {
|
|
118
|
-
if (e.target?.result) {
|
|
102
|
+
if (!isTextFile(file)) {
|
|
119
103
|
DEBUG &&
|
|
120
104
|
console.log(
|
|
121
|
-
`[useDragAndDrop]
|
|
122
|
-
);
|
|
123
|
-
resolve(e.target.result as string);
|
|
124
|
-
} else {
|
|
125
|
-
DEBUG &&
|
|
126
|
-
console.log(
|
|
127
|
-
`[useDragAndDrop] Failed to read file: ${file.name}`,
|
|
105
|
+
`[useDragAndDrop] Rejected non-text file: ${file.name}`,
|
|
128
106
|
);
|
|
129
107
|
reject(
|
|
130
|
-
new Error(
|
|
108
|
+
new Error(
|
|
109
|
+
`File ${file.name} is not a text file`,
|
|
110
|
+
),
|
|
131
111
|
);
|
|
112
|
+
return;
|
|
132
113
|
}
|
|
133
|
-
};
|
|
134
|
-
reader.onerror = () => {
|
|
135
|
-
DEBUG &&
|
|
136
|
-
console.log(
|
|
137
|
-
`[useDragAndDrop] Error reading file: ${file.name}`,
|
|
138
|
-
);
|
|
139
|
-
reject(
|
|
140
|
-
new Error(`Error reading file ${file.name}`),
|
|
141
|
-
);
|
|
142
|
-
};
|
|
143
|
-
reader.readAsText(file);
|
|
144
|
-
});
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
const readImageAsBase64 = (
|
|
148
|
-
file: File,
|
|
149
|
-
): Promise<string> => {
|
|
150
|
-
return new Promise((resolve, reject) => {
|
|
151
|
-
DEBUG &&
|
|
152
|
-
console.log(
|
|
153
|
-
`[useDragAndDrop] Reading image file: ${file.name}`,
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
if (!isImageFile(file)) {
|
|
157
|
-
DEBUG &&
|
|
158
|
-
console.log(
|
|
159
|
-
`[useDragAndDrop] Rejected non-image file: ${file.name}`,
|
|
160
|
-
);
|
|
161
|
-
reject(
|
|
162
|
-
new Error(
|
|
163
|
-
`File ${file.name} is not an image file`,
|
|
164
|
-
),
|
|
165
|
-
);
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
114
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
file.type === 'image/svg+xml' ||
|
|
172
|
-
file.name.toLowerCase().endsWith('.svg')
|
|
173
|
-
) {
|
|
174
|
-
const textReader = new FileReader();
|
|
175
|
-
textReader.onload = (e) => {
|
|
115
|
+
const reader = new FileReader();
|
|
116
|
+
reader.onload = (e) => {
|
|
176
117
|
if (e.target?.result) {
|
|
177
118
|
DEBUG &&
|
|
178
119
|
console.log(
|
|
179
|
-
`[useDragAndDrop] Successfully read
|
|
120
|
+
`[useDragAndDrop] Successfully read file: ${file.name}`,
|
|
180
121
|
);
|
|
181
122
|
resolve(e.target.result as string);
|
|
182
123
|
} else {
|
|
124
|
+
DEBUG &&
|
|
125
|
+
console.log(
|
|
126
|
+
`[useDragAndDrop] Failed to read file: ${file.name}`,
|
|
127
|
+
);
|
|
183
128
|
reject(
|
|
184
|
-
new Error(
|
|
185
|
-
`Failed to read SVG file ${file.name}`,
|
|
186
|
-
),
|
|
129
|
+
new Error(`Failed to read file ${file.name}`),
|
|
187
130
|
);
|
|
188
131
|
}
|
|
189
132
|
};
|
|
190
|
-
|
|
191
|
-
reject(
|
|
192
|
-
new Error(
|
|
193
|
-
`Error reading SVG file ${file.name}`,
|
|
194
|
-
),
|
|
195
|
-
);
|
|
196
|
-
textReader.readAsText(file);
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
const reader = new FileReader();
|
|
201
|
-
reader.onload = (e) => {
|
|
202
|
-
if (e.target?.result) {
|
|
133
|
+
reader.onerror = () => {
|
|
203
134
|
DEBUG &&
|
|
204
135
|
console.log(
|
|
205
|
-
`[useDragAndDrop]
|
|
136
|
+
`[useDragAndDrop] Error reading file: ${file.name}`,
|
|
206
137
|
);
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
138
|
+
reject(
|
|
139
|
+
new Error(`Error reading file ${file.name}`),
|
|
140
|
+
);
|
|
141
|
+
};
|
|
142
|
+
reader.readAsText(file);
|
|
143
|
+
});
|
|
144
|
+
},
|
|
145
|
+
[],
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
const readImageAsBase64 = useCallback(
|
|
149
|
+
(file: File): Promise<string> => {
|
|
150
|
+
return new Promise((resolve, reject) => {
|
|
151
|
+
DEBUG &&
|
|
152
|
+
console.log(
|
|
153
|
+
`[useDragAndDrop] Reading image file: ${file.name}`,
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
if (!isImageFile(file)) {
|
|
213
157
|
DEBUG &&
|
|
214
158
|
console.log(
|
|
215
|
-
`[useDragAndDrop]
|
|
159
|
+
`[useDragAndDrop] Rejected non-image file: ${file.name}`,
|
|
216
160
|
);
|
|
217
161
|
reject(
|
|
218
162
|
new Error(
|
|
219
|
-
`
|
|
163
|
+
`File ${file.name} is not an image file`,
|
|
220
164
|
),
|
|
221
165
|
);
|
|
166
|
+
return;
|
|
222
167
|
}
|
|
223
|
-
};
|
|
224
|
-
reader.onerror = () => {
|
|
225
|
-
DEBUG &&
|
|
226
|
-
console.log(
|
|
227
|
-
`[useDragAndDrop] Error reading image file: ${file.name}`,
|
|
228
|
-
);
|
|
229
|
-
reject(
|
|
230
|
-
new Error(
|
|
231
|
-
`Error reading image file ${file.name}`,
|
|
232
|
-
),
|
|
233
|
-
);
|
|
234
|
-
};
|
|
235
|
-
reader.readAsDataURL(file);
|
|
236
|
-
});
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
const processEntry = async (
|
|
240
|
-
entry: FileSystemEntry,
|
|
241
|
-
path: string,
|
|
242
|
-
): Promise<void> => {
|
|
243
|
-
try {
|
|
244
|
-
DEBUG &&
|
|
245
|
-
console.log(
|
|
246
|
-
`[useDragAndDrop] Processing entry: ${entry.name} at path: ${path}`,
|
|
247
|
-
);
|
|
248
168
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
if (
|
|
257
|
-
const content = await readImageAsBase64(file);
|
|
169
|
+
// For SVG files, read as text if they're text-based
|
|
170
|
+
if (
|
|
171
|
+
file.type === 'image/svg+xml' ||
|
|
172
|
+
file.name.toLowerCase().endsWith('.svg')
|
|
173
|
+
) {
|
|
174
|
+
const textReader = new FileReader();
|
|
175
|
+
textReader.onload = (e) => {
|
|
176
|
+
if (e.target?.result) {
|
|
258
177
|
DEBUG &&
|
|
259
178
|
console.log(
|
|
260
|
-
`[useDragAndDrop]
|
|
179
|
+
`[useDragAndDrop] Successfully read SVG file as text: ${file.name}`,
|
|
261
180
|
);
|
|
262
|
-
|
|
181
|
+
resolve(e.target.result as string);
|
|
263
182
|
} else {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
createFile(`${path}${file.name}`, content);
|
|
183
|
+
reject(
|
|
184
|
+
new Error(
|
|
185
|
+
`Failed to read SVG file ${file.name}`,
|
|
186
|
+
),
|
|
187
|
+
);
|
|
270
188
|
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
189
|
+
};
|
|
190
|
+
textReader.onerror = () =>
|
|
191
|
+
reject(
|
|
192
|
+
new Error(
|
|
193
|
+
`Error reading SVG file ${file.name}`,
|
|
194
|
+
),
|
|
195
|
+
);
|
|
196
|
+
textReader.readAsText(file);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const reader = new FileReader();
|
|
201
|
+
reader.onload = (e) => {
|
|
202
|
+
if (e.target?.result) {
|
|
203
|
+
DEBUG &&
|
|
204
|
+
console.log(
|
|
205
|
+
`[useDragAndDrop] Successfully read image file: ${file.name}`,
|
|
206
|
+
);
|
|
207
|
+
// Return just the base64 part without the data URL prefix
|
|
208
|
+
const base64 = (
|
|
209
|
+
e.target.result as string
|
|
210
|
+
).split(',')[1];
|
|
211
|
+
resolve(base64);
|
|
212
|
+
} else {
|
|
213
|
+
DEBUG &&
|
|
214
|
+
console.log(
|
|
215
|
+
`[useDragAndDrop] Failed to read image file: ${file.name}`,
|
|
216
|
+
);
|
|
217
|
+
reject(
|
|
218
|
+
new Error(
|
|
219
|
+
`Failed to read image file ${file.name}`,
|
|
220
|
+
),
|
|
275
221
|
);
|
|
276
222
|
}
|
|
277
|
-
}
|
|
278
|
-
|
|
223
|
+
};
|
|
224
|
+
reader.onerror = () => {
|
|
225
|
+
DEBUG &&
|
|
226
|
+
console.log(
|
|
227
|
+
`[useDragAndDrop] Error reading image file: ${file.name}`,
|
|
228
|
+
);
|
|
229
|
+
reject(
|
|
230
|
+
new Error(
|
|
231
|
+
`Error reading image file ${file.name}`,
|
|
232
|
+
),
|
|
233
|
+
);
|
|
234
|
+
};
|
|
235
|
+
reader.readAsDataURL(file);
|
|
236
|
+
});
|
|
237
|
+
},
|
|
238
|
+
[],
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
const processEntry = useCallback(
|
|
242
|
+
async (
|
|
243
|
+
entry: FileSystemEntry,
|
|
244
|
+
path: string,
|
|
245
|
+
): Promise<void> => {
|
|
246
|
+
try {
|
|
279
247
|
DEBUG &&
|
|
280
248
|
console.log(
|
|
281
|
-
`[useDragAndDrop] Processing
|
|
249
|
+
`[useDragAndDrop] Processing entry: ${entry.name} at path: ${path}`,
|
|
282
250
|
);
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
251
|
+
|
|
252
|
+
if (entry.isFile) {
|
|
253
|
+
DEBUG &&
|
|
254
|
+
console.log(
|
|
255
|
+
`[useDragAndDrop] Processing file: ${entry.name}`,
|
|
256
|
+
);
|
|
257
|
+
entry.file(async (file) => {
|
|
258
|
+
try {
|
|
259
|
+
if (isImageFile(file)) {
|
|
260
|
+
const content =
|
|
261
|
+
await readImageAsBase64(file);
|
|
288
262
|
DEBUG &&
|
|
289
263
|
console.log(
|
|
290
|
-
`[useDragAndDrop]
|
|
264
|
+
`[useDragAndDrop] Creating image file: ${path}${file.name}`,
|
|
291
265
|
);
|
|
292
|
-
|
|
293
|
-
|
|
266
|
+
createFile(`${path}${file.name}`, content);
|
|
267
|
+
} else {
|
|
268
|
+
const content = await readFileAsText(file);
|
|
269
|
+
DEBUG &&
|
|
270
|
+
console.log(
|
|
271
|
+
`[useDragAndDrop] Creating text file: ${path}${file.name}`,
|
|
272
|
+
);
|
|
273
|
+
createFile(`${path}${file.name}`, content);
|
|
294
274
|
}
|
|
275
|
+
} catch (error) {
|
|
276
|
+
console.error(
|
|
277
|
+
`Error processing file ${file.name}:`,
|
|
278
|
+
error,
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
} else if (entry.isDirectory) {
|
|
283
|
+
DEBUG &&
|
|
284
|
+
console.log(
|
|
285
|
+
`[useDragAndDrop] Processing directory: ${entry.name}`,
|
|
286
|
+
);
|
|
287
|
+
return new Promise<void>((resolve) => {
|
|
288
|
+
const dirReader = entry.createReader();
|
|
289
|
+
const readEntries = () => {
|
|
290
|
+
dirReader.readEntries(async (entries) => {
|
|
291
|
+
if (entries.length === 0) {
|
|
292
|
+
DEBUG &&
|
|
293
|
+
console.log(
|
|
294
|
+
`[useDragAndDrop] Finished reading directory: ${entry.name}`,
|
|
295
|
+
);
|
|
296
|
+
resolve();
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
295
299
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
+
const newPath = `${path}${entry.name}/`;
|
|
301
|
+
DEBUG &&
|
|
302
|
+
console.log(
|
|
303
|
+
`[useDragAndDrop] Reading ${entries.length} entries in directory: ${newPath}`,
|
|
304
|
+
);
|
|
305
|
+
await Promise.all(
|
|
306
|
+
entries.map((entry) =>
|
|
307
|
+
processEntry(entry, newPath),
|
|
308
|
+
),
|
|
300
309
|
);
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
310
|
+
readEntries(); // Continue reading if there are more entries
|
|
311
|
+
});
|
|
312
|
+
};
|
|
313
|
+
readEntries();
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
} catch (error) {
|
|
317
|
+
console.error(
|
|
318
|
+
`Error processing entry ${entry.name}:`,
|
|
319
|
+
error,
|
|
320
|
+
);
|
|
311
321
|
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
error,
|
|
316
|
-
);
|
|
317
|
-
}
|
|
318
|
-
};
|
|
322
|
+
},
|
|
323
|
+
[createFile, readFileAsText, readImageAsBase64],
|
|
324
|
+
);
|
|
319
325
|
|
|
320
326
|
const handleDrop = useCallback(
|
|
321
327
|
async (event: React.DragEvent<HTMLDivElement>) => {
|
|
@@ -394,7 +400,12 @@ export const useDragAndDrop = () => {
|
|
|
394
400
|
setIsProcessing(false);
|
|
395
401
|
}
|
|
396
402
|
},
|
|
397
|
-
[
|
|
403
|
+
[
|
|
404
|
+
createFile,
|
|
405
|
+
processEntry,
|
|
406
|
+
readFileAsText,
|
|
407
|
+
readImageAsBase64,
|
|
408
|
+
],
|
|
398
409
|
);
|
|
399
410
|
|
|
400
411
|
return {
|