Skip to content

Commit c3f0ba3

Browse files
committed
Realtime Notifications
1 parent 656bb73 commit c3f0ba3

26 files changed

+763
-83
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ php artisan queue:work
7777
- [ ] Video Playlists
7878
- [ ] Video Player - Google IMA Pre Roll Plugin
7979
- [ ] Video Player - VAST Ad Plugin
80-
- [ ] User Notification
80+
- [ ] ~~Realtime Notifications ( Dis/Like, Un/Subscribe Channel, Comments )~~
8181
- [ ] Admin Panel
8282

8383
## Credits

app/Console/Commands/ConvertVideoForStreaming.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public function handle()
6767
'progress' => $progress
6868
]);
6969
$this->info("Progress : {$progress}%");
70-
broadcast(new VideoProgress());
70+
broadcast(new VideoProgress($video->channel->id));
7171
})
7272
->toDisk($video->disk)
7373
->save($name)
@@ -82,7 +82,7 @@ public function handle()
8282
'progress' => 100,
8383
'status' => 'ready'
8484
]);
85-
broadcast(new VideoProgress());
85+
broadcast(new VideoProgress($video->channel->id));
8686
$this->info('Done!!');
8787
}catch (\Exception $e) {
8888
$video->update([

app/Events/DynamicChannel.php

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace App\Events;
4+
5+
use Illuminate\Broadcasting\Channel;
6+
use Illuminate\Broadcasting\InteractsWithSockets;
7+
use Illuminate\Broadcasting\PresenceChannel;
8+
use Illuminate\Broadcasting\PrivateChannel;
9+
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
10+
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
11+
use Illuminate\Foundation\Events\Dispatchable;
12+
use Illuminate\Queue\SerializesModels;
13+
14+
class DynamicChannel implements ShouldBroadcastNow
15+
{
16+
use Dispatchable, InteractsWithSockets, SerializesModels;
17+
18+
public $name;
19+
20+
/**
21+
* Create a new event instance.
22+
*
23+
* @return void
24+
*/
25+
public function __construct($name)
26+
{
27+
$this->name = $name;
28+
}
29+
30+
/**
31+
* Get the channels the event should broadcast on.
32+
*
33+
* @return \Illuminate\Broadcasting\Channel|array
34+
*/
35+
public function broadcastOn()
36+
{
37+
return new Channel($this->name);
38+
}
39+
}

app/Events/LiveCount.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
use Illuminate\Broadcasting\PresenceChannel;
88
use Illuminate\Broadcasting\PrivateChannel;
99
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
10+
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
1011
use Illuminate\Foundation\Events\Dispatchable;
1112
use Illuminate\Queue\SerializesModels;
1213

13-
class LiveCount implements ShouldBroadcast
14+
class LiveCount implements ShouldBroadcastNow
1415
{
1516
use Dispatchable, InteractsWithSockets, SerializesModels;
1617

app/Events/UserNotifications.php

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace App\Events;
4+
5+
use Illuminate\Broadcasting\Channel;
6+
use Illuminate\Broadcasting\InteractsWithSockets;
7+
use Illuminate\Broadcasting\PresenceChannel;
8+
use Illuminate\Broadcasting\PrivateChannel;
9+
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
10+
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
11+
use Illuminate\Foundation\Events\Dispatchable;
12+
use Illuminate\Queue\SerializesModels;
13+
14+
class UserNotifications implements ShouldBroadcastNow
15+
{
16+
use Dispatchable, InteractsWithSockets, SerializesModels;
17+
18+
public $user;
19+
20+
/**
21+
* Create a new event instance.
22+
*
23+
* @param $user
24+
*/
25+
public function __construct($user)
26+
{
27+
$this->user = $user;
28+
}
29+
30+
/**
31+
* Get the channels the event should broadcast on.
32+
*
33+
* @return \Illuminate\Broadcasting\Channel|array
34+
*/
35+
public function broadcastOn()
36+
{
37+
return new PrivateChannel('user.notifications.'. $this->user->id);
38+
}
39+
}

app/Events/VideoProgress.php

+7-4
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,24 @@
77
use Illuminate\Broadcasting\PresenceChannel;
88
use Illuminate\Broadcasting\PrivateChannel;
99
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
10+
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
1011
use Illuminate\Foundation\Events\Dispatchable;
1112
use Illuminate\Queue\SerializesModels;
1213

13-
class VideoProgress implements ShouldBroadcast
14+
class VideoProgress implements ShouldBroadcastNow
1415
{
1516
use Dispatchable, InteractsWithSockets, SerializesModels;
1617

18+
public $id;
19+
1720
/**
1821
* Create a new event instance.
1922
*
2023
* @return void
2124
*/
22-
public function __construct()
25+
public function __construct($id)
2326
{
24-
//
27+
$this->id = $id;
2528
}
2629

2730
/**
@@ -31,6 +34,6 @@ public function __construct()
3134
*/
3235
public function broadcastOn()
3336
{
34-
return new Channel('progress');
37+
return new PrivateChannel('video.progress.'.$this->id);
3538
}
3639
}

app/Http/Livewire/Channel/Table/VideosTable.php

+10-7
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,20 @@ class VideosTable extends DataTableComponent
1414
{
1515
public $channel_id;
1616

17-
protected $listeners = [
18-
'videoUploaded' => '$refresh',
19-
'videoDeleted' => '$refresh',
20-
'videoUpdated' => '$refresh',
21-
'echo:progress,VideoProgress' => '$refresh'
22-
];
23-
2417
public array $bulkActions = [
2518
'restartTranscoding' => 'Restart Transcoding',
2619
];
2720

21+
protected function getListeners()
22+
{
23+
return [
24+
'videoUploaded' => '$refresh',
25+
'videoDeleted' => '$refresh',
26+
'videoUpdated' => '$refresh',
27+
"echo-private:video.progress.{$this->channel_id},VideoProgress" => '$refresh'
28+
];
29+
}
30+
2831
public function restartTranscoding()
2932
{
3033
if (count($this->selectedKeys)) {

app/Http/Livewire/Components/ChannelProfile.php

+8-4
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@ class ChannelProfile extends Component
1414
public $picture;
1515
public $count;
1616

17-
protected $listeners = [
18-
'channelSubscribed' => 'getData',
19-
'channelUnsubscribed' => 'getData',
20-
];
17+
public function getListeners()
18+
{
19+
return [
20+
'channelSubscribed' => 'getData',
21+
'channelUnsubscribed' => 'getData',
22+
"echo:{$this->channel->slug}.channel.subscribed,DynamicChannel" => 'getData'
23+
];
24+
}
2125

2226
public function mount()
2327
{

app/Http/Livewire/Components/Comment.php

+24-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
namespace App\Http\Livewire\Components;
44

5+
use App\Events\DynamicChannel;
56
use App\Models\Channel\Video;
7+
use App\Notifications\SendNotification;
68
use Livewire\Component;
79
use Livewire\WithPagination;
810

@@ -18,12 +20,16 @@ class Comment extends Component
1820

1921
public $perPage = 5;
2022

21-
protected $listeners = [
22-
'commentCreated' => 'getData',
23-
'commentDeleted' => 'getData',
24-
'commentUpdated' => 'getData',
25-
'settingsUpdated' => 'getData'
26-
];
23+
protected function getListeners()
24+
{
25+
return [
26+
'commentCreated' => 'getData',
27+
'commentDeleted' => 'getData',
28+
'commentUpdated' => 'getData',
29+
'settingsUpdated' => 'getData',
30+
"echo:{$this->video->media_id}.video.comments,DynamicChannel" => 'getData'
31+
];
32+
}
2733

2834
public function mount()
2935
{
@@ -52,6 +58,18 @@ public function submit()
5258
$comment->comment = $validated['comment'];
5359
$comment->save();
5460

61+
if ($this->video->channel->owner->id != auth()->user()->id)
62+
{
63+
$this->video->channel->owner->notify(new SendNotification([
64+
'type' => 'comment',
65+
'on' => $this->video,
66+
'by' => $this->commenter,
67+
'media_id' => $this->video->media_id
68+
]));
69+
}
70+
71+
broadcast(new DynamicChannel("{$this->video->media_id}.video.comments"));
72+
5573
$this->comment = '';
5674
$this->emit('commentCreated');
5775
}

app/Http/Livewire/Components/LikeDislikeButton.php

+20-4
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,24 @@
22

33
namespace App\Http\Livewire\Components;
44

5+
use App\Events\DynamicChannel;
56
use App\Models\Channel\Video;
7+
use App\Notifications\SendNotification;
68
use Livewire\Component;
79

810
class LikeDislikeButton extends Component
911
{
1012
public $video_id;
1113
public $video;
1214

13-
protected $listeners = [
14-
'videoLiked' => 'getData',
15-
'videoDisliked' => 'getData',
16-
];
15+
protected function getListeners()
16+
{
17+
return [
18+
'videoLiked' => 'getData',
19+
'videoDisliked' => 'getData',
20+
"echo:{$this->video->media_id}.video.liked,DynamicChannel" => 'getData'
21+
];
22+
}
1723

1824
public function mount()
1925
{
@@ -32,8 +38,17 @@ public function likeVideo()
3238
auth()->user()->cancelVote($this->video);
3339
}else{
3440
auth()->user()->upVote($this->video);
41+
if ($this->video->channel->owner->id != auth()->user()->id)
42+
{
43+
$this->video->channel->owner->notify(new SendNotification([
44+
'type' => 'liked',
45+
'on' => $this->video,
46+
'by' => auth()->user(),
47+
]));
48+
}
3549
}
3650
$this->emit('videoLiked');
51+
broadcast(new DynamicChannel("{$this->video->media_id}.video.liked"));
3752
}
3853

3954
public function dislikeVideo()
@@ -45,6 +60,7 @@ public function dislikeVideo()
4560
auth()->user()->downVote($this->video);
4661
}
4762
$this->emit('videoDisliked');
63+
broadcast(new DynamicChannel("{$this->video->media_id}.video.liked"));
4864
}
4965

5066
public function render()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
namespace App\Http\Livewire\Components;
4+
5+
use Illuminate\Notifications\Events\BroadcastNotificationCreated;
6+
use Livewire\Component;
7+
use Livewire\WithPagination;
8+
9+
class Notification extends Component
10+
{
11+
use WithPagination;
12+
13+
public $perPage = 5;
14+
15+
public function getListeners()
16+
{
17+
$id = auth()->user()->id;
18+
return [
19+
"echo-private:user.notifications.{$id},UserNotifications" => '$refresh',
20+
'markAllAsRead' => '$refresh',
21+
];
22+
}
23+
24+
public function loadMore()
25+
{
26+
$this->perPage = $this->perPage + 5;
27+
}
28+
29+
public function render()
30+
{
31+
return view('livewire.components.notification')->with([
32+
'notifications' => paginate(auth()->user()->unreadNotifications, $this->perPage)
33+
]);
34+
}
35+
36+
public function markAllAsRead()
37+
{
38+
auth()->user()->unreadNotifications->markAsRead();
39+
$this->emit('markAllAsRead');
40+
}
41+
}

app/Http/Livewire/Components/SubscribeButton.php

+12
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
namespace App\Http\Livewire\Components;
44

5+
use App\Events\DynamicChannel;
56
use App\Events\LiveCount;
67
use App\Models\Channel\Channel;
8+
use App\Notifications\SendNotification;
79
use Livewire\Component;
810

911
class SubscribeButton extends Component
@@ -38,12 +40,22 @@ public function subscribeChannel()
3840
auth()->user()->subscribe($this->channel);
3941
$this->emit('channelSubscribed');
4042
broadcast(new LiveCount($this->channel->slug));
43+
broadcast(new DynamicChannel("{$this->channel->slug}.channel.subscribed"));
44+
if ($this->channel->owner->id != auth()->user()->id)
45+
{
46+
$this->channel->owner->notify(new SendNotification([
47+
'type' => 'subscribed',
48+
'on' => $this->channel,
49+
'by' => auth()->user(),
50+
]));
51+
}
4152
}
4253

4354
public function unsubscribeChannel()
4455
{
4556
auth()->user()->unsubscribe($this->channel);
4657
$this->emit('channelUnsubscribed');
4758
broadcast(new LiveCount($this->channel->slug));
59+
broadcast(new DynamicChannel("{$this->channel->slug}.channel.subscribed"));
4860
}
4961
}

0 commit comments

Comments
 (0)