feat: add attachment button and mobile UI enhancements (v2.1)

This commit is contained in:
leeyj
2026-04-19 23:22:35 +09:00
parent 3d3709371d
commit ff9d75c26f
9 changed files with 97 additions and 41 deletions
+15 -1
View File
@@ -28,7 +28,9 @@ export const ComposerManager = {
foldBtn: document.getElementById('foldBtn'),
discardBtn: document.getElementById('discardBtn'),
deleteBtn: document.getElementById('deleteMemoBtn'), // NEW
categoryBar: document.getElementById('composerCategoryBar')
categoryBar: document.getElementById('composerCategoryBar'),
attachBtn: document.getElementById('attachBtn'),
fileInput: document.getElementById('composerFileInput')
};
if (!this.DOM.composer || !this.DOM.trigger) return;
@@ -71,6 +73,18 @@ export const ComposerManager = {
this.DOM.encryptionToggle.onclick = () => this.toggleEncryption();
this.initShortcutHint();
// 💡 파일 첨부 버튼 연동
if (this.DOM.attachBtn && this.DOM.fileInput) {
this.DOM.attachBtn.onclick = () => this.DOM.fileInput.click();
this.DOM.fileInput.onchange = (e) => {
const files = e.target.files;
if (files.length > 0) {
EditorManager.handleFiles(files);
e.target.value = ''; // 같은 파일 다시 올릴 수 있게 초기화
}
};
}
// 2. 자동 임시저장 및 키보드 리스너 등록
this.draftTimer = setInterval(() => this.saveDraft(), 3000);
ComposerDraft.checkRestore((draft) => this.restoreDraft(draft));
+36 -27
View File
@@ -147,37 +147,46 @@ export const EditorManager = {
if (!files || files.length === 0) return;
// 에디터가 닫혀있다면 상위에서 열어줘야 함
onDropComplete(true);
if (onDropComplete) onDropComplete(true);
for (let file of files) {
try {
const data = await API.uploadFile(file);
if (data.url) {
const filename = data.url.split('/').pop();
const isImg = ['png','jpg','jpeg','gif','webp','svg'].includes(data.ext?.toLowerCase());
const name = data.name || 'file';
// Ensure editor is focused before inserting
this.editor.focus();
if (isImg) {
this.editor.exec('addImage', { altText: name, imageUrl: data.url });
}
// 공통: 첨부 파일 목록에 추가 및 UI 갱신
this.attachedFiles.push({
filename: filename,
original_name: name,
file_type: file.type
});
this.sessionFiles.add(filename); // 세션 트래킹 추가
this.refreshAttachmentUI();
}
} catch (err) { console.error(err); }
}
await this.handleFiles(files);
});
},
/**
* 다중 파일을 처리(업로드 및 UI 반영)함
*/
async handleFiles(files) {
if (!files || files.length === 0) return;
for (let file of files) {
try {
const data = await API.uploadFile(file);
if (data.url) {
const filename = data.url.split('/').pop();
const isImg = ['png','jpg','jpeg','gif','webp','svg'].includes(data.ext?.toLowerCase());
const name = data.name || 'file';
// Ensure editor is focused before inserting
this.editor.focus();
if (isImg) {
this.editor.exec('addImage', { altText: name, imageUrl: data.url });
}
// 공통: 첨부 파일 목록에 추가 및 UI 갱신
this.attachedFiles.push({
filename: filename,
original_name: name,
file_type: file.type
});
this.sessionFiles.add(filename); // 세션 트래킹 추가
this.refreshAttachmentUI();
}
} catch (err) { console.error('[Editor] File process error:', err); }
}
},
getAttachedFilenames() {
return this.attachedFiles.map(f => f.filename);
},