mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-09-20 07:35:55 +08:00
This version uses Rollup instead of WebPack.
Due to that the code is smaller and has changes to prevent Circular Dependencies
This commit is contained in:
parent
5e63ade9dd
commit
ad8fd8879b
|
@ -13,13 +13,22 @@ import { initOnStartOrLangChange } from 'Common/Translator';
|
|||
import LanguageStore from 'Stores/Language';
|
||||
import ThemeStore from 'Stores/Theme';
|
||||
|
||||
import SaveTriggerComponent from 'Component/SaveTrigger';
|
||||
import InputComponent from 'Component/Input';
|
||||
import SelectComponent from 'Component/Select';
|
||||
import TextAreaComponent from 'Component/TextArea';
|
||||
import CheckboxMaterialDesignComponent from 'Component/MaterialDesign/Checkbox';
|
||||
import CheckboxComponent from 'Component/Checkbox';
|
||||
|
||||
const Settings = rl.settings, doc = document;
|
||||
|
||||
export class AbstractApp {
|
||||
/**
|
||||
* @param {RemoteStorage|AdminRemoteStorage} Remote
|
||||
*/
|
||||
constructor() {
|
||||
constructor(Remote) {
|
||||
this.Remote = Remote;
|
||||
|
||||
const refresh = (()=>dispatchEvent(new CustomEvent('rl.auto-logout-refresh'))).debounce(5000),
|
||||
fn = (ev=>{
|
||||
$htmlCL.toggle('rl-ctrl-key-pressed', ev.ctrlKey);
|
||||
|
@ -81,17 +90,15 @@ export class AbstractApp {
|
|||
bootstart() {
|
||||
const mobile = Settings.app('mobile');
|
||||
|
||||
ko.components.register('SaveTrigger', require('Component/SaveTrigger').default);
|
||||
ko.components.register('Input', require('Component/Input').default);
|
||||
ko.components.register('Select', require('Component/Select').default);
|
||||
ko.components.register('TextArea', require('Component/TextArea').default);
|
||||
|
||||
ko.components.register('SaveTrigger', SaveTriggerComponent);
|
||||
ko.components.register('Input', InputComponent);
|
||||
ko.components.register('Select', SelectComponent);
|
||||
ko.components.register('TextArea', TextAreaComponent);
|
||||
ko.components.register('CheckboxSimple', CheckboxComponent);
|
||||
if (Settings.app('materialDesign') && !rl.settings.app('mobile')) {
|
||||
ko.components.register('Checkbox', require('Component/MaterialDesign/Checkbox').default);
|
||||
ko.components.register('CheckboxSimple', require('Component/Checkbox').default);
|
||||
ko.components.register('Checkbox', CheckboxMaterialDesignComponent);
|
||||
} else {
|
||||
ko.components.register('Checkbox', require('Component/Checkbox').default);
|
||||
ko.components.register('CheckboxSimple', require('Component/Checkbox').default);
|
||||
ko.components.register('Checkbox', CheckboxComponent);
|
||||
}
|
||||
|
||||
initOnStartOrLangChange();
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import ko from 'External/User/ko'; // eslint-disable-line no-unused-vars
|
||||
|
||||
import { pInt, pString } from 'Common/Utils';
|
||||
import { isPosNumeric, delegateRunOnDestroy, mailToHelper } from 'Common/UtilsUser';
|
||||
|
||||
|
@ -67,7 +69,10 @@ import { startScreens, showScreenPopup } from 'Knoin/Knoin';
|
|||
|
||||
import { AbstractApp } from 'App/Abstract';
|
||||
|
||||
require('External/User/ko');
|
||||
import { ComposePopupView } from 'View/Popup/Compose';
|
||||
import { FolderSystemPopupView } from 'View/Popup/FolderSystem';
|
||||
import { AskPopupView } from 'View/Popup/Ask';
|
||||
import { TwoFactorConfigurationPopupView } from 'View/Popup/TwoFactorConfiguration';
|
||||
|
||||
const doc = document,
|
||||
Settings = rl.settings;
|
||||
|
@ -329,13 +334,13 @@ class AppUser extends AbstractApp {
|
|||
}
|
||||
|
||||
if (!oMoveFolder && bUseFolder) {
|
||||
showScreenPopup(require('View/Popup/FolderSystem'), [nSetSystemFoldersNotification]);
|
||||
showScreenPopup(FolderSystemPopupView, [nSetSystemFoldersNotification]);
|
||||
} else if (
|
||||
!bUseFolder ||
|
||||
(FolderType.Trash === iDeleteType &&
|
||||
(sFromFolderFullNameRaw === FolderStore.spamFolder() || sFromFolderFullNameRaw === FolderStore.trashFolder()))
|
||||
) {
|
||||
showScreenPopup(require('View/Popup/Ask'), [
|
||||
showScreenPopup(AskPopupView, [
|
||||
i18n('POPUPS_ASK/DESC_WANT_DELETE_MESSAGES'),
|
||||
() => {
|
||||
this.messagesDeleteHelper(sFromFolderFullNameRaw, aUidForRemove);
|
||||
|
@ -918,7 +923,7 @@ class AppUser extends AbstractApp {
|
|||
Settings.get('RequireTwoFactor')
|
||||
) {
|
||||
this.bootend();
|
||||
showScreenPopup(require('View/Popup/TwoFactorConfiguration'), [true]);
|
||||
showScreenPopup(TwoFactorConfigurationPopupView, [true]);
|
||||
} else {
|
||||
rl.setWindowTitle(i18n('GLOBAL/LOADING'));
|
||||
|
||||
|
@ -1022,7 +1027,7 @@ class AppUser extends AbstractApp {
|
|||
} catch (e) {} // eslint-disable-line no-empty
|
||||
|
||||
if (Settings.get('MailToEmail')) {
|
||||
mailToHelper(Settings.get('MailToEmail'), require('View/Popup/Compose'));
|
||||
mailToHelper(Settings.get('MailToEmail'), ComposePopupView);
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
|
@ -1047,6 +1052,11 @@ class AppUser extends AbstractApp {
|
|||
|
||||
setInterval(() => dispatchEvent(new CustomEvent('reload-time')), 60000);
|
||||
}
|
||||
|
||||
showComposePopupView(params = [])
|
||||
{
|
||||
showScreenPopup(ComposePopupView, params);
|
||||
}
|
||||
}
|
||||
|
||||
export default new AppUser();
|
||||
|
|
|
@ -1,5 +1,23 @@
|
|||
import { createCKEditor } from 'External/CKEditor.js';
|
||||
|
||||
const
|
||||
htmlre = /[&<>"']/g,
|
||||
htmlmap = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": '''
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @returns {string}
|
||||
*/
|
||||
export function encodeHtml(text) {
|
||||
return (text && text.toString ? text.toString() : ''+text).replace(htmlre, m => htmlmap[m]);
|
||||
}
|
||||
|
||||
class HtmlEditor {
|
||||
editor;
|
||||
blurTimer = 0;
|
|
@ -1,3 +1,5 @@
|
|||
import * as Knoin from 'Knoin/Knoin';
|
||||
|
||||
const USER_VIEW_MODELS_HOOKS = [],
|
||||
ADMIN_VIEW_MODELS_HOOKS = [];
|
||||
|
||||
|
@ -45,9 +47,8 @@ export function addSettingsViewModelForAdmin(SettingsViewModelClass, template, l
|
|||
* @param {boolean} admin
|
||||
*/
|
||||
export function runSettingsViewModelHooks(admin) {
|
||||
const Knoin = require('Knoin/Knoin');
|
||||
(admin ? ADMIN_VIEW_MODELS_HOOKS : USER_VIEW_MODELS_HOOKS).forEach(view => {
|
||||
Knoin.addSettingsViewModel(view[0], view[1], view[2], view[3]);
|
||||
Knoin.settingsAddViewModel(view[0], view[1], view[2], view[3]);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -160,3 +160,17 @@ export function reload(admin, language) {
|
|||
doc.head.append(script);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} language
|
||||
* @param {boolean=} isEng = false
|
||||
* @returns {string}
|
||||
*/
|
||||
export function convertLangName(language, isEng = false) {
|
||||
return i18n(
|
||||
'LANGS_NAMES' + (true === isEng ? '_EN' : '') + '/LANG_' + language.toUpperCase().replace(/[^a-zA-Z0-9]+/g, '_'),
|
||||
null,
|
||||
language
|
||||
);
|
||||
}
|
||||
|
|
|
@ -49,20 +49,6 @@ export const convertThemeName = theme => {
|
|||
.trim();
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} language
|
||||
* @param {boolean=} isEng = false
|
||||
* @returns {string}
|
||||
*/
|
||||
export function convertLangName(language, isEng = false) {
|
||||
return require('Common/Translator').i18n(
|
||||
'LANGS_NAMES' + (true === isEng ? '_EN' : '') + '/LANG_' + language.toUpperCase().replace(/[^a-zA-Z0-9]+/g, '_'),
|
||||
null,
|
||||
language
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} domOption
|
||||
* @param {object} item
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
import { ComposeType, FolderType } from 'Common/EnumsUser';
|
||||
import { EmailModel } from 'Model/Email';
|
||||
import { showScreenPopup } from 'Knoin/Knoin';
|
||||
import { encodeHtml } from 'Common/Html';
|
||||
|
||||
const
|
||||
tpl = document.createElement('template'),
|
||||
isArray = Array.isArray,
|
||||
htmlmap = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": '''
|
||||
},
|
||||
htmlspecialchars = str => (''+str).replace(/[&<>"']/g, m => htmlmap[m]);
|
||||
isArray = Array.isArray;
|
||||
|
||||
/**
|
||||
* @param {(string|number)} value
|
||||
|
@ -21,14 +16,6 @@ export function isPosNumeric(value, includeZero = true) {
|
|||
return null != value && (includeZero ? /^[0-9]*$/ : /^[1-9]+[0-9]*$/).test(value.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @returns {string}
|
||||
*/
|
||||
export function encodeHtml(text) {
|
||||
return null != text ? htmlspecialchars(text.toString()) : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @param {number=} len = 100
|
||||
|
@ -101,7 +88,7 @@ export function htmlToPlain(html) {
|
|||
.replace(/[\n]/gm, '<br />')
|
||||
.replace(/[\r]/gm, '')
|
||||
: '',
|
||||
fixAttibuteValue = (...args) => (args && 1 < args.length ? '' + args[1] + htmlspecialchars(args[2]) : ''),
|
||||
fixAttibuteValue = (...args) => (args && 1 < args.length ? '' + args[1] + encodeHtml(args[2]) : ''),
|
||||
convertLinks = (...args) => (args && 1 < args.length ? args[1].trim() : '');
|
||||
|
||||
tpl.innerHTML = html
|
||||
|
@ -470,8 +457,7 @@ export function mailToHelper(mailToUrl, PopupComposeViewModel) {
|
|||
params = {};
|
||||
|
||||
const email = mailToUrl.replace(/\?.+$/, ''),
|
||||
query = mailToUrl.replace(/^[^?]*\?/, ''),
|
||||
EmailModel = require('Model/Email').default;
|
||||
query = mailToUrl.replace(/^[^?]*\?/, '');
|
||||
|
||||
query.split('&').forEach(temp => {
|
||||
temp = temp.split('=');
|
||||
|
@ -506,7 +492,7 @@ export function mailToHelper(mailToUrl, PopupComposeViewModel) {
|
|||
bcc = EmailModel.parseEmailLine(decodeURIComponent(params.bcc));
|
||||
}
|
||||
|
||||
require('Knoin/Knoin').showScreenPopup(PopupComposeViewModel, [
|
||||
showScreenPopup(PopupComposeViewModel, [
|
||||
ComposeType.Empty,
|
||||
null,
|
||||
to,
|
||||
|
|
9
dev/External/Admin/ko.js
vendored
9
dev/External/Admin/ko.js
vendored
|
@ -1,6 +1,6 @@
|
|||
import { SaveSettingsStep } from 'Common/Enums';
|
||||
|
||||
const ko = window.ko;
|
||||
import { pInt } from 'Common/Utils';
|
||||
import ko from 'External/ko';
|
||||
|
||||
ko.bindingHandlers.saveTrigger = {
|
||||
init: (element) => {
|
||||
|
@ -38,11 +38,10 @@ ko.extenders.idleTrigger = (target) => {
|
|||
};
|
||||
|
||||
ko.extenders.posInterer = (target, defaultVal) => {
|
||||
const Utils = require('Common/Utils'),
|
||||
result = ko.computed({
|
||||
const result = ko.computed({
|
||||
read: target,
|
||||
write: newValue => {
|
||||
let val = Utils.pInt(newValue.toString(), defaultVal);
|
||||
let val = pInt(newValue.toString(), defaultVal);
|
||||
if (0 >= val) {
|
||||
val = defaultVal;
|
||||
}
|
||||
|
|
13
dev/External/User/ko.js
vendored
13
dev/External/User/ko.js
vendored
|
@ -1,6 +1,9 @@
|
|||
const ko = window.ko,
|
||||
import ko from 'External/ko';
|
||||
import { HtmlEditor } from 'Common/Html';
|
||||
import { timeToNode } from 'Common/Momentor';
|
||||
import { EmailModel } from 'Model/Email';
|
||||
|
||||
rlContentType = 'snappymail/action',
|
||||
const rlContentType = 'snappymail/action',
|
||||
|
||||
// In Chrome we have no access to dataTransfer.getData unless it's the 'drop' event
|
||||
// In Chrome Mobile dataTransfer.types.includes(rlContentType) fails, only text/plain is set
|
||||
|
@ -30,7 +33,6 @@ ko.bindingHandlers.editor = {
|
|||
let editor = null;
|
||||
|
||||
const fValue = fValueAccessor(),
|
||||
HtmlEditor = require('Common/HtmlEditor').default,
|
||||
fUpdateEditorValue = () => fValue && fValue.__editor && fValue.__editor.setHtmlOrPlain(fValue()),
|
||||
fUpdateKoValue = () => fValue && fValue.__editor && fValue(fValue.__editor.getDataWithHtmlMark()),
|
||||
fOnReady = () => {
|
||||
|
@ -51,7 +53,7 @@ ko.bindingHandlers.editor = {
|
|||
}
|
||||
};
|
||||
|
||||
let ttn = (element, fValueAccessor) => require('Common/Momentor').timeToNode(element, ko.unwrap(fValueAccessor()));
|
||||
let ttn = (element, fValueAccessor) => timeToNode(element, ko.unwrap(fValueAccessor()));
|
||||
ko.bindingHandlers.moment = {
|
||||
init: ttn,
|
||||
update: ttn
|
||||
|
@ -59,8 +61,7 @@ ko.bindingHandlers.moment = {
|
|||
|
||||
ko.bindingHandlers.emailsTags = {
|
||||
init: (element, fValueAccessor, fAllBindingsAccessor) => {
|
||||
const EmailModel = require('Model/Email').default,
|
||||
fValue = fValueAccessor(),
|
||||
const fValue = fValueAccessor(),
|
||||
fAllBindings = fAllBindingsAccessor(),
|
||||
inputDelimiters = [',', ';', '\n'];
|
||||
|
||||
|
|
23
dev/External/ko.js
vendored
23
dev/External/ko.js
vendored
|
@ -1,32 +1,31 @@
|
|||
import { i18n, i18nToNodes, trigger } from 'Common/Translator';
|
||||
import { dropdownVisibility } from 'Common/Globals';
|
||||
|
||||
const
|
||||
doc = document,
|
||||
ko = window.ko,
|
||||
Translator = () => require('Common/Translator'),
|
||||
Globals = () => require('Common/Globals'),
|
||||
isFunction = v => typeof v === 'function',
|
||||
koValue = value => !ko.isObservable(value) && isFunction(value) ? value() : ko.unwrap(value);
|
||||
|
||||
ko.bindingHandlers.tooltip = {
|
||||
init: (element, fValueAccessor) => {
|
||||
const Global = Globals();
|
||||
const sValue = koValue(fValueAccessor());
|
||||
|
||||
if ('off' === element.dataset.tooltipI18n) {
|
||||
element.title = sValue;
|
||||
} else {
|
||||
element.title = Translator().i18n(sValue);
|
||||
Translator().trigger.subscribe(() =>
|
||||
element.title = Translator().i18n(sValue)
|
||||
element.title = i18n(sValue);
|
||||
trigger.subscribe(() =>
|
||||
element.title = i18n(sValue)
|
||||
);
|
||||
Global.dropdownVisibility.subscribe(() =>
|
||||
element.title = Translator().i18n(sValue)
|
||||
dropdownVisibility.subscribe(() =>
|
||||
element.title = i18n(sValue)
|
||||
);
|
||||
}
|
||||
},
|
||||
update: (element, fValueAccessor) => {
|
||||
const sValue = koValue(fValueAccessor());
|
||||
if (sValue) {
|
||||
element.title = 'off' === element.dataset.tooltipI18n ? sValue : Translator().i18n(sValue);
|
||||
element.title = 'off' === element.dataset.tooltipI18n ? sValue : i18n(sValue);
|
||||
} else {
|
||||
element.title = '';
|
||||
}
|
||||
|
@ -111,13 +110,13 @@ ko.bindingHandlers.modal = {
|
|||
};
|
||||
|
||||
ko.bindingHandlers.i18nInit = {
|
||||
init: element => Translator().i18nToNodes(element)
|
||||
init: element => i18nToNodes(element)
|
||||
};
|
||||
|
||||
ko.bindingHandlers.i18nUpdate = {
|
||||
update: (element, fValueAccessor) => {
|
||||
ko.unwrap(fValueAccessor());
|
||||
Translator().i18nToNodes(element);
|
||||
i18nToNodes(element);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ export function createCommand(fExecute, fCanExecute = true) {
|
|||
* @param {boolean=} isDefault = false
|
||||
* @returns {void}
|
||||
*/
|
||||
export function addSettingsViewModel(SettingsViewModelClass, template, labelName, route, isDefault = false) {
|
||||
export function settingsAddViewModel(SettingsViewModelClass, template, labelName, route, isDefault = false) {
|
||||
SettingsViewModelClass.__rlSettingsData = {
|
||||
Label: labelName,
|
||||
Template: template,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { encodeHtml } from 'Common/UtilsUser';
|
||||
import { encodeHtml } from 'Common/Html';
|
||||
|
||||
import { AbstractModel } from 'Knoin/AbstractModel';
|
||||
|
||||
|
|
|
@ -1,227 +0,0 @@
|
|||
import ko from 'ko';
|
||||
|
||||
import { FolderType } from 'Common/EnumsUser';
|
||||
import { isPosNumeric } from 'Common/UtilsUser';
|
||||
import { i18n, trigger as translatorTrigger } from 'Common/Translator';
|
||||
|
||||
import { AbstractModel } from 'Knoin/AbstractModel';
|
||||
import { FolderCollectionModel } from 'Model/FolderCollection';
|
||||
|
||||
function getSystemFolderName(type, def)
|
||||
{
|
||||
switch (type) {
|
||||
case FolderType.Inbox:
|
||||
return i18n('FOLDER_LIST/INBOX_NAME');
|
||||
case FolderType.SentItems:
|
||||
return i18n('FOLDER_LIST/SENT_NAME');
|
||||
case FolderType.Draft:
|
||||
return i18n('FOLDER_LIST/DRAFTS_NAME');
|
||||
case FolderType.Spam:
|
||||
return i18n('GLOBAL/SPAM');
|
||||
case FolderType.Trash:
|
||||
return i18n('FOLDER_LIST/TRASH_NAME');
|
||||
case FolderType.Archive:
|
||||
return i18n('FOLDER_LIST/ARCHIVE_NAME');
|
||||
// no default
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
export class FolderModel extends AbstractModel {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.fullName = '';
|
||||
this.fullNameRaw = '';
|
||||
this.fullNameHash = '';
|
||||
this.delimiter = '';
|
||||
this.namespace = '';
|
||||
this.deep = 0;
|
||||
this.interval = 0;
|
||||
|
||||
this.selectable = false;
|
||||
this.exists = true;
|
||||
|
||||
this.addObservables({
|
||||
name: '',
|
||||
type: FolderType.User,
|
||||
|
||||
focused: false,
|
||||
selected: false,
|
||||
edited: false,
|
||||
subscribed: true,
|
||||
checkable: false,
|
||||
deleteAccess: false,
|
||||
|
||||
nameForEdit: '',
|
||||
|
||||
privateMessageCountAll: 0,
|
||||
privateMessageCountUnread: 0,
|
||||
|
||||
collapsedPrivate: true
|
||||
});
|
||||
|
||||
this.subFolders = ko.observableArray(new FolderCollectionModel);
|
||||
this.actionBlink = ko.observable(false).extend({ falseTimeout: 1000 });
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param {FetchJsonFolder} json
|
||||
* @returns {?FolderModel}
|
||||
*/
|
||||
static reviveFromJson(json) {
|
||||
const folder = super.reviveFromJson(json);
|
||||
if (folder) {
|
||||
folder.deep = json.FullNameRaw.split(folder.delimiter).length - 1;
|
||||
|
||||
folder.messageCountAll = ko.computed({
|
||||
read: folder.privateMessageCountAll,
|
||||
write: (iValue) => {
|
||||
if (isPosNumeric(iValue, true)) {
|
||||
folder.privateMessageCountAll(iValue);
|
||||
} else {
|
||||
folder.privateMessageCountAll.valueHasMutated();
|
||||
}
|
||||
}
|
||||
})
|
||||
.extend({ notify: 'always' });
|
||||
|
||||
folder.messageCountUnread = ko.computed({
|
||||
read: folder.privateMessageCountUnread,
|
||||
write: (value) => {
|
||||
if (isPosNumeric(value, true)) {
|
||||
folder.privateMessageCountUnread(value);
|
||||
} else {
|
||||
folder.privateMessageCountUnread.valueHasMutated();
|
||||
}
|
||||
}
|
||||
})
|
||||
.extend({ notify: 'always' });
|
||||
|
||||
folder.addComputables({
|
||||
|
||||
isInbox: () => FolderType.Inbox === folder.type(),
|
||||
|
||||
hasSubscribedSubfolders:
|
||||
() =>
|
||||
!!folder.subFolders.find(
|
||||
oFolder => (oFolder.subscribed() || oFolder.hasSubscribedSubfolders()) && !oFolder.isSystemFolder()
|
||||
),
|
||||
|
||||
canBeEdited: () => FolderType.User === folder.type() && folder.exists && folder.selectable,
|
||||
|
||||
visible: () => {
|
||||
const isSubscribed = folder.subscribed(),
|
||||
isSubFolders = folder.hasSubscribedSubfolders();
|
||||
|
||||
return isSubscribed || (isSubFolders && (!folder.exists || !folder.selectable));
|
||||
},
|
||||
|
||||
isSystemFolder: () => FolderType.User !== folder.type(),
|
||||
|
||||
hidden: () => {
|
||||
const isSystem = folder.isSystemFolder(),
|
||||
isSubFolders = folder.hasSubscribedSubfolders();
|
||||
|
||||
return (isSystem && !isSubFolders) || (!folder.selectable && !isSubFolders);
|
||||
},
|
||||
|
||||
printableUnreadCount: () => {
|
||||
const count = folder.messageCountAll(),
|
||||
unread = folder.messageCountUnread(),
|
||||
type = folder.type();
|
||||
|
||||
if (0 < count) {
|
||||
if (FolderType.Draft === type) {
|
||||
return '' + count;
|
||||
}
|
||||
if (
|
||||
0 < unread &&
|
||||
FolderType.Trash !== type &&
|
||||
FolderType.Archive !== type &&
|
||||
FolderType.SentItems !== type
|
||||
) {
|
||||
return '' + unread;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
|
||||
canBeDeleted: () => !folder.isSystemFolder() && !folder.subFolders.length,
|
||||
|
||||
selectableForFolderList: () => !folder.isSystemFolder() && folder.selectable,
|
||||
|
||||
canBeSubscribed: () => !folder.isSystemFolder() && folder.selectable,
|
||||
|
||||
canBeChecked: () => !folder.isSystemFolder() && folder.selectable,
|
||||
|
||||
localName: () => {
|
||||
let name = folder.name();
|
||||
if (folder.isSystemFolder()) {
|
||||
translatorTrigger();
|
||||
name = getSystemFolderName(folder.type(), name);
|
||||
}
|
||||
return name;
|
||||
},
|
||||
|
||||
manageFolderSystemName: () => {
|
||||
if (folder.isSystemFolder()) {
|
||||
translatorTrigger();
|
||||
let suffix = getSystemFolderName(folder.type(), '');
|
||||
if (folder.name() !== suffix && 'inbox' !== suffix.toLowerCase()) {
|
||||
return '(' + suffix + ')';
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
|
||||
collapsed: {
|
||||
read: () => !folder.hidden() && folder.collapsedPrivate(),
|
||||
write: (value) => {
|
||||
folder.collapsedPrivate(value);
|
||||
}
|
||||
},
|
||||
|
||||
hasUnreadMessages: () => 0 < folder.messageCountUnread() && folder.printableUnreadCount(),
|
||||
|
||||
hasSubscribedUnreadMessagesSubfolders: () =>
|
||||
!!folder.subFolders.find(
|
||||
folder => folder.hasUnreadMessages() || folder.hasSubscribedUnreadMessagesSubfolders()
|
||||
)
|
||||
});
|
||||
|
||||
folder.addSubscribables({
|
||||
name: value => folder.nameForEdit(value),
|
||||
|
||||
edited: value => value && folder.nameForEdit(folder.name()),
|
||||
|
||||
messageCountUnread: unread => {
|
||||
if (FolderType.Inbox === folder.type()) {
|
||||
dispatchEvent(new CustomEvent('mailbox.inbox-unread-count', {detail:unread}));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
collapsedCss() {
|
||||
return 'e-collapsed-sign ' + (this.hasSubscribedSubfolders()
|
||||
? (this.collapsed() ? 'icon-right-mini' : 'icon-down-mini')
|
||||
: 'icon-none'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
printableFullName() {
|
||||
return this.fullName.split(this.delimiter).join(' / ');
|
||||
}
|
||||
}
|
|
@ -10,11 +10,12 @@ import * as Local from 'Storage/Client';
|
|||
import AppStore from 'Stores/User/App';
|
||||
import FolderStore from 'Stores/User/Folder';
|
||||
|
||||
import { FolderModel } from 'Model/Folder';
|
||||
import ko from 'ko';
|
||||
|
||||
import Remote from 'Remote/User/Fetch';
|
||||
import { isPosNumeric } from 'Common/UtilsUser';
|
||||
import { i18n, trigger as translatorTrigger } from 'Common/Translator';
|
||||
|
||||
'use strict';
|
||||
import { AbstractModel } from 'Knoin/AbstractModel';
|
||||
|
||||
const Settings = rl.settings,
|
||||
|
||||
|
@ -141,7 +142,7 @@ export class FolderCollectionModel extends AbstractCollectionModel
|
|||
FolderStore.archiveFolder(normalizeFolder(Settings.get('ArchiveFolder')));
|
||||
|
||||
if (update) {
|
||||
Remote.saveSystemFolders(()=>{}, {
|
||||
rl.app.Remote.saveSystemFolders(()=>{}, {
|
||||
SentFolder: FolderStore.sentFolder(),
|
||||
DraftFolder: FolderStore.draftFolder(),
|
||||
SpamFolder: FolderStore.spamFolder(),
|
||||
|
@ -155,3 +156,222 @@ export class FolderCollectionModel extends AbstractCollectionModel
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
function getSystemFolderName(type, def)
|
||||
{
|
||||
switch (type) {
|
||||
case FolderType.Inbox:
|
||||
return i18n('FOLDER_LIST/INBOX_NAME');
|
||||
case FolderType.SentItems:
|
||||
return i18n('FOLDER_LIST/SENT_NAME');
|
||||
case FolderType.Draft:
|
||||
return i18n('FOLDER_LIST/DRAFTS_NAME');
|
||||
case FolderType.Spam:
|
||||
return i18n('GLOBAL/SPAM');
|
||||
case FolderType.Trash:
|
||||
return i18n('FOLDER_LIST/TRASH_NAME');
|
||||
case FolderType.Archive:
|
||||
return i18n('FOLDER_LIST/ARCHIVE_NAME');
|
||||
// no default
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
export class FolderModel extends AbstractModel {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.fullName = '';
|
||||
this.fullNameRaw = '';
|
||||
this.fullNameHash = '';
|
||||
this.delimiter = '';
|
||||
this.namespace = '';
|
||||
this.deep = 0;
|
||||
this.interval = 0;
|
||||
|
||||
this.selectable = false;
|
||||
this.exists = true;
|
||||
|
||||
this.addObservables({
|
||||
name: '',
|
||||
type: FolderType.User,
|
||||
|
||||
focused: false,
|
||||
selected: false,
|
||||
edited: false,
|
||||
subscribed: true,
|
||||
checkable: false,
|
||||
deleteAccess: false,
|
||||
|
||||
nameForEdit: '',
|
||||
|
||||
privateMessageCountAll: 0,
|
||||
privateMessageCountUnread: 0,
|
||||
|
||||
collapsedPrivate: true
|
||||
});
|
||||
|
||||
this.subFolders = ko.observableArray(new FolderCollectionModel);
|
||||
this.actionBlink = ko.observable(false).extend({ falseTimeout: 1000 });
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param {FetchJsonFolder} json
|
||||
* @returns {?FolderModel}
|
||||
*/
|
||||
static reviveFromJson(json) {
|
||||
const folder = super.reviveFromJson(json);
|
||||
if (folder) {
|
||||
folder.deep = json.FullNameRaw.split(folder.delimiter).length - 1;
|
||||
|
||||
folder.messageCountAll = ko.computed({
|
||||
read: folder.privateMessageCountAll,
|
||||
write: (iValue) => {
|
||||
if (isPosNumeric(iValue, true)) {
|
||||
folder.privateMessageCountAll(iValue);
|
||||
} else {
|
||||
folder.privateMessageCountAll.valueHasMutated();
|
||||
}
|
||||
}
|
||||
})
|
||||
.extend({ notify: 'always' });
|
||||
|
||||
folder.messageCountUnread = ko.computed({
|
||||
read: folder.privateMessageCountUnread,
|
||||
write: (value) => {
|
||||
if (isPosNumeric(value, true)) {
|
||||
folder.privateMessageCountUnread(value);
|
||||
} else {
|
||||
folder.privateMessageCountUnread.valueHasMutated();
|
||||
}
|
||||
}
|
||||
})
|
||||
.extend({ notify: 'always' });
|
||||
|
||||
folder.addComputables({
|
||||
|
||||
isInbox: () => FolderType.Inbox === folder.type(),
|
||||
|
||||
hasSubscribedSubfolders:
|
||||
() =>
|
||||
!!folder.subFolders.find(
|
||||
oFolder => (oFolder.subscribed() || oFolder.hasSubscribedSubfolders()) && !oFolder.isSystemFolder()
|
||||
),
|
||||
|
||||
canBeEdited: () => FolderType.User === folder.type() && folder.exists && folder.selectable,
|
||||
|
||||
visible: () => {
|
||||
const isSubscribed = folder.subscribed(),
|
||||
isSubFolders = folder.hasSubscribedSubfolders();
|
||||
|
||||
return isSubscribed || (isSubFolders && (!folder.exists || !folder.selectable));
|
||||
},
|
||||
|
||||
isSystemFolder: () => FolderType.User !== folder.type(),
|
||||
|
||||
hidden: () => {
|
||||
const isSystem = folder.isSystemFolder(),
|
||||
isSubFolders = folder.hasSubscribedSubfolders();
|
||||
|
||||
return (isSystem && !isSubFolders) || (!folder.selectable && !isSubFolders);
|
||||
},
|
||||
|
||||
printableUnreadCount: () => {
|
||||
const count = folder.messageCountAll(),
|
||||
unread = folder.messageCountUnread(),
|
||||
type = folder.type();
|
||||
|
||||
if (0 < count) {
|
||||
if (FolderType.Draft === type) {
|
||||
return '' + count;
|
||||
}
|
||||
if (
|
||||
0 < unread &&
|
||||
FolderType.Trash !== type &&
|
||||
FolderType.Archive !== type &&
|
||||
FolderType.SentItems !== type
|
||||
) {
|
||||
return '' + unread;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
|
||||
canBeDeleted: () => !folder.isSystemFolder() && !folder.subFolders.length,
|
||||
|
||||
selectableForFolderList: () => !folder.isSystemFolder() && folder.selectable,
|
||||
|
||||
canBeSubscribed: () => !folder.isSystemFolder() && folder.selectable,
|
||||
|
||||
canBeChecked: () => !folder.isSystemFolder() && folder.selectable,
|
||||
|
||||
localName: () => {
|
||||
let name = folder.name();
|
||||
if (folder.isSystemFolder()) {
|
||||
translatorTrigger();
|
||||
name = getSystemFolderName(folder.type(), name);
|
||||
}
|
||||
return name;
|
||||
},
|
||||
|
||||
manageFolderSystemName: () => {
|
||||
if (folder.isSystemFolder()) {
|
||||
translatorTrigger();
|
||||
let suffix = getSystemFolderName(folder.type(), '');
|
||||
if (folder.name() !== suffix && 'inbox' !== suffix.toLowerCase()) {
|
||||
return '(' + suffix + ')';
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
|
||||
collapsed: {
|
||||
read: () => !folder.hidden() && folder.collapsedPrivate(),
|
||||
write: (value) => {
|
||||
folder.collapsedPrivate(value);
|
||||
}
|
||||
},
|
||||
|
||||
hasUnreadMessages: () => 0 < folder.messageCountUnread() && folder.printableUnreadCount(),
|
||||
|
||||
hasSubscribedUnreadMessagesSubfolders: () =>
|
||||
!!folder.subFolders.find(
|
||||
folder => folder.hasUnreadMessages() || folder.hasSubscribedUnreadMessagesSubfolders()
|
||||
)
|
||||
});
|
||||
|
||||
folder.addSubscribables({
|
||||
name: value => folder.nameForEdit(value),
|
||||
|
||||
edited: value => value && folder.nameForEdit(folder.name()),
|
||||
|
||||
messageCountUnread: unread => {
|
||||
if (FolderType.Inbox === folder.type()) {
|
||||
dispatchEvent(new CustomEvent('mailbox.inbox-unread-count', {detail:unread}));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return folder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
collapsedCss() {
|
||||
return 'e-collapsed-sign ' + (this.hasSubscribedSubfolders()
|
||||
? (this.collapsed() ? 'icon-right-mini' : 'icon-down-mini')
|
||||
: 'icon-none'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
printableFullName() {
|
||||
return this.fullName.split(this.delimiter).join(' / ');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import ko from 'ko';
|
|||
import { MessagePriority } from 'Common/EnumsUser';
|
||||
import { i18n } from 'Common/Translator';
|
||||
|
||||
import { encodeHtml } from 'Common/UtilsUser';
|
||||
import { encodeHtml } from 'Common/Html';
|
||||
|
||||
import { messageViewLink, messageDownloadLink } from 'Common/Links';
|
||||
|
||||
|
@ -14,6 +14,8 @@ import { AttachmentCollectionModel } from 'Model/AttachmentCollection';
|
|||
import { EmailCollectionModel } from 'Model/EmailCollection';
|
||||
import { AbstractModel } from 'Knoin/AbstractModel';
|
||||
|
||||
import PreviewHTML from 'Html/PreviewMessage.html';
|
||||
|
||||
const isArray = Array.isArray,
|
||||
|
||||
SignedVerifyStatus = {
|
||||
|
@ -379,9 +381,8 @@ export class MessageModel extends AbstractModel {
|
|||
ccLine = this.ccToLine(false),
|
||||
m = 0 < timeStampInUTC ? new Date(timeStampInUTC * 1000) : null,
|
||||
win = open(''),
|
||||
doc = win.document,
|
||||
html = require('Html/PreviewMessage.html');
|
||||
doc.write((html.default)
|
||||
doc = win.document;
|
||||
doc.write(PreviewHTML
|
||||
.replace(/{{subject}}/g, encodeHtml(this.subject()))
|
||||
.replace('{{date}}', encodeHtml(m ? m.format('LLL') : ''))
|
||||
.replace('{{fromCreds}}', encodeHtml(this.fromToLine(false)))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { addSettingsViewModel } from 'Knoin/Knoin';
|
||||
import { settingsAddViewModel } from 'Knoin/Knoin';
|
||||
import { runSettingsViewModelHooks } from 'Common/Plugins';
|
||||
|
||||
import { AbstractSettingsScreen } from 'Screen/AbstractSettings';
|
||||
|
@ -25,7 +25,7 @@ export class SettingsAdminScreen extends AbstractSettingsScreen {
|
|||
* @param {Function=} fCallback = null
|
||||
*/
|
||||
setupSettings(fCallback = null) {
|
||||
addSettingsViewModel(
|
||||
settingsAddViewModel(
|
||||
GeneralAdminSettings,
|
||||
'AdminSettingsGeneral',
|
||||
'TABS_LABELS/LABEL_GENERAL_NAME',
|
||||
|
@ -43,7 +43,7 @@ export class SettingsAdminScreen extends AbstractSettingsScreen {
|
|||
[PackagesAdminSettings, 'Packages'],
|
||||
[AboutAdminSettings, 'About'],
|
||||
].forEach(item =>
|
||||
addSettingsViewModel(
|
||||
settingsAddViewModel(
|
||||
item[0],
|
||||
'AdminSettings'+item[1],
|
||||
'TABS_LABELS/LABEL_'+item[1].toUpperCase()+'_NAME',
|
||||
|
|
|
@ -20,6 +20,8 @@ import { warmUpScreenPopup } from 'Knoin/Knoin';
|
|||
|
||||
import { AbstractScreen } from 'Knoin/AbstractScreen';
|
||||
|
||||
import { ComposePopupView } from 'View/Popup/Compose';
|
||||
|
||||
const Settings = rl.settings;
|
||||
|
||||
export class MailBoxUserScreen extends AbstractScreen {
|
||||
|
@ -101,7 +103,7 @@ export class MailBoxUserScreen extends AbstractScreen {
|
|||
*/
|
||||
onStart() {
|
||||
setTimeout(() => SettingsStore.layout.valueHasMutated(), 50);
|
||||
setTimeout(() => warmUpScreenPopup(require('View/Popup/Compose')), 500);
|
||||
setTimeout(() => warmUpScreenPopup(ComposePopupView), 500);
|
||||
|
||||
addEventListener('mailbox.inbox-unread-count', e => {
|
||||
FolderStore.foldersInboxUnreadCount(e.detail);
|
||||
|
|
|
@ -6,7 +6,7 @@ import { initOnStartOrLangChange, i18n } from 'Common/Translator';
|
|||
import AppStore from 'Stores/User/App';
|
||||
import AccountStore from 'Stores/User/Account';
|
||||
|
||||
import { addSettingsViewModel } from 'Knoin/Knoin';
|
||||
import { settingsAddViewModel } from 'Knoin/Knoin';
|
||||
|
||||
import { AbstractSettingsScreen } from 'Screen/AbstractSettings';
|
||||
|
||||
|
@ -48,14 +48,14 @@ export class SettingsUserScreen extends AbstractSettingsScreen {
|
|||
return false;
|
||||
}
|
||||
|
||||
addSettingsViewModel(GeneralUserSettings, 'SettingsGeneral', 'SETTINGS_LABELS/LABEL_GENERAL_NAME', 'general', true);
|
||||
settingsAddViewModel(GeneralUserSettings, 'SettingsGeneral', 'SETTINGS_LABELS/LABEL_GENERAL_NAME', 'general', true);
|
||||
|
||||
if (AppStore.contactsIsAllowed()) {
|
||||
addSettingsViewModel(ContactsUserSettings, 'SettingsContacts', 'SETTINGS_LABELS/LABEL_CONTACTS_NAME', 'contacts');
|
||||
settingsAddViewModel(ContactsUserSettings, 'SettingsContacts', 'SETTINGS_LABELS/LABEL_CONTACTS_NAME', 'contacts');
|
||||
}
|
||||
|
||||
if (Settings.capa(Capa.AdditionalAccounts) || Settings.capa(Capa.Identities)) {
|
||||
addSettingsViewModel(
|
||||
settingsAddViewModel(
|
||||
AccountsUserSettings,
|
||||
'SettingsAccounts',
|
||||
Settings.capa(Capa.AdditionalAccounts)
|
||||
|
@ -66,15 +66,15 @@ export class SettingsUserScreen extends AbstractSettingsScreen {
|
|||
}
|
||||
|
||||
if (Settings.capa(Capa.Sieve)) {
|
||||
addSettingsViewModel(FiltersUserSettings, 'SettingsFilters', 'SETTINGS_LABELS/LABEL_FILTERS_NAME', 'filters');
|
||||
settingsAddViewModel(FiltersUserSettings, 'SettingsFilters', 'SETTINGS_LABELS/LABEL_FILTERS_NAME', 'filters');
|
||||
}
|
||||
|
||||
if (Settings.capa(Capa.AutoLogout) || Settings.capa(Capa.TwoFactor)) {
|
||||
addSettingsViewModel(SecurityUserSettings, 'SettingsSecurity', 'SETTINGS_LABELS/LABEL_SECURITY_NAME', 'security');
|
||||
settingsAddViewModel(SecurityUserSettings, 'SettingsSecurity', 'SETTINGS_LABELS/LABEL_SECURITY_NAME', 'security');
|
||||
}
|
||||
|
||||
if (Settings.capa(Capa.Templates)) {
|
||||
addSettingsViewModel(
|
||||
settingsAddViewModel(
|
||||
TemplatesUserSettings,
|
||||
'SettingsTemplates',
|
||||
'SETTINGS_LABELS/LABEL_TEMPLATES_NAME',
|
||||
|
@ -83,15 +83,15 @@ export class SettingsUserScreen extends AbstractSettingsScreen {
|
|||
}
|
||||
|
||||
if (Settings.capa(Capa.Folders)) {
|
||||
addSettingsViewModel(FoldersUserSettings, 'SettingsFolders', 'SETTINGS_LABELS/LABEL_FOLDERS_NAME', 'folders');
|
||||
settingsAddViewModel(FoldersUserSettings, 'SettingsFolders', 'SETTINGS_LABELS/LABEL_FOLDERS_NAME', 'folders');
|
||||
}
|
||||
|
||||
if (Settings.capa(Capa.Themes)) {
|
||||
addSettingsViewModel(ThemesUserSettings, 'SettingsThemes', 'SETTINGS_LABELS/LABEL_THEMES_NAME', 'themes');
|
||||
settingsAddViewModel(ThemesUserSettings, 'SettingsThemes', 'SETTINGS_LABELS/LABEL_THEMES_NAME', 'themes');
|
||||
}
|
||||
|
||||
if (Settings.capa(Capa.OpenPGP)) {
|
||||
addSettingsViewModel(OpenPgpUserSettings, 'SettingsOpenPGP', 'OpenPGP', 'openpgp');
|
||||
settingsAddViewModel(OpenPgpUserSettings, 'SettingsOpenPGP', 'OpenPGP', 'openpgp');
|
||||
}
|
||||
|
||||
runSettingsViewModelHooks(false);
|
||||
|
|
|
@ -6,6 +6,9 @@ import { showScreenPopup } from 'Knoin/Knoin';
|
|||
import DomainStore from 'Stores/Admin/Domain';
|
||||
import Remote from 'Remote/Admin/Fetch';
|
||||
|
||||
import { DomainPopupView } from 'View/Popup/Domain';
|
||||
import { DomainAliasPopupView } from 'View/Popup/DomainAlias';
|
||||
|
||||
export class DomainsAdminSettings {
|
||||
constructor() {
|
||||
this.domains = DomainStore.domains;
|
||||
|
@ -19,11 +22,11 @@ export class DomainsAdminSettings {
|
|||
}
|
||||
|
||||
createDomain() {
|
||||
showScreenPopup(require('View/Popup/Domain'));
|
||||
showScreenPopup(DomainPopupView);
|
||||
}
|
||||
|
||||
createDomainAlias() {
|
||||
showScreenPopup(require('View/Popup/DomainAlias'));
|
||||
showScreenPopup(DomainAliasPopupView);
|
||||
}
|
||||
|
||||
deleteDomain(domain) {
|
||||
|
@ -47,7 +50,7 @@ export class DomainsAdminSettings {
|
|||
|
||||
onDomainLoadRequest(sResult, oData) {
|
||||
if (StorageResultType.Success === sResult && oData && oData.Result) {
|
||||
showScreenPopup(require('View/Popup/Domain'), [oData.Result]);
|
||||
showScreenPopup(DomainPopupView, [oData.Result]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,12 +4,11 @@ import {
|
|||
pInt,
|
||||
settingsSaveHelperSimpleFunction,
|
||||
changeTheme,
|
||||
convertThemeName,
|
||||
convertLangName
|
||||
convertThemeName
|
||||
} from 'Common/Utils';
|
||||
|
||||
import { SaveSettingsStep } from 'Common/Enums';
|
||||
import { reload as translatorReload } from 'Common/Translator';
|
||||
import { reload as translatorReload, convertLangName } from 'Common/Translator';
|
||||
|
||||
import { showScreenPopup } from 'Knoin/Knoin';
|
||||
|
||||
|
@ -19,6 +18,7 @@ import ThemeStore from 'Stores/Theme';
|
|||
import LanguageStore from 'Stores/Language';
|
||||
import AppAdminStore from 'Stores/Admin/App';
|
||||
import CapaAdminStore from 'Stores/Admin/Capa';
|
||||
import LanguagesPopupView from 'View/Popup/Languages';
|
||||
|
||||
const settingsGet = rl.settings.get;
|
||||
|
||||
|
@ -167,11 +167,11 @@ export class GeneralAdminSettings {
|
|||
}
|
||||
|
||||
selectLanguage() {
|
||||
showScreenPopup(require('View/Popup/Languages'), [this.language, this.languages(), LanguageStore.userLanguage()]);
|
||||
showScreenPopup(LanguagesPopupView, [this.language, this.languages(), LanguageStore.userLanguage()]);
|
||||
}
|
||||
|
||||
selectLanguageAdmin() {
|
||||
showScreenPopup(require('View/Popup/Languages'), [
|
||||
showScreenPopup(LanguagesPopupView, [
|
||||
this.languageAdmin,
|
||||
this.languagesAdmin(),
|
||||
LanguageStore.userLanguageAdmin()
|
||||
|
|
|
@ -9,6 +9,8 @@ import PluginStore from 'Stores/Admin/Plugin';
|
|||
|
||||
import Remote from 'Remote/Admin/Fetch';
|
||||
|
||||
import { PluginPopupView } from 'View/Popup/Plugin';
|
||||
|
||||
export class PluginsAdminSettings {
|
||||
constructor() {
|
||||
this.enabledPlugins = ko.observable(!!rl.settings.get('EnabledPlugins'));
|
||||
|
@ -54,7 +56,7 @@ export class PluginsAdminSettings {
|
|||
|
||||
onPluginLoadRequest(result, data) {
|
||||
if (StorageResultType.Success === result && data && data.Result) {
|
||||
showScreenPopup(require('View/Popup/Plugin'), [data.Result]);
|
||||
showScreenPopup(PluginPopupView, [data.Result]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,9 @@ import Remote from 'Remote/User/Fetch';
|
|||
|
||||
import { showScreenPopup } from 'Knoin/Knoin';
|
||||
|
||||
import { AccountPopupView } from 'View/Popup/Account';
|
||||
import { IdentityPopupView } from 'View/Popup/Identity';
|
||||
|
||||
export class AccountsUserSettings {
|
||||
constructor() {
|
||||
this.allowAdditionalAccount = rl.settings.capa(Capa.AdditionalAccounts);
|
||||
|
@ -21,21 +24,21 @@ export class AccountsUserSettings {
|
|||
}
|
||||
|
||||
addNewAccount() {
|
||||
showScreenPopup(require('View/Popup/Account'));
|
||||
showScreenPopup(AccountPopupView);
|
||||
}
|
||||
|
||||
editAccount(account) {
|
||||
if (account && account.canBeEdit()) {
|
||||
showScreenPopup(require('View/Popup/Account'), [account]);
|
||||
showScreenPopup(AccountPopupView, [account]);
|
||||
}
|
||||
}
|
||||
|
||||
addNewIdentity() {
|
||||
showScreenPopup(require('View/Popup/Identity'));
|
||||
showScreenPopup(IdentityPopupView);
|
||||
}
|
||||
|
||||
editIdentity(identity) {
|
||||
showScreenPopup(require('View/Popup/Identity'), [identity]);
|
||||
showScreenPopup(IdentityPopupView, [identity]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,6 +11,8 @@ import { SieveScriptModel } from 'Model/SieveScript';
|
|||
|
||||
import { showScreenPopup } from 'Knoin/Knoin';
|
||||
|
||||
import { SieveScriptPopupView } from 'View/Popup/SieveScript';
|
||||
|
||||
export class FiltersUserSettings {
|
||||
constructor() {
|
||||
this.scripts = SieveStore.scripts;
|
||||
|
@ -60,11 +62,11 @@ export class FiltersUserSettings {
|
|||
}
|
||||
|
||||
addScript() {
|
||||
showScreenPopup(require('View/Popup/SieveScript'), [new SieveScriptModel()]);
|
||||
showScreenPopup(SieveScriptPopupView, [new SieveScriptModel()]);
|
||||
}
|
||||
|
||||
editScript(script) {
|
||||
showScreenPopup(require('View/Popup/SieveScript'), [script]);
|
||||
showScreenPopup(SieveScriptPopupView, [script]);
|
||||
}
|
||||
|
||||
deleteScript(script) {
|
||||
|
|
|
@ -14,6 +14,9 @@ import Remote from 'Remote/User/Fetch';
|
|||
|
||||
import { showScreenPopup } from 'Knoin/Knoin';
|
||||
|
||||
import { FolderCreatePopupView } from 'View/Popup/FolderCreate';
|
||||
import { FolderSystemPopupView } from 'View/Popup/FolderSystem';
|
||||
|
||||
export class FoldersUserSettings {
|
||||
constructor() {
|
||||
this.displaySpecSetting = FolderStore.displaySpecSetting;
|
||||
|
@ -79,11 +82,11 @@ export class FoldersUserSettings {
|
|||
}
|
||||
|
||||
createFolder() {
|
||||
showScreenPopup(require('View/Popup/FolderCreate'));
|
||||
showScreenPopup(FolderCreatePopupView);
|
||||
}
|
||||
|
||||
systemFolder() {
|
||||
showScreenPopup(require('View/Popup/FolderSystem'));
|
||||
showScreenPopup(FolderSystemPopupView);
|
||||
}
|
||||
|
||||
deleteFolder(folderToRemove) {
|
||||
|
|
|
@ -5,9 +5,9 @@ import { MESSAGES_PER_PAGE_VALUES } from 'Common/Consts';
|
|||
import { SaveSettingsStep } from 'Common/Enums';
|
||||
import { EditorDefaultType, Layout } from 'Common/EnumsUser';
|
||||
|
||||
import { settingsSaveHelperSimpleFunction, convertLangName } from 'Common/Utils';
|
||||
import { settingsSaveHelperSimpleFunction } from 'Common/Utils';
|
||||
|
||||
import { i18n, trigger as translatorTrigger, reload as translatorReload } from 'Common/Translator';
|
||||
import { i18n, trigger as translatorTrigger, reload as translatorReload, convertLangName } from 'Common/Translator';
|
||||
|
||||
import { showScreenPopup } from 'Knoin/Knoin';
|
||||
|
||||
|
@ -20,6 +20,9 @@ import MessageStore from 'Stores/User/Message';
|
|||
|
||||
import Remote from 'Remote/User/Fetch';
|
||||
|
||||
import { IdentityPopupView } from 'View/Popup/Identity';
|
||||
import { LanguagesPopupView } from 'View/Popup/Languages';
|
||||
|
||||
export class GeneralUserSettings {
|
||||
constructor() {
|
||||
this.language = LanguageStore.language;
|
||||
|
@ -87,7 +90,7 @@ export class GeneralUserSettings {
|
|||
editMainIdentity() {
|
||||
const identity = this.identityMain();
|
||||
if (identity) {
|
||||
showScreenPopup(require('View/Popup/Identity'), [identity]);
|
||||
showScreenPopup(IdentityPopupView, [identity]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,6 +164,6 @@ export class GeneralUserSettings {
|
|||
}
|
||||
|
||||
selectLanguage() {
|
||||
showScreenPopup(require('View/Popup/Languages'), [this.language, this.languages(), LanguageStore.userLanguage()]);
|
||||
showScreenPopup(LanguagesPopupView, [this.language, this.languages(), LanguageStore.userLanguage()]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,10 @@ import Remote from 'Remote/User/Fetch';
|
|||
|
||||
import { showScreenPopup } from 'Knoin/Knoin';
|
||||
|
||||
import { AddOpenPgpKeyPopupView } from 'View/Popup/AddOpenPgpKey';
|
||||
import { NewOpenPgpKeyPopupView } from 'View/Popup/NewOpenPgpKey';
|
||||
import { ViewOpenPgpKeyPopupView } from 'View/Popup/ViewOpenPgpKey';
|
||||
|
||||
export class OpenPgpUserSettings {
|
||||
constructor() {
|
||||
this.openpgpkeys = PgpStore.openpgpkeys;
|
||||
|
@ -21,16 +25,16 @@ export class OpenPgpUserSettings {
|
|||
}
|
||||
|
||||
addOpenPgpKey() {
|
||||
showScreenPopup(require('View/Popup/AddOpenPgpKey'));
|
||||
showScreenPopup(AddOpenPgpKeyPopupView);
|
||||
}
|
||||
|
||||
generateOpenPgpKey() {
|
||||
showScreenPopup(require('View/Popup/NewOpenPgpKey'));
|
||||
showScreenPopup(NewOpenPgpKeyPopupView);
|
||||
}
|
||||
|
||||
viewOpenPgpKey(openPgpKey) {
|
||||
if (openPgpKey) {
|
||||
showScreenPopup(require('View/Popup/ViewOpenPgpKey'), [openPgpKey]);
|
||||
showScreenPopup(ViewOpenPgpKeyPopupView, [openPgpKey]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ import SettinsStore from 'Stores/User/Settings';
|
|||
|
||||
import Remote from 'Remote/User/Fetch';
|
||||
|
||||
import { TwoFactorConfigurationPopupView } from 'View/Popup/TwoFactorConfiguration';
|
||||
|
||||
export class SecurityUserSettings {
|
||||
constructor() {
|
||||
this.capaAutoLogout = rl.settings.capa(Capa.AutoLogout);
|
||||
|
@ -34,7 +36,7 @@ export class SecurityUserSettings {
|
|||
}
|
||||
|
||||
configureTwoFactor() {
|
||||
showScreenPopup(require('View/Popup/TwoFactorConfiguration'));
|
||||
showScreenPopup(TwoFactorConfigurationPopupView);
|
||||
}
|
||||
|
||||
onBuild() {
|
||||
|
|
|
@ -7,6 +7,8 @@ import Remote from 'Remote/User/Fetch';
|
|||
|
||||
import { showScreenPopup } from 'Knoin/Knoin';
|
||||
|
||||
import { TemplatePopupView } from 'View/Popup/Template';
|
||||
|
||||
export class TemplatesUserSettings {
|
||||
constructor() {
|
||||
this.templates = TemplateStore.templates;
|
||||
|
@ -20,12 +22,12 @@ export class TemplatesUserSettings {
|
|||
}
|
||||
|
||||
addNewTemplate() {
|
||||
showScreenPopup(require('View/Popup/Template'));
|
||||
showScreenPopup(TemplatePopupView);
|
||||
}
|
||||
|
||||
editTemplate(oTemplateItem) {
|
||||
if (oTemplateItem) {
|
||||
showScreenPopup(require('View/Popup/Template'), [oTemplateItem]);
|
||||
showScreenPopup(TemplatePopupView, [oTemplateItem]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@ import AccountStore from 'Stores/User/Account';
|
|||
|
||||
import { showScreenPopup } from 'Knoin/Knoin';
|
||||
|
||||
import { MessageOpenPgpPopupView } from 'View/Popup/MessageOpenPgp';
|
||||
|
||||
function controlsHelper(dom, verControl, success, title, text)
|
||||
{
|
||||
dom.classList.toggle('error', !success);
|
||||
|
@ -264,7 +266,7 @@ class PgpUserStore {
|
|||
if (message && message.getEncryptionKeyIds) {
|
||||
const privateKeys = this.findPrivateKeysByEncryptionKeyIds(message.getEncryptionKeyIds(), recipients, true);
|
||||
if (privateKeys && privateKeys.length) {
|
||||
showScreenPopup(require('View/Popup/MessageOpenPgp'), [
|
||||
showScreenPopup(MessageOpenPgpPopupView, [
|
||||
(decryptedKey) => {
|
||||
if (decryptedKey) {
|
||||
message.decrypt(decryptedKey).then(
|
||||
|
|
|
@ -15,7 +15,8 @@ import {
|
|||
} from 'Common/EnumsUser';
|
||||
|
||||
import { inFocus, pInt } from 'Common/Utils';
|
||||
import { encodeHtml, delegateRunOnDestroy } from 'Common/UtilsUser';
|
||||
import { delegateRunOnDestroy } from 'Common/UtilsUser';
|
||||
import { encodeHtml } from 'Common/Html';
|
||||
|
||||
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
|
||||
import { upload } from 'Common/Links';
|
||||
|
@ -23,7 +24,7 @@ import { i18n, getNotification, getUploadErrorDescByCode } from 'Common/Translat
|
|||
import { format as momentorFormat } from 'Common/Momentor';
|
||||
import { MessageFlagsCache, setFolderHash } from 'Common/Cache';
|
||||
|
||||
import { HtmlEditor } from 'Common/HtmlEditor';
|
||||
import { HtmlEditor } from 'Common/Html';
|
||||
|
||||
import AppStore from 'Stores/User/App';
|
||||
import SettingsStore from 'Stores/User/Settings';
|
||||
|
@ -40,6 +41,11 @@ import { ComposeAttachmentModel } from 'Model/ComposeAttachment';
|
|||
import { command, isPopupVisible, showScreenPopup, hideScreenPopup } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
import { FolderSystemPopupView } from 'View/Popup/FolderSystem';
|
||||
import { AskPopupView } from 'View/Popup/Ask';
|
||||
import { ContactsPopupView } from 'View/Popup/Contacts';
|
||||
import { ComposeOpenPgpPopupView } from 'View/Popup/ComposeOpenPgp';
|
||||
|
||||
const Settings = rl.settings,
|
||||
/**
|
||||
* @param {string} prefix
|
||||
|
@ -403,7 +409,7 @@ class ComposePopupView extends AbstractViewPopup {
|
|||
}
|
||||
|
||||
if (!sSentFolder) {
|
||||
showScreenPopup(require('View/Popup/FolderSystem'), [SetSystemFoldersNotification.Sent]);
|
||||
showScreenPopup(FolderSystemPopupView, [SetSystemFoldersNotification.Sent]);
|
||||
} else {
|
||||
this.sendError(false);
|
||||
this.sending(true);
|
||||
|
@ -443,7 +449,7 @@ class ComposePopupView extends AbstractViewPopup {
|
|||
}
|
||||
|
||||
if (FolderStore.draftFolderNotEnabled()) {
|
||||
showScreenPopup(require('View/Popup/FolderSystem'), [SetSystemFoldersNotification.Draft]);
|
||||
showScreenPopup(FolderSystemPopupView, [SetSystemFoldersNotification.Draft]);
|
||||
} else {
|
||||
this.savedError(false);
|
||||
this.saving(true);
|
||||
|
@ -463,9 +469,8 @@ class ComposePopupView extends AbstractViewPopup {
|
|||
|
||||
@command((self) => self.isDraftFolderMessage())
|
||||
deleteCommand() {
|
||||
const PopupsAskViewModel = require('View/Popup/Ask');
|
||||
if (!isPopupVisible(PopupsAskViewModel) && this.modalVisibility()) {
|
||||
showScreenPopup(PopupsAskViewModel, [
|
||||
if (!isPopupVisible(AskPopupView) && this.modalVisibility()) {
|
||||
showScreenPopup(AskPopupView, [
|
||||
i18n('POPUPS_ASK/DESC_WANT_DELETE_MESSAGES'),
|
||||
() => {
|
||||
if (this.modalVisibility()) {
|
||||
|
@ -499,7 +504,7 @@ class ComposePopupView extends AbstractViewPopup {
|
|||
if (this.allowContacts) {
|
||||
this.skipCommand();
|
||||
setTimeout(() => {
|
||||
showScreenPopup(require('View/Popup/Contacts'), [true, this.sLastFocusedField]);
|
||||
showScreenPopup(ContactsPopupView, [true, this.sLastFocusedField]);
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
@ -535,7 +540,7 @@ class ComposePopupView extends AbstractViewPopup {
|
|||
|
||||
openOpenPgpPopup() {
|
||||
if (PgpStore.capaOpenPGP() && this.oEditor && !this.oEditor.isHtml()) {
|
||||
showScreenPopup(require('View/Popup/ComposeOpenPgp'), [
|
||||
showScreenPopup(ComposeOpenPgpPopupView, [
|
||||
(result) => {
|
||||
this.editor((editor) => {
|
||||
editor.setPlain(result);
|
||||
|
@ -780,7 +785,7 @@ class ComposePopupView extends AbstractViewPopup {
|
|||
if (AppStore.composeInEdit()) {
|
||||
type = type || ComposeType.Empty;
|
||||
if (ComposeType.Empty !== type) {
|
||||
showScreenPopup(require('View/Popup/Ask'), [
|
||||
showScreenPopup(AskPopupView, [
|
||||
i18n('COMPOSE/DISCARD_UNSAVED_DATA'),
|
||||
() => {
|
||||
this.initOnShow(type, oMessageOrArray, aToEmails, aCcEmails, aBccEmails, sCustomSubject, sCustomPlainText);
|
||||
|
@ -1137,12 +1142,11 @@ class ComposePopupView extends AbstractViewPopup {
|
|||
}
|
||||
|
||||
tryToClosePopup() {
|
||||
const PopupsAskViewModel = require('View/Popup/Ask');
|
||||
if (!isPopupVisible(PopupsAskViewModel) && this.modalVisibility()) {
|
||||
if (!isPopupVisible(AskPopupView) && this.modalVisibility()) {
|
||||
if (this.bSkipNextHide || (this.isEmptyForm() && !this.draftUid())) {
|
||||
this.closeCommand && this.closeCommand();
|
||||
} else {
|
||||
showScreenPopup(PopupsAskViewModel, [
|
||||
showScreenPopup(AskPopupView, [
|
||||
i18n('POPUPS_ASK/DESC_WANT_CLOSE_THIS_WINDOW'),
|
||||
() => {
|
||||
if (this.modalVisibility()) {
|
||||
|
|
|
@ -26,9 +26,10 @@ import { EmailModel } from 'Model/Email';
|
|||
import { ContactModel } from 'Model/Contact';
|
||||
import { ContactPropertyModel, ContactPropertyType } from 'Model/ContactProperty';
|
||||
|
||||
import { command, showScreenPopup, hideScreenPopup } from 'Knoin/Knoin';
|
||||
import { command, hideScreenPopup } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
|
||||
const CONTACTS_PER_PAGE = 50,
|
||||
propertyIsMail = prop => prop.isType(ContactPropertyType.Email),
|
||||
propertyIsName = prop => prop.isType(ContactPropertyType.FirstName) || prop.isType(ContactPropertyType.LastName);
|
||||
|
@ -225,7 +226,7 @@ class ContactsPopupView extends AbstractViewPopup {
|
|||
this.sLastComposeFocusedField = '';
|
||||
|
||||
setTimeout(() => {
|
||||
showScreenPopup(require('View/Popup/Compose'), [ComposeType.Empty, null, toEmails, ccEmails, bccEmails]);
|
||||
rl.app.showComposePopupView([ComposeType.Empty, null, toEmails, ccEmails, bccEmails]);
|
||||
}, 200);
|
||||
}
|
||||
|
||||
|
@ -567,7 +568,7 @@ class ContactsPopupView extends AbstractViewPopup {
|
|||
this.bBackToCompose = false;
|
||||
|
||||
if (rl.settings.capa(Capa.Composer)) {
|
||||
showScreenPopup(require('View/Popup/Compose'));
|
||||
rl.app.showComposePopupView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import Remote from 'Remote/User/Fetch';
|
|||
import { command } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
class FolderCreateView extends AbstractViewPopup {
|
||||
class FolderCreatePopupView extends AbstractViewPopup {
|
||||
constructor() {
|
||||
super('FolderCreate');
|
||||
|
||||
|
@ -77,4 +77,4 @@ class FolderCreateView extends AbstractViewPopup {
|
|||
}
|
||||
}
|
||||
|
||||
export { FolderCreateView, FolderCreateView as default };
|
||||
export { FolderCreatePopupView, FolderCreatePopupView as default };
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import ko from 'ko';
|
||||
|
||||
import { convertLangName } from 'Common/Utils';
|
||||
import { convertLangName } from 'Common/Translator';
|
||||
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import Remote from 'Remote/Admin/Fetch';
|
|||
|
||||
import { command, isPopupVisible, showScreenPopup } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
import { AskPopupView } from 'View/Popup/Ask';
|
||||
|
||||
class PluginPopupView extends AbstractViewPopup {
|
||||
constructor() {
|
||||
|
@ -88,9 +89,8 @@ class PluginPopupView extends AbstractViewPopup {
|
|||
}
|
||||
|
||||
tryToClosePopup() {
|
||||
const PopupsAskViewModel = require('View/Popup/Ask');
|
||||
if (!isPopupVisible(PopupsAskViewModel)) {
|
||||
showScreenPopup(PopupsAskViewModel, [
|
||||
if (!isPopupVisible(AskPopupView)) {
|
||||
showScreenPopup(AskPopupView, [
|
||||
i18n('POPUPS_ASK/DESC_WANT_CLOSE_THIS_WINDOW'),
|
||||
() => this.modalVisibility() && this.cancelCommand && this.cancelCommand()
|
||||
]);
|
||||
|
|
|
@ -12,6 +12,8 @@ import SieveStore from 'Stores/User/Sieve';
|
|||
import { showScreenPopup/*, command*/ } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
import { FilterPopupView } from 'View/Popup/Filter';
|
||||
|
||||
class SieveScriptPopupView extends AbstractViewPopup {
|
||||
constructor() {
|
||||
super('SieveScript');
|
||||
|
@ -83,7 +85,7 @@ class SieveScriptPopupView extends AbstractViewPopup {
|
|||
/* this = SieveScriptModel */
|
||||
const filter = new FilterModel();
|
||||
filter.generateID();
|
||||
showScreenPopup(require('View/Popup/Filter'), [
|
||||
showScreenPopup(FilterPopupView, [
|
||||
filter,
|
||||
() => {
|
||||
this.filters.push(filter);
|
||||
|
@ -94,7 +96,7 @@ class SieveScriptPopupView extends AbstractViewPopup {
|
|||
|
||||
editFilter(filter) {
|
||||
const clonedFilter = filter.cloneSelf();
|
||||
showScreenPopup(require('View/Popup/Filter'), [
|
||||
showScreenPopup(FilterPopupView, [
|
||||
clonedFilter,
|
||||
() => {
|
||||
const script = this.script(),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { StorageResultType, Notification } from 'Common/Enums';
|
||||
import { getNotification } from 'Common/Translator';
|
||||
import { HtmlEditor } from 'Common/HtmlEditor';
|
||||
import { HtmlEditor } from 'Common/Html';
|
||||
|
||||
import Remote from 'Remote/User/Fetch';
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@ import Remote from 'Remote/User/Fetch';
|
|||
import { showScreenPopup } from 'Knoin/Knoin';
|
||||
import { AbstractViewPopup } from 'Knoin/AbstractViews';
|
||||
|
||||
import { TwoFactorTestPopupView } from 'View/Popup/TwoFactorTest';
|
||||
|
||||
class TwoFactorConfigurationPopupView extends AbstractViewPopup {
|
||||
constructor() {
|
||||
super('TwoFactorConfiguration');
|
||||
|
@ -104,7 +106,7 @@ class TwoFactorConfigurationPopupView extends AbstractViewPopup {
|
|||
}
|
||||
|
||||
testTwoFactor() {
|
||||
showScreenPopup(require('View/Popup/TwoFactorTest'), [this.twoFactorTested]);
|
||||
showScreenPopup(TwoFactorTestPopupView, [this.twoFactorTested]);
|
||||
}
|
||||
|
||||
clearTwoFactor() {
|
||||
|
|
|
@ -8,6 +8,9 @@ import { settings } from 'Common/Links';
|
|||
import { showScreenPopup } from 'Knoin/Knoin';
|
||||
import { AbstractViewRight } from 'Knoin/AbstractViews';
|
||||
|
||||
import { KeyboardShortcutsHelpPopupView } from 'View/Popup/KeyboardShortcutsHelp';
|
||||
import { AccountPopupView } from 'View/Popup/Account';
|
||||
|
||||
const Settings = rl.settings;
|
||||
|
||||
export class AbstractSystemDropDownUserView extends AbstractViewRight {
|
||||
|
@ -63,13 +66,13 @@ export class AbstractSystemDropDownUserView extends AbstractViewRight {
|
|||
|
||||
settingsHelp() {
|
||||
if (Settings.capa(Capa.Help)) {
|
||||
showScreenPopup(require('View/Popup/KeyboardShortcutsHelp'));
|
||||
showScreenPopup(KeyboardShortcutsHelpPopupView);
|
||||
}
|
||||
}
|
||||
|
||||
addAccountClick() {
|
||||
if (this.capaAdditionalAccounts()) {
|
||||
showScreenPopup(require('View/Popup/Account'));
|
||||
showScreenPopup(AccountPopupView);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,7 +92,7 @@ export class AbstractSystemDropDownUserView extends AbstractViewRight {
|
|||
// shortcuts help
|
||||
shortcuts.add('?,f1,help', '', [KeyState.MessageList, KeyState.MessageView, KeyState.Settings], () => {
|
||||
if (this.viewModelVisible) {
|
||||
showScreenPopup(require('View/Popup/KeyboardShortcutsHelp'));
|
||||
showScreenPopup(KeyboardShortcutsHelpPopupView);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -7,9 +7,7 @@ import {
|
|||
|
||||
import { ClientSideKeyName } from 'Common/EnumsUser';
|
||||
|
||||
import { convertLangName } from 'Common/Utils';
|
||||
|
||||
import { getNotification, getNotificationFromResponse, reload as translatorReload } from 'Common/Translator';
|
||||
import { getNotification, getNotificationFromResponse, reload as translatorReload, convertLangName } from 'Common/Translator';
|
||||
|
||||
import AppStore from 'Stores/User/App';
|
||||
import LanguageStore from 'Stores/Language';
|
||||
|
@ -23,6 +21,8 @@ import { AbstractViewCenter } from 'Knoin/AbstractViews';
|
|||
|
||||
import { rootAdmin } from 'Common/Links';
|
||||
|
||||
import { LanguagesPopupView } from 'View/Popup/Languages';
|
||||
|
||||
const Settings = rl.settings,
|
||||
|
||||
LoginSignMeType = {
|
||||
|
@ -269,7 +269,7 @@ class LoginUserView extends AbstractViewCenter {
|
|||
}
|
||||
|
||||
selectLanguage() {
|
||||
showScreenPopup(require('View/Popup/Languages'), [this.language, this.languages(), LanguageStore.userLanguage()]);
|
||||
showScreenPopup(LanguagesPopupView, [this.language, this.languages(), LanguageStore.userLanguage()]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,10 @@ import MessageStore from 'Stores/User/Message';
|
|||
import { showScreenPopup } from 'Knoin/Knoin';
|
||||
import { AbstractViewLeft } from 'Knoin/AbstractViews';
|
||||
|
||||
import { ComposePopupView } from 'View/Popup/Compose';
|
||||
import { FolderCreatePopupView } from 'View/Popup/FolderCreate';
|
||||
import { ContactsPopupView } from 'View/Popup/Contacts';
|
||||
|
||||
const Settings = rl.settings;
|
||||
|
||||
class FolderListMailBoxUserView extends AbstractViewLeft {
|
||||
|
@ -200,12 +204,12 @@ class FolderListMailBoxUserView extends AbstractViewLeft {
|
|||
|
||||
composeClick() {
|
||||
if (Settings.capa(Capa.Composer)) {
|
||||
showScreenPopup(require('View/Popup/Compose'));
|
||||
showScreenPopup(ComposePopupView);
|
||||
}
|
||||
}
|
||||
|
||||
createFolder() {
|
||||
showScreenPopup(require('View/Popup/FolderCreate'));
|
||||
showScreenPopup(FolderCreatePopupView);
|
||||
}
|
||||
|
||||
configureFolders() {
|
||||
|
@ -214,7 +218,7 @@ class FolderListMailBoxUserView extends AbstractViewLeft {
|
|||
|
||||
contactsClick() {
|
||||
if (this.allowContacts) {
|
||||
showScreenPopup(require('View/Popup/Contacts'));
|
||||
showScreenPopup(ContactsPopupView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,10 @@ import Remote from 'Remote/User/Fetch';
|
|||
import { command, showScreenPopup, popupVisibility } from 'Knoin/Knoin';
|
||||
import { AbstractViewRight } from 'Knoin/AbstractViews';
|
||||
|
||||
import { FolderClearPopupView } from 'View/Popup/FolderClear';
|
||||
import { ComposePopupView } from 'View/Popup/Compose';
|
||||
import { AdvancedSearchPopupView } from 'View/Popup/AdvancedSearch';
|
||||
|
||||
const
|
||||
Settings = rl.settings,
|
||||
canBeMovedHelper = (self) => self.canBeMoved(),
|
||||
|
@ -244,7 +248,7 @@ class MessageListMailBoxUserView extends AbstractViewRight {
|
|||
@command()
|
||||
clearCommand() {
|
||||
if (Settings.capa(Capa.DangerousActions)) {
|
||||
showScreenPopup(require('View/Popup/FolderClear'), [FolderStore.currentFolder()]);
|
||||
showScreenPopup(FolderClearPopupView, [FolderStore.currentFolder()]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,7 +262,7 @@ class MessageListMailBoxUserView extends AbstractViewRight {
|
|||
@command(canBeMovedHelper)
|
||||
multyForwardCommand() {
|
||||
if (Settings.capa(Capa.Composer)) {
|
||||
showScreenPopup(require('View/Popup/Compose'), [
|
||||
showScreenPopup(ComposePopupView, [
|
||||
ComposeType.ForwardAsAttachment,
|
||||
MessageStore.messageListCheckedOrSelected()
|
||||
]);
|
||||
|
@ -350,7 +354,7 @@ class MessageListMailBoxUserView extends AbstractViewRight {
|
|||
|
||||
composeClick() {
|
||||
if (Settings.capa(Capa.Composer)) {
|
||||
showScreenPopup(require('View/Popup/Compose'));
|
||||
showScreenPopup(ComposePopupView);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -761,7 +765,7 @@ class MessageListMailBoxUserView extends AbstractViewRight {
|
|||
if (Settings.capa(Capa.Composer)) {
|
||||
// write/compose (open compose popup)
|
||||
shortcuts.add('w,c,new', '', [KeyState.MessageList, KeyState.MessageView], () => {
|
||||
showScreenPopup(require('View/Popup/Compose'));
|
||||
showScreenPopup(ComposePopupView);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
@ -887,7 +891,7 @@ class MessageListMailBoxUserView extends AbstractViewRight {
|
|||
|
||||
advancedSearchClick() {
|
||||
Settings.capa(Capa.SearchAdv)
|
||||
&& showScreenPopup(require('View/Popup/AdvancedSearch'), [this.mainMessageListSearch()]);
|
||||
&& showScreenPopup(AdvancedSearchPopupView, [this.mainMessageListSearch()]);
|
||||
}
|
||||
|
||||
quotaTooltip() {
|
||||
|
|
|
@ -41,6 +41,8 @@ import Remote from 'Remote/User/Fetch';
|
|||
import { command, showScreenPopup, createCommand } from 'Knoin/Knoin';
|
||||
import { AbstractViewRight } from 'Knoin/AbstractViews';
|
||||
|
||||
import { ComposePopupView } from 'View/Popup/Compose';
|
||||
|
||||
const Settings = rl.settings;
|
||||
|
||||
function isTransparent(color) {
|
||||
|
@ -342,7 +344,7 @@ class MessageViewMailBoxUserView extends AbstractViewRight {
|
|||
* @returns {void}
|
||||
*/
|
||||
replyOrforward(sType) {
|
||||
Settings.capa(Capa.Composer) && showScreenPopup(require('View/Popup/Compose'), [sType, MessageStore.message()]);
|
||||
Settings.capa(Capa.Composer) && showScreenPopup(ComposePopupView, [sType, MessageStore.message()]);
|
||||
}
|
||||
|
||||
checkHeaderHeight() {
|
||||
|
@ -426,7 +428,7 @@ class MessageViewMailBoxUserView extends AbstractViewRight {
|
|||
3 !== event.which &&
|
||||
mailToHelper(
|
||||
el.href,
|
||||
Settings.capa(Capa.Composer) ? require('View/Popup/Compose') : null
|
||||
Settings.capa(Capa.Composer) ? ComposePopupView : null
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -684,13 +686,13 @@ class MessageViewMailBoxUserView extends AbstractViewRight {
|
|||
|
||||
composeClick() {
|
||||
if (Settings.capa(Capa.Composer)) {
|
||||
showScreenPopup(require('View/Popup/Compose'));
|
||||
showScreenPopup(ComposePopupView);
|
||||
}
|
||||
}
|
||||
|
||||
editMessage() {
|
||||
if (Settings.capa(Capa.Composer) && MessageStore.message()) {
|
||||
showScreenPopup(require('View/Popup/Compose'), [ComposeType.Draft, MessageStore.message()]);
|
||||
showScreenPopup(ComposePopupView, [ComposeType.Draft, MessageStore.message()]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
15
package.json
15
package.json
|
@ -50,7 +50,6 @@
|
|||
"@babel/runtime-corejs3": "7.8.7",
|
||||
"babel-eslint": "10.1.0",
|
||||
"babel-loader": "8.0.6",
|
||||
"copy-webpack-plugin": "5.1.1",
|
||||
"css-loader": "3.4.2",
|
||||
"eslint": "6.8.0",
|
||||
"eslint-config-prettier": "6.10.0",
|
||||
|
@ -74,18 +73,18 @@
|
|||
"gulp-size": "3.0.0",
|
||||
"gulp-stripbom": "1.0.5",
|
||||
"gulp-terser": "^1.4.0",
|
||||
"gulp-through": "0.4.0",
|
||||
"gulp-util": "3.0.8",
|
||||
"gulp-zip": "5.0.1",
|
||||
"node-fs": "0.1.7",
|
||||
"openpgp": "2.6.2",
|
||||
"prettier": "1.19.1",
|
||||
"raw-loader": "4.0.0",
|
||||
"rimraf": "3.0.2",
|
||||
"style-loader": "1.1.3"
|
||||
"rimraf": "3.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"webpack": "4.42.0",
|
||||
"webpack-cli": "3.3.11"
|
||||
"rollup": "^2.38.0",
|
||||
"rollup-plugin-babel": "^4.4.0",
|
||||
"rollup-plugin-external-globals": "^0.6.1",
|
||||
"rollup-plugin-html": "^0.2.1",
|
||||
"rollup-plugin-includepaths": "^0.2.4",
|
||||
"rollup-plugin-terser": "^7.0.2"
|
||||
}
|
||||
}
|
||||
|
|
10
release.php
10
release.php
|
@ -7,6 +7,11 @@ if (!$gulp) {
|
|||
exit('gulp not installed, run as root: npm install --global gulp-cli');
|
||||
}
|
||||
|
||||
$rollup = trim(`which rollup`);
|
||||
if (!$rollup) {
|
||||
exit('rollup not installed, run as root: npm install --global rollup');
|
||||
}
|
||||
|
||||
$options = getopt('', ['docker']);
|
||||
$options['docker'] = isset($options['docker']);
|
||||
|
||||
|
@ -25,6 +30,11 @@ if ($return_var) {
|
|||
exit("gulp failed with error code {$return_var}\n");
|
||||
}
|
||||
|
||||
passthru("{$rollup} -c", $return_var);
|
||||
if ($return_var) {
|
||||
exit("rollup failed with error code {$return_var}\n");
|
||||
}
|
||||
|
||||
$cmddir = escapeshellcmd(__DIR__) . '/snappymail/v/0.0.0/static';
|
||||
|
||||
if ($gzip = trim(`which gzip`)) {
|
||||
|
|
95
rollup.config.js
Normal file
95
rollup.config.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
npm install rollup rollup-plugin-includepaths rollup-plugin-babel rollup-plugin-external-globals rollup-plugin-html rollup-plugin-terser
|
||||
rollup -c
|
||||
*/
|
||||
|
||||
import babel from 'rollup-plugin-babel';
|
||||
import includePaths from 'rollup-plugin-includepaths';
|
||||
import externalGlobals from "rollup-plugin-external-globals";
|
||||
import html from 'rollup-plugin-html';
|
||||
import { terser } from "rollup-plugin-terser";
|
||||
|
||||
let includePathOptions = {
|
||||
include: {},
|
||||
paths: ['dev'],
|
||||
external: [],
|
||||
extensions: ['.js', '.html']
|
||||
};
|
||||
|
||||
let babelConfig = {
|
||||
exclude: 'node_modules/**',
|
||||
babelrc: false,
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets: {"chrome": "60"},
|
||||
loose: true,
|
||||
modules: false
|
||||
}
|
||||
]
|
||||
],
|
||||
plugins: [
|
||||
[
|
||||
'@babel/plugin-proposal-decorators',
|
||||
{
|
||||
legacy: true
|
||||
}
|
||||
],
|
||||
'@babel/plugin-proposal-class-properties'
|
||||
]
|
||||
};
|
||||
|
||||
let terserConfig = {
|
||||
output: {
|
||||
comments: false
|
||||
},
|
||||
keep_classnames: true, // Required for AbstractModel and AbstractCollectionModel
|
||||
compress:{
|
||||
ecma: 6,
|
||||
drop_console: true
|
||||
/*
|
||||
,hoist_props: false
|
||||
,keep_fargs: false
|
||||
,toplevel: true
|
||||
,unsafe_arrows: true // Issue with knockoutjs
|
||||
,unsafe_methods: true
|
||||
,unsafe_proto: true
|
||||
*/
|
||||
}
|
||||
// ,mangle: {reserved:['SendMessage']}
|
||||
};
|
||||
|
||||
export default [{
|
||||
external: ['ko'],
|
||||
input: 'dev/admin.js',
|
||||
// dest: 'snappymail/v/0.0.0/static/js/admin.rollup.js',
|
||||
output: [
|
||||
{file: 'snappymail/v/0.0.0/static/js/admin.js', format: 'iife'}, // format: 'es'
|
||||
{file: 'snappymail/v/0.0.0/static/js/min/admin.min.js', format: 'iife', plugins: [terser(terserConfig)], }
|
||||
],
|
||||
plugins: [
|
||||
babel(babelConfig),
|
||||
includePaths(includePathOptions),
|
||||
externalGlobals({
|
||||
ko: 'ko'
|
||||
})
|
||||
],
|
||||
}, {
|
||||
external: ['ko'],
|
||||
input: 'dev/app.js',
|
||||
output: [
|
||||
{file: 'snappymail/v/0.0.0/static/js/app.js', format: 'iife'},
|
||||
{file: 'snappymail/v/0.0.0/static/js/min/app.min.js', format: 'iife', plugins: [terser(terserConfig)], }
|
||||
],
|
||||
plugins: [
|
||||
babel(babelConfig),
|
||||
includePaths(includePathOptions),
|
||||
externalGlobals({
|
||||
ko: 'ko'
|
||||
}),
|
||||
html({
|
||||
include: '**/*.html'
|
||||
})
|
||||
],
|
||||
}];
|
24
tasks/js.js
24
tasks/js.js
|
@ -16,7 +16,7 @@ const concat = require('gulp-concat-util'),
|
|||
const { config } = require('./config');
|
||||
const { del, getHead } = require('./common');
|
||||
|
||||
const { webpack } = require('./webpack');
|
||||
//const { rollupJS } = require('./rollup');
|
||||
|
||||
const jsClean = () => del(config.paths.staticJS + '/**/*.{js,map}');
|
||||
|
||||
|
@ -24,14 +24,28 @@ const jsClean = () => del(config.paths.staticJS + '/**/*.{js,map}');
|
|||
const jsBoot = () => {
|
||||
return gulp
|
||||
.src('dev/boot.js')
|
||||
.pipe(gulp.dest('snappymail/v/' + config.devVersion + '/static/js'));
|
||||
.pipe(gulp.dest(config.paths.staticJS));
|
||||
};
|
||||
|
||||
// ServiceWorker
|
||||
const jsServiceWorker = () => {
|
||||
return gulp
|
||||
.src('dev/serviceworker.js')
|
||||
.pipe(gulp.dest('snappymail/v/' + config.devVersion + '/static/js'));
|
||||
.pipe(gulp.dest(config.paths.staticJS));
|
||||
};
|
||||
|
||||
// OpenPGP
|
||||
const jsOpenPGP = () => {
|
||||
return gulp
|
||||
.src('node_modules/openpgp/dist/openpgp.min.js')
|
||||
.pipe(gulp.dest(config.paths.staticMinJS));
|
||||
};
|
||||
|
||||
// OpenPGP Worker
|
||||
const jsOpenPGPWorker = () => {
|
||||
return gulp
|
||||
.src('node_modules/openpgp/dist/openpgp.worker.min.js')
|
||||
.pipe(gulp.dest(config.paths.staticMinJS));
|
||||
};
|
||||
|
||||
// libs
|
||||
|
@ -114,8 +128,8 @@ const jsLint = () =>
|
|||
.pipe(eslint.failAfterError());
|
||||
|
||||
const jsState1 = gulp.series(jsLint);
|
||||
const jsState3 = gulp.parallel(jsBoot, jsServiceWorker, jsLibs, jsApp, jsAdmin);
|
||||
const jsState2 = gulp.series(jsClean, webpack, jsState3, jsMin);
|
||||
const jsState3 = gulp.parallel(jsBoot, jsServiceWorker, jsOpenPGP, jsOpenPGPWorker, jsLibs/*, jsApp, jsAdmin*/);
|
||||
const jsState2 = gulp.series(jsClean/*, rollupJS('app.js'), rollupJS('admin.js')*/, jsState3, jsMin);
|
||||
|
||||
exports.jsLint = jsLint;
|
||||
exports.js = gulp.parallel(jsState1, jsState2);
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/* RainLoop Webmail (c) RainLoop Team | Licensed under AGPL 3 */
|
||||
const webpack = require('webpack');
|
||||
const gutil = require('gulp-util');
|
||||
|
||||
const { config } = require('./config');
|
||||
|
||||
const webpackCfgBuilder = require('../webpack.config.builder.js');
|
||||
|
||||
const webpackError = (err) => {
|
||||
if (err) {
|
||||
gutil.log('[webpack]', '---');
|
||||
gutil.log('[webpack]', err.error ? err.error.toString() : '');
|
||||
gutil.log('[webpack]', err.message || '');
|
||||
gutil.log('[webpack]', '---');
|
||||
}
|
||||
};
|
||||
|
||||
const webpackCallback = (done) => (err, stats) => {
|
||||
if (err) {
|
||||
throw new gutil.PluginError('webpack', err);
|
||||
} else if (stats && stats.compilation && stats.compilation.errors && stats.compilation.errors[0]) {
|
||||
throw new gutil.PluginError('webpack', stats.compilation.errors[0]);
|
||||
}
|
||||
|
||||
done();
|
||||
};
|
||||
|
||||
exports.webpack = (done) => {
|
||||
webpack(webpackCfgBuilder(config.paths.staticJS, 'production'), webpackCallback(done));
|
||||
};
|
|
@ -1,134 +0,0 @@
|
|||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
|
||||
const devPath = path.resolve(__dirname, 'dev');
|
||||
const devPathJoin = path.join(__dirname, 'dev');
|
||||
const externalPathJoin = path.join(__dirname, 'dev', 'External');
|
||||
const loose = true;
|
||||
|
||||
//npm install closure-webpack-plugin google-closure-compiler
|
||||
//const ClosurePlugin = require('closure-webpack-plugin');
|
||||
|
||||
const babelLoaderOptions = function() {
|
||||
return {
|
||||
ignore: [/\/core-js/],
|
||||
cacheDirectory: true,
|
||||
overrides: [
|
||||
{
|
||||
test: './node_modules/',
|
||||
sourceType: 'unambiguous'
|
||||
}
|
||||
],
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets: {"chrome": "60"},
|
||||
// useBuiltIns: 'usage',
|
||||
// corejs: { version: 3, proposals: true },
|
||||
loose: loose,
|
||||
modules: false
|
||||
}
|
||||
]
|
||||
],
|
||||
plugins: [
|
||||
[
|
||||
'@babel/plugin-proposal-decorators',
|
||||
{
|
||||
legacy: true
|
||||
}
|
||||
],
|
||||
'@babel/plugin-proposal-class-properties'
|
||||
]
|
||||
};
|
||||
};
|
||||
|
||||
process.noDeprecation = true;
|
||||
module.exports = function(publicPath, mode) {
|
||||
return {
|
||||
// mode: 'production',
|
||||
mode: mode || 'development',
|
||||
devtool: 'inline-source-map',
|
||||
entry: {
|
||||
'js/app': path.join(devPathJoin, 'app.js'),
|
||||
'js/admin': path.join(devPathJoin, 'admin.js')
|
||||
},
|
||||
output: {
|
||||
pathinfo: true,
|
||||
path: path.join(__dirname, 'snappymail', 'v', '0.0.0', 'static'),
|
||||
filename: '[name].js',
|
||||
publicPath: publicPath || 'snappymail/v/0.0.0/static/'
|
||||
},
|
||||
performance: {
|
||||
hints: false
|
||||
},
|
||||
optimization: {
|
||||
concatenateModules: false,
|
||||
minimize: false
|
||||
/*
|
||||
,minimizer: [
|
||||
new ClosurePlugin({mode: 'STANDARD'}, {
|
||||
language_in:'ECMASCRIPT6',
|
||||
language_out:'ECMASCRIPT6',
|
||||
compilation_level: 'ADVANCED_OPTIMIZATIONS'
|
||||
// compiler flags here
|
||||
//
|
||||
// for debugging help, try these:
|
||||
//
|
||||
// formatting: 'PRETTY_PRINT'
|
||||
// debug: true,
|
||||
// renaming: false
|
||||
})
|
||||
]
|
||||
*/
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify('production'),
|
||||
'process.env': {
|
||||
NODE_ENV: JSON.stringify('production')
|
||||
}
|
||||
}),
|
||||
new webpack.DefinePlugin({}),
|
||||
new CopyWebpackPlugin([
|
||||
{ from: 'node_modules/openpgp/dist/openpgp.min.js', to: 'js/min/openpgp.min.js' },
|
||||
{ from: 'node_modules/openpgp/dist/openpgp.worker.min.js', to: 'js/min/openpgp.worker.min.js' }
|
||||
])
|
||||
],
|
||||
resolve: {
|
||||
modules: [devPath, 'node_modules'],
|
||||
extensions: ['.js'],
|
||||
alias: {
|
||||
'ko$': path.join(externalPathJoin, 'ko.js')
|
||||
}
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
include: [devPath],
|
||||
options: babelLoaderOptions()
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
loader: 'raw-loader',
|
||||
include: [devPath]
|
||||
},
|
||||
{
|
||||
test: /\.css/,
|
||||
loaders: ['style-loader', 'css-loader'],
|
||||
include: [devPath]
|
||||
},
|
||||
{
|
||||
test: /\.json$/,
|
||||
loader: 'json-loader',
|
||||
include: [devPath]
|
||||
}
|
||||
]
|
||||
},
|
||||
externals: {
|
||||
}
|
||||
};
|
||||
};
|
|
@ -1 +0,0 @@
|
|||
module.exports = require('./webpack.config.builder')();
|
Loading…
Reference in a new issue