Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
appinventor-sources
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
xpstem
appinventor-sources
Commits
fc2a232c
Commit
fc2a232c
authored
May 10, 2016
by
Aaron Suarez
Committed by
Evan W. Patton
Sep 09, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add media preview
Change-Id: I6702e49a89777c1aa65c6a9fb766e0980d0fc380
parent
2961d7df
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
253 additions
and
2 deletions
+253
-2
appinventor/appengine/src/com/google/appinventor/client/Images.java
...r/appengine/src/com/google/appinventor/client/Images.java
+18
-0
appinventor/appengine/src/com/google/appinventor/client/OdeMessages.java
...engine/src/com/google/appinventor/client/OdeMessages.java
+16
-0
appinventor/appengine/src/com/google/appinventor/client/explorer/commands/CommandRegistry.java
...appinventor/client/explorer/commands/CommandRegistry.java
+2
-0
appinventor/appengine/src/com/google/appinventor/client/explorer/commands/PreviewFileCommand.java
...inventor/client/explorer/commands/PreviewFileCommand.java
+118
-0
appinventor/appengine/src/com/google/appinventor/client/explorer/youngandroid/AssetList.java
...e/appinventor/client/explorer/youngandroid/AssetList.java
+18
-2
appinventor/appengine/src/com/google/appinventor/client/tracking/Tracking.java
.../src/com/google/appinventor/client/tracking/Tracking.java
+2
-0
appinventor/appengine/src/com/google/appinventor/images/mediaIcon_audio.png
...ine/src/com/google/appinventor/images/mediaIcon_audio.png
+0
-0
appinventor/appengine/src/com/google/appinventor/images/mediaIcon_img.png
...ngine/src/com/google/appinventor/images/mediaIcon_img.png
+0
-0
appinventor/appengine/src/com/google/appinventor/images/mediaIcon_video.png
...ine/src/com/google/appinventor/images/mediaIcon_video.png
+0
-0
appinventor/appengine/src/com/google/appinventor/shared/storage/StorageUtil.java
...rc/com/google/appinventor/shared/storage/StorageUtil.java
+77
-0
appinventor/appengine/war/Ya.css
appinventor/appengine/war/Ya.css
+2
-0
No files found.
appinventor/appengine/src/com/google/appinventor/client/Images.java
View file @
fc2a232c
...
...
@@ -586,4 +586,22 @@ public interface Images extends Resources {
@Source
(
"com/google/appinventor/images/rectangle.png"
)
ImageResource
rectangle
();
/**
* Media icon: image
*/
@Source
(
"com/google/appinventor/images/mediaIcon_img.png"
)
ImageResource
mediaIconImg
();
/**
* Media icon: audio
*/
@Source
(
"com/google/appinventor/images/mediaIcon_audio.png"
)
ImageResource
mediaIconAudio
();
/**
* Media icon: video
*/
@Source
(
"com/google/appinventor/images/mediaIcon_video.png"
)
ImageResource
mediaIconVideo
();
}
appinventor/appengine/src/com/google/appinventor/client/OdeMessages.java
View file @
fc2a232c
...
...
@@ -1376,6 +1376,13 @@ public interface OdeMessages extends Messages, AutogeneratedOdeMessages {
String
errorGeneratingYail
(
String
formName
);
// Used in explorer/commands/CommandRegistory.java
@DefaultMessage
(
"Preview..."
)
@Description
(
"Label for the context menu command that previews a file"
)
String
previewFileCommand
();
@DefaultMessage
(
"Close Preview"
)
@Description
(
"Text for closing a file preview window"
)
String
closeFilePreview
();
@DefaultMessage
(
"Delete..."
)
@Description
(
"Label for the context menu command that deletes a file"
)
...
...
@@ -1385,6 +1392,15 @@ public interface OdeMessages extends Messages, AutogeneratedOdeMessages {
@Description
(
"Label for the context menu command that downloads a file"
)
String
downloadFileCommand
();
// Used in explore/commands/FilePreviewCommand.java
@DefaultMessage
(
"Unfortunately, a preview for this file is unavailable."
)
@Description
(
"Text for files not compatible with HTML5 elements"
)
String
filePreviewError
();
@DefaultMessage
(
"Unfortunately, your browser does not support playback of this file."
)
@Description
(
"Text for browsers not compatable with HTML5 elements"
)
String
filePlaybackError
();
// Used in explorer/commands/CopyYoungAndroidProjectCommand.java
@DefaultMessage
(
"Checkpoint - {0}"
)
...
...
appinventor/appengine/src/com/google/appinventor/client/explorer/commands/CommandRegistry.java
View file @
fc2a232c
...
...
@@ -64,6 +64,8 @@ public class CommandRegistry extends MultiRegistry<ProjectNode, CommandRegistry.
super
(
ProjectNode
.
class
);
// Files
registerCommand
(
FileNode
.
class
,
new
ProjectNodeCommand
(
MESSAGES
.
previewFileCommand
(),
Tracking
.
PROJECT_ACTION_PREVIEW_FILE_YA
,
new
PreviewFileCommand
()));
registerCommand
(
FileNode
.
class
,
new
ProjectNodeCommand
(
MESSAGES
.
deleteFileCommand
(),
Tracking
.
PROJECT_ACTION_DELETE_FILE_YA
,
new
DeleteFileCommand
()));
registerCommand
(
FileNode
.
class
,
new
ProjectNodeCommand
(
MESSAGES
.
downloadFileCommand
(),
...
...
appinventor/appengine/src/com/google/appinventor/client/explorer/commands/PreviewFileCommand.java
0 → 100644
View file @
fc2a232c
// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2016 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.explorer.commands
;
import
com.google.appinventor.shared.storage.StorageUtil
;
import
com.google.gwt.event.dom.client.ClickEvent
;
import
com.google.gwt.event.dom.client.ClickHandler
;
import
com.google.appinventor.shared.rpc.project.ProjectNode
;
import
com.google.gwt.user.client.ui.Button
;
import
com.google.gwt.user.client.ui.DialogBox
;
import
com.google.gwt.user.client.ui.HTML
;
import
com.google.gwt.user.client.ui.HorizontalPanel
;
import
com.google.gwt.user.client.ui.Image
;
import
com.google.gwt.user.client.ui.VerticalPanel
;
import
com.google.gwt.user.client.ui.Widget
;
import
static
com
.
google
.
appinventor
.
client
.
Ode
.
MESSAGES
;
/**
* Command for previewing files.
*
*/
public
class
PreviewFileCommand
extends
ChainableCommand
{
/**
* Creates a new command for previewing a file.
*/
public
PreviewFileCommand
()
{
super
(
null
);
// no next command
}
@Override
public
boolean
willCallExecuteNextCommand
()
{
return
false
;
}
@Override
public
void
execute
(
final
ProjectNode
node
)
{
final
DialogBox
dialogBox
=
new
DialogBox
();
dialogBox
.
setText
(
node
.
getName
());
dialogBox
.
setStylePrimaryName
(
"ode-DialogBox"
);
//setting position of dialog box
dialogBox
.
center
();
dialogBox
.
setAnimationEnabled
(
true
);
//button element
final
Button
closeButton
=
new
Button
(
MESSAGES
.
closeFilePreview
());
closeButton
.
getElement
().
setId
(
"closeButton"
);
closeButton
.
addClickHandler
(
new
ClickHandler
()
{
@Override
public
void
onClick
(
ClickEvent
event
)
{
dialogBox
.
hide
();
}
});
HorizontalPanel
buttonPanel
=
new
HorizontalPanel
();
buttonPanel
.
setHorizontalAlignment
(
HorizontalPanel
.
ALIGN_CENTER
);
buttonPanel
.
setVerticalAlignment
(
HorizontalPanel
.
ALIGN_MIDDLE
);
buttonPanel
.
add
(
closeButton
);
VerticalPanel
dialogPanel
=
new
VerticalPanel
();
dialogPanel
.
setHorizontalAlignment
(
VerticalPanel
.
ALIGN_CENTER
);
dialogPanel
.
setVerticalAlignment
(
VerticalPanel
.
ALIGN_MIDDLE
);
Widget
filePreview
=
generateFilePreview
(
node
);
dialogPanel
.
clear
();
dialogPanel
.
add
(
filePreview
);
dialogPanel
.
add
(
buttonPanel
);
dialogPanel
.
setWidth
(
"300px"
);
dialogBox
.
setGlassEnabled
(
false
);
dialogBox
.
setModal
(
false
);
// Set the contents of the Widget
dialogBox
.
setWidget
(
dialogPanel
);
dialogBox
.
center
();
dialogBox
.
show
();
}
/**
* Generate a file preview to display
*
* @param node
* @return widget
*/
private
Widget
generateFilePreview
(
ProjectNode
node
)
{
String
fileSuffix
=
node
.
getProjectId
()
+
"/"
+
node
.
getFileId
();
String
fileUrl
=
StorageUtil
.
getFileUrl
(
node
.
getProjectId
(),
node
.
getFileId
());
if
(
StorageUtil
.
isImageFile
(
fileSuffix
))
{
// Image Preview
String
fileType
=
StorageUtil
.
getContentTypeForFilePath
(
fileSuffix
);
// Support preview for file types that all major browser support
if
(
fileType
.
endsWith
(
"png"
)
||
fileType
.
endsWith
(
"jpeg"
)
||
fileType
.
endsWith
(
"gif"
)
||
fileType
.
endsWith
(
"bmp"
))
{
Image
img
=
new
Image
(
fileUrl
);
img
.
getElement
().
getStyle
().
setProperty
(
"maxWidth"
,
"600px"
);
return
img
;
}
}
else
if
(
StorageUtil
.
isAudioFile
(
fileSuffix
))
{
// Audio Preview
String
fileType
=
StorageUtil
.
getContentTypeForFilePath
(
fileSuffix
);
if
(
fileType
.
endsWith
(
"mp3"
)
||
fileType
.
endsWith
(
"wav"
)
||
fileType
.
endsWith
(
"ogg"
))
{
return
new
HTML
(
"<audio controls><source src='"
+
fileUrl
+
"' type='"
+
fileType
+
"'>"
+
MESSAGES
.
filePlaybackError
()
+
"</audio>"
);
}
}
else
if
(
StorageUtil
.
isVideoFile
(
fileSuffix
))
{
// Video Preview
String
fileType
=
StorageUtil
.
getContentTypeForFilePath
(
fileSuffix
);
if
(
fileType
.
endsWith
(
"mp4"
)
||
fileType
.
endsWith
(
"webm"
))
{
return
new
HTML
(
"<video width='320' height='240' controls> <source src='"
+
fileUrl
+
"' type='"
+
fileType
+
"'>"
+
MESSAGES
.
filePlaybackError
()
+
"</video>"
);
}
}
return
new
HTML
(
MESSAGES
.
filePreviewError
());
}
}
appinventor/appengine/src/com/google/appinventor/client/explorer/youngandroid/AssetList.java
View file @
fc2a232c
...
...
@@ -6,6 +6,7 @@
package
com.google.appinventor.client.explorer.youngandroid
;
import
com.google.appinventor.client.Images
;
import
com.google.appinventor.client.Ode
;
import
static
com
.
google
.
appinventor
.
client
.
Ode
.
MESSAGES
;
import
com.google.appinventor.client.explorer.project.Project
;
...
...
@@ -18,12 +19,14 @@ import com.google.appinventor.shared.rpc.project.ProjectNode;
import
com.google.appinventor.shared.rpc.project.youngandroid.YoungAndroidAssetNode
;
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.event.dom.client.ClickEvent
;
import
com.google.gwt.event.dom.client.ClickHandler
;
import
com.google.gwt.event.logical.shared.SelectionEvent
;
import
com.google.gwt.event.logical.shared.SelectionHandler
;
import
com.google.gwt.user.client.ui.Composite
;
import
com.google.gwt.user.client.ui.HTML
;
import
com.google.gwt.user.client.ui.Image
;
import
com.google.gwt.user.client.ui.SimplePanel
;
import
com.google.gwt.user.client.ui.Tree
;
import
com.google.gwt.user.client.ui.TreeItem
;
...
...
@@ -93,6 +96,7 @@ public class AssetList extends Composite implements ProjectChangeListener {
* Populate the asset tree with files from the project's assets folder.
*/
private
void
refreshAssetList
()
{
final
Images
images
=
Ode
.
getImageBundle
();
OdeLog
.
log
(
"AssetList: refreshing for project "
+
projectId
);
assetList
.
clear
();
...
...
@@ -104,8 +108,20 @@ public class AssetList extends Composite implements ProjectChangeListener {
if
(
nodeName
.
length
()
>
20
)
nodeName
=
nodeName
.
substring
(
0
,
8
)
+
"..."
+
nodeName
.
substring
(
nodeName
.
length
()
-
9
,
nodeName
.
length
());
TreeItem
treeItem
=
new
TreeItem
(
new
HTML
(
"<span>"
+
nodeName
+
"</span>"
));
String
fileSuffix
=
node
.
getProjectId
()
+
"/"
+
node
.
getFileId
();
String
treeItemText
=
"<span style='cursor: pointer'>"
+
nodeName
+
"</span>"
;
if
(
StorageUtil
.
isImageFile
(
fileSuffix
))
{
Image
mediaIcon
=
new
Image
(
images
.
mediaIconImg
());
treeItemText
=
"<span>"
+
mediaIcon
+
nodeName
+
"</span>"
;
}
else
if
(
StorageUtil
.
isAudioFile
(
fileSuffix
))
{
Image
mediaIcon
=
new
Image
(
images
.
mediaIconAudio
());
treeItemText
=
"<span>"
+
mediaIcon
+
nodeName
+
"</span>"
;
}
else
{
Image
mediaIcon
=
new
Image
(
images
.
mediaIconVideo
());
treeItemText
=
"<span>"
+
mediaIcon
+
nodeName
+
"</span>"
;
}
TreeItem
treeItem
=
new
TreeItem
(
new
HTML
(
treeItemText
));
// keep a pointer from the tree item back to the actual node
treeItem
.
setUserObject
(
node
);
assetList
.
addItem
(
treeItem
);
...
...
appinventor/appengine/src/com/google/appinventor/client/tracking/Tracking.java
View file @
fc2a232c
...
...
@@ -27,6 +27,8 @@ public class Tracking {
"DeleteProject-YA"
;
public
static
final
String
PROJECT_ACTION_DELETE_FILE_YA
=
PROJECT_ACTION_PREFIX
+
"DeleteFile-YA"
;
public
static
final
String
PROJECT_ACTION_PREVIEW_FILE_YA
=
PROJECT_ACTION_PREFIX
+
"PreviewFile-YA"
;
public
static
final
String
PROJECT_ACTION_BUILD_BARCODE_YA
=
PROJECT_ACTION_PREFIX
+
"BuildBarcode-YA"
;
public
static
final
String
PROJECT_ACTION_BUILD_DOWNLOAD_YA
=
PROJECT_ACTION_PREFIX
+
...
...
appinventor/appengine/src/com/google/appinventor/images/mediaIcon_audio.png
0 → 100644
View file @
fc2a232c
275 Bytes
appinventor/appengine/src/com/google/appinventor/images/mediaIcon_img.png
0 → 100644
View file @
fc2a232c
331 Bytes
appinventor/appengine/src/com/google/appinventor/images/mediaIcon_video.png
0 → 100644
View file @
fc2a232c
290 Bytes
appinventor/appengine/src/com/google/appinventor/shared/storage/StorageUtil.java
View file @
fc2a232c
...
...
@@ -103,10 +103,12 @@ public class StorageUtil {
/**
* Returns the content type for the given filePath.
* References support media files listed at http://developer.android.com/guide/appendix/media-formats.html
*/
public
static
String
getContentTypeForFilePath
(
String
filePath
)
{
filePath
=
filePath
.
toLowerCase
();
// Image File Types
if
(
filePath
.
endsWith
(
".gif"
))
{
return
"image/gif"
;
}
...
...
@@ -116,10 +118,69 @@ public class StorageUtil {
if
(
filePath
.
endsWith
(
".png"
))
{
return
"image/png"
;
}
if
(
filePath
.
endsWith
(
".bmp"
))
{
return
"image/bmp"
;
}
if
(
filePath
.
endsWith
(
".webp"
))
{
return
"image/webp"
;
}
// Audio File Types
if
(
filePath
.
endsWith
(
".mp3"
))
{
return
"audio/mp3"
;
}
if
(
filePath
.
endsWith
(
".m4a"
))
{
return
"audio/m4a"
;
}
if
(
filePath
.
endsWith
(
".aac"
))
{
return
"audio/aac"
;
}
if
(
filePath
.
endsWith
(
".wav"
))
{
return
"audio/wav"
;
}
if
(
filePath
.
endsWith
(
".flac"
))
{
return
"audio/flac"
;
}
if
(
filePath
.
endsWith
(
".mid"
)
||
filePath
.
endsWith
(
".xmf"
)
||
filePath
.
endsWith
(
".mxmf"
))
{
return
"audio/midi"
;
}
if
(
filePath
.
endsWith
(
".ota"
))
{
return
"audio/ota"
;
}
if
(
filePath
.
endsWith
(
".rtttl"
))
{
return
"audio/rtttl"
;
}
if
(
filePath
.
endsWith
(
".rtx"
))
{
return
"audio/rtx"
;
}
if
(
filePath
.
endsWith
(
".imy"
))
{
return
"audio/imy"
;
}
if
(
filePath
.
endsWith
(
".ogg"
))
{
return
"audio/ogg"
;
}
// Video File Types
if
(
filePath
.
endsWith
(
".mp4"
))
{
return
"video/mp4"
;
}
if
(
filePath
.
endsWith
(
".3gp"
))
{
return
"video/3gp"
;
}
if
(
filePath
.
endsWith
(
".ts"
))
{
return
"video/ts"
;
}
if
(
filePath
.
endsWith
(
".webm"
))
{
return
"video/webm"
;
}
if
(
filePath
.
endsWith
(
".mkv"
))
{
return
"video/mkv"
;
}
if
(
filePath
.
endsWith
(
".svg"
))
{
return
"image/svg+xml"
;
}
// Other File Types
if
(
filePath
.
endsWith
(
".apk"
))
{
return
"application/vnd.android.package-archive"
;
}
...
...
@@ -152,6 +213,22 @@ public class StorageUtil {
return
contentType
.
startsWith
(
"text/"
);
}
/**
* Returns true if the given filePath refers an audio file.
*/
public
static
boolean
isAudioFile
(
String
filePath
)
{
String
contentType
=
getContentTypeForFilePath
(
filePath
);
return
contentType
.
startsWith
(
"audio/"
);
}
/**
* Returns true if the given filePath refers a video file.
*/
public
static
boolean
isVideoFile
(
String
filePath
)
{
String
contentType
=
getContentTypeForFilePath
(
filePath
);
return
contentType
.
startsWith
(
"video/"
);
}
/**
* Returns the URL for the given project file.
*/
...
...
appinventor/appengine/war/Ya.css
View file @
fc2a232c
...
...
@@ -625,8 +625,10 @@ select {
.gwt-Tree
.gwt-TreeItem
span
{
padding
:
8px
4px
4px
4px
;
cursor
:
pointer
;
}
.gwt-Tree
.gwt-TreeItem
span
:hover
,
.gwt-Tree
.gwt-TreeItem-selected
span
{
background-color
:
#d2e0a6
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment