mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-01 08:28:11 +08:00
Migrate dialogs to Rust and add a New File dialog (#623)
* Migrate coming soon and about dialog to Rust * Migrate confirm close and close all * Migrate dialog error * Improve keyboard navigation throughout UI * Cleanup and fix panic dialog * Reduce css spacing to better match old dialogs * Add new document modal * Fix crash when generating default name * Populate rust about graphite data on startup * Code review changes * Move one more :focus CSS rule into App.vue * Add a dialog message and move dialogs * Split out keyboard input navigation from this branch * Improvements including simplifying panic dialog code Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
committed by
Keavon Chambers
co-authored by
Keavon Chambers
parent
1a8cc9654a
commit
4b7d8b7ab0
@@ -1,9 +1,8 @@
|
||||
import { reactive, readonly } from "vue";
|
||||
|
||||
import { DisplayDialogAboutGraphite, DisplayDialogComingSoon } from "@/dispatcher/js-messages";
|
||||
import { defaultWidgetLayout, DisplayDialog, DisplayDialogDismiss, UpdateDialogDetails, WidgetLayout } from "@/dispatcher/js-messages";
|
||||
import { EditorState } from "@/state/wasm-loader";
|
||||
import { IconName } from "@/utilities/icons";
|
||||
import { stripIndents } from "@/utilities/strip-indents";
|
||||
import { TextButtonWidget } from "@/utilities/widgets";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
@@ -11,103 +10,47 @@ export function createDialogState(editor: EditorState) {
|
||||
const state = reactive({
|
||||
visible: false,
|
||||
icon: "" as IconName,
|
||||
heading: "",
|
||||
details: "",
|
||||
buttons: [] as TextButtonWidget[],
|
||||
widgets: defaultWidgetLayout(),
|
||||
// Special case for the crash dialog because we cannot handle button widget callbacks from Rust once the editor instance has panicked
|
||||
jsCallbackBasedButtons: undefined as undefined | TextButtonWidget[],
|
||||
});
|
||||
|
||||
const createDialog = (icon: IconName, heading: string, details: string, buttons: TextButtonWidget[]): void => {
|
||||
// Creates a panic dialog from JS.
|
||||
// Normal dialogs are created in the Rust backend, however for the crash dialog, the editor instance has panicked so it cannot respond to widget callbacks.
|
||||
const createPanicDialog = (widgets: WidgetLayout, jsCallbackBasedButtons: TextButtonWidget[]): void => {
|
||||
state.visible = true;
|
||||
state.icon = icon;
|
||||
state.heading = heading;
|
||||
state.details = details;
|
||||
state.buttons = buttons;
|
||||
state.icon = "Warning";
|
||||
state.widgets = widgets;
|
||||
state.jsCallbackBasedButtons = jsCallbackBasedButtons;
|
||||
};
|
||||
|
||||
const dismissDialog = (): void => {
|
||||
state.visible = false;
|
||||
};
|
||||
|
||||
const submitDialog = (): void => {
|
||||
const firstEmphasizedButton = state.buttons.find((button) => button.props.emphasized && button.callback);
|
||||
firstEmphasizedButton?.callback?.();
|
||||
};
|
||||
|
||||
const dialogIsVisible = (): boolean => state.visible;
|
||||
|
||||
const comingSoon = (issueNumber?: number): void => {
|
||||
const bugMessage = `— but you can help add it!\nSee issue #${issueNumber} on GitHub.`;
|
||||
const details = `This feature is not implemented yet${issueNumber ? bugMessage : ""}`;
|
||||
|
||||
const okButton: TextButtonWidget = {
|
||||
kind: "TextButton",
|
||||
callback: async () => dismissDialog(),
|
||||
props: { label: "OK", emphasized: true, minWidth: 96 },
|
||||
};
|
||||
const issueButton: TextButtonWidget = {
|
||||
kind: "TextButton",
|
||||
callback: async () => window.open(`https://github.com/GraphiteEditor/Graphite/issues/${issueNumber}`, "_blank"),
|
||||
props: { label: `Issue #${issueNumber}`, minWidth: 96 },
|
||||
};
|
||||
const buttons = issueNumber ? [okButton, issueButton] : [okButton];
|
||||
|
||||
createDialog("Warning", "Coming soon", details, buttons);
|
||||
};
|
||||
|
||||
const onAboutHandler = (): void => {
|
||||
const date = new Date(process.env.VUE_APP_COMMIT_DATE || "");
|
||||
const dateString = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
|
||||
const timeString = `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
|
||||
const timezoneName = Intl.DateTimeFormat(undefined, { timeZoneName: "long" })
|
||||
.formatToParts(new Date())
|
||||
.find((part) => part.type === "timeZoneName");
|
||||
const timezoneNameString = timezoneName?.value;
|
||||
|
||||
const hash = (process.env.VUE_APP_COMMIT_HASH || "").substring(0, 12);
|
||||
|
||||
const details = stripIndents`
|
||||
Release Series: ${process.env.VUE_APP_RELEASE_SERIES}
|
||||
|
||||
Date: ${dateString} ${timeString} ${timezoneNameString}
|
||||
Hash: ${hash}
|
||||
Branch: ${process.env.VUE_APP_COMMIT_BRANCH}
|
||||
`;
|
||||
|
||||
const buttons: TextButtonWidget[] = [
|
||||
{
|
||||
kind: "TextButton",
|
||||
callback: (): unknown => window.open("https://graphite.rs", "_blank"),
|
||||
props: { label: "Website", emphasized: false, minWidth: 0 },
|
||||
},
|
||||
{
|
||||
kind: "TextButton",
|
||||
callback: (): unknown => window.open("https://github.com/GraphiteEditor/Graphite/graphs/contributors", "_blank"),
|
||||
props: { label: "Credits", emphasized: false, minWidth: 0 },
|
||||
},
|
||||
{
|
||||
kind: "TextButton",
|
||||
callback: (): unknown => window.open("https://raw.githubusercontent.com/GraphiteEditor/Graphite/master/LICENSE.txt", "_blank"),
|
||||
props: { label: "License", emphasized: false, minWidth: 0 },
|
||||
},
|
||||
{
|
||||
kind: "TextButton",
|
||||
callback: (): unknown => window.open("/third-party-licenses.txt", "_blank"),
|
||||
props: { label: "Third-Party Licenses", emphasized: false, minWidth: 0 },
|
||||
},
|
||||
];
|
||||
|
||||
createDialog("GraphiteLogo", "Graphite", details, buttons);
|
||||
editor.instance.request_coming_soon_dialog(issueNumber);
|
||||
};
|
||||
|
||||
// Run on creation
|
||||
editor.dispatcher.subscribeJsMessage(DisplayDialogAboutGraphite, () => onAboutHandler());
|
||||
editor.dispatcher.subscribeJsMessage(DisplayDialogComingSoon, (displayDialogComingSoon) => comingSoon(displayDialogComingSoon.issue));
|
||||
editor.dispatcher.subscribeJsMessage(DisplayDialog, (displayDialog) => {
|
||||
state.visible = true;
|
||||
state.icon = displayDialog.icon;
|
||||
});
|
||||
|
||||
editor.dispatcher.subscribeJsMessage(DisplayDialogDismiss, dismissDialog);
|
||||
|
||||
editor.dispatcher.subscribeJsMessage(UpdateDialogDetails, (updateDialogDetails) => {
|
||||
state.widgets = updateDialogDetails;
|
||||
state.jsCallbackBasedButtons = undefined;
|
||||
});
|
||||
|
||||
return {
|
||||
state: readonly(state),
|
||||
createDialog,
|
||||
createPanicDialog,
|
||||
dismissDialog,
|
||||
submitDialog,
|
||||
dialogIsVisible,
|
||||
comingSoon,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user