fix: restrict file attachments to images only
The OpenClaw gateway only supports image attachments in chat.send; non-image files were silently dropped, confusing users (fixes #24). - Filter non-image files in addFiles handler - Update file input accept to image/* only - Remove unused fileToBase64 helper - Update i18n labels from 'Attach file' to 'Attach image' (all 8 langs) Fixes #24
This commit is contained in:
@@ -38,19 +38,6 @@ interface Props {
|
||||
const MAX_BASE64_CHARS = 300 * 1024; // ~225KB real, well under 512KB WS limit (JSON overhead + base64 bloat)
|
||||
const MAX_IMAGE_PIXELS = 1280; // Max dimension for resize
|
||||
|
||||
function fileToBase64(file: File): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
const dataUrl = reader.result as string;
|
||||
const base64 = dataUrl.split(',')[1] || '';
|
||||
resolve(base64);
|
||||
};
|
||||
reader.onerror = reject;
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
}
|
||||
|
||||
function compressImage(file: File, maxBase64Chars: number): Promise<{ base64: string; mimeType: string }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
@@ -184,24 +171,18 @@ export function ChatInput({ onSend, onNewSession, onAbort, isGenerating, disable
|
||||
const newFiles: FileAttachment[] = [];
|
||||
for (const file of Array.from(fileList)) {
|
||||
if (file.size > 20 * 1024 * 1024) continue; // 20MB max
|
||||
const isImage = file.type.startsWith('image/');
|
||||
let base64: string;
|
||||
let mimeType: string;
|
||||
if (isImage) {
|
||||
// Compress images to fit WS payload limit
|
||||
const compressed = await compressImage(file, MAX_BASE64_CHARS);
|
||||
base64 = compressed.base64;
|
||||
mimeType = compressed.mimeType;
|
||||
} else {
|
||||
base64 = await fileToBase64(file);
|
||||
mimeType = file.type || 'application/octet-stream';
|
||||
}
|
||||
// Only images are supported — the OpenClaw gateway drops non-image attachments
|
||||
if (!file.type.startsWith('image/')) continue;
|
||||
// Compress images to fit WS payload limit
|
||||
const compressed = await compressImage(file, MAX_BASE64_CHARS);
|
||||
const base64 = compressed.base64;
|
||||
const mimeType = compressed.mimeType;
|
||||
newFiles.push({
|
||||
id: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
||||
file,
|
||||
base64,
|
||||
mimeType,
|
||||
preview: isImage ? `data:${mimeType};base64,${base64}` : undefined,
|
||||
preview: `data:${mimeType};base64,${base64}`,
|
||||
});
|
||||
}
|
||||
setFiles(prev => [...prev, ...newFiles]);
|
||||
@@ -418,7 +399,7 @@ export function ChatInput({ onSend, onNewSession, onAbort, isGenerating, disable
|
||||
multiple
|
||||
className="hidden"
|
||||
onChange={(e) => { if (e.target.files) addFiles(e.target.files); e.target.value = ''; }}
|
||||
accept="image/*,.pdf,.txt,.md,.json,.csv,.log,.py,.js,.ts,.tsx,.jsx,.html,.css,.yaml,.yml,.xml,.sql,.sh,.env,.toml"
|
||||
accept="image/*"
|
||||
/>
|
||||
|
||||
<textarea
|
||||
|
||||
@@ -49,7 +49,7 @@ const en = {
|
||||
'chat.loadingHistory': 'Loading messages…',
|
||||
'chat.inputPlaceholder': 'Type a message…',
|
||||
'chat.inputLabel': 'Message',
|
||||
'chat.attachFile': 'Attach file',
|
||||
'chat.attachFile': 'Attach image',
|
||||
'chat.send': 'Send',
|
||||
'chat.stop': 'Stop',
|
||||
'chat.showPreview': 'Preview markdown',
|
||||
@@ -245,7 +245,7 @@ const fr: Record<keyof typeof en, string> = {
|
||||
'chat.loadingHistory': 'Chargement des messages…',
|
||||
'chat.inputPlaceholder': 'Tapez un message…',
|
||||
'chat.inputLabel': 'Message',
|
||||
'chat.attachFile': 'Joindre un fichier',
|
||||
'chat.attachFile': 'Joindre une image',
|
||||
'chat.send': 'Envoyer',
|
||||
'chat.stop': 'Arrêter',
|
||||
'chat.showPreview': 'Aperçu markdown',
|
||||
@@ -428,7 +428,7 @@ const es: Record<keyof typeof en, string> = {
|
||||
'chat.loadingHistory': 'Cargando mensajes…',
|
||||
'chat.inputPlaceholder': 'Escribe un mensaje…',
|
||||
'chat.inputLabel': 'Mensaje',
|
||||
'chat.attachFile': 'Adjuntar archivo',
|
||||
'chat.attachFile': 'Adjuntar imagen',
|
||||
'chat.send': 'Enviar',
|
||||
'chat.stop': 'Detener',
|
||||
'chat.showPreview': 'Vista previa markdown',
|
||||
@@ -613,7 +613,7 @@ const de: Record<keyof typeof en, string> = {
|
||||
'chat.loadingHistory': 'Nachrichten werden geladen…',
|
||||
'chat.inputPlaceholder': 'Nachricht eingeben…',
|
||||
'chat.inputLabel': 'Nachricht',
|
||||
'chat.attachFile': 'Datei anhängen',
|
||||
'chat.attachFile': 'Bild anhängen',
|
||||
'chat.send': 'Senden',
|
||||
'chat.stop': 'Stoppen',
|
||||
'chat.showPreview': 'Markdown-Vorschau',
|
||||
@@ -796,7 +796,7 @@ const ja: Record<keyof typeof en, string> = {
|
||||
'chat.loadingHistory': 'メッセージを読み込み中…',
|
||||
'chat.inputPlaceholder': 'メッセージを入力…',
|
||||
'chat.inputLabel': 'メッセージ',
|
||||
'chat.attachFile': 'ファイルを添付',
|
||||
'chat.attachFile': '画像を添付',
|
||||
'chat.send': '送信',
|
||||
'chat.stop': '停止',
|
||||
'chat.showPreview': 'Markdownプレビュー',
|
||||
@@ -979,7 +979,7 @@ const pt: Record<keyof typeof en, string> = {
|
||||
'chat.loadingHistory': 'Carregando mensagens…',
|
||||
'chat.inputPlaceholder': 'Digite uma mensagem…',
|
||||
'chat.inputLabel': 'Mensagem',
|
||||
'chat.attachFile': 'Anexar arquivo',
|
||||
'chat.attachFile': 'Anexar imagem',
|
||||
'chat.send': 'Enviar',
|
||||
'chat.stop': 'Parar',
|
||||
'chat.showPreview': 'Pré-visualizar markdown',
|
||||
@@ -1162,7 +1162,7 @@ const zh: Record<keyof typeof en, string> = {
|
||||
'chat.loadingHistory': '加载消息中…',
|
||||
'chat.inputPlaceholder': '输入消息…',
|
||||
'chat.inputLabel': '消息',
|
||||
'chat.attachFile': '添加附件',
|
||||
'chat.attachFile': '添加图片',
|
||||
'chat.send': '发送',
|
||||
'chat.stop': '停止',
|
||||
'chat.showPreview': '预览 Markdown',
|
||||
@@ -1345,7 +1345,7 @@ const it: Record<keyof typeof en, string> = {
|
||||
'chat.loadingHistory': 'Caricamento messaggi…',
|
||||
'chat.inputPlaceholder': 'Scrivi un messaggio…',
|
||||
'chat.inputLabel': 'Messaggio',
|
||||
'chat.attachFile': 'Allega file',
|
||||
'chat.attachFile': 'Allega immagine',
|
||||
'chat.send': 'Invia',
|
||||
'chat.stop': 'Ferma',
|
||||
'chat.showPreview': 'Anteprima markdown',
|
||||
|
||||
Reference in New Issue
Block a user