Support video content in detail view

Change-Id: I1a8d7bceefeff94a70dedf7cee7a9778fa61dd43
This commit is contained in:
Aaron Boodman 2014-05-18 12:16:35 -07:00
parent 54e0d07e5e
commit f7adfc2869
2 changed files with 45 additions and 11 deletions

View File

@ -125,6 +125,29 @@ cam.BlobItemVideoContent = React.createClass({
},
});
cam.BlobItemVideoContent.isVideo = function(rm) {
// From http://en.wikipedia.org/wiki/List_of_file_formats
// TODO(aa): Fix this quick hack once the server indexes movies and gives us more information.
var extensions = [
'3gp',
'aav',
'asf',
'avi',
'dat',
'm1v',
'm2v',
'm4v',
'mov',
'mp4',
'mpe',
'mpeg',
'mpg',
'ogg',
'wmv',
];
return rm && rm.file && goog.array.some(extensions, goog.string.endsWith.bind(null, rm.file.fileName.toLowerCase()));
};
cam.BlobItemVideoContent.getHandler = function(blobref, searchSession, href) {
var rm = searchSession.getResolvedMeta(blobref);
@ -147,7 +170,7 @@ cam.BlobItemVideoContent.getHandler = function(blobref, searchSession, href) {
'ogg',
'wmv',
];
if (rm && rm.file && goog.array.some(extensions, goog.string.endsWith.bind(null, rm.file.fileName.toLowerCase()))) {
if (cam.BlobItemVideoContent.isVideo(rm)) {
return new cam.BlobItemVideoContent.Handler(rm, href)
}

View File

@ -16,6 +16,7 @@ limitations under the License.
goog.provide('cam.ImageDetail');
goog.require('cam.BlobItemVideoContent');
goog.require('cam.PropertySheetContainer');
goog.require('cam.Thumber');
@ -35,9 +36,17 @@ cam.ImageDetail = React.createClass({
width: React.PropTypes.number.isRequired,
},
isVideo_: function() {
return !this.isImage_();
},
isImage_: function() {
return Boolean(this.props.resolvedMeta.image);
},
componentWillReceiveProps: function(nextProps) {
if (this.props == nextProps || this.props.resolvedMeta.blobRef != nextProps.resolvedMeta.blobRef) {
this.thumber_ = cam.Thumber.fromImageMeta(nextProps.resolvedMeta);
this.thumber_ = nextProps.resolvedMeta.image && cam.Thumber.fromImageMeta(nextProps.resolvedMeta);
this.setState({imgHasLoaded: false});
}
},
@ -124,16 +133,18 @@ cam.ImageDetail = React.createClass({
getImg_: function() {
var transition = React.addons.TransitionGroup({transitionName: 'detail-img'}, []);
if (this.imgSize_) {
var ctor = this.props.resolvedMeta.image ? React.DOM.img : React.DOM.video;
transition.props.children.push(
React.DOM.img({
ctor({
className: React.addons.classSet({
'detail-view-img': true,
'detail-view-img-loaded': this.state.imgHasLoaded
'detail-view-img-loaded': this.isImage_() ? this.state.imgHasLoaded : true,
}),
controls: true,
// We want each image to have its own node in the DOM so that during the crossfade, we don't see the image jump to the next image's size.
key: 'img' + this.props.resolvedMeta.blobRef,
onLoad: this.onImgLoad_,
src: this.thumber_.getSrc(this.imgSize_.height),
onLoad: this.isImage_() ? this.onImgLoad_ : null,
src: this.isImage_() ? this.thumber_.getSrc(this.imgSize_.height) : './download/' + this.props.resolvedMeta.blobRef + '/' + this.props.resolvedMeta.file.fileName,
style: this.getCenteredProps_(this.imgSize_.width, this.imgSize_.height)
})
);
@ -143,7 +154,7 @@ cam.ImageDetail = React.createClass({
getPiggy_: function() {
var transition = React.addons.TransitionGroup({transitionName: 'detail-piggy'}, []);
if (!this.state.imgHasLoaded) {
if (this.isImage_() && !this.state.imgHasLoaded) {
transition.props.children.push(
cam.SpritedAnimation({
src: 'glitch/npc_piggy__x1_walk_png_1354829432.png',
@ -173,8 +184,8 @@ cam.ImageDetail = React.createClass({
},
getImgSize_: function() {
if (!this.props.resolvedMeta.image) {
return null;
if (this.isVideo_()) {
return new goog.math.Size(this.props.width, this.props.height);
}
var rawSize = new goog.math.Size(this.props.resolvedMeta.image.width, this.props.resolvedMeta.image.height);
var available = new goog.math.Size(
@ -212,7 +223,7 @@ cam.ImageDetail.getAspect = function(blobref, searchSession) {
pm = null;
}
return rm && rm.image ? new cam.ImageDetail.Aspect(rm, pm) : null;
return rm && (rm.image || cam.BlobItemVideoContent.isVideo(rm)) ? new cam.ImageDetail.Aspect(rm, pm) : null;
// We don't handle camliContentImage like BlobItemImage.getHandler does because that only tells us what image to display in the search results. It doesn't actually make the permanode an image or anything.
};
@ -223,7 +234,7 @@ cam.ImageDetail.Aspect = function(resolvedMeta, permanodeMeta) {
};
cam.ImageDetail.Aspect.prototype.getTitle = function() {
return 'Image';
return this.resolvedMeta_.image ? 'Image' : 'Video';
};
// TODO(aa): Piggy should move into cam.Detail and use an onload handler to turn on/off.