@@ -79,6 +79,8 @@ class Push {
7979 protected $ deferPayloads = false ;
8080 /** @var array[] */
8181 protected $ deletesToPush = [];
82+ /** @var string[] */
83+ protected $ deleteAllsToPush = [];
8284 /** @var INotification[] */
8385 protected $ notificationsToPush = [];
8486
@@ -170,12 +172,18 @@ public function flushPayloads(): void {
170172 $ this ->notificationsToPush = [];
171173 }
172174
175+ if (!empty ($ this ->deleteAllsToPush )) {
176+ foreach ($ this ->deleteAllsToPush as $ userId ) {
177+ $ this ->pushDeleteToDevice ($ userId , null );
178+ }
179+ $ this ->deleteAllsToPush = [];
180+ }
181+
173182 if (!empty ($ this ->deletesToPush )) {
174- // Check for $id = 0 then only trigger delete all for that user
175- // Otherwise group by "app" (['spreed', 'talk', 'admin_notification_talk'] OR not!)
176- // And trigger each chunk per user
177- foreach ($ this ->deletesToPush as $ id => $ data ) {
178- $ this ->pushDeleteToDevice ($ data ['userId ' ], $ id , $ data ['app ' ]);
183+ foreach ($ this ->deletesToPush as $ userId => $ data ) {
184+ foreach ($ data as $ client => $ notificationIds ) {
185+ $ this ->pushDeleteToDevice ($ userId , $ notificationIds , $ client );
186+ }
179187 }
180188 $ this ->deletesToPush = [];
181189 }
@@ -313,21 +321,47 @@ public function pushToDevice(int $id, INotification $notification, ?OutputInterf
313321 }
314322 }
315323
316- public function pushDeleteToDevice (string $ userId , ?int $ notificationId , string $ app = '' ): void {
324+ /**
325+ * @param string $userId
326+ * @param ?int[] $notificationIds
327+ * @param string $app
328+ * @throws InvalidTokenException FIXME investigate
329+ */
330+ public function pushDeleteToDevice (string $ userId , ?array $ notificationIds , string $ app = '' ): void {
317331 if (!$ this ->config ->getSystemValueBool ('has_internet_connection ' , true )) {
318332 return ;
319333 }
320334
321335 if ($ this ->deferPreparing ) {
322- if ($ notificationId === null ) {
323- $ notificationId = 0 ;
336+ if ($ notificationIds === null ) {
337+ $ this ->deleteAllsToPush [$ userId ] = true ;
338+ if (isset ($ this ->deletesToPush [$ userId ])) {
339+ unset($ this ->deletesToPush [$ userId ]);
340+ }
341+ } else {
342+ if (isset ($ this ->deleteAllsToPush [$ userId ])) {
343+ return ;
344+ }
345+
346+ $ isTalkNotification = \in_array ($ app , ['spreed ' , 'talk ' , 'admin_notification_talk ' ], true );
347+ $ clientGroup = $ isTalkNotification ? 'talk ' : 'files ' ;
348+
349+ if (!isset ($ this ->deletesToPush [$ userId ])) {
350+ $ this ->deletesToPush [$ userId ] = [];
351+ }
352+ if (!isset ($ this ->deletesToPush [$ userId ][$ clientGroup ])) {
353+ $ this ->deletesToPush [$ userId ][$ clientGroup ] = [];
354+ }
355+
356+ foreach ($ notificationIds as $ notificationId ) {
357+ $ this ->deletesToPush [$ userId ][$ clientGroup ][] = $ notificationId ;
358+ }
324359 }
325- $ this ->deletesToPush [$ notificationId ] = ['userId ' => $ userId , 'app ' => $ app ]; // FIXME this assumes there is only 1 delete-all per request
326360 $ this ->loadDevicesForUsers [] = $ userId ;
327361 return ;
328362 }
329363
330- $ deleteAll = $ notificationId ! == null ;
364+ $ deleteAll = $ notificationIds = == null ;
331365
332366 $ user = $ this ->createFakeUserObject ($ userId );
333367
@@ -358,17 +392,21 @@ public function pushDeleteToDevice(string $userId, ?int $notificationId, string
358392 }
359393
360394 try {
361- if ($ deleteAll ) {
362- $ payload = json_encode ($ this ->encryptAndSignDelete ($ userKey , $ device , null ));
363- } else {
364- $ payload = json_encode ($ this ->encryptAndSignDelete ($ userKey , $ device , [$ notificationId ]));
365- }
366-
367395 $ proxyServer = rtrim ($ device ['proxyserver ' ], '/ ' );
368396 if (!isset ($ this ->payloadsToSend [$ proxyServer ])) {
369397 $ this ->payloadsToSend [$ proxyServer ] = [];
370398 }
371- $ this ->payloadsToSend [$ proxyServer ][] = $ payload ;
399+
400+ if ($ deleteAll ) {
401+ $ data = $ this ->encryptAndSignDelete ($ userKey , $ device , null );
402+ $ this ->payloadsToSend [$ proxyServer ][] = json_encode ($ data ['payload ' ]);
403+ } else {
404+ while (!empty ($ notificationIds )) {
405+ $ data = $ this ->encryptAndSignDelete ($ userKey , $ device , $ notificationIds );
406+ $ notificationIds = $ data ['remaining ' ];
407+ $ this ->payloadsToSend [$ proxyServer ][] = json_encode ($ data ['payload ' ]);
408+ }
409+ }
372410 } catch (\InvalidArgumentException $ e ) {
373411 // Failed to encrypt message for device: public key is invalid
374412 $ this ->deletePushToken ($ device ['token ' ]);
0 commit comments