feat: add persistent mobile notifications
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
abstract class MobileNotification extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public const array TYPES = [
|
||||
'certification_approved',
|
||||
'certification_rejected',
|
||||
'engagement_reminder',
|
||||
'meal_commented',
|
||||
'new_follower',
|
||||
'payment_failed',
|
||||
];
|
||||
|
||||
protected const string CATEGORY_ACCOUNT = 'account';
|
||||
|
||||
protected const string CATEGORY_ENGAGEMENT = 'engagement';
|
||||
|
||||
protected const string CATEGORY_SOCIAL = 'social';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->afterCommit();
|
||||
}
|
||||
|
||||
/** @return list<string> */
|
||||
public function via(object $notifiable): array
|
||||
{
|
||||
if ($this->category() === self::CATEGORY_ENGAGEMENT
|
||||
&& $notifiable instanceof User
|
||||
&& ! $notifiable->engagement_reminders_enabled) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$channels = ['database'];
|
||||
|
||||
if ($this->shouldSendPush($notifiable)) {
|
||||
$channels[] = 'expo';
|
||||
}
|
||||
|
||||
return $channels;
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public function toDatabase(object $notifiable): array
|
||||
{
|
||||
return [
|
||||
...$this->payload($notifiable),
|
||||
'category' => $this->category(),
|
||||
];
|
||||
}
|
||||
|
||||
public function databaseType(object $notifiable): string
|
||||
{
|
||||
return $this->payload($notifiable)['type'];
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public function toExpoPush(object $notifiable): array
|
||||
{
|
||||
$payload = $this->payload($notifiable);
|
||||
|
||||
return [
|
||||
'title' => $payload['title'],
|
||||
'body' => $payload['body'],
|
||||
'sound' => 'default',
|
||||
'channelId' => 'default',
|
||||
'data' => [
|
||||
'type' => $payload['type'],
|
||||
'url' => $payload['url'],
|
||||
...($this->id ? ['notificationId' => $this->id] : []),
|
||||
...($payload['data'] ?? []),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
abstract protected function category(): string;
|
||||
|
||||
/** @return array{type: string, title: string, body: string, url: string, data?: array<string, mixed>} */
|
||||
abstract protected function payload(object $notifiable): array;
|
||||
|
||||
private function shouldSendPush(object $notifiable): bool
|
||||
{
|
||||
if (! $notifiable instanceof User) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->category() !== self::CATEGORY_SOCIAL
|
||||
|| $notifiable->social_notifications_enabled;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user