Sebastian Kippe 2017da2af0 Render audio and video file preview
Audio and video files are not downloaded, but the element src is
fetching the content directly from storage. Unfortunately, one cannot
skip forward, when the RS server doesn't support content ranges.
2018-11-17 15:33:28 +00:00

178 lines
5.0 KiB
JavaScript

import Component from '@ember/component';
import { inject as service } from '@ember/service';
import { observer } from '@ember/object';
import { alias, none, not } from '@ember/object/computed';
import { scheduleOnce } from '@ember/runloop';
import JSONTreeView from 'npm:json-tree-view';
export default Component.extend({
storage: service(),
classNames: ['file-preview'],
fileLoaded: false,
uploadingChanges: false,
showEditor: null,
hideEditor: not('showEditor'),
fileContent: null,
objectURL: null,
metaData: null,
isJSON: null,
type: alias('metaData.type'),
isBinary: alias('metaData.isBinary'),
isUnknownBinary: none('isImage', 'isAudio', 'isVideo'),
isImage: function() {
return this.get('type').match(/^image\/.+$/);
}.property('type'),
isAudio: function() {
return this.get('type').match(/^audio\/.+$/);
}.property('type'),
isVideo: function() {
return this.get('type').match(/^video\/.+$/);
}.property('type'),
isText: function() {
return !this.get('isBinary');
}.property('isBinary'),
loadFile: function() {
let path = this.get('metaData.path');
if (this.get('isAudio') || this.get('isVideo')) {
this.set('fileLoaded', true);
this.set('objectURL', this.get('storage.client')
.getItemURL(path));
return;
}
// TODO don't fetch is size above certain limit
console.debug(`[file-preview] Loading file ${this.get('metaData.name')}`)
this.get('storage.client').getFile(path).then(file => {
if (this.get('isImage')) {
let view = new window.Uint8Array(file.data);
let blob = new window.Blob([view], { type: file.contentType });
this.set('objectURL', window.URL.createObjectURL(blob));
} else {
this.set('fileContent', file.data);
}
this.set('fileLoaded', true);
});
}.on('didInsertElement'),
onFileLoaded: observer('fileLoaded', function(){
if (this.get('fileLoaded') && this.get('isJSON') && this.get('jsonShowTree')) {
scheduleOnce('afterRender', this, 'renderJsonTree');
}
}),
onJsonViewChanged: observer('jsonShowTree', function(){
if (this.get('fileLoaded') && this.get('isJSON') && this.get('jsonShowTree')) {
scheduleOnce('afterRender', this, 'renderJsonTree');
}
}),
renderJsonTree () {
let value = JSON.parse(this.get('fileContent'));
let view = new JSONTreeView('content', value);
// this.attachJsonTreeEventHandlers(view);
const containerElement = document.getElementById('json-tree-view');
containerElement.innerHTML = ''; // Throw away any existing treeviews
containerElement.appendChild(view.dom);
window.jsonview = view;
view.expand(true);
view.withRootName = false;
view.readonly = this.get('hideEditor');
this.set('jsonTreeView', view);
},
attachJsonTreeEventHandlers (view) {
view.on('change', function(self, key, oldValue, newValue){
console.log('change', key, oldValue, '=>', newValue);
});
view.on('rename', function(self, key, oldName, newName) {
console.log('rename', key, oldName, '=>', newName);
});
view.on('delete', function(self, key) {
console.log('delete', key);
});
view.on('append', function(self, key, nameOrValue, newValue) {
console.log('append', key, nameOrValue, '=>', newValue);
});
view.on('click', function(self, key, value) {
console.log('click', key, '=', value);
});
view.on('expand', function(self, key, value) {
console.log('expand', key, '=', value);
});
view.on('collapse', function(self, key, value) {
console.log('collapse', key, '=', value);
});
view.on('refresh', function(self, key, value) {
console.log('refresh', key, '=', value);
});
},
onShowEditor: observer('showEditor', function(){
if (this.get('fileLoaded') && this.get('isJSON') && this.get('jsonShowTree')) {
const showEditor = this.get('showEditor');
if (showEditor) {
this.set('jsonTreeView.readonly', false);
} else {
this.set('jsonTreeView.readonly', true);
this.renderJsonTree();
}
}
}),
actions: {
saveChanges () {
const path = this.get('metaData.path');
if (this.get('isJSON') && this.get('jsonShowTree')) {
const content = JSON.stringify(this.get('jsonTreeView.value'));
this.set('uploadingChanges', true);
this.get('storage.client')
.storeFile('application/json', path, content)
.then(etag => {
this.setProperties({
'metaData.etag': etag,
fileContent: content,
showEditor: false
});
}).catch(err => {
alert('Failed to update the file. Check the console for more info.');
console.error(err);
}).finally(() => {
this.set('uploadingChanges', false);
});
} else {
console.warn('not implemented');
}
},
cancelEditor () {
this.set('showEditor', false);
}
}
});