Skip to content

Commit 3eb1ccb

Browse files
committed
frontend/latex-editor + code-editor: refactor and simplify the new/default layout frame-tree actions
1 parent 4fffc32 commit 3eb1ccb

File tree

6 files changed

+113
-54
lines changed

6 files changed

+113
-54
lines changed

src/packages/frontend/frame-editors/code-editor/actions.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -805,13 +805,18 @@ export class Actions<
805805
}
806806
}
807807

808-
_default_frame_tree(): Map<string, any> {
809-
let frame_tree = fromJS(this._raw_default_frame_tree()) as Map<string, any>;
808+
// Process a raw frame tree: convert to immutable, assign IDs, ensure uniqueness
809+
private _process_frame_tree(rawTree: FrameTree): Map<string, any> {
810+
let frame_tree = fromJS(rawTree) as Map<string, any>;
810811
frame_tree = tree_ops.assign_ids(frame_tree);
811812
frame_tree = tree_ops.ensure_ids_are_unique(frame_tree);
812813
return frame_tree;
813814
}
814815

816+
_default_frame_tree(): Map<string, any> {
817+
return this._process_frame_tree(this._raw_default_frame_tree());
818+
}
819+
815820
// overload this in derived classes to specify the default layout.
816821
_raw_default_frame_tree(): FrameTree {
817822
return { type: "cm" };
@@ -846,11 +851,9 @@ export class Actions<
846851
return node.get("data-" + key, def);
847852
}
848853

849-
// Reset the frame tree layout to the default.
850-
reset_frame_tree(): void {
854+
// Common logic to apply a processed frame tree and update state
855+
private _apply_frame_tree(tree: Map<string, any>): void {
851856
let local = this.store.get("local_view_state");
852-
// Set the frame tree to a new default frame tree.
853-
const tree = this._default_frame_tree();
854857
local = local.set("frame_tree", tree);
855858
// Also make some id active, since existing active_id is no longer valid.
856859
local = local.set("active_id", tree_ops.get_some_leaf_id(tree));
@@ -868,6 +871,16 @@ export class Actions<
868871
}
869872
}
870873

874+
// Reset the frame tree layout to the default.
875+
reset_frame_tree(): void {
876+
this._apply_frame_tree(this._default_frame_tree());
877+
}
878+
879+
// Replace the entire frame tree with a custom tree structure
880+
replace_frame_tree(customTree: FrameTree): void {
881+
this._apply_frame_tree(this._process_frame_tree(customTree));
882+
}
883+
871884
set_frame_tree_leafs(obj): void {
872885
this._tree_op("set_leafs", obj);
873886
}

src/packages/frontend/frame-editors/frame-tree/commands/generic-commands.tsx

Lines changed: 69 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
undo as chatUndo,
2222
} from "@cocalc/frontend/frame-editors/generic/chat";
2323
import { get_default_font_size } from "@cocalc/frontend/frame-editors/generic/client";
24+
import { Actions as LatexEditorActions } from "@cocalc/frontend/frame-editors/latex-editor/actions";
2425
import { labels, menu } from "@cocalc/frontend/i18n";
2526
import { editor } from "@cocalc/frontend/i18n/common";
2627
import { open_new_tab as openNewTab } from "@cocalc/frontend/misc/open-browser-tab";
@@ -1310,9 +1311,12 @@ addCommands({
13101311
children: ({ frameTypeCommands }) => frameTypeCommands(false),
13111312
},
13121313
reset_local_view_state: {
1313-
alwaysShow: true,
13141314
icon: "layout",
13151315
group: "frame_types",
1316+
isVisible: ({ props }) =>
1317+
// always show it, except for the LateX Editor: there we have classic_layout and new_layout
1318+
props.editor_actions == null ||
1319+
!(props.editor_actions instanceof LatexEditorActions),
13161320
title: defineMessage({
13171321
id: "command.generic.reset_local_view_state.title",
13181322
defaultMessage: "Reset the layout of all frames to the default",
@@ -1329,11 +1333,21 @@ addCommands({
13291333
new_layout: {
13301334
icon: "layout",
13311335
group: "frame_types",
1332-
title: defineMessage({
1333-
id: "command.generic.new_layout.title",
1334-
defaultMessage:
1335-
"Switch to a simplified layout with LaTeX source editor and multi-purpose output panel",
1336-
}),
1336+
title: ({ props }) => {
1337+
// Check if this is a LaTeX editor using instanceof
1338+
const isLatexEditor = props.editor_actions instanceof LatexEditorActions;
1339+
if (isLatexEditor) {
1340+
return defineMessage({
1341+
id: "command.generic.new_layout.title.latex",
1342+
defaultMessage:
1343+
"Switch to the new layout with LaTeX source editor and multi-purpose output panel",
1344+
});
1345+
}
1346+
return defineMessage({
1347+
id: "command.generic.new_layout.title.generic",
1348+
defaultMessage: "Switch to the new layout",
1349+
});
1350+
},
13371351
label: defineMessage({
13381352
id: "command.generic.new_layout.label",
13391353
defaultMessage: "New Layout",
@@ -1343,22 +1357,65 @@ addCommands({
13431357
defaultMessage: "New",
13441358
}),
13451359
isVisible: ({ props }) =>
1346-
typeof props.actions?._new_latex_frame_tree === "function",
1360+
typeof props.actions?._new_frame_tree_layout === "function",
13471361
onClick: ({ props }) => {
13481362
try {
1349-
// Check if this is a LaTeX editor and use its specific layout method
1363+
// Use the editor's custom layout method if available
13501364
if (
1351-
props.actions._new_latex_frame_tree &&
1352-
props.actions.replace_frame_tree_with_custom
1365+
props.actions._new_frame_tree_layout &&
1366+
props.actions.replace_frame_tree
13531367
) {
1354-
const tree = props.actions._new_latex_frame_tree();
1355-
props.actions.replace_frame_tree_with_custom(tree);
1368+
const tree = props.actions._new_frame_tree_layout();
1369+
props.actions.replace_frame_tree(tree);
13561370
}
13571371
} catch (error) {
13581372
console.error("Error in New Layout:", error);
13591373
}
13601374
},
13611375
},
1376+
classic_layout: {
1377+
icon: "layout",
1378+
group: "frame_types",
1379+
title: ({ props }) => {
1380+
// Check if this is a LaTeX editor using instanceof
1381+
const isLatexEditor = props.editor_actions instanceof LatexEditorActions;
1382+
if (isLatexEditor) {
1383+
return defineMessage({
1384+
id: "command.generic.classic_layout.title.latex",
1385+
defaultMessage:
1386+
"Switch to the classic 4-panel layout with separate frames for source, table of contents, errors, PDF, and build log",
1387+
});
1388+
}
1389+
return defineMessage({
1390+
id: "command.generic.classic_layout.title.generic",
1391+
defaultMessage: "Switch back to the classic layout",
1392+
});
1393+
},
1394+
label: defineMessage({
1395+
id: "command.generic.classic_layout.label",
1396+
defaultMessage: "Classic Layout",
1397+
}),
1398+
button: defineMessage({
1399+
id: "command.generic.classic_layout.button",
1400+
defaultMessage: "Classic",
1401+
}),
1402+
isVisible: ({ props }) =>
1403+
typeof props.actions?._classic_frame_tree_layout === "function",
1404+
onClick: ({ props }) => {
1405+
try {
1406+
// Use the editor's classic layout method if available
1407+
if (
1408+
props.actions._classic_frame_tree_layout &&
1409+
props.actions.replace_frame_tree
1410+
) {
1411+
const tree = props.actions._classic_frame_tree_layout();
1412+
props.actions.replace_frame_tree(tree);
1413+
}
1414+
} catch (error) {
1415+
console.error("Error in Classic Layout:", error);
1416+
}
1417+
},
1418+
},
13621419
button_bar: {
13631420
alwaysShow: true,
13641421
icon: "tool",

src/packages/frontend/frame-editors/frame-tree/commands/manage.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,12 @@ export class ManageCommands {
326326
}
327327

328328
if (typeof data === "function") {
329-
return data(this);
329+
const result = data(this);
330+
// Check if the function returned an IntlMessage
331+
if (isIntlMessage(result)) {
332+
return this.intl.formatMessage(result, this.formatMessageValues);
333+
}
334+
return result;
330335
}
331336

332337
// react-intl defineMessage object

src/packages/frontend/frame-editors/frame-tree/commands/types.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,17 @@ interface PopconfirmOpts {
5757
cancelText?: string | IntlMessage;
5858
}
5959

60+
/**
61+
* Type for command text fields (title, label, button) that can be:
62+
* - A static ReactNode
63+
* - A static IntlMessage for internationalization
64+
* - A function that returns either ReactNode or IntlMessage based on context
65+
*/
66+
export type CommandText =
67+
| ReactNode
68+
| IntlMessage
69+
| ((opts: ManageCommands) => ReactNode | IntlMessage);
70+
6071
/**
6172
* Defines a command that can appear in frame editor menus, toolbars, and buttons.
6273
* For example, split frame, zoom, save, etc.
@@ -89,7 +100,7 @@ export interface Command {
89100
pos?: number;
90101

91102
// Tooltip text shown when hovering over the command
92-
title?: ReactNode | ((opts: ManageCommands) => ReactNode) | IntlMessage;
103+
title?: CommandText;
93104

94105
// Icon to display for this command.
95106
icon?: IconName | ReactNode | ((opts: ManageCommands) => ReactNode);
@@ -98,13 +109,13 @@ export interface Command {
98109
iconRotate?: IconRotation;
99110

100111
// Label for button bar buttons. Separate from 'label' to allow different text in menus vs. compact button bar.
101-
button?: ReactNode | ((opts: ManageCommands) => ReactNode) | IntlMessage;
112+
button?: CommandText;
102113

103114
// unclear?
104115
//color?: string | ((opts: ManageCommands) => string);
105116

106117
// Primary label for the command in menus.
107-
label?: ReactNode | ((opts: ManageCommands) => ReactNode) | IntlMessage;
118+
label?: CommandText;
108119

109120
/**
110121
* Click handler for the command. If not provided, the system falls back to

src/packages/frontend/frame-editors/frame-tree/util.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { path_split, separate_file_extension } from "@cocalc/util/misc";
1111
import { fileURL } from "@cocalc/frontend/lib/cocalc-urls";
1212
import { getComputeServerId } from "@cocalc/frontend/frame-editors/generic/client";
1313

14-
1514
export function parse_path(path: string): {
1615
directory: string;
1716
base: string;

src/packages/frontend/frame-editors/latex-editor/actions.ts

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ export class Actions extends BaseActions<LatexEditorState> {
613613
return change;
614614
}
615615

616-
_raw_default_frame_tree(): FrameTree {
616+
_classic_frame_tree_layout(): FrameTree {
617617
if (this.is_public) {
618618
return { type: "cm" };
619619
} else {
@@ -645,7 +645,7 @@ export class Actions extends BaseActions<LatexEditorState> {
645645
}
646646
}
647647

648-
_new_latex_frame_tree(): FrameTree {
648+
_new_frame_tree_layout(): FrameTree {
649649
if (this.is_public) {
650650
return { type: "cm" };
651651
} else {
@@ -659,35 +659,9 @@ export class Actions extends BaseActions<LatexEditorState> {
659659
}
660660
}
661661

662-
// Method to replace the entire frame tree with a custom tree structure
663-
replace_frame_tree_with_custom(customTree: FrameTree): void {
664-
let local = this.store.get("local_view_state");
665-
666-
// Process the custom tree: assign IDs and ensure uniqueness
667-
let frame_tree = fromJS(customTree) as Map<string, any>;
668-
frame_tree = tree_ops.assign_ids(frame_tree);
669-
frame_tree = tree_ops.ensure_ids_are_unique(frame_tree);
670-
671-
// Set the frame tree to the custom tree
672-
local = local.set("frame_tree", frame_tree);
673-
674-
// Also make some id active, since existing active_id is no longer valid
675-
local = local.set("active_id", tree_ops.get_some_leaf_id(frame_tree));
676-
677-
// Update state, so visible to UI
678-
this.setState({ local_view_state: local });
679-
680-
// And save this new state to localStorage
681-
this.save_local_view_state();
682-
683-
// Emit new-frame events for all leaf nodes
684-
for (const id in this._get_leaf_ids()) {
685-
const leaf = this._get_frame_node(id);
686-
if (leaf != null) {
687-
const type = leaf.get("type");
688-
this.store.emit("new-frame", { id, type });
689-
}
690-
}
662+
// Override to make new layout the default
663+
_raw_default_frame_tree(): FrameTree {
664+
return this._new_frame_tree_layout();
691665
}
692666

693667
check_for_fatal_error(): void {

0 commit comments

Comments
 (0)