Skip to content

Commit

Permalink
feat: add push notifications (#2369)
Browse files Browse the repository at this point in the history
* feat: implement Firebase Cloud Messaging

* fix: move to custom `next-pwa` worker

* Revert "fix: move to custom `next-pwa` worker"

This reverts commit 2654d76.

* fix: remove `next-pwa`

* fix: convert SW to TS + add notification text

* fix: improve notifications

* refactor: separate types + add test

* fix: improve UI + add partial tests

* fix: add more test coverage

* fix: list Safes

* fix: migrate to SDK

* feat: basic notification preferences

* fix: tests

* fix: implement designs

* feat: per-Safe preferences

* refactor: move registrations to IndexedDB

* fix: adjust style, add banner + registration list

* fix: split databases + finish design

* fix: database reactivity with `ExternalStore`

* fix: update tests

* fix: preferences, env vars, not in UI + tweaks

* feat: add deep link to notification

* fix: add tracking + rename to push notifications

* fix: test

* fix: condense preferences

* fix: address review comments + adjust design

* fix: test

* refactor: clean up code

* refactor: make `_parseWebhookNotification` a map

* fix: register for confirmation requests by default

* fix: adjust text + fix tests

* fix: reduce service worker bundle size

* fix: don't re-export

* wip: reimplement next-pwa

* fix: `next-pwa` with custom worker

* chore: convert env var to JSON

* refactor: abstract code from component + fix test

* fix: env issue

* refactor: leverage SDK

* feat: add cached tracking

* fix: test

* fix: mock response on Safe Apps share page

* revert: cached tracking

* refactor: restructure/rename + add error codes

* fix: address review comments

* fix: address comments

* fix: regenerate lockfile

* fix: address comments

* feat: add push notification tracking (#2500)

* feat: add push notification tracking

* fix: address review comments

* fix: error message

* feat: add close button to banner

* fix: remove unnecessary types + qa findings

* fix: texts, confirmation registration + enable all

* fix: mock

* fix: spacing

* fix: spacing

* fix: use EIP-191

* fix: test

* feat: add feature flag

* fix: test

* fix: add space + only show banner on added Safes

* fix: remove space

* fix: e2e
  • Loading branch information
iamacook authored Sep 25, 2023
1 parent 8905820 commit 301facc
Show file tree
Hide file tree
Showing 48 changed files with 8,080 additions and 2,239 deletions.
7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,12 @@ NEXT_PUBLIC_CYPRESS_MNEMONIC=
NEXT_PUBLIC_SAFE_GELATO_RELAY_SERVICE_URL_PRODUCTION=
NEXT_PUBLIC_SAFE_GELATO_RELAY_SERVICE_URL_STAGING=

# Firebase Cloud Messaging
NEXT_PUBLIC_FIREBASE_OPTIONS_PRODUCTION=
NEXT_PUBLIC_FIREBASE_VAPID_KEY_PRODUCTION=

NEXT_PUBLIC_FIREBASE_OPTIONS_STAGING=
NEXT_PUBLIC_FIREBASE_VAPID_KEY_STAGING=

# Redefine
NEXT_PUBLIC_REDEFINE_API=
4 changes: 4 additions & 0 deletions .github/workflows/build/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,7 @@ runs:
NEXT_PUBLIC_SAFE_RELAY_SERVICE_URL_STAGING: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_SAFE_GELATO_RELAY_SERVICE_URL_STAGING }}
NEXT_PUBLIC_IS_OFFICIAL_HOST: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_IS_OFFICIAL_HOST }}
NEXT_PUBLIC_REDEFINE_API: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_REDEFINE_API }}
NEXT_PUBLIC_FIREBASE_OPTIONS_PRODUCTION: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_FIREBASE_OPTIONS_PRODUCTION }}
NEXT_PUBLIC_FIREBASE_OPTIONS_STAGING: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_FIREBASE_OPTIONS_STAGING }}
NEXT_PUBLIC_FIREBASE_VAPID_KEY_PRODUCTION: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_FIREBASE_VAPID_KEY_PRODUCTION }}
NEXT_PUBLIC_FIREBASE_VAPID_KEY_STAGING: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_FIREBASE_VAPID_KEY_STAGING }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ yalc.lock

/public/sw.js
/public/sw.js.map
/public/worker-*.js
/public/workbox-*.js
/public/workbox-*.js.map
/public/fallback*
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ Here's the list of all the required and optional variables:
| `NEXT_PUBLIC_SAFE_GELATO_RELAY_SERVICE_URL_STAGING` | optional | Relay URL on staging
| `NEXT_PUBLIC_IS_OFFICIAL_HOST` | optional | Whether it's the official distribution of the app, or a fork; has legal implications. Set to true only if you also update the legal pages like Imprint and Terms of use
| `NEXT_PUBLIC_REDEFINE_API` | optional | Redefine API base URL
| `NEXT_PUBLIC_FIREBASE_OPTIONS_PRODUCTION` | optional | Firebase Cloud Messaging (FCM) `initializeApp` options on production
| `NEXT_PUBLIC_FIREBASE_VAPID_KEY_PRODUCTION` | optional | FCM vapid key on production
| `NEXT_PUBLIC_FIREBASE_OPTIONS_STAGING` | optional | FCM `initializeApp` options on staging
| `NEXT_PUBLIC_FIREBASE_VAPID_KEY_STAGING` | optional | FCM vapid key on staging

If you don't provide some of the optional vars, the corresponding features will be disabled in the UI.

Expand Down
15 changes: 15 additions & 0 deletions cypress/e2e/pages/import_export.pages.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { format } from 'date-fns'
const path = require('path')

