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
+39
-3
@@ -43,6 +43,7 @@ class User extends Authenticatable implements MustVerifyEmail
|
||||
'two_factor_secret',
|
||||
'two_factor_enabled',
|
||||
'banner',
|
||||
'notification_preferences',
|
||||
];
|
||||
|
||||
protected $hidden = [
|
||||
@@ -51,11 +52,46 @@ class User extends Authenticatable implements MustVerifyEmail
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'email_verified_at' => 'datetime',
|
||||
'password' => 'hashed',
|
||||
'two_factor_enabled' => 'boolean',
|
||||
'email_verified_at' => 'datetime',
|
||||
'password' => 'hashed',
|
||||
'two_factor_enabled' => 'boolean',
|
||||
'notification_preferences' => 'array',
|
||||
];
|
||||
|
||||
// Defaults for each preference key (true = on, false = off)
|
||||
private const NOTIF_DEFAULTS = [
|
||||
'notif_new_comment' => true,
|
||||
'notif_new_reply' => true,
|
||||
'notif_comment_like' => true,
|
||||
'notif_video_like' => true,
|
||||
'notif_new_subscriber' => true,
|
||||
'notif_new_video_from_sub' => true,
|
||||
'notif_new_post_from_sub' => true,
|
||||
'notif_new_user_reg' => true,
|
||||
'email_new_comment' => true,
|
||||
'email_new_reply' => true,
|
||||
'email_comment_like' => false,
|
||||
'email_video_like' => false,
|
||||
'email_new_subscriber' => true,
|
||||
'email_new_video_from_sub' => true,
|
||||
'email_new_post_from_sub' => false,
|
||||
'email_video_processed' => true,
|
||||
'email_new_user_reg' => true,
|
||||
'email_weekly_digest' => true,
|
||||
];
|
||||
|
||||
public function notificationPref(string $key): bool
|
||||
{
|
||||
$prefs = $this->notification_preferences ?? [];
|
||||
$default = self::NOTIF_DEFAULTS[$key] ?? true;
|
||||
return isset($prefs[$key]) ? (bool) $prefs[$key] : $default;
|
||||
}
|
||||
|
||||
public static function notifDefaults(): array
|
||||
{
|
||||
return self::NOTIF_DEFAULTS;
|
||||
}
|
||||
|
||||
protected $appends = ['avatar_url', 'banner_url'];
|
||||
|
||||
// Auto-generate a unique slug-based username when creating a user without one
|
||||
|
||||
Reference in new issue
Block a user