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