diff --git a/packages/core/src/features/virtual-drive/folder/index.ts b/packages/core/src/features/virtual-drive/folder/index.ts index a70c8df5b..326d4586f 100644 --- a/packages/core/src/features/virtual-drive/folder/index.ts +++ b/packages/core/src/features/virtual-drive/folder/index.ts @@ -1,2 +1,3 @@ export * from "./virtualFolder"; -export * from "./virtualFolderLink"; \ No newline at end of file +export * from "./virtualFolderLink"; +export * from "./virtualLazyFolder"; \ No newline at end of file diff --git a/packages/core/src/features/virtual-drive/folder/virtualFolder.ts b/packages/core/src/features/virtual-drive/folder/virtualFolder.ts index ba87caa19..691ac98f8 100644 --- a/packages/core/src/features/virtual-drive/folder/virtualFolder.ts +++ b/packages/core/src/features/virtual-drive/folder/virtualFolder.ts @@ -370,6 +370,10 @@ export class VirtualFolder exte this.confirmChanges(); } + async loadContent(): Promise { + return Promise.resolve() + } + /** * Returns all files inside this folder. * @param showHidden - Whether to include hidden files. @@ -383,6 +387,11 @@ export class VirtualFolder exte ); } + async getFilesAsync(showHidden = false): Promise { + await this.loadContent(); + return this.getFiles(showHidden); + } + /** * Returns all sub-folders inside this folder. * @param showHidden - Whether to include hidden folders. @@ -396,6 +405,11 @@ export class VirtualFolder exte ); } + async getSubFoldersAsync(showHidden = false): Promise { + await this.loadContent(); + return this.getSubFolders(showHidden); + } + /** * Returns the amount of files and sub-folders inside this folder. * @param includeHidden - Whether to include hidden files and folders in the count. diff --git a/packages/core/src/features/virtual-drive/folder/virtualLazyFolder.ts b/packages/core/src/features/virtual-drive/folder/virtualLazyFolder.ts new file mode 100644 index 000000000..852320241 --- /dev/null +++ b/packages/core/src/features/virtual-drive/folder/virtualLazyFolder.ts @@ -0,0 +1,43 @@ +import { VirtualBase, VirtualBaseEvents } from "../virtualBase"; +import { VirtualFile } from "../file"; +import { VirtualFolder } from "./virtualFolder"; + +export class VirtualLazyFolder extends VirtualFolder { + private hasPopulated = false; + private content: Promise = Promise.resolve() + + constructor(name: string, type?: number) { + super(name, type); + } + + /** + * Override this method to populate the folder with files and sub-folders. + * Called once, the first time the folder's contents are requested. + */ + onPopulate(): Promise { + return Promise.resolve(); + } + + loadContent(): Promise { + if (this.hasPopulated) { + return this.content + } + + this.hasPopulated = true + this.content = this.onPopulate().then(() => { + this.emit(VirtualBase.UPDATE_EVENT); + }); + + return this.content + } + + getFiles(showHidden = false): VirtualFile[] { + this.loadContent(); + return super.getFiles(showHidden); + } + + getSubFolders(showHidden = false): VirtualFolder[] { + this.loadContent(); + return super.getSubFolders(showHidden); + } +} \ No newline at end of file diff --git a/packages/core/test/features/virtual-drive/virtualDrive.utils.ts b/packages/core/test/features/virtual-drive/virtualDrive.utils.ts index 208ddbdc9..e1c1c5f16 100644 --- a/packages/core/test/features/virtual-drive/virtualDrive.utils.ts +++ b/packages/core/test/features/virtual-drive/virtualDrive.utils.ts @@ -1,4 +1,4 @@ -import { SystemManager, VirtualBase, VirtualFile, VirtualFolder, VirtualRoot } from "../../../src/features"; +import { SystemManager, VirtualBase, VirtualFile, VirtualFolder, VirtualRoot, VirtualLazyFolder } from "../../../src/features"; export class MockVirtualFile extends VirtualFile { @@ -31,4 +31,28 @@ export class MockVirtualRoot extends VirtualRoot { this.init(); } +} + +export class MockVirtualLazyFolder extends VirtualLazyFolder { + private resolve!: () => void; + readonly populated: Promise; + private onPopulateCallback: (Folder: MockVirtualLazyFolder) => void + + constructor(name: string, onPopulateCallback: (Folder: MockVirtualLazyFolder) => void = () => {}) { + super(name); + this.onPopulateCallback = onPopulateCallback + this.populated = new Promise((resolve) => { + this.resolve = resolve; + }); + } + + override onPopulate(): Promise { + return this.populated.then(() =>{ + this.onPopulateCallback(this) + }) + } + + completePopulation() { + this.resolve(); + } } \ No newline at end of file diff --git a/packages/core/test/features/virtual-drive/virtualLazyFolder.test.ts b/packages/core/test/features/virtual-drive/virtualLazyFolder.test.ts new file mode 100644 index 000000000..800ab2cbb --- /dev/null +++ b/packages/core/test/features/virtual-drive/virtualLazyFolder.test.ts @@ -0,0 +1,30 @@ +import { test as base, expect } from "vitest"; +import { extend } from "@prozilla-os/dev-tools"; +import { VirtualLazyFolder } from "../../../dist/main"; +import { MockVirtualFile, MockVirtualLazyFolder } from "./virtualDrive.utils"; +import { beforeEach } from "vitest"; + +const test = extend(base) + +let mockVirtualLazyFolder: MockVirtualLazyFolder; + +beforeEach(() => { + mockVirtualLazyFolder = new MockVirtualLazyFolder("foo", (f) => { + f.addFile(new MockVirtualFile("test", "txt")); + }); +}); + +test("getFilesAsync()", async () => { + const mockFilesPromise = mockVirtualLazyFolder.getFilesAsync(); + expect(mockVirtualLazyFolder.getFiles()).toStrictEqual([]); + + mockVirtualLazyFolder.completePopulation(); + const mockFiles = await mockFilesPromise; + expect(mockFiles).toHaveLength(1) +}); + +test("onPopulate", async () => { + const mockPromise1 = mockVirtualLazyFolder.loadContent() + const mockPromise2 = mockVirtualLazyFolder.loadContent() + expect(mockPromise1).toBe(mockPromise2); +}); \ No newline at end of file