mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2026-10-19 09:22:12 +00:00
file explorer
This commit is contained in:
1 parent
b0a3c3a9ba
commit
ed90ba6a1f
14 files changed
+263
-19
No files matched your search
@@ -221,12 +221,13 @@ export async function createTauriBackend(): Promise<Backend> {
|
||||
exportFiles: (fileIds, options) =>
|
||||
invoke<boolean>('export_files', { fileIds, options }),
|
||||
listFolder: (path) => invoke<FolderEntry[]>('list_folder', { path }),
|
||||
listen: async (onEngineChanged, onWorkspaceChanged, onFilesOpened) => {
|
||||
listen: async (onEngineChanged, onWorkspaceChanged, onFilesOpened, onFolderChanged) => {
|
||||
await listen<Outcome>('files-opened', (event) => onFilesOpened(event.payload));
|
||||
await listen<Outcome>('engine-changed', (event) => onEngineChanged(event.payload));
|
||||
await listen<WorkspaceState>('workspace-changed', (event) =>
|
||||
onWorkspaceChanged(event.payload)
|
||||
);
|
||||
await listen<string[]>('folder-changed', () => onFolderChanged());
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
@@ -91,13 +91,15 @@ export interface DesktopFiles {
|
||||
listFolder(path?: string): Promise<FolderEntry[]>;
|
||||
/**
|
||||
* Tells when the engine changed without being asked, because the files on the disk did (the
|
||||
* outcome to apply), when the status of the files changed, and when files were opened with the
|
||||
* app from the system (the outcome to apply, which selected them).
|
||||
* outcome to apply), when the status of the files changed, when files were opened with the
|
||||
* app from the system (the outcome to apply, which selected them), and when something changed
|
||||
* in the open folder (the tree of its files is to be read again).
|
||||
*/
|
||||
listen(
|
||||
onEngineChanged: (outcome: Outcome) => void,
|
||||
onWorkspaceChanged: (workspace: WorkspaceState) => void,
|
||||
onFilesOpened: (outcome: Outcome) => void
|
||||
onFilesOpened: (outcome: Outcome) => void,
|
||||
onFolderChanged: () => void
|
||||
): Promise<void>;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ class Engine {
|
||||
private _lastError = writable<string | undefined>(undefined);
|
||||
private _outdated = writable(false);
|
||||
private _workspace = writable<WorkspaceState | undefined>(undefined);
|
||||
private _folderVersion = writable(0);
|
||||
private _canUndo = writable(false);
|
||||
private _canRedo = writable(false);
|
||||
private _canPaste = writable(false);
|
||||
@@ -86,6 +87,11 @@ class Engine {
|
||||
readonly workspace: Readable<WorkspaceState | undefined> = {
|
||||
subscribe: this._workspace.subscribe,
|
||||
};
|
||||
/**
|
||||
* A number that changes when something changed in the open folder on the file system, to read
|
||||
* its tree again.
|
||||
*/
|
||||
readonly folderVersion: Readable<number> = { subscribe: this._folderVersion.subscribe };
|
||||
/** Why the last call to the engine did nothing, `undefined` if it did something. */
|
||||
readonly lastError: Readable<string | undefined> = { subscribe: this._lastError.subscribe };
|
||||
/** What was copied or cut, waiting to be pasted. */
|
||||
@@ -689,7 +695,8 @@ class Engine {
|
||||
await this.sync(backend, outcome);
|
||||
this.report(outcome);
|
||||
this._opened.forEach((callback) => callback(outcome.added));
|
||||
})
|
||||
}),
|
||||
() => this._folderVersion.update((version) => version + 1)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { describe, it } from 'node:test';
|
||||
import { folderName, subfolder } from '$lib/engine/workspace';
|
||||
import { fileIdAt, folderName, subfolder } from '$lib/engine/workspace';
|
||||
|
||||
describe('subfolder', () => {
|
||||
it('is where a file is in the folder', () => {
|
||||
@@ -27,3 +27,23 @@ describe('folderName', () => {
|
||||
assert.equal(folderName('C:\\Users\\me\\tracks'), 'tracks');
|
||||
});
|
||||
});
|
||||
|
||||
describe('fileIdAt', () => {
|
||||
const workspace = {
|
||||
files: {
|
||||
a: { path: '/tracks/a.gpx' },
|
||||
b: { path: '/tracks/sub/b.gpx' },
|
||||
c: {},
|
||||
},
|
||||
};
|
||||
|
||||
it('is the open file that is linked to the path', () => {
|
||||
assert.equal(fileIdAt(workspace, '/tracks/a.gpx'), 'a');
|
||||
assert.equal(fileIdAt(workspace, '/tracks/sub/b.gpx'), 'b');
|
||||
});
|
||||
|
||||
it('is nothing for a file that is not open', () => {
|
||||
assert.equal(fileIdAt(workspace, '/tracks/other.gpx'), undefined);
|
||||
assert.equal(fileIdAt(undefined, '/tracks/a.gpx'), undefined);
|
||||
});
|
||||
});
|
||||
@@ -26,3 +26,11 @@ export function subfolder(
|
||||
}
|
||||
return file.slice(root.length, -1).join('/');
|
||||
}
|
||||
|
||||
/** The id of the open file that is linked to the file at `path`, `undefined` if there is none. */
|
||||
export function fileIdAt(
|
||||
workspace: { files: Record<string, { path?: string }> } | undefined,
|
||||
path: string
|
||||
): string | undefined {
|
||||
return Object.entries(workspace?.files ?? {}).find(([, file]) => file.path === path)?.[0];
|
||||
}
|
||||
Reference in new issue
Block a user