Skip to content

feat(cli/web): pwa push notifications #1892

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
69b683b
feat(cli/web): pwa push notifications
CFT-Chris Aug 21, 2019
531431d
fix(web): title and body for pushNotificationReceived (retry)
CFT-Chris Aug 23, 2019
c736bc8
Merge branch 'master' of https://github.com/ionic-team/capacitor into…
CFT-Chris Aug 29, 2019
d585207
Merge branch 'master' of https://github.com/ionic-team/capacitor into…
CFT-Chris Oct 2, 2019
1ec81ae
feat(cli): PWA FCM data messages
CFT-Chris Oct 22, 2019
96c992a
Merge branch 'master' of https://github.com/ionic-team/capacitor into…
CFT-Chris Oct 22, 2019
bcb90c1
Merge branch 'master' of https://github.com/ionic-team/capacitor into…
CFT-Chris Dec 1, 2019
95809eb
Merge branch 'master' of https://github.com/ionic-team/capacitor into…
CFT-Chris Jan 29, 2020
a070122
Merge branch 'master' of https://github.com/ionic-team/capacitor into…
CFT-Chris Feb 6, 2020
385fff2
fix(core/web): integrate PushNotificationRegistrationResponse
CFT-Chris Feb 6, 2020
88497a5
Merge branch 'master' of https://github.com/ionic-team/capacitor into…
CFT-Chris Feb 14, 2020
65324f0
feat(cli): timestamp SW, auto-activate SW
CFT-Chris Feb 19, 2020
a111cb0
Merge branch 'master' of https://github.com/ionic-team/capacitor into…
CFT-Chris Feb 19, 2020
5fca9b8
Merge branch 'master' of https://github.com/ionic-team/capacitor into…
CFT-Chris Mar 3, 2020
73b7546
Factor out all firebase related changes
CFT-Chris Mar 4, 2020
787c38d
feat(cli): precapcopyweb for PWA web plugins
CFT-Chris Mar 5, 2020
c11c2ef
Merge branch 'master' of https://github.com/ionic-team/capacitor into…
CFT-Chris Mar 5, 2020
b680acf
docs: factor out plugin-specific setup
CFT-Chris Mar 5, 2020
38c42bc
Merge branch 'master' of https://github.com/ionic-team/capacitor into…
CFT-Chris Jun 15, 2020
4b55014
fix(cli/web): copy.ts make CI tslint happy
CFT-Chris Jun 15, 2020
0ac12af
fix(cli/web): no package when copyWeb CI tested
CFT-Chris Jun 15, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,15 @@
"@types/fs-extra": "^4.0.5",
"@types/inquirer": "0.0.35",
"@types/jest": "^23.3.9",
"@types/lodash": "^4.14.137",
"@types/mock-fs": "^3.6.30",
"@types/open": "^6.1.0",
"@types/ora": "^1.3.1",
"@types/semver": "^5.4.0",
"@types/which": "^1.0.28",
"@types/xml2js": "^0.4.2",
"jest": "^23.6.0",
"lodash": "^4.17.15",
"mock-fs": "^4.4.2",
"np": "^2.18.2",
"rimraf": "^3.0.0",
Expand Down
7 changes: 6 additions & 1 deletion cli/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { accessSync, readFileSync } from 'fs';
import { basename, join, resolve } from 'path';
import { logFatal, readJSON } from './common';
import { CliConfig, ExternalConfig, OS, PackageJson } from './definitions';
import * as _ from 'lodash';

