Bugfix: conflicting File object with native JS

Cleanup: Stores and tooltips
This commit is contained in:
djmaze 2021-02-17 14:40:21 +01:00
parent 1df2e00862
commit db0d03db83
43 changed files with 204 additions and 295 deletions

View file

@ -2,13 +2,11 @@ import ko from 'ko';
import {
doc,
$htmlCL,
elementById,
leftPanelDisabled,
Settings
} from 'Common/Globals';
import { KeyState } from 'Common/Enums';
import { logoutLink } from 'Common/Links';
import { i18nToNodes, initOnStartOrLangChange } from 'Common/Translator';
@ -27,17 +25,6 @@ export class AbstractApp {
*/
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);
refresh();
}).debounce(500);
// doc.addEventListener('touchstart', fn, {passive:true});
['mousedown','keydown','keyup'/*,'mousemove'*/].forEach(t => doc.addEventListener(t, fn));
shortcuts.add('escape,enter', '', KeyState.All, () => rl.Dropdowns.detectVisibility());
}
remote() {
@ -110,7 +97,7 @@ export class AbstractApp {
register('Select', SelectComponent);
register('TextArea', TextAreaComponent);
register('CheckboxSimple', CheckboxComponent, 'CheckboxComponent');
if (/*ThemeStore.isMobile() || */!Settings.app('materialDesign')) {
if (!Settings.app('materialDesign')) {
register('Checkbox', CheckboxComponent);
} else {
register('Checkbox', CheckboxMaterialDesignComponent, 'CheckboxMaterialDesignComponent');

View file

@ -3,11 +3,11 @@ import ko from 'ko';
import { StorageResultType } from 'Common/Enums';
import AppStore from 'Stores/Admin/App';
import CapaStore from 'Stores/Admin/Capa';
import DomainStore from 'Stores/Admin/Domain';
import PluginStore from 'Stores/Admin/Plugin';
import PackageStore from 'Stores/Admin/Package';
import { AppAdminStore } from 'Stores/Admin/App';
import { CapaAdminStore } from 'Stores/Admin/Capa';
import { DomainAdminStore } from 'Stores/Admin/Domain';
import { PluginAdminStore } from 'Stores/Admin/Plugin';
import { PackageAdminStore } from 'Stores/Admin/Package';
import Remote from 'Remote/Admin/Fetch';
import { SettingsAdminScreen } from 'Screen/Admin/Settings';
@ -26,11 +26,11 @@ class AdminApp extends AbstractApp {
}
reloadDomainList() {
DomainStore.domains.loading(true);
DomainAdminStore.loading(true);
Remote.domainList((result, data) => {
DomainStore.domains.loading(false);
DomainAdminStore.loading(false);
if (StorageResultType.Success === result && data && data.Result) {
DomainStore.domains(
DomainAdminStore(
Object.entries(data.Result).map(([name, [enabled, alias]]) => ({
name: name,
disabled: ko.observable(!enabled),
@ -43,11 +43,11 @@ class AdminApp extends AbstractApp {
}
reloadPluginList() {
PluginStore.plugins.loading(true);
PluginAdminStore.loading(true);
Remote.pluginList((result, data) => {
PluginStore.plugins.loading(false);
PluginAdminStore.loading(false);
if (StorageResultType.Success === result && data && data.Result) {
PluginStore.plugins(
PluginAdminStore(
data.Result.map(item => ({
name: item.Name,
disabled: ko.observable(!item.Enabled),
@ -59,18 +59,16 @@ class AdminApp extends AbstractApp {
}
reloadPackagesList() {
PackageStore.packages.loading(true);
PackageStore.packagesReal(true);
PackageAdminStore.loading(true);
Remote.packagesList((result, data) => {
PackageStore.packages.loading(false);
PackageAdminStore.loading(false);
if (StorageResultType.Success === result && data && data.Result) {
PackageStore.packagesReal(!!data.Result.Real);
PackageStore.packagesMainUpdatable(!!data.Result.MainUpdatable);
PackageAdminStore.real(!!data.Result.Real);
let list = [];
const loading = {};
PackageStore.packages.forEach(item => {
PackageAdminStore.forEach(item => {
if (item && item.loading()) {
loading[item.file] = item;
}
@ -86,9 +84,9 @@ class AdminApp extends AbstractApp {
}).filter(v => v);
}
PackageStore.packages(list);
PackageAdminStore(list);
} else {
PackageStore.packagesReal(false);
PackageAdminStore.real(false);
}
});
}
@ -100,8 +98,8 @@ class AdminApp extends AbstractApp {
bootstart() {
super.bootstart();
AppStore.populate();
CapaStore.populate();
AppAdminStore.populate();
CapaAdminStore.populate();
this.hideLoading();

View file

@ -6,7 +6,8 @@ import { isPosNumeric, delegateRunOnDestroy, mailToHelper } from 'Common/UtilsUs
import {
Capa,
StorageResultType,
Notification
Notification,
KeyState
} from 'Common/Enums';
import {
@ -51,7 +52,7 @@ import SettingsStore from 'Stores/User/Settings';
import NotificationStore from 'Stores/User/Notification';
import AccountStore from 'Stores/User/Account';
import ContactStore from 'Stores/User/Contact';
import IdentityStore from 'Stores/User/Identity';
import { IdentityUserStore } from 'Stores/User/Identity';
import TemplateStore from 'Stores/User/Template';
import FolderStore from 'Stores/User/Folder';
import PgpStore from 'Stores/User/Pgp';
@ -124,6 +125,17 @@ class AppUser extends AbstractApp {
}
}, 1000);
}
const refresh = (()=>dispatchEvent(new CustomEvent('rl.auto-logout-refresh'))).debounce(5000),
fn = (ev=>{
$htmlCL.toggle('rl-ctrl-key-pressed', ev.ctrlKey);
refresh();
}).debounce(500);
// doc.addEventListener('touchstart', fn, {passive:true});
['mousedown','keydown','keyup'/*,'mousemove'*/].forEach(t => doc.addEventListener(t, fn));
shortcuts.add('escape,enter', '', KeyState.All, () => rl.Dropdowns.detectVisibility());
}
remote() {
@ -480,11 +492,11 @@ class AppUser extends AbstractApp {
accountsAndIdentities() {
AccountStore.accounts.loading(true);
IdentityStore.identities.loading(true);
IdentityUserStore.loading(true);
Remote.accountsAndIdentities((sResult, oData) => {
AccountStore.accounts.loading(false);
IdentityStore.identities.loading(false);
IdentityUserStore.loading(false);
if (StorageResultType.Success === sResult && oData.Result) {
const counts = {},
@ -506,9 +518,9 @@ class AppUser extends AbstractApp {
}
if (Array.isArray(oData.Result.Identities)) {
delegateRunOnDestroy(IdentityStore.identities());
delegateRunOnDestroy(IdentityUserStore());
IdentityStore.identities(
IdentityUserStore(
oData.Result.Identities.map(identityData => {
const id = pString(identityData.Id),
email = pString(identityData.Email),

View file

@ -6,7 +6,6 @@ const
app = 'application/',
msOffice = app+'vnd.openxmlformats-officedocument.',
openDoc = app+'vnd.oasis.opendocument.',
font = app+'x-font-',
sizes = ['B', 'KiB', 'MiB', 'GiB', 'TiB'],
exts = {
@ -54,10 +53,6 @@ const
'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',
@ -124,7 +119,7 @@ export const FileType = {
Archive: 'archive'
};
export const File = {
export const FileInfo = {
/**
* @param {string} fileName
* @returns {string}
@ -151,8 +146,8 @@ export const File = {
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 (/^(otf|sfnt|ttf|woff2?)$/.test(ext))
return 'font/'+ext;
if (/^(png|jpeg|gif|tiff|webp)$/.test(ext))
return 'image/'+ext;
@ -282,7 +277,7 @@ export const File = {
return result;
},
getIconClass: (ext, mime) => File.getTypeIconClass(File.getType(ext, mime)),
getIconClass: (ext, mime) => FileInfo.getTypeIconClass(FileInfo.getType(ext, mime)),
/**
* @param {string} sFileType
@ -291,7 +286,7 @@ export const File = {
getCombinedIconClass: data => {
if (Array.isNotEmpty(data)) {
let icons = data
.map(item => item ? File.getIconClass(File.getExtension(item[0]), item[1])[0] : '')
.map(item => item ? FileInfo.getIconClass(FileInfo.getExtension(item[0]), item[1])[0] : '')
.validUnique();
return (icons && 1 === icons.length && 'icon-file' !== icons[0])

View file

@ -230,3 +230,29 @@ ko.bindingHandlers.onEsc = {
ko.utils.domNodeDisposal.addDisposeCallback(element, () => element.removeEventListener('keyup', fn));
}
};
ko.bindingHandlers.registerBootstrapDropdown = {
init: element => {
rl.Dropdowns.register(element);
element.ddBtn = new BSN.Dropdown(element.querySelector('[data-toggle="dropdown"]'));
}
};
ko.bindingHandlers.openDropdownTrigger = {
update: (element, fValueAccessor) => {
if (ko.unwrap(fValueAccessor())) {
const el = element.ddBtn;
el.open || el.toggle();
// el.focus();
rl.Dropdowns.detectVisibility();
fValueAccessor()(false);
}
}
};
ko.bindingHandlers.dropdownCloser = {
init: element => element.closest('.dropdown').addEventListener('click', event =>
event.target.closestWithin('.e-item', element) && element.ddBtn.toggle()
)
};

63
dev/External/ko.js vendored
View file

@ -1,5 +1,5 @@
import { i18n, i18nToNodes, trigger } from 'Common/Translator';
import { doc, createElement, dropdownVisibility } from 'Common/Globals';
import { doc, createElement } from 'Common/Globals';
import { SaveSettingsStep } from 'Common/Enums';
const
@ -9,27 +9,11 @@ const
ko.bindingHandlers.tooltip = {
init: (element, fValueAccessor) => {
const sValue = koValue(fValueAccessor());
if ('off' === element.dataset.tooltipI18n) {
element.title = sValue;
} else {
element.title = i18n(sValue);
trigger.subscribe(() =>
element.title = i18n(sValue)
);
dropdownVisibility.subscribe(() =>
element.title = i18n(sValue)
);
}
element.title = i18n(sValue);
trigger.subscribe(() => element.title = i18n(sValue));
},
update: (element, fValueAccessor) => {
const sValue = koValue(fValueAccessor());
if (sValue) {
element.title = 'off' === element.dataset.tooltipI18n ? sValue : i18n(sValue);
} else {
element.title = '';
}
}
update: (element, fValueAccessor) =>
element.title = i18n(koValue(fValueAccessor()))
};
ko.bindingHandlers.tooltipErrorTip = {
@ -46,32 +30,6 @@ ko.bindingHandlers.tooltipErrorTip = {
}
};
ko.bindingHandlers.registerBootstrapDropdown = {
init: element => {
rl.Dropdowns.register(element);
element.ddBtn = new BSN.Dropdown(element.querySelector('[data-toggle="dropdown"]'));
}
};
ko.bindingHandlers.openDropdownTrigger = {
update: (element, fValueAccessor) => {
if (ko.unwrap(fValueAccessor())) {
const el = element.ddBtn;
el.open || el.toggle();
// el.focus();
rl.Dropdowns.detectVisibility();
fValueAccessor()(false);
}
}
};
ko.bindingHandlers.dropdownCloser = {
init: element => element.closest('.dropdown').addEventListener('click', event =>
event.target.closestWithin('.e-item', element) && element.ddBtn.toggle()
)
};
ko.bindingHandlers.onEnter = {
init: (element, fValueAccessor, fAllBindingsAccessor, viewModel) => {
let fn = event => {
@ -230,17 +188,6 @@ ko.extenders.limitedList = (target, limitedList) => {
return result;
};
ko.extenders.reversible = (target) => {
let value = target();
target.commit = () => value = target();
target.reverse = () => target(value);
target.commitedValue = () => value;
return target;
};
ko.extenders.toggleSubscribeProperty = (target, options) => {
const prop = options[1];
if (prop) {

View file

@ -1,6 +1,6 @@
import ko from 'ko';
import { File, FileType } from 'Common/File';
import { FileInfo, FileType } from 'Common/File';
import {
attachmentDownload,
serverRequestRaw
@ -44,11 +44,11 @@ export class AttachmentModel extends AbstractModel {
static reviveFromJson(json) {
const attachment = super.reviveFromJson(json);
if (attachment) {
attachment.friendlySize = File.friendlySize(json.EstimatedSize);
attachment.friendlySize = FileInfo.friendlySize(json.EstimatedSize);
attachment.cidWithoutTags = attachment.cid.replace(/^<+/, '').replace(/>+$/, '');
attachment.fileNameExt = File.getExtension(attachment.fileName);
attachment.fileType = File.getType(attachment.fileNameExt, attachment.mimeType);
attachment.fileNameExt = FileInfo.getExtension(attachment.fileName);
attachment.fileType = FileInfo.getType(attachment.fileNameExt, attachment.mimeType);
}
return attachment;
}
@ -211,13 +211,13 @@ export class AttachmentModel extends AbstractModel {
* @returns {string}
*/
iconClass() {
return File.getTypeIconClass(this.fileType)[0];
return FileInfo.getTypeIconClass(this.fileType)[0];
}
/**
* @returns {string}
*/
iconText() {
return File.getTypeIconClass(this.fileType)[1];
return FileInfo.getTypeIconClass(this.fileType)[1];
}
}

View file

@ -1,5 +1,5 @@
import { pInt } from 'Common/Utils';
import { File } from 'Common/File';
import { FileInfo } from 'Common/File';
import { AbstractModel } from 'Knoin/AbstractModel';
@ -51,11 +51,11 @@ export class ComposeAttachmentModel extends AbstractModel {
friendlySize: () => {
const localSize = this.size();
return null === localSize ? '' : File.friendlySize(localSize);
return null === localSize ? '' : FileInfo.friendlySize(localSize);
},
mimeType: () => File.getContentType(this.fileName()),
fileExt: () => File.getExtension(this.fileName())
mimeType: () => FileInfo.getContentType(this.fileName()),
fileExt: () => FileInfo.getExtension(this.fileName())
});
}
@ -96,13 +96,13 @@ export class ComposeAttachmentModel extends AbstractModel {
* @returns {string}
*/
iconClass() {
return File.getIconClass(this.fileExt(), this.mimeType())[0];
return FileInfo.getIconClass(this.fileExt(), this.mimeType())[0];
}
/**
* @returns {string}
*/
iconText() {
return File.getIconClass(this.fileExt(), this.mimeType())[1];
return FileInfo.getIconClass(this.fileExt(), this.mimeType())[1];
}
}

View file

@ -10,7 +10,7 @@ import { serverRequestRaw } from 'Common/Links';
import FolderStore from 'Stores/User/Folder';
import { File } from 'Common/File';
import { FileInfo } from 'Common/File';
import { AttachmentCollectionModel } from 'Model/AttachmentCollection';
import { EmailCollectionModel } from 'Model/EmailCollection';
import { AbstractModel } from 'Knoin/AbstractModel';
@ -85,7 +85,7 @@ export class MessageModel extends AbstractModel {
this.threads = ko.observableArray();
this.addComputables({
attachmentIconClass: () => File.getCombinedIconClass(this.hasAttachments() ? this.attachmentsSpecData() : []),
attachmentIconClass: () => FileInfo.getCombinedIconClass(this.hasAttachments() ? this.attachmentsSpecData() : []),
threadsLen: () => this.threads.length,
isImportant: () => MessagePriority.High === this.priority(),
});
@ -169,7 +169,7 @@ export class MessageModel extends AbstractModel {
* @returns {string}
*/
friendlySize() {
return File.friendlySize(this.size());
return FileInfo.friendlySize(this.size());
}
computeSenderEmail() {

View file

@ -26,9 +26,7 @@ export class AbstractSettingsScreen extends AbstractScreen {
* @param {Function=} fCallback
*/
setupSettings(fCallback = null) {
if (fCallback) {
fCallback();
}
fCallback && fCallback();
}
onRoute(subName) {

View file

@ -52,9 +52,7 @@ export class SettingsAdminScreen extends AbstractSettingsScreen {
runSettingsViewModelHooks(true);
if (fCallback) {
fCallback();
}
fCallback && fCallback();
}
onShow() {

View file

@ -38,9 +38,7 @@ export class SettingsUserScreen extends AbstractSettingsScreen {
*/
setupSettings(fCallback = null) {
if (!Settings.capa(Capa.Settings)) {
if (fCallback) {
fCallback();
}
fCallback && fCallback();
return false;
}
@ -93,9 +91,7 @@ export class SettingsUserScreen extends AbstractSettingsScreen {
runSettingsViewModelHooks(false);
if (fCallback) {
fCallback();
}
fCallback && fCallback();
return true;
}

View file

@ -3,7 +3,7 @@ import ko from 'ko';
import { StorageResultType } from 'Common/Enums';
import { showScreenPopup } from 'Knoin/Knoin';
import DomainStore from 'Stores/Admin/Domain';
import { DomainAdminStore } from 'Stores/Admin/Domain';
import Remote from 'Remote/Admin/Fetch';
import { DomainPopupView } from 'View/Popup/Domain';
@ -11,9 +11,9 @@ import { DomainAliasPopupView } from 'View/Popup/DomainAlias';
export class DomainsAdminSettings {
constructor() {
this.domains = DomainStore.domains;
this.domains = DomainAdminStore;
this.visibility = ko.computed(() => (this.domains.loading() ? 'visible' : 'hidden'));
this.visibility = ko.computed(() => (DomainAdminStore.loading() ? 'visible' : 'hidden'));
this.domainForDeletion = ko.observable(null).deleteAccessHelper();
@ -30,7 +30,7 @@ export class DomainsAdminSettings {
}
deleteDomain(domain) {
this.domains.remove(domain);
DomainAdminStore.remove(domain);
Remote.domainDelete(this.onDomainListChangeRequest, domain.name);
}

View file

@ -16,8 +16,8 @@ import Remote from 'Remote/Admin/Fetch';
import { ThemeStore } from 'Stores/Theme';
import { LanguageStore } from 'Stores/Language';
import AppAdminStore from 'Stores/Admin/App';
import CapaAdminStore from 'Stores/Admin/Capa';
import { AppAdminStore } from 'Stores/Admin/App';
import { CapaAdminStore } from 'Stores/Admin/Capa';
import LanguagesPopupView from 'View/Popup/Languages';
const settingsGet = rl.settings.get;
@ -31,7 +31,7 @@ export class GeneralAdminSettings {
this.languagesAdmin = ko.observableArray(Array.isArray(aLanguagesAdmin) ? aLanguagesAdmin : []);
this.languageAdmin = ko
.observable(settingsGet('LanguageAdmin'))
.extend({ limitedList: this.languagesAdmin, reversible: true });
.extend({ limitedList: this.languagesAdmin });
this.theme = ThemeStore.theme;
this.themes = ThemeStore.themes;

View file

@ -3,28 +3,26 @@ import ko from 'ko';
import { StorageResultType, Notification } from 'Common/Enums';
import { getNotification } from 'Common/Translator';
import PackageStore from 'Stores/Admin/Package';
import { PackageAdminStore } from 'Stores/Admin/Package';
import Remote from 'Remote/Admin/Fetch';
export class PackagesAdminSettings {
constructor() {
this.packagesError = ko.observable('');
this.packages = PackageStore.packages;
this.packagesReal = PackageStore.packagesReal;
this.packagesMainUpdatable = PackageStore.packagesMainUpdatable;
this.packages = PackageAdminStore;
this.packagesCurrent = ko.computed(() =>
this.packages.filter(item => item && item.installed && !item.compare)
PackageAdminStore.filter(item => item && item.installed && !item.compare)
);
this.packagesAvailableForUpdate = ko.computed(() =>
this.packages.filter(item => item && item.installed && !!item.compare)
PackageAdminStore.filter(item => item && item.installed && !!item.compare)
);
this.packagesAvailableForInstallation = ko.computed(() =>
this.packages.filter(item => item && !item.installed)
PackageAdminStore.filter(item => item && !item.installed)
);
this.visibility = ko.computed(() => (PackageStore.packages.loading() ? 'visible' : 'hidden'));
this.visibility = ko.computed(() => (PackageAdminStore.loading() ? 'visible' : 'hidden'));
}
onShow() {
@ -47,7 +45,7 @@ export class PackagesAdminSettings {
}
}
this.packages.forEach(item => {
PackageAdminStore.forEach(item => {
if (item && packageToRequest && item.loading && item.loading() && packageToRequest.file === item.file) {
packageToRequest.loading(false);
item.loading(false);

View file

@ -5,7 +5,7 @@ import { getNotification } from 'Common/Translator';
import { showScreenPopup } from 'Knoin/Knoin';
import PluginStore from 'Stores/Admin/Plugin';
import { PluginAdminStore } from 'Stores/Admin/Plugin';
import Remote from 'Remote/Admin/Fetch';
@ -15,10 +15,10 @@ export class PluginsAdminSettings {
constructor() {
this.enabledPlugins = ko.observable(!!rl.settings.get('EnabledPlugins'));
this.plugins = PluginStore.plugins;
this.pluginsError = PluginStore.plugins.error;
this.plugins = PluginAdminStore;
this.pluginsError = PluginAdminStore.error;
this.visibility = ko.computed(() => (PluginStore.plugins.loading() ? 'visible' : 'hidden'));
this.visibility = ko.computed(() => (PluginAdminStore.loading() ? 'visible' : 'hidden'));
this.onPluginLoadRequest = this.onPluginLoadRequest.bind(this);
this.onPluginDisableRequest = this.onPluginDisableRequest.bind(this);
@ -50,7 +50,7 @@ export class PluginsAdminSettings {
}
onShow() {
PluginStore.plugins.error('');
PluginAdminStore.error('');
rl.app.reloadPluginList();
}
@ -64,9 +64,9 @@ export class PluginsAdminSettings {
if (StorageResultType.Success === result && data) {
if (!data.Result && data.ErrorCode) {
if (Notification.UnsupportedPluginPackage === data.ErrorCode && data.ErrorMessage && data.ErrorMessage) {
PluginStore.plugins.error(data.ErrorMessage);
PluginAdminStore.error(data.ErrorMessage);
} else {
PluginStore.plugins.error(getNotification(data.ErrorCode));
PluginAdminStore.error(getNotification(data.ErrorCode));
}
}
}

View file

@ -2,8 +2,8 @@ import ko from 'ko';
import { StorageResultType } from 'Common/Enums';
import AppAdminStore from 'Stores/Admin/App';
import CapaAdminStore from 'Stores/Admin/Capa';
import { AppAdminStore } from 'Stores/Admin/App';
import { CapaAdminStore } from 'Stores/Admin/Capa';
import Remote from 'Remote/Admin/Fetch';

View file

@ -3,7 +3,7 @@ import ko from 'ko';
import { Capa, StorageResultType } from 'Common/Enums';
import AccountStore from 'Stores/User/Account';
import IdentityStore from 'Stores/User/Identity';
import { IdentityUserStore } from 'Stores/User/Identity';
import Remote from 'Remote/User/Fetch';
import { showScreenPopup } from 'Knoin/Knoin';
@ -17,7 +17,7 @@ export class AccountsUserSettings {
this.allowIdentities = rl.settings.capa(Capa.Identities);
this.accounts = AccountStore.accounts;
this.identities = IdentityStore.identities;
this.identities = IdentityUserStore;
this.accountForDeletion = ko.observable(null).deleteAccessHelper();
this.identityForDeletion = ko.observable(null).deleteAccessHelper();
@ -72,14 +72,14 @@ export class AccountsUserSettings {
this.identityForDeletion(null);
if (identityToRemove) {
IdentityStore.identities.remove(oIdentity => identityToRemove === oIdentity);
IdentityUserStore.remove(oIdentity => identityToRemove === oIdentity);
Remote.identityDelete(() => rl.app.accountsAndIdentities(), identityToRemove.id());
}
}
}
accountsAndIdentitiesAfterMove() {
Remote.accountsAndIdentitiesSortOrder(null, AccountStore.getEmailAddresses(), IdentityStore.getIDS());
Remote.accountsAndIdentitiesSortOrder(null, AccountStore.getEmailAddresses(), IdentityUserStore.getIDS());
}
onBuild(oDom) {

View file

@ -4,7 +4,7 @@ import { delegateRunOnDestroy } from 'Common/UtilsUser';
import { StorageResultType, Notification } from 'Common/Enums';
import { getNotification } from 'Common/Translator';
import SieveStore from 'Stores/User/Sieve';
import { SieveUserStore } from 'Stores/User/Sieve';
import Remote from 'Remote/User/Fetch';
import { SieveScriptModel } from 'Model/SieveScript';
@ -15,7 +15,7 @@ import { SieveScriptPopupView } from 'View/Popup/SieveScript';
export class FiltersUserSettings {
constructor() {
this.scripts = SieveStore.scripts;
this.scripts = SieveUserStore.scripts;
this.loading = ko.observable(false).extend({ debounce: 200 });
ko.addObservablesTo(this, {
@ -41,7 +41,7 @@ export class FiltersUserSettings {
this.scripts([]);
if (StorageResultType.Success === result && data && data.Result) {
SieveStore.capa(data.Result.Capa);
SieveUserStore.capa(data.Result.Capa);
/*
this.scripts(
data.Result.Scripts.map(aItem => SieveScriptModel.reviveFromJson(aItem)).filter(v => v)
@ -52,7 +52,7 @@ export class FiltersUserSettings {
value && this.scripts.push(value)
});
} else {
SieveStore.capa([]);
SieveUserStore.capa([]);
this.setError(
data && data.ErrorCode ? getNotification(data.ErrorCode) : getNotification(Notification.CantGetFilters)
);

View file

@ -14,7 +14,7 @@ import { showScreenPopup } from 'Knoin/Knoin';
import AppStore from 'Stores/User/App';
import { LanguageStore } from 'Stores/Language';
import SettingsStore from 'Stores/User/Settings';
import IdentityStore from 'Stores/User/Identity';
import { IdentityUserStore } from 'Stores/User/Identity';
import NotificationStore from 'Stores/User/Notification';
import MessageStore from 'Stores/User/Message';
@ -54,7 +54,7 @@ export class GeneralUserSettings {
layoutTrigger: SaveSettingsStep.Idle
});
this.identities = IdentityStore.identities;
this.identities = IdentityUserStore;
this.identityMain = ko.computed(() => {
const list = this.identities();

View file

@ -17,8 +17,8 @@ export class ThemesUserSettings {
this.themesObjects = ko.observableArray();
this.background = {};
this.background.name = ThemeStore.themeBackgroundName;
this.background.hash = ThemeStore.themeBackgroundHash;
this.background.name = ThemeStore.userBackgroundName;
this.background.hash = ThemeStore.userBackgroundHash;
this.background.uploaderButton = ko.observable(null);
this.background.loading = ko.observable(false);
this.background.error = ko.observable('');

View file

@ -1,20 +1,14 @@
import ko from 'ko';
class AppAdminStore {
constructor() {
this.weakPassword = ko.observable(false);
export const AppAdminStore = {
weakPassword: ko.observable(false),
dataFolderAccess: ko.observable(false),
this.dataFolderAccess = ko.observable(false);
}
populate() {
populate: function() {
this.weakPassword(!!rl.settings.get('WeakPassword'));
/*
if (settingsGet('Auth')) {
fetch('./data/VERSION?' + Math.random()).then(() => this.dataFolderAccess(true));
}
rl.settings.get('WeakPassword')
&& fetch('./data/VERSION?' + Math.random()).then(() => this.dataFolderAccess(true));
*/
}
}
export default new AppAdminStore();
};

View file

@ -1,24 +1,8 @@
import ko from 'ko';
import { Capa } from 'Common/Enums';
class CapaAdminStore {
constructor() {
ko.addObservablesTo(this, {
additionalAccounts: false,
identities: false,
attachmentThumbnails: false,
sieve: false,
filters: false,
themes: true,
userBackground: false,
openPGP: false,
twoFactorAuth: false,
twoFactorAuthForce: false,
templates: false
});
}
populate() {
export const CapaAdminStore = {
populate: function() {
let capa = rl.settings.capa;
this.additionalAccounts(capa(Capa.AdditionalAccounts));
this.identities(capa(Capa.Identities));
@ -32,6 +16,18 @@ class CapaAdminStore {
this.twoFactorAuthForce(capa(Capa.TwoFactorForce));
this.templates(capa(Capa.Templates));
}
}
};
export default new CapaAdminStore();
ko.addObservablesTo(CapaAdminStore, {
additionalAccounts: false,
identities: false,
attachmentThumbnails: false,
sieve: false,
filters: false,
themes: true,
userBackground: false,
openPGP: false,
twoFactorAuth: false,
twoFactorAuthForce: false,
templates: false
});

View file

@ -1,11 +1,5 @@
import ko from 'ko';
class DomainAdminStore {
constructor() {
this.domains = ko.observableArray();
this.domains.loading = ko.observable(false).extend({ 'throttle': 100 });
this.domainsWithoutAliases = ko.computed(() => this.domains.filter(item => item && !item.alias));
}
}
export const DomainAdminStore = ko.observableArray();
export default new DomainAdminStore();
DomainAdminStore.loading = ko.observable(false).extend({ 'throttle': 100 });

View file

@ -1,15 +1,7 @@
import ko from 'ko';
class PackageAdminStore {
constructor() {
this.packages = ko.observableArray();
this.packages.loading = ko.observable(false).extend({ debounce: 100 });
export const PackageAdminStore = ko.observableArray();
ko.addObservablesTo(this, {
packagesReal: true,
packagesMainUpdatable: true
});
}
}
PackageAdminStore.real = ko.observable(true);
export default new PackageAdminStore();
PackageAdminStore.loading = ko.observable(false).extend({ debounce: 100 });

View file

@ -1,11 +1,5 @@
import ko from 'ko';
class PluginAdminStore {
constructor() {
this.plugins = ko.observableArray();
this.plugins.loading = ko.observable(false).extend({ debounce: 100 });
this.plugins.error = ko.observable('');
}
}
export default new PluginAdminStore();
export const PluginAdminStore = ko.observableArray();
PluginAdminStore.loading = ko.observable(false).extend({ debounce: 100 });
PluginAdminStore.error = ko.observable('');

View file

@ -14,4 +14,4 @@ export const LanguageStore = {
}
LanguageStore.language = ko.observable('')
.extend({ limitedList: LanguageStore.languages, reversible: true });
.extend({ limitedList: LanguageStore.languages });

View file

@ -3,8 +3,9 @@ import { $htmlCL } from 'Common/Globals';
export const ThemeStore = {
themes: ko.observableArray(),
themeBackgroundName: ko.observable(''),
themeBackgroundHash: ko.observable(''),
userBackgroundName: ko.observable(''),
userBackgroundHash: ko.observable(''),
isMobile: ko.observable($htmlCL.contains('rl-mobile')),
populate: function(){
const Settings = rl.settings,
@ -13,13 +14,12 @@ export const ThemeStore = {
this.themes(Array.isArray(themes) ? themes : []);
this.theme(Settings.get('Theme'));
if (!this.isMobile()) {
this.themeBackgroundName(Settings.get('UserBackgroundName'));
this.themeBackgroundHash(Settings.get('UserBackgroundHash'));
this.userBackgroundName(Settings.get('UserBackgroundName'));
this.userBackgroundHash(Settings.get('UserBackgroundHash'));
}
}
};
ThemeStore.theme = ko.observable('').extend({ limitedList: ThemeStore.themes });
ThemeStore.isMobile = ko.observable($htmlCL.contains('rl-mobile'));
ThemeStore.isMobile.subscribe(value => $htmlCL.toggle('rl-mobile', value));

View file

@ -30,13 +30,6 @@ class AccountUserStore {
this.email(rl.settings.get('Email'));
this.parentEmail(rl.settings.get('ParentEmail'));
}
/**
* @returns {boolean}
*/
isRootAccount() {
return !this.parentEmail();
}
}
export default new AccountUserStore();

View file

@ -1,12 +1,7 @@
import ko from 'ko';
class IdentityUserStore {
constructor() {
this.identities = ko.observableArray();
this.identities.loading = ko.observable(false).extend({ debounce: 100 });
export const IdentityUserStore = ko.observableArray();
this.getIDS = () => this.identities.map(item => (item ? item.id() : null)).filter(value => null !== value);
}
}
export default new IdentityUserStore();
IdentityUserStore.getIDS = () => IdentityUserStore.map(item => (item ? item.id() : null))
.filter(value => null !== value);
IdentityUserStore.loading = ko.observable(false).extend({ debounce: 100 });

View file

@ -1,12 +1,8 @@
import ko from 'ko';
class SieveUserStore {
constructor() {
// capabilities
this.capa = ko.observableArray();
// Sieve scripts SieveScriptModel
this.scripts = ko.observableArray();
}
export const SieveUserStore = {
// capabilities
capa: ko.observableArray(),
// Sieve scripts SieveScriptModel
scripts: ko.observableArray()
}
export default new SieveUserStore();

View file

@ -2,9 +2,9 @@ import ko from 'ko';
import Remote from 'Remote/Admin/Fetch';
import DomainStore from 'Stores/Admin/Domain';
import PluginStore from 'Stores/Admin/Plugin';
import PackageStore from 'Stores/Admin/Package';
import { DomainAdminStore } from 'Stores/Admin/Domain';
import { PluginAdminStore } from 'Stores/Admin/Plugin';
import { PackageAdminStore } from 'Stores/Admin/Package';
import { AbstractViewRight } from 'Knoin/AbstractViews';
@ -19,9 +19,9 @@ class PaneSettingsAdminView extends AbstractViewRight {
this.leftPanelDisabled = leftPanelDisabled;
this.adminManLoadingVisibility = ko
.computed(() => (DomainStore.domains.loading()
|| PluginStore.plugins.loading()
|| PackageStore.packages.loading()) ? 'visible' : 'hidden')
.computed(() => (DomainAdminStore.loading()
|| PluginAdminStore.loading()
|| PackageAdminStore.loading()) ? 'visible' : 'hidden')
.extend({ rateLimit: 300 });
}

View file

@ -27,7 +27,7 @@ import { Settings } from 'Common/Globals';
import AppStore from 'Stores/User/App';
import SettingsStore from 'Stores/User/Settings';
import IdentityStore from 'Stores/User/Identity';
import { IdentityUserStore } from 'Stores/User/Identity';
import AccountStore from 'Stores/User/Account';
import FolderStore from 'Stores/User/Folder';
import PgpStore from 'Stores/User/Pgp';
@ -136,7 +136,7 @@ class ComposePopupView extends AbstractViewPopup {
this.capaOpenPGP = PgpStore.capaOpenPGP;
this.identities = IdentityStore.identities;
this.identities = IdentityUserStore;
this.addObservables({
identitiesDropdownTrigger: false,
@ -258,7 +258,7 @@ class ComposePopupView extends AbstractViewPopup {
isDraftFolderMessage: () => this.draftFolder() && this.draftUid(),
identitiesOptions: () =>
IdentityStore.identities.map(item => ({
IdentityUserStore.map(item => ({
'item': item,
'optValue': item.id(),
'optText': item.formattedName()
@ -553,7 +553,7 @@ class ComposePopupView extends AbstractViewPopup {
findIdentityByMessage(composeType, message) {
let resultIndex = 1000,
resultIdentity = null;
const identities = IdentityStore.identities(),
const identities = IdentityUserStore(),
identitiesCache = {},
fEachHelper = (item) => {
if (item && item.email && identitiesCache[item.email]) {

View file

@ -2,7 +2,7 @@ import { StorageResultType, Notification } from 'Common/Enums';
import { pInt, pString } from 'Common/Utils';
import { i18n } from 'Common/Translator';
import CapaAdminStore from 'Stores/Admin/Capa';
import { CapaAdminStore } from 'Stores/Admin/Capa';
import Remote from 'Remote/Admin/Fetch';

View file

@ -3,7 +3,7 @@ import ko from 'ko';
import { StorageResultType, Notification } from 'Common/Enums';
import { i18n } from 'Common/Translator';
import DomainStore from 'Stores/Admin/Domain';
import { DomainAdminStore } from 'Stores/Admin/Domain';
import Remote from 'Remote/Admin/Fetch';
@ -23,7 +23,7 @@ class DomainAliasPopupView extends AbstractViewPopup {
alias: ''
});
this.domains = DomainStore.domainsWithoutAliases;
this.domains = ko.computed(() => DomainAdminStore.filter(item => item && !item.alias));
this.domainsOptions = ko.computed(() => this.domains().map(item => ({ optValue: item.name, optText: item.name })));

View file

@ -6,7 +6,7 @@ import { defaultOptionsAfterRender } from 'Common/Utils';
import { i18n, initOnStartOrLangChange } from 'Common/Translator';
import FolderStore from 'Stores/User/Folder';
import SieveStore from 'Stores/User/Sieve';
import { SieveUserStore } from 'Stores/User/Sieve';
import { command } from 'Knoin/Knoin';
import { AbstractViewPopup } from 'Knoin/AbstractViews';
@ -35,7 +35,7 @@ class FilterPopupView extends AbstractViewPopup {
initOnStartOrLangChange(this.populateOptions.bind(this));
SieveStore.capa.subscribe(this.populateOptions, this);
SieveUserStore.capa.subscribe(this.populateOptions, this);
}
@command()
@ -79,7 +79,7 @@ class FilterPopupView extends AbstractViewPopup {
// this.actionTypeOptions.push({'id': FilterAction.None,
// 'name': i18n('GLOBAL/NONE')});
const modules = SieveStore.capa;
const modules = SieveUserStore.capa;
if (modules) {
if (modules.includes('imap4flags')) {
this.allowMarkAsRead(true);

View file

@ -7,7 +7,7 @@ import { i18nToNodes } from 'Common/Translator';
import Remote from 'Remote/User/Fetch';
import { FilterModel } from 'Model/Filter';
import SieveStore from 'Stores/User/Sieve';
import { SieveUserStore } from 'Stores/User/Sieve';
import { showScreenPopup/*, command*/ } from 'Knoin/Knoin';
import { AbstractViewPopup } from 'Knoin/AbstractViews';
@ -26,7 +26,7 @@ class SieveScriptPopupView extends AbstractViewPopup {
script: null
});
this.sieveCapabilities = SieveStore.capa.join(' ');
this.sieveCapabilities = SieveUserStore.capa.join(' ');
this.saving = false;
this.filterForDeletion = ko.observable(null).deleteAccessHelper();
@ -41,7 +41,7 @@ class SieveScriptPopupView extends AbstractViewPopup {
return false;
}
if (!script.exists() && SieveStore.scripts.find(item => item.name() === script.name())) {
if (!script.exists() && SieveUserStore.scripts.find(item => item.name() === script.name())) {
script.nameError(true);
return false;
}
@ -58,7 +58,7 @@ class SieveScriptPopupView extends AbstractViewPopup {
self.saving = false;
if (StorageResultType.Success === result && data && data.Result) {
script.exists() || SieveStore.scripts.push(script);
script.exists() || SieveUserStore.scripts.push(script);
script.exists(true);
script.hasChanges(false);
} else {

View file

@ -18,7 +18,7 @@ import { UNUSED_OPTION_VALUE } from 'Common/Consts';
import { doc, leftPanelDisabled, moveAction, Settings } from 'Common/Globals';
import { computedPaginatorHelper } from 'Common/UtilsUser';
import { File } from 'Common/File';
import { FileInfo } from 'Common/File';
import { mailBox, serverRequest } from 'Common/Links';
import { Selector } from 'Common/Selector';
@ -882,9 +882,9 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
quotaTooltip() {
return i18n('MESSAGE_LIST/QUOTA_SIZE', {
'SIZE': File.friendlySize(this.userUsageSize()),
'SIZE': FileInfo.friendlySize(this.userUsageSize()),
'PROC': this.userUsageProc(),
'LIMIT': File.friendlySize(this.userQuota())
'LIMIT': FileInfo.friendlySize(this.userQuota())
});
}

View file

@ -13,7 +13,7 @@ nl_NL:
LABEL_DOMAINS_NAME: "Domeinen"
LABEL_SECURITY_NAME: "Beveiliging"
LABEL_PLUGINS_NAME: "Invoegtoepassingen"
LABEL_PACKAGES_NAME: "Paketten"
LABEL_PACKAGES_NAME: "Pakketten"
LABEL_ABOUT_NAME: "Over"
TAB_GENERAL:
LEGEND_INTERFACE: "Interface"

View file

@ -1,6 +1,6 @@
<div class="b-admin-packages">
<div class="alert" style="margin-top: 10px;" data-bind="visible: !packagesReal() && !packages.loading()"
<div class="alert" style="margin-top: 10px;" data-bind="visible: !packages.real() && !packages.loading()"
data-i18n="TAB_PACKAGES/ALERT_CANNOT_ACCESS_REPOSITORY"></div>
<div class="alert" style="margin-top: 10px;" data-bind="visible: '' !== packagesError()">

View file

@ -7,8 +7,8 @@
</div>
<div class="modal-body" style="min-height: 150px;">
<div data-bind="foreach: languages">
<label class="lang-item" data-tooltip-i18n="off" data-bind="click: function () { $root.changeLanguage(key); }, css: {'selected': selected, 'user': user},
tooltip: function () { return $root.languageTooltipName(key); },
<label class="lang-item" data-bind="click: function () { $root.changeLanguage(key); }, css: {'selected': selected, 'user': user},
attr: { title: $root.languageTooltipName(key) },
text: fullName">
</label>
</div>

View file

@ -202,7 +202,7 @@
</div>
</div>
<div class="b-footer thm-message-list-bottom-toolbar">
<span data-tooltip-i18n="off" data-bind="visible: 0 < userUsageProc(), tooltip: quotaTooltip" class="e-quota">
<span data-bind="visible: 0 < userUsageProc(), attr: { title: quotaTooltip }" class="e-quota">
<span data-bind="text: userUsageProc"></span>%
</span>
<div class="pull-right">

View file

@ -1,8 +1,8 @@
<div class="b-system-drop-down g-ui-user-select-none">
<div class="b-toolbar">
<div class="btn-toolbar">
<div class="audioPlace" data-tooltip-i18n="off"
data-bind="visible: '' !== currentAudio(), tooltip: currentAudio, click: stopPlay">
<div class="audioPlace"
data-bind="visible: '' !== currentAudio(), attr: { title: currentAudio }, click: stopPlay">
<div class="playIcon equaliser" data-bind="css: {'animated': '' !== currentAudio()}">
<div class="bar first"></div>
<div class="bar second"></div>