-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathcontroller.ts
More file actions
109 lines (88 loc) · 3.88 KB
/
Copy pathcontroller.ts
File metadata and controls
109 lines (88 loc) · 3.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import { pluginNodesToUINodes, PluginUINodeData } from "./model.js";
import { PluginNode } from "./node.js";
/**
* A constant used to remove a previously applied style or token.
*/
export const STYLE_REMOVE = "__REMOVE__";
/**
* The state object that is passed back and forth between the plugin UI and Controller portions.
*/
export interface PluginUIState {
selectedNodes: PluginUINodeData[];
}
/**
* Controller class designed to handle communication between the plugin and the design tool.
* The controller is designed to be agnostic to the design environment,
* relying on the abstract properties and methods to supply the implementation
* details that might exist for the ecosystem it is being run in. (Figma, Sketch, etc).
*/
export abstract class Controller {
/**
* Tracks the number of nodes loaded for performance stats.
*/
public static nodeCount: number = 0;
/**
* Gets a Node from the design tool by ID.
* @param id - The ID of the node.
* @returns The PluginNode or null if no node by the provided ID exists.
*/
public abstract getNode(id: string): Promise<PluginNode | null>;
/**
* Provides the state object to the UI component and updates the UI.
* @param state - The UI state object.
*/
protected abstract sendStateToUI(state: PluginUIState): void;
/**
* Sets the selected node IDs - Setting the IDs will trigger a UI refresh.
* @param ids - The node IDs.
*/
public async setSelectedNodes(ids: string[]): Promise<void> {
Controller.nodeCount = 0;
// console.log("--------------------------------");
// console.log("Controller.setSelectedNodes begin - selected nodes", ids);
// const timeStart = new Date().getTime();
this.sendStateToUI(await this.getPluginUIState(ids));
// const timeEnd = new Date().getTime();
// const timeDiff = timeEnd - timeStart;
// console.log("Controller.setSelectedNodes end - timing", timeDiff, "node count", Controller.nodeCount);
// console.log("--------------------------------");
}
/**
* Handle the updated state that's posted from the UI.
* @param state - The state from the UI.
*/
public async receiveStateFromUI(state: PluginUIState): Promise<void> {
// console.log("--------------------------------");
// console.log("Controller.receiveStateFromUI begin", state);
// const timeStart = new Date().getTime();
await this.syncPluginNodes(state.selectedNodes);
// const timeEnd = new Date().getTime();
// const timeDiff = timeEnd - timeStart;
// console.log("Controller.receiveStateFromUI end - timing", timeDiff);
// console.log("--------------------------------");
}
private async getPluginUIState(ids: string[]): Promise<PluginUIState> {
const nodes = await Promise.all(ids
.map(async id => await this.getNode(id))
);
const selectedNodes = nodes.filter((node): node is PluginNode => node !== null);
const includeChildren = selectedNodes[0].type !== "PAGE";
return {
selectedNodes: await pluginNodesToUINodes(selectedNodes, true, includeChildren),
};
}
private async syncPluginNodes(nodes: PluginUINodeData[]) {
for (const node of nodes) {
const pluginNode = await this.getNode(node.id);
if (pluginNode) {
await pluginNode.handleManualDarkMode();
await pluginNode.setDesignTokens(node.designTokens);
pluginNode.setAppliedStyleModules(node.appliedStyleModules);
pluginNode.setAppliedDesignTokens(node.appliedDesignTokens);
// Paint all applied design tokens on the node
await pluginNode.paint(node.effectiveAppliedStyleValues);
await this.syncPluginNodes(node.children);
}
}
}
}