@konemono/nostr-login 1.7.11

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 (43) hide show
  1. package/.prettierrc.json +13 -0
  2. package/README.md +167 -0
  3. package/dist/const/index.d.ts +1 -0
  4. package/dist/iife-module.d.ts +1 -0
  5. package/dist/index.d.ts +27 -0
  6. package/dist/index.esm.js +18 -0
  7. package/dist/index.esm.js.map +1 -0
  8. package/dist/modules/AuthNostrService.d.ts +84 -0
  9. package/dist/modules/BannerManager.d.ts +20 -0
  10. package/dist/modules/ModalManager.d.ts +25 -0
  11. package/dist/modules/Nip46.d.ts +56 -0
  12. package/dist/modules/Nostr.d.ts +34 -0
  13. package/dist/modules/NostrExtensionService.d.ts +17 -0
  14. package/dist/modules/NostrParams.d.ts +8 -0
  15. package/dist/modules/Popup.d.ts +7 -0
  16. package/dist/modules/ProcessManager.d.ts +10 -0
  17. package/dist/modules/Signer.d.ts +9 -0
  18. package/dist/modules/index.d.ts +8 -0
  19. package/dist/types.d.ts +72 -0
  20. package/dist/unpkg.js +17 -0
  21. package/dist/utils/index.d.ts +27 -0
  22. package/dist/utils/nip44.d.ts +9 -0
  23. package/index.html +30 -0
  24. package/package.json +28 -0
  25. package/rollup.config.js +55 -0
  26. package/src/const/index.ts +1 -0
  27. package/src/iife-module.ts +81 -0
  28. package/src/index.ts +347 -0
  29. package/src/modules/AuthNostrService.ts +756 -0
  30. package/src/modules/BannerManager.ts +146 -0
  31. package/src/modules/ModalManager.ts +635 -0
  32. package/src/modules/Nip46.ts +441 -0
  33. package/src/modules/Nostr.ts +107 -0
  34. package/src/modules/NostrExtensionService.ts +99 -0
  35. package/src/modules/NostrParams.ts +18 -0
  36. package/src/modules/Popup.ts +27 -0
  37. package/src/modules/ProcessManager.ts +67 -0
  38. package/src/modules/Signer.ts +25 -0
  39. package/src/modules/index.ts +8 -0
  40. package/src/types.ts +124 -0
  41. package/src/utils/index.ts +326 -0
  42. package/src/utils/nip44.ts +185 -0
  43. package/tsconfig.json +15 -0
