This commit is contained in:
djmaze 2021-04-13 14:11:17 +02:00
parent 84f3a7dd77
commit 89107387d5
8 changed files with 129 additions and 213 deletions

View file

@ -13,16 +13,15 @@ const
exts = { exts = {
eml: 'message/rfc822', eml: 'message/rfc822',
mime: 'message/rfc822', mime: 'message/rfc822',
rtx: 'text/richtext',
vcard: 'text/vcard', vcard: 'text/vcard',
vcf: 'text/vcard', vcf: 'text/vcard',
htm: 'text/html', htm: 'text/html',
html: 'text/html', html: 'text/html',
csv: 'text/csv', csv: 'text/csv',
ics: 'text/calendar', ics: 'text/calendar',
ifb: 'text/calendar',
xml: 'text/xml', xml: 'text/xml',
json: app+'json', json: app+'json',
asc: app+'pgp-signature',
p10: app+'pkcs10', p10: app+'pkcs10',
p7c: app+'pkcs7-mime', p7c: app+'pkcs7-mime',
p7m: app+'pkcs7-mime', p7m: app+'pkcs7-mime',
@ -34,8 +33,7 @@ const
pl: 'text/perl', pl: 'text/perl',
css: 'text/css', css: 'text/css',
asp: 'text/asp', asp: 'text/asp',
php: app+'x-httpd-php', php: app+'x-php',
phtml: app+'x-httpd-php',
// images // images
jpg: 'image/jpeg', jpg: 'image/jpeg',
@ -101,23 +99,21 @@ const
odt: openDoc+'text', odt: openDoc+'text',
ods: openDoc+'spreadsheet', ods: openDoc+'spreadsheet',
odp: openDoc+'presentation' odp: openDoc+'presentation'
}; };
export const FileType = { export const FileType = {
Unknown: 'unknown', Unknown: 'unknown',
Text: 'text', Text: 'text',
Html: 'html',
Code: 'code', Code: 'code',
Eml: 'eml', Eml: 'eml',
WordText: 'word-text', Word: 'word',
Pdf: 'pdf', Pdf: 'pdf',
Image: 'image', Image: 'image',
Audio: 'audio', Audio: 'audio',
Video: 'video', Video: 'video',
Sheet: 'sheet', Spreadsheet: 'spreadsheet',
Presentation: 'presentation', Presentation: 'presentation',
Certificate: 'certificate', Certificate: 'certificate',
CertificateBin: 'certificate-bin',
Archive: 'archive' Archive: 'archive'
}; };
@ -138,7 +134,7 @@ export const FileInfo = {
return app + 'ms-tnef'; return app + 'ms-tnef';
} }
let ext = fileName.split('.').pop(); let ext = fileName.split('.').pop();
if (/^(txt|text|def|list|in|ini|log|sql|cfg|conf|asc)$/.test(ext)) if (/^(txt|text|def|list|in|ini|log|sql|cfg|conf)$/.test(ext))
return 'text/plain'; return 'text/plain';
if (/^(mpe?g|mpe|m1v|m2v)$/.test(ext)) if (/^(mpe?g|mpe|m1v|m2v)$/.test(ext))
return 'video/mpeg'; return 'video/mpeg';
@ -186,15 +182,12 @@ export const FileInfo = {
case 'video' == mimeTypeParts[0] || 'mkv' == ext || 'avi' == ext: case 'video' == mimeTypeParts[0] || 'mkv' == ext || 'avi' == ext:
result = FileType.Video; result = FileType.Video;
break; break;
case ['php', 'js', 'css'].includes(ext): case ['php', 'js', 'css', 'xml', 'html'].includes(ext) || 'text/html' == mimeType:
result = FileType.Code; result = FileType.Code;
break; break;
case 'eml' == ext || ['message/delivery-status', 'message/rfc822'].includes(mimeType): case 'eml' == ext || ['message/delivery-status', 'message/rfc822'].includes(mimeType):
result = FileType.Eml; result = FileType.Eml;
break; break;
case 'text/html' == mimeType || 'html' == ext:
result = FileType.Html;
break;
case 'text' == mimeTypeParts[0] || 'txt' == ext || 'log' == ext: case 'text' == mimeTypeParts[0] || 'txt' == ext || 'log' == ext:
result = FileType.Text; result = FileType.Text;
break; break;
@ -204,19 +197,17 @@ export const FileInfo = {
case 'pdf' == type || 'pdf' == ext: case 'pdf' == type || 'pdf' == ext:
result = FileType.Pdf; result = FileType.Pdf;
break; break;
case [app+'pgp-signature', app+'pgp-keys'].includes(mimeType) || case [app+'pgp-signature', app+'pgp-keys'].includes(mimeType)
['asc', 'pem', 'ppk'].includes(ext): || ['asc', 'pem', 'ppk'].includes(ext)
|| [app+'pkcs7-signature'].includes(mimeType) || 'p7s' == ext:
result = FileType.Certificate; result = FileType.Certificate;
break; break;
case [app+'pkcs7-signature'].includes(mimeType) || 'p7s' == ext:
result = FileType.CertificateBin;
break;
case match(msOffice+'.wordprocessingml') || match(openDoc+'.text') || match('vnd.ms-word') case match(msOffice+'.wordprocessingml') || match(openDoc+'.text') || match('vnd.ms-word')
|| ['rtf', 'msword', 'vnd.msword'].includes(type): || ['rtf', 'msword', 'vnd.msword'].includes(type):
result = FileType.WordText; result = FileType.Word;
break; break;
case match(msOffice+'.spreadsheetml') || match(openDoc+'.spreadsheet') || match('ms-excel'): case match(msOffice+'.spreadsheetml') || match(openDoc+'.spreadsheet') || match('ms-excel'):
result = FileType.Sheet; result = FileType.Spreadsheet;
break; break;
case match(msOffice+'.presentationml') || match(openDoc+'.presentation') || match('ms-powerpoint'): case match(msOffice+'.presentationml') || match(openDoc+'.presentation') || match('ms-powerpoint'):
result = FileType.Presentation; result = FileType.Presentation;
@ -232,43 +223,22 @@ export const FileInfo = {
* @returns {string} * @returns {string}
*/ */
getTypeIconClass: fileType => { getTypeIconClass: fileType => {
let result = ['icon-file', '']; let result = 'icon-file';
switch (fileType) { switch (fileType) {
case FileType.Text: case FileType.Text:
case FileType.Eml: case FileType.Eml:
case FileType.WordText:
result[0] += '-text';
break;
case FileType.Html:
case FileType.Code:
result[0] += '-code';
break;
case FileType.Image:
result[0] += '-image';
break;
case FileType.Audio:
result[0] += '-music';
break;
case FileType.Video:
result[0] += '-movie';
break;
case FileType.Archive:
result[0] += '-zip';
break;
case FileType.Certificate:
case FileType.CertificateBin:
result[0] += '-certificate';
break;
case FileType.Sheet:
result[0] += '-excel';
break;
case FileType.Presentation:
result[0] += '-chart-graph';
break;
case FileType.Pdf: case FileType.Pdf:
result[1] = 'pdf'; case FileType.Word:
break; return result + '-text';
// no default case FileType.Code:
case FileType.Image:
case FileType.Audio:
case FileType.Video:
case FileType.Archive:
case FileType.Certificate:
case FileType.Spreadsheet:
case FileType.Presentation:
return result + '-' + fileType;
} }
return result; return result;
}, },
@ -282,7 +252,7 @@ export const FileInfo = {
getCombinedIconClass: data => { getCombinedIconClass: data => {
if (isNonEmptyArray(data)) { if (isNonEmptyArray(data)) {
let icons = data let icons = data
.map(item => item ? FileInfo.getIconClass(FileInfo.getExtension(item[0]), item[1])[0] : '') .map(item => item ? FileInfo.getIconClass(FileInfo.getExtension(item[0]), item[1]) : '')
.validUnique(); .validUnique();
return (icons && 1 === icons.length && 'icon-file' !== icons[0]) return (icons && 1 === icons.length && 'icon-file' !== icons[0])

View file

@ -10,8 +10,6 @@ import { AbstractModel } from 'Knoin/AbstractModel';
import { SMAudio } from 'Common/Audio'; import { SMAudio } from 'Common/Audio';
const bAllowPdfPreview = undefined !== navigator.mimeTypes['application/pdf'];
export class AttachmentModel extends AbstractModel { export class AttachmentModel extends AbstractModel {
constructor() { constructor() {
super(); super();
@ -92,27 +90,21 @@ export class AttachmentModel extends AbstractModel {
* @returns {boolean} * @returns {boolean}
*/ */
isText() { isText() {
return ( return FileType.Text === this.fileType || FileType.Eml === this.fileType;
FileType.Text === this.fileType ||
FileType.Eml === this.fileType ||
FileType.Certificate === this.fileType ||
FileType.Html === this.fileType ||
FileType.Code === this.fileType
);
} }
/** /**
* @returns {boolean} * @returns {boolean}
*/ */
isPdf() { pdfPreview() {
return FileType.Pdf === this.fileType; return null != navigator.mimeTypes['application/pdf'] && FileType.Pdf === this.fileType;
} }
/** /**
* @returns {boolean} * @returns {boolean}
*/ */
hasPreview() { hasPreview() {
return this.isImage() || (this.isPdf() && bAllowPdfPreview) || this.isText(); return this.isImage() || this.pdfPreview() || this.isText();
} }
/** /**
@ -155,13 +147,6 @@ export class AttachmentModel extends AbstractModel {
return link ? 'background:url(' + link + ')' : ''; return link ? 'background:url(' + link + ')' : '';
} }
/**
* @returns {string}
*/
linkPreviewAsPlain() {
return serverRequestRaw('ViewAsPlain', this.download);
}
/** /**
* @returns {string} * @returns {string}
*/ */
@ -169,11 +154,11 @@ export class AttachmentModel extends AbstractModel {
let result = ''; let result = '';
switch (true) { switch (true) {
case this.isImage(): case this.isImage():
case this.isPdf() && bAllowPdfPreview: case this.pdfPreview():
result = this.linkPreview(); result = this.linkPreview();
break; break;
case this.isText(): case this.isText():
result = this.linkPreviewAsPlain(); result = serverRequestRaw('ViewAsPlain', this.download);
break; break;
// no default // no default
} }
@ -181,18 +166,6 @@ export class AttachmentModel extends AbstractModel {
return result; return result;
} }
/**
* @returns {string}
*/
generateTransferDownloadUrl() {
let link = this.linkDownload();
if ('http' !== link.substr(0, 4)) {
link = location.protocol + '//' + location.host + location.pathname + link;
}
return this.mimeType + ':' + this.fileName + ':' + link;
}
/** /**
* @param {AttachmentModel} attachment * @param {AttachmentModel} attachment
* @param {*} event * @param {*} event
@ -201,7 +174,11 @@ export class AttachmentModel extends AbstractModel {
eventDragStart(attachment, event) { eventDragStart(attachment, event) {
const localEvent = event.originalEvent || event; const localEvent = event.originalEvent || event;
if (attachment && localEvent && localEvent.dataTransfer && localEvent.dataTransfer.setData) { if (attachment && localEvent && localEvent.dataTransfer && localEvent.dataTransfer.setData) {
localEvent.dataTransfer.setData('DownloadURL', this.generateTransferDownloadUrl()); let link = this.linkDownload();
if ('http' !== link.substr(0, 4)) {
link = location.protocol + '//' + location.host + location.pathname + link;
}
localEvent.dataTransfer.setData('DownloadURL', this.mimeType + ':' + this.fileName + ':' + link);
} }
return true; return true;
@ -211,13 +188,6 @@ export class AttachmentModel extends AbstractModel {
* @returns {string} * @returns {string}
*/ */
iconClass() { iconClass() {
return FileInfo.getTypeIconClass(this.fileType)[0]; return FileInfo.getTypeIconClass(this.fileType);
}
/**
* @returns {string}
*/
iconText() {
return FileInfo.getTypeIconClass(this.fileType)[1];
} }
} }

View file

@ -96,13 +96,6 @@ export class ComposeAttachmentModel extends AbstractModel {
* @returns {string} * @returns {string}
*/ */
iconClass() { iconClass() {
return FileInfo.getIconClass(this.fileExt(), this.mimeType())[0]; return FileInfo.getIconClass(this.fileExt(), this.mimeType());
}
/**
* @returns {string}
*/
iconText() {
return FileInfo.getIconClass(this.fileExt(), this.mimeType())[1];
} }
} }

View file

@ -103,16 +103,6 @@
} }
} }
.attachmentIconText {
display: inline-block;
font-size: 28px;
width: 60px;
height: 56px;
color: #aaa;
line-height: 56px;
font-style: normal;
}
/* /*
.attachmentIconParent.hasPreview.isImage { .attachmentIconParent.hasPreview.isImage {
.iconMain { .iconMain {

View file

@ -744,7 +744,6 @@ END;
'sql' => 'text/plain', 'sql' => 'text/plain',
'cfg' => 'text/plain', 'cfg' => 'text/plain',
'conf' => 'text/plain', 'conf' => 'text/plain',
'asc' => 'text/plain',
'rtx' => 'text/richtext', 'rtx' => 'text/richtext',
'vcard' => 'text/vcard', 'vcard' => 'text/vcard',
'vcf' => 'text/vcard', 'vcf' => 'text/vcard',
@ -759,6 +758,7 @@ END;
'hlp' => 'application/winhlp', 'hlp' => 'application/winhlp',
'wgt' => 'application/widget', 'wgt' => 'application/widget',
'chm' => 'application/vnd.ms-htmlhelp', 'chm' => 'application/vnd.ms-htmlhelp',
'asc' => 'application/pgp-signature',
'p10' => 'application/pkcs10', 'p10' => 'application/pkcs10',
'p7c' => 'application/pkcs7-mime', 'p7c' => 'application/pkcs7-mime',
'p7m' => 'application/pkcs7-mime', 'p7m' => 'application/pkcs7-mime',
@ -770,11 +770,7 @@ END;
'pl' => 'text/perl', 'pl' => 'text/perl',
'css' => 'text/css', 'css' => 'text/css',
'asp' => 'text/asp', 'asp' => 'text/asp',
'php' => 'application/x-httpd-php', 'php' => 'application/x-php',
'php3' => 'application/x-httpd-php',
'php4' => 'application/x-httpd-php',
'php5' => 'application/x-httpd-php',
'phtml' => 'application/x-httpd-php',
// images // images
'png' => 'image/png', 'png' => 'image/png',

View file

@ -278,15 +278,13 @@
<div class="attachmentIconParent" data-bind="css: { 'hasPreview': hasPreview(), 'hasPreplay': hasPreplay(), 'isImage': isImage() }"> <div class="attachmentIconParent" data-bind="css: { 'hasPreview': hasPreview(), 'hasPreplay': hasPreplay(), 'isImage': isImage() }">
<div class="hidePreview"> <div class="hidePreview">
<div class="iconMain"> <div class="iconMain">
<i class="attachmentIcon attachmentMainIcon" data-bind="css: iconClass()"></i> <i class="attachmentIcon" data-bind="css: iconClass()"></i>
<i class="attachmentIconText attachmentMainIconText" data-bind="text: iconText()"></i>
</div> </div>
</div> </div>
<div class="showPreview"> <div class="showPreview">
<a data-bind="click: $root.attachmentPreview, css: {'attachmentImagePreview': isImage(), 'visible': !isLinked}, attr: { 'title': fileName, 'href': linkPreviewMain() }" target="_blank"> <a data-bind="click: $root.attachmentPreview, css: {'attachmentImagePreview': isImage(), 'visible': !isLinked}, attr: { 'title': fileName, 'href': linkPreviewMain() }" target="_blank">
<div class="iconMain"> <div class="iconMain">
<i class="attachmentIcon attachmentMainIcon" data-bind="css: iconClass()"></i> <i class="attachmentIcon" data-bind="css: iconClass()"></i>
<i class="attachmentIconText attachmentMainIconText" data-bind="text: iconText()"></i>
</div> </div>
<div class="iconBG" data-bind="attr: { 'style': linkThumbnailPreviewStyle() }"></div> <div class="iconBG" data-bind="attr: { 'style': linkThumbnailPreviewStyle() }"></div>
<div class="iconPreview attachmentIcon fontastic show-hover">👁</div> <div class="iconPreview attachmentIcon fontastic show-hover">👁</div>
@ -294,7 +292,7 @@
</div> </div>
<div class="showPreplay"> <div class="showPreplay">
<div class="iconMain"> <div class="iconMain">
<i class="attachmentIcon attachmentMainIcon" data-bind="css: iconClass()"></i> <i class="attachmentIcon" data-bind="css: iconClass()"></i>
</div> </div>
<div class="iconPreview attachmentIcon fontastic show-hover"></div> <div class="iconPreview attachmentIcon fontastic show-hover"></div>
</div> </div>
@ -316,8 +314,8 @@
<span data-bind="visible: downloadAsZipAllowed"> <span data-bind="visible: downloadAsZipAllowed">
<i class="fontastic iconcolor-red" data-bind="visible: downloadAsZipError"></i> <i class="fontastic iconcolor-red" data-bind="visible: downloadAsZipError"></i>
<i class="icon-file-zip" data-bind="visible: !downloadAsZipError(), <i class="icon-file-archive" data-bind="visible: !downloadAsZipError(),
css: {'icon-file-zip': !downloadAsZipLoading(), 'icon-spinner': downloadAsZipLoading()}"></i> css: {'icon-file-archive': !downloadAsZipLoading(), 'icon-spinner': downloadAsZipLoading()}"></i>
<span class="g-ui-link" data-bind="click: downloadAsZip" <span class="g-ui-link" data-bind="click: downloadAsZip"
data-i18n="MESSAGE/LINK_DOWNLOAD_AS_ZIP"></span> data-i18n="MESSAGE/LINK_DOWNLOAD_AS_ZIP"></span>
</span> </span>

View file

@ -171,8 +171,7 @@
<li class="attachmentItem" data-bind="attr: { 'title': title }, css: { 'waiting': waiting, 'error': '' !== error() }"> <li class="attachmentItem" data-bind="attr: { 'title': title }, css: { 'waiting': waiting, 'error': '' !== error() }">
<div class="attachmentIconParent"> <div class="attachmentIconParent">
<div class="iconMain"> <div class="iconMain">
<i class="attachmentIcon attachmentMainIcon" data-bind="css: iconClass(), visible: !uploading() || 0 === progress()"></i> <i class="attachmentIcon" data-bind="css: iconClass(), visible: !uploading() || 0 === progress()"></i>
<i class="attachmentIconText attachmentMainIconText" data-bind="text: iconText(), visible: !uploading() || 0 === progress()"></i>
</div> </div>
<div class="iconProgress" data-bind="attr: { 'style': progressStyle }, visible: uploading"></div> <div class="iconProgress" data-bind="attr: { 'style': progressStyle }, visible: uploading"></div>
<div class="iconBG" data-bind="text: progressText, visible: uploading"></div> <div class="iconBG" data-bind="text: progressText, visible: uploading"></div>

View file

@ -55,13 +55,13 @@
.icon-file-code::before { .icon-file-code::before {
content: "\e030"; content: "\e030";
} }
.icon-file-chart-graph::before { .icon-file-presentation::before {
content: "\e031"; /* 📊 */ content: "\e031"; /* 📊 */
} }
.icon-file-zip::before { .icon-file-archive::before {
content: "\e032"; content: "\e032";
} }
.icon-file-music::before { .icon-file-audio::before {
content: "\e033"; content: "\e033";
} }
.icon-file-text::before { .icon-file-text::before {
@ -76,10 +76,10 @@
.icon-attachment::before { .icon-attachment::before {
content: "📎"; content: "📎";
} }
.icon-file-excel::before { .icon-file-spreadsheet::before {
content: "\e03a"; content: "\e03a";
} }
.icon-file-movie::before { .icon-file-video::before {
content: "\e03b"; content: "\e03b";
} }
.icon-folder-add::before { .icon-folder-add::before {