From f02634b76d4ef2723b9c839cf051f4fe24cbe5a0 Mon Sep 17 00:00:00 2001 From: CI010 Date: Sat, 30 Dec 2023 19:45:19 +0800 Subject: [PATCH] fix: Should not re-scan the mods if the instance mounted --- xmcl-runtime/mod/InstanceModsService.ts | 55 +++++++++++++++++-------- 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/xmcl-runtime/mod/InstanceModsService.ts b/xmcl-runtime/mod/InstanceModsService.ts index 9e51ea526..52bf1e0b7 100644 --- a/xmcl-runtime/mod/InstanceModsService.ts +++ b/xmcl-runtime/mod/InstanceModsService.ts @@ -66,26 +66,35 @@ export class InstanceModsService extends AbstractService implements IInstanceMod const basePath = join(instancePath, 'mods') await ensureDir(basePath) await this.resourceService.whenReady(ResourceDomain.Mods) - state.mods = await scan(basePath) + const initializing = scan(basePath) + state.mods = await initializing + + const processUpdate = async (filePath: string) => { + const [resource] = await this.resourceService.importResources([{ path: filePath, domain: ResourceDomain.Mods }], true) + if (isModResource(resource)) { + this.log(`Instance mod add ${filePath}`) + } else { + this.warn(`Non mod resource added in /mods directory! ${filePath}`) + } + updateMod.push([resource, InstanceModUpdatePayloadAction.Upsert]) + } + + const processRemove = async (filePath: string) => { + const target = state.mods.find(r => r.path === filePath) + if (target) { + this.log(`Instance mod remove ${filePath}`) + updateMod.push([target, InstanceModUpdatePayloadAction.Remove]) + } else { + this.warn(`Cannot remove the mod ${filePath} as it's not found in memory cache!`) + } + } const watcher = watch(basePath, async (event, filePath) => { if (shouldIgnoreFile(filePath) || filePath === basePath) return if (event === 'update') { - const [resource] = await this.resourceService.importResources([{ path: filePath, domain: ResourceDomain.Mods }], true) - if (isModResource(resource)) { - this.log(`Instance mod add ${filePath}`) - } else { - this.warn(`Non mod resource added in /mods directory! ${filePath}`) - } - updateMod.push([resource, InstanceModUpdatePayloadAction.Upsert]) + processUpdate(filePath) } else { - const target = state.mods.find(r => r.path === filePath) - if (target) { - this.log(`Instance mod remove ${filePath}`) - updateMod.push([target, InstanceModUpdatePayloadAction.Remove]) - } else { - this.warn(`Cannot remove the mod ${filePath} as it's not found in memory cache!`) - } + processRemove(filePath) } }) @@ -101,12 +110,24 @@ export class InstanceModsService extends AbstractService implements IInstanceMod .removeListener('resourceUpdate', onResourceUpdate) }, async () => { // relvaidate + await initializing.catch(() => undefined) const files = await readdirIfPresent(basePath) - const expectFiles = files.filter((file) => !shouldIgnoreFile(file)) + const expectFiles = files.filter((file) => !shouldIgnoreFile(file)).map((file) => join(basePath, file)) const current = state.mods.length if (current !== expectFiles.length) { this.log(`Instance mods count mismatch: ${current} vs ${expectFiles.length}`) - state.mods = await scan(basePath) + // Find differences + const currentFiles = state.mods.map(r => r.path) + const added = expectFiles.filter(f => !currentFiles.includes(f)) + const removed = currentFiles.filter(f => !expectFiles.includes(f)) + if (added.length > 0) { + this.log(`Instance mods added: ${added.length}`) + added.map(f => join(basePath, f)).forEach(processUpdate) + } + if (removed.length > 0) { + this.log(`Instance mods removed: ${removed.length}`) + removed.map(f => join(basePath, f)).forEach(processRemove) + } } }] })