diff --git a/package-lock.json b/package-lock.json index 2851112..ebd3454 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,18 @@ { "name": "patchreader-extension", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "patchreader-extension", - "version": "1.0.0", + "version": "1.0.1", "license": "MIT", "devDependencies": { "diff2html": "^3.4.55" + }, + "engines": { + "node": ">=22.0.0" } }, "node_modules/@profoundlogic/hogan": { diff --git a/package.json b/package.json index c77f738..66f5796 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "patchreader-extension", - "version": "1.0.0", + "version": "1.0.1", "description": "Browser extension to read and render patch/diff files using diff2html", "main": "index.js", "engines": { diff --git a/src/chrome/manifest.json b/src/chrome/manifest.json index 0dd091f..b5a01f5 100644 --- a/src/chrome/manifest.json +++ b/src/chrome/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Patch Reader", - "version": "1.0.0", + "version": "1.0.1", "description": "Read and render patch/diff files with diff2html", "default_locale": "en", "icons": { diff --git a/src/common/_locales/en/messages.json b/src/common/_locales/en/messages.json index ce6313f..958e73b 100644 --- a/src/common/_locales/en/messages.json +++ b/src/common/_locales/en/messages.json @@ -30,7 +30,7 @@ "message": "After entering or uploading patch/diff content, the rendered result will be displayed here" }, "inputPlaceholder": { - "message": "Paste patch/diff content here, or click the upload button to upload .patch or .diff files..." + "message": "Paste patch/diff content here, drag and drop files here, or click the upload button to upload .patch or .diff files..." }, "fileReadFailed": { "message": "File read failed" @@ -40,5 +40,8 @@ }, "viewed": { "message": "Viewed" + }, + "invalidFileType": { + "message": "Please drop .patch, .diff, or .txt files" } } diff --git a/src/common/_locales/ja/messages.json b/src/common/_locales/ja/messages.json index ecff61f..549055e 100644 --- a/src/common/_locales/ja/messages.json +++ b/src/common/_locales/ja/messages.json @@ -30,7 +30,7 @@ "message": "patch/diff 内容を入力またはアップロードすると、レンダリング結果がここに表示されます" }, "inputPlaceholder": { - "message": "ここに patch/diff 内容を貼り付けるか、アップロードボタンをクリックして .patch または .diff ファイルをアップロードしてください..." + "message": "ここに patch/diff 内容を貼り付けるか、ファイルをここにドラッグアンドドロップするか、アップロードボタンをクリックして .patch または .diff ファイルをアップロードしてください..." }, "fileReadFailed": { "message": "ファイルの読み取りに失敗しました" @@ -40,5 +40,8 @@ }, "viewed": { "message": "確認済み" + }, + "invalidFileType": { + "message": ".patch、.diff、または .txt ファイルをドロップしてください" } } diff --git a/src/common/_locales/zh/messages.json b/src/common/_locales/zh/messages.json index fb9e27b..15027e0 100644 --- a/src/common/_locales/zh/messages.json +++ b/src/common/_locales/zh/messages.json @@ -30,7 +30,7 @@ "message": "输入或上传 patch/diff 内容后,渲染结果将显示在这里" }, "inputPlaceholder": { - "message": "在此粘贴 patch/diff 内容,或点击上传文件按钮上传 .patch 或 .diff 文件..." + "message": "在此粘贴 patch/diff 内容,拖拽文件到此处,或点击上传文件按钮上传 .patch 或 .diff 文件..." }, "fileReadFailed": { "message": "文件读取失败" @@ -40,5 +40,8 @@ }, "viewed": { "message": "已查看" + }, + "invalidFileType": { + "message": "请拖拽 .patch、.diff 或 .txt 文件" } } diff --git a/src/common/diff-viewer.html b/src/common/diff-viewer.html index 2fb911c..05e9985 100644 --- a/src/common/diff-viewer.html +++ b/src/common/diff-viewer.html @@ -30,7 +30,7 @@

Input Patch/Diff Content

- +
diff --git a/src/common/diff-viewer.js b/src/common/diff-viewer.js index c1bbfce..4397879 100644 --- a/src/common/diff-viewer.js +++ b/src/common/diff-viewer.js @@ -53,6 +53,102 @@ // Delegate click events for viewed checkboxes diffOutput.addEventListener('change', handleViewedCheckboxChange); + + // Drag and drop event listeners for the textarea + diffInput.addEventListener('dragover', handleDragOver); + diffInput.addEventListener('dragenter', handleDragEnter); + diffInput.addEventListener('dragleave', handleDragLeave); + diffInput.addEventListener('drop', handleDrop); + } + + // Track drag enter/leave to handle nested elements + let dragCounter = 0; + + // Handle drag over event + function handleDragOver(event) { + event.preventDefault(); + event.stopPropagation(); + } + + // Handle drag enter event + function handleDragEnter(event) { + event.preventDefault(); + event.stopPropagation(); + dragCounter++; + diffInput.classList.add('drag-over'); + } + + // Handle drag leave event + function handleDragLeave(event) { + event.preventDefault(); + event.stopPropagation(); + dragCounter--; + if (dragCounter === 0) { + diffInput.classList.remove('drag-over'); + } + } + + // Handle drop event + function handleDrop(event) { + event.preventDefault(); + event.stopPropagation(); + dragCounter = 0; + diffInput.classList.remove('drag-over'); + + const files = event.dataTransfer.files; + if (!files || files.length === 0) return; + + // Filter for valid file types + const validFiles = Array.from(files).filter(file => { + const fileName = file.name.toLowerCase(); + return fileName.endsWith('.patch') || fileName.endsWith('.diff') || fileName.endsWith('.txt'); + }); + + if (validFiles.length === 0) { + const errorMsg = window.i18n ? window.i18n.getMessage('invalidFileType') : 'Please drop .patch, .diff, or .txt files'; + showError(errorMsg); + return; + } + + processFiles(validFiles); + } + + // Process files (shared by drag-drop and file upload) + function processFiles(files) { + const readPromises = Array.from(files).map(file => { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = (e) => resolve({ + name: file.name, + content: e.target.result + }); + reader.onerror = () => reject(new Error(`Failed to read file: ${file.name}`)); + reader.readAsText(file); + }); + }); + + Promise.all(readPromises) + .then(results => { + // Combine all file contents + const combinedContent = results.map(r => { + // Add file header comment if multiple files + if (results.length > 1) { + return `# File: ${r.name}\n${r.content}`; + } + return r.content; + }).join('\n\n'); + + diffInput.value = combinedContent; + // Clear viewed files when new content is loaded + viewedFiles.clear(); + saveViewedFiles(); + renderDiff(); + saveState(); + }) + .catch(error => { + const errorMsg = window.i18n ? window.i18n.getMessage('fileReadFailed') : 'File read failed'; + showError(`${errorMsg}: ${error.message}`); + }); } // Handle viewed checkbox change @@ -147,40 +243,7 @@ const files = event.target.files; if (!files || files.length === 0) return; - const readPromises = Array.from(files).map(file => { - return new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.onload = (e) => resolve({ - name: file.name, - content: e.target.result - }); - reader.onerror = () => reject(new Error(`Failed to read file: ${file.name}`)); - reader.readAsText(file); - }); - }); - - Promise.all(readPromises) - .then(results => { - // Combine all file contents - const combinedContent = results.map(r => { - // Add file header comment if multiple files - if (results.length > 1) { - return `# File: ${r.name}\n${r.content}`; - } - return r.content; - }).join('\n\n'); - - diffInput.value = combinedContent; - // Clear viewed files when new content is loaded - viewedFiles.clear(); - saveViewedFiles(); - renderDiff(); - saveState(); - }) - .catch(error => { - const errorMsg = window.i18n ? window.i18n.getMessage('fileReadFailed') : 'File read failed'; - showError(`${errorMsg}: ${error.message}`); - }); + processFiles(files); // Reset file input fileInput.value = ''; diff --git a/src/common/styles.css b/src/common/styles.css index 4084d1d..75f155a 100644 --- a/src/common/styles.css +++ b/src/common/styles.css @@ -173,6 +173,13 @@ body { color: #6a737d; } +/* Drag and drop state */ +#diff-input.drag-over { + background-color: #dafbe1; + border: 2px dashed #238636; + outline: none; +} + /* Output Section */ .output-section { flex: 1; diff --git a/src/edge/manifest.json b/src/edge/manifest.json index 0dd091f..b5a01f5 100644 --- a/src/edge/manifest.json +++ b/src/edge/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Patch Reader", - "version": "1.0.0", + "version": "1.0.1", "description": "Read and render patch/diff files with diff2html", "default_locale": "en", "icons": {