Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15467362
D11297.id38669.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
13 KB
Referenced Files
None
Subscribers
None
D11297.id38669.diff
View Options
diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -7,7 +7,7 @@
*/
return array(
'names' => array(
- 'core.pkg.css' => 'b9927580',
+ 'core.pkg.css' => '0e3b60db',
'core.pkg.js' => '3f15fa62',
'darkconsole.pkg.js' => 'e7393ebb',
'differential.pkg.css' => 'f3fb8324',
@@ -104,7 +104,7 @@
'rsrc/css/application/tokens/tokens.css' => '3d0f239e',
'rsrc/css/application/uiexample/example.css' => '528b19de',
'rsrc/css/core/core.css' => 'd0801452',
- 'rsrc/css/core/remarkup.css' => '787105d6',
+ 'rsrc/css/core/remarkup.css' => '845a390d',
'rsrc/css/core/syntax.css' => '9fc496d5',
'rsrc/css/core/z-index.css' => '5b6fcf3f',
'rsrc/css/diviner/diviner-shared.css' => 'aa3656aa',
@@ -149,7 +149,7 @@
'rsrc/css/phui/phui-pager.css' => 'bea33d23',
'rsrc/css/phui/phui-pinboard-view.css' => '2495140e',
'rsrc/css/phui/phui-profile-menu.css' => 'c8557f33',
- 'rsrc/css/phui/phui-property-list-view.css' => '1d42ee7c',
+ 'rsrc/css/phui/phui-property-list-view.css' => '6458f614',
'rsrc/css/phui/phui-remarkup-preview.css' => '1a8f2591',
'rsrc/css/phui/phui-segment-bar-view.css' => '46342871',
'rsrc/css/phui/phui-spacing.css' => '042804d6',
@@ -784,7 +784,7 @@
'phabricator-object-selector-css' => '85ee8ce6',
'phabricator-phtize' => 'd254d646',
'phabricator-prefab' => 'e67df814',
- 'phabricator-remarkup-css' => '787105d6',
+ 'phabricator-remarkup-css' => '845a390d',
'phabricator-search-results-css' => '7dea472c',
'phabricator-shaped-request' => '7cbe244b',
'phabricator-side-menu-view-css' => 'dd849797',
@@ -851,7 +851,7 @@
'phui-pager-css' => 'bea33d23',
'phui-pinboard-view-css' => '2495140e',
'phui-profile-menu-css' => 'c8557f33',
- 'phui-property-list-view-css' => '1d42ee7c',
+ 'phui-property-list-view-css' => '6458f614',
'phui-remarkup-preview-css' => '1a8f2591',
'phui-segment-bar-view-css' => '46342871',
'phui-spacing-css' => '042804d6',
diff --git a/src/applications/files/config/PhabricatorFilesConfigOptions.php b/src/applications/files/config/PhabricatorFilesConfigOptions.php
--- a/src/applications/files/config/PhabricatorFilesConfigOptions.php
+++ b/src/applications/files/config/PhabricatorFilesConfigOptions.php
@@ -34,9 +34,16 @@
'image/x-icon' => 'image/x-icon',
'image/vnd.microsoft.icon' => 'image/x-icon',
- 'audio/x-wav' => 'audio/x-wav',
+ // This is a generic type for both OGG video and OGG audio.
'application/ogg' => 'application/ogg',
- 'audio/mpeg' => 'audio/mpeg',
+
+ 'audio/x-wav' => 'audio/x-wav',
+ 'audio/mpeg' => 'audio/mpeg',
+ 'audio/ogg' => 'audio/ogg',
+
+ 'video/mp4' => 'video/mp4',
+ 'video/ogg' => 'video/ogg',
+ 'video/webm' => 'video/webm',
);
$image_default = array(
@@ -49,10 +56,29 @@
'image/vnd.microsoft.icon' => true,
);
+
+ // The "application/ogg" type is listed as both an audio and video type,
+ // because it may contain either type of content.
+
$audio_default = array(
- 'audio/x-wav' => true,
+ 'audio/x-wav' => true,
+ 'audio/mpeg' => true,
+ 'audio/ogg' => true,
+
+ // These are video or ambiguous types, but can be forced to render as
+ // audio with `media=audio`, which seems to work properly in browsers.
+ // (For example, you can embed a music video as audio if you just want
+ // to set the mood for your task without distracting viewers.)
+ 'video/mp4' => true,
+ 'video/ogg' => true,
+ 'application/ogg' => true,
+ );
+
+ $video_default = array(
+ 'video/mp4' => true,
+ 'video/ogg' => true,
+ 'video/webm' => true,
'application/ogg' => true,
- 'audio/mpeg' => true,
);
// largely lifted from http://en.wikipedia.org/wiki/Internet_media_type
@@ -70,6 +96,7 @@
// movie file icon
'video/mpeg' => 'fa-file-movie-o',
'video/mp4' => 'fa-file-movie-o',
+ 'application/ogg' => 'fa-file-movie-o',
'video/ogg' => 'fa-file-movie-o',
'video/quicktime' => 'fa-file-movie-o',
'video/webm' => 'fa-file-movie-o',
@@ -122,8 +149,14 @@
->setSummary(pht('Configure which MIME types are audio.'))
->setDescription(
pht(
- 'List of MIME types which can be used to render an `%s` tag.',
+ 'List of MIME types which can be rendered with an `%s` tag.',
'<audio />')),
+ $this->newOption('files.video-mime-types', 'set', $video_default)
+ ->setSummary(pht('Configure which MIME types are video.'))
+ ->setDescription(
+ pht(
+ 'List of MIME types which can be rendered with a `%s` tag.',
+ '<video />')),
$this->newOption('files.icon-mime-types', 'wild', $icon_default)
->setLocked(true)
->setSummary(pht('Configure which MIME types map to which icons.'))
diff --git a/src/applications/files/controller/PhabricatorFileInfoController.php b/src/applications/files/controller/PhabricatorFileInfoController.php
--- a/src/applications/files/controller/PhabricatorFileInfoController.php
+++ b/src/applications/files/controller/PhabricatorFileInfoController.php
@@ -230,23 +230,34 @@
$cache_string = pht('Not Applicable');
}
- $finfo->addProperty(pht('Viewable Image'), $image_string);
- $finfo->addProperty(pht('Cacheable'), $cache_string);
+ $types = array();
+ if ($file->isViewableImage()) {
+ $types[] = pht('Image');
+ }
- $builtin = $file->getBuiltinName();
- if ($builtin === null) {
- $builtin_string = pht('No');
- } else {
- $builtin_string = $builtin;
+ if ($file->isVideo()) {
+ $types[] = pht('Video');
+ }
+
+ if ($file->isAudio()) {
+ $types[] = pht('Audio');
}
- $finfo->addProperty(pht('Builtin'), $builtin_string);
+ if ($file->getCanCDN()) {
+ $types[] = pht('Can CDN');
+ }
+
+ $builtin = $file->getBuiltinName();
+ if ($builtin !== null) {
+ $types[] = pht('Builtin ("%s")', $builtin);
+ }
- $is_profile = $file->getIsProfileImage()
- ? pht('Yes')
- : pht('No');
+ if ($file->getIsProfileImage()) {
+ $types[] = pht('Profile');
+ }
- $finfo->addProperty(pht('Profile'), $is_profile);
+ $types = implode(', ', $types);
+ $finfo->addProperty(pht('Attributes'), $types);
$storage_properties = new PHUIPropertyListView();
$box->addPropertyList($storage_properties, pht('Storage'));
@@ -293,6 +304,23 @@
->addImageContent($linked_image);
$box->addPropertyList($media);
+ } else if ($file->isVideo()) {
+ $video = phutil_tag(
+ 'video',
+ array(
+ 'controls' => 'controls',
+ 'class' => 'phui-property-list-video',
+ ),
+ phutil_tag(
+ 'source',
+ array(
+ 'src' => $file->getViewURI(),
+ 'type' => $file->getMimeType(),
+ )));
+ $media = id(new PHUIPropertyListView())
+ ->addImageContent($video);
+
+ $box->addPropertyList($media);
} else if ($file->isAudio()) {
$audio = phutil_tag(
'audio',
diff --git a/src/applications/files/markup/PhabricatorEmbedFileRemarkupRule.php b/src/applications/files/markup/PhabricatorEmbedFileRemarkupRule.php
--- a/src/applications/files/markup/PhabricatorEmbedFileRemarkupRule.php
+++ b/src/applications/files/markup/PhabricatorEmbedFileRemarkupRule.php
@@ -43,12 +43,27 @@
$is_viewable_image = $object->isViewableImage();
$is_audio = $object->isAudio();
+ $is_video = $object->isVideo();
$force_link = ($options['layout'] == 'link');
- $options['viewable'] = ($is_viewable_image || $is_audio);
+ // If a file is both audio and video, as with "application/ogg" by default,
+ // render it as video but allow the user to specify `media=audio` if they
+ // want to force it to render as audio.
+ if ($is_audio && $is_video) {
+ $media = $options['media'];
+ if ($media == 'audio') {
+ $is_video = false;
+ } else {
+ $is_audio = false;
+ }
+ }
+
+ $options['viewable'] = ($is_viewable_image || $is_audio || $is_video);
if ($is_viewable_image && !$force_link) {
return $this->renderImageFile($object, $handle, $options);
+ } else if ($is_video && !$force_link) {
+ return $this->renderVideoFile($object, $handle, $options);
} else if ($is_audio && !$force_link) {
return $this->renderAudioFile($object, $handle, $options);
} else {
@@ -58,12 +73,15 @@
private function getFileOptions($option_string) {
$options = array(
- 'size' => null,
- 'layout' => 'left',
- 'float' => false,
- 'width' => null,
- 'height' => null,
+ 'size' => null,
+ 'layout' => 'left',
+ 'float' => false,
+ 'width' => null,
+ 'height' => null,
'alt' => null,
+ 'media' => null,
+ 'autoplay' => null,
+ 'loop' => null,
);
if ($option_string) {
@@ -201,22 +219,47 @@
PhabricatorFile $file,
PhabricatorObjectHandle $handle,
array $options) {
+ return $this->renderMediaFile('audio', $file, $handle, $options);
+ }
+
+ private function renderVideoFile(
+ PhabricatorFile $file,
+ PhabricatorObjectHandle $handle,
+ array $options) {
+ return $this->renderMediaFile('video', $file, $handle, $options);
+ }
+
+ private function renderMediaFile(
+ $tag,
+ PhabricatorFile $file,
+ PhabricatorObjectHandle $handle,
+ array $options) {
+
+ $is_video = ($tag == 'video');
if (idx($options, 'autoplay')) {
$preload = 'auto';
$autoplay = 'autoplay';
} else {
- $preload = 'none';
+ // If we don't preload video, the user can't see the first frame and
+ // has no clue what they're looking at, so always preload.
+ if ($is_video) {
+ $preload = 'auto';
+ } else {
+ $preload = 'none';
+ }
$autoplay = null;
}
return $this->newTag(
- 'audio',
+ $tag,
array(
'controls' => 'controls',
'preload' => $preload,
'autoplay' => $autoplay,
'loop' => idx($options, 'loop') ? 'loop' : null,
+ 'alt' => $options['alt'],
+ 'class' => 'phabricator-media',
),
$this->newTag(
'source',
diff --git a/src/applications/files/storage/PhabricatorFile.php b/src/applications/files/storage/PhabricatorFile.php
--- a/src/applications/files/storage/PhabricatorFile.php
+++ b/src/applications/files/storage/PhabricatorFile.php
@@ -58,6 +58,11 @@
private $originalFile = self::ATTACHABLE;
private $transforms = self::ATTACHABLE;
+ public function getMimeType() {
+ $type = parent::getMimeType();
+ return $type;
+ }
+
public static function initializeNewFile() {
$app = id(new PhabricatorApplicationQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
@@ -802,6 +807,16 @@
return idx($mime_map, $mime_type);
}
+ public function isVideo() {
+ if (!$this->isViewableInBrowser()) {
+ return false;
+ }
+
+ $mime_map = PhabricatorEnv::getEnvConfig('files.video-mime-types');
+ $mime_type = $this->getMimeType();
+ return idx($mime_map, $mime_type);
+ }
+
public function isTransformableImage() {
// NOTE: The way the 'gd' extension works in PHP is that you can install it
// with support for only some file types, so it might be able to handle
diff --git a/src/docs/user/userguide/remarkup.diviner b/src/docs/user/userguide/remarkup.diviner
--- a/src/docs/user/userguide/remarkup.diviner
+++ b/src/docs/user/userguide/remarkup.diviner
@@ -410,18 +410,29 @@
{F123, layout=left, float, size=full, alt="a duckling"}
-Valid options are:
+Valid options for all files are:
- **layout** left (default), center, right, inline, link (render a link
instead of a thumbnail for images)
+ - **name** with `layout=link` or for non-images, use this name for the link
+ text
+ - **alt** Provide alternate text for assistive technologies.
+
+Image files support these options:
+
- **float** If layout is set to left or right, the image will be floated so
text wraps around it.
- **size** thumb (default), full
- - **name** with `layout=link` or for non-images, use this name for the link
- text
- **width** Scale image to a specific width.
- **height** Scale image to a specific height.
- - **alt** Provide alternate text for assistive technologies.
+
+Audio and video files support these options:
+
+ - **media**: Specify the media type as `audio` or `video`. This allows you
+ to disambiguate how file format which may contain either audio or video
+ should be rendered.
+ - **loop**: Loop this media.
+ - **autoplay**: Automatically begin playing this media.
== Embedding Countdowns
diff --git a/webroot/rsrc/css/core/remarkup.css b/webroot/rsrc/css/core/remarkup.css
--- a/webroot/rsrc/css/core/remarkup.css
+++ b/webroot/rsrc/css/core/remarkup.css
@@ -218,6 +218,17 @@
width: 50%;
}
+video.phabricator-media {
+ background: {$greybackground};
+}
+
+.phabricator-remarkup video {
+ display: block;
+ margin: 0 auto;
+ min-width: 240px;
+ width: 90%;
+}
+
.phabricator-remarkup-mention-exists {
font-weight: bold;
background: #e6f3ff;
diff --git a/webroot/rsrc/css/phui/phui-property-list-view.css b/webroot/rsrc/css/phui/phui-property-list-view.css
--- a/webroot/rsrc/css/phui/phui-property-list-view.css
+++ b/webroot/rsrc/css/phui/phui-property-list-view.css
@@ -160,6 +160,13 @@
min-width: 240px;
}
+.phui-property-list-video {
+ display: block;
+ margin: 0 auto;
+ width: 90%;
+ min-width: 240px;
+}
+
/* When tags appear in property lists, give them a little more vertical
spacing. */
.phui-property-list-view .phui-tag-view {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Apr 4, 2:10 PM (4 d, 7 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7388511
Default Alt Text
D11297.id38669.diff (13 KB)
Attached To
Mode
D11297: Add Videos to Remarkup
Attached
Detach File
Event Timeline
Log In to Comment