Unverified Commit 0c69abc1 authored by SusanRatiLane's avatar SusanRatiLane Committed by Jeffrey I. Schiller

Add Send To Gallery button to designer toolbar template

Also fix the code to properly detect extensions in candidate projects
to be published and refuse to publish them (MIT Policy on non-source
code in the Gallery).

Change-Id: Iecefdba61a988dd9a6de666b5e2825d500db1ba1
parent 0b42cb2a
......@@ -25,40 +25,53 @@ public class SendToGalleryAction implements Command {
@Override
public void execute() {
if (lockPublishButton) {
return; // De-bounce the publish button
}
if (Ode.getInstance().getCurrentView() == Ode.PROJECTS) {
List<Project> selectedProjects =
ProjectListBox.getProjectListBox().getProjectList().getSelectedProjects();
if (selectedProjects.size() != 1) {
ErrorReporter.reportInfo(MESSAGES.selectOnlyOneProject());
} else {
if (!lockPublishButton) {
if (Ode.getInstance().getCurrentYoungAndroidProjectRootNode().hasExtensions()) {
lockPublishButton = false;
return;
}
Project project = selectedProjects.get(0);
sendToGallery(project);
} else {
if (Ode.getInstance().getCurrentYoungAndroidProjectRootNode().hasExtensions()) {
ErrorReporter.reportError(MESSAGES.HasExtensionError());
lockPublishButton = false;
return;
}
Project project = Ode.getCurrentProject();
sendToGallery(project);
}
}
private void sendToGallery(Project project) {
lockPublishButton = true;
Ode.getInstance().getProjectService().sendToGallery(project.getProjectId(),
new OdeAsyncCallback<RpcResult>(
MESSAGES.GallerySendingError()) {
@Override
public void onSuccess(RpcResult result) {
lockPublishButton = false;
if (result.getResult() == RpcResult.SUCCESS) {
Window.open(result.getOutput(), "_blank", "");
} else if (result.getResult() == RpcResult.GALLERY_HAS_EXTENSION) {
ErrorReporter.reportError(MESSAGES.HasExtensionError());
return;
} else {
ErrorReporter.reportError(result.getError());
}
lockPublishButton = true;
Project project = selectedProjects.get(0);
Ode.getInstance().getProjectService().sendToGallery(project.getProjectId(),
new OdeAsyncCallback<RpcResult>(
MESSAGES.GallerySendingError()) {
@Override
public void onSuccess(RpcResult result) {
lockPublishButton = false;
if (result.getResult() == RpcResult.SUCCESS) {
Window.open(result.getOutput(), "_blank", "");
} else {
ErrorReporter.reportError(result.getError());
}
}
}
@Override
public void onFailure(Throwable t) {
lockPublishButton = false;
super.onFailure(t);
}
});
@Override
public void onFailure(Throwable t) {
lockPublishButton = false;
super.onFailure(t);
}
}
}
});
}
}
......@@ -10,7 +10,6 @@ import com.google.appinventor.client.ErrorReporter;
import com.google.appinventor.client.Ode;
import com.google.appinventor.client.editor.FileEditor;
import com.google.appinventor.client.editor.ProjectEditor;
import com.google.appinventor.client.editor.youngandroid.actions.SendToGalleryAction;
import com.google.appinventor.client.editor.youngandroid.actions.SwitchScreenAction;
import com.google.appinventor.client.widgets.DropDownButton;
import com.google.appinventor.client.widgets.DropDownItem;
......@@ -40,9 +39,6 @@ import static com.google.appinventor.client.Ode.MESSAGES;
public class DesignToolbar extends Toolbar {
private static final Logger LOG = Logger.getLogger(DesignToolbar.class.getName());
private volatile boolean lockPublishButton = false; // Used to prevent double-clicking the
// SendToGallery button
/*
* A Screen groups together the form editor and blocks editor for an
* application screen. Name is the name of the screen (form) displayed
......@@ -145,6 +141,7 @@ public class DesignToolbar extends Toolbar {
@UiField ToolbarItem removeFormItem;
@UiField ToolbarItem switchToDesign;
@UiField ToolbarItem switchToBlocks;
@UiField ToolbarItem sendToGalleryItem;
@UiField ToolbarItem projectPropertiesDialog;
/**
......@@ -158,18 +155,9 @@ public class DesignToolbar extends Toolbar {
setVisibleItem(addFormItem, false);
setVisibleItem(removeFormItem, false);
}
// Is the Gallery Enabled (new gallery)?
if (Ode.getSystemConfig().getGalleryEnabled() && !Ode.getInstance().getGalleryReadOnly()) {
add(new ToolbarItem(WIDGET_NAME_SENDTOGALLERY,
MESSAGES.publishToGalleryButton(), new SendToGalleryAction(() -> {
if (!lockPublishButton) {
lockPublishButton = true;
return true;
}
return false;
}, () -> lockPublishButton = false)));
}
setVisibleItem(sendToGalleryItem, Ode.getSystemConfig().getGalleryEnabled()
&& !Ode.getInstance().getGalleryReadOnly());
// Gray out the Designer button and enable the blocks button
toggleEditor(false);
......
......@@ -7,6 +7,7 @@
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:ai="urn:import:com.google.appinventor.client.widgets"
xmlns:ya="urn:import:com.google.appinventor.client.editor.youngandroid.actions"
xmlns:actions="urn:import:com.google.appinventor.client.actions"
ui:generatedFormat="com.google.gwt.i18n.server.PropertyCatalogFactory"
ui:generatedKeys="com.google.gwt.i18n.server.keygen.MethodNameKeyGenerator"
ui:generateLocales="default">
......@@ -27,13 +28,17 @@
<ya:AddFormAction />
</ai:ToolbarItem>
<ai:ToolbarItem name="RemoveForm" caption="{messages.removeFormButton}" ui:field="removeFormItem"
align="center">
align="center">
<ya:RemoveFormAction />
</ai:ToolbarItem>
<ai:ToolbarItem name="ProjectPropertiesDialog" caption="{messages.projectPropertiesText}" ui:field="projectPropertiesDialog"
align="center">
<ya:ProjectPropertiesAction />
</ai:ToolbarItem>
<ai:ToolbarItem name="Gallery" caption="{messages.publishToGalleryButton}"
ui:field="sendToGalleryItem" align="center">
<actions:SendToGalleryAction />
</ai:ToolbarItem>
<ai:ToolbarItem name="switchToDesign" caption="{messages.switchToFormEditorButton}"
ui:field="switchToDesign" align="right">
<ya:SwitchToFormEditorAction />
......
// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2020-2023 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
package com.google.appinventor.client.editor.youngandroid.actions;
import static com.google.appinventor.client.Ode.MESSAGES;
import com.google.appinventor.client.ErrorReporter;
import com.google.appinventor.client.Ode;
import com.google.appinventor.client.OdeAsyncCallback;
import com.google.appinventor.client.editor.youngandroid.DesignToolbar;
import com.google.appinventor.shared.rpc.RpcResult;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;
import java.util.concurrent.Callable;
import java.util.logging.Logger;
public class SendToGalleryAction implements Command {
private static final Logger LOG = Logger.getLogger(SendToGalleryAction.class.getName());
private final Callable<Boolean> before;
private final Runnable after;
public SendToGalleryAction(Callable<Boolean> before, Runnable postCommand) {
this.before = before;
this.after = postCommand;
}
@Override
public void execute() {
final DesignToolbar toolbar = Ode.getInstance().getDesignToolbar();
if (toolbar.getCurrentProject() == null) {
LOG.warning("DesignToolbar.currentProject is null. "
+ "Ignoring SendToGalleryAction.execute().");
return;
}
if (Ode.getInstance().getCurrentYoungAndroidProjectRootNode().hasExtensions()) {
ErrorReporter.reportError(MESSAGES.HasExtensionError());
return;
}
boolean shouldRun;
try {
shouldRun = before.call();
} catch (Exception e) {
return;
}
if (shouldRun) {
Ode.getInstance().getProjectService().sendToGallery(toolbar.getCurrentProject().getProjectId(),
new OdeAsyncCallback<RpcResult>(
MESSAGES.GallerySendingError()) {
@Override
public void onSuccess(RpcResult result) {
after.run();
if (result.getResult() == RpcResult.SUCCESS) {
Window.open(result.getOutput(), "_blank", "");
} else {
ErrorReporter.reportError(result.getError());
}
}
@Override
public void onFailure(Throwable t) {
after.run();
super.onFailure(t);
}
});
}
}
}
// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2023 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
package com.google.appinventor.server;
import java.io.IOException;
/**
* Thrown by StorageIo modules when an extension
* is detected in a project.
*
* @author jis@mit.edu (Jeffrey I. Schiller)
*/
public final class GalleryExtensionException extends IOException {
/**
* Creates a GalleryExtentionException
*
*/
public GalleryExtensionException() {
super();
}
}
......@@ -17,6 +17,7 @@ import com.google.appinventor.server.FileExporterImpl;
import com.google.appinventor.server.FileImporter;
import com.google.appinventor.server.FileImporterException;
import com.google.appinventor.server.FileImporterImpl;
import com.google.appinventor.server.GalleryExtensionException;
import com.google.appinventor.server.Server;
import com.google.appinventor.server.encryption.EncryptionException;
import com.google.appinventor.server.flags.Flag;
......@@ -690,6 +691,8 @@ public final class YoungAndroidProjectService extends CommonProjectService {
String returl = readContent(connection.getInputStream()); // Need to drain any response
return new RpcResult(0, returl, "");
}
} catch (GalleryExtensionException e) {
return new RpcResult(RpcResult.GALLERY_HAS_EXTENSION, "", "");
} catch (Exception e) {
throw CrashReport.createAndLogError(LOG, null, e.getMessage(), e);
}
......
......@@ -23,6 +23,7 @@ import com.google.appengine.api.taskqueue.TaskOptions;
import com.google.apphosting.api.ApiProxy;
import com.google.appinventor.server.CrashReport;
import com.google.appinventor.server.FileExporter;
import com.google.appinventor.server.GalleryExtensionException;
import com.google.appinventor.server.Server;
import com.google.appinventor.server.flags.Flag;
import com.google.appinventor.server.storage.StoredData.AllowedTutorialUrls;
......@@ -1809,7 +1810,7 @@ public class ObjectifyStorageIo implements StorageIo {
FileData fd = it.next();
String fileName = fd.fileName;
if (fileName.startsWith("assets/external_comps") && forGallery) {
throw new IOException("FATAL Error, external component in gallery app");
throw new GalleryExtensionException();
}
if (!fd.role.equals(FileData.RoleEnum.SOURCE)) {
it.remove();
......
......@@ -35,6 +35,7 @@ public class RpcResult implements IsSerializable {
* other value indicates failure.
*/
public static final int SUCCESS = 0;
public static final int GALLERY_HAS_EXTENSION = -20;
private int result;
private String output;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment