미디어 선택 요청 흐름 분리

This commit is contained in:
2026-07-28 10:27:02 +09:00
parent 5e4ccbf2bf
commit 9f3ef337ef
10 changed files with 267 additions and 83 deletions

View File

@@ -37,13 +37,9 @@ import {
resolvePreviewFocusPosition as resolveMarkdownPreviewFocusPosition
} from '../../lib/markdown-editor-focus.js'
import {
createMediaPickerFetchQuery,
createMediaUploadFormData,
createSelectedMediaInsertPlan,
filterImageUploadFiles,
findUploadSizeLimitError,
resolveImageUploadInsertTarget,
resolveUploadedMediaFiles,
resolveUploadFetchErrorMessage
} from '../../lib/markdown-editor-media.js'
import {
@@ -166,10 +162,8 @@ const {
onMediaSearchInput,
onMediaSearchCompositionEnd,
mediaPickerPage,
mediaPickerPageSize,
selectedMediaUrls,
mediaPickerAccept,
mediaPickerKind,
mediaPickerTitle,
isGalleryMediaPicker,
mediaPickerPageCount,
@@ -183,15 +177,17 @@ const {
isUploadFileAllowedForPicker,
openMediaPickerState,
closeMediaPickerState,
applyMediaPickerResponse,
fetchMediaItems,
uploadMediaFilesWithState,
uploadFilesIntoMediaPicker,
setMediaPickerPage: setMediaPickerPageState,
toggleMediaSelection,
resolveCurrentSelectedMediaItems,
selectUploadedMediaFiles,
prependUploadedMediaItems,
getGallerySelectionOrder
} = useAdminMarkdownMediaPicker({
uploadSizeLimits
uploadSizeLimits,
uploadMaxFileCount,
uploadMaxTotalSize
})
/** @type {HTMLElement|null} 슬래시 메뉴 위치 갱신을 위해 구독한 미리보기 스크롤 영역 */
let liveSlashPreviewScrollElement = null
@@ -2836,29 +2832,6 @@ const insertGallery = (images) => {
insertBlockSnippet([':::gallery', ...images.map(createImageMarkdown), ':::'].join('\n'))
}
/**
* 미디어 목록을 불러온다.
* @returns {Promise<void>}
*/
const fetchMediaItems = async () => {
isLoadingMedia.value = true
try {
const response = await $fetch('/admin/api/media', {
query: createMediaPickerFetchQuery({
page: mediaPickerPage.value,
pageSize: mediaPickerPageSize,
kind: mediaPickerKind.value,
searchQuery: mediaSearchQuery.value
})
})
applyMediaPickerResponse(response)
} finally {
isLoadingMedia.value = false
}
}
/**
* 미디어 선택 창을 연다.
* @param {'image'|'gallery'|'active-gallery'} target - 삽입 대상
@@ -2973,31 +2946,6 @@ const applyMediaSelection = () => {
closeMediaPicker()
}
/**
* 미디어 파일을 업로드한다.
* @param {FileList|Array<File>} files - 업로드 파일 목록
* @returns {Promise<Array<Object>>} 업로드된 파일 목록
*/
const uploadMediaFiles = async (files) => {
const sizeLimitError = findUploadSizeLimitError({
files,
maxFileCount: uploadMaxFileCount.value,
maxTotalSize: uploadMaxTotalSize.value,
uploadSizeLimits: uploadSizeLimits.value
})
if (sizeLimitError) {
throw new Error(sizeLimitError)
}
const result = await $fetch('/admin/api/uploads', {
method: 'POST',
body: createMediaUploadFormData(files)
})
return resolveUploadedMediaFiles(result)
}
/**
* 업로드 파일을 현재 커서 위치에 삽입한다.
* @param {FileList|Array<File>} files - 파일 목록
@@ -3009,10 +2957,13 @@ const uploadAndInsert = async (files, target = 'image') => {
return
}
isUploading.value = true
try {
const uploadedFiles = await uploadMediaFiles(files)
const uploadedFiles = await uploadMediaFilesWithState(files)
if (!uploadedFiles.length) {
return
}
const plan = createSelectedMediaInsertPlan({
target,
selectedItems: uploadedFiles,
@@ -3032,8 +2983,6 @@ const uploadAndInsert = async (files, target = 'image') => {
}
} catch (error) {
showToast('error', resolveUploadFetchErrorMessage(error))
} finally {
isUploading.value = false
}
}
@@ -3058,22 +3007,16 @@ const uploadFromMediaModal = async (files) => {
return
}
isUploading.value = true
try {
const uploadedFiles = await uploadMediaFiles(files)
selectUploadedMediaFiles(uploadedFiles)
activeMediaPickerTab.value = 'library'
mediaSearchQuery.value = ''
mediaPickerPage.value = 1
await fetchMediaItems().catch(() => {
prependUploadedMediaItems(uploadedFiles)
})
const uploadedFiles = await uploadFilesIntoMediaPicker(files)
if (!uploadedFiles.length) {
return
}
showToast('success', '업로드가 완료되어 파일이 선택되었습니다.')
} catch (error) {
showToast('error', resolveUploadFetchErrorMessage(error))
} finally {
isUploading.value = false
}
}