@@ -3,9 +3,12 @@ const SETTINGS_STORAGE_KEY = "ide-projet-personnel.settings";
33const USER_PROFILE_STORAGE_KEY = "ide-projet-personnel.user-profile" ;
44
55const PROJECTS_DB_NAME = "ide-projet-personnel" ;
6- const PROJECTS_DB_VERSION = 1 ;
6+ const PROJECTS_DB_VERSION = 2 ;
77const PROJECTS_STORE_NAME = "project_storage" ;
88const PROJECTS_RECORD_KEY = "projects" ;
9+ const APP_STORE_NAME = "app_storage" ;
10+ const SETTINGS_RECORD_KEY = "settings" ;
11+ const USER_PROFILE_RECORD_KEY = "user-profile" ;
912
1013let projectsDbPromise = null ;
1114
@@ -35,6 +38,9 @@ function openProjectsDb() {
3538 if ( ! db . objectStoreNames . contains ( PROJECTS_STORE_NAME ) ) {
3639 db . createObjectStore ( PROJECTS_STORE_NAME ) ;
3740 }
41+ if ( ! db . objectStoreNames . contains ( APP_STORE_NAME ) ) {
42+ db . createObjectStore ( APP_STORE_NAME ) ;
43+ }
3844 } ;
3945
4046 request . onsuccess = ( ) => resolve ( request . result ) ;
@@ -89,6 +95,51 @@ async function writeProjectsToIndexedDb(projects) {
8995 } ) ;
9096}
9197
98+ function runAppStore ( mode , action ) {
99+ return openProjectsDb ( ) . then (
100+ ( db ) =>
101+ new Promise ( ( resolve , reject ) => {
102+ const tx = db . transaction ( APP_STORE_NAME , mode ) ;
103+ const store = tx . objectStore ( APP_STORE_NAME ) ;
104+
105+ let settled = false ;
106+ const resolveOnce = ( value ) => {
107+ if ( settled ) return ;
108+ settled = true ;
109+ resolve ( value ) ;
110+ } ;
111+
112+ const rejectOnce = ( error ) => {
113+ if ( settled ) return ;
114+ settled = true ;
115+ reject ( error ) ;
116+ } ;
117+
118+ tx . oncomplete = ( ) => resolveOnce ( ) ;
119+ tx . onerror = ( ) => rejectOnce ( tx . error || new Error ( "IndexedDB transaction failed" ) ) ;
120+ tx . onabort = ( ) => rejectOnce ( tx . error || new Error ( "IndexedDB transaction aborted" ) ) ;
121+
122+ action ( store , resolveOnce , rejectOnce ) ;
123+ } )
124+ ) ;
125+ }
126+
127+ async function readAppValueFromIndexedDb ( recordKey ) {
128+ return runAppStore ( "readonly" , ( store , resolve , reject ) => {
129+ const request = store . get ( recordKey ) ;
130+ request . onsuccess = ( ) => resolve ( request . result ) ;
131+ request . onerror = ( ) => reject ( request . error || new Error ( "Failed to read app record" ) ) ;
132+ } ) ;
133+ }
134+
135+ async function writeAppValueToIndexedDb ( recordKey , value ) {
136+ await runAppStore ( "readwrite" , ( store , resolve , reject ) => {
137+ const request = store . put ( value , recordKey ) ;
138+ request . onsuccess = ( ) => resolve ( ) ;
139+ request . onerror = ( ) => reject ( request . error || new Error ( "Failed to write app record" ) ) ;
140+ } ) ;
141+ }
142+
92143export async function loadProjects ( ) {
93144 try {
94145 const indexedDbProjects = await readProjectsFromIndexedDb ( ) ;
@@ -118,8 +169,7 @@ export async function saveProjects(projects) {
118169 }
119170}
120171
121- export function loadSettings ( ) {
122- const raw = localStorage . getItem ( SETTINGS_STORAGE_KEY ) ;
172+ function parseJsonObject ( raw ) {
123173 if ( ! raw ) return null ;
124174
125175 try {
@@ -129,21 +179,60 @@ export function loadSettings() {
129179 }
130180}
131181
132- export function saveSettings ( settings ) {
133- localStorage . setItem ( SETTINGS_STORAGE_KEY , JSON . stringify ( settings ) ) ;
182+ export async function loadSettings ( ) {
183+ try {
184+ const indexedDbSettings = await readAppValueFromIndexedDb ( SETTINGS_RECORD_KEY ) ;
185+
186+ if ( indexedDbSettings && typeof indexedDbSettings === "object" ) {
187+ return indexedDbSettings ;
188+ }
189+
190+ const rawLegacySettings = localStorage . getItem ( SETTINGS_STORAGE_KEY ) ;
191+ const legacySettings = parseJsonObject ( rawLegacySettings ) ;
192+
193+ if ( rawLegacySettings !== null && legacySettings ) {
194+ await writeAppValueToIndexedDb ( SETTINGS_RECORD_KEY , legacySettings ) ;
195+ }
196+
197+ return legacySettings ;
198+ } catch {
199+ return parseJsonObject ( localStorage . getItem ( SETTINGS_STORAGE_KEY ) ) ;
200+ }
134201}
135202
136- export function loadUserProfile ( ) {
137- const raw = localStorage . getItem ( USER_PROFILE_STORAGE_KEY ) ;
138- if ( ! raw ) return null ;
203+ export async function saveSettings ( settings ) {
204+ try {
205+ await writeAppValueToIndexedDb ( SETTINGS_RECORD_KEY , settings ) ;
206+ } catch {
207+ localStorage . setItem ( SETTINGS_STORAGE_KEY , JSON . stringify ( settings ) ) ;
208+ }
209+ }
139210
211+ export async function loadUserProfile ( ) {
140212 try {
141- return JSON . parse ( raw ) ;
213+ const indexedDbUserProfile = await readAppValueFromIndexedDb ( USER_PROFILE_RECORD_KEY ) ;
214+
215+ if ( indexedDbUserProfile && typeof indexedDbUserProfile === "object" ) {
216+ return indexedDbUserProfile ;
217+ }
218+
219+ const rawLegacyUserProfile = localStorage . getItem ( USER_PROFILE_STORAGE_KEY ) ;
220+ const legacyUserProfile = parseJsonObject ( rawLegacyUserProfile ) ;
221+
222+ if ( rawLegacyUserProfile !== null && legacyUserProfile ) {
223+ await writeAppValueToIndexedDb ( USER_PROFILE_RECORD_KEY , legacyUserProfile ) ;
224+ }
225+
226+ return legacyUserProfile ;
142227 } catch {
143- return null ;
228+ return parseJsonObject ( localStorage . getItem ( USER_PROFILE_STORAGE_KEY ) ) ;
144229 }
145230}
146231
147- export function saveUserProfile ( profile ) {
148- localStorage . setItem ( USER_PROFILE_STORAGE_KEY , JSON . stringify ( profile ) ) ;
232+ export async function saveUserProfile ( profile ) {
233+ try {
234+ await writeAppValueToIndexedDb ( USER_PROFILE_RECORD_KEY , profile ) ;
235+ } catch {
236+ localStorage . setItem ( USER_PROFILE_STORAGE_KEY , JSON . stringify ( profile ) ) ;
237+ }
149238}
0 commit comments