mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-01 05:29:20 +03:00
Merge branch 'master' into plugin-hooks
# Conflicts: # dev/View/User/Login.js
This commit is contained in:
commit
2ab42b1f03
547 changed files with 29045 additions and 52993 deletions
|
|
@ -4,8 +4,6 @@
|
|||
* @enum {string}
|
||||
*/
|
||||
export const Capa = {
|
||||
TwoFactor: 'TWO_FACTOR',
|
||||
TwoFactorForce: 'TWO_FACTOR_FORCE',
|
||||
OpenPGP: 'OPEN_PGP',
|
||||
Prefetch: 'PREFETCH',
|
||||
Composer: 'COMPOSER',
|
||||
|
|
@ -86,9 +84,6 @@ export const Notification = {
|
|||
DomainNotAllowed: 109,
|
||||
AccountNotAllowed: 110,
|
||||
|
||||
AccountTwoFactorAuthRequired: 120,
|
||||
AccountTwoFactorAuthError: 121,
|
||||
|
||||
ContactsSyncError: 140,
|
||||
|
||||
CantGetMessageList: 201,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,22 @@ export const FolderType = {
|
|||
User: 99
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
export const FolderSortMode = {
|
||||
DateDesc: '', // default 'REVERSE DATE'
|
||||
DateAsc: 'DATE',
|
||||
FromDesc: 'REVERSE FROM',
|
||||
FromAsc: 'FROM',
|
||||
SizeDesc: 'REVERSE SIZE',
|
||||
SizeAsc: 'SIZE',
|
||||
SubjectDesc: 'REVERSE SUBJECT',
|
||||
SubjectAsc: 'SUBJECT'
|
||||
// ToDesc: 'REVERSE TO',
|
||||
// ToAsc: 'TO',
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -11,113 +11,109 @@ const
|
|||
sizes = ['B', 'KiB', 'MiB', 'GiB', 'TiB'],
|
||||
|
||||
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',
|
||||
eml: 'message/rfc822',
|
||||
mime: 'message/rfc822',
|
||||
vcard: 'text/vcard',
|
||||
vcf: 'text/vcard',
|
||||
htm: 'text/html',
|
||||
html: 'text/html',
|
||||
csv: 'text/csv',
|
||||
ics: 'text/calendar',
|
||||
xml: 'text/xml',
|
||||
json: app+'json',
|
||||
asc: app+'pgp-signature',
|
||||
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',
|
||||
// scripts
|
||||
js: app+'javascript',
|
||||
pl: 'text/perl',
|
||||
css: 'text/css',
|
||||
asp: 'text/asp',
|
||||
php: app+'x-php',
|
||||
|
||||
// images
|
||||
jpg: 'image/jpeg',
|
||||
ico: 'image/x-icon',
|
||||
tif: 'image/tiff',
|
||||
svg: 'image/svg+xml',
|
||||
svgz: 'image/svg+xml',
|
||||
// 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',
|
||||
// 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',
|
||||
|
||||
// audio
|
||||
mp3: 'audio/mpeg',
|
||||
wav: 'audio/x-wav',
|
||||
mp4a: 'audio/mp4',
|
||||
weba: 'audio/webm',
|
||||
m3u: 'audio/x-mpegurl',
|
||||
// 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',
|
||||
// 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',
|
||||
// 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',
|
||||
// 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'
|
||||
};
|
||||
// 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',
|
||||
Word: 'word',
|
||||
Pdf: 'pdf',
|
||||
Image: 'image',
|
||||
Audio: 'audio',
|
||||
Video: 'video',
|
||||
Sheet: 'sheet',
|
||||
Spreadsheet: 'spreadsheet',
|
||||
Presentation: 'presentation',
|
||||
Certificate: 'certificate',
|
||||
CertificateBin: 'certificate-bin',
|
||||
Archive: 'archive'
|
||||
};
|
||||
|
||||
|
|
@ -138,7 +134,7 @@ export const FileInfo = {
|
|||
return app + 'ms-tnef';
|
||||
}
|
||||
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';
|
||||
if (/^(mpe?g|mpe|m1v|m2v)$/.test(ext))
|
||||
return 'video/mpeg';
|
||||
|
|
@ -186,15 +182,12 @@ export const FileInfo = {
|
|||
case 'video' == mimeTypeParts[0] || 'mkv' == ext || 'avi' == ext:
|
||||
result = FileType.Video;
|
||||
break;
|
||||
case ['php', 'js', 'css'].includes(ext):
|
||||
case ['php', 'js', 'css', 'xml', 'html'].includes(ext) || 'text/html' == mimeType:
|
||||
result = FileType.Code;
|
||||
break;
|
||||
case 'eml' == ext || ['message/delivery-status', 'message/rfc822'].includes(mimeType):
|
||||
result = FileType.Eml;
|
||||
break;
|
||||
case 'text/html' == mimeType || 'html' == ext:
|
||||
result = FileType.Html;
|
||||
break;
|
||||
case 'text' == mimeTypeParts[0] || 'txt' == ext || 'log' == ext:
|
||||
result = FileType.Text;
|
||||
break;
|
||||
|
|
@ -204,19 +197,17 @@ export const FileInfo = {
|
|||
case 'pdf' == type || 'pdf' == ext:
|
||||
result = FileType.Pdf;
|
||||
break;
|
||||
case [app+'pgp-signature', app+'pgp-keys'].includes(mimeType) ||
|
||||
['asc', 'pem', 'ppk'].includes(ext):
|
||||
case [app+'pgp-signature', app+'pgp-keys'].includes(mimeType)
|
||||
|| ['asc', 'pem', 'ppk'].includes(ext)
|
||||
|| [app+'pkcs7-signature'].includes(mimeType) || 'p7s' == ext:
|
||||
result = FileType.Certificate;
|
||||
break;
|
||||
case [app+'pkcs7-signature'].includes(mimeType) || 'p7s' == 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;
|
||||
result = FileType.Word;
|
||||
break;
|
||||
case match(msOffice+'.spreadsheetml') || match(openDoc+'.spreadsheet') || match('ms-excel'):
|
||||
result = FileType.Sheet;
|
||||
result = FileType.Spreadsheet;
|
||||
break;
|
||||
case match(msOffice+'.presentationml') || match(openDoc+'.presentation') || match('ms-powerpoint'):
|
||||
result = FileType.Presentation;
|
||||
|
|
@ -232,45 +223,23 @@ export const FileInfo = {
|
|||
* @returns {string}
|
||||
*/
|
||||
getTypeIconClass: fileType => {
|
||||
let result = ['icon-file', ''];
|
||||
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
|
||||
case FileType.Word:
|
||||
return result + '-text';
|
||||
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;
|
||||
},
|
||||
|
||||
|
|
@ -283,7 +252,7 @@ export const FileInfo = {
|
|||
getCombinedIconClass: data => {
|
||||
if (isNonEmptyArray(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();
|
||||
|
||||
return (icons && 1 === icons.length && 'icon-file' !== icons[0])
|
||||
|
|
@ -297,7 +266,7 @@ export const FileInfo = {
|
|||
friendlySize: bytes => {
|
||||
bytes = parseInt(bytes, 10) || 0;
|
||||
let i = Math.floor(Math.log(bytes) / Math.log(1024));
|
||||
return (bytes / Math.pow(1024, i)).toFixed(2>i ? 0 : 1) + sizes[i];
|
||||
return (bytes / Math.pow(1024, i)).toFixed(2>i ? 0 : 1) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -179,12 +179,13 @@ export function mailBox(folder, page = 1, search = '', threadUid = '') {
|
|||
}
|
||||
|
||||
if (1 < page) {
|
||||
result = result.replace(/[/]+$/, '') + '/p' + page;
|
||||
result = result.replace(/\/+$/, '') + '/p' + page;
|
||||
}
|
||||
|
||||
if (search) {
|
||||
result = result.replace(/[/]+$/, '') + '/' + encodeURI(search);
|
||||
result = result.replace(/\/+$/, '') + '/' + encodeURI(search);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { Notification, UploadErrorCode } from 'Common/Enums';
|
|||
import { langLink } from 'Common/Links';
|
||||
import { doc, createElement } from 'Common/Globals';
|
||||
|
||||
let I18N_DATA = window.rainloopI18N || {};
|
||||
let I18N_DATA = window.snappymailI18N || {};
|
||||
|
||||
export const trigger = ko.observable(false);
|
||||
|
||||
|
|
@ -14,14 +14,16 @@ export const trigger = ko.observable(false);
|
|||
* @returns {string}
|
||||
*/
|
||||
export function i18n(key, valueList, defaulValue) {
|
||||
let result = I18N_DATA[key] || defaulValue || key;
|
||||
|
||||
let path = key.split('/');
|
||||
if (!I18N_DATA[path[0]] || !path[1]) {
|
||||
return defaulValue || key;
|
||||
}
|
||||
let result = I18N_DATA[path[0]][path[1]] || defaulValue || key;
|
||||
if (valueList) {
|
||||
Object.entries(valueList).forEach(([key, value]) => {
|
||||
result = result.replace('%' + key + '%', value);
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -75,7 +77,7 @@ function getNotificationMessage(code) {
|
|||
let key = getKeyByValue(Notification, code);
|
||||
if (key) {
|
||||
key = i18nKey(key).replace('_NOTIFICATION', '_ERROR');
|
||||
return I18N_DATA['NOTIFICATIONS/' + key];
|
||||
return I18N_DATA.NOTIFICATIONS[key];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -125,13 +127,13 @@ export function reload(admin, language) {
|
|||
const script = createElement('script');
|
||||
script.onload = () => {
|
||||
// reload the data
|
||||
if (window.rainloopI18N) {
|
||||
I18N_DATA = window.rainloopI18N || {};
|
||||
if (window.snappymailI18N) {
|
||||
I18N_DATA = window.snappymailI18N;
|
||||
i18nToNodes(doc);
|
||||
dispatchEvent(new CustomEvent('reload-time'));
|
||||
trigger(!trigger());
|
||||
}
|
||||
window.rainloopI18N = null;
|
||||
window.snappymailI18N = null;
|
||||
script.remove();
|
||||
resolve();
|
||||
};
|
||||
|
|
@ -150,7 +152,7 @@ export function reload(admin, language) {
|
|||
*/
|
||||
export function convertLangName(language, isEng = false) {
|
||||
return i18n(
|
||||
'LANGS_NAMES' + (true === isEng ? '_EN' : '') + '/LANG_' + language.toUpperCase().replace(/[^a-zA-Z0-9]+/g, '_'),
|
||||
'LANGS_NAMES' + (true === isEng ? '_EN' : '') + '/' + language,
|
||||
null,
|
||||
language
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue