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

Add mock preview support for extensions #3200

Open
wants to merge 35 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
8923496
chore: add wrapper for `DedicatedWorker`
shreyashsaitwal Jun 17, 2024
4d66526
chore: add ability to pack mock scripts with extensions
shreyashsaitwal Jun 17, 2024
16d6b16
chore: add test mock for visible extensions
shreyashsaitwal Jun 17, 2024
6e33fb8
chore(poc): add `Blob` and `URL` JS types
shreyashsaitwal Jun 24, 2024
3bbdf27
chore(poc): enhance `Worker`'s API
shreyashsaitwal Jun 24, 2024
bfa71f7
chore(poc): very bare, unsafe POC implementation
shreyashsaitwal Jun 24, 2024
ede08cb
refactor: move JS interop code to `jstypes` subpackage
shreyashsaitwal Jul 15, 2024
757bff0
chore: add `DOMPurify` and `linkedom` JS libs
shreyashsaitwal Jul 15, 2024
450185c
chore: change worker type to `module`
shreyashsaitwal Jul 17, 2024
3269f99
chore: perform sanitization of mock & initiate mocks API impl
shreyashsaitwal Jul 21, 2024
8c547c3
fix: fix unexpected type coercion (by linter)
shreyashsaitwal Jul 21, 2024
2728dd7
chore: update minified linkedom and rm non-minified version
shreyashsaitwal Jul 21, 2024
eb2138f
chore: revoke worker URL after component deletion
shreyashsaitwal Jul 21, 2024
b0c88c0
chore: add support for getting initial properties in template
shreyashsaitwal Jul 21, 2024
ea3cd91
chore: remove duplicate condition in `SimpleComponentDescriptor`
shreyashsaitwal Jul 21, 2024
3fac567
chore: render the mock inside Shadow DOM
shreyashsaitwal Jul 28, 2024
b5176e0
chore: give property values relevant types before posting to worker
shreyashsaitwal Aug 5, 2024
a1efb86
chore: handle typefaces correctly
shreyashsaitwal Aug 5, 2024
c6fe9c1
chore: use JSONObject to pass `initialProperties`
shreyashsaitwal Aug 11, 2024
02df289
fix: don't initialize component mock to get its icon image
shreyashsaitwal Aug 11, 2024
b4d121d
chore: initialize worker in the mock constructor
shreyashsaitwal Aug 11, 2024
5bce842
fix: passing numeric values to worker caused unnecessary object nesting
shreyashsaitwal Aug 13, 2024
91f95a9
Merge branch 'mit-cml:master' into gsoc/develop
shreyashsaitwal Aug 13, 2024
31cada5
chore: handle upgradation of extensions
shreyashsaitwal Aug 13, 2024
a872b88
chore: refresh form after initializing the worker
shreyashsaitwal Aug 14, 2024
715a0c1
chore: post render requests from worker as objects
shreyashsaitwal Aug 14, 2024
2f141e4
chore: add external css support
shreyashsaitwal Aug 16, 2024
6e995d7
chore: store mock file names in component.json
shreyashsaitwal Aug 16, 2024
a8aab6f
chore: add `onError` event to `Mock`
shreyashsaitwal Aug 16, 2024
e93a780
refactor: clean up the code
shreyashsaitwal Aug 17, 2024
dee4817
chore: suggestions
shreyashsaitwal Aug 19, 2024
7e1c92a
fix: update `MockInfo` after extension upgrade
shreyashsaitwal Aug 19, 2024
fc9a879
chore: show error in designer and console if mock can't be rendered
shreyashsaitwal Sep 16, 2024
f4a0b43
chore: better error when mock script is missing
shreyashsaitwal Sep 16, 2024
563e599
fix: fix shifting of mock when selected & hide overflow
shreyashsaitwal Sep 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions appinventor/appengine/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@
<include name="closure-library/closure/goog/css/dialog.css"/>
<include name="closure-library/closure/goog/css/hsvapalette.css"/>
<include name="closure-library/closure/goog/deps.js"/>
<!-- include the DOMPurify lib used for sanitizing HTML of extension mocks -->
<include name="dompurify/purify.min.js" />
<!-- include the linkedom lib used for supporting DOM manipulation of mocks -->
<include name="linkedom/linkedom.min.js" />
</fileset>
<fileset dir="${docs.dir}/html/static">
<include name="js/*"/>
Expand Down Expand Up @@ -633,6 +637,7 @@
<arg value="-extra"/>
<arg value="${build.extra.dir}"/>
<arg line="${client.flags} ${client.module}"/>
<arg line="-generateJsInteropExports"/>
shreyashsaitwal marked this conversation as resolved.
Show resolved Hide resolved
</java>
<copy todir="${build.war.dir}/ode"
file="${appinventor.dir}/appengine/extra/cdnok.js" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,15 @@ public String getTypeDescription(String componentName) {
return component.getTypeDescription();
}

