Skip to content

Commit d86cfdd

Browse files
Merge pull request #38 from gridaco/flutter-support-with-universal-tokenization
Flutter universal token support (1/3)
2 parents 8ee218f + 9216fcf commit d86cfdd

File tree

82 files changed

+1522
-726
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+1522
-726
lines changed

docs/flutter-svg-support.md

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Flutter does not have a SVG support.
2+
3+
**Use `flutter_svg`**
4+
5+
> Can't run on dartpad.
6+
7+
```dart
8+
9+
```
10+
11+
**Use `Image.network()`**
12+
13+
> Can run on dartpad, requires hosting within svg to png conversion.
14+
15+
```dart
16+
17+
```

editor/components/app-runner/app-runner.tsx

+14-9
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,12 @@ function DedicatedFrameworkRunner({
7777
switch (platform) {
7878
case "flutter":
7979
return (
80-
<div>
81-
<FlutterAppRunner
82-
width="100%"
83-
height="100%"
84-
q={{
85-
language: "dart",
86-
src: src,
87-
}}
88-
/>
80+
<div
81+
style={{
82+
width: "100%",
83+
height: "100%",
84+
}}
85+
>
8986
<button
9087
onClick={() => {
9188
const _name = "fluttercodefromdesigntocode";
@@ -108,6 +105,14 @@ function DedicatedFrameworkRunner({
108105
>
109106
open in console
110107
</button>
108+
<FlutterAppRunner
109+
width="100%"
110+
height="100%"
111+
q={{
112+
language: "dart",
113+
src: src,
114+
}}
115+
/>
111116
</div>
112117
);
113118
case "react":

editor/pages/figma/to-flutter.tsx

+9-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import React, { useEffect, useState } from "react";
22
import { designTo } from "@designto/code";
3+
import styled from "@emotion/styled";
4+
import { RemoteImageRepositories } from "@design-sdk/figma-remote/lib/asset-repository/image-repository";
5+
import {
6+
ImageRepository,
7+
MainImageRepository,
8+
} from "@design-sdk/core/assets-repository";
9+
import { output } from "@designto/config";
10+
import { tokenize } from "@designto/token";
311
import { utils_dart } from "../../utils";
412
import { DefaultEditorWorkspaceLayout } from "../../layout/default-editor-workspace-layout";
513
import { LayerHierarchy } from "../../components/editor-hierarchy";
@@ -8,15 +16,8 @@ import {
816
WorkspaceContentPanelGridLayout,
917
} from "../../layout/panel";
1018
import { PreviewAndRunPanel } from "../../components/preview-and-run";
11-
import styled from "@emotion/styled";
1219
import { useDesign } from "../../query-hooks";
1320
import { MonacoEditor } from "../../components/code-editor";
14-
import { RemoteImageRepositories } from "@design-sdk/figma-remote/lib/asset-repository/image-repository";
15-
import {
16-
ImageRepository,
17-
MainImageRepository,
18-
} from "@design-sdk/core/assets-repository";
19-
import { output } from "@designto/config";
2021
import LoadingLayout from "../../layout/loading-overlay";
2122

2223
export default function FigmaToFlutterPage() {
@@ -26,7 +27,6 @@ export default function FigmaToFlutterPage() {
2627
useEffect(() => {
2728
if (design) {
2829
const { reflect, url, node, file } = design;
29-
const { id, name } = reflect;
3030

3131
// ------------------------------------------------------------
3232
// other platforms are not supported yet
@@ -39,13 +39,10 @@ export default function FigmaToFlutterPage() {
3939
)
4040
);
4141
// ------------------------------------------------------------
42-
4342
designTo
4443
.flutter({
4544
input: {
46-
id: id,
47-
name: name,
48-
design: reflect,
45+
widget: tokenize(reflect),
4946
},
5047
asset_config: { asset_repository: MainImageRepository.instance },
5148
})

editor/pages/to-code/index.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export default function DesignToCodeUniversalPage() {
6565
return <LoadingLayout />;
6666
}
6767

68-
const { code, name: componentName } = result;
68+
const { code, scaffold, name: componentName } = result;
6969

7070
const runner_platform = get_runner_platform(framework_config);
7171
return (
@@ -84,7 +84,7 @@ export default function DesignToCodeUniversalPage() {
8484
<PreviewAndRunPanel
8585
key={design.url ?? design.reflect?.id}
8686
config={{
87-
src: code.raw,
87+
src: scaffold.raw,
8888
platform: runner_platform,
8989
componentName: componentName,
9090
sceneSize: {
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
export interface FlutterComponentOutput {}
1+
import { ComponentOutput } from "../output";
2+
3+
export interface FlutterComponentOutput extends ComponentOutput {}

packages/design-sdk

packages/designto-code/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"@designto/web": "0.0.0",
1111
"@design-sdk/universal": "0.0.0",
1212
"@reflect-ui/detection": "0.1.1",
13-
"@flutter-builder/flutter": "^2.5.0-f2"
13+
"@flutter-builder/flutter": "^2.5.0-f3"
1414
},
1515
"files": [
1616
"README.md",

packages/designto-code/universal/design-to-code.ts

+16-24
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { Widget } from "@reflect-ui/core";
44
import * as toreact from "@designto/react";
55
import * as tovanilla from "@designto/vanilla";
66
import * as toflutter from "@designto/flutter";
7-
import { composeAppWithHome } from "@flutter-builder/flutter";
87
import {
98
fetch_all_assets,
109
finalize_temporary_assets_with_prefixed_static_string_keys__dangerously,
@@ -27,14 +26,14 @@ export async function designToCode({
2726
asset_config: AssetsConfig;
2827
}): Promise<output.ICodeOutput> {
2928
const token = tokenize(input.design);
30-
29+
const _tokenized_widget_input = { widget: token };
3130
switch (framework.framework) {
3231
case "vanilla":
33-
return designToVanilla({ input: { widget: token }, asset_config });
32+
return designToVanilla({ input: _tokenized_widget_input, asset_config });
3433
case "react":
35-
return designToReact({ input: { widget: token }, asset_config });
34+
return designToReact({ input: _tokenized_widget_input, asset_config });
3635
case "flutter":
37-
return designToFlutter({ input, asset_config });
36+
return designToFlutter({ input: _tokenized_widget_input, asset_config });
3837
}
3938
throw `The framework "${framework}" is not supported at this point.`;
4039
return;
@@ -78,38 +77,31 @@ export async function designToFlutter({
7877
input,
7978
asset_config,
8079
}: {
81-
input: input.IDesignInput;
80+
input: { widget: Widget };
8281
asset_config?: AssetsConfig;
8382
}): Promise<output.ICodeOutput> {
8483
await Promise.resolve();
8584

86-
const flutterAppBuild = toflutter.buildApp(input.design);
87-
const widget = flutterAppBuild?.widget;
88-
const app =
89-
widget &&
90-
toflutter.makeApp({
91-
widget: widget,
92-
scrollable: flutterAppBuild.scrollable,
93-
});
85+
const flutterwidget = toflutter.buildFlutterWidget(input.widget);
86+
const flutterapp = toflutter.buildFlutterApp(flutterwidget);
9487

95-
let widgetCode = widget?.build()?.finalize();
96-
let rootAppCode = composeAppWithHome(app);
9788
// ------------------------------------------------------------------------
9889
// finilize temporary assets
9990
// this should be placed somewhere else
10091
if (asset_config?.asset_repository && !asset_config.skip_asset_replacement) {
10192
const assets = await fetch_all_assets(asset_config?.asset_repository);
102-
rootAppCode = dangerous_temporary_asset_replacer(rootAppCode, assets);
103-
widgetCode = dangerous_temporary_asset_replacer(widgetCode, assets);
93+
flutterapp.scaffold.raw = dangerous_temporary_asset_replacer(
94+
flutterapp.scaffold.raw,
95+
assets
96+
);
97+
flutterapp.code.raw = dangerous_temporary_asset_replacer(
98+
flutterapp.code.raw,
99+
assets
100+
);
104101
}
105102
// ------------------------------------------------------------------------
106103

107-
return {
108-
code: { raw: widgetCode },
109-
scaffold: { raw: rootAppCode },
110-
id: input.id,
111-
name: input.name,
112-
};
104+
return flutterapp;
113105
}
114106

115107
export function designToVue(input: input.IDesignInput): output.ICodeOutput {

packages/designto-flutter/utils/make-as-safe-single.ts renamed to packages/designto-flutter/_utils/array-utils.ts

+7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
import * as flutter from "@flutter-builder/flutter";
2+
export function makeSafelyAsList<T>(maybeList: Array<T> | T): Array<T> {
3+
if (Array.isArray(maybeList)) {
4+
return maybeList;
5+
} else {
6+
return [maybeList];
7+
}
8+
}
29

310
export function makeSaflyAsSingle(
411
maybeWidget: Array<flutter.Widget> | flutter.Widget
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from "./round-double";
2+
export * from "./array-utils";
3+
export * from "./size-utils";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Image.memory handling
2+
3+
Unlike web, using base64 encoded image string requires extra steps on flutter
4+
5+
```dart
6+
import 'dart:convert';
7+
import 'package:flutter/widgets.dart';
8+
9+
Image.memory(base64Decode(base64String));
10+
```
11+
12+
### References
13+
14+
- https://stackoverflow.com/questions/46145472/how-to-convert-base64-string-into-image-with-flutter
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Flutter svg support - [Learn more at docs](../../../../docs/flutter-svg-support.md)
2+
3+
- https://github.com/lovell/sharp
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { VectorWidget } from "@reflect-ui/core";
2+
import * as flutter from "@flutter-builder/flutter";
3+
4+
/**
5+
* @deprecated - not implemented
6+
* @param vector
7+
*/
8+
export function flutter_handle_svg_vector_as_bitmap_converted(
9+
vector: VectorWidget
10+
): flutter.Widget {
11+
throw `svg to png conversion is not supported yet.`;
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Nested stack in flutter
2+
3+
Nested stack (stack under positioned under stack) requires width and height.
4+
This,
5+
6+
```dart
7+
Stack(
8+
children: [
9+
Positioned(
10+
left: 795,
11+
top: 163,
12+
child: Stack(
13+
children: [
14+
Positioned(
15+
left: 0,
16+
top: 83,
17+
child: Text(
18+
"BeoPlay S3 draws heavily on geometry as a design reference. But also, it is reminiscent from the lines of two shapes embracing each other.",
19+
style: TextStyle(
20+
fontSize: 18,
21+
fontWeight: FontWeight.w400,
22+
fontFamily: "Roboto",
23+
),
24+
),
25+
),
26+
Positioned(
27+
left: 0,
28+
top: 23,
29+
child: Text(
30+
"B.play Homeaaaa Speaker ",
31+
style: TextStyle(
32+
fontSize: 36,
33+
fontWeight: FontWeight.w700,
34+
fontFamily: "Poppins",
35+
),
36+
),
37+
),
38+
Positioned(
39+
left: 0,
40+
top: 0,
41+
child: Text(
42+
"SPEAKERS",
43+
style: TextStyle(
44+
fontSize: 14,
45+
fontWeight: FontWeight.w500,
46+
fontFamily: "Poppins",
47+
),
48+
),
49+
),
50+
51+
/// stack requires empty non positioned widget to work properly. refer: https://github.com/flutter/flutter/issues/49631#issuecomment-582090992
52+
Container(),
53+
],
54+
),
55+
),
56+
57+
/// stack requires empty non positioned widget to work properly. refer: https://github.com/flutter/flutter/issues/49631#issuecomment-582090992
58+
Container(),
59+
],
60+
);
61+
```
62+
63+
Tobe
64+
65+
```dart
66+
Stack(
67+
children: [
68+
Positioned(
69+
left: 795,
70+
top: 163,
71+
child: Container(
72+
width: MediaQuery.of(context).width, /// <-----------
73+
height: MediaQuery.of(context).height, /// <-----------
74+
child: Stack(
75+
children: [
76+
Positioned(
77+
left: 0,
78+
top: 83,
79+
child: Text(
80+
"BeoPlay S3 draws heavily on geometry as a design reference. But also, it is reminiscent from the lines of two shapes embracing each other.",
81+
style: TextStyle(
82+
fontSize: 18,
83+
fontWeight: FontWeight.w400,
84+
fontFamily: "Roboto",
85+
),
86+
),
87+
),
88+
Positioned(
89+
left: 0,
90+
top: 23,
91+
child: Text(
92+
"B.play Homeaaaa Speaker ",
93+
style: TextStyle(
94+
fontSize: 36,
95+
fontWeight: FontWeight.w700,
96+
fontFamily: "Poppins",
97+
),
98+
),
99+
),
100+
Positioned(
101+
left: 0,
102+
top: 0,
103+
child: Text(
104+
"SPEAKERS",
105+
style: TextStyle(
106+
fontSize: 14,
107+
fontWeight: FontWeight.w500,
108+
fontFamily: "Poppins",
109+
),
110+
),
111+
),
112+
113+
/// stack requires empty non positioned widget to work properly. refer: https://github.com/flutter/flutter/issues/49631#issuecomment-582090992
114+
Container(),
115+
],
116+
),
117+
),
118+
),
119+
120+
/// stack requires empty non positioned widget to work properly. refer: https://github.com/flutter/flutter/issues/49631#issuecomment-582090992
121+
Container(),
122+
],
123+
);
124+
```
125+
126+
- https://stackoverflow.com/a/52936983/5463235

0 commit comments

Comments
 (0)