Mail widerherstellen, Snooze-Funktion (WIP)#588
Conversation
WalkthroughDie E-Mail-Verwaltung erhält eine Snoozed-Ansicht, lädt Soft-Deleted-Mails und trennt das Verschieben in den Papierkorb von der Wiederherstellung. Die React-Oberfläche bietet dafür neue Navigationseinträge, ansichtsabhängige Aktionen und einen Undo-Workflow. ChangesE-Mail-Lebenszyklus
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant EmailIndex
participant EmailRoutes
participant EmailController
participant DropboxMail
EmailIndex->>EmailRoutes: Papierkorb- oder Restore-Aktion
EmailRoutes->>EmailController: trash() oder restore()
EmailController->>DropboxMail: delete() oder restore()
EmailController-->>EmailIndex: Weiterleitung zur Mail-Ansicht
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 PHPStan (2.2.5)PHPStan was skipped because the config uses disallowed 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
app/Http/Controllers/App/EmailController.php (1)
222-246: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winVerwende
redirect()->back()um die aktuelle Ansicht beizubehalten.Derzeit leiten
restoreundtrashhart aufapp.email.indexweiter. Dadurch geht der aktuelleview-Query-Parameter verloren und der Benutzer wird unfreiwillig in den Posteingang (inbox) zurückgeworfen (z. B. wenn er sich im Papierkorb befindet und auf "Undo" klickt).
Um konsistent zu den bestehenden Methoden wiearchive()zu bleiben und die aktuelle Ansicht des Nutzers intakt zu lassen, nutze stattdessenredirect()->back().💡 Lösungsvorschlag
public function restore(Dropbox $dropbox, DropboxMail $mail): RedirectResponse { if ( (! $dropbox->is_shared && $dropbox->user_id !== auth()->id()) || $mail->dropbox_id !== $dropbox->id ) { abort(403); } $mail->restore(); - return redirect(route('app.email.index', ['dropbox' => $dropbox->id])); + return redirect()->back(); } public function trash(Dropbox $dropbox, DropboxMail $mail): RedirectResponse { if ( (! $dropbox->is_shared && $dropbox->user_id !== auth()->id()) || $mail->dropbox_id !== $dropbox->id ) { abort(403); } $mail->delete(); - return redirect(route('app.email.index', ['dropbox' => $dropbox->id])); + return redirect()->back(); }🤖 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 `@app/Http/Controllers/App/EmailController.php` around lines 222 - 246, Update the restore and trash methods in EmailController to return redirect()->back() after completing their mail operation, preserving the current view query parameter and matching the behavior of archive(). Keep the existing authorization checks and restore/delete calls unchanged.
🧹 Nitpick comments (3)
resources/js/Pages/App/Email/EmailIndex.tsx (3)
35-45: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueEntferne ungenutzten Code (
handleDelete).Nach der Einführung von
handleTrashscheint diese Methode redundant zu sein. Sie wird im bereitgestellten Codeausschnitt nicht mehr für den Toolbar verwendet. DahandleTrasheinen komfortableren Undo-Toast anstelle eines Bestätigungsdialogs bietet, kannhandleDeletewahrscheinlich restlos entfernt werden.🤖 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 `@resources/js/Pages/App/Email/EmailIndex.tsx` around lines 35 - 45, Remove the unused handleDelete function from EmailIndex, including its confirmation-dialog logic, and retain the existing handleTrash flow as the sole deletion action.
47-50: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMemoisiere
handleRestoremituseCallback.Da
handleRestoreinnerhalb desonSuccess-Callbacks vonhandleTrash(Zeile 74) referenziert wird, sollte die Methode mituseCallbackmemoisiert und als Abhängigkeit registriert werden. Das vermeidet veraltete Closures und erfüllt die React-Hooks-Regeln.♻️ Refactoring-Vorschlag
- const handleRestore = async () => { - if (!mail) return - router.put(route('app.email.restore', { dropbox: dropbox.id, mail: mail.id })) - } + const handleRestore = useCallback(async () => { + if (!mail) return + router.put(route('app.email.restore', { dropbox: dropbox.id, mail: mail.id })) + }, [mail, dropbox.id])Vergiss nicht,
handleRestoredanach im Dependency-Array vonhandleTrash(Zeile 80) hinzuzufügen:}, [mail?.id, dropbox.id, handleRestore])🤖 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 `@resources/js/Pages/App/Email/EmailIndex.tsx` around lines 47 - 50, Memoize handleRestore with useCallback, preserving its existing mail guard and restore navigation while declaring the values it uses as dependencies. Add handleRestore to handleTrash’s dependency array so the onSuccess callback uses the current restore handler and satisfies the Hooks rules.
33-33: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winSetze einen Fallback für die aktuelle Ansicht.
Wenn kein
view-Parameter in der URL existiert (wie beim direkten Aufruf von/app/emails/...), istroute().params.viewundefined. Ein expliziter Fallback auf'inbox'stellt sicher, dass der Wert konsistent ist und Typ-Fehler in Folgekomponenten wieEmailIndexEntryvermieden werden.💡 Lösungsvorschlag
- const view = route().params.view + const view = (route().params.view as string) ?? 'inbox'Anschließend kannst du in Zeile 205 bei
EmailIndexEntryebenfalls den gesicherten Wert nutzen:view={view as 'inbox' | ...}.🤖 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 `@resources/js/Pages/App/Email/EmailIndex.tsx` at line 33, Set a default of 'inbox' when assigning the current view from route().params.view, and update the EmailIndexEntry usage to pass this normalized view value rather than the potentially undefined route parameter. Preserve the existing view typing for other supported values.
🤖 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 `@app/Models/DropboxMail.php`:
- Line 75: Update the default branch of the query in DropboxMail to exclude
emails with an active snooze: retain only records whose snoozed_until is null or
has already elapsed, while preserving the existing archived_at and is_inbound
filters.
---
Outside diff comments:
In `@app/Http/Controllers/App/EmailController.php`:
- Around line 222-246: Update the restore and trash methods in EmailController
to return redirect()->back() after completing their mail operation, preserving
the current view query parameter and matching the behavior of archive(). Keep
the existing authorization checks and restore/delete calls unchanged.
---
Nitpick comments:
In `@resources/js/Pages/App/Email/EmailIndex.tsx`:
- Around line 35-45: Remove the unused handleDelete function from EmailIndex,
including its confirmation-dialog logic, and retain the existing handleTrash
flow as the sole deletion action.
- Around line 47-50: Memoize handleRestore with useCallback, preserving its
existing mail guard and restore navigation while declaring the values it uses as
dependencies. Add handleRestore to handleTrash’s dependency array so the
onSuccess callback uses the current restore handler and satisfies the Hooks
rules.
- Line 33: Set a default of 'inbox' when assigning the current view from
route().params.view, and update the EmailIndexEntry usage to pass this
normalized view value rather than the potentially undefined route parameter.
Preserve the existing view typing for other supported values.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: dcfb9c08-32d7-419b-a545-8d4e2eef7440
📒 Files selected for processing (6)
app/Http/Controllers/App/EmailController.phpapp/Models/DropboxMail.phpdatabase/migrations/tenant/2026_07_14_131215_add_snoozed_to_dropbox_mails.phpresources/js/Pages/App/Email/EmailIndex.tsxresources/js/Pages/App/Email/EmailView.tsxroutes/tenant.php
Summary by CodeRabbit
Neue Funktionen
Verbesserungen