|
@@ -20,6 +20,44 @@ import {MediaboxService} from '../services/mediabox';
|
|
|
import {MessageService} from '../services/message';
|
|
|
import {WebClientService} from '../services/webclient';
|
|
|
|
|
|
+function showAudioDialog(
|
|
|
+ $mdDialog: ng.material.IDialogService,
|
|
|
+ $log: ng.ILogService,
|
|
|
+ blobInfo: threema.BlobInfo,
|
|
|
+): void {
|
|
|
+ $mdDialog.show({
|
|
|
+ controllerAs: 'ctrl',
|
|
|
+ controller: function() {
|
|
|
+ this.cancel = () => $mdDialog.cancel();
|
|
|
+ this.audioSrc = bufferToUrl(
|
|
|
+ blobInfo.buffer,
|
|
|
+ blobInfo.mimetype,
|
|
|
+ logAdapter($log.warn, '[AudioPlayerDialog]'),
|
|
|
+ );
|
|
|
+ },
|
|
|
+ template: `
|
|
|
+ <md-dialog translate-attr="{'aria-label': 'messageTypes.AUDIO_MESSAGE'}">
|
|
|
+ <md-toolbar>
|
|
|
+ <div class="md-toolbar-tools">
|
|
|
+ <h2 translate>messageTypes.AUDIO_MESSAGE</h2>
|
|
|
+ </div>
|
|
|
+ </md-toolbar>
|
|
|
+ <md-dialog-content layout="row" layout-align="center">
|
|
|
+ <audio controls autoplay ng-src="{{ ctrl.audioSrc | unsafeResUrl }}">
|
|
|
+ Your browser does not support the <code>audio</code> element.
|
|
|
+ </audio>
|
|
|
+ </md-dialog-content>
|
|
|
+ <md-dialog-actions layout="row" >
|
|
|
+ <md-button ng-click="ctrl.cancel()">
|
|
|
+ <span translate>common.OK</span>
|
|
|
+ </md-button>
|
|
|
+ </md-dialog-actions>
|
|
|
+ </md-dialog>`,
|
|
|
+ parent: angular.element(document.body),
|
|
|
+ clickOutsideToClose: true,
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
export default [
|
|
|
'WebClientService',
|
|
|
'MediaboxService',
|
|
@@ -53,224 +91,194 @@ export default [
|
|
|
controller: [function() {
|
|
|
this.logTag = '[MessageMedia]';
|
|
|
|
|
|
- this.type = this.message.type;
|
|
|
+ this.$onInit = function() {
|
|
|
+ this.type = this.message.type;
|
|
|
|
|
|
- // Downloading
|
|
|
- this.downloading = false;
|
|
|
- this.thumbnailDownloading = false;
|
|
|
- this.downloaded = false;
|
|
|
+ // Downloading
|
|
|
+ this.downloading = false;
|
|
|
+ this.thumbnailDownloading = false;
|
|
|
+ this.downloaded = false;
|
|
|
|
|
|
- // Uploading
|
|
|
- this.uploading = this.message.temporaryId !== undefined
|
|
|
- && this.message.temporaryId !== null;
|
|
|
+ // Uploading
|
|
|
+ this.uploading = this.message.temporaryId !== undefined
|
|
|
+ && this.message.temporaryId !== null;
|
|
|
|
|
|
- // AnimGIF detection
|
|
|
- this.isAnimGif = !this.uploading
|
|
|
- && (this.message as threema.Message).type === 'file'
|
|
|
- && (this.message as threema.Message).file.type === 'image/gif';
|
|
|
+ // AnimGIF detection
|
|
|
+ this.isAnimGif = !this.uploading
|
|
|
+ && (this.message as threema.Message).type === 'file'
|
|
|
+ && (this.message as threema.Message).file.type === 'image/gif';
|
|
|
|
|
|
- // Preview thumbnail
|
|
|
- let thumbnailPreviewUri = null;
|
|
|
- this.getThumbnailPreviewUri = () => {
|
|
|
- // Cache thumbnail preview URI
|
|
|
- if (thumbnailPreviewUri === null && hasValue(this.message) && hasValue(this.message.thumbnail)) {
|
|
|
- thumbnailPreviewUri = bufferToUrl(
|
|
|
- (this.message as threema.Message).thumbnail.preview,
|
|
|
- webClientService.appCapabilities.imageFormat.thumbnail,
|
|
|
- logAdapter($log.warn, this.logTag),
|
|
|
- );
|
|
|
- }
|
|
|
- return thumbnailPreviewUri;
|
|
|
- };
|
|
|
+ // Preview thumbnail
|
|
|
+ let thumbnailPreviewUri = null;
|
|
|
+ this.getThumbnailPreviewUri = () => {
|
|
|
+ // Cache thumbnail preview URI
|
|
|
+ if (thumbnailPreviewUri === null
|
|
|
+ && hasValue(this.message) && hasValue(this.message.thumbnail)) {
|
|
|
+ thumbnailPreviewUri = bufferToUrl(
|
|
|
+ (this.message as threema.Message).thumbnail.preview,
|
|
|
+ webClientService.appCapabilities.imageFormat.thumbnail,
|
|
|
+ logAdapter($log.warn, this.logTag),
|
|
|
+ );
|
|
|
+ }
|
|
|
+ return thumbnailPreviewUri;
|
|
|
+ };
|
|
|
|
|
|
- // Thumbnail loading
|
|
|
- //
|
|
|
- // Do not show thumbnail in file messages (except anim gif).
|
|
|
- // If a thumbnail in file messages are available, the thumbnail
|
|
|
- // will be shown in the file circle
|
|
|
- this.showThumbnail = this.message.thumbnail !== undefined
|
|
|
- && ((this.message as threema.Message).type !== 'file' || this.isAnimGif);
|
|
|
- this.thumbnail = null;
|
|
|
- this.thumbnailFormat = webClientService.appCapabilities.imageFormat.thumbnail;
|
|
|
- if (this.message.thumbnail !== undefined) {
|
|
|
- this.thumbnailStyle = {
|
|
|
- width: this.message.thumbnail.width + 'px',
|
|
|
- height: this.message.thumbnail.height + 'px' };
|
|
|
- }
|
|
|
+ // Thumbnail loading
|
|
|
+ //
|
|
|
+ // Do not show thumbnail in file messages (except anim gif).
|
|
|
+ // If a thumbnail in file messages are available, the thumbnail
|
|
|
+ // will be shown in the file circle
|
|
|
+ this.showThumbnail = this.message.thumbnail !== undefined
|
|
|
+ && ((this.message as threema.Message).type !== 'file' || this.isAnimGif);
|
|
|
+ this.thumbnail = null;
|
|
|
+ this.thumbnailFormat = webClientService.appCapabilities.imageFormat.thumbnail;
|
|
|
+ if (this.message.thumbnail !== undefined) {
|
|
|
+ this.thumbnailStyle = {
|
|
|
+ width: this.message.thumbnail.width + 'px',
|
|
|
+ height: this.message.thumbnail.height + 'px' };
|
|
|
+ }
|
|
|
|
|
|
- let loadingThumbnailTimeout = null;
|
|
|
+ let loadingThumbnailTimeout = null;
|
|
|
|
|
|
- this.wasInView = false;
|
|
|
- this.thumbnailInView = (inView: boolean) => {
|
|
|
- if (this.message.thumbnail === undefined
|
|
|
- || this.wasInView === inView) {
|
|
|
- // do nothing
|
|
|
- return;
|
|
|
- }
|
|
|
- this.wasInView = inView;
|
|
|
+ this.wasInView = false;
|
|
|
+ this.thumbnailInView = (inView: boolean) => {
|
|
|
+ if (this.message.thumbnail === undefined
|
|
|
+ || this.wasInView === inView) {
|
|
|
+ // do nothing
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.wasInView = inView;
|
|
|
|
|
|
- if (!inView) {
|
|
|
- $timeout.cancel(loadingThumbnailTimeout);
|
|
|
- this.thumbnailDownloading = false;
|
|
|
- this.thumbnail = null;
|
|
|
- } else {
|
|
|
- if (this.thumbnail === null) {
|
|
|
- const setThumbnail = (buf: ArrayBuffer) => {
|
|
|
- this.thumbnail = bufferToUrl(
|
|
|
- buf,
|
|
|
- webClientService.appCapabilities.imageFormat.thumbnail,
|
|
|
- logAdapter($log.warn, this.logTag),
|
|
|
- );
|
|
|
- };
|
|
|
+ if (!inView) {
|
|
|
+ $timeout.cancel(loadingThumbnailTimeout);
|
|
|
+ this.thumbnailDownloading = false;
|
|
|
+ this.thumbnail = null;
|
|
|
+ } else {
|
|
|
+ if (this.thumbnail === null) {
|
|
|
+ const setThumbnail = (buf: ArrayBuffer) => {
|
|
|
+ this.thumbnail = bufferToUrl(
|
|
|
+ buf,
|
|
|
+ webClientService.appCapabilities.imageFormat.thumbnail,
|
|
|
+ logAdapter($log.warn, this.logTag),
|
|
|
+ );
|
|
|
+ };
|
|
|
|
|
|
- if (this.message.thumbnail.img !== undefined) {
|
|
|
- setThumbnail(this.message.thumbnail.img);
|
|
|
- return;
|
|
|
- } else {
|
|
|
- this.thumbnailDownloading = true;
|
|
|
- loadingThumbnailTimeout = $timeout(() => {
|
|
|
- webClientService
|
|
|
- .requestThumbnail(this.receiver, this.message)
|
|
|
- .then((img) => $timeout(() => {
|
|
|
- setThumbnail(img);
|
|
|
- this.thumbnailDownloading = false;
|
|
|
- }));
|
|
|
- }, 1000);
|
|
|
+ if (this.message.thumbnail.img !== undefined) {
|
|
|
+ setThumbnail(this.message.thumbnail.img);
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ this.thumbnailDownloading = true;
|
|
|
+ loadingThumbnailTimeout = $timeout(() => {
|
|
|
+ webClientService
|
|
|
+ .requestThumbnail(this.receiver, this.message)
|
|
|
+ .then((img) => $timeout(() => {
|
|
|
+ setThumbnail(img);
|
|
|
+ this.thumbnailDownloading = false;
|
|
|
+ }));
|
|
|
+ }, 1000);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+ };
|
|
|
+
|
|
|
+ // For locations, retrieve the coordinates
|
|
|
+ this.location = null;
|
|
|
+ if (this.message.location !== undefined) {
|
|
|
+ this.location = this.message.location;
|
|
|
+ this.downloaded = true;
|
|
|
}
|
|
|
- };
|
|
|
|
|
|
- // For locations, retrieve the coordinates
|
|
|
- this.location = null;
|
|
|
- if (this.message.location !== undefined) {
|
|
|
- this.location = this.message.location;
|
|
|
- this.downloaded = true;
|
|
|
- }
|
|
|
+ // Open map link in new window using mapLink-filter
|
|
|
+ this.openMapLink = () => {
|
|
|
+ $window.open($filter<any>('mapLink')(this.location), '_blank');
|
|
|
+ };
|
|
|
|
|
|
- // Open map link in new window using mapLink-filter
|
|
|
- this.openMapLink = () => {
|
|
|
- $window.open($filter<any>('mapLink')(this.location), '_blank');
|
|
|
- };
|
|
|
+ // Play a Audio file in a dialog
|
|
|
+ this.playAudio = (blobInfo: threema.BlobInfo) => showAudioDialog($mdDialog, $log, blobInfo);
|
|
|
|
|
|
- // Play a Audio file in a dialog
|
|
|
- this.playAudio = (blobInfo: threema.BlobInfo) => {
|
|
|
- $mdDialog.show({
|
|
|
- controllerAs: 'ctrl',
|
|
|
- controller: function() {
|
|
|
- this.blobBuffer = blobInfo.buffer;
|
|
|
- this.mimeType = blobInfo.mimetype;
|
|
|
- this.cancel = () => {
|
|
|
- $mdDialog.cancel();
|
|
|
- };
|
|
|
- },
|
|
|
- template: `
|
|
|
- <md-dialog translate-attr="{'aria-label': 'messageTypes.AUDIO_MESSAGE'}">
|
|
|
- <md-toolbar>
|
|
|
- <div class="md-toolbar-tools">
|
|
|
- <h2 translate>messageTypes.AUDIO_MESSAGE</h2>
|
|
|
- </div>
|
|
|
- </md-toolbar>
|
|
|
- <md-dialog-content layout="row" layout-align="center">
|
|
|
- <audio
|
|
|
- controls
|
|
|
- autoplay ng-src="{{ ctrl.blobBuffer | bufferToUrl:ctrl.mimeType }}">
|
|
|
- Your browser does not support the <code>audio</code> element.
|
|
|
- </audio>
|
|
|
- </md-dialog-content>
|
|
|
- <md-dialog-actions layout="row" >
|
|
|
- <md-button ng-click="ctrl.cancel()">
|
|
|
- <span translate>common.OK</span>
|
|
|
- </md-button>
|
|
|
- </md-dialog-actions>
|
|
|
- </md-dialog>`,
|
|
|
- parent: angular.element(document.body),
|
|
|
- clickOutsideToClose: true,
|
|
|
- });
|
|
|
- };
|
|
|
-
|
|
|
- // Download function
|
|
|
- this.download = () => {
|
|
|
- $log.debug(this.logTag, 'Download blob');
|
|
|
- if (this.downloading) {
|
|
|
- $log.debug(this.logTag, 'Download already in progress...');
|
|
|
- return;
|
|
|
- }
|
|
|
- const message: threema.Message = this.message;
|
|
|
- const receiver: threema.Receiver = this.receiver;
|
|
|
- this.downloading = true;
|
|
|
- webClientService.requestBlob(message.id, receiver)
|
|
|
- .then((blobInfo: threema.BlobInfo) => {
|
|
|
- $rootScope.$apply(() => {
|
|
|
- $log.debug(this.logTag, 'Blob loaded');
|
|
|
- this.downloading = false;
|
|
|
- this.downloaded = true;
|
|
|
+ // Download function
|
|
|
+ this.download = () => {
|
|
|
+ $log.debug(this.logTag, 'Download blob');
|
|
|
+ if (this.downloading) {
|
|
|
+ $log.debug(this.logTag, 'Download already in progress...');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const message: threema.Message = this.message;
|
|
|
+ const receiver: threema.Receiver = this.receiver;
|
|
|
+ this.downloading = true;
|
|
|
+ webClientService.requestBlob(message.id, receiver)
|
|
|
+ .then((blobInfo: threema.BlobInfo) => {
|
|
|
+ $rootScope.$apply(() => {
|
|
|
+ $log.debug(this.logTag, 'Blob loaded');
|
|
|
+ this.downloading = false;
|
|
|
+ this.downloaded = true;
|
|
|
|
|
|
- switch (this.message.type) {
|
|
|
- case 'image':
|
|
|
- const caption = message.caption || '';
|
|
|
- mediaboxService.setMedia(
|
|
|
- blobInfo.buffer,
|
|
|
- blobInfo.filename,
|
|
|
- blobInfo.mimetype,
|
|
|
- caption,
|
|
|
- );
|
|
|
- break;
|
|
|
- case 'video':
|
|
|
- saveAs(new Blob([blobInfo.buffer]), blobInfo.filename);
|
|
|
- break;
|
|
|
- case 'file':
|
|
|
- if (this.message.file.type === 'image/gif') {
|
|
|
- // Show inline
|
|
|
- this.blobBufferUrl = bufferToUrl(
|
|
|
+ switch (this.message.type) {
|
|
|
+ case 'image':
|
|
|
+ const caption = message.caption || '';
|
|
|
+ mediaboxService.setMedia(
|
|
|
blobInfo.buffer,
|
|
|
- 'image/gif',
|
|
|
- logAdapter($log.warn, this.logTag),
|
|
|
+ blobInfo.filename,
|
|
|
+ blobInfo.mimetype,
|
|
|
+ caption,
|
|
|
);
|
|
|
- // Hide thumbnail
|
|
|
- this.showThumbnail = false;
|
|
|
- } else {
|
|
|
+ break;
|
|
|
+ case 'video':
|
|
|
saveAs(new Blob([blobInfo.buffer]), blobInfo.filename);
|
|
|
- }
|
|
|
- break;
|
|
|
- case 'audio':
|
|
|
- // Show inline
|
|
|
- this.playAudio(blobInfo);
|
|
|
- break;
|
|
|
- default:
|
|
|
- $log.warn(this.logTag,
|
|
|
- 'Ignored download request for message type', this.message.type);
|
|
|
- }
|
|
|
- });
|
|
|
- })
|
|
|
- .catch((error) => {
|
|
|
- $rootScope.$apply(() => {
|
|
|
- this.downloading = false;
|
|
|
- let contentString;
|
|
|
- switch (error) {
|
|
|
- case 'blobDownloadFailed':
|
|
|
- contentString = 'error.BLOB_DOWNLOAD_FAILED';
|
|
|
- break;
|
|
|
- case 'blobDecryptFailed':
|
|
|
- contentString = 'error.BLOB_DECRYPT_FAILED';
|
|
|
- break;
|
|
|
- default:
|
|
|
- contentString = 'error.ERROR_OCCURRED';
|
|
|
- break;
|
|
|
- }
|
|
|
- const confirm = $mdDialog.alert()
|
|
|
- .title($translate.instant('common.ERROR'))
|
|
|
- .textContent($translate.instant(contentString))
|
|
|
- .ok($translate.instant('common.OK'));
|
|
|
- $mdDialog.show(confirm);
|
|
|
+ break;
|
|
|
+ case 'file':
|
|
|
+ if (this.message.file.type === 'image/gif') {
|
|
|
+ // Show inline
|
|
|
+ this.blobBufferUrl = bufferToUrl(
|
|
|
+ blobInfo.buffer,
|
|
|
+ 'image/gif',
|
|
|
+ logAdapter($log.warn, this.logTag),
|
|
|
+ );
|
|
|
+ // Hide thumbnail
|
|
|
+ this.showThumbnail = false;
|
|
|
+ } else {
|
|
|
+ saveAs(new Blob([blobInfo.buffer]), blobInfo.filename);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 'audio':
|
|
|
+ // Show inline
|
|
|
+ this.playAudio(blobInfo);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ $log.warn(this.logTag,
|
|
|
+ 'Ignored download request for message type', this.message.type);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ })
|
|
|
+ .catch((error) => {
|
|
|
+ $rootScope.$apply(() => {
|
|
|
+ this.downloading = false;
|
|
|
+ let contentString;
|
|
|
+ switch (error) {
|
|
|
+ case 'blobDownloadFailed':
|
|
|
+ contentString = 'error.BLOB_DOWNLOAD_FAILED';
|
|
|
+ break;
|
|
|
+ case 'blobDecryptFailed':
|
|
|
+ contentString = 'error.BLOB_DECRYPT_FAILED';
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ contentString = 'error.ERROR_OCCURRED';
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ const confirm = $mdDialog.alert()
|
|
|
+ .title($translate.instant('common.ERROR'))
|
|
|
+ .textContent($translate.instant(contentString))
|
|
|
+ .ok($translate.instant('common.OK'));
|
|
|
+ $mdDialog.show(confirm);
|
|
|
+ });
|
|
|
});
|
|
|
- });
|
|
|
- };
|
|
|
+ };
|
|
|
|
|
|
- this.isDownloading = () => {
|
|
|
- return this.downloading
|
|
|
- || this.thumbnailDownloading
|
|
|
- || (this.showDownloading && this.showDownloading());
|
|
|
+ this.isDownloading = () => {
|
|
|
+ return this.downloading
|
|
|
+ || this.thumbnailDownloading
|
|
|
+ || (this.showDownloading && this.showDownloading());
|
|
|
+ };
|
|
|
};
|
|
|
}],
|
|
|
templateUrl: 'directives/message_media.html',
|