@@ -0,0 +1,635 @@
1
+ import { NostrLoginOptions, StartScreens, TypeModal } from '../types';
2
+ import { checkNip05, getBunkerUrl, getDarkMode, localStorageRemoveRecent, localStorageSetItem, prepareSignupRelays } from '../utils';
3
+ import { AuthNostrService, NostrExtensionService, NostrParams } from '.';
4
+ import { EventEmitter } from 'tseep';
5
+ import { ConnectionString, Info, RecentType } from 'nostr-login-components';
6
+ import { nip19 } from 'nostr-tools';
7
+ import { setDarkMode } from '..';
8
+
9
+ class ModalManager extends EventEmitter {
10
+ private modal: TypeModal | null = null;
11
+ private params: NostrParams;
12
+ private extensionService: NostrExtensionService;
13
+ private authNostrService: AuthNostrService;
14
+ private launcherPromise?: Promise<void>;
15
+ private accounts: Info[] = [];
16
+ private recents: RecentType[] = [];
17
+ private opt?: NostrLoginOptions;
18
+
19
+ constructor(params: NostrParams, authNostrService: AuthNostrService, extensionManager: NostrExtensionService) {
20
+ super();
21
+ this.params = params;
22
+ this.extensionService = extensionManager;
23
+ this.authNostrService = authNostrService;
24
+ }
25
+
26
+ public async waitReady() {
27
+ if (this.launcherPromise) {
28
+ try {
29
+ await this.launcherPromise;
30
+ } catch {}
31
+ this.launcherPromise = undefined;
32
+ }
33
+ }
34
+
35
+ public async launch(opt: NostrLoginOptions) {
36
+ console.log('nostr-login launch', opt);
37
+ // mutex
38
+ if (this.launcherPromise) await this.waitReady();
39
+
40
+ // hmm?!
41
+ if (this.authNostrService.isAuthing()) this.authNostrService.resetAuth();
42
+
43
+ this.opt = opt;
44
+
45
+ const dialog = document.createElement('dialog');
46
+ this.modal = document.createElement('nl-auth');
47
+ this.modal.accounts = this.accounts;
48
+ this.modal.recents = this.recents;
49
+
50
+ this.modal.setAttribute('dark-mode', String(getDarkMode(opt)));
51
+
52
+ if (opt.theme) {
53
+ this.modal.setAttribute('theme', opt.theme);
54
+ }
55
+
56
+ if (opt.startScreen) {
57
+ this.modal.setAttribute('start-screen', opt.startScreen);
58
+ }
59
+
60
+ if (opt.bunkers) {
61
+ this.modal.setAttribute('bunkers', opt.bunkers);
62
+ } else {
63
+ let bunkers = 'nsec.app,highlighter.com';
64
+ // if (opt.dev) bunkers += ',new.nsec.app';
65
+ this.modal.setAttribute('bunkers', bunkers);
66
+ }
67
+
68
+ if (opt.methods !== undefined) {
69
+ this.modal.authMethods = opt.methods;
70
+ }
71
+
72
+ if (opt.localSignup !== undefined) {
73
+ this.modal.localSignup = opt.localSignup;
74
+ }
75
+
76
+ if (opt.signupNstart !== undefined) {
77
+ this.modal.signupNjump = opt.signupNstart;
78
+ }
79
+
80
+ if (opt.title) {
81
+ this.modal.welcomeTitle = opt.title;
82
+ }
83
+
84
+ if (opt.description) {
85
+ this.modal.welcomeDescription = opt.description;
86
+ }
87
+
88
+ this.modal.hasExtension = this.extensionService.hasExtension();
89
+ this.modal.hasOTP = !!opt.otpRequestUrl && !!opt.otpReplyUrl;
90
+
91
+ this.modal.isLoadingExtension = false;
92
+ this.modal.isLoading = false;
93
+
94
+ [this.modal.connectionString, this.modal.connectionStringServices] = await this.authNostrService.getNostrConnectServices();
95
+
96
+ dialog.appendChild(this.modal);
97
+ document.body.appendChild(dialog);
98
+
99
+ let otpPubkey = '';
100
+
101
+ this.launcherPromise = new Promise<void>((ok, err) => {
102
+ dialog.addEventListener('close', () => {
103
+ // noop if already resolved
104
+ err(new Error('Closed'));
105
+
106
+ this.authNostrService.resetAuth();
107
+
108
+ if (this.modal) {
109
+ // it's reset on modal creation
110
+ // // reset state
111
+ // this.modal.isLoading = false;
112
+ // this.modal.authUrl = '';
113
+ // this.modal.iframeUrl = '';
114
+ // this.modal.error = '';
115
+ // this.modal.isLoadingExtension = false;
116
+
117
+ // drop it
118
+ // @ts-ignore
119
+ document.body.removeChild(this.modal.parentNode);
120
+ this.modal = null;
121
+ }
122
+ });
123
+
124
+ const done = async (ok: () => void) => {
125
+ if (this.modal) this.modal.isLoading = false;
126
+ await this.authNostrService.endAuth();
127
+ dialog.close();
128
+ this.modal = null;
129
+ ok();
130
+ };
131
+
132
+ const exec = async (
133
+ body: () => Promise<void>,
134
+ options?: {
135
+ start?: boolean;
136
+ end?: boolean;
137
+ },
138
+ ) => {
139
+ if (this.modal) {
140
+ this.modal.isLoading = true;
141
+ }
142
+
143
+ try {
144
+ if (!options || options.start) await this.authNostrService.startAuth();
145
+ await body();
146
+ if (!options || options.end) await done(ok);
147
+ } catch (e: any) {
148
+ console.log('error', e);
149
+ if (this.modal) {
150
+ this.modal.isLoading = false;
151
+ this.modal.authUrl = '';
152
+ this.modal.iframeUrl = '';
153
+ if (e !== 'cancelled') this.modal.error = e.toString();
154
+ }
155
+ }
156
+ };
157
+
158
+ const login = async (name: string, domain?: string) => {
159
+ await exec(async () => {
160
+ // convert name to bunker url
161
+ const bunkerUrl = await getBunkerUrl(name, this.params.optionsModal);
162
+
163
+ // connect to bunker by url
164
+ await this.authNostrService.authNip46('login', { name, bunkerUrl, domain });
165
+ });
166
+ };
167
+
168
+ const signup = async (name: string) => {
169
+ await exec(async () => {
170
+ // create acc on service and get bunker url
171
+ const { bunkerUrl, sk } = await this.authNostrService.createAccount(name);
172
+
173
+ // connect to bunker by url
174
+ await this.authNostrService.authNip46('signup', { name, bunkerUrl, sk });
175
+ });
176
+ };
177
+
178
+ const exportKeys = async () => {
179
+ try {
180
+ await navigator.clipboard.writeText(this.authNostrService.exportKeys());
181
+ localStorageSetItem('backupKey', 'true');
182
+ } catch (err) {
183
+ console.error('Failed to copy to clipboard: ', err);
184
+ }
185
+ };
186
+
187
+ const importKeys = async (cs: ConnectionString) => {
188
+ await exec(async () => {
189
+ const { iframeUrl } = cs;
190
+ cs.link = this.authNostrService.prepareImportUrl(cs.link);
191
+
192
+ if (this.modal && iframeUrl) {
193
+ // we pass the link down to iframe so it could open it
194
+ this.modal.authUrl = cs.link;
195
+ this.modal.iframeUrl = iframeUrl;
196
+ this.modal.isLoading = false;
197
+ console.log('nostrconnect authUrl', this.modal.authUrl, this.modal.iframeUrl);
198
+ }
199
+
200
+ await this.authNostrService.importAndConnect(cs);
201
+ });
202
+ };
203
+
204
+ const nostrConnect = async (cs?: ConnectionString) => {
205
+ await exec(async () => {
206
+ const { relay, domain, link, iframeUrl } = cs || {};
207
+ console.log('nostrConnect', cs, relay, domain, link, iframeUrl);
208
+
209
+ if (this.modal) {
210
+ if (iframeUrl) {
211
+ // we pass the link down to iframe so it could open it
212
+ this.modal.authUrl = link;
213
+ this.modal.iframeUrl = iframeUrl;
214
+ this.modal.isLoading = false;
215
+ console.log('nostrconnect authUrl', this.modal.authUrl, this.modal.iframeUrl);
216
+ }
217
+
218
+ if (!cs) this.modal.isLoading = false;
219
+ }
220
+
221
+ await this.authNostrService.nostrConnect(relay, { domain, link, iframeUrl });
222
+ });
223
+ };
224
+
225
+ const localSignup = async (name?: string) => {
226
+ await exec(async () => {
227
+ if (!name) throw new Error('Please enter some nickname');
228
+ await this.authNostrService.localSignup(name);
229
+ });
230
+ };
231
+
232
+ const signupNjump = async () => {
233
+ await exec(async () => {
234
+ const self = new URL(window.location.href);
235
+ const name =
236
+ self.hostname
237
+ .toLocaleLowerCase()
238
+ .replace(/^www\./i, '')
239
+ .charAt(0)
240
+ .toUpperCase() + self.hostname.slice(1);
241
+ const relays = prepareSignupRelays(this.params.optionsModal.signupRelays);
242
+ // const url = `https://start.njump.me/?an=${name}&at=popup&ac=${window.location.href}&s=${this.opt!.followNpubs || ''}&arr=${relays}&awr=${relays}`;
243
+ // console.log('njump url', url);
244
+
245
+ this.modal!.njumpIframe = `
246
+ <html><body>
247
+ <script src='https://start.njump.me/modal.js'></script>
248
+ <script>
249
+ new NstartModal({
250
+ baseUrl: 'https://start.njump.me',
251
+ // Required parameters
252
+ an: '${name}',
253
+ // Optional parameters
254
+ s: [${this.opt!.followNpubs ? `'${this.opt!.followNpubs}'` : ''}],
255
+ afb: false, // forceBunker
256
+ asb: false, // skipBunker
257
+ aan: false, // avoidNsec
258
+ aac: true, // avoidNcryptsec
259
+ ahc: true, // hide close button
260
+ arr: ${JSON.stringify(relays)}, //readRelays
261
+ awr: ${JSON.stringify(relays)}, //writeRelays
262
+ // Callbacks
263
+ onComplete: (result) => {
264
+ console.log('Login token:', result.nostrLogin);
265
+ window.parent.location.href='${window.location.href}#nostr-login='+result.nostrLogin;
266
+ },
267
+ onCancel: () => {
268
+ window.parent.location.href='${window.location.href}#nostr-login=null';
269
+ },
270
+ }).open();
271
+ </script>
272
+ </body></html>
273
+ `.replaceAll('&', '&amp;'); // needed?
274
+
275
+ return new Promise((ok, err) => {
276
+ const process = async (nsecOrBunker: string) => {
277
+ // process the returned value
278
+ console.log('nsecOrBunker', nsecOrBunker);
279
+ if (nsecOrBunker.startsWith('nsec1')) {
280
+ let decoded;
281
+ try {
282
+ decoded = nip19.decode(nsecOrBunker);
283
+ } catch (e) {
284
+ throw new Error('Bad nsec value');
285
+ }
286
+ if (decoded.type !== 'nsec') throw new Error('Bad bech32 type');
287
+ await this.authNostrService.localSignup('', decoded.data);
288
+ ok();
289
+ } else if (nsecOrBunker.startsWith('bunker:')) {
290
+ await this.authNostrService.authNip46('login', { name: '', bunkerUrl: nsecOrBunker });
291
+ ok();
292
+ } else if (nsecOrBunker === 'null') {
293
+ err('Cancelled');
294
+ } else {
295
+ err('Unknown return value');
296
+ }
297
+ };
298
+
299
+ const onOpen = async () => {
300
+ if (window.location.hash.startsWith('#nostr-login=')) {
301
+ const nsecOrBunker = window.location.hash.split('#nostr-login=')[1];
302
+
303
+ // clear hash from history
304
+ const url = new URL(window.location.toString());
305
+ url.hash = '';
306
+ window.history.replaceState({}, '', url.toString());
307
+
308
+ process(nsecOrBunker);
309
+ }
310
+ };
311
+
312
+ // // use random 'target' to make sure window.opener is
313
+ // // accessible to the popup
314
+ // window.open(url, '' + Date.now(), 'popup=true,width=600,height=950');
315
+ window.addEventListener('hashchange', onOpen);
316
+ });
317
+ });
318
+ };
319
+
320
+ if (!this.modal) throw new Error('WTH?');
321
+
322
+ this.modal.addEventListener('handleContinue', () => {
323
+ if (this.modal) {
324
+ this.modal.isLoading = true;
325
+ this.emit('onAuthUrlClick', this.modal.authUrl);
326
+ }
327
+ });
328
+
329
+ this.modal.addEventListener('nlLogin', (event: any) => {
330
+ login(event.detail);
331
+ });
332
+
333
+ this.modal.addEventListener('nlSignup', (event: any) => {
334
+ signup(event.detail);
335
+ });
336
+
337
+ this.modal.addEventListener('nlLocalSignup', (event: any) => {
338
+ localSignup(event.detail);
339
+ });
340
+
341
+ this.modal.addEventListener('nlSignupNjump', (event: any) => {
342
+ signupNjump();
343
+ });
344
+
345
+ this.modal.addEventListener('nlImportAccount', (event: any) => {
346
+ importKeys(event.detail);
347
+ });
348
+
349
+ this.modal.addEventListener('nlExportKeys', (event: any) => {
350
+ exportKeys();
351
+ });
352
+
353
+ this.modal.addEventListener('handleLogoutBanner', () => {
354
+ this.emit('onLogoutBanner');
355
+ });
356
+
357
+ this.modal.addEventListener('nlNostrConnect', (event: any) => {
358
+ nostrConnect(event.detail);
359
+ });
360
+
361
+ this.modal.addEventListener('nlNostrConnectDefault', () => {
362
+ // dedup the calls
363
+ if (!this.authNostrService.isAuthing()) nostrConnect();
364
+ });
365
+
366
+ this.modal.addEventListener('nlNostrConnectDefaultCancel', () => {
367
+ console.log('nlNostrConnectDefaultCancel');
368
+ this.authNostrService.cancelNostrConnect();
369
+ });
370
+
371
+ this.modal.addEventListener('nlSwitchAccount', (event: any) => {
372
+ const eventInfo: Info = event.detail as Info;
373
+
374
+ this.emit('onSwitchAccount', eventInfo);
375
+
376
+ // wait a bit, if dialog closes before
377
+ // switching finishes then launched promise rejects
378
+
379
+ // FIXME this calls resetAuth which then prevents
380
+ // endAuth from getting properly called. 300 is not
381
+ // enough to init iframe, so there should be a
382
+ // feedback from switchAccount here
383
+ setTimeout(() => dialog.close(), 300);
384
+ });
385
+
386
+ this.modal.addEventListener('nlLoginRecentAccount', async (event: any) => {
387
+ const userInfo: Info = event.detail as Info;
388
+
389
+ if (userInfo.authMethod === 'readOnly') {
390
+ this.authNostrService.setReadOnly(userInfo.pubkey);
391
+ dialog.close();
392
+ } else if (userInfo.authMethod === 'otp') {
393
+ try {
394
+ this.modal!.dispatchEvent(
395
+ new CustomEvent('nlLoginOTPUser', {
396
+ detail: userInfo.nip05 || userInfo.pubkey,
397
+ }),
398
+ );
399
+ } catch (e) {
400
+ console.error(e);
401
+ }
402
+ } else if (userInfo.authMethod === 'extension') {
403
+ await this.extensionService.trySetExtensionForPubkey(userInfo.pubkey);
404
+ dialog.close();
405
+ } else {
406
+ const input = userInfo.bunkerUrl || userInfo.nip05;
407
+ if (!input) throw new Error('Bad connect info');
408
+ login(input, userInfo.domain);
409
+ }
410
+ });
411
+
412
+ this.modal.addEventListener('nlRemoveRecent', (event: any) => {
413
+ localStorageRemoveRecent(event.detail as RecentType);
414
+ this.emit('updateAccounts');
415
+ });
416
+
417
+ const nameToPubkey = async (nameNpub: string) => {
418
+ let pubkey = '';
419
+ if (nameNpub.includes('@')) {
420
+ const { error, pubkey: nip05pubkey } = await checkNip05(nameNpub);
421
+ if (nip05pubkey) pubkey = nip05pubkey;
422
+ else throw new Error(error);
423
+ } else if (nameNpub.startsWith('npub')) {
424
+ const { type, data } = nip19.decode(nameNpub);
425
+ if (type === 'npub') pubkey = data as string;
426
+ else throw new Error('Bad npub');
427
+ } else if (nameNpub.trim().length === 64) {
428
+ pubkey = nameNpub.trim();
429
+ nip19.npubEncode(pubkey); // check
430
+ }
431
+ return pubkey;
432
+ };
433
+
434
+ this.modal.addEventListener('nlLoginReadOnly', async (event: any) => {
435
+ await exec(async () => {
436
+ const nameNpub = event.detail;
437
+ const pubkey = await nameToPubkey(nameNpub);
438
+ this.authNostrService.setReadOnly(pubkey);
439
+ });
440
+ });
441
+
442
+ this.modal.addEventListener('nlLoginExtension', async () => {
443
+ if (!this.extensionService.hasExtension()) {
444
+ throw new Error('No extension');
445
+ }
446
+
447
+ await exec(async () => {
448
+ if (!this.modal) return;
449
+ this.modal.isLoadingExtension = true;
450
+ await this.extensionService.setExtension();
451
+ this.modal.isLoadingExtension = false;
452
+ });
453
+ });
454
+
455
+ this.modal.addEventListener('nlLoginOTPUser', async (event: any) => {
456
+ await exec(
457
+ async () => {
458
+ if (!this.modal) return;
459
+
460
+ const nameNpub = event.detail;
461
+ const pubkey = await nameToPubkey(nameNpub);
462
+ const url = this.opt!.otpRequestUrl! + (this.opt!.otpRequestUrl!.includes('?') ? '&' : '?') + 'pubkey=' + pubkey;
463
+ const r = await fetch(url);
464
+ if (r.status !== 200) {
465
+ console.warn('nostr-login: bad otp reply', r);
466
+ throw new Error('Failed to send DM');
467
+ }
468
+
469
+ // switch to 'enter code' mode
470
+ this.modal.isOTP = true;
471
+
472
+ // remember for code handler below
473
+ otpPubkey = pubkey;
474
+
475
+ // spinner off
476
+ this.modal.isLoading = false;
477
+ },
478
+ { start: true },
479
+ );
480
+ });
481
+
482
+ this.modal.addEventListener('nlLoginOTPCode', async (event: any) => {
483
+ await exec(
484
+ async () => {
485
+ if (!this.modal) return;
486
+ const code = event.detail;
487
+ const url = this.opt!.otpReplyUrl! + (this.opt!.otpRequestUrl!.includes('?') ? '&' : '?') + 'pubkey=' + otpPubkey + '&code=' + code;
488
+ const r = await fetch(url);
489
+ if (r.status !== 200) {
490
+ console.warn('nostr-login: bad otp reply', r);
491
+ throw new Error('Invalid code');
492
+ }
493
+
494
+ const data = await r.text();
495
+ this.authNostrService.setOTP(otpPubkey, data);
496
+
497
+ this.modal.isOTP = false;
498
+ },
499
+ { end: true },
500
+ );
501
+ });
502
+
503
+ this.modal.addEventListener('nlCheckSignup', async (event: any) => {
504
+ const { available, taken, error } = await checkNip05(event.detail);
505
+ if (this.modal) {
506
+ this.modal.error = String(error);
507
+
508
+ if (!error && taken) {
509
+ this.modal.error = 'Already taken';
510
+ }
511
+
512
+ this.modal.signupNameIsAvailable = available;
513
+ }
514
+ });
515
+
516
+ this.modal.addEventListener('nlCheckLogin', async (event: any) => {
517
+ const { available, taken, error } = await checkNip05(event.detail);
518
+ if (this.modal) {
519
+ this.modal.error = String(error);
520
+ if (available) {
521
+ this.modal.error = 'Name not found';
522
+ }
523
+ this.modal.loginIsGood = taken;
524
+ }
525
+ });
526
+
527
+ const cancel = () => {
528
+ if (this.modal) {
529
+ this.modal.isLoading = false;
530
+ }
531
+
532
+ // this.authNostrService.cancelListenNostrConnect();
533
+
534
+ dialog.close();
535
+ err(new Error('Cancelled'));
536
+ };
537
+ this.modal.addEventListener('stopFetchHandler', cancel);
538
+ this.modal.addEventListener('nlCloseModal', cancel);
539
+
540
+ this.modal.addEventListener('nlChangeDarkMode', (event: any) => {
541
+ setDarkMode(event.detail);
542
+ document.dispatchEvent(new CustomEvent('nlDarkMode', { detail: event.detail }));
543
+ });
544
+
545
+ this.on('onIframeAuthUrlCallEnd', () => {
546
+ dialog.close();
547
+ this.modal = null;
548
+ ok();
549
+ });
550
+
551
+ dialog.showModal();
552
+ });
553
+
554
+ return this.launcherPromise;
555
+ }
556
+
557
+ public async showIframeUrl(url: string) {
558
+ // make sure we consume the previous promise,
559
+ // otherwise launch will start await-ing
560
+ // before modal is created and setting iframeUrl will fail
561
+ await this.waitReady();
562
+
563
+ this.launch({
564
+ startScreen: 'iframe' as StartScreens,
565
+ }).catch(() => console.log('closed auth iframe'));
566
+
567
+ this.modal!.authUrl = url;
568
+ }
569
+
570
+ public connectModals(defaultOpt: NostrLoginOptions) {
571
+ const initialModals = async (opt: NostrLoginOptions) => {
572
+ await this.launch(opt);
573
+ };
574
+
575
+ const nlElements = document.getElementsByTagName('nl-button');
576
+
577
+ for (let i = 0; i < nlElements.length; i++) {
578
+ const theme = nlElements[i].getAttribute('nl-theme');
579
+ const startScreen = nlElements[i].getAttribute('start-screen');
580
+
581
+ const elementOpt = {
582
+ ...defaultOpt,
583
+ };
584
+ if (theme) elementOpt.theme = theme;
585
+
586
+ switch (startScreen as StartScreens) {
587
+ case 'login':
588
+ case 'login-bunker-url':
589
+ case 'login-read-only':
590
+ case 'signup':
591
+ case 'switch-account':
592
+ case 'welcome':
593
+ elementOpt.startScreen = startScreen as StartScreens;
594
+ }
595
+
596
+ nlElements[i].addEventListener('click', function () {
597
+ initialModals(elementOpt);
598
+ });
599
+ }
600
+ }
601
+
602
+ public onAuthUrl(url: string) {
603
+ if (this.modal) {
604
+ this.modal.authUrl = url;
605
+ this.modal.isLoading = false;
606
+ }
607
+ }
608
+
609
+ public onIframeUrl(url: string) {
610
+ if (this.modal) {
611
+ console.log('modal iframe url', url);
612
+ this.modal.iframeUrl = url;
613
+ }
614
+ }
615
+
616
+ public onCallEnd() {
617
+ if (this.modal && this.modal.authUrl && this.params.userInfo?.iframeUrl) {
618
+ this.emit('onIframeAuthUrlCallEnd');
619
+ }
620
+ }
621
+
622
+ public onUpdateAccounts(accounts: Info[], recents: RecentType[]) {
623
+ this.accounts = accounts;
624
+ this.recents = recents;
625
+ if (!this.modal) return;
626
+ this.modal.accounts = accounts;
627
+ this.modal.recents = recents;
628
+ }
629
+
630
+ public onDarkMode(dark: boolean) {
631
+ if (this.modal) this.modal.darkMode = dark;
632
+ }
633
+ }
634
+
635
+ export default ModalManager;