diff --git a/server/perkeepd/ui/audio_detail.css b/server/perkeepd/ui/audio_detail.css new file mode 100644 index 000000000..4581c6ac8 --- /dev/null +++ b/server/perkeepd/ui/audio_detail.css @@ -0,0 +1,56 @@ +/* +Copyright 2019 The Perkeep Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.cam-detail-audio { + display: flex; + flex-direction: column; + width: 100%; + background: black; + + &-controls { + display: flex; + align-items: center; + + @media screen and (max-width: 768px) { + flex-direction: column; + align-items: flex-start; + } + + &-player { + padding: 12px; + font-size: 0; + flex-grow: 1; + + audio { + width: 100%; + } + } + + &-meta { + padding: 12px; + + &-title { + color: white; + font-size: 17px; + } + + &-artist { + color: lightgrey; + font-size: 15px; + } + } + } +} diff --git a/server/perkeepd/ui/audio_detail.js b/server/perkeepd/ui/audio_detail.js new file mode 100644 index 000000000..026551db0 --- /dev/null +++ b/server/perkeepd/ui/audio_detail.js @@ -0,0 +1,98 @@ +/* +Copyright 2019 The Perkeep Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +goog.provide('cam.AudioDetail'); + +goog.require('cam.BlobItemAudioContent'); + +cam.AudioDetail = React.createClass({ + displayName: 'AudioDetail', + + propTypes: { + permanodeMeta: React.PropTypes.object, + resolvedMeta: React.PropTypes.object.isRequired, + }, + + render: function() { + return React.DOM.div({ + className: 'cam-detail-audio', + }, + this.getControls_(), + ); + }, + + getControls_: function() { + var mediaTags = this.props.resolvedMeta.mediaTags; + return React.DOM.div({ + className: 'cam-detail-audio-controls', + }, + React.DOM.div({ + className: 'cam-detail-audio-controls-meta' + }, + mediaTags.title != null && React.DOM.div({ + className: 'cam-detail-audio-controls-meta-title', + }, mediaTags.title), + + mediaTags.artist != null && React.DOM.div({ + className: 'cam-detail-audio-controls-meta-artist', + }, mediaTags.artist), + ), + + React.DOM.div({ + className: 'cam-detail-audio-controls-player', + }, + React.DOM.audio({ + controls: true, + key: this.props.resolvedMeta.blobRef, + src: goog.string.subs('%s%s/%s', goog.global.CAMLISTORE_CONFIG.downloadHelper, this.props.resolvedMeta.blobRef, this.props.resolvedMeta.file.fileName), + }), + ), + ); + }, +}); + +cam.AudioDetail.getAspect = function(blobref, searchSession) { + if (!blobref) { + return null; + } + + var rm = searchSession.getResolvedMeta(blobref); + var pm = searchSession.getMeta(blobref); + + if (!pm) { + return null; + } + + if (pm.camliType != 'permanode') { + pm = null; + } + + if (rm && cam.BlobItemAudioContent.isAudio(rm)) { + return { + fragment: 'audio', + title: 'Audio', + createContent: function(size, backwardPiggy) { + return React.createElement(cam.AudioDetail, { + key: 'audio', + permanodeMeta: pm, + resolvedMeta: rm, + }); + }, + }; + } else { + return null; + } +}; diff --git a/server/perkeepd/ui/index.html b/server/perkeepd/ui/index.html index 8c1772604..7df08088b 100644 --- a/server/perkeepd/ui/index.html +++ b/server/perkeepd/ui/index.html @@ -54,6 +54,7 @@ limitations under the License. + diff --git a/server/perkeepd/ui/index.js b/server/perkeepd/ui/index.js index 0193c7701..065fc52bc 100644 --- a/server/perkeepd/ui/index.js +++ b/server/perkeepd/ui/index.js @@ -33,6 +33,8 @@ goog.require('goog.string'); goog.require('goog.Uri'); goog.require('cam.BlobDetail'); +goog.require('cam.ImageDetail'); +goog.require('cam.AudioDetail'); goog.require('cam.BlobItemContainerReact'); goog.require('cam.DirContainer'); goog.require('cam.BlobItemDemoContent'); @@ -249,9 +251,10 @@ cam.IndexPage = React.createClass({ var specificAspects = [ cam.ImageDetail.getAspect, + cam.AudioDetail.getAspect, cam.PdfDetail.getAspect, this.getDirAspect_.bind(null), - ].map(getAspect).filter(goog.functions.identity); + ]; var generalAspects = [ this.getSearchAspect_.bind(null, specificAspects), @@ -260,9 +263,12 @@ cam.IndexPage = React.createClass({ this.props.availWidth, this.props.availHeight - this.HEADER_HEIGHT_, this.updateSearchBarOnMap_, this.setPendingQuery_, this.childSearchSession_), cam.BlobDetail.getAspect.bind(null, this.getDetailURL_, this.props.serverConnection), - ].map(getAspect).filter(goog.functions.identity); + ]; - return specificAspects.concat(generalAspects); + return specificAspects + .concat(generalAspects) + .map(getAspect) + .filter(goog.functions.identity); }, getSearchAspect_: function(specificAspects, blobref, targetSearchSession) {