flutter_local_notifications icon indicating copy to clipboard operation
flutter_local_notifications copied to clipboard

Web Support

Open Levi-Lesches opened this issue 1 year ago • 10 comments

Adds web support. The plan is as follows, taken from https://github.com/MaikuB/flutter_local_notifications/issues/481#issuecomment-2473307972:

Basic functionality

  • [x] Get a web version of the plugin to register on launch
  • [x] Show a notification with show()
  • [x] List all notifications using getActiveNotifications()
  • [x] Cancel notifications using cancel() and cancelAll()
  • [x] periodicallyShow and periodicallyShowWithDuration would throw UnsupportedError
  • [x] pendingNotificationRequest would return an empty list

Advanced Functionality

  • [x] Support all customizations options offered by web.NotificationOptions
  • [x] Register a custom service worker that can listen for notification clicks
  • [x] Call handler when a notification is clicked in the foreground
  • [x] Support getNotificationAppLaunchDetails() from terminated state

PR Cleanup

  • [x] Document everything (ie, re-enable lint)
  • [x] Add web-specific examples to the example app
  • [x] Write tests where applicable (I didn't find any good spots)
Custom service workers

Of course, getNotificationAppLaunchDetails and setting any handlers would require the ability to customize the service worker. That appears to be blocked on flutter/flutter#145828, we can also register a new service worker at runtime:

let flutter_sw = await navigator.serviceWorker.getRegistration();
if (flutter_sw != null) flutter_sw.unregister();
let plugin_sw = await navigator.serviceWorker.register("/flutter_local_notifications_sw.js");

Where our custom service worker can start off as simple as

function _handleNotif(event) {
  console.log(`Clicked: ${event}`);
  clients.openWindow(`/?id=${event.notification.tag`);
}

self.addEventListener("notificationclick", _handleNotif);

It evolved more throughout the PR, but that's the gist

Levi-Lesches avatar Nov 15 '24 03:11 Levi-Lesches

@MaikuB I'll once again put in my request to disable the always_specify_types and lines_longer_than_80_chars lints, as they cause a lot of headache when trying to write readable code here. Disabling them now won't require changing old code, but will allow cleaner code going forward, and there may be a fair amount of code since this is a big feature. I'll also point out again that always_specify_types contradicts Effective Dart and there are even replacements such as omit_obvious_local_variable_types and specify_nonobvious_local_variabletypes. As for line lengths, the new formatter will allow custom line lengths, for which I find 100 is a reasonable limit, especially with variable names as long as WebFlutterLocalNotificationsPlugin.

Levi-Lesches avatar Nov 15 '24 03:11 Levi-Lesches

Love this test feedback!

 Failed to load ".../flutter_local_notification_test.dart": Instance of 'VmServiceDisappearedException'

Levi-Lesches avatar Nov 17 '24 00:11 Levi-Lesches

Hi @Levi-Lesches, I would like to know how I can install this alpha version inside my project. Can you please write a simple procedure on how to use it? Thanks so much

therickys93 avatar Feb 17 '25 14:02 therickys93

Look into git dependencies in your pubspec, and set the URL to my repo and ref to my branch

Levi-Lesches avatar Feb 18 '25 02:02 Levi-Lesches

Look into git dependencies in your pubspec, and set the URL to my repo and ref to my branch

thanks so much. Is there an example on how to show a basic notification (title and subtitle) like on the other platforms? I cannot find a simple example in your code.

therickys93 avatar Feb 18 '25 05:02 therickys93

It's been a while since I've touched this PR, but show() should work. Are you able to run the example app on chrome?

Levi-Lesches avatar Feb 18 '25 19:02 Levi-Lesches

Hello @Levi-Lesches is there an update or ETA to have basic functionality merged?

MichalNemec avatar Jul 25 '25 01:07 MichalNemec

I hear your calls! Foreground callbacks are now supported!

await plugin.initialize(
  initializationSettings,
  // same as other platforms, but now it'll work on web too!
  onDidReceiveNotificationResponse: myHandler,
);

Oh, but this commit also adds a new package to the mix, which is unpublished, so you'll need to clone this whole repository and use path overrides for flutter_local_notifications_web


Launch details are also now supported!

// Same as every other platform!
final launchDetails = await plugin.getNotificationAppLaunchDetails();

If a notification is tapped when your tab is closed, it will be re-opened with a bunch of query parameters. Calling this function will read them and clear them so the user doesn't see them for too long.


I'm going to clean up the PR now. Here's what I did not add:

  • background handlers: when a tab is closed, it is terminated. Browser tabs don't really have a standard suspended state as far as I know, and the code I wrote will just treat them as terminated and open a new tab
  • scheduled notifications: The browser just doesn't offer the same flexibility as an app here, so I don't think this is reasonably possible.
    • The Periodic Background Sync API looked promising, but
      • permission is granted when the browser "trusts" you, and there's no way to request it
      • the interval parameter is just a suggestion, and the browser will decide when to run your code based on how often the user interacts with your page. Being a few seconds or even minutes off is acceptable for this package, but this is too unreliable
      • Not supported by Firefox or Safari

Levi-Lesches avatar Sep 16 '25 21:09 Levi-Lesches

@MaikuB I'm ready for a review!

There a handful of lints that are coming up from the master branch that aren't related to this PR. I opened https://github.com/MaikuB/flutter_local_notifications/pull/2687 for those

I couldn't really think of a great way to unit test this since it's so close to the actual JS layer and there's barely any plain Dart, so I just did the usual in making the really detailed examples. Let me know if you have a specific test case in mind.

I also didn't touch changelogs because I see you have a lot of PRs open and didn't want to conflict. This release is non-breaking though!

I added snippets in the web-only README, and made some light changes to the main README, but I want to save my main documentation effort for #2477 and adding a web guide to that PR

Levi-Lesches avatar Sep 17 '25 01:09 Levi-Lesches

Thanks I'll take a look when I can do so. Regarding changelogs, that is something I can deal as part of resolving merge conflicts. With that in mind, if your wanted to, you can add details under "vNext" to represent next release. This is optional though

MaikuB avatar Sep 21 '25 04:09 MaikuB