@things-factory/notification 6.1.18 → 6.1.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/client/{bootstrap.js → bootstrap.ts} +13 -9
  2. package/client/pages/notification/notification-list-page.ts +267 -0
  3. package/client/pages/notification-rule/notification-rule-importer.ts +93 -0
  4. package/client/pages/notification-rule/notification-rule-list-page.ts +395 -0
  5. package/client/route.ts +10 -0
  6. package/client/tsconfig.json +13 -0
  7. package/client/viewparts/notification-badge.ts +58 -0
  8. package/client/viewparts/notification-item.ts +242 -0
  9. package/client/viewparts/notification-list.ts +171 -0
  10. package/client/viewparts/notification-sender.ts +126 -0
  11. package/client/viewparts/{notification-setting-let.js → notification-setting-let.ts} +48 -52
  12. package/dist-client/actions/notification-fcm.d.ts +7 -0
  13. package/dist-client/actions/notification-fcm.js +125 -0
  14. package/dist-client/actions/notification-fcm.js.map +1 -0
  15. package/dist-client/bootstrap.d.ts +1 -0
  16. package/dist-client/bootstrap.js +112 -0
  17. package/dist-client/bootstrap.js.map +1 -0
  18. package/dist-client/index.d.ts +5 -0
  19. package/dist-client/index.js +6 -0
  20. package/dist-client/index.js.map +1 -0
  21. package/dist-client/pages/notification/notification-list-page.d.ts +49 -0
  22. package/dist-client/pages/notification/notification-list-page.js +262 -0
  23. package/dist-client/pages/notification/notification-list-page.js.map +1 -0
  24. package/dist-client/pages/notification-rule/notification-rule-importer.d.ts +22 -0
  25. package/dist-client/pages/notification-rule/notification-rule-importer.js +100 -0
  26. package/dist-client/pages/notification-rule/notification-rule-importer.js.map +1 -0
  27. package/dist-client/pages/notification-rule/notification-rule-list-page.d.ts +62 -0
  28. package/dist-client/pages/notification-rule/notification-rule-list-page.js +380 -0
  29. package/dist-client/pages/notification-rule/notification-rule-list-page.js.map +1 -0
  30. package/dist-client/reducers/notification.d.ts +8 -0
  31. package/dist-client/reducers/notification.js +22 -0
  32. package/dist-client/reducers/notification.js.map +1 -0
  33. package/dist-client/route.d.ts +1 -0
  34. package/dist-client/route.js +11 -0
  35. package/dist-client/route.js.map +1 -0
  36. package/dist-client/tsconfig.tsbuildinfo +1 -0
  37. package/dist-client/viewparts/notification-badge.d.ts +15 -0
  38. package/dist-client/viewparts/notification-badge.js +61 -0
  39. package/dist-client/viewparts/notification-badge.js.map +1 -0
  40. package/dist-client/viewparts/notification-item.d.ts +16 -0
  41. package/dist-client/viewparts/notification-item.js +249 -0
  42. package/dist-client/viewparts/notification-item.js.map +1 -0
  43. package/dist-client/viewparts/notification-list.d.ts +20 -0
  44. package/dist-client/viewparts/notification-list.js +160 -0
  45. package/dist-client/viewparts/notification-list.js.map +1 -0
  46. package/dist-client/viewparts/notification-sender.d.ts +13 -0
  47. package/dist-client/viewparts/notification-sender.js +122 -0
  48. package/dist-client/viewparts/notification-sender.js.map +1 -0
  49. package/dist-client/viewparts/notification-setting-let.d.ts +20 -0
  50. package/dist-client/viewparts/notification-setting-let.js +193 -0
  51. package/dist-client/viewparts/notification-setting-let.js.map +1 -0
  52. package/dist-server/service/index.js +10 -1
  53. package/dist-server/service/index.js.map +1 -1
  54. package/dist-server/service/notification/index.js +6 -3
  55. package/dist-server/service/notification/index.js.map +1 -1
  56. package/dist-server/service/notification/notification-mutation.js +110 -0
  57. package/dist-server/service/notification/notification-mutation.js.map +1 -0
  58. package/dist-server/service/notification/notification-query.js +109 -0
  59. package/dist-server/service/notification/notification-query.js.map +1 -0
  60. package/dist-server/service/notification/notification-subscription.js +45 -0
  61. package/dist-server/service/notification/notification-subscription.js.map +1 -0
  62. package/dist-server/service/notification/notification-type.js +82 -0
  63. package/dist-server/service/notification/notification-type.js.map +1 -0
  64. package/dist-server/service/notification/notification.js +81 -8
  65. package/dist-server/service/notification/notification.js.map +1 -1
  66. package/dist-server/service/notification-rule/event-subscriber.js +21 -0
  67. package/dist-server/service/notification-rule/event-subscriber.js.map +1 -0
  68. package/dist-server/service/notification-rule/index.js +12 -0
  69. package/dist-server/service/notification-rule/index.js.map +1 -0
  70. package/dist-server/service/notification-rule/notification-rule-history.js +146 -0
  71. package/dist-server/service/notification-rule/notification-rule-history.js.map +1 -0
  72. package/dist-server/service/notification-rule/notification-rule-mutation.js +170 -0
  73. package/dist-server/service/notification-rule/notification-rule-mutation.js.map +1 -0
  74. package/dist-server/service/notification-rule/notification-rule-query.js +97 -0
  75. package/dist-server/service/notification-rule/notification-rule-query.js.map +1 -0
  76. package/dist-server/service/notification-rule/notification-rule-type.js +102 -0
  77. package/dist-server/service/notification-rule/notification-rule-type.js.map +1 -0
  78. package/dist-server/service/notification-rule/notification-rule.js +146 -0
  79. package/dist-server/service/notification-rule/notification-rule.js.map +1 -0
  80. package/dist-server/tsconfig.tsbuildinfo +1 -1
  81. package/helps/notification/noti-box.md +160 -0
  82. package/helps/notification/noti-rule.md +160 -0
  83. package/helps/notification/notibox.md +160 -0
  84. package/package.json +15 -12
  85. package/server/service/index.ts +14 -0
  86. package/server/service/notification/index.ts +6 -3
  87. package/server/service/notification/notification-mutation.ts +119 -0
  88. package/server/service/notification/notification-query.ts +70 -0
  89. package/server/service/notification/{notification-resolver.ts → notification-subscription.ts} +4 -4
  90. package/server/service/notification/notification-type.ts +55 -0
  91. package/server/service/notification/notification.ts +87 -14
  92. package/server/service/notification-rule/event-subscriber.ts +20 -0
  93. package/server/service/notification-rule/index.ts +9 -0
  94. package/server/service/notification-rule/notification-rule-history.ts +130 -0
  95. package/server/service/notification-rule/notification-rule-mutation.ts +203 -0
  96. package/server/service/notification-rule/notification-rule-query.ts +62 -0
  97. package/server/service/notification-rule/notification-rule-type.ts +71 -0
  98. package/server/service/notification-rule/notification-rule.ts +125 -0
  99. package/server/tsconfig.json +9 -0
  100. package/things-factory.config.js +7 -1
  101. package/client/viewparts/notification-badge.js +0 -63
  102. package/client/viewparts/notification-item.js +0 -250
  103. package/client/viewparts/notification-list.js +0 -177
  104. package/client/viewparts/notification-sender.js +0 -128
  105. package/tsconfig.json +0 -9
  106. /package/client/actions/{notification-fcm.js → notification-fcm.ts} +0 -0
  107. /package/client/{index.js → index.ts} +0 -0
  108. /package/client/reducers/{notification.js → notification.ts} +0 -0
