From 9992b201638e451f6e7692fd01e6c16dd609c99f Mon Sep 17 00:00:00 2001 From: djmaze Date: Fri, 2 Oct 2020 14:44:29 +0200 Subject: [PATCH] Merge file and mime code into simple Common/File.js --- README.md | 22 +- dev/Common/Enums.js | 63 ---- dev/Common/File.js | 313 ++++++++++++++++++ dev/Common/Mime.js | 165 --------- dev/Common/Utils.js | 34 -- dev/Model/Attachment.js | 165 +-------- dev/Model/ComposeAttachment.js | 12 +- dev/Model/Message.js | 4 +- .../0.0.0/app/libraries/MailSo/Base/Utils.php | 19 +- 9 files changed, 345 insertions(+), 452 deletions(-) create mode 100644 dev/Common/File.js delete mode 100644 dev/Common/Mime.js diff --git a/README.md b/README.md index 69f4296e0..b5397166f 100644 --- a/README.md +++ b/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 | diff --git a/dev/Common/Enums.js b/dev/Common/Enums.js index b166fa736..fc4477725 100644 --- a/dev/Common/Enums.js +++ b/dev/Common/Enums.js @@ -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} */ diff --git a/dev/Common/File.js b/dev/Common/File.js new file mode 100644 index 000000000..e7b45a835 --- /dev/null +++ b/dev/Common/File.js @@ -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 ''; + } +}; diff --git a/dev/Common/Mime.js b/dev/Common/Mime.js deleted file mode 100644 index e0a6863b3..000000000 --- a/dev/Common/Mime.js +++ /dev/null @@ -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 }; diff --git a/dev/Common/Utils.js b/dev/Common/Utils.js index e9692432a..484279fe9 100644 --- a/dev/Common/Utils.js +++ b/dev/Common/Utils.js @@ -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} diff --git a/dev/Model/Attachment.js b/dev/Model/Attachment.js index e1016526e..168f90277 100644 --- a/dev/Model/Attachment.js +++ b/dev/Model/Attachment.js @@ -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]; } } diff --git a/dev/Model/ComposeAttachment.js b/dev/Model/ComposeAttachment.js index de02ae46c..176427524 100644 --- a/dev/Model/ComposeAttachment.js +++ b/dev/Model/ComposeAttachment.js @@ -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]; } } diff --git a/dev/Model/Message.js b/dev/Model/Message.js index 9d7b724d0..ead03274b 100644 --- a/dev/Model/Message.js +++ b/dev/Model/Message.js @@ -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); diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php b/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php index a5b8161d4..6313cfd87 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Base/Utils.php @@ -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' );