Restyle and refactor shortcut labels to send hints bar and welcome screen layouts from Rust (#3447)

* Restyle UserInputLabel and refactor its usages to have all input its data sent from Rust

* Replace the welcome screen quick buttons with ones sent by backend

* Add the ShortcutLabel widget to the backend

* Replace hints bar with a backend-controlled layout; show mouse icons in place of mouse labels
This commit is contained in:
Keavon Chambers
2025-12-04 01:04:14 -08:00
committed by GitHub
parent 6ed42d06bb
commit 810ce40e9b
78 changed files with 981 additions and 997 deletions
+66 -79
View File
@@ -2,7 +2,7 @@
import { Transform, Type, plainToClass } from "class-transformer";
import { type EditorHandle } from "@graphite/../wasm/pkg/graphite_wasm.js";
import { type EditorHandle } from "@graphite/../wasm/pkg/graphite_wasm";
import { type PopoverButtonStyle, type IconName, type IconSize } from "@graphite/icons";
export class JsMessage {
@@ -305,37 +305,14 @@ export class UpdateViewportPhysicalBounds extends JsMessage {
readonly height!: number;
}
export class UpdateInputHints extends JsMessage {
@Type(() => HintInfo)
readonly hintData!: HintData;
}
export type HintData = HintGroup[];
export type HintGroup = HintInfo[];
export class HintInfo {
readonly keyGroups!: LayoutKeysGroup[];
readonly keyGroupsMac!: LayoutKeysGroup[] | undefined;
readonly mouse!: MouseMotion | undefined;
readonly label!: string;
readonly plus!: boolean;
readonly slash!: boolean;
}
// Rust enum `Key`
export type KeyRaw = string;
// Serde converts a Rust `Key` enum variant into this format with both the `Key` variant name (called `RawKey` in TS) and the localized `label` for the key
export type Key = { key: KeyRaw; label: string };
export type LayoutKeysGroup = Key[];
export type ActionKeys = { keys: LayoutKeysGroup };
export type LabeledKey = { key: KeyRaw; label: string };
export type MouseMotion = "None" | "Lmb" | "Rmb" | "Mmb" | "ScrollUp" | "ScrollDown" | "Drag" | "LmbDouble" | "LmbDrag" | "RmbDrag" | "RmbDouble" | "MmbDrag";
export type LabeledKeyOrMouseMotion = LabeledKey | MouseMotion;
export type LabeledShortcut = LabeledKeyOrMouseMotion[];
export type ActionShortcut = { shortcut: LabeledShortcut };
// Channels can have any range (0-1, 0-255, 0-100, 0-360) in the context they are being used in, these are just containers for the numbers
export type HSVA = { h: number; s: number; v: number; a: number };
@@ -910,8 +887,8 @@ export class CheckboxInput extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
forLabel!: bigint | undefined;
}
@@ -954,8 +931,8 @@ export class ColorInput extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
}
export type FillChoice = Color | Gradient;
@@ -1000,9 +977,7 @@ export type MenuListEntry = {
disabled?: boolean;
tooltipLabel?: string;
tooltipDescription?: string;
tooltipShortcut?: string;
shortcutKeys?: ActionKeys;
shortcutRequiresLock?: boolean;
tooltipShortcut?: ActionShortcut;
children?: MenuListEntry[][];
};
@@ -1028,8 +1003,8 @@ export class CurveInput extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
}
export class DropdownInput extends WidgetProps {
@@ -1051,8 +1026,8 @@ export class DropdownInput extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
// Styling
@@ -1076,8 +1051,8 @@ export class FontInput extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
}
export class IconButton extends WidgetProps {
@@ -1097,8 +1072,8 @@ export class IconButton extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
}
export class IconLabel extends WidgetProps {
@@ -1112,8 +1087,8 @@ export class IconLabel extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
}
export class ImageButton extends WidgetProps {
@@ -1131,8 +1106,8 @@ export class ImageButton extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
}
export class ImageLabel extends WidgetProps {
@@ -1150,8 +1125,13 @@ export class ImageLabel extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
}
export class ShortcutLabel extends WidgetProps {
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
shortcut!: ActionShortcut | undefined;
}
export type NumberInputIncrementBehavior = "Add" | "Multiply" | "Callback" | "None";
@@ -1168,8 +1148,8 @@ export class NumberInput extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
// Disabled
@@ -1234,8 +1214,8 @@ export class PopoverButton extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
// Body
popoverLayout!: LayoutGroup[];
@@ -1251,7 +1231,7 @@ export type RadioEntryData = {
icon?: IconName;
tooltipLabel?: string;
tooltipDescription?: string;
tooltipShortcut?: string;
tooltipShortcut?: ActionShortcut;
};
export type RadioEntries = RadioEntryData[];
@@ -1297,8 +1277,8 @@ export class TextAreaInput extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
}
export class ParameterExposeButton extends WidgetProps {
@@ -1312,8 +1292,8 @@ export class ParameterExposeButton extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
}
export class TextButton extends WidgetProps {
@@ -1339,8 +1319,8 @@ export class TextButton extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
menuListChildren!: MenuListEntry[][];
}
@@ -1356,8 +1336,8 @@ export class BreadcrumbTrailButtons extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
}
export class TextInput extends WidgetProps {
@@ -1379,8 +1359,8 @@ export class TextInput extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
}
export class TextLabel extends WidgetProps {
@@ -1412,8 +1392,8 @@ export class TextLabel extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
forCheckbox!: bigint | undefined;
}
@@ -1431,8 +1411,8 @@ export class ReferencePointInput extends WidgetProps {
@Transform(({ value }: { value: string }) => value || undefined)
tooltipDescription!: string | undefined;
@Transform(({ value }: { value: string }) => value || undefined)
tooltipShortcut!: string | undefined;
@Transform(({ value }: { value: ActionShortcut }) => value || undefined)
tooltipShortcut!: ActionShortcut | undefined;
}
// WIDGET
@@ -1447,6 +1427,7 @@ const widgetSubTypes = [
{ value: IconButton, name: "IconButton" },
{ value: ImageButton, name: "ImageButton" },
{ value: ImageLabel, name: "ImageLabel" },
{ value: ShortcutLabel, name: "ShortcutLabel" },
{ value: IconLabel, name: "IconLabel" },
{ value: NodeCatalog, name: "NodeCatalog" },
{ value: NumberInput, name: "NumberInput" },
@@ -1586,7 +1567,7 @@ export function isWidgetSpanRow(layoutRow: LayoutGroup): layoutRow is WidgetSpan
return Boolean((layoutRow as WidgetSpanRow)?.rowWidgets);
}
export type WidgetTable = { tableWidgets: Widget[][] };
export type WidgetTable = { tableWidgets: Widget[][]; unstyled: boolean };
export function isWidgetTable(layoutTable: LayoutGroup): layoutTable is WidgetTable {
return Boolean((layoutTable as WidgetTable)?.tableWidgets);
}
@@ -1643,6 +1624,7 @@ function createLayoutGroup(layoutGroup: any): LayoutGroup {
if (layoutGroup.table) {
const result: WidgetTable = {
tableWidgets: layoutGroup.table.tableWidgets.map(hoistWidgetHolders),
unstyled: layoutGroup.table.unstyled,
};
return result;
}
@@ -1671,10 +1653,14 @@ export class UpdateMenuBarLayout extends WidgetDiffUpdate {}
export class UpdateNodeGraphControlBarLayout extends WidgetDiffUpdate {}
export class UpdateWelcomeScreenButtonsLayout extends WidgetDiffUpdate {}
export class UpdatePropertiesPanelLayout extends WidgetDiffUpdate {}
export class UpdateDataPanelLayout extends WidgetDiffUpdate {}
export class UpdateStatusBarHintsLayout extends WidgetDiffUpdate {}
export class UpdateToolOptionsLayout extends WidgetDiffUpdate {}
export class UpdateToolShelfLayout extends WidgetDiffUpdate {}
@@ -1696,21 +1682,21 @@ export const messageMakers: Record<string, MessageMaker> = {
SendUIMetadata,
TriggerAboutGraphiteLocalizedCommitDate,
TriggerDisplayThirdPartyLicensesDialog,
TriggerSaveDocument,
TriggerSaveFile,
TriggerExportImage,
TriggerFetchAndOpenDocument,
TriggerFontLoad,
TriggerImport,
TriggerPersistenceRemoveDocument,
TriggerPersistenceWriteDocument,
TriggerLoadFirstAutoSaveDocument,
TriggerLoadPreferences,
TriggerLoadRestAutoSaveDocuments,
TriggerOpenLaunchDocuments,
TriggerOpenDocument,
TriggerOpenLaunchDocuments,
TriggerPaste,
TriggerPersistenceRemoveDocument,
TriggerPersistenceWriteDocument,
TriggerSaveActiveDocument,
TriggerSaveDocument,
TriggerSaveFile,
TriggerSavePreferences,
TriggerTextCommit,
TriggerTextCopy,
@@ -1719,6 +1705,8 @@ export const messageMakers: Record<string, MessageMaker> = {
UpdateBox,
UpdateClickTargets,
UpdateContextMenuInformation,
UpdateDataPanelLayout,
UpdateDataPanelState,
UpdateDialogButtons,
UpdateDialogColumn1,
UpdateDialogColumn2,
@@ -1735,18 +1723,18 @@ export const messageMakers: Record<string, MessageMaker> = {
UpdateGraphViewOverlay,
UpdateImportReorderIndex,
UpdateImportsExports,
UpdateInputHints,
UpdateInSelectedNetwork,
UpdateLayersPanelBottomBarLayout,
UpdateLayersPanelControlBarLeftLayout,
UpdateLayersPanelControlBarRightLayout,
UpdateLayersPanelState,
UpdateLayerWidths,
UpdateMaximized,
UpdateMenuBarLayout,
UpdateMouseCursor,
UpdateNodeGraphControlBarLayout,
UpdateNodeGraphNodes,
UpdateNodeGraphErrorDiagnostic,
UpdateNodeGraphNodes,
UpdateNodeGraphSelection,
UpdateNodeGraphTransform,
UpdateNodeGraphWires,
@@ -1754,15 +1742,14 @@ export const messageMakers: Record<string, MessageMaker> = {
UpdateOpenDocumentsList,
UpdatePlatform,
UpdatePropertiesPanelLayout,
UpdateDataPanelLayout,
UpdateDataPanelState,
UpdatePropertiesPanelState,
UpdateLayersPanelState,
UpdateStatusBarHintsLayout,
UpdateToolOptionsLayout,
UpdateToolShelfLayout,
UpdateViewportHolePunch,
UpdateViewportPhysicalBounds,
UpdateVisibleNodes,
UpdateWelcomeScreenButtonsLayout,
UpdateWirePathInProgress,
UpdateWorkingColorsLayout,
} as const;