@Override
public MockInfo getMockInfo(String componentName) {
final ComponentDefinition component = components.get(componentName);
if (component == null) {
throw new ComponentNotFoundException(componentName);
}
return component.getMockInfo();
}

public String getComponentsJSONString() {
return componentsJSONString;
}
Expand All @@ -339,6 +348,17 @@ private boolean initComponent(JSONObject componentNode) {
// This must be a component upgrade! We remove existing entry
components.remove(name);
}
final MockInfo mockInfo;
if (properties.get("mock") != null) {
final JSONObject obj = properties.get("mock").asObject();
final JSONValue css = obj.get("css");
mockInfo =
new MockInfo(
obj.get("script").asString().getString(),
css != null ? css.asString().getString() : null);
} else {
mockInfo = null;
}
ComponentDefinition component = new ComponentDefinition(name,
Integer.parseInt(properties.get("version").asString().getString()),
optString(properties.get("versionName"), ""),
Expand All @@ -352,7 +372,9 @@ private boolean initComponent(JSONObject componentNode) {
Boolean.valueOf(properties.get("nonVisible").asString().getString()),
properties.get("iconName").asString().getString(),
properties.containsKey("licenseName") ? properties.get("licenseName").asString().getString() : "",
componentNode.toJson());
componentNode.toJson(),
mockInfo
);
findComponentProperties(component, properties.get("properties").asArray(),
properties.get("blockProperties").asArray());
findComponentBlockProperties(component, properties.get("blockProperties").asArray());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ private void setFontTypefaceProperty(String text) {
*/
private void setImageProperty(String text) {
imagePropValue = text;
String url = convertImagePropertyValueToUrl(text);
String url = MockComponentsUtil.convertAssetValueToUrl(editor, text);
shreyashsaitwal marked this conversation as resolved.
Show resolved Hide resolved
if (url == null) {
hasImage = false;
url = "";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ private void setBackgroundColorProperty(String text) {
* Sets the canvas's BackgroundImage property to a new value.
*/
private void setBackgroundImageProperty(String text) {
String url = convertImagePropertyValueToUrl(text);
String url = MockComponentsUtil.convertAssetValueToUrl(editor, text);

// We tell the layout (which is a MockCanvasLayout) that there is (or is not) a background
// image so it can adjust the "layout width/height". The "layout width/height" is used when the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import com.google.appinventor.client.editor.youngandroid.YaBlocksEditor;
import com.google.appinventor.client.editor.youngandroid.YaFormEditor;
import com.google.appinventor.client.explorer.SourceStructureExplorerItem;
import com.google.appinventor.client.explorer.project.Project;
import com.google.appinventor.client.widgets.ClonedWidget;
import com.google.appinventor.client.widgets.LabeledTextBox;
import com.google.appinventor.client.widgets.dnd.DragSource;
Expand All @@ -30,11 +29,6 @@
import com.google.appinventor.client.widgets.properties.StringPropertyEditor;
import com.google.appinventor.client.widgets.properties.TextPropertyEditor;
import com.google.appinventor.client.youngandroid.TextValidators;
import com.google.appinventor.shared.rpc.project.HasAssetsFolder;
import com.google.appinventor.shared.rpc.project.ProjectNode;
import com.google.appinventor.shared.rpc.project.youngandroid.YoungAndroidAssetsFolder;
import com.google.appinventor.shared.rpc.project.youngandroid.YoungAndroidProjectNode;
import com.google.appinventor.shared.storage.StorageUtil;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
Expand Down Expand Up @@ -855,41 +849,6 @@ public final SourceStructureExplorerItem getSourceStructureExplorerItem() {
return sourceStructureExplorerItem;
}

/**
* Returns the asset node with the given name.
*
* @param name asset name
* @return asset node found or {@code null}
*/
protected ProjectNode getAssetNode(String name) {
Project project = Ode.getInstance().getProjectManager().getProject(editor.getProjectId());
if (project != null) {
HasAssetsFolder<YoungAndroidAssetsFolder> hasAssetsFolder =
(YoungAndroidProjectNode) project.getRootNode();
for (ProjectNode asset : hasAssetsFolder.getAssetsFolder().getChildren()) {
if (asset.getName().equals(name)) {
return asset;
}
}
}
return null;
}

/**
* Converts the given image property value to an image url.
* Returns null if the image property value is blank or not recognized as an
* asset.
*/
protected String convertImagePropertyValueToUrl(String text) {
shreyashsaitwal marked this conversation as resolved.
Show resolved Hide resolved
if (text.length() > 0) {
ProjectNode asset = getAssetNode(text);
if (asset != null) {
return StorageUtil.getFileUrl(asset.getProjectId(), asset.getFileId());
}
}
return null;
}

// For debugging purposes only
private String describeElement(com.google.gwt.dom.client.Element element) {
if (element == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,17 +198,18 @@ static ProjectNode getAssetNode(SimpleEditor editor, String name) {
}
return null;
}

/**
* Converts the given font typeface property value to font resource URL
* Converts the given asset name to a file URL. Returns null if the name is
* blank or not recognized as an asset.
*
* @param editor the editor
* @param text asset name
* @param name asset name
* @return the string value of font resource URL
*/
static String convertFontPropertyValueToUrl(SimpleEditor editor, String text) {
if (text.length() > 0) {
ProjectNode asset = getAssetNode(editor, text);
static String convertAssetValueToUrl(SimpleEditor editor, String name) {
if (!name.isEmpty()) {
ProjectNode asset = getAssetNode(editor, name);
if (asset != null) {
return StorageUtil.getFileUrl(asset.getProjectId(), asset.getFileId());
}
Expand Down Expand Up @@ -254,7 +255,7 @@ static void setWidgetFontTypeface(SimpleEditor editor, Widget widget, String typ
} else {
fontFamily = typeface.substring(0, typeface.lastIndexOf("."));
String resourceID = typeface.toLowerCase().substring(0, typeface.lastIndexOf("."));
String resourceURL = convertFontPropertyValueToUrl(editor, typeface);
String resourceURL = convertAssetValueToUrl(editor, typeface);
if (Document.get().getElementById(resourceID) == null) {
createFontResource(fontFamily, resourceURL, resourceID);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,7 @@ private void setBackgroundColorProperty(String text) {
* Sets the form's BackgroundImage property to a new value.
*/
private void setBackgroundImageProperty(String text) {
String url = convertImagePropertyValueToUrl(text);
String url = MockComponentsUtil.convertAssetValueToUrl(editor, text);
if (url == null) {
// text was not recognized as an asset.
url = "";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ private void adjustAlignmentDropdowns() {
*/
private void setImageProperty(String text) {
imagePropValue = text;
String url = convertImagePropertyValueToUrl(text);
String url = MockComponentsUtil.convertAssetValueToUrl(editor, text);
if (url == null) {
hasImage = false;
url = "";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public void onLoad(LoadEvent event) {
*/
private void setPictureProperty(String text) {
picturePropValue = text;
String url = convertImagePropertyValueToUrl(text);
String url = MockComponentsUtil.convertAssetValueToUrl(editor, text);
if (url == null) {
// text was not recognized as an asset. Just display the icon for this type of component.
image.setUrl(getIconImage().getUrl());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ private void createLabelItem(List<JSONObject> arrayList) {
*/
private Image createImage(String imageName, String widthValue, String heightValue) {
Image image = new Image();
String url = convertImagePropertyValueToUrl(imageName);
String url = MockComponentsUtil.convertAssetValueToUrl(editor, imageName);
if (url == null) {
// text was not recognized as an asset. Just display the icon for this type of component.
image.setUrl(getIconImage().getUrl());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ public void onSuccess(List<FileDescriptorWithContent> arg0) {
});
} else {
svgContent = null;
String url = convertImagePropertyValueToUrl(assetPath);
String url = MockComponentsUtil.convertAssetValueToUrl(editor, assetPath);
if (url != null) {
setMarkerAssetUrl(url);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ public abstract class MockVisibleComponent extends MockComponent {
super(editor, type, new Image(icon));
}

MockVisibleComponent(SimpleEditor editor, String type, Image icon) {
super(editor, type, icon);
}

@Override
public final void initComponent(Widget widget) {
super.initComponent(widget);
Expand Down
Loading