mirror of
https://github.com/balzack/databag.git
synced 2025-04-23 01:55:17 +00:00
adding push notifications to web
This commit is contained in:
parent
0290ae98b1
commit
8b6eb48161
BIN
app/client/web/favicon.ico
Normal file
BIN
app/client/web/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/src/favicon.svg" />
|
||||
<link rel="icon" type="image/svg+xml" href="/src/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Databag</title>
|
||||
</head>
|
||||
|
@ -2,12 +2,27 @@ import { useEffect, useState, useContext, useRef } from 'react'
|
||||
import { AppContext } from '../context/AppContext'
|
||||
import { DisplayContext } from '../context/DisplayContext'
|
||||
import { ContextType } from '../context/ContextType'
|
||||
import { type Profile, type Config } from 'databag-client-sdk'
|
||||
import { type Profile, type Config, type PushParams, PushType } from 'databag-client-sdk'
|
||||
import { Point, Area } from 'react-easy-crop/types'
|
||||
|
||||
const IMAGE_DIM = 192
|
||||
const DEBOUNCE_MS = 1000
|
||||
|
||||
function urlB64ToUint8Array(b64: string) {
|
||||
const padding = '='.repeat((4 - b64.length % 4) % 4);
|
||||
const base64 = (b64 + padding)
|
||||
.replace(/-/g, '+')
|
||||
.replace(/_/g, '/');
|
||||
|
||||
const rawData = window.atob(base64);
|
||||
const outputArray = new Uint8Array(rawData.length);
|
||||
|
||||
for (var i = 0; i < rawData.length; ++i) {
|
||||
outputArray[i] = rawData.charCodeAt(i);
|
||||
}
|
||||
return outputArray;
|
||||
}
|
||||
|
||||
export function useSettings() {
|
||||
const display = useContext(DisplayContext) as ContextType
|
||||
const app = useContext(AppContext) as ContextType
|
||||
@ -46,6 +61,7 @@ export function useSettings() {
|
||||
secretImage: '',
|
||||
code: '',
|
||||
editImage: '',
|
||||
webPushKey: null,
|
||||
sealPassword: '',
|
||||
sealConfirm: '',
|
||||
sealDelete: '',
|
||||
@ -127,10 +143,8 @@ export function useSettings() {
|
||||
updateState({ blockedMessages });
|
||||
},
|
||||
loadBlockedChannels: async () => {
|
||||
console.log("LOAD BLOCKED");
|
||||
const settings = app.state.session.getSettings();
|
||||
const blockedChannels = await settings.getBlockedChannels();
|
||||
console.log("LOADED: ", blockedChannels);
|
||||
updateState({ blockedChannels });
|
||||
},
|
||||
unblockChannel: async (cardId: string | null, channelId: string) => {
|
||||
@ -159,8 +173,38 @@ console.log("LOADED: ", blockedChannels);
|
||||
await settings.setLogin(state.handle, state.password)
|
||||
},
|
||||
enableNotifications: async () => {
|
||||
const { settings } = getSession()
|
||||
await settings.enableNotifications()
|
||||
const webPushKey = state.config?.webPushKey;
|
||||
if (!webPushKey) {
|
||||
throw new Error('web push key not set');
|
||||
}
|
||||
const status = await Notification.requestPermission();
|
||||
if (status === 'granted') {
|
||||
const registration = await navigator.serviceWorker.register('push.js');
|
||||
await navigator.serviceWorker.ready;
|
||||
const params = { userVisibleOnly: true, applicationServerKey: urlB64ToUint8Array(webPushKey) };
|
||||
const subscription = await registration.pushManager.subscribe(params);
|
||||
|
||||
const endpoint = subscription.endpoint;
|
||||
const binPublicKey = subscription.getKey('p256dh');
|
||||
const binAuth = subscription.getKey('auth');
|
||||
|
||||
if (endpoint && binPublicKey && binAuth) {
|
||||
const numPublicKey: number[] = [];
|
||||
(new Uint8Array(binPublicKey)).forEach(val => {
|
||||
numPublicKey.push(val);
|
||||
});
|
||||
const numAuth: number[] = [];
|
||||
(new Uint8Array(binAuth)).forEach(val => {
|
||||
numAuth.push(val);
|
||||
});
|
||||
const publicKey = btoa(String.fromCharCode.apply(null, numPublicKey));
|
||||
const auth = btoa(String.fromCharCode.apply(null, numAuth));
|
||||
|
||||
const pushParams = { endpoint, publicKey, auth, type: PushType.Web };
|
||||
const { settings } = getSession()
|
||||
await settings.enableNotifications(pushParams)
|
||||
}
|
||||
}
|
||||
},
|
||||
disableNotifications: async () => {
|
||||
const { settings } = getSession()
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { Channel, Topic, AssetSource, Asset, Tag, Article, Group, Card, Profile, Call, FocusDetail, Config, NodeConfig, NodeAccount, Participant } from './types';
|
||||
import type { Channel, Topic, AssetSource, Asset, Tag, Article, Group, Card, Profile, Call, FocusDetail, Config, NodeConfig, NodeAccount, Participant, PushParams } from './types';
|
||||
|
||||
export interface Session {
|
||||
getSettings(): Settings;
|
||||
@ -31,7 +31,7 @@ export interface Ring {
|
||||
export interface Settings {
|
||||
getUsernameStatus(username: string): Promise<boolean>;
|
||||
setLogin(username: string, password: string): Promise<void>;
|
||||
enableNotifications(): Promise<void>;
|
||||
enableNotifications(params?: PushParams): Promise<void>;
|
||||
disableNotifications(): Promise<void>;
|
||||
enableRegistry(): Promise<void>;
|
||||
disableRegistry(): Promise<void>;
|
||||
|
@ -1,7 +1,12 @@
|
||||
import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
import { PushParams } from '../types';
|
||||
|
||||
export async function setAccountNotifications(node: string, secure: boolean, token: string, flag: boolean) {
|
||||
const endpoint = `http${secure ? 's' : ''}://${node}/account/notification?agent=${token}`;
|
||||
export async function setAccountNotifications(node: string, secure: boolean, token: string, flag: boolean, pushParams: PushParams) {
|
||||
const pushEndpoint = pushParams ? encodeURIComponent(pushParams.endpoint) : '';
|
||||
const publicKey = pushParams ? encodeURIComponent(pushParams.publicKey) : '';
|
||||
const auth = pushParams ? encodeURIComponent(pushParams.auth) : '';
|
||||
const params = pushParams ? `&webEndpoint=${pushEndpoint}&webPublicKey=${publicKey}&webAuth=${auth}&pushType=${pushParams.type}` : ''
|
||||
const endpoint = `http${secure ? 's' : ''}://${node}/account/notification?agent=${token}${params}`;
|
||||
const { status } = await fetchWithTimeout(endpoint, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(flag),
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
import type { Settings } from './api';
|
||||
import type { Config } from './types';
|
||||
import type { Config, PushParams } from './types';
|
||||
import { Store } from './store';
|
||||
import { Crypto } from './crypto';
|
||||
import { Logging } from './logging';
|
||||
@ -152,9 +152,9 @@ export class SettingsModule implements Settings {
|
||||
await this.sync();
|
||||
}
|
||||
|
||||
public async enableNotifications(): Promise<void> {
|
||||
public async enableNotifications(params?: PushParams): Promise<void> {
|
||||
const { node, secure, token } = this;
|
||||
await setAccountNotifications(node, secure, token, true);
|
||||
await setAccountNotifications(node, secure, token, true, params);
|
||||
}
|
||||
|
||||
public async disableNotifications(): Promise<void> {
|
||||
|
@ -258,3 +258,17 @@ export type SessionParams = {
|
||||
version: string;
|
||||
appName: string;
|
||||
};
|
||||
|
||||
export enum PushType {
|
||||
UPN = 'upn', // unified push notifications
|
||||
Web = 'web', // browser push notifications
|
||||
FCM = 'fcm', // firebase cloud messaging
|
||||
}
|
||||
|
||||
export type PushParams = {
|
||||
endpoint: string;
|
||||
publicKey: string;
|
||||
auth: string;
|
||||
type: PushType;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user