@@ -0,0 +1,171 @@
1
+ import { LitElement, html, css } from 'lit'
2
+ import { customElement, property } from 'lit/decorators.js'
3
+ import { connect } from 'pwa-helpers'
4
+ import { store, notificationStore } from '@operato/shell'
5
+ import { i18next, localize } from '@operato/i18n'
6
+ import { UPDATE_NOTIFICATION } from '../actions/notification-fcm'
7
+
8
+ import '@material/mwc-icon'
9
+ import './notification-item'
10
+
11
+ @customElement('notification-list')
12
+ export class NotificationList extends connect(store)(localize(i18next)(LitElement)) {
13
+ static styles = [
14
+ css`
15
+ :host {
16
+ display: block;
17
+ background-color: var(--theme-white-color);
18
+ box-shadow: var(--box-shadow);
19
+ margin-right: var(--margin-wide);
20
+ padding: var(--padding-default);
21
+ max-height: 100%;
22
+ overflow-x: hidden;
23
+ overflow-y: auto;
24
+ }
25
+ :host::before {
26
+ content: '';
27
+ width: 0px;
28
+ height: 0px;
29
+ border-left: 7px solid transparent;
30
+ border-right: 7px solid transparent;
31
+ border-bottom: 7px solid var(--theme-white-color);
32
+ position: absolute;
33
+ margin-top: -7px;
34
+ right: 50px;
35
+ }
36
+
37
+ [notifications-wrap] {
38
+ display: flex;
39
+ flex-direction: column;
40
+ justify-content: flex-start;
41
+ }
42
+ [notifications-wrap] div {
43
+ align-items: stretch;
44
+ border-bottom: 1px solid var(--primary-color);
45
+ }
46
+ [notifications-wrap] strong {
47
+ color: var(--primary-color);
48
+ text-transform: capitalize;
49
+ line-height: 2;
50
+ }
51
+ [notifications-wrap] mwc-button {
52
+ float: right;
53
+ --mdc-button-horizontal-padding: var(--padding-narrow);
54
+ --mdc-typography-button-font-size: 0.75em;
55
+ }
56
+ [no-notifications] {
57
+ margin: 0;
58
+ padding: var(--padding-wide);
59
+ text-align: center;
60
+ font-size: var(--fontsize-default);
61
+ font-weight: bold;
62
+ color: var(--secondary-color);
63
+ }
64
+ div mwc-icon {
65
+ display: block;
66
+ opacity: 0.3;
67
+ }
68
+ @media screen and (max-width: 480px) {
69
+ :host {
70
+ height: 100%;
71
+ width: 100vw;
72
+ }
73
+ }
74
+ `
75
+ ]
76
+
77
+ @property({ type: Array }) history: any[] = []
78
+
79
+ render() {
80
+ var history = this.history.reverse()
81
+
82
+ return history.length > 0
83
+ ? html`
84
+ <div notifications-wrap>
85
+ <div>
86
+ <strong>${i18next.t('label.notification list')}</strong>
87
+ <mwc-button
88
+ outlined
89
+ dense
90
+ label=${String(i18next.t('label.clear all'))}
91
+ icon="delete_outline"
92
+ @click=${e => this.onclearall()}
93
+ ></mwc-button>
94
+ </div>
95
+ ${history.map(
96
+ notification => html`
97
+ <notification-item
98
+ @close=${e => {
99
+ this.onClose(notification)
100
+ }}
101
+ .type=${notification.type}
102
+ .notification=${notification}
103
+ ></notification-item>
104
+ `
105
+ )}
106
+ </div>
107
+ `
108
+ : html`
109
+ <div no-notifications @click=${e => window.history.back()}>
110
+ <mwc-icon>notifications_off</mwc-icon>${i18next.t('text.no notification available')}
111
+ </div>
112
+ `
113
+ }
114
+
115
+ onClose(notification) {
116
+ const { id } = notification
117
+
118
+ store.dispatch((async dispatch => {
119
+ if (notification) {
120
+ await notificationStore.delete(id)
121
+ }
122
+
123
+ const history = await notificationStore.getAll()
124
+
125
+ dispatch({
126
+ type: UPDATE_NOTIFICATION,
127
+ history: [...history]
128
+ })
129
+ }) as any)
130
+ }
131
+
132
+ onclearall() {
133
+ store.dispatch((async dispatch => {
134
+ await notificationStore.clear()
135
+ const history = await notificationStore.getAll()
136
+
137
+ dispatch({
138
+ type: UPDATE_NOTIFICATION,
139
+ history: [...history]
140
+ })
141
+ }) as any)
142
+ }
143
+
144
+ stateChanged(state) {
145
+ this.history = state.notification.history
146
+ }
147
+
148
+ async disconnectedCallback() {
149
+ super.disconnectedCallback()
150
+
151
+ await Promise.all(
152
+ this.history
153
+ .filter(notification => !notification.confirmed)
154
+ .map(async notification => {
155
+ return await notificationStore.put({
156
+ ...notification,
157
+ confirmed: true
158
+ })
159
+ })
160
+ )
161
+
162
+ store.dispatch((async dispatch => {
163
+ const history = await notificationStore.getAll()
164
+
165
+ dispatch({
166
+ type: UPDATE_NOTIFICATION,
167
+ history: [...history]
168
+ })
169
+ }) as any)
170
+ }
171
+ }
@@ -0,0 +1,126 @@
1
+ import '@material/mwc-formfield'
2
+ import '@material/mwc-button'
3
+ import '@material/mwc-checkbox'
4
+ import '@operato/i18n/ox-i18n.js'
5
+
6
+ import { css, html, LitElement } from 'lit'
7
+ import { customElement, property } from 'lit/decorators.js'
8
+ import { auth } from '@things-factory/auth-base/dist-client'
9
+ import { i18next, localize } from '@operato/i18n'
10
+ import { ScrollbarStyles } from '@operato/styles'
11
+
12
+ import { notify as webpushNotify } from '../actions/notification-fcm'
13
+
14
+ @customElement('notification-sender')
15
+ export class NotificationSender extends localize(i18next)(LitElement) {
16
+ static styles = [
17
+ ScrollbarStyles,
18
+ css`
19
+ :host {
20
+ display: flex;
21
+ background-color: var(--main-section-background-color);
22
+ padding: var(--padding-wide);
23
+ }
24
+
25
+ form {
26
+ flex: 1;
27
+ display: flex;
28
+ flex-direction: column;
29
+ }
30
+ [content] > * {
31
+ margin: var(--margin-default);
32
+ }
33
+
34
+ [content] {
35
+ flex: 1;
36
+ flex-direction: column;
37
+ display: flex;
38
+ overflow: auto;
39
+ }
40
+
41
+ [buttons] {
42
+ margin-top: auto;
43
+ display: flex;
44
+ flex-direction: row-reverse;
45
+ }
46
+ mwc-button {
47
+ margin-left: var(--padding-default);
48
+ }
49
+
50
+ @media screen and (max-width: 480px) {
51
+ :host {
52
+ padding: var(--padding-default);
53
+ }
54
+ }
55
+ `
56
+ ]
57
+
58
+ render() {
59
+ return html`
60
+ <form>
61
+ <div content>
62
+ <mwc-textfield
63
+ type="text"
64
+ name="receivers"
65
+ .label=${i18next.t('field.receivers')}
66
+ placeholder=${auth.credential?.email}
67
+ required
68
+ icon="account_circle"
69
+ ></mwc-textfield>
70
+ <mwc-textfield
71
+ type="text"
72
+ name="title"
73
+ .label=${i18next.t('field.title')}
74
+ required
75
+ icon="notifications_none"
76
+ ></mwc-textfield>
77
+
78
+ <mwc-textfield
79
+ type="text"
80
+ name="image"
81
+ .label=${i18next.t('field.image')}
82
+ icon="insert_photo"
83
+ ></mwc-textfield>
84
+ <mwc-textfield type="text" name="url" .label=${i18next.t('field.url')} icon="link"></mwc-textfield>
85
+ <mwc-textarea type="text" name="body" .label=${i18next.t('field.body')} required rows="5"></mwc-textarea>
86
+ <mwc-formfield label="In-App Message">
87
+ <mwc-checkbox name="inappmsg"></mwc-checkbox>
88
+ </mwc-formfield>
89
+ </div>
90
+
91
+ <div buttons>
92
+ <mwc-button raised icon="send" @click=${e => this.ontest()}>
93
+ <ox-i18n msgid="button.notification-send"> </ox-i18n>
94
+ </mwc-button>
95
+
96
+ <mwc-button type="reset" outlined @click=${e => this.onReset()}>
97
+ <ox-i18n msgid="button.reset"> </ox-i18n>
98
+ </mwc-button>
99
+ </div>
100
+ </form>
101
+ `
102
+ }
103
+
104
+ ontest() {
105
+ const [receivers, title, body, image, url] = ['receivers', 'title', 'body', 'image', 'url'].map(
106
+ key => (this.renderRoot.querySelector(`[name="${key}"]`)! as any).value
107
+ )
108
+ const mode = (this.renderRoot.querySelector(`[name="inappmsg"]`)! as any).checked ? 'inapp' : 'background'
109
+
110
+ webpushNotify({
111
+ receivers,
112
+ title,
113
+ body,
114
+ image,
115
+ mode,
116
+ url
117
+ })
118
+ }
119
+
120
+ onReset() {
121
+ ;['receivers', 'title', 'body', 'image', 'url'].map(
122
+ key => ((this.renderRoot.querySelector(`[name="${key}"]`)! as any).value = '')
123
+ )
124
+ ;(this.renderRoot.querySelector(`[name="inappmsg"]`)! as any).checked = false
125
+ }
126
+ }
@@ -7,65 +7,63 @@ import '@operato/i18n/ox-i18n.js'
7
7
 
