Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
ddaea31
WIP: Add global asset management functionality
lakshyashishir Jun 11, 2025
8374bd4
feat: add global asset upload support with UI and backend integration
lakshyashishir Jun 25, 2025
22e2cbd
feat: add global asset linking, sync indicators, and enhanced UI comp…
lakshyashishir Jul 5, 2025
db6813c
feat: integrate Asset Library UI and backend enhancements for improve…
lakshyashishir Aug 6, 2025
dc48841
Remove redundant GlobalAssetServiceAsync interface
lakshyashishir Aug 13, 2025
15ea182
Merge asset-library branch with master
lakshyashishir Aug 13, 2025
887e489
Make global assets use GCS consistently
lakshyashishir Aug 20, 2025
aaa7b38
Implement asset conflict detection and resolution features
lakshyashishir Aug 27, 2025
47374df
Merge upstream/master - resolve conflicts
lakshyashishir Aug 28, 2025
97b8b0f
WIP: asset library fixes - companion shows error after successful dow…
lakshyashishir Aug 29, 2025
98af6b6
Fix asset library refresh and preview issues
lakshyashishir Aug 30, 2025
b711679
Implement folder rename and delete operations with assets
lakshyashishir Aug 30, 2025
1663888
Fix asset library dialog success feedback
lakshyashishir Aug 30, 2025
6ad332d
Fix asset library error handling and designer preview cache issues
lakshyashishir Sep 1, 2025
25f2c6e
Improve Classic & Neo UI with refined layout and styles
lakshyashishir Sep 2, 2025
cdfb2e9
WIP: Fix double assets path issue in companion app
lakshyashishir Sep 3, 2025
a23e4d0
Fix double assets path
lakshyashishir Sep 4, 2025
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
10 changes: 10 additions & 0 deletions appinventor/appengine/src/com/google/appinventor/YaClient.gwt.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<inherits name="com.google.gwt.query.Query" />
<inherits name="org.pepstock.charba.Charba"/>
<inherits name="com.google.gwt.xml.XML" />
<inherits name="com.google.appinventor.client.assetlibrary.AssetLibrary" />

<set-property name="gwt.logging.logLevel" value="INFO"/>
<set-property name="gwt.logging.enabled" value="TRUE"/>
Expand All @@ -45,6 +46,7 @@
<servlet path="/projects" class="com.google.appinventor.server.ProjectServiceImpl" />
<servlet path="/upload" class="com.google.appinventor.server.UploadServlet" />
<servlet path="/userinfo" class="com.google.appinventor.server.UserInfoServiceImpl" />
<servlet path="/globalassets" class="com.google.appinventor.server.GlobalAssetServiceImpl" />

<!-- srcs -->
<source path="" includes="simple_components.json" />
Expand Down Expand Up @@ -93,6 +95,8 @@
<source path="shared/rpc/project"/>
<source path="shared/rpc/user"/>
<source path="shared/rpc/project/youngandroid"/>
<source path="shared/rpc/globalasset"/>
<source path="shared/rpc/globalasset"/>

<!-- extra_module_contents -->

Expand All @@ -110,6 +114,12 @@
<when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService" />
</generate-with>

<!--
<generate-with class="com.google.gwt.user.client.rpc.RemoteServiceProxyGenerator">
<when-type-assignable class="com.google.appinventor.shared.rpc.globalasset.GlobalAssetService" />
</generate-with>
-->

