mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-10 06:58:27 +03:00
Merge file and mime code into simple Common/File.js
This commit is contained in:
parent
cb2048f163
commit
9992b20163
9 changed files with 345 additions and 452 deletions
22
README.md
22
README.md
|
|
@ -106,22 +106,22 @@ RainLoop 1.14 vs SnappyMail
|
|||
|
||||
|js/* |RainLoop |Snappy |
|
||||
|----------- |--------: |--------: |
|
||||
|admin.js |2.130.942 | 825.627 |
|
||||
|app.js |4.184.455 |2.463.325 |
|
||||
|admin.js |2.130.942 | 798.252 |
|
||||
|app.js |4.184.455 |2.450.286 |
|
||||
|boot.js | 671.522 | 5.285 |
|
||||
|libs.js | 647.614 | 253.356 |
|
||||
|libs.js | 647.614 | 254.910 |
|
||||
|polyfills.js | 325.834 | 0 |
|
||||
|TOTAL |7.960.367 |3.547.593 |
|
||||
|TOTAL |7.960.367 |3.508.733 |
|
||||
|
||||
|js/min/* |RainLoop |Snappy |Rain gzip |gzip |brotli |
|
||||
|--------------- |--------: |--------: |--------: |--------: |--------: |
|
||||
|admin.min.js | 252.147 | 112.115 | 73.657 | 30.610 | 26.437 |
|
||||
|app.min.js | 511.202 | 334.897 |140.462 | 86.030 | 69.713 |
|
||||
|admin.min.js | 252.147 | 106.871 | 73.657 | 28.834 | 25.063 |
|
||||
|app.min.js | 511.202 | 332.055 |140.462 | 85.613 | 69.336 |
|
||||
|boot.min.js | 66.007 | 2.935 | 22.567 | 1.510 | 1.285 |
|
||||
|libs.min.js | 572.545 | 149.819 |176.720 | 52.834 | 46.924 |
|
||||
|libs.min.js | 572.545 | 149.580 |176.720 | 52.695 | 46.823 |
|
||||
|polyfills.min.js | 32.452 | 0 | 11.312 | 0 | 0 |
|
||||
|TOTAL |1.434.353 | 599.766 |424.718 |170.984 |144.359 |
|
||||
|TOTAL (no admin) |1.182.206 | 487.651 |351.061 |140.374 |117.922 |
|
||||
|TOTAL |1.434.353 | 591.441 |424.718 |168.652 |142.507 |
|
||||
|TOTAL (no admin) |1.182.206 | 484.570 |351.061 |139.818 |117.444 |
|
||||
|
||||
For a user its around 60% smaller and faster than traditional RainLoop.
|
||||
|
||||
|
|
@ -148,8 +148,8 @@ For a user its around 60% smaller and faster than traditional RainLoop.
|
|||
|
||||
|css/* |1.14.0 |native |gzip 1.14 |gzip |brotli |
|
||||
|-------------- |-------: |-------: |------: |------: |------: |
|
||||
|app.css | 340.334 | 186.431 | 46,959 | 28.748 | 24.209 |
|
||||
|app.min.css | 274.791 | 152.540 | 39.618 | 25.289 | 21.842 |
|
||||
|app.css | 340.334 | 186.119 | 46,959 | 28.731 | 24.189 |
|
||||
|app.min.css | 274.791 | 152.283 | 39.618 | 25.276 | 21.801 |
|
||||
|boot.css | | 2.534 | | 837 | 668 |
|
||||
|boot.min.css | | 2.055 | | 732 | 560 |
|
||||
|
||||
|
|
|
|||
|
|
@ -1,68 +1,5 @@
|
|||
/* eslint quote-props: 0 */
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
export const FileType = {
|
||||
Unknown: 'unknown',
|
||||
Text: 'text',
|
||||
Html: 'html',
|
||||
Code: 'code',
|
||||
Eml: 'eml',
|
||||
WordText: 'word-text',
|
||||
Pdf: 'pdf',
|
||||
Image: 'image',
|
||||
Audio: 'audio',
|
||||
Video: 'video',
|
||||
Sheet: 'sheet',
|
||||
Presentation: 'presentation',
|
||||
Certificate: 'certificate',
|
||||
CertificateBin: 'certificate-bin',
|
||||
Archive: 'archive',
|
||||
|
||||
getIconClass: function(type) {
|
||||
let result = ['icon-file', ''];
|
||||
switch (type) {
|
||||
case this.Text:
|
||||
case this.Eml:
|
||||
case this.WordText:
|
||||
result[0] += '-text';
|
||||
break;
|
||||
case this.Html:
|
||||
case this.Code:
|
||||
result[0] += '-code';
|
||||
break;
|
||||
case this.Image:
|
||||
result[0] += '-image';
|
||||
break;
|
||||
case this.Audio:
|
||||
result[0] += '-music';
|
||||
break;
|
||||
case this.Video:
|
||||
result[0] += '-movie';
|
||||
break;
|
||||
case this.Archive:
|
||||
result[0] += '-zip';
|
||||
break;
|
||||
case this.Certificate:
|
||||
case this.CertificateBin:
|
||||
result[0] += '-certificate';
|
||||
break;
|
||||
case this.Sheet:
|
||||
result[0] += '-excel';
|
||||
break;
|
||||
case this.Presentation:
|
||||
result[0] += '-chart-graph';
|
||||
break;
|
||||
case this.Pdf:
|
||||
result['icon-none', 'pdf'];
|
||||
break;
|
||||
// no default
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
|
|
|
|||
313
dev/Common/File.js
Normal file
313
dev/Common/File.js
Normal file
|
|
@ -0,0 +1,313 @@
|
|||
/* eslint key-spacing: 0 */
|
||||
/* eslint quote-props: 0 */
|
||||
|
||||
const
|
||||
cache = {},
|
||||
app = 'application/',
|
||||
msOffice = app+'vnd.openxmlformats-officedocument.',
|
||||
openDoc = app+'vnd.oasis.opendocument.',
|
||||
font = app+'x-font-',
|
||||
|
||||
exts = {
|
||||
'eml': 'message/rfc822',
|
||||
'mime': 'message/rfc822',
|
||||
'rtx': 'text/richtext',
|
||||
'vcard': 'text/vcard',
|
||||
'vcf': 'text/vcard',
|
||||
'htm': 'text/html',
|
||||
'html': 'text/html',
|
||||
'csv': 'text/csv',
|
||||
'ics': 'text/calendar',
|
||||
'ifb': 'text/calendar',
|
||||
'xml': 'text/xml',
|
||||
'json': app+'json',
|
||||
'p10': app+'pkcs10',
|
||||
'p7c': app+'pkcs7-mime',
|
||||
'p7m': app+'pkcs7-mime',
|
||||
'p7s': app+'pkcs7-signature',
|
||||
'torrent': app+'x-bittorrent',
|
||||
|
||||
// scripts
|
||||
'js': app+'javascript',
|
||||
'pl': 'text/perl',
|
||||
'css': 'text/css',
|
||||
'asp': 'text/asp',
|
||||
'php': app+'x-httpd-php',
|
||||
'phtml': app+'x-httpd-php',
|
||||
|
||||
// images
|
||||
'jpg': 'image/jpeg',
|
||||
'ico': 'image/x-icon',
|
||||
'tif': 'image/tiff',
|
||||
'svg': 'image/svg+xml',
|
||||
'svgz': 'image/svg+xml',
|
||||
|
||||
// archives
|
||||
'zip': app+'zip',
|
||||
'7z': app+'x-7z-compressed',
|
||||
'rar': app+'x-rar-compressed',
|
||||
'cab': app+'vnd.ms-cab-compressed',
|
||||
'gz': app+'x-gzip',
|
||||
'tgz': app+'x-gzip',
|
||||
'bz': app+'x-bzip',
|
||||
'bz2': app+'x-bzip2',
|
||||
'deb': app+'x-debian-package',
|
||||
|
||||
// fonts
|
||||
'psf': font+'linux-psf',
|
||||
'ttc': font+'ttf',
|
||||
|
||||
// audio
|
||||
'mp3': 'audio/mpeg',
|
||||
'wav': 'audio/x-wav',
|
||||
'mp4a': 'audio/mp4',
|
||||
'weba': 'audio/webm',
|
||||
'm3u': 'audio/x-mpegurl',
|
||||
|
||||
// video
|
||||
'qt': 'video/quicktime',
|
||||
'mov': 'video/quicktime',
|
||||
'wmv': 'video/windows-media',
|
||||
'avi': 'video/x-msvideo',
|
||||
'3gp': 'video/3gpp',
|
||||
'3g2': 'video/3gpp2',
|
||||
'mp4v': 'video/mp4',
|
||||
'mpg4': 'video/mp4',
|
||||
'ogv': 'video/ogg',
|
||||
'm4v': 'video/x-m4v',
|
||||
'asf': 'video/x-ms-asf',
|
||||
'asx': 'video/x-ms-asf',
|
||||
'wm': 'video/x-ms-wm',
|
||||
'wmx': 'video/x-ms-wmx',
|
||||
'wvx': 'video/x-ms-wvx',
|
||||
'movie': 'video/x-sgi-movie',
|
||||
|
||||
// adobe
|
||||
'pdf': app+'pdf',
|
||||
'psd': 'image/vnd.adobe.photoshop',
|
||||
'ai': app+'postscript',
|
||||
'eps': app+'postscript',
|
||||
'ps': app+'postscript',
|
||||
|
||||
// ms office
|
||||
'doc': app+'msword',
|
||||
'rtf': app+'rtf',
|
||||
'xls': app+'vnd.ms-excel',
|
||||
'ppt': app+'vnd.ms-powerpoint',
|
||||
'docx': msOffice+'wordprocessingml.document',
|
||||
'xlsx': msOffice+'spreadsheetml.sheet',
|
||||
'dotx': msOffice+'wordprocessingml.template',
|
||||
'pptx': msOffice+'presentationml.presentation',
|
||||
|
||||
// open office
|
||||
'odt': openDoc+'text',
|
||||
'ods': openDoc+'spreadsheet',
|
||||
'odp': openDoc+'presentation'
|
||||
};
|
||||
|
||||
export const FileType = {
|
||||
Unknown: 'unknown',
|
||||
Text: 'text',
|
||||
Html: 'html',
|
||||
Code: 'code',
|
||||
Eml: 'eml',
|
||||
WordText: 'word-text',
|
||||
Pdf: 'pdf',
|
||||
Image: 'image',
|
||||
Audio: 'audio',
|
||||
Video: 'video',
|
||||
Sheet: 'sheet',
|
||||
Presentation: 'presentation',
|
||||
Certificate: 'certificate',
|
||||
CertificateBin: 'certificate-bin',
|
||||
Archive: 'archive'
|
||||
};
|
||||
|
||||
export const File = {
|
||||
/**
|
||||
* @param {string} fileName
|
||||
* @returns {string}
|
||||
*/
|
||||
getExtension: fileName => {
|
||||
fileName = fileName.toLowerCase().trim();
|
||||
const result = fileName.split('.').pop();
|
||||
return result === fileName ? '' : result;
|
||||
},
|
||||
|
||||
getContentType: fileName => {
|
||||
fileName = fileName.toLowerCase().trim();
|
||||
if ('winmail.dat' === fileName) {
|
||||
return 'application/ms-tnef';
|
||||
}
|
||||
let ext = fileName.split('.').pop();
|
||||
if (/^(txt|text|def|list|in|ini|log|sql|cfg|conf|asc)$/.test(ext))
|
||||
return 'text/plain';
|
||||
if (/^(mpe?g|mpe|m1v|m2v)$/.test(ext))
|
||||
return 'video/mpeg';
|
||||
if (/^aif[cf]?$/.test(ext))
|
||||
return 'audio/aiff';
|
||||
if (/^(aac|flac|midi|ogg)$/.test(ext))
|
||||
return 'audio/'+ext;
|
||||
if (/^(h26[134]|jpgv|mp4|webm)$/.test(ext))
|
||||
return 'video/'+ext;
|
||||
if (/^(otf|pcf|snf|ttf)$/.test(ext))
|
||||
return font+ext;
|
||||
if (/^(png|jpeg|gif|tiff|webp)$/.test(ext))
|
||||
return 'image/'+ext;
|
||||
|
||||
return exts[ext] || app+'octet-stream';
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} sExt
|
||||
* @param {string} sMimeType
|
||||
* @returns {string}
|
||||
*/
|
||||
getType: (ext, mimeType) => {
|
||||
ext = ext.toLowerCase().trim();
|
||||
mimeType = mimeType.toLowerCase().trim().replace('csv/plain', 'text/csv');
|
||||
|
||||
let key = ext + mimeType;
|
||||
if (cache[key]) {
|
||||
return cache[key];
|
||||
}
|
||||
|
||||
let result = FileType.Unknown;
|
||||
const mimeTypeParts = mimeType.split('/'),
|
||||
type = mimeTypeParts[1],
|
||||
match = str => type.includes(str);
|
||||
|
||||
switch (true) {
|
||||
case 'image' === mimeTypeParts[0] || ['png', 'jpg', 'jpeg', 'gif'].includes(ext):
|
||||
result = FileType.Image;
|
||||
break;
|
||||
case 'audio' === mimeTypeParts[0] || ['mp3', 'ogg', 'oga', 'wav'].includes(ext):
|
||||
result = FileType.Audio;
|
||||
break;
|
||||
case 'video' === mimeTypeParts[0] || ['mkv', 'avi'].includes(ext):
|
||||
result = FileType.Video;
|
||||
break;
|
||||
case ['php', 'js', 'css'].includes(ext):
|
||||
result = FileType.Code;
|
||||
break;
|
||||
case 'eml' === ext || ['message/delivery-status', 'message/rfc822'].includes(mimeType):
|
||||
result = FileType.Eml;
|
||||
break;
|
||||
case 'text/html' === mimeType || ['html'].includes(ext):
|
||||
result = FileType.Html;
|
||||
break;
|
||||
case 'text' === mimeTypeParts[0] || ['txt', 'log'].includes(ext):
|
||||
result = FileType.Text;
|
||||
break;
|
||||
case [
|
||||
'zip',
|
||||
'7z',
|
||||
'tar',
|
||||
'rar',
|
||||
'gzip',
|
||||
'bzip',
|
||||
'bzip2',
|
||||
'x-zip',
|
||||
'x-7z',
|
||||
'x-rar',
|
||||
'x-tar',
|
||||
'x-gzip',
|
||||
'x-bzip',
|
||||
'x-bzip2',
|
||||
'x-zip-compressed',
|
||||
'x-7z-compressed',
|
||||
'x-rar-compressed'
|
||||
].includes(type) || ['zip', '7z', 'tar', 'rar', 'gzip', 'bzip', 'bzip2'].includes(ext):
|
||||
result = FileType.Archive;
|
||||
break;
|
||||
case ['pdf', 'x-pdf'].includes(type) || ['pdf'].includes(ext):
|
||||
result = FileType.Pdf;
|
||||
break;
|
||||
case ['application/pgp-signature', 'application/pgp-keys'].includes(mimeType) ||
|
||||
['asc', 'pem', 'ppk'].includes(ext):
|
||||
result = FileType.Certificate;
|
||||
break;
|
||||
case ['application/pkcs7-signature'].includes(mimeType) || ['p7s'].includes(ext):
|
||||
result = FileType.CertificateBin;
|
||||
break;
|
||||
case match(msOffice+'.wordprocessingml') || match(openDoc+'.text') || match('vnd.ms-word')
|
||||
|| ['rtf', 'msword', 'vnd.msword'].includes(type):
|
||||
result = FileType.WordText;
|
||||
break;
|
||||
case match(msOffice+'.spreadsheetml') || match(openDoc+'.spreadsheet') || match('ms-excel'):
|
||||
result = FileType.Sheet;
|
||||
break;
|
||||
case match(msOffice+'.presentationml') || match(openDoc+'.presentation') || match('ms-powerpoint'):
|
||||
result = FileType.Presentation;
|
||||
break;
|
||||
// no default
|
||||
}
|
||||
return cache[key] = result;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} sFileType
|
||||
* @returns {string}
|
||||
*/
|
||||
getTypeIconClass: fileType => {
|
||||
let result = ['icon-file', ''];
|
||||
switch (fileType) {
|
||||
case FileType.Text:
|
||||
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:
|
||||
result['icon-none', 'pdf'];
|
||||
break;
|
||||
// no default
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
getIconClass: (ext, mime) => File.getTypeIconClass(File.getType(ext, mime)),
|
||||
|
||||
/**
|
||||
* @param {string} sFileType
|
||||
* @returns {string}
|
||||
*/
|
||||
getCombinedIconClass: data => {
|
||||
if (Array.isNotEmpty(data)) {
|
||||
let icons = data
|
||||
.map(item => item ? File.getIconClass(File.getExtension(item[0]), item[1])[0] : '')
|
||||
.filter((value, index, self) => value && self.indexOf(value) == index);
|
||||
|
||||
return (icons && 1 === icons.length && 'icon-file' !== icons[0])
|
||||
? icons[0]
|
||||
: 'icon-attachment';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
|
@ -1,165 +0,0 @@
|
|||
/* eslint key-spacing: 0 */
|
||||
/* eslint quote-props: 0 */
|
||||
|
||||
const Mime = {
|
||||
'eml': 'message/rfc822',
|
||||
'mime': 'message/rfc822',
|
||||
'txt': 'text/plain',
|
||||
'text': 'text/plain',
|
||||
'def': 'text/plain',
|
||||
'list': 'text/plain',
|
||||
'in': 'text/plain',
|
||||
'ini': 'text/plain',
|
||||
'log': 'text/plain',
|
||||
'sql': 'text/plain',
|
||||
'cfg': 'text/plain',
|
||||
'conf': 'text/plain',
|
||||
'asc': 'text/plain',
|
||||
'rtx': 'text/richtext',
|
||||
'vcard': 'text/vcard',
|
||||
'vcf': 'text/vcard',
|
||||
'htm': 'text/html',
|
||||
'html': 'text/html',
|
||||
'csv': 'text/csv',
|
||||
'ics': 'text/calendar',
|
||||
'ifb': 'text/calendar',
|
||||
'xml': 'text/xml',
|
||||
'json': 'application/json',
|
||||
'swf': 'application/x-shockwave-flash',
|
||||
'hlp': 'application/winhlp',
|
||||
'wgt': 'application/widget',
|
||||
'chm': 'application/vnd.ms-htmlhelp',
|
||||
'p10': 'application/pkcs10',
|
||||
'p7c': 'application/pkcs7-mime',
|
||||
'p7m': 'application/pkcs7-mime',
|
||||
'p7s': 'application/pkcs7-signature',
|
||||
'torrent': 'application/x-bittorrent',
|
||||
|
||||
// scripts
|
||||
'js': 'application/javascript',
|
||||
'pl': 'text/perl',
|
||||
'css': 'text/css',
|
||||
'asp': 'text/asp',
|
||||
'php': 'application/x-httpd-php',
|
||||
'php3': 'application/x-httpd-php',
|
||||
'php4': 'application/x-httpd-php',
|
||||
'php5': 'application/x-httpd-php',
|
||||
'phtml': 'application/x-httpd-php',
|
||||
|
||||
// images
|
||||
'png': 'image/png',
|
||||
'jpg': 'image/jpeg',
|
||||
'jpeg': 'image/jpeg',
|
||||
'jpe': 'image/jpeg',
|
||||
'jfif': 'image/jpeg',
|
||||
'gif': 'image/gif',
|
||||
'bmp': 'image/bmp',
|
||||
'cgm': 'image/cgm',
|
||||
'ief': 'image/ief',
|
||||
'ico': 'image/x-icon',
|
||||
'tif': 'image/tiff',
|
||||
'tiff': 'image/tiff',
|
||||
'svg': 'image/svg+xml',
|
||||
'svgz': 'image/svg+xml',
|
||||
'djv': 'image/vnd.djvu',
|
||||
'djvu': 'image/vnd.djvu',
|
||||
'webp': 'image/webp',
|
||||
|
||||
// archives
|
||||
'zip': 'application/zip',
|
||||
'7z': 'application/x-7z-compressed',
|
||||
'rar': 'application/x-rar-compressed',
|
||||
'exe': 'application/x-msdownload',
|
||||
'dll': 'application/x-msdownload',
|
||||
'scr': 'application/x-msdownload',
|
||||
'com': 'application/x-msdownload',
|
||||
'bat': 'application/x-msdownload',
|
||||
'msi': 'application/x-msdownload',
|
||||
'cab': 'application/vnd.ms-cab-compressed',
|
||||
'gz': 'application/x-gzip',
|
||||
'tgz': 'application/x-gzip',
|
||||
'bz': 'application/x-bzip',
|
||||
'bz2': 'application/x-bzip2',
|
||||
'deb': 'application/x-debian-package',
|
||||
|
||||
// fonts
|
||||
'psf': 'application/x-font-linux-psf',
|
||||
'otf': 'application/x-font-otf',
|
||||
'pcf': 'application/x-font-pcf',
|
||||
'snf': 'application/x-font-snf',
|
||||
'ttf': 'application/x-font-ttf',
|
||||
'ttc': 'application/x-font-ttf',
|
||||
|
||||
// audio
|
||||
'mp3': 'audio/mpeg',
|
||||
'amr': 'audio/amr',
|
||||
'aac': 'audio/x-aac',
|
||||
'aif': 'audio/x-aiff',
|
||||
'aifc': 'audio/x-aiff',
|
||||
'aiff': 'audio/x-aiff',
|
||||
'wav': 'audio/x-wav',
|
||||
'wma': 'audio/x-ms-wma',
|
||||
'wax': 'audio/x-ms-wax',
|
||||
'midi': 'audio/midi',
|
||||
'mp4a': 'audio/mp4',
|
||||
'ogg': 'audio/ogg',
|
||||
'weba': 'audio/webm',
|
||||
'ra': 'audio/x-pn-realaudio',
|
||||
'ram': 'audio/x-pn-realaudio',
|
||||
'rmp': 'audio/x-pn-realaudio-plugin',
|
||||
'm3u': 'audio/x-mpegurl',
|
||||
|
||||
// video
|
||||
'flv': 'video/x-flv',
|
||||
'qt': 'video/quicktime',
|
||||
'mov': 'video/quicktime',
|
||||
'wmv': 'video/windows-media',
|
||||
'avi': 'video/x-msvideo',
|
||||
'mpg': 'video/mpeg',
|
||||
'mpeg': 'video/mpeg',
|
||||
'mpe': 'video/mpeg',
|
||||
'm1v': 'video/mpeg',
|
||||
'm2v': 'video/mpeg',
|
||||
'3gp': 'video/3gpp',
|
||||
'3g2': 'video/3gpp2',
|
||||
'h261': 'video/h261',
|
||||
'h263': 'video/h263',
|
||||
'h264': 'video/h264',
|
||||
'jpgv': 'video/jpgv',
|
||||
'mp4': 'video/mp4',
|
||||
'mp4v': 'video/mp4',
|
||||
'mpg4': 'video/mp4',
|
||||
'ogv': 'video/ogg',
|
||||
'webm': 'video/webm',
|
||||
'm4v': 'video/x-m4v',
|
||||
'asf': 'video/x-ms-asf',
|
||||
'asx': 'video/x-ms-asf',
|
||||
'wm': 'video/x-ms-wm',
|
||||
'wmx': 'video/x-ms-wmx',
|
||||
'wvx': 'video/x-ms-wvx',
|
||||
'movie': 'video/x-sgi-movie',
|
||||
|
||||
// adobe
|
||||
'pdf': 'application/pdf',
|
||||
'psd': 'image/vnd.adobe.photoshop',
|
||||
'ai': 'application/postscript',
|
||||
'eps': 'application/postscript',
|
||||
'ps': 'application/postscript',
|
||||
|
||||
// ms office
|
||||
'doc': 'application/msword',
|
||||
'dot': 'application/msword',
|
||||
'rtf': 'application/rtf',
|
||||
'xls': 'application/vnd.ms-excel',
|
||||
'ppt': 'application/vnd.ms-powerpoint',
|
||||
'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'dotx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
|
||||
'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
|
||||
// open office
|
||||
'odt': 'application/vnd.oasis.opendocument.text',
|
||||
'ods': 'application/vnd.oasis.opendocument.spreadsheet'
|
||||
};
|
||||
|
||||
export { Mime, Mime as default };
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
import { ComposeType, SaveSettingsStep, FolderType } from 'Common/Enums';
|
||||
import { Mime } from 'Common/Mime';
|
||||
|
||||
const
|
||||
doc = document,
|
||||
|
|
@ -820,39 +819,6 @@ export function computedPagenatorHelper(koCurrentPage, koPageCount) {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} fileName
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getFileExtension(fileName) {
|
||||
fileName = fileName.toLowerCase().trim();
|
||||
|
||||
const result = fileName.split('.').pop();
|
||||
return result === fileName ? '' : result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} fileName
|
||||
* @returns {string}
|
||||
*/
|
||||
export function mimeContentType(fileName) {
|
||||
let ext = '',
|
||||
result = 'application/octet-stream';
|
||||
|
||||
fileName = fileName.toLowerCase().trim();
|
||||
|
||||
if ('winmail.dat' === fileName) {
|
||||
return 'application/ms-tnef';
|
||||
}
|
||||
|
||||
ext = getFileExtension(fileName);
|
||||
if (ext && ext.length && undefined !== Mime[ext]) {
|
||||
result = Mime[ext];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} color
|
||||
* @returns {boolean}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import ko from 'ko';
|
||||
|
||||
import { FileType } from 'Common/Enums';
|
||||
import { pInt, getFileExtension, friendlySize } from 'Common/Utils';
|
||||
import { File, FileType } from 'Common/File';
|
||||
import { pInt, friendlySize } from 'Common/Utils';
|
||||
import {
|
||||
attachmentDownload,
|
||||
attachmentPreview,
|
||||
|
|
@ -16,159 +16,6 @@ import Audio from 'Common/Audio';
|
|||
|
||||
const bAllowPdfPreview = undefined !== navigator.mimeTypes['application/pdf'];
|
||||
|
||||
/**
|
||||
* @param {string} sExt
|
||||
* @param {string} sMimeType
|
||||
* @returns {string}
|
||||
*/
|
||||
export const staticFileType = (() => {
|
||||
let cache = {},
|
||||
msOffice = 'vnd.openxmlformats-officedocument',
|
||||
openDoc = 'vnd.oasis.opendocument';
|
||||
return (ext, mimeType) => {
|
||||
ext = ext.toLowerCase().trim();
|
||||
mimeType = mimeType.toLowerCase().trim();
|
||||
|
||||
let key = ext + mimeType;
|
||||
if (cache[key]) {
|
||||
return cache[key];
|
||||
}
|
||||
|
||||
let result = FileType.Unknown;
|
||||
const mimeTypeParts = mimeType.split('/'),
|
||||
type = mimeTypeParts[1],
|
||||
match = str => type.includes(str);
|
||||
|
||||
switch (true) {
|
||||
case 'image' === mimeTypeParts[0] || ['png', 'jpg', 'jpeg', 'gif'].includes(ext):
|
||||
result = FileType.Image;
|
||||
break;
|
||||
case 'audio' === mimeTypeParts[0] || ['mp3', 'ogg', 'oga', 'wav'].includes(ext):
|
||||
result = FileType.Audio;
|
||||
break;
|
||||
case 'video' === mimeTypeParts[0] || ['mkv', 'avi'].includes(ext):
|
||||
result = FileType.Video;
|
||||
break;
|
||||
case ['php', 'js', 'css'].includes(ext):
|
||||
result = FileType.Code;
|
||||
break;
|
||||
case 'eml' === ext || ['message/delivery-status', 'message/rfc822'].includes(mimeType):
|
||||
result = FileType.Eml;
|
||||
break;
|
||||
case ('text' === mimeTypeParts[0] && 'html' !== type) || ['txt', 'log'].includes(ext):
|
||||
result = FileType.Text;
|
||||
break;
|
||||
case 'text/html' === mimeType || ['html'].includes(ext):
|
||||
result = FileType.Html;
|
||||
break;
|
||||
case [
|
||||
'zip',
|
||||
'7z',
|
||||
'tar',
|
||||
'rar',
|
||||
'gzip',
|
||||
'bzip',
|
||||
'bzip2',
|
||||
'x-zip',
|
||||
'x-7z',
|
||||
'x-rar',
|
||||
'x-tar',
|
||||
'x-gzip',
|
||||
'x-bzip',
|
||||
'x-bzip2',
|
||||
'x-zip-compressed',
|
||||
'x-7z-compressed',
|
||||
'x-rar-compressed'
|
||||
].includes(type) || ['zip', '7z', 'tar', 'rar', 'gzip', 'bzip', 'bzip2'].includes(ext):
|
||||
result = FileType.Archive;
|
||||
break;
|
||||
case ['pdf', 'x-pdf'].includes(type) || ['pdf'].includes(ext):
|
||||
result = FileType.Pdf;
|
||||
break;
|
||||
case ['application/pgp-signature', 'application/pgp-keys'].includes(mimeType) ||
|
||||
['asc', 'pem', 'ppk'].includes(ext):
|
||||
result = FileType.Certificate;
|
||||
break;
|
||||
case ['application/pkcs7-signature'].includes(mimeType) || ['p7s'].includes(ext):
|
||||
result = FileType.CertificateBin;
|
||||
break;
|
||||
case match(msOffice+'.wordprocessingml') || match(openDoc+'.text') || match('vnd.ms-word')
|
||||
|| ['rtf', 'msword', 'vnd.msword'].includes(type):
|
||||
result = FileType.WordText;
|
||||
break;
|
||||
case match(msOffice+'.spreadsheetml') || match(openDoc+'.spreadsheet') || match('ms-excel'):
|
||||
result = FileType.Sheet;
|
||||
break;
|
||||
case match(msOffice+'.presentationml') || match(openDoc+'.presentation') || match('ms-powerpoint'):
|
||||
result = FileType.Presentation;
|
||||
break;
|
||||
// no default
|
||||
}
|
||||
|
||||
return cache[key] = result;
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* @param {string} sFileType
|
||||
* @returns {string}
|
||||
*/
|
||||
export const staticIconClass = fileType => FileType.getIconClass(fileType);
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param {string} sFileType
|
||||
* @returns {string}
|
||||
*/
|
||||
export const staticCombinedIconClass = (data) => {
|
||||
let result = '',
|
||||
types = [];
|
||||
|
||||
if (Array.isNotEmpty(data)) {
|
||||
result = 'icon-attachment';
|
||||
types = data.map(item => item ? staticFileType(getFileExtension(item[0]), item[1]) : '')
|
||||
.filter((value, index, self) => !!value && self.indexOf(value) == index);
|
||||
|
||||
if (types && 1 === types.length && types[0]) {
|
||||
switch (types[0]) {
|
||||
case FileType.Text:
|
||||
case FileType.WordText:
|
||||
result = 'icon-file-text';
|
||||
break;
|
||||
case FileType.Html:
|
||||
case FileType.Code:
|
||||
result = 'icon-file-code';
|
||||
break;
|
||||
case FileType.Image:
|
||||
result = 'icon-file-image';
|
||||
break;
|
||||
case FileType.Audio:
|
||||
result = 'icon-file-music';
|
||||
break;
|
||||
case FileType.Video:
|
||||
result = 'icon-file-movie';
|
||||
break;
|
||||
case FileType.Archive:
|
||||
result = 'icon-file-zip';
|
||||
break;
|
||||
case FileType.Certificate:
|
||||
case FileType.CertificateBin:
|
||||
result = 'icon-file-certificate';
|
||||
break;
|
||||
case FileType.Sheet:
|
||||
result = 'icon-file-excel';
|
||||
break;
|
||||
case FileType.Presentation:
|
||||
result = 'icon-file-chart-graph';
|
||||
break;
|
||||
// no default
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
class AttachmentModel extends AbstractModel {
|
||||
constructor() {
|
||||
super('AttachmentModel');
|
||||
|
|
@ -232,8 +79,8 @@ class AttachmentModel extends AbstractModel {
|
|||
this.friendlySize = friendlySize(this.estimatedSize);
|
||||
this.cidWithoutTags = this.cid.replace(/^<+/, '').replace(/>+$/, '');
|
||||
|
||||
this.fileNameExt = getFileExtension(this.fileName);
|
||||
this.fileType = staticFileType(this.fileNameExt, this.mimeType);
|
||||
this.fileNameExt = File.getExtension(this.fileName);
|
||||
this.fileType = File.getType(this.fileNameExt, this.mimeType);
|
||||
|
||||
bResult = true;
|
||||
}
|
||||
|
|
@ -406,14 +253,14 @@ class AttachmentModel extends AbstractModel {
|
|||
* @returns {string}
|
||||
*/
|
||||
iconClass() {
|
||||
return staticIconClass(this.fileType)[0];
|
||||
return File.getTypeIconClass(this.fileType)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
iconText() {
|
||||
return staticIconClass(this.fileType)[1];
|
||||
return File.getTypeIconClass(this.fileType)[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import ko from 'ko';
|
||||
import { pInt, friendlySize, mimeContentType, getFileExtension } from 'Common/Utils';
|
||||
import { pInt, friendlySize } from 'Common/Utils';
|
||||
import { File } from 'Common/File';
|
||||
|
||||
import { staticIconClass, staticFileType } from 'Model/Attachment';
|
||||
import { AbstractModel } from 'Knoin/AbstractModel';
|
||||
|
||||
class ComposeAttachmentModel extends AbstractModel {
|
||||
|
|
@ -54,8 +54,8 @@ class ComposeAttachmentModel extends AbstractModel {
|
|||
return null === localSize ? '' : friendlySize(localSize);
|
||||
});
|
||||
|
||||
this.mimeType = ko.computed(() => mimeContentType(this.fileName()));
|
||||
this.fileExt = ko.computed(() => getFileExtension(this.fileName()));
|
||||
this.mimeType = ko.computed(() => File.getContentType(this.fileName()));
|
||||
this.fileExt = ko.computed(() => File.getExtension(this.fileName()));
|
||||
|
||||
this.regDisposables([
|
||||
this.progressText,
|
||||
|
|
@ -104,14 +104,14 @@ class ComposeAttachmentModel extends AbstractModel {
|
|||
* @returns {string}
|
||||
*/
|
||||
iconClass() {
|
||||
return staticIconClass(staticFileType(this.fileExt(), this.mimeType()))[0];
|
||||
return File.getIconClass(this.fileExt(), this.mimeType())[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
iconText() {
|
||||
return staticIconClass(staticFileType(this.fileExt(), this.mimeType()))[1];
|
||||
return File.getIconClass(this.fileExt(), this.mimeType())[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import { messageViewLink, messageDownloadLink } from 'Common/Links';
|
|||
import FolderStore from 'Stores/User/Folder';
|
||||
import PgpStore from 'Stores/User/Pgp';
|
||||
|
||||
import { staticCombinedIconClass } from 'Model/Attachment';
|
||||
import { File } from 'Common/File';
|
||||
import { AttachmentCollectionModel } from 'Model/AttachmentCollection';
|
||||
import { EmailCollectionModel } from 'Model/EmailCollection';
|
||||
import { AbstractModel } from 'Knoin/AbstractModel';
|
||||
|
|
@ -69,7 +69,7 @@ class MessageModel extends AbstractModel {
|
|||
this.attachmentsSpecData = ko.observableArray([]);
|
||||
|
||||
this.attachmentIconClass = ko.computed(() =>
|
||||
staticCombinedIconClass(this.hasAttachments() ? this.attachmentsSpecData() : [])
|
||||
File.getCombinedIconClass(this.hasAttachments() ? this.attachmentsSpecData() : [])
|
||||
);
|
||||
|
||||
this.isHtml = ko.observable(false);
|
||||
|
|
|
|||
|
|
@ -828,26 +828,20 @@ END;
|
|||
'ttc' => 'application/x-font-ttf',
|
||||
|
||||
// audio
|
||||
'aac' => 'audio/aac',
|
||||
'flac' => 'audio/flac',
|
||||
'mp3' => 'audio/mpeg',
|
||||
'amr' => 'audio/amr',
|
||||
'aac' => 'audio/x-aac',
|
||||
'aif' => 'audio/x-aiff',
|
||||
'aifc' => 'audio/x-aiff',
|
||||
'aiff' => 'audio/x-aiff',
|
||||
'aif' => 'audio/aiff',
|
||||
'aifc' => 'audio/aiff',
|
||||
'aiff' => 'audio/aiff',
|
||||
'wav' => 'audio/x-wav',
|
||||
'wma' => 'audio/x-ms-wma',
|
||||
'wax' => 'audio/x-ms-wax',
|
||||
'midi' => 'audio/midi',
|
||||
'mp4a' => 'audio/mp4',
|
||||
'ogg' => 'audio/ogg',
|
||||
'weba' => 'audio/webm',
|
||||
'ra' => 'audio/x-pn-realaudio',
|
||||
'ram' => 'audio/x-pn-realaudio',
|
||||
'rmp' => 'audio/x-pn-realaudio-plugin',
|
||||
'm3u' => 'audio/x-mpegurl',
|
||||
|
||||
// video
|
||||
'flv' => 'video/x-flv',
|
||||
'qt' => 'video/quicktime',
|
||||
'mov' => 'video/quicktime',
|
||||
'avi' => 'video/x-msvideo',
|
||||
|
|
@ -896,7 +890,8 @@ END;
|
|||
|
||||
// open office
|
||||
'odt' => 'application/vnd.oasis.opendocument.text',
|
||||
'ods' => 'application/vnd.oasis.opendocument.spreadsheet'
|
||||
'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
|
||||
'odp' => 'application/vnd.oasis.opendocument.presentation'
|
||||
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue