Add full notification preferences system
Users can now control which in-app and email notifications they receive from their Settings tab on their channel page. Bell (in-app) preferences: - New comment on my video (default: on) - Reply to my comment (default: on) - Comment liked (default: on) - Video liked (default: on) - New subscriber (default: on) - New video from channels I follow (default: on) - New post from channels I follow (default: on) - New user registration — super admins only (default: on) Email preferences (same set plus): - Comment liked (default: off — too noisy) - Video liked (default: off — too noisy) - New post from channels I follow (default: off) - My video finished processing (default: on) - Weekly activity digest every Monday (default: on) - New user registration — super admins only (default: on) Implementation: - Migration: notification_preferences JSON column on users table - User::notificationPref($key) helper with typed defaults - All existing notification classes updated to check prefs in via() - 4 new notification classes: NewSubscriberNotification, VideoLikedNotification, NewPostNotification, WeeklyDigestNotification - 8 new email views matching existing dark theme - SendWeeklyDigest artisan command, scheduled every Monday 09:00 - NewSubscriberNotification wired into UserController::toggleSubscribe - VideoLikedNotification wired into UserController::toggleLike - NewPostNotification wired into PostController::store (to all subscribers) - Bell renderer updated for new_subscriber, video_like, new_post types - Preferences saved via AJAX (POST /settings/notifications) — instant toggle with automatic revert on failure Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
1 parent
3fe167e33f
commit
f8d13457fa
26 files changed
+808
-18
No files matched your search
@@ -7,6 +7,8 @@ use App\Models\AuditLog;
|
||||
use App\Models\Post;
|
||||
use App\Models\User;
|
||||
use App\Models\Video;
|
||||
use App\Notifications\NewSubscriberNotification;
|
||||
use App\Notifications\VideoLikedNotification;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
@@ -151,6 +153,22 @@ class UserController extends Controller
|
||||
return redirect()->route('channel')->with('toast_success', 'Password updated!')->with('_open_tab', 'settings');
|
||||
}
|
||||
|
||||
// Save a single notification preference toggle (AJAX)
|
||||
public function updateNotificationPreferences(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'key' => ['required', 'string', 'in:' . implode(',', array_keys(User::notifDefaults()))],
|
||||
'value' => ['required', 'boolean'],
|
||||
]);
|
||||
|
||||
$user = Auth::user();
|
||||
$prefs = $user->notification_preferences ?? [];
|
||||
$prefs[$request->key] = (bool) $request->value;
|
||||
$user->update(['notification_preferences' => $prefs]);
|
||||
|
||||
return response()->json(['ok' => true]);
|
||||
}
|
||||
|
||||
// Logout all other devices
|
||||
public function logoutAllDevices(Request $request)
|
||||
{
|
||||
@@ -348,6 +366,9 @@ class UserController extends Controller
|
||||
} else {
|
||||
$video->likes()->attach($user->id);
|
||||
$liked = true;
|
||||
if ($video->user_id && $video->user_id !== $user->id) {
|
||||
try { $video->user->notify(new VideoLikedNotification($video, $user)); } catch (\Throwable) {}
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
@@ -370,6 +391,7 @@ class UserController extends Controller
|
||||
} else {
|
||||
$me->subscriptions()->attach($user->id);
|
||||
$subscribed = true;
|
||||
try { $user->notify(new NewSubscriberNotification($me)); } catch (\Throwable) {}
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
|
||||
Reference in new issue
Block a user