const enablePushNotificationsStr = 'Enable push notifications'
const addressBookBtnStr = 'Address book'
const dataImportModalStr = 'Data import'
const appsBtnStr = 'Apps'
const bookmarkedAppsBtnStr = 'Bookmarked apps'
const settingsBtnStr = 'Settings'
const appearenceTabStr = 'Appearance'
const showMoreTabsBtn = '[data-testid="KeyboardArrowRightIcon"]'
const dataTabStr = 'Data'
const tab = 'div[role="tablist"] a'
export const prependChainPrefixStr = 'Prepend chain prefix to addresses'
Expand Down Expand Up @@ -41,6 +43,12 @@ export function clickOnImportedSafe(safe) {
cy.contains(safe).click()
}

export function clickOnClosePushNotificationsBanner() {
cy.waitForSelector(() => {
return cy.get('h6').contains(enablePushNotificationsStr).siblings('.MuiButtonBase-root').click({ force: true })
})
}

export function clickOnAddressBookBtn() {
cy.contains(addressBookBtnStr).click()
}
Expand Down Expand Up @@ -82,6 +90,13 @@ export function clickOnAppearenceBtn() {
cy.contains(tab, appearenceTabStr).click()
}

export function clickOnShowMoreTabsBtn() {
cy.get(showMoreTabsBtn).click()
}

export function verifDataTabBtnIsVisible() {
cy.contains(tab, dataTabStr).should('be.visible')
}
export function clickOnDataTab() {
cy.contains(tab, dataTabStr).click()
}
Expand Down
3 changes: 3 additions & 0 deletions cypress/e2e/smoke/import_export_data.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ describe('Import Export Data', () => {
file.verifyImportModalData()
file.clickOnImportBtnDataImportModal()
file.clickOnImportedSafe(safe)
file.clickOnClosePushNotificationsBanner()
})

it("Verify safe's address book imported data", () => {
Expand All @@ -45,6 +46,8 @@ describe('Import Export Data', () => {
})

it('Verifies data for export in Data tab', () => {
file.clickOnShowMoreTabsBtn()
file.verifDataTabBtnIsVisible()
file.clickOnDataTab()
file.verifyImportModalData()
file.verifyFileDownload()
Expand Down
13 changes: 10 additions & 3 deletions next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import path from 'path'
import withBundleAnalyzer from '@next/bundle-analyzer'
import NextPwa from 'next-pwa'
import withPWAInit from '@ducanh2912/next-pwa'

const withPWA = NextPwa({
disable: process.env.NODE_ENV === 'development',
const SERVICE_WORKERS_PATH = './src/service-workers'

const withPWA = withPWAInit({
dest: 'public',
workboxOptions: {
mode: 'production',
},
reloadOnOnline: false,
/* Do not precache anything */
publicExcludes: ['**/*'],
buildExcludes: [/./],
customWorkerSrc: SERVICE_WORKERS_PATH,
// Prefer InjectManifest for Web Push
swSrc: `${SERVICE_WORKERS_PATH}/index.ts`,
})

/** @type {import('next').NextConfig} */
Expand Down
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"routes": "node scripts/generate-routes.js > src/config/routes.ts && prettier -w src/config/routes.ts && cat src/config/routes.ts",
"css-vars": "ts-node-esm ./scripts/css-vars.ts > ./src/styles/vars.css && prettier -w src/styles/vars.css",
"generate-types": "typechain --target ethers-v5 --out-dir src/types/contracts ./node_modules/@safe-global/safe-deployments/dist/assets/**/*.json ./node_modules/@safe-global/safe-modules-deployments/dist/assets/**/*.json ./node_modules/@openzeppelin/contracts/build/contracts/ERC20.json ./node_modules/@openzeppelin/contracts/build/contracts/ERC721.json",
"postinstall": "yarn generate-types && yarn css-vars",
"postinstall": "yarn patch-package && yarn generate-types && yarn css-vars",
"analyze": "cross-env ANALYZE=true yarn build",
"cypress:open": "cross-env TZ=UTC cypress open --e2e",
"cypress:canary": "cross-env TZ=UTC cypress open --e2e -b chrome:canary",
Expand All @@ -39,6 +39,7 @@
},
"dependencies": {
"@date-io/date-fns": "^2.15.0",
"@ducanh2912/next-pwa": "^9.5.0",
"@emotion/cache": "^11.10.1",
"@emotion/react": "^11.10.0",
"@emotion/server": "^11.10.0",
Expand Down Expand Up @@ -70,12 +71,13 @@
"ethereum-blockies-base64": "^1.0.2",
"ethers": "5.7.2",
"exponential-backoff": "^3.1.0",
"firebase": "^10.3.1",
"framer-motion": "^10.13.1",
"fuse.js": "^6.6.2",
"idb-keyval": "^6.2.1",
"js-cookie": "^3.0.1",
"lodash": "^4.17.21",
"next": "^13.2.0",
"next-pwa": "^5.6.0",
"papaparse": "^5.3.2",
"qrcode.react": "^3.1.0",
"react": "18.2.0",
Expand Down Expand Up @@ -118,14 +120,17 @@
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-unused-imports": "^2.0.0",
"fake-indexeddb": "^4.0.2",
"jest": "^29.6.2",
"jest-environment-jsdom": "^29.6.2",
"patch-package": "^8.0.0",
"pre-commit": "^1.2.2",
"prettier": "^2.7.0",
"ts-node": "^10.8.2",
"ts-prune": "^0.10.3",
"typechain": "^8.0.0",
"typescript": "4.9.4",
"typescript-plugin-css-modules": "^4.2.2"
"typescript-plugin-css-modules": "^4.2.2",
"webpack": "^5.88.2"
}
}
Loading

0 comments on commit 301facc

Please sign in to comment.