mirror of
https://github.com/oxen-io/session-desktop.git
synced 2023-12-14 02:12:57 +01:00
Improve unsupported file type handling
Make arbitrary files look nicer and display the filename. If an audio or video element fails to load for any reason, timeout after a few seconds and render it as an arbitrary file. Also short circuit to this treatment for common audio and video file types that we know are going to fail, e.g., proprietary formats from apple. // FREEBIE
This commit is contained in:
parent
27a1c9f18a
commit
a27ea20f3e
7 changed files with 119 additions and 23 deletions
|
@ -151,6 +151,10 @@
|
||||||
<img src='{{ source }}' class='preview' />
|
<img src='{{ source }}' class='preview' />
|
||||||
<a class='x close' alt='remove attachment' href='#'></a>
|
<a class='x close' alt='remove attachment' href='#'></a>
|
||||||
</script>
|
</script>
|
||||||
|
<script type='text/x-tmpl-mustache' id='file-view'>
|
||||||
|
<span class='icon'></span>
|
||||||
|
<span class='fileName' alt='{{ fileName }}' title='{{ altText }}'>{{ fileName }}</a>
|
||||||
|
</script>
|
||||||
<script type='text/x-tmpl-mustache' id='hasRetry'>
|
<script type='text/x-tmpl-mustache' id='hasRetry'>
|
||||||
{{ messageNotSent }}
|
{{ messageNotSent }}
|
||||||
<span href='#' class='retry'>{{ resend }}</span>
|
<span href='#' class='retry'>{{ resend }}</span>
|
||||||
|
|
1
images/file.svg
Normal file
1
images/file.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48"><path d="M12 4C9.79 4 8.02 5.79 8.02 8L8 40c0 2.21 1.77 4 3.98 4H36c2.21 0 4-1.79 4-4V16L28 4H12zm14 14V7l11 11H26z"/></svg>
|
After Width: | Height: | Size: 207 B |
|
@ -4,16 +4,15 @@
|
||||||
(function () {
|
(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var FileView = Backbone.View.extend({
|
var FileView = Whisper.View.extend({
|
||||||
tagName: 'a',
|
tagName: 'div',
|
||||||
initialize: function(dataUrl) {
|
className: 'fileView',
|
||||||
this.dataUrl = dataUrl;
|
templateName: 'file-view',
|
||||||
this.$el.text(i18n('unsupportedAttachment'));
|
render_attributes: function() {
|
||||||
},
|
return {
|
||||||
render: function() {
|
fileName : this.model.fileName,
|
||||||
this.$el.attr('href', this.dataUrl);
|
altText : i18n('unsupportedAttachment')
|
||||||
this.trigger('update');
|
};
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -58,6 +57,12 @@
|
||||||
var AudioView = MediaView.extend({ tagName: 'audio' });
|
var AudioView = MediaView.extend({ tagName: 'audio' });
|
||||||
var VideoView = MediaView.extend({ tagName: 'video' });
|
var VideoView = MediaView.extend({ tagName: 'video' });
|
||||||
|
|
||||||
|
// Blacklist common file types known to be unsupported in Chrome
|
||||||
|
var UnsupportedFileTypes = [
|
||||||
|
'audio/aiff',
|
||||||
|
'video/quicktime'
|
||||||
|
];
|
||||||
|
|
||||||
Whisper.AttachmentView = Backbone.View.extend({
|
Whisper.AttachmentView = Backbone.View.extend({
|
||||||
tagName: 'span',
|
tagName: 'span',
|
||||||
className: 'attachment',
|
className: 'attachment',
|
||||||
|
@ -76,9 +81,6 @@
|
||||||
},
|
},
|
||||||
onclick: function(e) {
|
onclick: function(e) {
|
||||||
switch (this.contentType) {
|
switch (this.contentType) {
|
||||||
case 'audio':
|
|
||||||
case 'video':
|
|
||||||
return;
|
|
||||||
case 'image':
|
case 'image':
|
||||||
var view = new Whisper.LightboxView({ model: this });
|
var view = new Whisper.LightboxView({ model: this });
|
||||||
view.render();
|
view.render();
|
||||||
|
@ -86,6 +88,10 @@
|
||||||
view.$el.trigger('show');
|
view.$el.trigger('show');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'video':
|
||||||
|
if (this.view instanceof MediaView) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
this.saveFile();
|
this.saveFile();
|
||||||
}
|
}
|
||||||
|
@ -126,18 +132,39 @@
|
||||||
var View;
|
var View;
|
||||||
switch(this.contentType) {
|
switch(this.contentType) {
|
||||||
case 'image': View = ImageView; break;
|
case 'image': View = ImageView; break;
|
||||||
case 'audio': View = AudioView; break;
|
|
||||||
case 'video': View = VideoView; break;
|
case 'video': View = VideoView; break;
|
||||||
default : View = FileView; break;
|
case 'audio': View = AudioView; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!View || _.contains(UnsupportedFileTypes, this.model.contentType)) {
|
||||||
|
return this.renderFileView();
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.objectUrl) {
|
if (!this.objectUrl) {
|
||||||
this.objectUrl = window.URL.createObjectURL(this.blob);
|
this.objectUrl = window.URL.createObjectURL(this.blob);
|
||||||
}
|
}
|
||||||
var view = new View(this.objectUrl, this.model.contentType);
|
this.view = new View(this.objectUrl, this.model.contentType);
|
||||||
view.$el.appendTo(this.$el);
|
this.view.$el.appendTo(this.$el);
|
||||||
view.on('update', this.trigger.bind(this, 'update'));
|
this.listenTo(this.view, 'update', this.update);
|
||||||
view.render();
|
this.view.render();
|
||||||
|
this.timeout = setTimeout(this.onTimeout.bind(this), 3000);
|
||||||
return this;
|
return this;
|
||||||
|
},
|
||||||
|
onTimeout: function() {
|
||||||
|
// Image or media element failed to load. Fall back to FileView.
|
||||||
|
this.stopListening(this.view);
|
||||||
|
this.renderFileView();
|
||||||
|
},
|
||||||
|
renderFileView: function() {
|
||||||
|
this.view = new FileView({model: {fileName: this.suggestedName()}});
|
||||||
|
this.view.$el.appendTo(this.$el.empty());
|
||||||
|
this.view.render();
|
||||||
|
this.update();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
update: function() {
|
||||||
|
clearTimeout(this.timeout);
|
||||||
|
this.trigger('update');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -465,6 +465,39 @@ li.entry .error-icon-container {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fileView {
|
||||||
|
position: relative;
|
||||||
|
padding: 5px;
|
||||||
|
padding-right: 10px;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border: 1px solid $grey_l2;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
cursor: pointer;
|
||||||
|
color: $grey_d;
|
||||||
|
|
||||||
|
.icon, .fileName {
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.icon, .fileName {
|
||||||
|
opacity: 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
&:before {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
width: $button-height;
|
||||||
|
height: $button-height;
|
||||||
|
@include color-svg('/images/file.svg', black);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.outgoing .avatar {
|
.outgoing .avatar {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0 50px;
|
padding: 0 60px;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
|
|
@ -83,7 +83,7 @@ $text-dark: #CCCCCC;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@include color-svg('/images/double-check.svg', white);
|
@include color-svg('/images/double-check.svg', white);
|
||||||
}
|
}
|
||||||
.paperclip:before {
|
.file-input .paperclip:before {
|
||||||
content: '';
|
content: '';
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: $button-height;
|
width: $button-height;
|
||||||
|
|
|
@ -551,7 +551,7 @@ input[type=text]:active, input[type=text]:focus, input[type=search]:active, inpu
|
||||||
background-color: rgba(0, 0, 0, 0.8); }
|
background-color: rgba(0, 0, 0, 0.8); }
|
||||||
.lightbox.modal .content {
|
.lightbox.modal .content {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0 50px;
|
padding: 0 60px;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
@ -1313,6 +1313,37 @@ li.entry .error-icon-container {
|
||||||
.message-container .attachments img,
|
.message-container .attachments img,
|
||||||
.message-list .attachments img {
|
.message-list .attachments img {
|
||||||
cursor: pointer; }
|
cursor: pointer; }
|
||||||
|
.message-container .attachments .fileView,
|
||||||
|
.message-list .attachments .fileView {
|
||||||
|
position: relative;
|
||||||
|
padding: 5px;
|
||||||
|
padding-right: 10px;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border: 1px solid #d9d9d9;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #454545; }
|
||||||
|
.message-container .attachments .fileView .icon, .message-container .attachments .fileView .fileName,
|
||||||
|
.message-list .attachments .fileView .icon,
|
||||||
|
.message-list .attachments .fileView .fileName {
|
||||||
|
opacity: 0.75; }
|
||||||
|
.message-container .attachments .fileView:hover .icon, .message-container .attachments .fileView:hover .fileName,
|
||||||
|
.message-list .attachments .fileView:hover .icon,
|
||||||
|
.message-list .attachments .fileView:hover .fileName {
|
||||||
|
opacity: 1.0; }
|
||||||
|
.message-container .attachments .fileView .icon,
|
||||||
|
.message-list .attachments .fileView .icon {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle; }
|
||||||
|
.message-container .attachments .fileView .icon:before,
|
||||||
|
.message-list .attachments .fileView .icon:before {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
-webkit-mask: url("/images/file.svg") no-repeat center;
|
||||||
|
-webkit-mask-size: 100%;
|
||||||
|
background-color: black; }
|
||||||
.message-container .outgoing .avatar,
|
.message-container .outgoing .avatar,
|
||||||
.message-list .outgoing .avatar {
|
.message-list .outgoing .avatar {
|
||||||
display: none; }
|
display: none; }
|
||||||
|
@ -1820,7 +1851,7 @@ li.entry .error-icon-container {
|
||||||
-webkit-mask: url("/images/double-check.svg") no-repeat center;
|
-webkit-mask: url("/images/double-check.svg") no-repeat center;
|
||||||
-webkit-mask-size: 100%;
|
-webkit-mask-size: 100%;
|
||||||
background-color: white; }
|
background-color: white; }
|
||||||
.android-dark .paperclip:before {
|
.android-dark .file-input .paperclip:before {
|
||||||
content: '';
|
content: '';
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
|
|
Loading…
Reference in a new issue