8
8
  import Clipboard from 'clipboard'
9
9
  import { css, html, LitElement } from 'lit'
10
+ import { customElement, property } from 'lit/decorators.js'
10
11
 
11
12
  import { notify, openPopup } from '@operato/layout'
12
- import { i18next, localize } from '@things-factory/i18n-base'
13
+ import { i18next, localize } from '@operato/i18n'
13
14
 
14
15
  import { getSubscriptionToken, isSupportingMessaging, subscribe, unsubscribe } from '../actions/notification-fcm'
15
16
 
17
+ @customElement('notification-setting-let')
16
18
  export class NotificationSettingLet extends localize(i18next)(LitElement) {
17
- static get styles() {
18
- return [
19
- css`
20
- div[onoff] {
21
- display: flex;
22
- align-items: center;
23
- border-bottom: var(--border-dark-color);
24
- margin-bottom: var(--margin-default);
25
- padding-bottom: var(--padding-default);
26
- }
19
+ static styles = [
20
+ css`
21
+ div[onoff] {
22
+ display: flex;
23
+ align-items: center;
24
+ border-bottom: var(--border-dark-color);
25
+ margin-bottom: var(--margin-default);
26
+ padding-bottom: var(--padding-default);
27
+ }
27
28
 
28
- div[info] {
29
- display: flex;
30
- flex-direction: column;
31
- position: relative;
32
- }
29
+ div[info] {
30
+ display: flex;
31
+ flex-direction: column;
32
+ position: relative;
33
+ }
33
34
 
34
- label {
35
- font: var(--label-font);
36
- color: var(--label-color);
37
- text-transform: var(--label-text-transform);
38
- }
35
+ label {
36
+ font: var(--label-font);
37
+ color: var(--label-color);
38
+ text-transform: var(--label-text-transform);
39
+ }
39
40
 
40
- [test] {
41
- margin-left: auto;
42
- }
41
+ [test] {
42
+ margin-left: auto;
43
+ }
43
44
 
44
- input {
45
- border: var(--border-dark-color);
46
- border-radius: var(--border-radius);
47
- margin: var(--input-margin);
48
- padding: var(--input-padding);
49
- font: var(--input-font);
45
+ input {
46
+ border: var(--border-dark-color);
47
+ border-radius: var(--border-radius);
48
+ margin: var(--input-margin);
49
+ padding: var(--input-padding);
50
+ font: var(--input-font);
50
51
 
51
- flex: 1;
52
- }
52
+ flex: 1;
53
+ }
53
54
 
54
- [button-in-field] {
55
- position: absolute;
56
- top: 24px;
57
- right: 4px;
58
- }
59
- `
60
- ]
61
- }
55
+ [button-in-field] {
56
+ position: absolute;
57
+ top: 24px;
58
+ right: 4px;
59
+ }
60
+ `
61
+ ]
62
62
 
63
- static get properties() {
64
- return {
65
- subscription: Object,
66
- supported: Boolean
67
- }
68
- }
63
+ @property({ type: Object }) subscription?: any
64
+ @property({ type: Boolean }) supported?: boolean
65
+
66
+ clipboard: any
69
67
 
70
68
  render() {
71
69
  const supported = !!this.supported
@@ -77,11 +75,11 @@ export class NotificationSettingLet extends localize(i18next)(LitElement) {
77
75
  ${supported
78
76
  ? html`
79
77
  <div slot="content" onoff>
80
- <mwc-formfield label=${i18next.t('label.allow push message')}>
78
+ <mwc-formfield label=${String(i18next.t('label.allow push message'))}>
81
79
  <mwc-switch label="allow message" ?selected=${!!this.subscription} @click=${e =>
82
80
  this.onClickSwitch(e)}></mwc-switch>
83
81
  </mwc-formfield>
84
- <mwc-button test outlined label=${i18next.t('button.push message test')} @click=${e =>
82
+ <mwc-button test outlined label=${String(i18next.t('button.push message test'))} @click=${e =>
85
83
  this.ontest()}></mwc-button>
86
84
  </div>
87
85
 
@@ -104,7 +102,7 @@ export class NotificationSettingLet extends localize(i18next)(LitElement) {
104
102
  const copybuttons = this.renderRoot.querySelectorAll('[clipboard-copy]')
105
103
 
106
104
  this.clipboard = new Clipboard(copybuttons, {
107
- target: trigger => trigger.parentElement.querySelector('input')
105
+ target: trigger => trigger.parentElement!.querySelector('input')!
108
106
  })
109
107
  }
110
108
  }
@@ -190,7 +188,7 @@ export class NotificationSettingLet extends localize(i18next)(LitElement) {
190
188
  } catch (err) {
191
189
  notify({
192
190
  level: 'error',
193
- message: err
191
+ message: String(err)
194
192
  })
195
193
  } finally {
196
194
  target.checked = !!this.subscription
@@ -205,5 +203,3 @@ export class NotificationSettingLet extends localize(i18next)(LitElement) {
205
203
  })
206
204
  }
207
205
  }
208
-
209
- customElements.define('notification-setting-let', NotificationSettingLet)
@@ -0,0 +1,7 @@
1
+ export declare const UPDATE_NOTIFICATION = "UPDATE_NOTIFICATION";
2
+ export declare const CONFIRM_NOTIFICATION = "CONFIRM_NOTIFICATION";
3
+ export declare function isSupportingMessaging(): Promise<boolean>;
4
+ export declare function getSubscriptionToken(force?: boolean): Promise<any>;
5
+ export declare function subscribe(): Promise<any>;
6
+ export declare function unsubscribe(): Promise<void>;
7
+ export declare function notify(options: any): Promise<boolean>;
@@ -0,0 +1,125 @@
1
+ export const UPDATE_NOTIFICATION = 'UPDATE_NOTIFICATION';
2
+ export const CONFIRM_NOTIFICATION = 'CONFIRM_NOTIFICATION';
3
+ import { initializeApp } from 'firebase/app';
4
+ import { getMessaging, getToken, deleteToken } from 'firebase/messaging';
5
+ import { synchronize } from '@things-factory/utils';
6
+ var vapidKey;
7
+ var appConfig;
8
+ var messaging;
9
+ async function _getVapidKey() {
10
+ if (!vapidKey || !appConfig) {
11
+ if (Notification.permission === 'denied') {
12
+ console.warn('Notification permission denied');
13
+ return;
14
+ }
15
+ const response = await fetch('/notification/config', {
16
+ headers: {
17
+ Accept: 'application/json'
18
+ }
19
+ });
20
+ if (!response.ok) {
21
+ throw new Error(`fail to get notification configuration: ${response.status}`);
22
+ }
23
+ const conf = await response.json();
24
+ if (!conf || !conf.vapidPublicKey || !conf.appConfig) {
25
+ throw new Error('correct notification configuration required.');
26
+ }
27
+ try {
28
+ const app = await initializeApp(conf.appConfig);
29
+ messaging = getMessaging(app);
30
+ // messaging = _messaging.isSupported() ? _messaging() : null
31
+ if (!messaging) {
32
+ console.warn('###################################################');
33
+ console.warn('push notification is not supported in this browser.');
34
+ console.warn('###################################################');
35
+ }
36
+ vapidKey = conf.vapidPublicKey;
37
+ appConfig = conf.appConfig;
38
+ }
39
+ catch (err) {
40
+ throw new Error(`failed to initialize firebase app.`);
41
+ }
42
+ }
43
+ return { vapidKey, messaging };
44
+ }
45
+ // to avoid race condition
46
+ const getVapidKey = synchronize(_getVapidKey);
47
+ export async function isSupportingMessaging() {
48
+ const { messaging } = await getVapidKey();
49
+ return !!messaging;
50
+ }
51
+ export async function getSubscriptionToken(force = false) {
52
+ var _a;
53
+ // const registration = await navigator.serviceWorker.getRegistration('/')
54
+ const registration = await ((_a = navigator.serviceWorker) === null || _a === void 0 ? void 0 : _a.ready);
55
+ if (!registration) {
56
+ console.warn('service worker not registered.');
57
+ return;
58
+ }
59
+ if (!registration.pushManager || (!force && !(await registration.pushManager.getSubscription()))) {
60
+ return;
61
+ }
62
+ const { vapidKey, messaging } = (await getVapidKey()) || {};
63
+ try {
64
+ return (vapidKey &&
65
+ (await getToken(messaging, {
66
+ vapidKey,
67
+ serviceWorkerRegistration: registration
68
+ })));
69
+ }
70
+ catch (err) {
71
+ console.error(err);
72
+ }
73
+ }
74
+ export async function subscribe() {
75
+ const token = await getSubscriptionToken(true);
76
+ if (!token) {
77
+ return;
78
+ }
79
+ await fetch('/notification/register', {
80
+ method: 'post',
81
+ headers: {
82
+ 'Content-type': 'application/json',
83
+ Accept: 'application/json'
84
+ },
85
+ body: JSON.stringify({
86
+ subscription: token
87
+ })
88
+ });
89
+ return token;
90
+ }
91
+ export async function unsubscribe() {
92
+ const token = await getSubscriptionToken();
93
+ if (!token) {
94
+ return;
95
+ }
96
+ try {
97
+ const { vapidKey, messaging } = (await getVapidKey()) || {};
98
+ vapidKey && (await deleteToken(messaging));
99
+ }
100
+ catch (err) {
101
+ console.error(err);
102
+ }
103
+ await fetch('/notification/unregister', {
104
+ method: 'post',
105
+ headers: {
106
+ 'Content-type': 'application/json',
107
+ Accept: 'application/json'
108
+ },
109
+ body: JSON.stringify({
110
+ subscription: token
111
+ })
112
+ });
113
+ }
114
+ export async function notify(options) {
115
+ const response = await fetch('/notification/notify', {
116
+ method: 'post',
117
+ headers: {
118
+ 'Content-type': 'application/json',
119
+ Accept: 'application/json'
120
+ },
121
+ body: JSON.stringify(options)
122
+ });
123
+ return response.ok;
124
+ }
125
+ //# sourceMappingURL=notification-fcm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification-fcm.js","sourceRoot":"","sources":["../../client/actions/notification-fcm.ts"],"names":[],"mappings":"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","sourcesContent":["export const UPDATE_NOTIFICATION = 'UPDATE_NOTIFICATION'\nexport const CONFIRM_NOTIFICATION = 'CONFIRM_NOTIFICATION'\n\nimport { initializeApp } from 'firebase/app'\nimport { getMessaging, getToken, deleteToken } from 'firebase/messaging'\n\nimport { synchronize } from '@things-factory/utils'\n\nvar vapidKey\nvar appConfig\nvar messaging\n\nasync function _getVapidKey() {\n if (!vapidKey || !appConfig) {\n if (Notification.permission === 'denied') {\n console.warn('Notification permission denied')\n return\n }\n\n const response = await fetch('/notification/config', {\n headers: {\n Accept: 'application/json'\n }\n })\n if (!response.ok) {\n throw new Error(`fail to get notification configuration: ${response.status}`)\n }\n const conf = await response.json()\n\n if (!conf || !conf.vapidPublicKey || !conf.appConfig) {\n throw new Error('correct notification configuration required.')\n }\n\n try {\n const app = await initializeApp(conf.appConfig)\n messaging = getMessaging(app)\n\n // messaging = _messaging.isSupported() ? _messaging() : null\n if (!messaging) {\n console.warn('###################################################')\n console.warn('push notification is not supported in this browser.')\n console.warn('###################################################')\n }\n\n vapidKey = conf.vapidPublicKey\n appConfig = conf.appConfig\n } catch (err) {\n throw new Error(`failed to initialize firebase app.`)\n }\n }\n\n return { vapidKey, messaging }\n}\n\n// to avoid race condition\nconst getVapidKey = synchronize(_getVapidKey)\n\nexport async function isSupportingMessaging() {\n const { messaging } = await getVapidKey()\n return !!messaging\n}\n\nexport async function getSubscriptionToken(force = false) {\n // const registration = await navigator.serviceWorker.getRegistration('/')\n const registration = await navigator.serviceWorker?.ready\n\n if (!registration) {\n console.warn('service worker not registered.')\n return\n }\n\n if (!registration.pushManager || (!force && !(await registration.pushManager.getSubscription()))) {\n return\n }\n\n const { vapidKey, messaging } = (await getVapidKey()) || {}\n\n try {\n return (\n vapidKey &&\n (await getToken(messaging, {\n vapidKey,\n serviceWorkerRegistration: registration\n }))\n )\n } catch (err) {\n console.error(err)\n }\n}\n\nexport async function subscribe() {\n const token = await getSubscriptionToken(true)\n\n if (!token) {\n return\n }\n\n await fetch('/notification/register', {\n method: 'post',\n headers: {\n 'Content-type': 'application/json',\n Accept: 'application/json'\n },\n body: JSON.stringify({\n subscription: token\n })\n })\n\n return token\n}\n\nexport async function unsubscribe() {\n const token = await getSubscriptionToken()\n if (!token) {\n return\n }\n\n try {\n const { vapidKey, messaging } = (await getVapidKey()) || {}\n vapidKey && (await deleteToken(messaging))\n } catch (err) {\n console.error(err)\n }\n\n await fetch('/notification/unregister', {\n method: 'post',\n headers: {\n 'Content-type': 'application/json',\n Accept: 'application/json'\n },\n body: JSON.stringify({\n subscription: token\n })\n })\n}\n\nexport async function notify(options) {\n const response = await fetch('/notification/notify', {\n method: 'post',\n headers: {\n 'Content-type': 'application/json',\n Accept: 'application/json'\n },\n body: JSON.stringify(options)\n })\n\n return response.ok\n}\n"]}
@@ -0,0 +1 @@
1
+ export default function bootstrap(): Promise<void>;