Support audio files with HTML5 <audio />
Summary: Ref T3887. Similar to how we render images with `<img />`, render audio with `<audio />` if possible. Test Plan: See screenshots. Reviewers: btrahan, chad Reviewed By: btrahan CC: aran Maniphest Tasks: T3887 Differential Revision: https://secure.phabricator.com/D7156
This commit is contained in:
@@ -29,6 +29,10 @@ final class PhabricatorFilesConfigOptions
|
||||
'image/x-ico' => 'image/x-icon',
|
||||
'image/x-icon' => 'image/x-icon',
|
||||
'image/vnd.microsoft.icon' => 'image/x-icon',
|
||||
|
||||
'audio/x-wav' => 'audio/x-wav',
|
||||
'application/ogg' => 'application/ogg',
|
||||
'audio/mpeg' => 'audio/mpeg',
|
||||
);
|
||||
|
||||
$image_default = array(
|
||||
@@ -41,6 +45,12 @@ final class PhabricatorFilesConfigOptions
|
||||
'image/vnd.microsoft.icon' => true,
|
||||
);
|
||||
|
||||
$audio_default = array(
|
||||
'audio/x-wav' => true,
|
||||
'application/ogg' => true,
|
||||
'audio/mpeg' => true,
|
||||
);
|
||||
|
||||
// largely lifted from http://en.wikipedia.org/wiki/Internet_media_type
|
||||
$icon_default = array(
|
||||
// audio file icon
|
||||
@@ -82,7 +92,7 @@ final class PhabricatorFilesConfigOptions
|
||||
'browsers tend to freak out when viewing enormous binary files.'.
|
||||
"\n\n".
|
||||
'The keys in this map are vieweable MIME types; the values are '.
|
||||
'the MIME type sthey are delivered as when they are viewed in '.
|
||||
'the MIME types they are delivered as when they are viewed in '.
|
||||
'the browser.')),
|
||||
$this->newOption('files.image-mime-types', 'set', $image_default)
|
||||
->setSummary(pht('Configure which MIME types are images.'))
|
||||
@@ -90,6 +100,12 @@ final class PhabricatorFilesConfigOptions
|
||||
pht(
|
||||
'List of MIME types which can be used as the `src` for an '.
|
||||
'`<img />` tag.')),
|
||||
$this->newOption('files.audio-mime-types', 'set', $audio_default)
|
||||
->setSummary(pht('Configure which MIME types are audio.'))
|
||||
->setDescription(
|
||||
pht(
|
||||
'List of MIME types which can be used to render an '.
|
||||
'`<audio />` tag.')),
|
||||
$this->newOption('files.icon-mime-types', 'wild', $icon_default)
|
||||
->setSummary(pht('Configure which MIME types map to which icons.'))
|
||||
->setDescription(
|
||||
|
||||
@@ -217,6 +217,20 @@ final class PhabricatorFileInfoController extends PhabricatorFileController {
|
||||
$image);
|
||||
|
||||
$view->addImageContent($linked_image);
|
||||
} else if ($file->isAudio()) {
|
||||
$audio = phutil_tag(
|
||||
'audio',
|
||||
array(
|
||||
'controls' => 'controls',
|
||||
'class' => 'phabricator-property-list-audio',
|
||||
),
|
||||
phutil_tag(
|
||||
'source',
|
||||
array(
|
||||
'src' => $file->getViewURI(),
|
||||
'type' => $file->getMimeType(),
|
||||
)));
|
||||
$view->addImageContent($audio);
|
||||
}
|
||||
|
||||
return $view;
|
||||
|
||||
@@ -57,6 +57,7 @@ final class PhabricatorRemarkupRuleEmbedFile
|
||||
$options['name'] = $file_name;
|
||||
|
||||
$is_viewable_image = $file->isViewableImage();
|
||||
$is_audio = $file->isAudio();
|
||||
|
||||
$attrs = array();
|
||||
if ($is_viewable_image) {
|
||||
@@ -91,10 +92,20 @@ final class PhabricatorRemarkupRuleEmbedFile
|
||||
$bundle['meta'] = array(
|
||||
'phid' => $file->getPHID(),
|
||||
'viewable' => $is_viewable_image,
|
||||
'audio' => $is_audio,
|
||||
'uri' => $file->getBestURI(),
|
||||
'dUri' => $file->getDownloadURI(),
|
||||
'name' => $options['name'],
|
||||
'mime' => $file->getMimeType(),
|
||||
);
|
||||
|
||||
if ($is_audio) {
|
||||
$bundle['meta'] += array(
|
||||
'autoplay' => idx($options, 'autoplay'),
|
||||
'loop' => idx($options, 'loop'),
|
||||
);
|
||||
}
|
||||
|
||||
$metadata[$phid][] = $bundle;
|
||||
$engine->setTextMetadata($metadata_key, $metadata);
|
||||
|
||||
@@ -118,7 +129,10 @@ final class PhabricatorRemarkupRuleEmbedFile
|
||||
$options = $data['options'];
|
||||
$meta = $data['meta'];
|
||||
|
||||
if (!$meta['viewable'] || $options['layout'] == 'link') {
|
||||
$is_image = idx($meta, 'viewable');
|
||||
$is_audio = idx($meta, 'audio');
|
||||
|
||||
if ((!$is_image && !$is_audio) || $options['layout'] == 'link') {
|
||||
$link = id(new PhabricatorFileLinkView())
|
||||
->setFilePHID($meta['phid'])
|
||||
->setFileName($meta['name'])
|
||||
@@ -130,6 +144,33 @@ final class PhabricatorRemarkupRuleEmbedFile
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($is_audio) {
|
||||
if (idx($options, 'autoplay')) {
|
||||
$preload = 'auto';
|
||||
$autoplay = 'autoplay';
|
||||
} else {
|
||||
$preload = 'none';
|
||||
$autoplay = null;
|
||||
}
|
||||
|
||||
$link = phutil_tag(
|
||||
'audio',
|
||||
array(
|
||||
'controls' => 'controls',
|
||||
'preload' => $preload,
|
||||
'autoplay' => $autoplay,
|
||||
'loop' => idx($options, 'loop') ? 'loop' : null,
|
||||
),
|
||||
phutil_tag(
|
||||
'source',
|
||||
array(
|
||||
'src' => $meta['uri'],
|
||||
'type' => $meta['mime'],
|
||||
)));
|
||||
$engine->overwriteStoredText($data['token'], $link);
|
||||
continue;
|
||||
}
|
||||
|
||||
require_celerity_resource('lightbox-attachment-css');
|
||||
$img = phutil_tag('img', $data['attrs']);
|
||||
|
||||
|
||||
@@ -564,6 +564,16 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
||||
return idx($mime_map, $mime_type);
|
||||
}
|
||||
|
||||
public function isAudio() {
|
||||
if (!$this->isViewableInBrowser()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$mime_map = PhabricatorEnv::getEnvConfig('files.audio-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
|
||||
|
||||
Reference in New Issue
Block a user