Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support JSX and Interactive UI in simulator #2409

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

GuillaumeRx
Copy link
Contributor

@GuillaumeRx GuillaumeRx commented May 15, 2024

Description

This PR allows the simulator to consume the new JSX components from Snaps custom UI.

It also enable interactive interfaces to work in the simulator.

Breakdown:

  • Renderer:

    • Swap the old component format to the JSX format
    • Create a Context provider to provide interaction handlers to the components
  • OnRpcRequest and OnTransaction:

    • Add the missing hooks and handlers to the simulation backend and Redux Store
    • Create a dupe of the interface in the redux store to enable reactive re-rendering of the interface.
    • Interfaces now all go through the SnapInterfaceController
  • UI Builder:

    • Refactor the code generation methods
    • Refactor the component extraction methods
    • Adds the Field component

Copy link

socket-security bot commented May 15, 2024

New dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher
npm/@types/[email protected] None 0 7.29 kB types
npm/@types/[email protected] None 0 3.2 kB types
npm/@types/[email protected] None 0 3.19 kB types
npm/@types/[email protected] None 0 3.2 kB types
npm/[email protected] None 0 16.5 kB jdalton

View full report↗︎

@GuillaumeRx GuillaumeRx force-pushed the gr/fix-simulator-interactive-interface branch 2 times, most recently from 6bf80d6 to 26f6de0 Compare May 29, 2024 14:21
Copy link

socket-security bot commented May 31, 2024

👍 Dependency issues cleared. Learn more about Socket for GitHub ↗︎

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

View full report↗︎

@GuillaumeRx GuillaumeRx changed the title [WIP] Support JSX in simulator Support JSX in simulator Jun 6, 2024
@GuillaumeRx GuillaumeRx changed the title Support JSX in simulator Support JSX and Interactive UI in simulator Jun 6, 2024
@GuillaumeRx GuillaumeRx force-pushed the gr/fix-simulator-interactive-interface branch from 45829da to 9e8ebe8 Compare June 6, 2024 12:20
return false;
}

return node.type === 'Input' || node.type === 'Button';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fields can also take dropdowns and soon file inputs. Can we make this more generic somehow?

.map(componentToCode)
.join(',\n')}\n])`;
}
function getElementProps(props: Record<string, unknown>) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may be able to share some code between this and snaps-jest here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you point me to what part you were thinking we could reuse ? I've searched in snaps-jest but nothing seems relevant.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean this part:

/**
* Serialise a JSX prop to a string.
*
* @param prop - The JSX prop.
* @returns The serialised JSX prop.
*/
function serialiseProp(prop: unknown): string {
if (typeof prop === 'string') {
return `"${prop}"`;
}
return `{${JSON.stringify(prop)}}`;
}
/**
* Serialise JSX props to a string.
*
* @param props - The JSX props.
* @returns The serialised JSX props.
*/
function serialiseProps(props: Record<string, unknown>): string {
return Object.entries(props)
.filter(([key]) => key !== 'children')
.sort(([a], [b]) => a.localeCompare(b))
.map(([key, value]) => ` ${key}=${serialiseProp(value)}`)
.join('');
}
/**
* Serialise a JSX node to a string.
*
* @param node - The JSX node.
* @param indentation - The indentation level. Defaults to `0`. This should not
* be set by the caller, as it is used for recursion.
* @returns The serialised JSX node.
*/
export function serialiseJsx(node: SnapNode, indentation = 0): string {
if (Array.isArray(node)) {
return node.map((child) => serialiseJsx(child, indentation)).join('');
}
const indent = ' '.repeat(indentation);
if (typeof node === 'string') {
return `${indent}${node}\n`;
}
if (!node) {
return '';
}
const { type, props } = node;
const trailingNewline = indentation > 0 ? '\n' : '';
if (hasProperty(props, 'children')) {
const children = serialiseJsx(props.children as SnapNode, indentation + 1);
return `${indent}<${type}${serialiseProps(
props,
)}>\n${children}${indent}</${type}>${trailingNewline}`;
}
return `${indent}<${type}${serialiseProps(props)} />${trailingNewline}`;
}

It turns a rendered JSX node into code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants