Skip to content

feat: add drag and drop support for opening images#62

Merged
amemya merged 8 commits into
mainfrom
feat/issue-50-drag-drop
Jun 12, 2026
Merged

feat: add drag and drop support for opening images#62
amemya merged 8 commits into
mainfrom
feat/issue-50-drag-drop

Conversation

@amemya

@amemya amemya commented Jun 12, 2026

Copy link
Copy Markdown
Owner

DDによる追加

(Fixes #50 )

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: beb44c17-9f65-4abb-969c-9b2b6f8f11d6

📥 Commits

Reviewing files that changed from the base of the PR and between 1e85a15 and d92622f.

📒 Files selected for processing (2)
  • frontend/src/App.css
  • frontend/src/App.tsx

📝 Walkthrough

Summary by CodeRabbit

  • 新機能
    • 画像のドラッグ&ドロップアップロードを追加(JPG/JPEG/PNG対応、1ファイルのみ処理)。
  • UI改善
    • ドラッグ時の全面オーバーレイ表示と「Drop image here」案内を追加。
    • プレビュー領域の案内文を「クリック/ドラッグ」に更新。
  • 信頼性向上
    • プレビュー読み込みとエラー時の復帰処理を統一し、多重起動を抑止、失敗時に通知を表示。

Walkthrough

バックエンドで EXIF 処理を公開化(ProcessImageFile)、Wails ウィンドウでファイルドロップを有効化、フロントエンドにドラッグ&ドロップ UI・購読・処理統合(handleExifResult)を追加してプレビュー領域でドラッグ登録を実装しました。

Changes

ドラッグアンドドロップによるファイル追加機能

Layer / File(s) Summary
バックエンド画像処理API公開化
app.go, watcher.go
processImageFileProcessImageFile に改名・公開化し、OpenImage とバックグラウンド処理からの呼び出しを更新。
ウィンドウレベルのファイルドロップ有効化
main.go
Wails ウィンドウで EnableFileDrop を有効化し、WindowFilesDropped を購読して files-dropped イベントをフロントエンドへ配信するハンドラを追加。
フロントエンドのドラッグ&ドロップ UI とスタイル
frontend/src/App.css, frontend/src/App.tsx
プレビュー領域にドラッグオーバーレイ(.drop-overlay / .drop-overlay-text)と DOM を追加し、空状態テキストを「クリックまたはドラッグ」に変更。
ドロップファイル処理とプレビュー更新統合
frontend/src/App.tsx
files-dropped 購読で配列/単体の差分を吸収し単数かつ JPG/JPEG/PNG の場合に ProcessImageFile を呼び出して handleExifResult でプレビュー/EXIF 状態を一元更新。OpenImage の結果処理も handleExifResult に統一。

Sequence Diagram

sequenceDiagram
  participant User as ユーザー
  participant Wails as Wailsウィンドウ
  participant Frontend as App.tsx
  participant Backend as バックエンドAPI
  User->>Wails: ファイルをドラッグアンドドロップ
  Wails->>Frontend: files-dropped イベント配信
  Frontend->>Frontend: 拡張子チェック / 単数チェック
  alt JPG/PNG ファイルの場合
    Frontend->>Backend: ProcessImageFile(filePath)
    Backend->>Frontend: ExifResult 返却
    Frontend->>Frontend: handleExifResult で状態更新(画像/EXIF等)およびプレビュー表示
  else その他の拡張子
    Frontend->>Frontend: トーストで非対応を表示
  end
  Frontend->>Frontend: 選択状態を復帰
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • amemya/ExifFrame#44: app.go の画像抽出パスを別手法(ストリームベース)で改修した PR と重複する箇所があります。
  • amemya/ExifFrame#11: frontend/src/App.tsx の選択ガード/isSelecting ロジック変更が関連します。
  • amemya/ExifFrame#12: フロントエンドの EXIF/result ハンドリングの変更点が関連します。
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PRタイトルは「drag and drop support for opening images」とあり、変更の主要な目的であるドラッグ&ドロップ機能の追加を明確に表しており、コードベースの変更内容と対応しています。
Description check ✅ Passed PR説明は日本語で「DDによる追加」と記載されており、ドラッグ&ドロップに関連する内容を示し、また「Fixes #50」で関連するIssueを参照しています。
Linked Issues check ✅ Passed Issue #50で要求された「起動時のClick to open photoでドラッグ&ドロップ対応」「データ入力画面でのドラッグ&ドロップ対応」の両要件に対し、本PRは該当機能を実装しています。
Out of Scope Changes check ✅ Passed ProcessImageFileメソッドの公開化はドラッグ&ドロップ機能実装時の内部呼び出しの整理であり、Issue #50の要件に関連する範囲内の変更です

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-50-drag-drop

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/App.tsx`:
- Around line 701-704: The overlay is closing incorrectly because onDragLeave
toggles setIsDragging(false) even when entering child elements; change to a
drag-depth counter approach: add a ref/variable (e.g., dragCounterRef) and
increment it in the onDragEnter handler used now, decrement it in onDragLeave,
only call setIsDragging(false) when the counter reaches 0, and reset the counter
to 0 on onDrop and onDrop handler's e.preventDefault(); update the existing
onDragEnter, onDragLeave, and onDrop handlers to use this counter while keeping
setIsDragging(true) on initial enter.
- Around line 468-500: The files-dropped handler (the Events.On callback
referenced by offFilesDropped) currently silently uses only files[0], so
multiple dropped images are ignored; update the handler to detect when
files.length > 1 and explicitly notify the user (call showToast with a clear
message like "Multiple files dropped — please drop one image at a time") and
return, or alternatively handle all images by iterating over files, validating
each with the existing lower.endsWith checks and calling AppAPI.ProcessImageFile
and handleExifResult for each (ensuring you respect isSelectingRef /
setIsSelecting to avoid concurrent UI state races and setIsDragging(false)
appropriately); modify the logic inside the Events.On callback (around the
files.length checks and where files[0] is used) to implement one of these
behaviors and keep error handling consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3c6fbbe9-affe-402b-9623-7dba710306cc

📥 Commits

Reviewing files that changed from the base of the PR and between 0ef44fc and 33afbb7.

📒 Files selected for processing (5)
  • app.go
  • frontend/src/App.css
  • frontend/src/App.tsx
  • main.go
  • watcher.go

Comment thread frontend/src/App.tsx
Comment thread frontend/src/App.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/App.tsx (1)

506-508: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

非対応ファイル時のドラッグカウンタのリセットが欠けています。

Line 508 で setIsDragging(false) を設定していますが、dragCounterRef.current = 0 のリセットが抜けています。Lines 484, 494 との一貫性のため、ここでもカウンタをリセットしてください。

🛠️ 修正案
 } else {
     showToast("Invalid file: only JPG and PNG are supported.");
     setIsDragging(false);
+    dragCounterRef.current = 0;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/App.tsx` around lines 506 - 508, Invalid file branch fails to
reset the drag counter; when rejecting unsupported files you call showToast(...)
and setIsDragging(false) but forget to reset dragCounterRef.current to 0. Update
the rejection branch (the block that calls showToast and setIsDragging) to also
set dragCounterRef.current = 0 so it matches the other handlers (lines handling
drag enter/leave) and prevents stale drag counts; reference the dragCounterRef,
setIsDragging, and showToast symbols when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@frontend/src/App.tsx`:
- Around line 506-508: Invalid file branch fails to reset the drag counter; when
rejecting unsupported files you call showToast(...) and setIsDragging(false) but
forget to reset dragCounterRef.current to 0. Update the rejection branch (the
block that calls showToast and setIsDragging) to also set dragCounterRef.current
= 0 so it matches the other handlers (lines handling drag enter/leave) and
prevents stale drag counts; reference the dragCounterRef, setIsDragging, and
showToast symbols when making the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 946b004f-1ddd-41f9-8b33-c04b248d606c

📥 Commits

Reviewing files that changed from the base of the PR and between 33afbb7 and fb195b7.

📒 Files selected for processing (1)
  • frontend/src/App.tsx

- Resolve TDZ error by moving handleExifResult before its usage
- Remove React-based drag state tracking to eliminate overlay flicker
- Use Wails native CSS class for reliable drag hover
- Fix overlay sizing bug in WebKit flex containers by using inset: 0
- Reject multiple files dropped simultaneously
- Add explanatory comment to time.Sleep in watcher.go
@amemya

amemya commented Jun 12, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/App.tsx (1)

370-410: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

showToastuseCallback でメモ化して依存配列に追加してください。

handleExifResult 内で showToast を使用していますが、依存配列に含まれていません。showToast は ref と安定した state setter のみを使用しているため機能的には動作しますが、React のベストプラクティスに従っていません。

showToastuseCallback でラップし(依存配列は空配列)、handleExifResult の依存配列に追加することで、コードの保守性と意図の明確さが向上します。

♻️ 修正案

showToast 関数(Line 349 付近)を useCallback でラップ:

-    const showToast = (message: string) => {
+    const showToast = useCallback((message: string) => {
         if (toastTimerRef.current !== null) {
             window.clearTimeout(toastTimerRef.current);
             toastTimerRef.current = null;
         }
         // ... rest of function
-    };
+    }, []);

次に handleExifResult の依存配列に追加:

-    }, []);
+    }, [showToast]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/App.tsx` around lines 370 - 410, Wrap the existing showToast
function in a useCallback with an empty dependency array (so it is memoized and
stable), then add showToast to the dependency array of the useCallback that
defines handleExifResult; update the showToast declaration (the function
referenced by handleExifResult) to use useCallback([]) and ensure
handleExifResult’s dependencies include showToast so React’s hooks rules are
satisfied.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/App.css`:
- Around line 241-243: Add a brief inline comment above the CSS rule for the
selector ".preview-area.file-drop-target-active .drop-overlay" stating that the
".file-drop-target-active" class is automatically applied by the Wails runtime
to elements with the data-file-drop-target="true" attribute during drag
operations, so future readers understand this behavior and maintainers know it's
not defined elsewhere in our codebase.

In `@frontend/src/App.tsx`:
- Around line 700-705: Add a short inline comment near the preview-area element
explaining that the data-file-drop-target="true" attribute is required by the
Wails runtime to detect drag-and-drop targets and will automatically add the
.file-drop-target-active class to show the .drop-overlay; reference the
preview-area container, the data-file-drop-target attribute, the .drop-overlay
element and the .file-drop-target-active class so future maintainers understand
this Wails-specific integration point.

---

Outside diff comments:
In `@frontend/src/App.tsx`:
- Around line 370-410: Wrap the existing showToast function in a useCallback
with an empty dependency array (so it is memoized and stable), then add
showToast to the dependency array of the useCallback that defines
handleExifResult; update the showToast declaration (the function referenced by
handleExifResult) to use useCallback([]) and ensure handleExifResult’s
dependencies include showToast so React’s hooks rules are satisfied.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: fd9b39bf-c80b-4f50-90d5-19a40b49339b

📥 Commits

Reviewing files that changed from the base of the PR and between fb195b7 and 1e85a15.

📒 Files selected for processing (2)
  • frontend/src/App.css
  • frontend/src/App.tsx

Comment thread frontend/src/App.css
Comment thread frontend/src/App.tsx
@amemya amemya merged commit 160cbcf into main Jun 12, 2026
1 check passed
@amemya amemya deleted the feat/issue-50-drag-drop branch June 12, 2026 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

写真追加時にドラッグアンドドロップで追加可能にする

1 participant