Files
Graphite/frontend/src/state/dialog.ts
2022-01-12 14:16:13 -08:00

121 lines
4.1 KiB
TypeScript

import { reactive, readonly } from "vue";
import { DisplayDialogAboutGraphite } 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
export function createDialogState(editor: EditorState) {
const state = reactive({
visible: false,
icon: "" as IconName,
heading: "",
details: "",
buttons: [] as TextButtonWidget[],
});
const createDialog = (icon: IconName, heading: string, details: string, buttons: TextButtonWidget[]): void => {
state.visible = true;
state.icon = icon;
state.heading = heading;
state.details = details;
state.buttons = buttons;
};
const dismissDialog = (): void => {
state.visible = false;
};
const submitDialog = (): void => {
const firstEmphasizedButton = state.buttons.find((button) => button.props.emphasized && button.callback);
if (firstEmphasizedButton) {
// If statement satisfies TypeScript
if (firstEmphasizedButton.callback) firstEmphasizedButton.callback();
}
};
const dialogIsVisible = (): boolean => {
return 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 = [okButton];
if (issueNumber) buttons.push(issueButton);
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 && 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://www.graphite.design", "_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);
};
// Run on creation
editor.dispatcher.subscribeJsMessage(DisplayDialogAboutGraphite, () => onAboutHandler());
return {
state: readonly(state),
createDialog,
dismissDialog,
submitDialog,
dialogIsVisible,
comingSoon,
};
}
export type DialogState = ReturnType<typeof createDialogState>;