<replace-with class="com.google.appinventor.client.utils.FocusImplStandard">
<when-type-is class="com.google.gwt.user.client.ui.impl.FocusImpl"/>
<when-property-is name="user.agent" value="gecko1_8"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -834,4 +834,16 @@ public interface Images extends Resources {
*/
@Source("com/google/appinventor/images/trendline.png")
ImageResource trendline();

/**
* Generic file icon for assets that are not images, audio, or video.
*/
@Source("com/google/appinventor/images/file.png")
ImageResource fileIcon();

/**
* Sync icon for updated global assets.
*/
@Source("com/google/appinventor/images/syncIcon.png")
ImageResource syncIcon();
}
39 changes: 39 additions & 0 deletions appinventor/appengine/src/com/google/appinventor/client/Ode.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.google.appinventor.client.editor.youngandroid.TutorialPanel;
import com.google.appinventor.client.editor.youngandroid.YaFormEditor;
import com.google.appinventor.client.editor.youngandroid.YaProjectEditor;
import com.google.appinventor.client.editor.youngandroid.AssetManagerPanel;
import com.google.appinventor.client.editor.youngandroid.YaVisibleComponentsPanel;
import com.google.appinventor.client.explorer.commands.ChainableCommand;
import com.google.appinventor.client.explorer.commands.CommandRegistry;
Expand Down Expand Up @@ -96,6 +97,7 @@
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiFactory;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Event.NativePreviewEvent;
Expand Down Expand Up @@ -227,6 +229,7 @@ public class Ode implements EntryPoint {
private int projectsTabIndex;
private int designTabIndex;
private int debuggingTabIndex;
private int assetLibraryTabIndex;
private int userAdminTabIndex;
@UiField protected TopPanel topPanel;
@UiField protected StatusPanel statusPanel;
Expand All @@ -238,6 +241,21 @@ public class Ode implements EntryPoint {
@UiField (provided = true) protected PaletteBox paletteBox = PaletteBox.getPaletteBox();
@UiField (provided = true) protected ViewerBox viewerBox = ViewerBox.getViewerBox();
@UiField (provided = true) protected AssetListBox assetListBox = AssetListBox.getAssetListBox();
// @UiField protected AssetManagerPanel assetManagerPanel;

// public AssetManagerPanel getAssetManagerPanel() {
// return assetManagerPanel;
// }

@UiFactory
public com.google.appinventor.client.assetlibrary.AssetLibraryWidget createAssetLibraryWidget() {
return new com.google.appinventor.client.assetlibrary.AssetLibraryWidget(this);
}

@UiFactory
public com.google.appinventor.client.assetlibrary.AssetLibraryWidgetClassic createAssetLibraryWidgetClassic() {
return new com.google.appinventor.client.assetlibrary.AssetLibraryWidgetClassic(this);
}
@UiField (provided = true) protected SourceStructureBox sourceStructureBox;
@UiField (provided = true) protected PropertiesBox propertiesBox = PropertiesBox.getPropertiesBox();

Expand Down Expand Up @@ -387,6 +405,15 @@ public AssetManager getAssetManager() {
return assetManager;
}

/**
* Returns the asset list box.
*
* @return asset list box
*/
public AssetListBox getAssetListBox() {
return assetListBox;
}

/**
* Returns true if we have received the window closing event.
*/
Expand Down Expand Up @@ -529,6 +556,15 @@ public void switchToDebuggingView() {
resizeWorkArea((WorkAreaPanel) deckPanel.getWidget(debuggingTabIndex));
}

/**
* Switch to the Asset Library tab
*/
public void switchToAssetLibraryView() {
hideChaff();
hideTutorials();
deckPanel.showWidget(assetLibraryTabIndex);
}

/**
* Processes the template and galleryId flags.
*
Expand Down Expand Up @@ -1049,6 +1085,9 @@ public final void onBrowserEvent(Event event) {
// Debugging Panel
debuggingTabIndex = 3;

// Asset Library Panel
assetLibraryTabIndex = 4;

RootPanel.get().add(mainPanel);

// Add a handler to the RootPanel to keep track of Google Chrome Pinch Zooming and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
xmlns:ex="urn:import:com.google.appinventor.client.explorer.youngandroid"
xmlns:ode="urn:import:com.google.appinventor.client"
xmlns:box="urn:import:com.google.appinventor.client.boxes"
xmlns:assetlib="urn:import:com.google.appinventor.client.assetlibrary"
ui:generatedFormat="com.google.gwt.i18n.server.PropertyCatalogFactory"
ui:generatedKeys="com.google.gwt.i18n.server.keygen.MethodNameKeyGenerator"
ui:generateLocales="default">
Expand Down Expand Up @@ -39,6 +40,10 @@
<g:FlowPanel width="100%">
<box:AdminUserListBox />
</g:FlowPanel>
<g:FlowPanel width="100%" />
<g:FlowPanel>
<assetlib:AssetLibraryWidgetClassic />
</g:FlowPanel>
</g:DeckPanel>
</g:FlowPanel>
<ode:StatusPanel ui:field="statusPanel" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,44 @@ public interface OdeMessages extends Messages, ComponentTranslations {
@Description("Text on Toggle Warning Button")
String hideWarnings();

@DefaultMessage("Upload File ...")
@Description("Text on \"Add...\" button")
String addButton();
@DefaultMessage("Upload File ...") @Description("Text on \"Add...\" button") String addButton(); @DefaultMessage("Preview") @Description("Text on \"Preview\" button") String previewButton(); @DefaultMessage("Download") @Description("Text on \"Download\" button") String downloadButton(); @DefaultMessage("Link to Project")
@Description("Text for button to link a global asset to the current project")
String linkToProjectButton();

@DefaultMessage("Error linking global asset to project.")
@Description("Error message when linking global asset to project fails")
String linkGlobalAssetError();

@DefaultMessage("Global asset ''{0}'' linked successfully to project.")
@Description("Success message when a global asset is linked to a project")
String globalAssetLinked(String assetName);

@DefaultMessage("No project is currently open. Please open a project to link global assets.")
@Description("Warning message when trying to link a global asset without an open project")
String noProjectOpenForLinking();

@DefaultMessage("Global Asset Update")
@Description("Title for the global asset update dialog")
String globalAssetUpdateDialogTitle();

@DefaultMessage("The global asset \"{0}\" has been updated.\n\n" +
"Current version timestamp: {1}\n" +
"New version timestamp: {2}\n\n" +
"Do you want to update this asset in your project?")
@Description("Message for the global asset update dialog")
String globalAssetUpdateMessage(String fileName, String oldTimestamp, String newTimestamp);

@DefaultMessage("Error updating global asset in project.")
@Description("Error message when updating global asset in project fails")
String globalAssetUpdateError();

@DefaultMessage("Global asset \"{0}\" updated successfully.")
@Description("Success message when a global asset is updated in the project")
String globalAssetUpdatedSuccessfully(String fileName);

@DefaultMessage("Error checking for global asset updates.")
@Description("Error message when checking for global asset updates fails")
String errorCheckingGlobalAssetUpdate();

@DefaultMessage("Name")
@Description("Header for name column of project table")
Expand Down Expand Up @@ -539,6 +574,10 @@ public interface OdeMessages extends Messages, ComponentTranslations {
@Description("Name of Import Template menuitem")
String importTemplateButton();

@DefaultMessage("Asset Library")
@Description("Name of Asset Library menuitem")
String assetLibraryMenuItem();

@DefaultMessage("Export selected project (.aia) to my computer")
@Description("Name of Export Project menuitem")
String exportProjectMenuItem();
Expand Down Expand Up @@ -5823,4 +5862,120 @@ String newerVersionComponentException(String componentType, int srcCompVersion,
@DefaultMessage("Welcome to App Inventor Neo! If you are looking for the classic App Inventor look, you can switch in the User Interface Settings, or <a href=\"\">click here</a>.")
@Description("Message shown in the info popup when the user first opens the Neo UI.")
String neoWelcomeMessage();

@DefaultMessage("Asset Manager")
@Description("Title for the Asset Manager panel")
String assetManagerTitle();

@DefaultMessage("Upload Asset")
@Description("Text for the upload asset button")
String uploadAssetButton();

@DefaultMessage("Search Assets")
@Description("Placeholder text for asset search box")
String searchAssetsPlaceholder();

@DefaultMessage("Folders")
@Description("Title for the folders section")
String foldersSectionTitle();

@DefaultMessage("Tags")
@Description("Title for the tags section")
String tagsSectionTitle();

@DefaultMessage("Recent")
@Description("Title for the recent assets section")
String recentAssetsTitle();

@DefaultMessage("Drag and drop files here")
@Description("Text shown in the upload drop zone")
String dragDropText();

@DefaultMessage("or click to browse")
@Description("Text shown next to drag and drop message")
String clickToBrowseText();

@DefaultMessage("Preview")
@Description("Title for the asset preview panel")
String previewTitle();

@DefaultMessage("Properties")
@Description("Title for the asset properties panel")
String propertiesTitle();

@DefaultMessage("Name")
@Description("Label for asset name property")
String assetNameLabel();

@DefaultMessage("Type")
@Description("Label for asset type property")
String assetTypeLabel();

@DefaultMessage("Size")
@Description("Label for asset size property")
String assetSizeLabel();

@DefaultMessage("Date Added")
@Description("Label for asset date added property")
String assetDateAddedLabel();

@DefaultMessage("Tags")
@Description("Label for asset tags property")
String assetTagsLabel();

@DefaultMessage("Add to Project")
@Description("Text for the add to project button")
String addToProjectButton();

@DefaultMessage("Delete")
@Description("Text for the delete asset button")
String deleteAssetButton();

@DefaultMessage("Edit")
@Description("Text for the edit asset button")
String editAssetButton();

@DefaultMessage("Create Folder")
@Description("Text for the create folder button")
String createFolderButton();

@DefaultMessage("Add Tag")
@Description("Text for the add tag button")
String addTagButton();

@DefaultMessage("Filter by Type")
@Description("Label for the asset type filter")
String filterByTypeLabel();

@DefaultMessage("All Types")
@Description("Text for the all types filter option")
String allTypesFilter();

@DefaultMessage("Images")
@Description("Text for the images filter option")
String imagesFilter();

@DefaultMessage("Audio")
@Description("Text for the audio filter option")
String audioFilter();

@DefaultMessage("Video")
@Description("Text for the video filter option")
String videoFilter();

@DefaultMessage("Other")
@Description("Text for the other files filter option")
String otherFilter();

@DefaultMessage("Upload as Global Asset")
@Description("Label for the checkbox to upload as a global asset")
String uploadAsGlobalAssetCheckbox();

@DefaultMessage("Global Folder (optional)")
@Description("Placeholder for the global folder text box in asset upload")
String globalFolderPlaceholder();

@DefaultMessage("Error fetching global assets.")
@Description("Error message when fetching global assets fails")
String errorFetchingGlobalAssets();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
uploadAsGlobalAssetCheckbox=Upload as Global Asset
globalFolderPlaceholder=Global Folder (optional)
errorFetchingGlobalAssets=Error fetching global assets.
previewButton=Preview
downloadButton=Download
Loading