Implement push notifications

This commit is contained in:
Toby Zerner 2015-08-04 21:22:59 +09:30
parent f0100ca7c0
commit 807c9295a4
4 changed files with 99 additions and 12 deletions

View File

@ -11,7 +11,19 @@ app.initializers.add('pusher', () => {
const loadPusher = m.deferred();
$.getScript('//js.pusher.com/3.0/pusher.min.js', () => {
loadPusher.resolve(new Pusher(app.forum.attribute('pusherKey')).subscribe('public'));
const socket = new Pusher(app.forum.attribute('pusherKey'), {
authEndpoint: app.forum.attribute('apiUrl') + '/pusher/auth',
auth: {
headers: {
'Authorization': 'Token ' + app.session.token
}
}
});
loadPusher.resolve({
main: socket.subscribe('public'),
user: app.session.user ? socket.subscribe('private-user' + app.session.user.id()) : null
});
});
app.pusher = loadPusher.promise;
@ -20,8 +32,8 @@ app.initializers.add('pusher', () => {
extend(DiscussionList.prototype, 'config', function(x, isInitialized, context) {
if (isInitialized) return;
app.pusher.then(channel => {
channel.bind('newPost', data => {
app.pusher.then(channels => {
channels.main.bind('newPost', data => {
const params = this.props.params;
if (!params.q && !params.sort) {
@ -43,7 +55,7 @@ app.initializers.add('pusher', () => {
}
});
context.onunload = () => channel.unbind();
context.onunload = () => channels.main.unbind();
});
});
@ -75,8 +87,8 @@ app.initializers.add('pusher', () => {
extend(DiscussionPage.prototype, 'config', function(x, isInitialized, context) {
if (isInitialized) return;
app.pusher.then(channel => {
channel.bind('newPost', data => {
app.pusher.then(channels => {
channels.main.bind('newPost', data => {
if (this.discussion && this.discussion.id() === data.discussionId && this.stream) {
const oldCount = this.discussion.commentsCount();
@ -92,11 +104,23 @@ app.initializers.add('pusher', () => {
}
});
context.onunload = () => channel.unbind();
context.onunload = () => channels.main.unbind();
});
});
extend(IndexPage.prototype, 'actionItems', items => {
delete items.refresh;
});
app.pusher.then(channels => {
if (channels.user) {
channels.user.bind('notification', () => {
app.session.user.pushAttributes({
unreadNotificationsCount: app.session.user.unreadNotificationsCount() + 1
});
delete app.cache.notifications;
m.redraw();
});
}
});
});

View File

@ -0,0 +1,37 @@
<?php namespace Flarum\Pusher\Api;
use Flarum\Api\Actions\JsonApiAction;
use Flarum\Api\Request;
use Flarum\Core\Settings\SettingsRepository;
use Zend\Diactoros\Response\JsonResponse;
use Zend\Diactoros\Response\EmptyResponse;
use Pusher;
class AuthAction extends JsonApiAction
{
protected $settings;
public function __construct(SettingsRepository $settings)
{
$this->settings = $settings;
}
protected function respond(Request $request)
{
$userChannel = 'private-user' . $request->actor->id;
if ($request->get('channel_name') === $userChannel) {
$pusher = new Pusher(
$this->settings->get('pusher.app_key'),
$this->settings->get('pusher.app_secret'),
$this->settings->get('pusher.app_id')
);
$payload = json_decode($pusher->socket_auth($userChannel, $request->get('socket_id')), true);
return new JsonResponse($payload);
}
return new EmptyResponse(403);
}
}

View File

@ -1,6 +1,7 @@
<?php namespace Flarum\Pusher\Listeners;
use Flarum\Events\ApiAttributes;
use Flarum\Events\RegisterApiRoutes;
use Illuminate\Contracts\Events\Dispatcher;
use Flarum\Api\Serializers\ForumSerializer;
@ -9,6 +10,7 @@ class AddApiAttributes
public function subscribe(Dispatcher $events)
{
$events->listen(ApiAttributes::class, [$this, 'addAttributes']);
$events->listen(RegisterApiRoutes::class, [$this, 'addRoutes']);
}
public function addAttributes(ApiAttributes $event)
@ -17,4 +19,9 @@ class AddApiAttributes
$event->attributes['pusherKey'] = app('Flarum\Core\Settings\SettingsRepository')->get('pusher.app_key');
}
}
public function addRoutes(RegisterApiRoutes $event)
{
$event->post('/pusher/auth', 'pusher.auth', 'Flarum\Pusher\Api\AuthAction');
}
}

View File

@ -1,6 +1,7 @@
<?php namespace Flarum\Pusher\Listeners;
use Flarum\Events\PostWasPosted;
use Flarum\Events\NotificationWillBeSent;
use Illuminate\Contracts\Events\Dispatcher;
use Flarum\Core\Settings\SettingsRepository;
use Flarum\Core\Users\Guest;
@ -19,16 +20,13 @@ class PushNewPosts
public function subscribe(Dispatcher $events)
{
$events->listen(PostWasPosted::class, [$this, 'pushNewPost']);
$events->listen(NotificationWillBeSent::class, [$this, 'pushNotification']);
}
public function pushNewPost(PostWasPosted $event)
{
if ($event->post->isVisibleTo(new Guest)) {
$pusher = new Pusher(
$this->settings->get('pusher.app_key'),
$this->settings->get('pusher.app_secret'),
$this->settings->get('pusher.app_id')
);
$pusher = $this->getPusher();
$pusher->trigger('public', 'newPost', [
'postId' => $event->post->id,
@ -37,4 +35,25 @@ class PushNewPosts
]);
}
}
public function pushNotification(NotificationWillBeSent $event)
{
$pusher = $this->getPusher();
$blueprint = $event->blueprint;
foreach ($event->users as $user) {
if ($user->shouldAlert($blueprint::getType())) {
$pusher->trigger('private-user' . $user->id, 'notification', null);
}
}
}
protected function getPusher()
{
return new Pusher(
$this->settings->get('pusher.app_key'),
$this->settings->get('pusher.app_secret'),
$this->settings->get('pusher.app_id')
);
}
}