mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Implement closing the current, and all, documents from the menu bar (#265)
Closes #261 Additional cleanup and refactoring with the way the backend relays the list of open documents to the frontend and prompts for confirmation.
This commit is contained in:
@@ -83,8 +83,8 @@ const menuEntries: MenuListEntries = [
|
||||
},
|
||||
],
|
||||
[
|
||||
{ label: "Close", shortcut: ["Ctrl", "W"] },
|
||||
{ label: "Close All", shortcut: ["Ctrl", "Alt", "W"] },
|
||||
{ label: "Close", shortcut: ["Ctrl", "W"], action: async () => (await wasm).close_active_document_with_confirmation() },
|
||||
{ label: "Close All", shortcut: ["Ctrl", "Alt", "W"], action: async () => (await wasm).close_all_documents_with_confirmation() },
|
||||
],
|
||||
[
|
||||
{ label: "Save", shortcut: ["Ctrl", "S"] },
|
||||
@@ -154,6 +154,7 @@ export default defineComponent({
|
||||
window.open("https://www.graphite.design", "_blank");
|
||||
},
|
||||
actionNotImplemented() {
|
||||
// eslint-disable-next-line no-alert
|
||||
alert("This action is not yet implemented");
|
||||
},
|
||||
},
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
:class="{ active: tabIndex === tabActiveIndex }"
|
||||
v-for="(tabLabel, tabIndex) in tabLabels"
|
||||
:key="tabLabel"
|
||||
@click.middle="closeTab(tabIndex)"
|
||||
@click.middle="handleTabClose(tabIndex)"
|
||||
@click="handleTabClick(tabIndex)"
|
||||
>
|
||||
<span>{{ tabLabel }}</span>
|
||||
<IconButton :icon="'CloseX'" :size="16" v-if="tabCloseButtons" @click.stop="closeTab(tabIndex)" />
|
||||
<IconButton :icon="'CloseX'" :size="16" v-if="tabCloseButtons" @click.stop="handleTabClose(tabIndex)" />
|
||||
</div>
|
||||
</div>
|
||||
<PopoverButton :icon="PopoverButtonIcon.VerticalEllipsis">
|
||||
@@ -150,7 +150,7 @@ import Minimap from "../panels/Minimap.vue";
|
||||
import IconButton from "../widgets/buttons/IconButton.vue";
|
||||
import PopoverButton, { PopoverButtonIcon } from "../widgets/buttons/PopoverButton.vue";
|
||||
import { MenuDirection } from "../widgets/floating-menus/FloatingMenu.vue";
|
||||
import { ResponseType, registerResponseHandler, Response } from "../../utilities/response-handler";
|
||||
import { ResponseType, registerResponseHandler, Response, PromptConfirmationToCloseDocument } from "../../utilities/response-handler";
|
||||
|
||||
const wasm = import("../../../wasm/pkg");
|
||||
|
||||
@@ -164,24 +164,37 @@ export default defineComponent({
|
||||
PopoverButton,
|
||||
},
|
||||
methods: {
|
||||
async handleTabClick(tabIndex: number) {
|
||||
if (this.panelType !== "Document") return;
|
||||
|
||||
handleTabClick(tabIndex: number) {
|
||||
if (this.panelType === "Document") this.selectDocument(tabIndex);
|
||||
},
|
||||
handleTabClose(tabIndex: number) {
|
||||
if (this.panelType === "Document") this.closeDocumentWithConfirmation(tabIndex);
|
||||
},
|
||||
async selectDocument(tabIndex: number) {
|
||||
const { select_document } = await wasm;
|
||||
select_document(tabIndex);
|
||||
},
|
||||
async closeTab(tabIndex: number) {
|
||||
if (this.panelType !== "Document") return;
|
||||
|
||||
const { close_document } = await wasm;
|
||||
async closeDocumentWithConfirmation(tabIndex: number) {
|
||||
// eslint-disable-next-line no-alert
|
||||
const result = window.confirm("Closing this document will permanently discard all work. Continue?");
|
||||
if (result) close_document(tabIndex);
|
||||
const userConfirmation = window.confirm("Closing this document will permanently discard all work. Continue?");
|
||||
if (userConfirmation) (await wasm).close_document(tabIndex);
|
||||
},
|
||||
async closeAllDocumentsWithConfirmation() {
|
||||
// eslint-disable-next-line no-alert
|
||||
const userConfirmation = window.confirm("Closing all documents will permanently discard all work in each of them. Continue?");
|
||||
if (userConfirmation) (await wasm).close_all_documents();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
registerResponseHandler(ResponseType.PromptCloseConfirmationModal, (_responseData: Response) => {
|
||||
this.closeTab(this.tabActiveIndex);
|
||||
// TODO: Move these somewhere more appropriate to act upon all panels
|
||||
|
||||
registerResponseHandler(ResponseType.PromptConfirmationToCloseDocument, (responseData: Response) => {
|
||||
const promptData = responseData as PromptConfirmationToCloseDocument;
|
||||
this.closeDocumentWithConfirmation(promptData.document_index);
|
||||
});
|
||||
|
||||
registerResponseHandler(ResponseType.PromptConfirmationToCloseAllDocuments, (_responseData: Response) => {
|
||||
this.closeAllDocumentsWithConfirmation();
|
||||
});
|
||||
},
|
||||
props: {
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
import { ResponseType, registerResponseHandler, Response, SetActiveDocument, NewDocument, CloseDocument } from "../../utilities/response-handler";
|
||||
import { ResponseType, registerResponseHandler, Response, SetActiveDocument, UpdateOpenDocumentsList } from "../../utilities/response-handler";
|
||||
import LayoutRow from "../layout/LayoutRow.vue";
|
||||
import LayoutCol from "../layout/LayoutCol.vue";
|
||||
import Panel from "./Panel.vue";
|
||||
@@ -59,15 +59,10 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
mounted() {
|
||||
registerResponseHandler(ResponseType.NewDocument, (responseData: Response) => {
|
||||
const documentData = responseData as NewDocument;
|
||||
if (documentData) this.documents.push(documentData.document_name);
|
||||
});
|
||||
|
||||
registerResponseHandler(ResponseType.CloseDocument, (responseData: Response) => {
|
||||
const documentData = responseData as CloseDocument;
|
||||
if (documentData) {
|
||||
this.documents.splice(documentData.document_index, 1);
|
||||
registerResponseHandler(ResponseType.UpdateOpenDocumentsList, (responseData: Response) => {
|
||||
const documentListData = responseData as UpdateOpenDocumentsList;
|
||||
if (documentListData) {
|
||||
this.documents = documentListData.open_documents;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -80,7 +75,7 @@ export default defineComponent({
|
||||
data() {
|
||||
return {
|
||||
activeDocument: 0,
|
||||
documents: ["Untitled Document"],
|
||||
documents: ["Untitled Document"], // TODO: start as an empty list
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -18,12 +18,12 @@ export enum ResponseType {
|
||||
CollapseFolder = "CollapseFolder",
|
||||
SetActiveTool = "SetActiveTool",
|
||||
SetActiveDocument = "SetActiveDocument",
|
||||
NewDocument = "NewDocument",
|
||||
CloseDocument = "CloseDocument",
|
||||
UpdateOpenDocumentsList = "UpdateOpenDocumentsList",
|
||||
UpdateWorkingColors = "UpdateWorkingColors",
|
||||
PromptCloseConfirmationModal = "PromptCloseConfirmationModal",
|
||||
SetCanvasZoom = "SetCanvasZoom",
|
||||
SetRotation = "SetRotation",
|
||||
PromptConfirmationToCloseDocument = "PromptConfirmationToCloseDocument",
|
||||
PromptConfirmationToCloseAllDocuments = "PromptConfirmationToCloseAllDocuments",
|
||||
}
|
||||
|
||||
export function registerResponseHandler(responseType: ResponseType, callback: ResponseCallback) {
|
||||
@@ -57,10 +57,8 @@ function parseResponse(responseType: string, data: any): Response {
|
||||
return newSetActiveTool(data.SetActiveTool);
|
||||
case "SetActiveDocument":
|
||||
return newSetActiveDocument(data.SetActiveDocument);
|
||||
case "NewDocument":
|
||||
return newNewDocument(data.NewDocument);
|
||||
case "CloseDocument":
|
||||
return newCloseDocument(data.CloseDocument);
|
||||
case "UpdateOpenDocumentsList":
|
||||
return newUpdateOpenDocumentsList(data.UpdateOpenDocumentsList);
|
||||
case "UpdateCanvas":
|
||||
return newUpdateCanvas(data.UpdateCanvas);
|
||||
case "SetCanvasZoom":
|
||||
@@ -71,8 +69,10 @@ function parseResponse(responseType: string, data: any): Response {
|
||||
return newExportDocument(data.ExportDocument);
|
||||
case "UpdateWorkingColors":
|
||||
return newUpdateWorkingColors(data.UpdateWorkingColors);
|
||||
case "PromptCloseConfirmationModal":
|
||||
return {};
|
||||
case "PromptConfirmationToCloseDocument":
|
||||
return newPromptConfirmationToCloseDocument(data.PromptConfirmationToCloseDocument);
|
||||
case "PromptConfirmationToCloseAllDocuments":
|
||||
return newPromptConfirmationToCloseAllDocuments(data.PromptConfirmationToCloseAllDocuments);
|
||||
default:
|
||||
throw new Error(`Unrecognized origin/responseType pair: ${origin}, '${responseType}'`);
|
||||
}
|
||||
@@ -80,11 +80,11 @@ function parseResponse(responseType: string, data: any): Response {
|
||||
|
||||
export type Response = SetActiveTool | UpdateCanvas | DocumentChanged | CollapseFolder | ExpandFolder | UpdateWorkingColors | SetCanvasZoom | SetRotation;
|
||||
|
||||
export interface CloseDocument {
|
||||
document_index: number;
|
||||
export interface UpdateOpenDocumentsList {
|
||||
open_documents: Array<string>;
|
||||
}
|
||||
function newCloseDocument(input: any): CloseDocument {
|
||||
return { document_index: input.document_index };
|
||||
function newUpdateOpenDocumentsList(input: any): UpdateOpenDocumentsList {
|
||||
return { open_documents: input.open_documents };
|
||||
}
|
||||
|
||||
export interface Color {
|
||||
@@ -127,15 +127,19 @@ function newSetActiveDocument(input: any): SetActiveDocument {
|
||||
};
|
||||
}
|
||||
|
||||
export interface NewDocument {
|
||||
document_name: string;
|
||||
export interface PromptConfirmationToCloseDocument {
|
||||
document_index: number;
|
||||
}
|
||||
function newNewDocument(input: any): NewDocument {
|
||||
function newPromptConfirmationToCloseDocument(input: any): PromptConfirmationToCloseDocument {
|
||||
return {
|
||||
document_name: input.document_name,
|
||||
document_index: input.document_index,
|
||||
};
|
||||
}
|
||||
|
||||
function newPromptConfirmationToCloseAllDocuments(_input: any): {} {
|
||||
return {};
|
||||
}
|
||||
|
||||
export interface UpdateCanvas {
|
||||
document: string;
|
||||
}
|
||||
|
||||
@@ -28,14 +28,29 @@ pub fn select_document(document: usize) -> Result<(), JsValue> {
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::SelectDocument(document)).map_err(convert_error))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn new_document() -> Result<(), JsValue> {
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::NewDocument).map_err(convert_error))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn close_document(document: usize) -> Result<(), JsValue> {
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::CloseDocument(document)).map_err(convert_error))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn new_document() -> Result<(), JsValue> {
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::NewDocument).map_err(convert_error))
|
||||
pub fn close_all_documents() -> Result<(), JsValue> {
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::CloseAllDocuments).map_err(convert_error))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn close_active_document_with_confirmation() -> Result<(), JsValue> {
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::CloseActiveDocumentWithConfirmation).map_err(convert_error))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn close_all_documents_with_confirmation() -> Result<(), JsValue> {
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::CloseAllDocumentsWithConfirmation).map_err(convert_error))
|
||||
}
|
||||
|
||||
// TODO: Call event when the panels are resized
|
||||
@@ -196,7 +211,7 @@ pub fn toggle_layer_expansion(path: Vec<LayerId>) -> Result<(), JsValue> {
|
||||
.map_err(convert_error)
|
||||
}
|
||||
|
||||
/// Renames a layer from the layer list
|
||||
/// Renames a layer from the layer list
|
||||
#[wasm_bindgen]
|
||||
pub fn rename_layer(path: Vec<LayerId>, new_name: String) -> Result<(), JsValue> {
|
||||
EDITOR_STATE
|
||||
@@ -204,7 +219,7 @@ pub fn rename_layer(path: Vec<LayerId>, new_name: String) -> Result<(), JsValue>
|
||||
.map_err(convert_error)
|
||||
}
|
||||
|
||||
/// Deletes a layer from the layer list
|
||||
/// Deletes a layer from the layer list
|
||||
#[wasm_bindgen]
|
||||
pub fn delete_layer(path: Vec<LayerId>) -> Result<(), JsValue> {
|
||||
EDITOR_STATE
|
||||
@@ -212,7 +227,7 @@ pub fn delete_layer(path: Vec<LayerId>) -> Result<(), JsValue> {
|
||||
.map_err(convert_error)
|
||||
}
|
||||
|
||||
/// Requests the backend to add a layer to the layer list
|
||||
/// Requests the backend to add a layer to the layer list
|
||||
#[wasm_bindgen]
|
||||
pub fn add_folder(path: Vec<LayerId>) -> Result<(), JsValue> {
|
||||
EDITOR_STATE.with(|editor| editor.borrow_mut().handle_message(DocumentMessage::AddFolder(path))).map_err(convert_error)
|
||||
|
||||
Reference in New Issue
Block a user