@@ -6,10 +6,27 @@ import { LocalStorageWithSchema } from "../utils/local-storage-with-schema";
66import { z } from "zod" ;
77import { CompletedEventCustomTextSchema } from "@monkeytype/contracts/schemas/results" ;
88import { deepClone } from "../utils/misc" ;
9+ import { DBSchema , IDBPDatabase , openDB } from "idb" ;
910
11+ type CustomTextDB = DBSchema & {
12+ customTexts : {
13+ key : string ;
14+ value : {
15+ text : string ;
16+ } ;
17+ } ;
18+ customLongTexts : {
19+ key : string ;
20+ value : {
21+ text : string ;
22+ progress : number ;
23+ } ;
24+ } ;
25+ } ;
26+
27+ //Legacy storage
1028const CustomTextObjectSchema = z . record ( z . string ( ) , z . string ( ) ) ;
1129type CustomTextObject = z . infer < typeof CustomTextObjectSchema > ;
12-
1330const CustomTextLongObjectSchema = z . record (
1431 z . string ( ) ,
1532 z . object ( { text : z . string ( ) , progress : z . number ( ) } )
@@ -21,13 +38,53 @@ const customTextLS = new LocalStorageWithSchema({
2138 schema : CustomTextObjectSchema ,
2239 fallback : { } ,
2340} ) ;
41+
2442//todo maybe add migrations here?
2543const customTextLongLS = new LocalStorageWithSchema ( {
2644 key : "customTextLong" ,
2745 schema : CustomTextLongObjectSchema ,
2846 fallback : { } ,
2947} ) ;
3048
49+ export async function getDB ( ) : Promise < IDBPDatabase < CustomTextDB > > {
50+ return await openDB < CustomTextDB > ( "customTexts" , 1 , {
51+ async upgrade ( db , oldVersion , _newVersion , tx , _event ) {
52+ if ( oldVersion === 0 ) {
53+ console . debug ( "Initialize indexedDB for customTexts from localStorage" ) ;
54+
55+ //create objectStores
56+ await db . createObjectStore ( "customTexts" ) ;
57+ await db . createObjectStore ( "customLongTexts" ) ;
58+
59+ const ctStore = tx . objectStore ( "customTexts" ) ;
60+ const longCtStore = tx . objectStore ( "customLongTexts" ) ;
61+
62+ //copy from old localStorage
63+ await Promise . all ( [
64+ ...Object . entries ( customTextLS . get ( ) ) . map ( async ( [ key , value ] ) =>
65+ ctStore . add ( { text : value } , key )
66+ ) ,
67+ ...Object . entries ( customTextLongLS . get ( ) ) . map ( async ( [ key , value ] ) =>
68+ longCtStore . add ( { text : value . text , progress : value . progress } , key )
69+ ) ,
70+ tx . done ,
71+ ] ) ;
72+
73+ console . debug ( "Remove localStorage after migration" ) ;
74+ //TODO:
75+ //customTextLS.destroy();
76+ //customTextLongLS.destroy();
77+ }
78+ } ,
79+ } ) ;
80+ }
81+
82+ window . globalThis [ "db" ] = {
83+ get : getDB ,
84+ getText : getCustomText ,
85+ setText : setCustomText ,
86+ } ;
87+
3188export const CustomTextSettingsSchema = CompletedEventCustomTextSchema . omit ( {
3289 textLen : true ,
3390} ) . extend ( {
@@ -140,56 +197,38 @@ export function getData(): CustomTextSettings {
140197 return customTextSettings . get ( ) ;
141198}
142199
143- export function getCustomText ( name : string , long = false ) : string [ ] {
144- if ( long ) {
145- const customTextLong = getLocalStorageLong ( ) ;
146- const customText = customTextLong [ name ] ;
147- if ( customText === undefined )
148- throw new Error ( `Custom text ${ name } not found` ) ;
149- return customText . text . split ( / + / ) ;
150- } else {
151- const customText = getLocalStorage ( ) [ name ] ;
152- if ( customText === undefined )
153- throw new Error ( `Custom text ${ name } not found` ) ;
154- return customText . split ( / + / ) ;
155- }
200+ export async function getCustomText (
201+ name : string ,
202+ long = false
203+ ) : Promise < string [ ] > {
204+ const db = await getDB ( ) ;
205+ const customText = await db . get (
206+ long ? "customLongTexts" : "customTexts" ,
207+ name
208+ ) ;
209+ if ( customText === undefined )
210+ throw new Error ( `Custom text ${ name } not found` ) ;
211+
212+ return customText . text . split ( / + / ) ;
156213}
157214
158- export function setCustomText (
215+ export async function setCustomText (
159216 name : string ,
160217 text : string | string [ ] ,
161218 long = false
162- ) : boolean {
163- if ( long ) {
164- const customText = getLocalStorageLong ( ) ;
165-
166- customText [ name ] = {
167- text : "" ,
168- progress : 0 ,
169- } ;
170-
171- const textByName = customText [ name ] ;
172- if ( textByName === undefined ) {
173- throw new Error ( "Custom text not found" ) ;
174- }
175-
176- if ( typeof text === "string" ) {
177- textByName . text = text ;
219+ ) : Promise < boolean > {
220+ const db = await getDB ( ) ;
221+ const textToStore = typeof text === "string" ? text : text . join ( " " ) ;
222+ try {
223+ if ( long ) {
224+ await db . put ( "customLongTexts" , { text : textToStore , progress : 0 } , name ) ;
178225 } else {
179- textByName . text = text . join ( " " ) ;
226+ await db . put ( "customTexts" , { text : textToStore } , name ) ;
180227 }
181-
182- return setLocalStorageLong ( customText ) ;
183- } else {
184- const customText = getLocalStorage ( ) ;
185-
186- if ( typeof text === "string" ) {
187- customText [ name ] = text ;
188- } else {
189- customText [ name ] = text . join ( " " ) ;
190- }
191-
192- return setLocalStorage ( customText ) ;
228+ return true ;
229+ } catch ( e ) {
230+ console . debug ( "Storing to indexedDb failed: " , e ) ;
231+ return false ;
193232 }
194233}
195234
0 commit comments