(function () { function qs(id) { return document.getElementById(id); } function humanSize(bytes) { if (!bytes && bytes !== 0) return ''; var units = ['B', 'KB', 'MB', 'GB']; var i = 0; var n = bytes; while (n >= 1024 && i < units.length - 1) { n /= 1024; i++; } return (Math.round(n * 10) / 10) + ' ' + units[i]; } function setStatus(text) { var el = qs('upload-status'); if (el) el.textContent = text || ''; } function init() { var dropzone = qs('dropzone'); var fileInput = qs('file-input'); var previewWrap = qs('upload-preview'); var previewImg = qs('preview-img'); var previewMeta = qs('preview-meta'); var uploadBtn = qs('upload-btn'); if (!dropzone || !fileInput || !uploadBtn) return; var selectedFile = null; function showPreview(file) { selectedFile = file; uploadBtn.disabled = !file; setStatus(''); if (!file) { if (previewWrap) previewWrap.style.display = 'none'; return; } if (previewWrap) previewWrap.style.display = 'block'; if (previewMeta) previewMeta.textContent = file.name + ' · ' + humanSize(file.size); var reader = new FileReader(); reader.onload = function (e) { if (previewImg) previewImg.src = e.target.result; }; reader.readAsDataURL(file); } function isImageFile(file) { return file && file.type && file.type.indexOf('image/') === 0; } function onFiles(files) { if (!files || !files.length) return; var f = files[0]; if (!isImageFile(f)) { setStatus('이미지 파일만 업로드 가능합니다.'); return; } showPreview(f); } function pad2(n) { return (n < 10 ? '0' : '') + n; } function pasteFilename(mime) { var now = new Date(); var stamp = now.getFullYear() + pad2(now.getMonth() + 1) + pad2(now.getDate()) + '_' + pad2(now.getHours()) + pad2(now.getMinutes()) + pad2(now.getSeconds()); var ext = 'png'; if (mime === 'image/jpeg') ext = 'jpg'; else if (mime === 'image/gif') ext = 'gif'; else if (mime === 'image/webp') ext = 'webp'; return 'paste_' + stamp + '.' + ext; } function fileFromClipboardItem(item) { if (!item || typeof item.getAsFile !== 'function') return null; var blob = item.getAsFile(); if (!blob || !isImageFile(blob)) return null; var name = blob.name && blob.name !== 'image.png' ? blob.name : pasteFilename(blob.type || 'image/png'); try { return new File([blob], name, { type: blob.type || 'image/png' }); } catch (e) { // Older browsers may not support File constructor blob.name = name; return blob; } } function onPaste(e) { var target = e.target; if (target) { var tag = (target.tagName || '').toLowerCase(); if (tag === 'input' || tag === 'textarea' || target.isContentEditable) { return; } } var clipboard = e.clipboardData || window.clipboardData; if (!clipboard) return; var items = clipboard.items; if (items && items.length) { for (var i = 0; i < items.length; i++) { var item = items[i]; if (!item || !item.type || item.type.indexOf('image/') !== 0) continue; var file = fileFromClipboardItem(item); if (!file) continue; e.preventDefault(); showPreview(file); setStatus('클립보드 이미지 선택됨. 업로드를 눌러주세요.'); return; } } // Fallback: some browsers expose files directly if (clipboard.files && clipboard.files.length) { var pasted = clipboard.files[0]; if (isImageFile(pasted)) { e.preventDefault(); onFiles(clipboard.files); setStatus('클립보드 이미지 선택됨. 업로드를 눌러주세요.'); } } } dropzone.addEventListener('dragover', function (e) { e.preventDefault(); dropzone.classList.add('dragover'); }); dropzone.addEventListener('dragleave', function () { dropzone.classList.remove('dragover'); }); dropzone.addEventListener('drop', function (e) { e.preventDefault(); dropzone.classList.remove('dragover'); onFiles(e.dataTransfer.files); }); fileInput.addEventListener('change', function () { onFiles(fileInput.files); }); document.addEventListener('paste', onPaste); uploadBtn.addEventListener('click', function () { if (!selectedFile) return; uploadBtn.disabled = true; setStatus('업로드 중...'); var fd = new FormData(); fd.append('image', selectedFile); fetch('api/upload_image.php', { method: 'POST', body: fd, credentials: 'same-origin' }) .then(function (r) { return r.json(); }) .then(function (data) { if (!data || !data.ok) { throw new Error((data && data.error) ? data.error : '업로드 실패'); } // Add immediately to current gallery var filename = data.filename; var thumbHtml = (typeof buildThumbLi === 'function') ? buildThumbLi(filename) : ''; if (thumbHtml && window.dreamgirlGallery && typeof window.dreamgirlGallery.appendImage === 'function') { window.dreamgirlGallery.appendImage(thumbHtml); } else if (thumbHtml) { // fallback: append to DOM var ul = document.querySelector('#thumbs ul.thumbs'); if (ul) ul.insertAdjacentHTML('beforeend', thumbHtml); } // keep in-memory list (doesn't persist; list_images.php handles persistence) if (window.DREAMGIRL_IMAGES && window.DREAMGIRL_IMAGES.push) { window.DREAMGIRL_IMAGES.push(filename); } setStatus('업로드 완료: ' + filename); // reset selectedFile = null; if (fileInput) fileInput.value = ''; if (previewWrap) previewWrap.style.display = 'none'; }) .catch(function (err) { setStatus('에러: ' + (err && err.message ? err.message : '업로드 실패')); }) .finally(function () { uploadBtn.disabled = false; }); }); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();