11<script lang =" ts" >
22 import { fly } from ' svelte/transition' ;
3- import type { StorageProvider } from " ../../types" ;
4- import { getMessage } from ' ../../utils' ;
3+ import type { StorageProvider } from ' ../../types' ;
4+ import { base64EncodeIcon , getMessage , isFirefox } from " ../../utils" ;
55 import { options } from ' ../stores/options-store' ;
66
77 export let index: number ;
88 export let provider: StorageProvider ;
9+
10+ let errorMsg: string | null = null ;
11+
12+ const hideAlert = () => {
13+ errorMsg = null ;
14+ }
15+
16+ const getIcon = (icon : string ) => {
17+ if (icon .startsWith (' icons/' )) {
18+ return chrome .runtime .getURL (icon );
19+ }
20+ return icon ;
21+ }
22+
23+ $ : iconUrl = getIcon (provider .icon );
24+
25+ const uploadIcon = () => {
26+ if (isFirefox ) {
27+ errorMsg = getMessage (" msgIconUploadNotSupported" );
28+ return ;
29+ }
30+
31+ const fileInput = document .createElement (' input' );
32+ fileInput .type = ' file' ;
33+ fileInput .accept = ' image/*' ;
34+
35+ fileInput .addEventListener (' change' , () => {
36+ if (! fileInput .files || fileInput .files .length === 0 ) {
37+ return ;
38+ }
39+ errorMsg = null ;
40+
41+ const file = fileInput .files [0 ];
42+ if (! file .type .startsWith (' image/' )) {
43+ errorMsg = getMessage (' msgIconUploadNotImage' );
44+ return ;
45+ }
46+
47+ const tmpImg = new Image ();
48+
49+ tmpImg .addEventListener (' error' , () => {
50+ errorMsg = getMessage (' msgIconUploadNotImage' );
51+ });
52+
53+ tmpImg .addEventListener (' load' , () => {
54+ if (tmpImg .naturalHeight !== tmpImg .naturalWidth ) {
55+ errorMsg = getMessage (' msgIconUploadNotSquareImage' );
56+ return ;
57+ }
58+
59+ const canvas = document .createElement (' canvas' );
60+ canvas .width = 24 ;
61+ canvas .height = 24 ;
62+
63+ const ctx = canvas .getContext (' 2d' );
64+ if (! ctx ) {
65+ errorMsg = getMessage (' msgIconUploadNotImage' );
66+ return ;
67+ }
68+ ctx .drawImage (tmpImg , 0 , 0 , 24 , 24 );
69+
70+ provider .icon = base64EncodeIcon (ctx );
71+ });
72+
73+ tmpImg .src = URL .createObjectURL (file );
74+ });
75+
76+ fileInput .click ();
77+ }
78+
979 </script >
1080
1181
31101 />
32102 </div >
33103 <div class =" input-group-text" >
34- <img alt ="Icon" width ="24" height ="24" src ={` ../${ provider . icon } ` } />
104+ <img class = "pointer" alt ="Icon" width ="24" height ="24" src ={iconUrl } on:click ={ uploadIcon } />
35105 </div >
36106 <input
37107 class =" form-control"
59129 >❌
60130 </button >
61131</fieldset >
132+
133+ {#if errorMsg !== null }
134+ <div class =" row mt-3" transition:fly >
135+ <div class =" col" >
136+ <div
137+ class =" alert alert-danger alert-dismissible"
138+ role =" alert"
139+ >
140+ {errorMsg }
141+ <button
142+ type =" button"
143+ class =" btn-close"
144+ data-bs-dismiss =" alert"
145+ aria-label =" Close"
146+ on:click ={hideAlert }
147+ >
148+ </button >
149+ </div >
150+ </div >
151+ </div >
152+ {/if }
0 commit comments