Implement File > Import and fix Ctrl+O to Open hotkey

Closes #671
This commit is contained in:
Keavon Chambers
2022-07-23 15:17:20 -07:00
parent 08a81002ff
commit f3bdf970f4
10 changed files with 54 additions and 31 deletions
@@ -255,7 +255,7 @@ export default defineComponent({
this.editor.instance.new_document_dialog();
},
openDocument() {
this.editor.instance.open_file_upload();
this.editor.instance.document_open();
},
},
components: {
+7 -3
View File
@@ -3,7 +3,7 @@ import { reactive, readonly } from "vue";
import { download, downloadBlob, upload } from "@/utility-functions/files";
import { Editor } from "@/wasm-communication/editor";
import { TriggerFileDownload, TriggerRasterDownload, FrontendDocumentDetails, TriggerFileUpload, UpdateActiveDocument, UpdateOpenDocumentsList } from "@/wasm-communication/messages";
import { TriggerFileDownload, TriggerRasterDownload, FrontendDocumentDetails, TriggerOpenDocument, TriggerImport, UpdateActiveDocument, UpdateOpenDocumentsList } from "@/wasm-communication/messages";
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function createPortfolioState(editor: Editor) {
@@ -22,11 +22,15 @@ export function createPortfolioState(editor: Editor) {
const activeId = state.documents.findIndex((doc) => doc.id === updateActiveDocument.document_id);
state.activeDocumentIndex = activeId;
});
editor.subscriptions.subscribeJsMessage(TriggerFileUpload, async () => {
editor.subscriptions.subscribeJsMessage(TriggerOpenDocument, async () => {
const extension = editor.instance.file_save_suffix();
const data = await upload(extension);
const data = await upload(extension, "text");
editor.instance.open_document_file(data.filename, data.content);
});
editor.subscriptions.subscribeJsMessage(TriggerImport, async () => {
const data = await upload("image/*", "data");
editor.instance.paste_image(data.type, Uint8Array.from(data.content));
});
editor.subscriptions.subscribeJsMessage(TriggerFileDownload, (triggerFileDownload) => {
download(triggerFileDownload.name, triggerFileDownload.document);
});
+10 -6
View File
@@ -18,22 +18,24 @@ export function download(filename: string, fileData: string): void {
URL.revokeObjectURL(url);
}
export async function upload(acceptedEextensions: string): Promise<{ filename: string; content: string }> {
return new Promise<{ filename: string; content: string }>((resolve, _) => {
export async function upload<T extends "text" | "data">(acceptedExtensions: string, textOrData: T): Promise<UploadResult<T>> {
return new Promise<UploadResult<T>>((resolve, _) => {
const element = document.createElement("input");
element.type = "file";
element.style.display = "none";
element.accept = acceptedEextensions;
element.accept = acceptedExtensions;
element.addEventListener(
"change",
async () => {
if (element.files?.length) {
const file = element.files[0];
const filename = file.name;
const content = await file.text();
resolve({ filename, content });
const filename = file.name;
const type = file.type;
const content = (textOrData === "text" ? await file.text() : new Uint8Array(await file.arrayBuffer())) as UploadResultType<T>;
resolve({ filename, type, content });
}
},
{ capture: false, once: true }
@@ -44,3 +46,5 @@ export async function upload(acceptedEextensions: string): Promise<{ filename: s
// Once `element` goes out of scope, it has no references so it gets garbage collected along with its event listener, so `removeEventListener` is not needed
});
}
export type UploadResult<T> = { filename: string; type: string; content: UploadResultType<T> };
type UploadResultType<T> = T extends "text" ? string : T extends "data" ? Uint8Array : never;
+16 -13
View File
@@ -206,7 +206,9 @@ export class TriggerFileDownload extends JsMessage {
readonly name!: string;
}
export class TriggerFileUpload extends JsMessage {}
export class TriggerOpenDocument extends JsMessage {}
export class TriggerImport extends JsMessage {}
export class TriggerPaste extends JsMessage {}
@@ -808,23 +810,22 @@ type MessageMaker = typeof JsMessage | JSMessageFactory;
export const messageMakers: Record<string, MessageMaker> = {
DisplayDialog,
DisplayDialogPanic,
UpdateDocumentLayerTreeStructure: newUpdateDocumentLayerTreeStructure,
DisplayEditableTextbox,
UpdateImageData,
DisplayRemoveEditableTextbox,
DisplayDialogDismiss,
DisplayDialogPanic,
DisplayEditableTextbox,
DisplayRemoveEditableTextbox,
TriggerAboutGraphiteLocalizedCommitDate,
TriggerOpenDocument,
TriggerFileDownload,
TriggerFileUpload,
TriggerIndexedDbRemoveDocument,
TriggerFontLoad,
TriggerImport,
TriggerIndexedDbRemoveDocument,
TriggerIndexedDbWriteDocument,
TriggerPaste,
TriggerRasterDownload,
TriggerRefreshBoundsOfViewports,
TriggerTextCommit,
TriggerTextCopy,
TriggerAboutGraphiteLocalizedCommitDate,
TriggerViewportResize,
TriggerVisitLink,
UpdateActiveDocument,
@@ -832,21 +833,23 @@ export const messageMakers: Record<string, MessageMaker> = {
UpdateDocumentArtboards,
UpdateDocumentArtwork,
UpdateDocumentBarLayout,
UpdateToolShelfLayout,
UpdateDocumentLayerDetails,
UpdateDocumentLayerTreeStructure: newUpdateDocumentLayerTreeStructure,
UpdateDocumentModeLayout,
UpdateDocumentOverlays,
UpdateDocumentRulers,
UpdateDocumentScrollbars,
UpdateImageData,
UpdateInputHints,
UpdateLayerTreeOptionsLayout,
UpdateMenuBarLayout,
UpdateMouseCursor,
UpdateNodeGraphVisibility,
UpdateOpenDocumentsList,
UpdatePropertyPanelOptionsLayout,
UpdatePropertyPanelSectionsLayout,
UpdateLayerTreeOptionsLayout,
UpdateDocumentModeLayout,
UpdateToolOptionsLayout,
UpdateToolShelfLayout,
UpdateWorkingColorsLayout,
UpdateMenuBarLayout,
} as const;
export type JsMessageType = keyof typeof messageMakers;