diff --git a/examples/register.ts b/examples/register.ts index 5ed00fbe..90c91f87 100644 --- a/examples/register.ts +++ b/examples/register.ts @@ -20,14 +20,15 @@ const handlers = { handleAdd, handleHydrate, handleDehydrate, handleChangeSize } const notify = { onTaskSuccess: async () => undefined, onTaskProcessing: async () => undefined }; const queueManager = new QueueManager(handlers, notify, settings.queuePersistPath); -drive.registerSyncRoot(settings.driveName, settings.driveVersion, settings.providerid, callbacks, settings.iconPath); -drive.connectSyncRoot(); - -try { - initInfoItems(); - drive.watchAndWait(settings.syncRootPath, queueManager, settings.watcherLogPath); -} catch (error) { - logger.error(error); - drive.disconnectSyncRoot(); - VirtualDrive.unregisterSyncRoot(settings.syncRootPath); -} +drive.registerSyncRoot(settings.driveName, settings.driveVersion, settings.providerid, callbacks, settings.iconPath).then(() => { + drive.connectSyncRoot(); + + try { + initInfoItems(); + drive.watchAndWait(settings.syncRootPath, queueManager, settings.watcherLogPath); + } catch (error) { + logger.error(error); + drive.disconnectSyncRoot(); + VirtualDrive.unregisterSyncRoot(settings.syncRootPath); + } +}); diff --git a/src/get-placeholder-states.ts b/src/get-placeholder-states.ts new file mode 100644 index 00000000..f34a66a0 --- /dev/null +++ b/src/get-placeholder-states.ts @@ -0,0 +1,30 @@ +import { readdir } from "fs/promises"; +import { join } from "path"; + +import { isFileInDevice } from "./is-file-in-device"; +import VirtualDrive from "./virtual-drive"; + +type TProps = { + self: VirtualDrive; + path: string; +}; + +export const getPlaceholderStates = async ({ self, path }: TProps) => { + const files = await readdir(path, { withFileTypes: true }); + + const promises = files.map(async (file) => { + const filePath = join(path, file.name); + + if (file.isDirectory()) { + return getPlaceholderStates({ self, path: filePath }); + } else { + const status = self.getPlaceholderState(filePath); + if (isFileInDevice(status)) { + const id = self.getFileIdentity(filePath); + self.watcher.fileInDevice.add(id); + } + } + }); + + await Promise.all(promises); +}; diff --git a/src/is-file-in-device.ts b/src/is-file-in-device.ts new file mode 100644 index 00000000..74bddaca --- /dev/null +++ b/src/is-file-in-device.ts @@ -0,0 +1,12 @@ +import { PinState, SyncState } from "./types/placeholder.type"; + +type TProps = { + syncState: SyncState; + pinState: PinState; +}; + +export const isFileInDevice = ({ syncState, pinState }: TProps) => { + const inSync = syncState === SyncState.InSync; + const isHydrated = pinState === PinState.AlwaysLocal || pinState === PinState.Unspecified; + return inSync && isHydrated; +}; diff --git a/src/virtual-drive.ts b/src/virtual-drive.ts index 02c7f9d3..aaa00790 100644 --- a/src/virtual-drive.ts +++ b/src/virtual-drive.ts @@ -6,6 +6,7 @@ import { IQueueManager } from "./queue/queueManager"; import { createLogger } from "./logger"; import { Addon } from "./addon-wrapper"; +import { getPlaceholderStates } from "./get-placeholder-states"; import winston from "winston"; const addon = new Addon(); @@ -154,7 +155,21 @@ class VirtualDrive { callbacks: Callbacks, logoPath: string ): Promise { - this.callbacks = callbacks; + this.callbacks = { + ...callbacks, + fetchDataCallback: (...args) => { + const id = args[0]; + this.watcher.fileInDevice.add(id); + return callbacks.fetchDataCallback?.(...args); + } + }; + + try { + await getPlaceholderStates({ self: this, path: this.syncRootPath}); + } catch (exc) { + this.logger.error("getPlaceholderStates", exc) + } + return addon.registerSyncRoot({ providerName, providerVersion, diff --git a/src/watcher/detect-context-menu-action.service.ts b/src/watcher/detect-context-menu-action.service.ts index 5a9c8e63..09376cfa 100644 --- a/src/watcher/detect-context-menu-action.service.ts +++ b/src/watcher/detect-context-menu-action.service.ts @@ -11,7 +11,7 @@ export class DetectContextMenuActionService { const status = self.addon.getPlaceholderState({ path }); const itemId = self.addon.getFileIdentity({ path }); - const isInDevice = self.fileInDevice.has(path); + const isInDevice = self.fileInDevice.has(itemId) || self.fileInDevice.has(path); self.logger.info({ event: "change", @@ -31,48 +31,27 @@ export class DetectContextMenuActionService { }, }); - if ( - prev.size === curr.size && - prev.ctimeMs !== curr.ctimeMs && - prev.mtimeMs === curr.mtimeMs && - status.pinState === PinState.AlwaysLocal && - status.syncState === SyncState.InSync && - !isInDevice - ) { - self.fileInDevice.add(path); - - if (curr.blocks !== 0) { - // This event is triggered from the addon - return "Doble click en el archivo"; - } - - self.queueManager.enqueue({ path, type: typeQueue.hydrate, isFolder, fileId: itemId }); - return "Mantener siempre en el dispositivo"; - } - - if ( - prev.size === curr.size && - prev.ctimeMs !== curr.ctimeMs && - status.pinState == PinState.OnlineOnly && - status.syncState == SyncState.InSync - ) { - // TODO: we need to disable this for now even if dehydate it's called two times - // because files that are a .zip have blocks === 0, so they never dehydrate - // because it's seems that it's already been dehydrated - // if (curr.blocks === 0) { - // return "Liberando espacio"; - // } - - self.fileInDevice.delete(path); - self.queueManager.enqueue({ path, type: typeQueue.dehydrate, isFolder, fileId: itemId }); - return "Liberar espacio"; - } - + // TODO: check same size but different content if (prev.size !== curr.size) { self.queueManager.enqueue({ path, type: typeQueue.changeSize, isFolder, fileId: itemId }); - self.fileInDevice.add(path); + self.fileInDevice.add(itemId); return "Cambio de tamaƱo"; } + + if (prev.ctimeMs !== curr.ctimeMs && status.syncState === SyncState.InSync) { + if (status.pinState === PinState.AlwaysLocal && !isInDevice) { + self.fileInDevice.add(itemId); + self.queueManager.enqueue({ path, type: typeQueue.hydrate, isFolder, fileId: itemId }); + return "Mantener siempre en el dispositivo"; + } + + if (status.pinState == PinState.OnlineOnly && isInDevice) { + self.fileInDevice.delete(path); + self.fileInDevice.delete(itemId); + self.queueManager.enqueue({ path, type: typeQueue.dehydrate, isFolder, fileId: itemId }); + return "Liberar espacio"; + } + } } }