settings.component.ts raw
1 import { Component, inject, OnInit } from '@angular/core';
2 import { FormsModule } from '@angular/forms';
3 import { Router } from '@angular/router';
4 import {
5 BrowserSyncFlow,
6 ConfirmComponent,
7 DateHelper,
8 LoggerService,
9 NavComponent,
10 NavItemComponent,
11 StartupService,
12 StorageService,
13 } from '@common';
14 import { getNewStorageServiceConfig } from '../../../common/data/get-new-storage-service-config';
15 import { Buffer } from 'buffer';
16 import browser from 'webextension-polyfill';
17
18 @Component({
19 selector: 'app-settings',
20 imports: [ConfirmComponent, NavItemComponent, FormsModule],
21 templateUrl: './settings.component.html',
22 styleUrl: './settings.component.scss',
23 })
24 export class SettingsComponent extends NavComponent implements OnInit {
25 readonly #router = inject(Router);
26 syncFlow: string | undefined;
27 override devMode = false;
28 newPassword = '';
29 changingPassword = false;
30 passwordChanged = false;
31
32 readonly #storage = inject(StorageService);
33 readonly #startup = inject(StartupService);
34 readonly #logger = inject(LoggerService);
35
36 ngOnInit(): void {
37 const vault = JSON.stringify(
38 this.#storage.getBrowserSyncHandler().browserSyncData
39 );
40 console.log(vault.length / 1024 + ' KB');
41
42 switch (this.#storage.getSignerMetaHandler().signerMetaData?.syncFlow) {
43 case BrowserSyncFlow.NO_SYNC:
44 this.syncFlow = 'Off';
45 break;
46
47 case BrowserSyncFlow.BROWSER_SYNC:
48 this.syncFlow = 'Mozilla Firefox';
49 break;
50
51 default:
52 break;
53 }
54
55 // Load dev mode setting
56 this.devMode = this.#storage.getSignerMetaHandler().signerMetaData?.devMode ?? false;
57 }
58
59 async onToggleDevMode(event: Event) {
60 const checked = (event.target as HTMLInputElement).checked;
61 this.devMode = checked;
62 await this.#storage.getSignerMetaHandler().setDevMode(checked);
63 }
64
65 override async onTestPrompt() {
66 // Open a test permission prompt window
67 const testEvent = {
68 kind: 1,
69 content: 'This is a test note for permission prompt preview.',
70 tags: [],
71 created_at: Math.floor(Date.now() / 1000),
72 };
73 const base64Event = Buffer.from(JSON.stringify(testEvent, null, 2)).toString('base64');
74 const currentIdentity = this.#storage.getBrowserSessionHandler().browserSessionData?.identities.find(
75 i => i.id === this.#storage.getBrowserSessionHandler().browserSessionData?.selectedIdentityId
76 );
77 const nick = currentIdentity?.nick ?? 'Test Identity';
78
79 const width = 375;
80 const height = 600;
81 const left = Math.round((screen.width - width) / 2);
82 const top = Math.round((screen.height - height) / 2);
83
84 browser.windows.create({
85 type: 'popup',
86 url: `prompt.html?method=signEvent&host=example.com&id=test-${Date.now()}&nick=${encodeURIComponent(nick)}&event=${base64Event}`,
87 width,
88 height,
89 left,
90 top,
91 });
92 }
93
94 async onResetExtension() {
95 try {
96 this.#logger.logVaultReset();
97 await this.#storage.resetExtension();
98 this.#startup.startOver(getNewStorageServiceConfig());
99 } catch (error) {
100 console.log(error);
101 // TODO
102 }
103 }
104
105 async onChangePassword() {
106 if (!this.newPassword || this.changingPassword) return;
107 this.changingPassword = true;
108 this.passwordChanged = false;
109 try {
110 await this.#storage.changePassword(this.newPassword);
111 this.passwordChanged = true;
112 this.newPassword = '';
113 } catch (e) {
114 console.error('Change password failed:', e);
115 } finally {
116 this.changingPassword = false;
117 }
118 }
119
120 async onClickExportVault() {
121 const jsonVault = this.#storage.exportVault();
122
123 const dateTimeString = DateHelper.dateToISOLikeButLocal(new Date());
124 const fileName = `Smesh Signer Firefox - Vault Export - ${dateTimeString}.json`;
125
126 this.#downloadJson(jsonVault, fileName);
127 this.#logger.logVaultExport(fileName);
128 }
129
130 #downloadJson(jsonString: string, fileName: string) {
131 const dataStr =
132 'data:text/json;charset=utf-8,' + encodeURIComponent(jsonString);
133 const downloadAnchorNode = document.createElement('a');
134 downloadAnchorNode.setAttribute('href', dataStr);
135 downloadAnchorNode.setAttribute('download', fileName);
136 document.body.appendChild(downloadAnchorNode);
137 downloadAnchorNode.click();
138 downloadAnchorNode.remove();
139 }
140
141 async onClickLock() {
142 this.#logger.logVaultLock();
143 await this.#storage.lockVault();
144 this.#router.navigateByUrl('/vault-login');
145 }
146 }
147