mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2026-10-19 09:22:12 +00:00
explorer actions
This commit is contained in:
1 parent
adbf89e318
commit
3ef2bf135a
20 files changed
+1183
-65
No files matched your search
@@ -211,7 +211,7 @@ export async function createTauriBackend(): Promise<Backend> {
|
||||
desktop: {
|
||||
workspace: () => invoke<WorkspaceState>('workspace_state'),
|
||||
openFiles: () => invoke<Outcome>('open_files'),
|
||||
openPaths: (paths) => invoke<Outcome>('open_paths', { paths }),
|
||||
openPaths: (paths, preview) => invoke<Outcome>('open_paths', { paths, preview }),
|
||||
openFolder: (unsaved) => invoke<Outcome>('open_folder', { unsaved }),
|
||||
closeFolder: (unsaved) => invoke<Outcome>('close_folder', { unsaved }),
|
||||
closeFiles: (fileIds, unsaved) => invoke<Outcome>('close_files', { fileIds, unsaved }),
|
||||
@@ -222,6 +222,12 @@ export async function createTauriBackend(): Promise<Backend> {
|
||||
invoke<boolean>('export_files', { fileIds, options }),
|
||||
listFolder: (path) => invoke<FolderEntry[]>('list_folder', { path }),
|
||||
openUrl: (url) => invoke('open_url', { url }),
|
||||
newFile: (name, folder) => invoke<Outcome>('new_file', { name, folder }),
|
||||
createFolder: (parent, name) => invoke<string>('create_folder', { parent, name }),
|
||||
renamePath: (path, name) => invoke<Outcome>('rename_path', { path, name }),
|
||||
movePaths: (paths, folder) => invoke('move_paths', { paths, folder }),
|
||||
deletePaths: (paths) => invoke<Outcome>('delete_paths', { paths }),
|
||||
revealPath: (path) => invoke('reveal_path', { path }),
|
||||
listen: async (onEngineChanged, onWorkspaceChanged, onFilesOpened, onFolderChanged) => {
|
||||
await listen<Outcome>('files-opened', (event) => onFilesOpened(event.payload));
|
||||
await listen<Outcome>('engine-changed', (event) => onEngineChanged(event.payload));
|
||||
|
||||
@@ -30,6 +30,8 @@ export type FileStatus = {
|
||||
replaced: boolean;
|
||||
/** The file on the disk is gone. */
|
||||
missing: boolean;
|
||||
/** The file is open as a preview (a single click in the tree), which the next one replaces. */
|
||||
preview: boolean;
|
||||
};
|
||||
|
||||
/** An entry of the tree of the open folder: a folder, or a GPX file. */
|
||||
@@ -56,8 +58,12 @@ export interface DesktopFiles {
|
||||
workspace(): Promise<WorkspaceState>;
|
||||
/** Opens the files that the user picks, which get selected. */
|
||||
openFiles(): Promise<Outcome>;
|
||||
/** Opens files of the file system by their path, like the ones of the tree of the folder. */
|
||||
openPaths(paths: string[]): Promise<Outcome>;
|
||||
/**
|
||||
* Opens files of the file system by their path, like the ones of the tree of the folder. With
|
||||
* `preview`, a single file is open as a preview: the next preview replaces it, until it is
|
||||
* edited or opened for good. Otherwise they are open for good.
|
||||
*/
|
||||
openPaths(paths: string[], preview?: boolean): Promise<Outcome>;
|
||||
/**
|
||||
* Opens the folder that the user picks, which is watched. Its files are not opened: they are
|
||||
* in its tree (`listFolder`). The folder that was open is closed with its files (see
|
||||
@@ -91,6 +97,24 @@ export interface DesktopFiles {
|
||||
listFolder(path?: string): Promise<FolderEntry[]>;
|
||||
/** Opens a web page (or an email to write) in the app of the system for it. */
|
||||
openUrl(url: string): Promise<void>;
|
||||
/** Makes a new file, written at once in `folder` (a folder of the open folder), and selects it. */
|
||||
newFile(name: string, folder: string): Promise<Outcome>;
|
||||
/** Makes a folder in a folder of the open folder (numbered if the name is taken): its path. */
|
||||
createFolder(parent: string, name: string): Promise<string>;
|
||||
/**
|
||||
* Renames a file or a folder of the open folder. An open file is renamed like in its info (it
|
||||
* is selected), which can be undone.
|
||||
*/
|
||||
renamePath(path: string, name: string): Promise<Outcome>;
|
||||
/** Moves files and folders of the open folder into a folder of it. */
|
||||
movePaths(paths: string[], folder: string): Promise<void>;
|
||||
/**
|
||||
* Moves files and folders of the open folder to the trash. The open files among them are
|
||||
* closed, unless they have edits.
|
||||
*/
|
||||
deletePaths(paths: string[]): Promise<Outcome>;
|
||||
/** Shows a file or a folder in the file manager of the system. */
|
||||
revealPath(path: string): Promise<void>;
|
||||
/**
|
||||
* 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, when files were opened with the
|
||||
|
||||
@@ -562,9 +562,87 @@ class Engine {
|
||||
return this.addedBy((b) => b.desktop!.openFiles());
|
||||
}
|
||||
|
||||
/** Opens files of the file system by their path, which get selected. Resolves to the new ids. */
|
||||
async openPaths(paths: string[]): Promise<string[]> {
|
||||
return this.addedBy((b) => b.desktop!.openPaths(paths));
|
||||
/**
|
||||
* Opens files of the file system by their path, which get selected: as a preview with
|
||||
* `preview`, see `DesktopFiles.openPaths`. Resolves to the new ids.
|
||||
*/
|
||||
async openPaths(paths: string[], preview = false): Promise<string[]> {
|
||||
const added = await this.addedBy((b) => b.desktop!.openPaths(paths, preview));
|
||||
// which file is the preview may have changed, without a file changing
|
||||
await this.enqueue(async () => this.refreshWorkspace(this.backend!));
|
||||
return added;
|
||||
}
|
||||
|
||||
// What the explorer does to the tree of the open folder (the desktop app). When it fails,
|
||||
// `lastError` tells why (a key of the dictionaries, or a message).
|
||||
|
||||
/**
|
||||
* Makes a new file in a folder of the open folder, which is written there at once and selected.
|
||||
* Resolves to its id.
|
||||
*/
|
||||
async newFileIn(name: string, folder: string): Promise<string | undefined> {
|
||||
const [id] = await this.addedBy((b) => b.desktop!.newFile(name, folder));
|
||||
this._folderVersion.update((version) => version + 1);
|
||||
return id;
|
||||
}
|
||||
|
||||
/** Makes a folder in a folder of the open folder: resolves to its path. */
|
||||
async createFolder(parent: string, name: string): Promise<string | undefined> {
|
||||
return (await this.treeOperation((desktop) => desktop.createFolder(parent, name))).value;
|
||||
}
|
||||
|
||||
/** Renames a file or a folder of the open folder. Resolves to whether it was done. */
|
||||
async renamePath(path: string, name: string): Promise<boolean> {
|
||||
const changed = await this.run((b) => b.desktop!.renamePath(path, name));
|
||||
const failed = get(this._lastError) !== undefined;
|
||||
await this.treeOperation(async () => {});
|
||||
return changed || !failed;
|
||||
}
|
||||
|
||||
/** Moves files and folders of the open folder into a folder of it. */
|
||||
async movePaths(paths: string[], folder: string): Promise<boolean> {
|
||||
return (await this.treeOperation((desktop) => desktop.movePaths(paths, folder))).done;
|
||||
}
|
||||
|
||||
/** Moves files and folders of the open folder to the trash. */
|
||||
async deletePaths(paths: string[]): Promise<boolean> {
|
||||
const changed = await this.run((b) => b.desktop!.deletePaths(paths));
|
||||
const failed = get(this._lastError) !== undefined;
|
||||
await this.treeOperation(async () => {});
|
||||
return changed || !failed;
|
||||
}
|
||||
|
||||
/** Shows a file or a folder in the file manager of the system. */
|
||||
async revealPath(path: string) {
|
||||
await this.ready;
|
||||
try {
|
||||
await this.backend!.desktop?.revealPath(path);
|
||||
} catch (error) {
|
||||
console.error('engine:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does something to the file system, then reads where the files are and the tree again
|
||||
* (without waiting for the watcher). Resolves to whether it was done, with what it gives.
|
||||
*/
|
||||
private async treeOperation<T>(
|
||||
action: (desktop: DesktopFiles) => Promise<T>
|
||||
): Promise<{ done: boolean; value?: T }> {
|
||||
await this.ready;
|
||||
return this.enqueue(async () => {
|
||||
const backend = this.backend!;
|
||||
let result: { done: boolean; value?: T } = { done: false };
|
||||
try {
|
||||
result = { done: true, value: await action(backend.desktop!) };
|
||||
} catch (error) {
|
||||
console.error('engine:', error);
|
||||
this._lastError.set(String(error));
|
||||
}
|
||||
await this.refreshWorkspace(backend);
|
||||
this._folderVersion.update((version) => version + 1);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user