let Package: PackageJson;
let ExtConfig: ExternalConfig;
Expand Down Expand Up @@ -85,6 +86,10 @@ export class Config implements CliConfig {
extConfigFilePath: '',
extConfig: ExtConfig,
bundledWebRuntime: false,
serviceWorker: {
name: 'capacitor-sw.js',
combineWorkers: []
},
plugins: {},
assets: {
templateName: 'app-template',
Expand Down Expand Up @@ -215,7 +220,7 @@ export class Config implements CliConfig {
private mergeConfigData() {
const extConfig: ExternalConfig = this.app.extConfig || {};

Object.assign(this.app, extConfig);
_.merge(this.app, extConfig);

// Build the absolute path to the web directory
this.app.webDirAbs = resolve(this.app.rootDir, this.app.webDir);
Expand Down
6 changes: 6 additions & 0 deletions cli/src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export interface CliConfigApp {
* module imports, set this to "true" and import "capacitor.js" manually.
*/
bundledWebRuntime: boolean;
serviceWorker: CliConfigServiceWorker;
assets: CliConfigPlatformAssets;
}

Expand All @@ -104,3 +105,8 @@ export interface CliConfig {
app: CliConfigApp;
plugins: CliConfigPlugins;
}

export interface CliConfigServiceWorker {
name: string;
combineWorkers: string[];
}
63 changes: 59 additions & 4 deletions cli/src/web/copy.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,74 @@
import { logFatal, resolveNode, runTask } from '../common';
import { logFatal, readJSON, resolveNode, runCommand, runTask } from '../common';
import { Config } from '../config';
import { copy } from 'fs-extra';
import { writeFileAsync } from '../util/fs';
import { join } from 'path';
import { getDependencies } from '../plugin';
import chalk from 'chalk';

const NPM_PRECAPCOPYWEB_SCRIPT = 'precapcopyweb';

// When a new version of Capacitor's PWA service worker is seen by the browser, immediately activate it after installation
const CAPACITOR_SERVICEWORKER_HEADER = `
// Timestamp: ${Date.now()}

self.addEventListener('installed', () => {
self.skipWaiting();
});
`;

export async function copyWeb(config: Config) {
let serviceWorker = '';
let runtimePath: string | null = null;

const deps = config.app.package ? getDependencies(config) : [];

await runTask(`Scan for web plugins and run ${NPM_PRECAPCOPYWEB_SCRIPT} npm scripts`, async () => {
await Promise.all(
deps.map(async p => {
const rootPath = resolveNode(config, p);

if (!rootPath) {
logFatal(`Unable to find node_modules/${p}. Are you sure ${p} is installed?`);
return null;
}

const packagePath = join(rootPath, 'package.json');
const meta = await readJSON(packagePath);

if (meta.scripts && meta.scripts[NPM_PRECAPCOPYWEB_SCRIPT]) {
await runTask(chalk` {white {bold ${p}}}: running ${NPM_PRECAPCOPYWEB_SCRIPT} npm script`, async () => {
await runCommand(`npm explore ${p} -- npm run ${NPM_PRECAPCOPYWEB_SCRIPT}`);
});
}
})
);
});

if (config.app.bundledWebRuntime) {
const runtimePath = resolveNode(config, '@capacitor/core', 'dist', 'capacitor.js');
runtimePath = resolveNode(config, '@capacitor/core', 'dist', 'capacitor.js');

if (!runtimePath) {
logFatal(`Unable to find node_modules/@capacitor/core/dist/capacitor.js. Are you sure`,
'@capacitor/core is installed? This file is required for Capacitor to function');
return;
}

return runTask(`Copying capacitor.js to web dir`, () => {
return copy(runtimePath, join(config.app.webDirAbs, 'capacitor.js'));
await runTask(`Copying capacitor.js to web dir`, async () => {
if (runtimePath)
await copy(runtimePath, join(config.app.webDirAbs, 'capacitor.js'));
});
}

if (config.app.serviceWorker) {
serviceWorker = CAPACITOR_SERVICEWORKER_HEADER;

if (config.app.serviceWorker.combineWorkers) {
serviceWorker += config.app.serviceWorker.combineWorkers.map(s => `importScripts('${s}');`).join('\n');
}

await runTask(`Copying ${config.app.serviceWorker.name} to web dir`, async () => {
await writeFileAsync(join(config.app.webDirAbs, config.app.serviceWorker.name), serviceWorker);
});
}
}
7 changes: 6 additions & 1 deletion site/docs-md/apis/push-notifications/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,27 @@ contributors:
- jcesarmobile
---

<plugin-platforms platforms="ios,android"></plugin-platforms>
<plugin-platforms platforms="pwa,ios,android"></plugin-platforms>

# Push Notifications

The Push Notifications API provides methods for registering a device to receive notifications from a server, along with processing received notifications and responding to them. In contrast, the [Local Notifications](/docs/apis/local-notifications) API provides means for offline, local notification scheduling and processing.

## Enabling Push Notifications Capabilites

*Ios*:
On iOS you must enable Push Notifications Capabilities in your project to enable the Push Notifications plugin to work. To do so, go to the `Capabilities` section of the app project and switch the `Push Notifications` button from `OFF` to the `ON` position.

This change adds the push capabilites to the app and creates an entitlements file in the project.

![Enabling Push Notifications Capabilities](/assets/img/docs/ios/enable-push-capabilities.png)

*Android*:
On Android just download the app project's `google-services.json` file from the Firebase console, and place it in the `projectName/android/app` folder.

*PWA*:
For progressive web apps, add the [PWA Push Notifications with Firebase](../../community/plugins.md) plugin and follow its setup instructions.

## Push Notifications icon

On Android, the Push Notifications icon with the appropriate name should be added to the `AndroidManifest.xml` file:
Expand Down
1 change: 1 addition & 0 deletions site/docs-md/community/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ Are we missing your awesome plugin? [Add it to this page](https://github.com/ion
| ----------------------- | ----------- | ------ | ------ |
| Fancy Notifications | `fancy-notifications` | <https://github.com/triniwiz/fancy-notifications> | |
| FCM | `capacitor-fcm` | <https://github.com/stewwan/capacitor-fcm> | |
| PWA Push Notifications with Firebase | `capacitor-pwa-firebase-msg` | <https://github.com/CFT-Chris/capacitor-pwa-firebase-msg> | |

## Files/Networking

Expand Down