@@ -4,7 +4,7 @@ import { Asset } from "../types/asset.type";
44import { CardTemplate } from "../types/card-template.type" ;
55import { FieldType } from "../types/field-type.type" ;
66import { Deck } from "../types/deck.type" ;
7- import { exportDB , importDB } from "dexie-export-import" ;
7+ import { exportDB , importDB , importInto } from "dexie-export-import" ;
88import FileUtils from "src/app/shared/utils/file-utils" ;
99import { ExportProgress } from "dexie-export-import/dist/export" ;
1010import { ImportProgress } from "dexie-export-import/dist/import" ;
@@ -39,6 +39,7 @@ export class AppDB extends Dexie {
3939 private httpClient ;
4040 private changeSubject : Subject < any > ;
4141 private loadSubject : Subject < null > ;
42+ private isPopulating : boolean = false ;
4243
4344 constructor ( httpClient : HttpClient ,
4445 electronService : ElectronService ,
@@ -151,9 +152,10 @@ export class AppDB extends Dexie {
151152 . then ( count => {
152153 if ( ! electronService . isElectron ( ) && count > 0 ) {
153154 console . log ( 'db already populated' ) ;
155+ return Promise . resolve ( ) ;
154156 } else {
155157 console . log ( 'populate from file' ) ;
156- this . populateFromFile ( ) . then ( ( ) => {
158+ return this . populateFromFile ( ) . then ( ( ) => {
157159 // cause asset urls to update
158160 this . loadSubject . next ( null ) ;
159161 } ) ;
@@ -176,7 +178,9 @@ export class AppDB extends Dexie {
176178
177179 // Add hooks for granular dirty tracking
178180 const trackChange = ( tableName : string , type : string , key : any ) => {
179- this . changeSubject . next ( { tableName, type, key } ) ;
181+ if ( ! this . isPopulating ) {
182+ this . changeSubject . next ( { tableName, type, key } ) ;
183+ }
180184 } ;
181185
182186 // We need to wait for tables to be initialized or just access them via this.table()
@@ -211,15 +215,39 @@ export class AppDB extends Dexie {
211215
212216 }
213217
214- async populateFromFile ( ) {
215- const blob = await firstValueFrom ( this . httpClient . get ( AppDB . SAMPLE_DB_FILE , { responseType : 'blob' } ) ) ;
216- const file = new File ( [ blob ] , 'database.json' , { type : 'application/json' , lastModified : Date . now ( ) } ) ;
217- return importDB ( file , {
218- //noTransaction: true
219- } ) . then ( ( db ) => {
220- this . initializeData ( ) ;
221- return db ;
222- } ) ;
218+ async populateFromFile ( emitChange : boolean = true ) {
219+ // This is a destructive operation, but it's only called when the DB is effectively empty
220+ // or we fully intend to reset to the sample state.
221+ this . isPopulating = true ;
222+
223+ try {
224+ // 1. Fetch the sample file
225+ const blob = await firstValueFrom ( this . httpClient . get ( AppDB . SAMPLE_DB_FILE , { responseType : 'blob' } ) ) ;
226+ const file = new File ( [ blob ] , 'database.json' , { type : 'application/json' , lastModified : Date . now ( ) } ) ;
227+
228+ // 2. Import into the CURRENT existing database logic
229+ // We do NOT close or delete the DB. We just clear existing tables and import data.
230+ // options:
231+ // - clearTablesBeforeImport: true -> effectively a reset
232+ // - acceptVersionDiff: true -> ignores that the file might be v2 and the DB is v10
233+ // - overwriteValues: true -> ensures import wins
234+ await importInto ( this , file , {
235+ clearTablesBeforeImport : true ,
236+ acceptVersionDiff : true ,
237+ overwriteValues : true
238+ } ) ;
239+
240+ // 3. Notify that the database has been populated (refreshes UI/Sidebar)
241+ // We use a generic event so listeners know something changed.
242+ // We also wait a tick to ensure listeners are ready if this is part of initial load.
243+ if ( emitChange ) {
244+ this . changeSubject . next ( { tableName : 'all' , type : 'reset' , key : null } ) ;
245+ }
246+ } finally {
247+ this . isPopulating = false ;
248+ }
249+
250+ return this ;
223251 }
224252
225253 /**
@@ -264,11 +292,13 @@ export class AppDB extends Dexie {
264292 public async resetDatabase ( keepEmpty ?: boolean ) {
265293 this . close ( ) ;
266294 await this . delete ( ) ;
295+ await this . open ( ) ;
267296 if ( ! keepEmpty ) {
268- const tempDb = await this . populateFromFile ( ) ;
269- tempDb . close ( ) ;
297+ await this . populateFromFile ( false ) ;
298+ // Don't close here! populateFromFile leaves the DB open (via importInto),
299+ // and we want it to stay open for initializeData.
270300 }
271- await this . open ( ) . then ( ( ) => this . initializeData ( ) ) ;
301+ await this . initializeData ( ) ;
272302 this . changeSubject . next ( null ) ;
273303 return true ;
274304 }
0 commit comments