diff --git a/lib/App.php b/lib/App.php index 192e100ae..6cb010088 100644 --- a/lib/App.php +++ b/lib/App.php @@ -45,12 +45,17 @@ public function __construct(Handler $handler, Push $push) { public function notify(INotification $notification): void { $notificationId = $this->handler->add($notification); + $shouldFlush = $this->push->deferPayloads(); try { $notificationToPush = $this->handler->getById($notificationId, $notification->getUser()); $this->push->pushToDevice($notificationId, $notificationToPush); } catch (NotificationNotFoundException $e) { throw new \InvalidArgumentException('Error while preparing push notification'); } + + if ($shouldFlush) { + $this->push->flushPayloads(); + } } /** @@ -69,10 +74,23 @@ public function getCount(INotification $notification): int { public function markProcessed(INotification $notification): void { $deleted = $this->handler->delete($notification); + $shouldFlush = $this->push->deferPayloads(); foreach ($deleted as $user => $notifications) { foreach ($notifications as $notificationId) { $this->push->pushDeleteToDevice($user, $notificationId); } } + + if ($shouldFlush) { + $this->push->flushPayloads(); + } + } + + public function defer(): void { + $this->push->deferPayloads(); + } + + public function flush(): void { + $this->push->flushPayloads(); } } diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 6a9de02b8..517827bfb 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -26,7 +26,10 @@ use OCA\Notifications\Capabilities; use OCA\Notifications\Handler; use OCA\Notifications\Notifier\AdminNotifications; +use OCA\Notifications\Push; use OCP\AppFramework\IAppContainer; +use OCP\EventDispatcher\IEventDispatcher; +use OCP\Notification\IApp; use OCP\Util; class Application extends \OCP\AppFramework\App { @@ -44,6 +47,7 @@ public function __construct() { public function register(): void { $this->registerNotificationApp(); + $this->registerTalkDeferPushing(); $this->registerAdminNotifications(); $this->registerUserInterface(); $this->registerUserDeleteHook(); @@ -77,6 +81,22 @@ protected function registerUserInterface(): void { } } + protected function registerTalkDeferPushing(): void { + /** @var IEventDispatcher $dispatcher */ + $dispatcher = $this->getContainer()->getServer()->query(IEventDispatcher::class); + + $dispatcher->addListener(IApp::class . '::defer', function() { + /** @var App $app */ + $app = $this->getContainer()->query(App::class); + $app->defer(); + }); + $dispatcher->addListener(IApp::class . '::flush', function() { + /** @var App $app */ + $app = $this->getContainer()->query(App::class); + $app->flush(); + }); + } + protected function registerUserDeleteHook(): void { Util::connectHook('OC_User', 'post_deleteUser', $this, 'deleteUser'); } diff --git a/lib/Push.php b/lib/Push.php index e059f185f..2b6c0aedb 100644 --- a/lib/Push.php +++ b/lib/Push.php @@ -97,7 +97,6 @@ public function pushToDevice(int $id, INotification $notification): void { }); $hasTalkApps = !empty($talkApps); - $pushNotifications = []; foreach ($devices as $device) { if (!$isTalkNotification && $device['apptype'] === 'talk') { // The iOS app can not kill notifications, @@ -118,8 +117,8 @@ public function pushToDevice(int $id, INotification $notification): void { $payload = json_encode($this->encryptAndSign($userKey, $device, $id, $notification, $isTalkNotification)); $proxyServer = rtrim($device['proxyserver'], '/'); - if (!isset($pushNotifications[$proxyServer])) { - $pushNotifications[$proxyServer] = []; + if (!isset($this->payloadsToSend[$proxyServer])) { + $this->payloadsToSend[$proxyServer] = []; } $pushNotifications[$proxyServer][] = $payload; } catch (InvalidTokenException $e) { @@ -131,7 +130,9 @@ public function pushToDevice(int $id, INotification $notification): void { } } - $this->sendNotificationsToProxies($pushNotifications); + if (!$this->deferPayloads) { + $this->sendNotificationsToProxies(); + } } public function pushDeleteToDevice(string $userId, int $notificationId): void { @@ -146,14 +147,13 @@ public function pushDeleteToDevice(string $userId, int $notificationId): void { } $userKey = $this->keyManager->getKey($user); - $pushNotifications = []; foreach ($devices as $device) { try { $payload = json_encode($this->encryptAndSignDelete($userKey, $device, $notificationId)); $proxyServer = rtrim($device['proxyserver'], '/'); - if (!isset($pushNotifications[$proxyServer])) { - $pushNotifications[$proxyServer] = []; + if (!isset($this->payloadsToSend[$proxyServer])) { + $this->payloadsToSend[$proxyServer] = []; } $pushNotifications[$proxyServer][] = $payload; } catch (InvalidTokenException $e) { @@ -165,10 +165,14 @@ public function pushDeleteToDevice(string $userId, int $notificationId): void { } } - $this->sendNotificationsToProxies($pushNotifications); + if (!$this->deferPayloads) { + $this->sendNotificationsToProxies(); + } } - protected function sendNotificationsToProxies(array $pushNotifications): void { + protected function sendNotificationsToProxies(): void { + $pushNotifications = $this->payloadsToSend; + $this->payloadsToSend = []; if (empty($pushNotifications)) { return; }