framework icon indicating copy to clipboard operation
framework copied to clipboard

[Pusher] New notifications count increment doesnt work

Open clownishthorn opened this issue 1 year ago • 1 comments

Current Behavior

Unread notifications count doesn't update on events

Steps to Reproduce

  1. Log-in (to be able to subscribe to private channel) and go to any page
  2. Receive new pusher notification (post in discussion you are subscribed to; new private discussion; etc)
  3. Notifications count doesnt update untill the page is refreshed

Expected Behavior

Unread notifications count should increment by 1 with each notification

Screenshots

No response

Environment

  • Flarum version: 1.8.3
  • PHP version: 8.1

Output of php flarum info

No response

Possible Solution

https://github.com/flarum/framework/blob/1.x/extensions/pusher/js/src/forum/index.tsx#L152C12-L153C84

Replace in those 2 lines: app.session.user.unreadNotificationCount() ?? 0 + 1 to (app.session.user.unreadNotificationCount() ?? 0) + 1 app.session.user.newNotificationCount() ?? 0 + 1 to (app.session.user.newNotificationCount() ?? 0) + 1

Additional Context

No response

clownishthorn avatar Feb 29 '24 06:02 clownishthorn

Managed to solve this by adding some code in my custom extension:

forum/index.js:

import { getNotificationCounts } from './util';

app.initializers.add('custom-extend', () => {
  console.log(app.pusher);
  app.pusher.then(binding => {
    const pusher = binding.pusher;

    console.log({ pusher });

    pusher.bind('newPost', async (data) => {
      console.log('newPost', data);

      if (app.session.user) {
        console.log(app.session.user.unreadNotificationCount());
        console.log(app.session.user.newNotificationCount());

        // Fetch the latest notification counts
        const counts = await getNotificationCounts();
        console.log('Updated notification counts:', counts);

        // Update the user's notification counts if needed
        if (counts.unreadNotificationCount !== app.session.user.unreadNotificationCount() ||
            counts.newNotificationCount !== app.session.user.newNotificationCount()) {
          app.session.user.pushAttributes({
            unreadNotificationCount: counts.unreadNotificationCount,
            newNotificationCount: counts.newNotificationCount
          });
        }
      }
      app.notifications.clear();
      m.redraw();
    });
  });
}, -100); // with low priority so it is run last when pusher is hooked

util.js:

import app from 'flarum/forum/app';

/**
 * Fetch notification counts from the API
 *
 * @returns {Promise} Promise that resolves with notification count data
 */
export async function getNotificationCounts() {
  try {
    const response = await app.request({
      method: 'GET',
      url: app.forum.attribute('apiUrl') + '/notification-counts'
    });
    return response;
  } catch (error) {
    console.error('Error fetching notification counts:', error);
    return {
      unreadNotificationCount: 0,
      newNotificationCount: 0
    };
  }
}

extend.php:

 (new Extend\Routes('api'))
        ->get('/notification-counts', 'notification.counts', GetNotificationCountsController::class),

GetNotificationCountsController.php:

<?php

namespace CustomExtend\Api\Controller;

use Flarum\Http\RequestUtil;
use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;

class GetNotificationCountsController implements RequestHandlerInterface
{
    /**
     * Handle the request and return a response.
     */
    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        // Get the current user
        $actor = RequestUtil::getActor($request);

        // Ensure the user is authenticated
        if ($actor->isGuest()) {
            $data = [
                'unreadNotificationCount' => 0,
                'newNotificationCount' => 0
            ];
        } else {
            // Get notification counts for authenticated user
            $data = [
                'unreadNotificationCount' => (int) $actor->getUnreadNotificationCount(),
                'newNotificationCount' => (int) $actor->getNewNotificationCount()
            ];
        }

        // Return JSON response
        return new JsonResponse($data);
    }
}

Basically, it listens for the "newPost" message and then does an AJAX call to fetch new notification counts.

justrau avatar May 14 '25 05:05 justrau