diff --git a/dev/App/Abstract.js b/dev/App/Abstract.js index 86fff871b..95d5e1485 100644 --- a/dev/App/Abstract.js +++ b/dev/App/Abstract.js @@ -314,6 +314,10 @@ }); ssm.ready(); + + require('Stores/Language').populate(); + require('Stores/Theme').populate(); + require('Stores/Social').populate(); }; module.exports = AbstractApp; diff --git a/dev/App/Admin.js b/dev/App/Admin.js index 4a81b5291..e937e5631 100644 --- a/dev/App/Admin.js +++ b/dev/App/Admin.js @@ -15,7 +15,11 @@ Translator = require('Common/Translator'), Settings = require('Storage/Settings'), - Data = require('Storage/Admin/Data'), + DomainStore = require('Stores/Admin/Domain'), + PluginStore = require('Stores/Admin/Plugin'), + LicenseStore = require('Stores/Admin/License'), + PackageStore = require('Stores/Admin/Package'), + CoreStore = require('Stores/Admin/Core'), Remote = require('Storage/Admin/Remote'), kn = require('Knoin/Knoin'), @@ -38,17 +42,12 @@ return Remote; }; - AdminApp.prototype.data = function () - { - return Data; - }; - AdminApp.prototype.reloadDomainList = function () { - Data.domains.loading(true); + DomainStore.collection.loading(true); Remote.domainList(function (sResult, oData) { - Data.domains.loading(false); + DomainStore.collection.loading(false); if (Enums.StorageResultType.Success === sResult && oData && oData.Result) { var aList = _.map(oData.Result, function (bEnabled, sName) { @@ -59,17 +58,18 @@ }; }, this); - Data.domains(aList); + DomainStore.collection(aList); } }); }; AdminApp.prototype.reloadPluginList = function () { - Data.plugins.loading(true); + PluginStore.collection.loading(true); + Remote.pluginList(function (sResult, oData) { - Data.plugins.loading(false); + PluginStore.collection.loading(false); if (Enums.StorageResultType.Success === sResult && oData && oData.Result) { @@ -81,31 +81,31 @@ }; }, this); - Data.plugins(aList); + PluginStore.collection(aList); } }); }; AdminApp.prototype.reloadPackagesList = function () { - Data.packages.loading(true); - Data.packagesReal(true); + PackageStore.collection.loading(true); + PackageStore.packagesReal(true); Remote.packagesList(function (sResult, oData) { - Data.packages.loading(false); + PackageStore.collection.loading(false); if (Enums.StorageResultType.Success === sResult && oData && oData.Result) { - Data.packagesReal(!!oData.Result.Real); - Data.packagesMainUpdatable(!!oData.Result.MainUpdatable); + PackageStore.packagesReal(!!oData.Result.Real); + PackageStore.packagesMainUpdatable(!!oData.Result.MainUpdatable); var aList = [], aLoading = {} ; - _.each(Data.packages(), function (oItem) { + _.each(PackageStore.collection(), function (oItem) { if (oItem && oItem['loading']()) { aLoading[oItem['file']] = oItem; @@ -124,33 +124,33 @@ })); } - Data.packages(aList); + PackageStore.collection(aList); } else { - Data.packagesReal(false); + PackageStore.packagesReal(false); } }); }; AdminApp.prototype.updateCoreData = function () { - Data.coreUpdating(true); + CoreStore.coreUpdating(true); Remote.updateCoreData(function (sResult, oData) { - Data.coreUpdating(false); - Data.coreRemoteVersion(''); - Data.coreRemoteRelease(''); - Data.coreVersionCompare(-2); + CoreStore.coreUpdating(false); + CoreStore.coreRemoteVersion(''); + CoreStore.coreRemoteRelease(''); + CoreStore.coreVersionCompare(-2); if (Enums.StorageResultType.Success === sResult && oData && oData.Result) { - Data.coreReal(true); + CoreStore.coreReal(true); window.location.reload(); } else { - Data.coreReal(false); + CoreStore.coreReal(false); } }); @@ -158,32 +158,32 @@ AdminApp.prototype.reloadCoreData = function () { - Data.coreChecking(true); - Data.coreReal(true); + CoreStore.coreChecking(true); + CoreStore.coreReal(true); Remote.coreData(function (sResult, oData) { - Data.coreChecking(false); + CoreStore.coreChecking(false); if (Enums.StorageResultType.Success === sResult && oData && oData.Result) { - Data.coreReal(!!oData.Result.Real); - Data.coreChannel(oData.Result.Channel || 'stable'); - Data.coreType(oData.Result.Type || 'stable'); - Data.coreUpdatable(!!oData.Result.Updatable); - Data.coreAccess(!!oData.Result.Access); - Data.coreRemoteVersion(oData.Result.RemoteVersion || ''); - Data.coreRemoteRelease(oData.Result.RemoteRelease || ''); - Data.coreVersionCompare(Utils.pInt(oData.Result.VersionCompare)); + CoreStore.coreReal(!!oData.Result.Real); + CoreStore.coreChannel(oData.Result.Channel || 'stable'); + CoreStore.coreType(oData.Result.Type || 'stable'); + CoreStore.coreUpdatable(!!oData.Result.Updatable); + CoreStore.coreAccess(!!oData.Result.Access); + CoreStore.coreRemoteVersion(oData.Result.RemoteVersion || ''); + CoreStore.coreRemoteRelease(oData.Result.RemoteRelease || ''); + CoreStore.coreVersionCompare(Utils.pInt(oData.Result.VersionCompare)); } else { - Data.coreReal(false); - Data.coreChannel('stable'); - Data.coreType('stable'); - Data.coreRemoteVersion(''); - Data.coreRemoteRelease(''); - Data.coreVersionCompare(-2); + CoreStore.coreReal(false); + CoreStore.coreChannel('stable'); + CoreStore.coreType('stable'); + CoreStore.coreRemoteVersion(''); + CoreStore.coreRemoteRelease(''); + CoreStore.coreVersionCompare(-2); } }); }; @@ -196,18 +196,18 @@ { bForce = Utils.isUnd(bForce) ? false : !!bForce; - Data.licensingProcess(true); - Data.licenseError(''); + LicenseStore.licensingProcess(true); + LicenseStore.licenseError(''); Remote.licensing(function (sResult, oData) { - Data.licensingProcess(false); + LicenseStore.licensingProcess(false); if (Enums.StorageResultType.Success === sResult && oData && oData.Result && Utils.isNormal(oData.Result['Expired'])) { - Data.licenseValid(true); - Data.licenseExpired(Utils.pInt(oData.Result['Expired'])); - Data.licenseError(''); + LicenseStore.licenseValid(true); + LicenseStore.licenseExpired(Utils.pInt(oData.Result['Expired'])); + LicenseStore.licenseError(''); - Data.licensing(true); + LicenseStore.licensing(true); } else { @@ -216,19 +216,19 @@ Enums.Notification.LicensingExpired ])) { - Data.licenseError(Translator.getNotification(Utils.pInt(oData.ErrorCode))); - Data.licensing(true); + LicenseStore.licenseError(Translator.getNotification(Utils.pInt(oData.ErrorCode))); + LicenseStore.licensing(true); } else { if (Enums.StorageResultType.Abort === sResult) { - Data.licenseError(Translator.getNotification(Enums.Notification.LicensingServerIsUnavailable)); - Data.licensing(true); + LicenseStore.licenseError(Translator.getNotification(Enums.Notification.LicensingServerIsUnavailable)); + LicenseStore.licensing(true); } else { - Data.licensing(false); + LicenseStore.licensing(false); } } } @@ -239,7 +239,8 @@ { AbstractApp.prototype.bootstart.call(this); - Data.populateDataOnStart(); + require('Stores/Admin/App').populate(); + require('Stores/Admin/Capa').populate(); kn.hideLoading(); diff --git a/dev/App/User.js b/dev/App/User.js index d0c1501b6..3f7df8e7c 100644 --- a/dev/App/User.js +++ b/dev/App/User.js @@ -22,9 +22,9 @@ kn = require('Knoin/Knoin'), SocialStore = require('Stores/Social'), - UserSettingsStore = require('Stores/UserSettings'), + SettingsUserStore = require('Stores/User/Settings'), - Local = require('Storage/Local'), + Local = require('Storage/Client'), Settings = require('Storage/Settings'), Data = require('Storage/User/Data'), Cache = require('Storage/User/Cache'), @@ -136,11 +136,6 @@ return Remote; }; - AppUser.prototype.data = function () - { - return Data; - }; - AppUser.prototype.reloadFlagsCurrentMessageListAndMessageFromCache = function () { _.each(Data.messageList(), function (oMessage) { @@ -158,7 +153,7 @@ { var self = this, - iOffset = (Data.messageListPage() - 1) * UserSettingsStore.messagesPerPage() + iOffset = (Data.messageListPage() - 1) * SettingsUserStore.messagesPerPage() ; if (Utils.isUnd(bDropCurrenFolderCache) ? false : !!bDropCurrenFolderCache) @@ -195,12 +190,12 @@ ); } - }, Data.currentFolderFullNameRaw(), iOffset, UserSettingsStore.messagesPerPage(), Data.messageListSearch()); + }, Data.currentFolderFullNameRaw(), iOffset, SettingsUserStore.messagesPerPage(), Data.messageListSearch()); }; AppUser.prototype.recacheInboxMessageList = function () { - Remote.messageList(Utils.emptyFunction, Cache.getFolderInboxName(), 0, UserSettingsStore.messagesPerPage(), '', true); + Remote.messageList(Utils.emptyFunction, Cache.getFolderInboxName(), 0, SettingsUserStore.messagesPerPage(), '', true); }; AppUser.prototype.reloadMessageListHelper = function (bEmptyList) @@ -585,7 +580,7 @@ Utils.isArray(oData.Result) && 1 < oData.Result.length && Utils.isPosNumeric(oData.Result[0], true) && Utils.isPosNumeric(oData.Result[1], true)) { - require('Stores/Quota').populateData( + require('Stores/User/Quota').populateData( Utils.pInt(oData.Result[1]), Utils.pInt(oData.Result[0])); } }); @@ -999,7 +994,7 @@ Data.messageListCount(iCount); Data.messageListSearch(Utils.isNormal(oData.Result.Search) ? oData.Result.Search : ''); - Data.messageListPage(window.Math.ceil((iOffset / UserSettingsStore.messagesPerPage()) + 1)); + Data.messageListPage(window.Math.ceil((iOffset / SettingsUserStore.messagesPerPage()) + 1)); Data.messageListEndFolder(Utils.isNormal(oData.Result.Folder) ? oData.Result.Folder : ''); Data.messageListEndSearch(Utils.isNormal(oData.Result.Search) ? oData.Result.Search : ''); Data.messageListEndPage(Data.messageListPage()); @@ -1014,7 +1009,7 @@ Cache.clearNewMessageCache(); - if (oFolder && (bCached || bUnreadCountChange || Data.useThreads())) + if (oFolder && (bCached || bUnreadCountChange || SettingsUserStore.useThreads())) { this.folderInformation(oFolder.fullNameRaw, aList); } @@ -1384,6 +1379,10 @@ { AbstractApp.prototype.bootstart.call(this); + require('Stores/User/App').populate(); + require('Stores/User/Settings').populate(); + require('Stores/User/Notification').populate(); + Data.populateDataOnStart(); var diff --git a/dev/Storage/LocalDriver/Cookie.js b/dev/Common/ClientStorageDriver/Cookie.js similarity index 85% rename from dev/Storage/LocalDriver/Cookie.js rename to dev/Common/ClientStorageDriver/Cookie.js index 36d93ac97..27c25861c 100644 --- a/dev/Storage/LocalDriver/Cookie.js +++ b/dev/Common/ClientStorageDriver/Cookie.js @@ -14,7 +14,7 @@ /** * @constructor */ - function CookieLocalDriver() + function CookieDriver() { } @@ -22,7 +22,7 @@ * @static * @return {boolean} */ - CookieLocalDriver.supported = function () + CookieDriver.supported = function () { return !!(window.navigator && window.navigator.cookieEnabled); }; @@ -32,7 +32,7 @@ * @param {*} mData * @return {boolean} */ - CookieLocalDriver.prototype.set = function (sKey, mData) + CookieDriver.prototype.set = function (sKey, mData) { var mStorageValue = $.cookie(Consts.Values.ClientSideStorageIndexName), @@ -70,7 +70,7 @@ * @param {string} sKey * @return {*} */ - CookieLocalDriver.prototype.get = function (sKey) + CookieDriver.prototype.get = function (sKey) { var mStorageValue = $.cookie(Consts.Values.ClientSideStorageIndexName), @@ -94,6 +94,6 @@ return mResult; }; - module.exports = CookieLocalDriver; + module.exports = CookieDriver; }()); \ No newline at end of file diff --git a/dev/Storage/LocalDriver/LocalStorage.js b/dev/Common/ClientStorageDriver/LocalStorage.js similarity index 83% rename from dev/Storage/LocalDriver/LocalStorage.js rename to dev/Common/ClientStorageDriver/LocalStorage.js index 855f6315e..2ad03cea8 100644 --- a/dev/Storage/LocalDriver/LocalStorage.js +++ b/dev/Common/ClientStorageDriver/LocalStorage.js @@ -14,7 +14,7 @@ /** * @constructor */ - function LocalStorageLocalDriver() + function LocalStorageDriver() { } @@ -22,7 +22,7 @@ * @static * @return {boolean} */ - LocalStorageLocalDriver.supported = function () + LocalStorageDriver.supported = function () { return !!window.localStorage; }; @@ -32,7 +32,7 @@ * @param {*} mData * @return {boolean} */ - LocalStorageLocalDriver.prototype.set = function (sKey, mData) + LocalStorageDriver.prototype.set = function (sKey, mData) { var mStorageValue = window.localStorage[Consts.Values.ClientSideStorageIndexName] || null, @@ -68,7 +68,7 @@ * @param {string} sKey * @return {*} */ - LocalStorageLocalDriver.prototype.get = function (sKey) + LocalStorageDriver.prototype.get = function (sKey) { var mStorageValue = window.localStorage[Consts.Values.ClientSideStorageIndexName] || null, @@ -92,6 +92,6 @@ return mResult; }; - module.exports = LocalStorageLocalDriver; + module.exports = LocalStorageDriver; }()); \ No newline at end of file diff --git a/dev/Common/Utils.js b/dev/Common/Utils.js index e4e5f6ccf..4ab764c9a 100644 --- a/dev/Common/Utils.js +++ b/dev/Common/Utils.js @@ -217,7 +217,7 @@ return sValue; }; - Utils.rsaEncode.supported = !!(window.crypto && window.crypto.getRandomValues && JSEncrypt); + Utils.rsaEncode.supported = !!(window.crypto && window.crypto.getRandomValues && false && JSEncrypt); /** * @param {string} sText @@ -623,52 +623,6 @@ return fResult; }; - /** - * @param {Object} oData - */ - Utils.initDataConstructorBySettings = function (oData) - { - oData.showImages = ko.observable(false); - oData.contactsAutosave = ko.observable(false); - oData.interfaceAnimation = ko.observable(true); - - oData.capaThemes = ko.observable(true); - oData.capaUserBackground = ko.observable(false); - oData.allowLanguagesOnSettings = ko.observable(true); - oData.allowLanguagesOnLogin = ko.observable(true); - - oData.useLocalProxyForExternalImages = ko.observable(false); - - oData.useThreads = ko.observable(true); - oData.replySameFolder = ko.observable(true); - oData.useCheckboxesInList = ko.observable(true); - - oData.interfaceAnimation.subscribe(function (bValue) { - if (Globals.bMobileDevice || !bValue) - { - Globals.$html.removeClass('rl-anim').addClass('no-rl-anim'); - } - else - { - Globals.$html.removeClass('no-rl-anim').addClass('rl-anim'); - } - }); - - oData.interfaceAnimation.valueHasMutated(); - - oData.capaAdditionalAccounts = ko.observable(false); - oData.capaAdditionalIdentities = ko.observable(false); - oData.capaGravatar = ko.observable(false); - oData.capaSieve = ko.observable(false); - oData.capaAttachmentThumbnails = ko.observable(false); - oData.determineUserLanguage = ko.observable(false); - oData.determineUserDomain = ko.observable(false); - - oData.weakPassword = ko.observable(false); - - oData.contactsIsAllowed = ko.observable(false); - }; - /** * @param {{moment:Function}} oObject */ diff --git a/dev/Screen/User/MailBox.js b/dev/Screen/User/MailBox.js index 5341e40da..cb589c85b 100644 --- a/dev/Screen/User/MailBox.js +++ b/dev/Screen/User/MailBox.js @@ -12,7 +12,7 @@ Events = require('Common/Events'), Translator = require('Common/Translator'), - UserSettingsStore = require('Stores/UserSettings'), + SettingsUserStore = require('Stores/User/Settings'), Data = require('Storage/User/Data'), Cache = require('Storage/User/Cache'), @@ -71,7 +71,7 @@ { if (Utils.isUnd(bPreview) ? false : !!bPreview) { - if (Enums.Layout.NoPreview === UserSettingsStore.layout() && !Data.message()) + if (Enums.Layout.NoPreview === SettingsUserStore.layout() && !Data.message()) { require('App/User').historyBack(); } @@ -91,7 +91,7 @@ .messageListSearch(sSearch) ; - if (Enums.Layout.NoPreview === UserSettingsStore.layout() && Data.message()) + if (Enums.Layout.NoPreview === SettingsUserStore.layout() && Data.message()) { Data.message(null); } @@ -107,7 +107,7 @@ Data.messageList.subscribe(Utils.windowResizeCallback); Data.message.subscribe(Utils.windowResizeCallback); - UserSettingsStore.layout.subscribe(function (nValue) { + SettingsUserStore.layout.subscribe(function (nValue) { Globals.$html.toggleClass('rl-no-preview-pane', Enums.Layout.NoPreview === nValue); Globals.$html.toggleClass('rl-side-preview-pane', Enums.Layout.SidePreview === nValue); @@ -116,7 +116,7 @@ Events.pub('layout', [nValue]); }); - UserSettingsStore.layout.valueHasMutated(); + SettingsUserStore.layout.valueHasMutated(); Events.sub('mailbox.inbox-unread-count', function (nCount) { Data.foldersInboxUnreadCount(nCount); diff --git a/dev/Screen/User/Settings.js b/dev/Screen/User/Settings.js index c8dd5323f..042cbb521 100644 --- a/dev/Screen/User/Settings.js +++ b/dev/Screen/User/Settings.js @@ -10,6 +10,7 @@ Globals = require('Common/Globals'), Translator = require('Common/Translator'), + AppStore = require('Stores/User/App'), Settings = require('Storage/Settings'), kn = require('Knoin/Knoin'), @@ -46,7 +47,7 @@ kn.addSettingsViewModel(require('Settings/User/General'), 'SettingsGeneral', 'SETTINGS_LABELS/LABEL_GENERAL_NAME', 'general', true); - if (Settings.settingsGet('ContactsIsAllowed')) + if (AppStore.contactsIsAllowed()) { kn.addSettingsViewModel(require('Settings/User/Contacts'), 'SettingsContacts', 'SETTINGS_LABELS/LABEL_CONTACTS_NAME', 'contacts'); diff --git a/dev/Settings/Admin/About.js b/dev/Settings/Admin/About.js index 77ab4804b..24583076a 100644 --- a/dev/Settings/Admin/About.js +++ b/dev/Settings/Admin/About.js @@ -4,7 +4,10 @@ 'use strict'; var - ko = require('ko') + ko = require('ko'), + + Settings = require('Storage/Settings'), + CoreStore = require('Stores/Admin/Core') ; /** @@ -12,25 +15,20 @@ */ function AboutAdminSettings() { - var - Settings = require('Storage/Settings'), - Data = require('Storage/Admin/Data') - ; - this.version = ko.observable(Settings.settingsGet('Version')); this.access = ko.observable(!!Settings.settingsGet('CoreAccess')); this.errorDesc = ko.observable(''); - this.coreReal = Data.coreReal; - this.coreChannel = Data.coreChannel; - this.coreType = Data.coreType; - this.coreUpdatable = Data.coreUpdatable; - this.coreAccess = Data.coreAccess; - this.coreChecking = Data.coreChecking; - this.coreUpdating = Data.coreUpdating; - this.coreRemoteVersion = Data.coreRemoteVersion; - this.coreRemoteRelease = Data.coreRemoteRelease; - this.coreVersionCompare = Data.coreVersionCompare; + this.coreReal = CoreStore.coreReal; + this.coreChannel = CoreStore.coreChannel; + this.coreType = CoreStore.coreType; + this.coreUpdatable = CoreStore.coreUpdatable; + this.coreAccess = CoreStore.coreAccess; + this.coreChecking = CoreStore.coreChecking; + this.coreUpdating = CoreStore.coreUpdating; + this.coreRemoteVersion = CoreStore.coreRemoteVersion; + this.coreRemoteRelease = CoreStore.coreRemoteRelease; + this.coreVersionCompare = CoreStore.coreVersionCompare; this.statusType = ko.computed(function () { diff --git a/dev/Settings/Admin/Domains.js b/dev/Settings/Admin/Domains.js index b5aa1fdb8..ffc1ebc9f 100644 --- a/dev/Settings/Admin/Domains.js +++ b/dev/Settings/Admin/Domains.js @@ -12,7 +12,7 @@ PopupsDomainViewModel = require('View/Popup/Domain'), - Data = require('Storage/Admin/Data'), + DomainStore = require('Stores/Admin/Domain'), Remote = require('Storage/Admin/Remote') ; @@ -21,12 +21,12 @@ */ function DomainsAdminSettings() { - this.domains = Data.domains; + this.domains = DomainStore.collection; this.iDomainForDeletionTimeout = 0; this.visibility = ko.computed(function () { - return Data.domains.loading() ? 'visible' : 'hidden'; + return this.domains.loading() ? 'visible' : 'hidden'; }, this); this.domainForDeletion = ko.observable(null).extend({'toggleSubscribe': [this, diff --git a/dev/Settings/Admin/General.js b/dev/Settings/Admin/General.js index 74b6bfc47..16dd61e16 100644 --- a/dev/Settings/Admin/General.js +++ b/dev/Settings/Admin/General.js @@ -11,10 +11,12 @@ Utils = require('Common/Utils'), Links = require('Common/Links'), - UserSettingsStore = require('Stores/UserSettings'), + ThemeStore = require('Stores/Theme'), + LanguageStore = require('Stores/Language'), + AppAdminStore = require('Stores/Admin/App'), + CapaAdminStore = require('Stores/Admin/Capa'), - Settings = require('Storage/Settings'), - Data = require('Storage/Admin/Data') + Settings = require('Storage/Settings') ; /** @@ -22,20 +24,20 @@ */ function GeneralAdminSettings() { - this.language = UserSettingsStore.language; - this.languages = UserSettingsStore.languages; - this.theme = UserSettingsStore.theme; - this.themes = UserSettingsStore.themes; + this.language = LanguageStore.language; + this.languages = LanguageStore.languages; + this.theme = ThemeStore.theme; + this.themes = ThemeStore.themes; - this.capaThemes = Data.capaThemes; - this.capaUserBackground = Data.capaUserBackground; - this.allowLanguagesOnSettings = Data.allowLanguagesOnSettings; - this.capaGravatar = Data.capaGravatar; - this.capaAdditionalAccounts = Data.capaAdditionalAccounts; - this.capaAdditionalIdentities = Data.capaAdditionalIdentities; - this.capaAttachmentThumbnails = Data.capaAttachmentThumbnails; + this.capaThemes = CapaAdminStore.themes; + this.capaUserBackground = CapaAdminStore.userBackground; + this.capaGravatar = CapaAdminStore.gravatar; + this.capaAdditionalAccounts = CapaAdminStore.additionalAccounts; + this.capaAdditionalIdentities = CapaAdminStore.additionalIdentities; + this.capaAttachmentThumbnails = CapaAdminStore.attachmentThumbnails; - this.weakPassword = Data.weakPassword; + this.allowLanguagesOnSettings = AppAdminStore.allowLanguagesOnSettings; + this.weakPassword = AppAdminStore.weakPassword; this.mainAttachmentLimit = ko.observable(Utils.pInt(Settings.settingsGet('AttachmentLimit')) / (1024 * 1024)).extend({'posInterer': 25}); this.uploadData = Settings.settingsGet('PhpUploadSizes'); diff --git a/dev/Settings/Admin/Licensing.js b/dev/Settings/Admin/Licensing.js index 102057809..1ba99a409 100644 --- a/dev/Settings/Admin/Licensing.js +++ b/dev/Settings/Admin/Licensing.js @@ -8,7 +8,7 @@ moment = require('moment'), Settings = require('Storage/Settings'), - Data = require('Storage/Admin/Data') + LicenseStore = require('Stores/Admin/License') ; /** @@ -16,12 +16,12 @@ */ function LicensingAdminSettings() { - this.licensing = Data.licensing; - this.licensingProcess = Data.licensingProcess; - this.licenseValid = Data.licenseValid; - this.licenseExpired = Data.licenseExpired; - this.licenseError = Data.licenseError; - this.licenseTrigger = Data.licenseTrigger; + this.licensing = LicenseStore.licensing; + this.licensingProcess = LicenseStore.licensingProcess; + this.licenseValid = LicenseStore.licenseValid; + this.licenseExpired = LicenseStore.licenseExpired; + this.licenseError = LicenseStore.licenseError; + this.licenseTrigger = LicenseStore.licenseTrigger; this.adminDomain = ko.observable(''); this.subscriptionEnabled = ko.observable(!!Settings.settingsGet('SubscriptionEnabled')); diff --git a/dev/Settings/Admin/Login.js b/dev/Settings/Admin/Login.js index 14f4f354f..908aecfdb 100644 --- a/dev/Settings/Admin/Login.js +++ b/dev/Settings/Admin/Login.js @@ -10,8 +10,9 @@ Enums = require('Common/Enums'), Utils = require('Common/Utils'), - Settings = require('Storage/Settings'), - Data = require('Storage/Admin/Data') + AppAdminStore = require('Stores/Admin/App'), + + Settings = require('Storage/Settings') ; /** @@ -19,12 +20,12 @@ */ function LoginAdminSettings() { - this.determineUserLanguage = Data.determineUserLanguage; - this.determineUserDomain = Data.determineUserDomain; + this.determineUserLanguage = AppAdminStore.determineUserLanguage; + this.determineUserDomain = AppAdminStore.determineUserDomain; this.defaultDomain = ko.observable(Settings.settingsGet('LoginDefaultDomain')); - this.allowLanguagesOnLogin = Data.allowLanguagesOnLogin; + this.allowLanguagesOnLogin = AppAdminStore.allowLanguagesOnLogin; this.defaultDomainTrigger = ko.observable(Enums.SaveSettingsStep.Idle); this.dummy = ko.observable(false); diff --git a/dev/Settings/Admin/Packages.js b/dev/Settings/Admin/Packages.js index 177d58988..af5205cf8 100644 --- a/dev/Settings/Admin/Packages.js +++ b/dev/Settings/Admin/Packages.js @@ -5,12 +5,13 @@ var window = require('window'), + _ = require('_'), ko = require('ko'), Enums = require('Common/Enums'), Translator = require('Common/Translator'), - Data = require('Storage/Admin/Data'), + PackageStore = require('Stores/Admin/Package'), Remote = require('Storage/Admin/Remote') ; @@ -21,9 +22,9 @@ { this.packagesError = ko.observable(''); - this.packages = Data.packages; - this.packagesReal = Data.packagesReal; - this.packagesMainUpdatable = Data.packagesMainUpdatable; + this.packages = PackageStore.collection; + this.packagesReal = PackageStore.packagesReal; + this.packagesMainUpdatable = PackageStore.packagesMainUpdatable; this.packagesCurrent = this.packages.filter(function (oItem) { return oItem && '' !== oItem['installed'] && !oItem['compare']; @@ -38,7 +39,7 @@ }); this.visibility = ko.computed(function () { - return Data.packages.loading() ? 'visible' : 'hidden'; + return PackageStore.collection.loading() ? 'visible' : 'hidden'; }, this); } @@ -70,7 +71,7 @@ } } - _.each(Data.packages(), function (oItem) { + _.each(self.packages(), function (oItem) { if (oItem && oPackage && oItem['loading']() && oPackage['file'] === oItem['file']) { oPackage['loading'](false); diff --git a/dev/Settings/Admin/Plugins.js b/dev/Settings/Admin/Plugins.js index 0ff7d62dd..27e9e9269 100644 --- a/dev/Settings/Admin/Plugins.js +++ b/dev/Settings/Admin/Plugins.js @@ -12,7 +12,7 @@ Translator = require('Common/Translator'), Settings = require('Storage/Settings'), - Data = require('Storage/Admin/Data'), + PluginStore = require('Stores/Admin/Plugin'), Remote = require('Storage/Admin/Remote') ; @@ -23,12 +23,11 @@ { this.enabledPlugins = ko.observable(!!Settings.settingsGet('EnabledPlugins')); - this.pluginsError = ko.observable(''); - - this.plugins = Data.plugins; + this.plugins = PluginStore.collection; + this.pluginsError = PluginStore.collection.error; this.visibility = ko.computed(function () { - return Data.plugins.loading() ? 'visible' : 'hidden'; + return PluginStore.collection.loading() ? 'visible' : 'hidden'; }, this); this.onPluginLoadRequest = _.bind(this.onPluginLoadRequest, this); @@ -76,7 +75,7 @@ PluginsAdminSettings.prototype.onShow = function () { - this.pluginsError(''); + PluginStore.collection.error(''); require('App/Admin').reloadPluginList(); }; @@ -96,11 +95,11 @@ { if (Enums.Notification.UnsupportedPluginPackage === oData.ErrorCode && oData.ErrorMessage && '' !== oData.ErrorMessage) { - this.pluginsError(oData.ErrorMessage); + PluginStore.collection.error(oData.ErrorMessage); } else { - this.pluginsError(Translator.getNotification(oData.ErrorCode)); + PluginStore.collection.error(Translator.getNotification(oData.ErrorCode)); } } } diff --git a/dev/Settings/Admin/Security.js b/dev/Settings/Admin/Security.js index a891da2de..5f7d43b6e 100644 --- a/dev/Settings/Admin/Security.js +++ b/dev/Settings/Admin/Security.js @@ -11,8 +11,10 @@ Utils = require('Common/Utils'), Links = require('Common/Links'), + AppAdminStore = require('Stores/Admin/App'), + CapaAdminStore = require('Stores/Admin/Capa'), + Settings = require('Storage/Settings'), - Data = require('Storage/Admin/Data'), Remote = require('Storage/Admin/Remote') ; @@ -21,12 +23,12 @@ */ function SecurityAdminSettings() { - this.useLocalProxyForExternalImages = Data.useLocalProxyForExternalImages; + this.useLocalProxyForExternalImages = AppAdminStore.useLocalProxyForExternalImages; - this.weakPassword = Data.weakPassword; + this.weakPassword = AppAdminStore.weakPassword; - this.capaOpenPGP = ko.observable(Settings.capa(Enums.Capa.OpenPGP)); - this.capaTwoFactorAuth = ko.observable(Settings.capa(Enums.Capa.TwoFactor)); + this.capaOpenPGP = CapaAdminStore.openPGP; + this.capaTwoFactorAuth = CapaAdminStore.twoFactorAuth; this.verifySslCertificate = ko.observable(!!Settings.settingsGet('VerifySslCertificate')); this.allowSelfSigned = ko.observable(!!Settings.settingsGet('AllowSelfSigned')); diff --git a/dev/Settings/User/Contacts.js b/dev/Settings/User/Contacts.js index d557d71ee..523a5deb2 100644 --- a/dev/Settings/User/Contacts.js +++ b/dev/Settings/User/Contacts.js @@ -6,6 +6,8 @@ var ko = require('ko'), + AppStore = require('Stores/User/App'), + Remote = require('Storage/User/Remote'), Data = require('Storage/User/Data') ; @@ -15,7 +17,7 @@ */ function ContactsUserSettings() { - this.contactsAutosave = Data.contactsAutosave; + this.contactsAutosave = AppStore.contactsAutosave; this.allowContactsSync = Data.allowContactsSync; this.enableContactsSync = Data.enableContactsSync; @@ -35,7 +37,7 @@ ContactsUserSettings.prototype.onBuild = function () { - Data.contactsAutosave.subscribe(function (bValue) { + this.contactsAutosave.subscribe(function (bValue) { Remote.saveSettings(null, { 'ContactsAutosave': bValue ? '1' : '0' }); diff --git a/dev/Settings/User/Filters.js b/dev/Settings/User/Filters.js index 0e4e041a4..41b874a7a 100644 --- a/dev/Settings/User/Filters.js +++ b/dev/Settings/User/Filters.js @@ -11,7 +11,7 @@ Utils = require('Common/Utils'), Translator = require('Common/Translator'), - FilterStore = require('Stores/Filter'), + FilterStore = require('Stores/User/Filter'), Remote = require('Storage/User/Remote') ; diff --git a/dev/Settings/User/Folders.js b/dev/Settings/User/Folders.js index 9fb18e52e..eac460179 100644 --- a/dev/Settings/User/Folders.js +++ b/dev/Settings/User/Folders.js @@ -14,7 +14,7 @@ Data = require('Storage/User/Data'), Cache = require('Storage/User/Cache'), Remote = require('Storage/User/Remote'), - Local = require('Storage/Local') + Local = require('Storage/Client') ; /** diff --git a/dev/Settings/User/General.js b/dev/Settings/User/General.js index 419faad61..f34ea92a4 100644 --- a/dev/Settings/User/General.js +++ b/dev/Settings/User/General.js @@ -13,8 +13,10 @@ Utils = require('Common/Utils'), Translator = require('Common/Translator'), - UserSettingsStore = require('Stores/UserSettings'), - NotificationSettingsStore = require('Stores/NotificationSettings'), + AppStore = require('Stores/User/App'), + LanguageStore = require('Stores/Language'), + SettingsStore = require('Stores/User/Settings'), + NotificationStore = require('Stores/User/Notification'), Data = require('Storage/User/Data'), Remote = require('Storage/User/Remote') @@ -25,25 +27,27 @@ */ function GeneralUserSettings() { - this.language = UserSettingsStore.language; - this.messagesPerPage = UserSettingsStore.messagesPerPage; + this.language = LanguageStore.language; + this.messagesPerPage = SettingsStore.messagesPerPage; this.messagesPerPageArray = Consts.Defaults.MessagesPerPageArray; - this.editorDefaultType = UserSettingsStore.editorDefaultType; - this.layout = UserSettingsStore.layout; - this.usePreviewPane = UserSettingsStore.usePreviewPane; + this.editorDefaultType = SettingsStore.editorDefaultType; + this.layout = SettingsStore.layout; + this.usePreviewPane = SettingsStore.usePreviewPane; - this.showImages = Data.showImages; + this.soundNotificationIsSupported = NotificationStore.soundNotificationIsSupported; + this.enableSoundNotification = NotificationStore.enableSoundNotification; - this.enableDesktopNotification = NotificationSettingsStore.enableDesktopNotification; - this.isDesktopNotificationSupported = NotificationSettingsStore.isDesktopNotificationSupported; - this.isDesktopNotificationDenied = NotificationSettingsStore.isDesktopNotificationDenied; + this.enableDesktopNotification = NotificationStore.enableDesktopNotification; + this.isDesktopNotificationSupported = NotificationStore.isDesktopNotificationSupported; + this.isDesktopNotificationDenied = NotificationStore.isDesktopNotificationDenied; + this.showImages = SettingsStore.showImages; + this.useCheckboxesInList = SettingsStore.useCheckboxesInList; this.threading = Data.threading; - this.useThreads = Data.useThreads; - this.replySameFolder = Data.replySameFolder; - this.useCheckboxesInList = Data.useCheckboxesInList; - this.allowLanguagesOnSettings = Data.allowLanguagesOnSettings; + this.useThreads = SettingsStore.useThreads; + this.replySameFolder = SettingsStore.replySameFolder; + this.allowLanguagesOnSettings = AppStore.allowLanguagesOnSettings; this.languageFullName = ko.computed(function () { return Utils.convertLangName(this.language()); @@ -77,6 +81,11 @@ }, this); } + GeneralUserSettings.prototype.testSoundNotification = function () + { + NotificationStore.playSoundNotification(true); + }; + GeneralUserSettings.prototype.onBuild = function () { var self = this; @@ -122,7 +131,7 @@ }); }); - Data.showImages.subscribe(function (bValue) { + self.showImages.subscribe(function (bValue) { Remote.saveSettings(null, { 'ShowImages': bValue ? '1' : '0' }); @@ -136,7 +145,15 @@ }, 3000); }); - Data.replySameFolder.subscribe(function (bValue) { + self.enableSoundNotification.subscribe(function (bValue) { + Utils.timeOutAction('SaveSoundNotification', function () { + Remote.saveSettings(null, { + 'SoundNotification': bValue ? '1' : '0' + }); + }, 3000); + }); + + self.replySameFolder.subscribe(function (bValue) { Utils.timeOutAction('SaveReplySameFolder', function () { Remote.saveSettings(null, { 'ReplySameFolder': bValue ? '1' : '0' @@ -144,7 +161,7 @@ }, 3000); }); - Data.useThreads.subscribe(function (bValue) { + self.useThreads.subscribe(function (bValue) { Data.messageList([]); @@ -162,7 +179,7 @@ }); }); - Data.useCheckboxesInList.subscribe(function (bValue) { + self.useCheckboxesInList.subscribe(function (bValue) { Remote.saveSettings(null, { 'UseCheckboxesInList': bValue ? '1' : '0' }); diff --git a/dev/Settings/User/Themes.js b/dev/Settings/User/Themes.js index e4e231af5..6b53155fd 100644 --- a/dev/Settings/User/Themes.js +++ b/dev/Settings/User/Themes.js @@ -14,9 +14,9 @@ Links = require('Common/Links'), Translator = require('Common/Translator'), - UserSettingsStore = require('Stores/UserSettings'), + ThemeStore = require('Stores/Theme'), - Data = require('Storage/User/Data'), + Settings = require('Storage/Settings'), Remote = require('Storage/User/Remote') ; @@ -25,18 +25,18 @@ */ function ThemesUserSettings() { - this.theme = UserSettingsStore.theme; - this.themes = UserSettingsStore.themes; + this.theme = ThemeStore.theme; + this.themes = ThemeStore.themes; this.themesObjects = ko.observableArray([]); this.background = {}; - this.background.name = UserSettingsStore.themeBackgroundName; - this.background.hash = UserSettingsStore.themeBackgroundHash; + this.background.name = ThemeStore.themeBackgroundName; + this.background.hash = ThemeStore.themeBackgroundHash; this.background.uploaderButton = ko.observable(null); this.background.loading = ko.observable(false); this.background.error = ko.observable(''); - this.capaUserBackground = Data.capaUserBackground; + this.capaUserBackground = ko.observable(Settings.capa(Enums.Capa.UserBackground)); this.themeTrigger = ko.observable(Enums.SaveSettingsStep.Idle).extend({'throttle': 100}); diff --git a/dev/Storage/AbstractData.js b/dev/Storage/AbstractData.js deleted file mode 100644 index 753098e5e..000000000 --- a/dev/Storage/AbstractData.js +++ /dev/null @@ -1,56 +0,0 @@ - -(function () { - - 'use strict'; - - var - Enums = require('Common/Enums'), - Utils = require('Common/Utils'), - - Settings = require('Storage/Settings') - ; - - /** - * @constructor - */ - function AbstractDataStorate() - { - Utils.initDataConstructorBySettings(this); - } - - AbstractDataStorate.prototype.populateDataOnStart = function() - { - this.capaAdditionalAccounts(Settings.capa(Enums.Capa.AdditionalAccounts)); - this.capaAdditionalIdentities(Settings.capa(Enums.Capa.AdditionalIdentities)); - this.capaGravatar(Settings.capa(Enums.Capa.Gravatar)); - this.capaAttachmentThumbnails(Settings.capa(Enums.Capa.AttachmentThumbnails)); - this.capaSieve(Settings.capa(Enums.Capa.Sieve)); - this.determineUserLanguage(!!Settings.settingsGet('DetermineUserLanguage')); - this.determineUserDomain(!!Settings.settingsGet('DetermineUserDomain')); - - this.weakPassword(!!Settings.settingsGet('WeakPassword')); - - this.capaThemes(Settings.capa(Enums.Capa.Themes)); - this.capaUserBackground(Settings.capa(Enums.Capa.UserBackground)); - this.allowLanguagesOnLogin(!!Settings.settingsGet('AllowLanguagesOnLogin')); - this.allowLanguagesOnSettings(!!Settings.settingsGet('AllowLanguagesOnSettings')); - this.useLocalProxyForExternalImages(!!Settings.settingsGet('UseLocalProxyForExternalImages')); - - this.showImages(!!Settings.settingsGet('ShowImages')); - this.contactsAutosave(!!Settings.settingsGet('ContactsAutosave')); - this.interfaceAnimation(!!Settings.settingsGet('InterfaceAnimation')); - - this.useThreads(!!Settings.settingsGet('UseThreads')); - this.replySameFolder(!!Settings.settingsGet('ReplySameFolder')); - this.useCheckboxesInList(!!Settings.settingsGet('UseCheckboxesInList')); - - require('Stores/Social').populate(); - require('Stores/UserSettings').populate(); - require('Stores/NotificationSettings').populate(); - - this.contactsIsAllowed(!!Settings.settingsGet('ContactsIsAllowed')); - }; - - module.exports = AbstractDataStorate; - -}()); \ No newline at end of file diff --git a/dev/Storage/Admin/Data.js b/dev/Storage/Admin/Data.js deleted file mode 100644 index 130b60e6c..000000000 --- a/dev/Storage/Admin/Data.js +++ /dev/null @@ -1,69 +0,0 @@ - -(function () { - - 'use strict'; - - var - _ = require('_'), - ko = require('ko'), - - AbstractData = require('Storage/AbstractData') - ; - - /** - * @constructor - * @extends AbstractData - */ - function DataAdminStorage() - { - AbstractData.call(this); - - this.domains = ko.observableArray([]); - this.domains.loading = ko.observable(false).extend({'throttle': 100}); - - this.plugins = ko.observableArray([]); - this.plugins.loading = ko.observable(false).extend({'throttle': 100}); - - this.packagesReal = ko.observable(true); - this.packagesMainUpdatable = ko.observable(true); - this.packages = ko.observableArray([]); - this.packages.loading = ko.observable(false).extend({'throttle': 100}); - - this.coreReal = ko.observable(true); - this.coreChannel = ko.observable('stable'); - this.coreType = ko.observable('stable'); - this.coreUpdatable = ko.observable(true); - this.coreAccess = ko.observable(true); - this.coreChecking = ko.observable(false).extend({'throttle': 100}); - this.coreUpdating = ko.observable(false).extend({'throttle': 100}); - this.coreRemoteVersion = ko.observable(''); - this.coreRemoteRelease = ko.observable(''); - this.coreVersionCompare = ko.observable(-2); - - this.licensing = ko.observable(false); - this.licensingProcess = ko.observable(false); - this.licenseValid = ko.observable(false); - this.licenseExpired = ko.observable(0); - this.licenseError = ko.observable(''); - - this.licenseTrigger = ko.observable(false); - - this.adminManLoading = ko.computed(function () { - return '000' !== [this.domains.loading() ? '1' : '0', this.plugins.loading() ? '1' : '0', this.packages.loading() ? '1' : '0'].join(''); - }, this); - - this.adminManLoadingVisibility = ko.computed(function () { - return this.adminManLoading() ? 'visible' : 'hidden'; - }, this).extend({'rateLimit': 300}); - } - - _.extend(DataAdminStorage.prototype, AbstractData.prototype); - - DataAdminStorage.prototype.populateDataOnStart = function() - { - AbstractData.prototype.populateDataOnStart.call(this); - }; - - module.exports = new DataAdminStorage(); - -}()); \ No newline at end of file diff --git a/dev/Storage/Local.js b/dev/Storage/Client.js similarity index 68% rename from dev/Storage/Local.js rename to dev/Storage/Client.js index 7ccc6295d..e37adaa67 100644 --- a/dev/Storage/Local.js +++ b/dev/Storage/Client.js @@ -6,12 +6,12 @@ /** * @constructor */ - function LocalStorage() + function ClientStorage() { var NextStorageDriver = require('_').find([ - require('Storage/LocalDriver/LocalStorage'), - require('Storage/LocalDriver/Cookie') + require('Common/ClientStorageDriver/LocalStorage'), + require('Common/ClientStorageDriver/Cookie') ], function (NextStorageDriver) { return NextStorageDriver && NextStorageDriver.supported(); }) @@ -28,14 +28,14 @@ /** * @type {LocalStorageDriver|CookieDriver|null} */ - LocalStorage.prototype.oDriver = null; + ClientStorage.prototype.oDriver = null; /** * @param {number} iKey * @param {*} mData * @return {boolean} */ - LocalStorage.prototype.set = function (iKey, mData) + ClientStorage.prototype.set = function (iKey, mData) { return this.oDriver ? this.oDriver.set('p' + iKey, mData) : false; }; @@ -44,11 +44,11 @@ * @param {number} iKey * @return {*} */ - LocalStorage.prototype.get = function (iKey) + ClientStorage.prototype.get = function (iKey) { return this.oDriver ? this.oDriver.get('p' + iKey) : null; }; - module.exports = new LocalStorage(); + module.exports = new ClientStorage(); }()); \ No newline at end of file diff --git a/dev/Storage/User/Data.js b/dev/Storage/User/Data.js index 1762f284f..836011c87 100644 --- a/dev/Storage/User/Data.js +++ b/dev/Storage/User/Data.js @@ -17,6 +17,8 @@ Links = require('Common/Links'), Translator = require('Common/Translator'), + SettingsUserStore = require('Stores/User/Settings'), + Settings = require('Storage/Settings'), Cache = require('Storage/User/Cache'), @@ -24,18 +26,14 @@ MessageModel = require('Model/Message'), - Local = require('Storage/Local'), - AbstractData = require('Storage/AbstractData') + Local = require('Storage/Client') ; /** * @constructor - * @extends AbstractData */ function DataUserStorage() { - AbstractData.call(this); - var fRemoveSystemFolderType = function (observable) { return function () { @@ -272,7 +270,7 @@ this.messageListPageCount = ko.computed(function () { var iPage = window.Math.ceil(this.messageListCount() / - require('Stores/UserSettings').messagesPerPage()); + SettingsUserStore.messagesPerPage()); return 0 >= iPage ? 1 : iPage; }, this); @@ -328,13 +326,13 @@ this.messageFullScreenMode(false); this.hideMessageBodies(); - if (Enums.Layout.NoPreview === require('Stores/UserSettings').layout() && + if (Enums.Layout.NoPreview === SettingsUserStore.layout() && -1 < window.location.hash.indexOf('message-preview')) { require('App/User').historyBack(); } } - else if (Enums.Layout.NoPreview === require('Stores/UserSettings').layout()) + else if (Enums.Layout.NoPreview === SettingsUserStore.layout()) { this.message.focused(true); } @@ -348,7 +346,7 @@ } else if (Enums.KeyState.MessageView === Globals.keyScope()) { - if (Enums.Layout.NoPreview === require('Stores/UserSettings').layout() && this.message()) + if (Enums.Layout.NoPreview === SettingsUserStore.layout() && this.message()) { Globals.keyScope(Enums.KeyState.MessageView); } @@ -451,8 +449,6 @@ this.purgeMessageBodyCacheThrottle = _.throttle(this.purgeMessageBodyCache, 1000 * 30); } - _.extend(DataUserStorage.prototype, AbstractData.prototype); - DataUserStorage.prototype.purgeMessageBodyCache = function() { var @@ -487,8 +483,6 @@ DataUserStorage.prototype.populateDataOnStart = function() { - AbstractData.prototype.populateDataOnStart.call(this); - this.accountEmail(Settings.settingsGet('Email')); this.accountIncLogin(Settings.settingsGet('IncLogin')); this.accountOutLogin(Settings.settingsGet('OutLogin')); @@ -519,52 +513,18 @@ var iIndex = 0, iLen = aNewMessages.length, - fNotificationHelper = function (sImageSrc, sTitle, sText) - { - var - NotificationSettingsStore = require('Stores/NotificationSettings'), - NotificationClass = NotificationSettingsStore.notificationClass(), - oNotification = null - ; - - if (NotificationClass && NotificationSettingsStore.enableDesktopNotification()) - { - oNotification = new NotificationClass(sTitle, { - 'body': sText, - 'icon': sImageSrc - }); - - if (oNotification) - { - if (oNotification.show) - { - oNotification.show(); - } - - window.setTimeout((function (oLocalNotifications) { - return function () { - if (oLocalNotifications.cancel) - { - oLocalNotifications.cancel(); - } - else if (oLocalNotifications.close) - { - oLocalNotifications.close(); - } - }; - }(oNotification)), 7000); - } - } - } + NotificationStore = require('Stores/User/Notification') ; _.each(aNewMessages, function (oItem) { Cache.addNewMessageCache(sFolder, oItem.Uid); }); + NotificationStore.playSoundNotification(); + if (3 < iLen) { - fNotificationHelper( + NotificationStore.displayDesktopNotification( Links.notificationMailIcon(), this.accountEmail(), Translator.i18n('MESSAGE_LIST/NEW_MESSAGE_NOTIFICATION', { @@ -576,7 +536,7 @@ { for (; iIndex < iLen; iIndex++) { - fNotificationHelper( + NotificationStore.displayDesktopNotification( Links.notificationMailIcon(), MessageModel.emailsToLine(MessageModel.initEmailsFromJson(aNewMessages[iIndex].From), false), aNewMessages[iIndex].Subject @@ -907,7 +867,7 @@ oMessage.showInternalImages(true); } - if (oMessage.hasImages() && this.showImages()) + if (oMessage.hasImages() && SettingsUserStore.showImages()) { oMessage.showExternalImages(true); } diff --git a/dev/Storage/User/Remote.js b/dev/Storage/User/Remote.js index 285229edb..11127a787 100644 --- a/dev/Storage/User/Remote.js +++ b/dev/Storage/User/Remote.js @@ -10,6 +10,8 @@ Consts = require('Common/Consts'), Base64 = require('Common/Base64'), + SettingsUserStore = require('Stores/User/Settings'), + Settings = require('Storage/Settings'), Cache = require('Storage/User/Cache'), Data = require('Storage/User/Data'), @@ -285,7 +287,7 @@ Data.projectHash(), sFolderHash, Cache.getFolderInboxName() === sFolderFullNameRaw ? Cache.getFolderUidNext(sFolderFullNameRaw) : '', - Data.threading() && Data.useThreads() ? '1' : '0', + Data.threading() && SettingsUserStore.useThreads() ? '1' : '0', Data.threading() && sFolderFullNameRaw === Data.messageListThreadFolder() ? Data.messageListThreadUids().join(',') : '' ].join(String.fromCharCode(0))), bSilent ? [] : ['MessageList']); } @@ -297,7 +299,7 @@ 'Limit': iLimit, 'Search': sSearch, 'UidNext': Cache.getFolderInboxName() === sFolderFullNameRaw ? Cache.getFolderUidNext(sFolderFullNameRaw) : '', - 'UseThreads': Data.threading() && Data.useThreads() ? '1' : '0', + 'UseThreads': Data.threading() && SettingsUserStore.useThreads() ? '1' : '0', 'ExpandedThreadUid': Data.threading() && sFolderFullNameRaw === Data.messageListThreadFolder() ? Data.messageListThreadUids().join(',') : '' }, '' === sSearch ? Consts.Defaults.DefaultAjaxTimeout : Consts.Defaults.SearchAjaxTimeout, '', bSilent ? [] : ['MessageList']); } @@ -332,7 +334,7 @@ sFolderFullNameRaw, iUid, Data.projectHash(), - Data.threading() && Data.useThreads() ? '1' : '0' + Data.threading() && SettingsUserStore.useThreads() ? '1' : '0' ].join(String.fromCharCode(0))), ['Message']); return true; @@ -411,7 +413,7 @@ 'UidNext': Cache.getFolderInboxName() === sFolder ? Cache.getFolderUidNext(sFolder) : '' }); } - else if (Data.useThreads()) + else if (SettingsUserStore.useThreads()) { require('App/User').reloadFlagsCurrentMessageListAndMessageFromCache(); } diff --git a/dev/Stores/Admin/App.js b/dev/Stores/Admin/App.js new file mode 100644 index 000000000..2249918a8 --- /dev/null +++ b/dev/Stores/Admin/App.js @@ -0,0 +1,43 @@ + +(function () { + + 'use strict'; + + var + ko = require('ko'), + + Settings = require('Storage/Settings') + ; + + /** + * @constructor + */ + function AppAdminStore() + { + // same + this.allowLanguagesOnSettings = ko.observable(true); + this.allowLanguagesOnLogin = ko.observable(true); + // ---- + + this.determineUserLanguage = ko.observable(false); + this.determineUserDomain = ko.observable(false); + + this.weakPassword = ko.observable(false); + this.useLocalProxyForExternalImages = ko.observable(false); + } + + AppAdminStore.prototype.populate = function() + { + this.allowLanguagesOnLogin(!!Settings.settingsGet('AllowLanguagesOnLogin')); + this.allowLanguagesOnSettings(!!Settings.settingsGet('AllowLanguagesOnSettings')); + + this.determineUserLanguage(!!Settings.settingsGet('DetermineUserLanguage')); + this.determineUserDomain(!!Settings.settingsGet('DetermineUserDomain')); + + this.weakPassword(!!Settings.settingsGet('WeakPassword')); + this.useLocalProxyForExternalImages(!!Settings.settingsGet('UseLocalProxyForExternalImages')); + }; + + module.exports = new AppAdminStore(); + +}()); diff --git a/dev/Stores/Admin/Capa.js b/dev/Stores/Admin/Capa.js new file mode 100644 index 000000000..65f6f9aeb --- /dev/null +++ b/dev/Stores/Admin/Capa.js @@ -0,0 +1,45 @@ + +(function () { + + 'use strict'; + + var + ko = require('ko'), + + Enums = require('Common/Enums'), + + Settings = require('Storage/Settings') + ; + + /** + * @constructor + */ + function CapaAdminStore() + { + this.additionalAccounts = ko.observable(false); + this.additionalIdentities = ko.observable(false); + this.gravatar = ko.observable(false); + this.attachmentThumbnails = ko.observable(false); + this.sieve = ko.observable(false); + this.themes = ko.observable(true); + this.userBackground = ko.observable(false); + this.openPGP = ko.observable(false); + this.twoFactorAuth = ko.observable(false); + } + + CapaAdminStore.prototype.populate = function() + { + this.additionalAccounts(Settings.capa(Enums.Capa.AdditionalAccounts)); + this.additionalIdentities(Settings.capa(Enums.Capa.AdditionalIdentities)); + this.gravatar(Settings.capa(Enums.Capa.Gravatar)); + this.attachmentThumbnails(Settings.capa(Enums.Capa.AttachmentThumbnails)); + this.sieve(Settings.capa(Enums.Capa.Sieve)); + this.themes(Settings.capa(Enums.Capa.Themes)); + this.userBackground(Settings.capa(Enums.Capa.UserBackground)); + this.openPGP(Settings.capa(Enums.Capa.OpenPGP)); + this.twoFactorAuth(Settings.capa(Enums.Capa.TwoFactor)); + }; + + module.exports = new CapaAdminStore(); + +}()); diff --git a/dev/Stores/Admin/Core.js b/dev/Stores/Admin/Core.js new file mode 100644 index 000000000..6c08eac60 --- /dev/null +++ b/dev/Stores/Admin/Core.js @@ -0,0 +1,29 @@ + +(function () { + + 'use strict'; + + var + ko = require('ko') + ; + + /** + * @constructor + */ + function CoreAdminStore() + { + this.coreReal = ko.observable(true); + this.coreChannel = ko.observable('stable'); + this.coreType = ko.observable('stable'); + this.coreUpdatable = ko.observable(true); + this.coreAccess = ko.observable(true); + this.coreChecking = ko.observable(false).extend({'throttle': 100}); + this.coreUpdating = ko.observable(false).extend({'throttle': 100}); + this.coreRemoteVersion = ko.observable(''); + this.coreRemoteRelease = ko.observable(''); + this.coreVersionCompare = ko.observable(-2); + } + + module.exports = new CoreAdminStore(); + +}()); diff --git a/dev/Stores/Admin/Domain.js b/dev/Stores/Admin/Domain.js new file mode 100644 index 000000000..2fee09cc2 --- /dev/null +++ b/dev/Stores/Admin/Domain.js @@ -0,0 +1,21 @@ + +(function () { + + 'use strict'; + + var + ko = require('ko') + ; + + /** + * @constructor + */ + function DomainAdminStore() + { + this.collection = ko.observableArray([]); + this.collection.loading = ko.observable(false).extend({'throttle': 100}); + } + + module.exports = new DomainAdminStore(); + +}()); diff --git a/dev/Stores/Admin/License.js b/dev/Stores/Admin/License.js new file mode 100644 index 000000000..b2adc2a74 --- /dev/null +++ b/dev/Stores/Admin/License.js @@ -0,0 +1,26 @@ + +(function () { + + 'use strict'; + + var + ko = require('ko') + ; + + /** + * @constructor + */ + function LicenseAdminStore() + { + this.licensing = ko.observable(false); + this.licensingProcess = ko.observable(false); + this.licenseValid = ko.observable(false); + this.licenseExpired = ko.observable(0); + this.licenseError = ko.observable(''); + + this.licenseTrigger = ko.observable(false); + } + + module.exports = new LicenseAdminStore(); + +}()); diff --git a/dev/Stores/Admin/Package.js b/dev/Stores/Admin/Package.js new file mode 100644 index 000000000..791b660dd --- /dev/null +++ b/dev/Stores/Admin/Package.js @@ -0,0 +1,24 @@ + +(function () { + + 'use strict'; + + var + ko = require('ko') + ; + + /** + * @constructor + */ + function PluginAdminStore() + { + this.collection = ko.observableArray([]); + this.collection.loading = ko.observable(false).extend({'throttle': 100}); + + this.packagesReal = ko.observable(true); + this.packagesMainUpdatable = ko.observable(true); + } + + module.exports = new PluginAdminStore(); + +}()); diff --git a/dev/Stores/Admin/Plugin.js b/dev/Stores/Admin/Plugin.js new file mode 100644 index 000000000..c29ee2ea3 --- /dev/null +++ b/dev/Stores/Admin/Plugin.js @@ -0,0 +1,22 @@ + +(function () { + + 'use strict'; + + var + ko = require('ko') + ; + + /** + * @constructor + */ + function PluginAdminStore() + { + this.collection = ko.observableArray([]); + this.collection.loading = ko.observable(false).extend({'throttle': 100}); + this.collection.error = ko.observable(''); + } + + module.exports = new PluginAdminStore(); + +}()); diff --git a/dev/Stores/Language.js b/dev/Stores/Language.js new file mode 100644 index 000000000..fa521c456 --- /dev/null +++ b/dev/Stores/Language.js @@ -0,0 +1,35 @@ + +(function () { + + 'use strict'; + + var + ko = require('ko'), + + Utils = require('Common/Utils'), + + Settings = require('Storage/Settings') + ; + + /** + * @constructor + */ + function LanguageStore() + { + this.languages = ko.observableArray([]); + + this.language = ko.observable('') + .extend({'limitedList': this.languages}); + } + + LanguageStore.prototype.populate = function () + { + var aLanguages = Settings.settingsGet('Languages'); + + this.languages(Utils.isArray(aLanguages) ? aLanguages : []); + this.language(Settings.settingsGet('Language')); + }; + + module.exports = new LanguageStore(); + +}()); diff --git a/dev/Stores/Social.js b/dev/Stores/Social.js index d290f7fb4..0e870ce5b 100644 --- a/dev/Stores/Social.js +++ b/dev/Stores/Social.js @@ -12,7 +12,6 @@ */ function SocialStore() { - // TODO this.google = {}; this.twitter = {}; this.facebook = {}; diff --git a/dev/Stores/Theme.js b/dev/Stores/Theme.js new file mode 100644 index 000000000..ba459f09e --- /dev/null +++ b/dev/Stores/Theme.js @@ -0,0 +1,39 @@ + +(function () { + + 'use strict'; + + var + ko = require('ko'), + + Utils = require('Common/Utils'), + + Settings = require('Storage/Settings') + ; + + /** + * @constructor + */ + function ThemeStore() + { + this.themes = ko.observableArray([]); + this.themeBackgroundName = ko.observable(''); + this.themeBackgroundHash = ko.observable(''); + + this.theme = ko.observable('') + .extend({'limitedList': this.themes}); + } + + ThemeStore.prototype.populate = function () + { + var aThemes = Settings.settingsGet('Themes'); + + this.themes(Utils.isArray(aThemes) ? aThemes : []); + this.theme(Settings.settingsGet('Theme')); + this.themeBackgroundName(Settings.settingsGet('UserBackgroundName')); + this.themeBackgroundHash(Settings.settingsGet('UserBackgroundHash')); + }; + + module.exports = new ThemeStore(); + +}()); diff --git a/dev/Stores/User/App.js b/dev/Stores/User/App.js new file mode 100644 index 000000000..7df00e1d8 --- /dev/null +++ b/dev/Stores/User/App.js @@ -0,0 +1,57 @@ + +(function () { + + 'use strict'; + + var + ko = require('ko'), + + Globals = require('Common/Globals'), + + Settings = require('Storage/Settings') + ; + + /** + * @constructor + */ + function AppUserStore() + { + // same + this.allowLanguagesOnSettings = ko.observable(true); + this.allowLanguagesOnLogin = ko.observable(true); + // ---- + + this.contactsAutosave = ko.observable(false); + this.useLocalProxyForExternalImages = ko.observable(false); + + this.contactsIsAllowed = ko.observable(false); + + this.interfaceAnimation = ko.observable(true); + + this.interfaceAnimation.subscribe(function (bValue) { + if (Globals.bMobileDevice || !bValue) + { + Globals.$html.removeClass('rl-anim').addClass('no-rl-anim'); + } + else + { + Globals.$html.removeClass('no-rl-anim').addClass('rl-anim'); + } + }); + + this.interfaceAnimation.valueHasMutated(); + } + + AppUserStore.prototype.populate = function() + { + this.allowLanguagesOnLogin(!!Settings.settingsGet('AllowLanguagesOnLogin')); + this.allowLanguagesOnSettings(!!Settings.settingsGet('AllowLanguagesOnSettings')); + + this.useLocalProxyForExternalImages(!!Settings.settingsGet('UseLocalProxyForExternalImages')); + this.contactsIsAllowed(!!Settings.settingsGet('ContactsIsAllowed')); + this.interfaceAnimation(!!Settings.settingsGet('InterfaceAnimation')); + }; + + module.exports = new AppUserStore(); + +}()); diff --git a/dev/Stores/Filter.js b/dev/Stores/User/Filter.js similarity index 85% rename from dev/Stores/Filter.js rename to dev/Stores/User/Filter.js index 894519249..7357142c1 100644 --- a/dev/Stores/Filter.js +++ b/dev/Stores/User/Filter.js @@ -10,7 +10,7 @@ /** * @constructor */ - function FilterStore() + function FilterUserStore() { this.capa = ko.observable(''); this.modules = ko.observable({}); @@ -23,6 +23,6 @@ this.raw = ko.observable(''); } - module.exports = new FilterStore(); + module.exports = new FilterUserStore(); }()); diff --git a/dev/Stores/NotificationSettings.js b/dev/Stores/User/Notification.js similarity index 63% rename from dev/Stores/NotificationSettings.js rename to dev/Stores/User/Notification.js index edd86ceb9..2f5da49d6 100644 --- a/dev/Stores/NotificationSettings.js +++ b/dev/Stores/User/Notification.js @@ -6,8 +6,10 @@ var window = require('window'), ko = require('ko'), + buzz = require('buzz'), Enums = require('Common/Enums'), + Links = require('Common/Links'), Settings = require('Storage/Settings') ; @@ -15,10 +17,15 @@ /** * @constructor */ - function NotificationSettings() + function NotificationUserStore() { var self = this; + this.buzz = null; + + this.enableSoundNotification = ko.observable(true); + this.soundNotificationIsSupported = ko.observable(false); + this.allowDesktopNotification = ko.observable(false); this.desktopNotificationPermisions = ko.computed(function () { @@ -120,9 +127,11 @@ } this.computedProperies(); + + this.initNotificationPlayer(); } - NotificationSettings.prototype.computedProperies = function () + NotificationUserStore.prototype.computedProperies = function () { this.isDesktopNotificationSupported = ko.computed(function () { return Enums.DesktopNotification.NotSupported !== this.desktopNotificationPermisions(); @@ -134,19 +143,80 @@ }, this); }; - NotificationSettings.prototype.populate = function () + NotificationUserStore.prototype.initNotificationPlayer = function () { + if (buzz && buzz.isSupported() && (buzz.isOGGSupported() || buzz.isMP3Supported())) + { + this.soundNotificationIsSupported(true); + + this.buzz = new buzz.sound(Links.sound('new-mail'), { + formats: ['ogg', 'mp3'] + }); + } + else + { + this.enableSoundNotification(false); + this.soundNotificationIsSupported(false); + } + }; + + NotificationUserStore.prototype.playSoundNotification = function (bSkipSetting) + { + if (this.buzz && (bSkipSetting ? true : this.enableSoundNotification())) + { + this.buzz.play(); + } + }; + + NotificationUserStore.prototype.displayDesktopNotification = function (sImageSrc, sTitle, sText) + { + if (this.enableDesktopNotification()) + { + var + NotificationClass = this.notificationClass(), + oNotification = NotificationClass ? new NotificationClass(sTitle, { + 'body': sText, + 'icon': sImageSrc + }) : null + ; + + if (oNotification) + { + if (oNotification.show) + { + oNotification.show(); + } + + window.setTimeout((function (oLocalNotifications) { + return function () { + if (oLocalNotifications.cancel) + { + oLocalNotifications.cancel(); + } + else if (oLocalNotifications.close) + { + oLocalNotifications.close(); + } + }; + }(oNotification)), 7000); + } + } + }; + + NotificationUserStore.prototype.populate = function () + { + this.enableSoundNotification(!!Settings.settingsGet('SoundNotification')); this.enableDesktopNotification(!!Settings.settingsGet('DesktopNotifications')); }; /** * @return {*|null} */ - NotificationSettings.prototype.notificationClass = function () + NotificationUserStore.prototype.notificationClass = function () { return window.Notification && window.Notification.requestPermission ? window.Notification : null; }; - module.exports = new NotificationSettings(); + module.exports = new NotificationUserStore(); }()); diff --git a/dev/Stores/Quota.js b/dev/Stores/User/Quota.js similarity index 79% rename from dev/Stores/Quota.js rename to dev/Stores/User/Quota.js index 7e74df46d..5f21638bf 100644 --- a/dev/Stores/Quota.js +++ b/dev/Stores/User/Quota.js @@ -11,7 +11,7 @@ /** * @constructor */ - function QuotaStore() + function QuotaUserStore() { this.quota = ko.observable(0); this.usage = ko.observable(0); @@ -32,12 +32,12 @@ * @param {number} iQuota * @param {number} iUsage */ - QuotaStore.prototype.populateData = function(iQuota, iUsage) + QuotaUserStore.prototype.populateData = function(iQuota, iUsage) { this.quota(iQuota * 1024); this.usage(iUsage * 1024); }; - module.exports = new QuotaStore(); + module.exports = new QuotaUserStore(); }()); diff --git a/dev/Stores/UserSettings.js b/dev/Stores/User/Settings.js similarity index 54% rename from dev/Stores/UserSettings.js rename to dev/Stores/User/Settings.js index 68551c780..91c92b1b2 100644 --- a/dev/Stores/UserSettings.js +++ b/dev/Stores/User/Settings.js @@ -16,7 +16,7 @@ /** * @constructor */ - function UserSettingsStore() + function SettingsUserStore() { this.layout = ko.observable(Enums.Layout.SidePreview) .extend({'limitedList': [ @@ -29,52 +29,37 @@ Enums.EditorDefaultType.HtmlForced, Enums.EditorDefaultType.PlainForced ]}); - this.languages = ko.observableArray([]); - - this.language = ko.observable('') - .extend({'limitedList': this.languages}); - - this.themes = ko.observableArray([]); - this.themeBackgroundName = ko.observable(''); - this.themeBackgroundHash = ko.observable(''); - - this.theme = ko.observable('') - .extend({'limitedList': this.themes}); - this.messagesPerPage = ko.observable(Consts.Defaults.MessagesPerPage) .extend({'limitedList': Consts.Defaults.MessagesPerPageArray}); + this.showImages = ko.observable(false); + this.useCheckboxesInList = ko.observable(true); + this.useThreads = ko.observable(false); + this.replySameFolder = ko.observable(false); + this.computedProperies(); } - UserSettingsStore.prototype.computedProperies = function () + SettingsUserStore.prototype.computedProperies = function () { this.usePreviewPane = ko.computed(function () { return Enums.Layout.NoPreview !== this.layout(); }, this); }; - UserSettingsStore.prototype.populate = function () + SettingsUserStore.prototype.populate = function () { - var - aLanguages = Settings.settingsGet('Languages'), - aThemes = Settings.settingsGet('Themes') - ; - this.layout(Utils.pInt(Settings.settingsGet('Layout'))); this.editorDefaultType(Settings.settingsGet('EditorDefaultType')); - this.languages(Utils.isArray(aLanguages) ? aLanguages : []); - this.language(Settings.settingsGet('Language')); - - this.themes(Utils.isArray(aThemes) ? aThemes : []); - this.theme(Settings.settingsGet('Theme')); - this.themeBackgroundName(Settings.settingsGet('UserBackgroundName')); - this.themeBackgroundHash(Settings.settingsGet('UserBackgroundHash')); - this.messagesPerPage(Settings.settingsGet('MPP')); + + this.showImages(!!Settings.settingsGet('ShowImages')); + this.useCheckboxesInList(!!Settings.settingsGet('UseCheckboxesInList')); + this.useThreads(!!Settings.settingsGet('UseThreads')); + this.replySameFolder(!!Settings.settingsGet('ReplySameFolder')); }; - module.exports = new UserSettingsStore(); + module.exports = new SettingsUserStore(); }()); diff --git a/dev/Styles/_FontasticToBoot.less b/dev/Styles/_FontasticToBoot.less index 2a67de993..36cfb3c1f 100644 --- a/dev/Styles/_FontasticToBoot.less +++ b/dev/Styles/_FontasticToBoot.less @@ -22,6 +22,11 @@ font-size: 24px; } +.iconsize24 { + line-height: 20px; + font-size: 20px; +} + /* White icons with optional class, or on hover/active states of certain elements */ .icon-white, .nav > .active > a > [class^="icon-"], diff --git a/dev/View/Admin/Settings/Pane.js b/dev/View/Admin/Settings/Pane.js index 6e93c9e91..56e4f50c2 100644 --- a/dev/View/Admin/Settings/Pane.js +++ b/dev/View/Admin/Settings/Pane.js @@ -8,7 +8,6 @@ ko = require('ko'), Settings = require('Storage/Settings'), - Data = require('Storage/Admin/Data'), Remote = require('Storage/Admin/Remote'), kn = require('Knoin/Knoin'), @@ -26,9 +25,20 @@ this.adminDomain = ko.observable(Settings.settingsGet('AdminDomain')); this.version = ko.observable(Settings.settingsGet('Version')); - this.adminManLoadingVisibility = Data.adminManLoadingVisibility; this.capa = !!Settings.settingsGet('PremType'); + this.adminManLoading = ko.computed(function () { + return '000' !== [ + require('Stores/Admin/Domain').collection.loading() ? '1' : '0', + require('Stores/Admin/Plugin').collection.loading() ? '1' : '0', + require('Stores/Admin/Package').collection.loading() ? '1' : '0' + ].join(''); + }, this); + + this.adminManLoadingVisibility = ko.computed(function () { + return this.adminManLoading() ? 'visible' : 'hidden'; + }, this).extend({'rateLimit': 300}); + kn.constructorEnd(this); } diff --git a/dev/View/Popup/Activate.js b/dev/View/Popup/Activate.js index bc5deeb9d..aa0e9fe37 100644 --- a/dev/View/Popup/Activate.js +++ b/dev/View/Popup/Activate.js @@ -12,8 +12,8 @@ Translator = require('Common/Translator'), Settings = require('Storage/Settings'), - Data = require('Storage/Admin/Data'), Remote = require('Storage/Admin/Remote'), + LicenseStore = require('Stores/Admin/License'), kn = require('Knoin/Knoin'), AbstractView = require('Knoin/AbstractView') @@ -34,7 +34,7 @@ this.key.focus = ko.observable(false); this.activationSuccessed = ko.observable(false); - this.licenseTrigger = Data.licenseTrigger; + this.licenseTrigger = LicenseStore.licenseTrigger; this.activateProcess = ko.observable(false); this.activateText = ko.observable(''); diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js index 5f5b0f9ee..9bfd53462 100644 --- a/dev/View/Popup/Compose.js +++ b/dev/View/Popup/Compose.js @@ -21,8 +21,9 @@ HtmlEditor = require('Common/HtmlEditor'), Translator = require('Common/Translator'), + AppStore = require('Stores/User/App'), + SettingsUserStore = require('Stores/User/Settings'), SocialStore = require('Stores/Social'), - UserSettingsStore = require('Stores/UserSettings'), Settings = require('Storage/Settings'), Data = require('Storage/User/Data'), @@ -51,7 +52,7 @@ this.bCapaAdditionalIdentities = Settings.capa(Enums.Capa.AdditionalIdentities); - this.allowContacts = !!Settings.settingsGet('ContactsIsAllowed'); + this.allowContacts = !!AppStore.contactsIsAllowed(); var self = this, @@ -65,7 +66,7 @@ this.bSkipNextHide = false; this.composeInEdit = Data.composeInEdit; - this.editorDefaultType = UserSettingsStore.editorDefaultType; + this.editorDefaultType = SettingsUserStore.editorDefaultType; this.capaOpenPGP = Data.capaOpenPGP; @@ -280,7 +281,7 @@ } else { - if (Data.replySameFolder()) + if (SettingsUserStore.replySameFolder()) { if (Utils.isArray(this.aDraftInfo) && 3 === this.aDraftInfo.length && Utils.isNormal(this.aDraftInfo[2]) && 0 < this.aDraftInfo[2].length) { diff --git a/dev/View/Popup/Contacts.js b/dev/View/Popup/Contacts.js index 8844891e1..7f0c23c6a 100644 --- a/dev/View/Popup/Contacts.js +++ b/dev/View/Popup/Contacts.js @@ -18,6 +18,8 @@ Links = require('Common/Links'), Translator = require('Common/Translator'), + SettingsUserStore = require('Stores/User/Settings'), + Data = require('Storage/User/Data'), Remote = require('Storage/User/Remote'), @@ -173,7 +175,7 @@ this.viewSaving = ko.observable(false); - this.useCheckboxesInList = Data.useCheckboxesInList; + this.useCheckboxesInList = SettingsUserStore.useCheckboxesInList; this.search.subscribe(function () { this.reloadContactList(); diff --git a/dev/View/Popup/Domain.js b/dev/View/Popup/Domain.js index cbd993bb8..4bc748f6d 100644 --- a/dev/View/Popup/Domain.js +++ b/dev/View/Popup/Domain.js @@ -11,8 +11,9 @@ Consts = require('Common/Consts'), Utils = require('Common/Utils'), + CapaAdminStore = require('Stores/Admin/Capa'), + Remote = require('Storage/Admin/Remote'), - Settings = require('Storage/Settings'), kn = require('Knoin/Knoin'), AbstractView = require('Knoin/AbstractView') @@ -63,7 +64,7 @@ this.name = ko.observable(''); this.name.focused = ko.observable(false); - this.allowSieve = ko.observable(Settings.capa(Enums.Capa.Sieve)); + this.allowSieve = CapaAdminStore.sieve; this.imapServer = ko.observable(''); this.imapPort = ko.observable('' + Consts.Values.ImapDefaulPort); diff --git a/dev/View/Popup/Filter.js b/dev/View/Popup/Filter.js index 95a081dec..7d03ada3a 100644 --- a/dev/View/Popup/Filter.js +++ b/dev/View/Popup/Filter.js @@ -13,7 +13,7 @@ Data = require('Storage/User/Data'), - FilterStore = require('Stores/Filter'), + FilterStore = require('Stores/User/Filter'), kn = require('Knoin/Knoin'), AbstractView = require('Knoin/AbstractView') diff --git a/dev/View/Popup/Languages.js b/dev/View/Popup/Languages.js index d7b4cf9ca..b8f23dda0 100644 --- a/dev/View/Popup/Languages.js +++ b/dev/View/Popup/Languages.js @@ -21,12 +21,12 @@ { AbstractView.call(this, 'Popups', 'PopupsLanguages'); - this.UserSettingsStore = require('Stores/UserSettings'); + this.LanguageStore = require('Stores/Language'); this.exp = ko.observable(false); this.languages = ko.computed(function () { - return _.map(this.UserSettingsStore.languages(), function (sLanguage) { + return _.map(this.LanguageStore.languages(), function (sLanguage) { return { 'key': sLanguage, 'selected': ko.observable(false), @@ -35,7 +35,7 @@ }); }, this); - this.UserSettingsStore.language.subscribe(function () { + this.LanguageStore.language.subscribe(function () { this.resetMainLanguage(); }, this); @@ -53,7 +53,7 @@ LanguagesPopupView.prototype.resetMainLanguage = function () { - var sCurrent = this.UserSettingsStore.language(); + var sCurrent = this.LanguageStore.language(); _.each(this.languages(), function (oItem) { oItem['selected'](oItem['key'] === sCurrent); }); @@ -73,7 +73,7 @@ LanguagesPopupView.prototype.changeLanguage = function (sLang) { - this.UserSettingsStore.language(sLang); + this.LanguageStore.language(sLang); this.cancelCommand(); }; diff --git a/dev/View/User/Login.js b/dev/View/User/Login.js index d48be01dc..39ed38b48 100644 --- a/dev/View/User/Login.js +++ b/dev/View/User/Login.js @@ -17,7 +17,8 @@ Plugins = require('Common/Plugins'), - UserSettingsStore = require('Stores/UserSettings'), + LanguageStore = require('Stores/Language'), + AppStore = require('Stores/User/App'), Settings = require('Storage/Settings'), Data = require('Storage/User/Data'), @@ -88,10 +89,10 @@ } }, this); - this.allowLanguagesOnLogin = Data.allowLanguagesOnLogin; + this.allowLanguagesOnLogin = AppStore.allowLanguagesOnLogin; this.langRequest = ko.observable(false); - this.language = UserSettingsStore.language; + this.language = LanguageStore.language; this.bSendLanguage = false; @@ -307,7 +308,7 @@ if (Settings.settingsGet('UserLanguage')) { - $.cookie('rllang', UserSettingsStore.language(), {'expires': 30}); + $.cookie('rllang', LanguageStore.language(), {'expires': 30}); } }, this), 100); @@ -376,7 +377,7 @@ } _.delay(function () { - UserSettingsStore.language.subscribe(function (sValue) { + LanguageStore.language.subscribe(function (sValue) { self.langRequest(true); diff --git a/dev/View/User/MailBox/FolderList.js b/dev/View/User/MailBox/FolderList.js index c61802640..f686cf7c4 100644 --- a/dev/View/User/MailBox/FolderList.js +++ b/dev/View/User/MailBox/FolderList.js @@ -15,9 +15,9 @@ Globals = require('Common/Globals'), Links = require('Common/Links'), - UserSettingsStore = require('Stores/UserSettings'), + AppStore = require('Stores/User/App'), + SettingsUserStore = require('Stores/User/Settings'), - Settings = require('Storage/Settings'), Cache = require('Storage/User/Cache'), Data = require('Storage/User/Data'), @@ -47,7 +47,7 @@ this.iDropOverTimer = 0; - this.allowContacts = !!Settings.settingsGet('ContactsIsAllowed'); + this.allowContacts = !!AppStore.contactsIsAllowed(); kn.constructorEnd(this); } @@ -90,7 +90,7 @@ if (oFolder) { - if (Enums.Layout.NoPreview === UserSettingsStore.layout()) + if (Enums.Layout.NoPreview === SettingsUserStore.layout()) { Data.message(null); } diff --git a/dev/View/User/MailBox/MessageList.js b/dev/View/User/MailBox/MessageList.js index 2e93d4601..4f14d0132 100644 --- a/dev/View/User/MailBox/MessageList.js +++ b/dev/View/User/MailBox/MessageList.js @@ -20,8 +20,8 @@ Selector = require('Common/Selector'), Translator = require('Common/Translator'), - QuotaStore = require('Stores/Quota'), - UserSettingsStore = require('Stores/UserSettings'), + QuotaStore = require('Stores/User/Quota'), + SettingsStore = require('Stores/User/Settings'), Settings = require('Storage/Settings'), Cache = require('Storage/User/Cache'), @@ -57,7 +57,7 @@ this.messageListError = Data.messageListError; this.folderMenuForMove = Data.folderMenuForMove; - this.useCheckboxesInList = Data.useCheckboxesInList; + this.useCheckboxesInList = SettingsStore.useCheckboxesInList; this.mainMessageListSearch = Data.mainMessageListSearch; this.messageListEndFolder = Data.messageListEndFolder; @@ -85,7 +85,7 @@ this.dragOverBodyArea = ko.observable(null); this.messageListItemTemplate = ko.computed(function () { - return Enums.Layout.SidePreview === UserSettingsStore.layout() ? + return Enums.Layout.SidePreview === SettingsStore.layout() ? 'MailMessageListItem' : 'MailMessageListItemNoPreviewPane'; }); @@ -231,7 +231,7 @@ Data.message(Data.staticMessageList.populateByMessageListItem(oMessage)); this.populateMessageBody(Data.message()); - if (Enums.Layout.NoPreview === UserSettingsStore.layout()) + if (Enums.Layout.NoPreview === SettingsStore.layout()) { kn.setHash(Links.messagePreview(), true); Data.message.focused(true); @@ -251,11 +251,11 @@ this.selector.scrollToTop(); }, this); - UserSettingsStore.layout.subscribe(function (mValue) { + SettingsStore.layout.subscribe(function (mValue) { this.selector.autoSelect(Enums.Layout.NoPreview !== mValue); }, this); - UserSettingsStore.layout.valueHasMutated(); + SettingsStore.layout.valueHasMutated(); Events .sub('mailbox.message-list.selector.go-down', function () { @@ -815,14 +815,12 @@ return false; }); - // TODO key('ctrl+left, command+left', Enums.KeyState.MessageView, function () { - return false; + return false; // TODO }); - // TODO key('ctrl+right, command+right', Enums.KeyState.MessageView, function () { - return false; + return false; // TODO }); }; diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index bc3b8ac7b..00084470e 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -19,9 +19,9 @@ Events = require('Common/Events'), Translator = require('Common/Translator'), - UserSettingsStore = require('Stores/UserSettings'), + SettingsUserStore = require('Stores/User/Settings'), - Local = require('Storage/Local'), + Local = require('Storage/Client'), Cache = require('Storage/User/Cache'), Data = require('Storage/User/Data'), Remote = require('Storage/User/Remote'), @@ -62,10 +62,10 @@ this.messageLoading = Data.messageLoading; this.messageLoadingThrottle = Data.messageLoadingThrottle; this.messagesBodiesDom = Data.messagesBodiesDom; - this.useThreads = Data.useThreads; - this.replySameFolder = Data.replySameFolder; - this.layout = UserSettingsStore.layout; - this.usePreviewPane = UserSettingsStore.usePreviewPane; + this.useThreads = SettingsUserStore.useThreads; + this.replySameFolder = SettingsUserStore.replySameFolder; + this.layout = SettingsUserStore.layout; + this.usePreviewPane = SettingsUserStore.usePreviewPane; this.isMessageSelected = Data.isMessageSelected; this.messageActiveDom = Data.messageActiveDom; this.messageError = Data.messageError; diff --git a/gulpfile.js b/gulpfile.js index a1fc2f0e9..94aab9c3b 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -164,10 +164,11 @@ cfg.paths.js = { 'vendors/knockout-sortable/knockout-sortable.min.js', 'vendors/ssm/ssm.min.js', 'vendors/jua/jua.min.js', + 'vendors/buzz/buzz.min.js', 'vendors/Autolinker/Autolinker.min.js', 'vendors/photoswipe/photoswipe.min.js', 'vendors/photoswipe/photoswipe-ui-default.min.js', - 'vendors/jsencrypt/jsencrypt.min.js', +// 'vendors/jsencrypt/jsencrypt.min.js', 'vendors/keymaster/keymaster.min.js', 'vendors/ifvisible/ifvisible.min.js', 'vendors/bootstrap/js/bootstrap.min.js' @@ -279,7 +280,7 @@ gulp.task('js:ckeditor:beautify', function() { }); gulp.task('js:webpack:clear', function() { - return gulp.src([cfg.paths.staticJS + '*.chunk.js', cfg.paths.staticMinJS + '*.chunk.js'], {read: false}) + return gulp.src([cfg.paths.staticJS + '*.subapp.js', cfg.paths.staticMinJS + '*.subapp.js'], {read: false}) .pipe(require('gulp-rimraf')()); }); @@ -320,7 +321,7 @@ gulp.task('js:admin', ['js:webpack'], function() { }); gulp.task('js:chunks', ['js:webpack'], function() { - return gulp.src(cfg.paths.staticJS + '*.chunk.js') + return gulp.src(cfg.paths.staticJS + '*.subapp.js') .pipe(header('/* RainLoop Webmail (c) RainLoop Team | Licensed under CC BY-NC-SA 3.0 */\n')) .pipe(eol('\n', true)) .pipe(gulp.dest(cfg.paths.staticJS)) diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php index ba0101a59..2904a799f 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -1233,7 +1233,7 @@ class Actions $aResult['AllowDropboxSocial'] = (bool) $oConfig->Get('social', 'dropbox_enable', false); $aResult['DropboxApiKey'] = \trim($oConfig->Get('social', 'dropbox_api_key', '')); - + if (!$aResult['AllowDropboxSocial']) { $aResult['DropboxApiKey'] = ''; @@ -1332,6 +1332,7 @@ class Actions $aResult['ShowImages'] = (bool) $oConfig->Get('webmail', 'show_images', false); $aResult['ContactsAutosave'] = true; $aResult['MPP'] = (int) $oConfig->Get('webmail', 'messages_per_page', 25); + $aResult['SoundNotification'] = false; $aResult['DesktopNotifications'] = false; $aResult['UseThreads'] = false; $aResult['ReplySameFolder'] = false; @@ -1370,6 +1371,7 @@ class Actions $aResult['ShowImages'] = (bool) $oSettings->GetConf('ShowImages', $aResult['ShowImages']); $aResult['ContactsAutosave'] = (bool) $oSettings->GetConf('ContactsAutosave', $aResult['ContactsAutosave']); $aResult['MPP'] = (int) $oSettings->GetConf('MPP', $aResult['MPP']); + $aResult['SoundNotification'] = (bool) $oSettings->GetConf('SoundNotification', $aResult['SoundNotification']); $aResult['DesktopNotifications'] = (bool) $oSettings->GetConf('DesktopNotifications', $aResult['DesktopNotifications']); $aResult['UseThreads'] = (bool) $oSettings->GetConf('UseThreads', $aResult['UseThreads']); $aResult['ReplySameFolder'] = (bool) $oSettings->GetConf('ReplySameFolder', $aResult['ReplySameFolder']); @@ -1409,7 +1411,7 @@ class Actions $bUserLanguage = false; if (!$bAdmin && !$aResult['Auth'] && !empty($_COOKIE['rllang']) && - $oConfig->Get('webmail', 'allow_languages_on_login', true)) + $oConfig->Get('login', 'allow_languages_on_login', true)) { $sLanguage = $_COOKIE['rllang']; } @@ -1417,6 +1419,7 @@ class Actions { $sUserLanguage = ''; if (!$bAdmin && !$aResult['Auth'] && + $oConfig->Get('login', 'allow_languages_on_login', true) && $oConfig->Get('login', 'determine_user_language', true)) { $sUserLanguage = $this->detectUserLanguage(); @@ -4057,6 +4060,7 @@ class Actions $this->setSettingsFromParams($oSettings, 'ShowImages', 'bool'); $this->setSettingsFromParams($oSettings, 'ContactsAutosave', 'bool'); $this->setSettingsFromParams($oSettings, 'DesktopNotifications', 'bool'); + $this->setSettingsFromParams($oSettings, 'SoundNotification', 'bool'); $this->setSettingsFromParams($oSettings, 'UseThreads', 'bool'); $this->setSettingsFromParams($oSettings, 'ReplySameFolder', 'bool'); $this->setSettingsFromParams($oSettings, 'UseCheckboxesInList', 'bool'); diff --git a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsLogin.html b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsLogin.html index 51dd04083..670ce4c88 100644 --- a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsLogin.html +++ b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsLogin.html @@ -29,9 +29,9 @@ name: 'Checkbox', params: { value: allowLanguagesOnLogin, label: 'Allow language selection on login screen' } }"> -
diff --git a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsSecurity.html b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsSecurity.html index 8ede1e572..d118effc8 100644 --- a/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsSecurity.html +++ b/rainloop/v/0.0.0/app/templates/Views/Admin/AdminSettingsSecurity.html @@ -9,18 +9,10 @@ name: 'Checkbox', params: { value: capaTwoFactorAuth, label: 'Allow 2-Step Verification (Google Authenticator)' } }"> - - -
-
-
-
-
-
-
- SSL -
-
-
-
-    - (unstable) -
-
- -
-
-
-
Admin Panel Access Credentials @@ -116,4 +78,33 @@
+
+
+ SSL +
+
+
+
+    + (unstable) +
+
+ +
+
+
\ No newline at end of file diff --git a/rainloop/v/0.0.0/app/templates/Views/Admin/PopupsDomain.html b/rainloop/v/0.0.0/app/templates/Views/Admin/PopupsDomain.html index 86468079b..9f0a7c14a 100644 --- a/rainloop/v/0.0.0/app/templates/Views/Admin/PopupsDomain.html +++ b/rainloop/v/0.0.0/app/templates/Views/Admin/PopupsDomain.html @@ -74,6 +74,8 @@   Sieve configuration +    + (beta) @@ -91,7 +93,6 @@
-
+
+
- +
@@ -129,6 +130,20 @@
+
+
+    + + + +
diff --git a/rainloop/v/0.0.0/langs/bg.ini b/rainloop/v/0.0.0/langs/bg.ini index fc5a3614c..13d34ad51 100644 --- a/rainloop/v/0.0.0/langs/bg.ini +++ b/rainloop/v/0.0.0/langs/bg.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Place replies in the folder of the message being repl LABEL_SHOW_IMAGES = "Always display external images in message body" LABEL_SHOW_ANIMATION = "Show animation" LABEL_MESSAGE_PER_PAGE = "messages on page" -LABEL_CHROME_NOTIFICATION = "Известия" +LABEL_NOTIFICATIONS = "Известия" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Show new messages notification popups" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Blocked by the browser)" diff --git a/rainloop/v/0.0.0/langs/de.ini b/rainloop/v/0.0.0/langs/de.ini index 46a41663b..c70ae57fd 100644 --- a/rainloop/v/0.0.0/langs/de.ini +++ b/rainloop/v/0.0.0/langs/de.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Antworten im gleichen Ordner wie die Nachricht, auf d LABEL_SHOW_IMAGES = "In der Nachricht enthaltene Bilder immer anzeigen" LABEL_SHOW_ANIMATION = "Animation anzeigen" LABEL_MESSAGE_PER_PAGE = "Nachrichten pro Seite" -LABEL_CHROME_NOTIFICATION = "Benachrichtigungen" +LABEL_NOTIFICATIONS = "Benachrichtigungen" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Popups einblenden, wenn neue Nachrichten vorhanden sind" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Vom Browser blockiert.)" diff --git a/rainloop/v/0.0.0/langs/en.ini b/rainloop/v/0.0.0/langs/en.ini index ad125ba03..37ff1a0dd 100644 --- a/rainloop/v/0.0.0/langs/en.ini +++ b/rainloop/v/0.0.0/langs/en.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Place replies in the folder of the message being repl LABEL_SHOW_IMAGES = "Always display external images in message body" LABEL_SHOW_ANIMATION = "Show animation" LABEL_MESSAGE_PER_PAGE = "messages on page" -LABEL_CHROME_NOTIFICATION = "Notifications" +LABEL_NOTIFICATIONS = "Notifications" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Show new messages notification popups" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Blocked by the browser)" diff --git a/rainloop/v/0.0.0/langs/es.ini b/rainloop/v/0.0.0/langs/es.ini index 5cb08b91e..547bf7aa5 100644 --- a/rainloop/v/0.0.0/langs/es.ini +++ b/rainloop/v/0.0.0/langs/es.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Coloque las respuestas en la carpeta del mensaje que LABEL_SHOW_IMAGES = "Mostrar siempre las imágenes en el cuerpo del mensaje" LABEL_SHOW_ANIMATION = "Mostrar animación" LABEL_MESSAGE_PER_PAGE = "mensajes en página" -LABEL_CHROME_NOTIFICATION = "Notificaciones" +LABEL_NOTIFICATIONS = "Notificaciones" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Mostrar notificación de nuevos mensajes en Popup" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Bloqueado por el explorador)" diff --git a/rainloop/v/0.0.0/langs/fr.ini b/rainloop/v/0.0.0/langs/fr.ini index ba799ce8b..8a1bb7f22 100644 --- a/rainloop/v/0.0.0/langs/fr.ini +++ b/rainloop/v/0.0.0/langs/fr.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Placer les réponses dans le dossier du message" LABEL_SHOW_IMAGES = "Toujours afficher les images dans le mail" LABEL_SHOW_ANIMATION = "Voir les animations" LABEL_MESSAGE_PER_PAGE = "messages par page" -LABEL_CHROME_NOTIFICATION = "Notifications" +LABEL_NOTIFICATIONS = "Notifications" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Afficher un pop-up de notification pour les nouveaux messages" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Bloqué par le navigateur)" diff --git a/rainloop/v/0.0.0/langs/hu.ini b/rainloop/v/0.0.0/langs/hu.ini index 32f7d99b7..69bdbf5ee 100644 --- a/rainloop/v/0.0.0/langs/hu.ini +++ b/rainloop/v/0.0.0/langs/hu.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Place replies in the folder of the message being repl LABEL_SHOW_IMAGES = "Always display external images in message body" LABEL_SHOW_ANIMATION = "Show animation" LABEL_MESSAGE_PER_PAGE = "messages on page" -LABEL_CHROME_NOTIFICATION = "Notifications" +LABEL_NOTIFICATIONS = "Notifications" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Show new messages notification popups" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Blocked by the browser)" diff --git a/rainloop/v/0.0.0/langs/is.ini b/rainloop/v/0.0.0/langs/is.ini index 7b9abc82b..498e83b8f 100644 --- a/rainloop/v/0.0.0/langs/is.ini +++ b/rainloop/v/0.0.0/langs/is.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Setja svör í möppu þar sem bréfið sem er verið LABEL_SHOW_IMAGES = "Sýna ávallt myndir í bréfum" LABEL_SHOW_ANIMATION = "Sýna hreyfingar" LABEL_MESSAGE_PER_PAGE = "bréf á síðu" -LABEL_CHROME_NOTIFICATION = "Tilkynningar" +LABEL_NOTIFICATIONS = "Tilkynningar" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Sýna tilkynningarglugga fyrir ný bréf" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Lokað af vafra)" diff --git a/rainloop/v/0.0.0/langs/it.ini b/rainloop/v/0.0.0/langs/it.ini index 28d2d4a41..173ba8db6 100644 --- a/rainloop/v/0.0.0/langs/it.ini +++ b/rainloop/v/0.0.0/langs/it.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Posiziona le risposte nella cartella del messaggio a LABEL_SHOW_IMAGES = "Visualizza sempre le immagini esterne nel messaggio" LABEL_SHOW_ANIMATION = "Mostra le animazioni" LABEL_MESSAGE_PER_PAGE = "messaggi per pagina" -LABEL_CHROME_NOTIFICATION = "Notifiche" +LABEL_NOTIFICATIONS = "Notifiche" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Mostra le notifiche in caso di nuovi messaggi" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Bloccate dal browser)" diff --git a/rainloop/v/0.0.0/langs/ja-jp.ini b/rainloop/v/0.0.0/langs/ja-jp.ini index 87825e294..737758a95 100644 --- a/rainloop/v/0.0.0/langs/ja-jp.ini +++ b/rainloop/v/0.0.0/langs/ja-jp.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Place replies in the folder of the message being repl LABEL_SHOW_IMAGES = "外部画像を常に表示する" LABEL_SHOW_ANIMATION = "Show animation" LABEL_MESSAGE_PER_PAGE = "件のメールを1ページに表示する" -LABEL_CHROME_NOTIFICATION = "通知設定" +LABEL_NOTIFICATIONS = "通知設定" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "新しいメッセージを受信したらポップアップで知らせる" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(ブラウザでブロックされています)" diff --git a/rainloop/v/0.0.0/langs/ko-kr.ini b/rainloop/v/0.0.0/langs/ko-kr.ini index d6dd2b3e4..ebbc2f886 100644 --- a/rainloop/v/0.0.0/langs/ko-kr.ini +++ b/rainloop/v/0.0.0/langs/ko-kr.ini @@ -464,7 +464,8 @@ LABEL_REPLY_SAME_FOLDER = "답장 메시지를 같은 폴더에 위치시킵니 LABEL_SHOW_IMAGES = "본문 내 외부 이미지를 항상 표시합니다." LABEL_SHOW_ANIMATION = "애니메이션 보기" LABEL_MESSAGE_PER_PAGE = "페이지 당 메시지 수" -LABEL_CHROME_NOTIFICATION = "알림" +LABEL_NOTIFICATIONS = "알림" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "새 메시지 알림 팝업 사용" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(브라우저에 의해 차단됨)" diff --git a/rainloop/v/0.0.0/langs/lt.ini b/rainloop/v/0.0.0/langs/lt.ini index 95a7ace76..513815092 100644 --- a/rainloop/v/0.0.0/langs/lt.ini +++ b/rainloop/v/0.0.0/langs/lt.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Atsakymus dėti į katalogą, kuriame yra pradinė ž LABEL_SHOW_IMAGES = "Visada rodyti išorinius vaizdus žinutėse" LABEL_SHOW_ANIMATION = "Rodyti animaciją" LABEL_MESSAGE_PER_PAGE = "Žinučių lape" -LABEL_CHROME_NOTIFICATION = "Pranešimai" +LABEL_NOTIFICATIONS = "Pranešimai" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Rodyti iššokančius pranešimus apie naujas žinutes" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Blokuoja naršyklė)" diff --git a/rainloop/v/0.0.0/langs/lv.ini b/rainloop/v/0.0.0/langs/lv.ini index 432e1d2bb..d69b046b9 100644 --- a/rainloop/v/0.0.0/langs/lv.ini +++ b/rainloop/v/0.0.0/langs/lv.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Atbildes ziņojumus ielikt mapē kurā atrodas vēstu LABEL_SHOW_IMAGES = "Vienmēr rādīt attēlus ziņojumos" LABEL_SHOW_ANIMATION = "Rādīt animāciju" LABEL_MESSAGE_PER_PAGE = "ziņojumi lapā" -LABEL_CHROME_NOTIFICATION = "Paziņojumi" +LABEL_NOTIFICATIONS = "Paziņojumi" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Rādīt jaunus paziņojumus kā izlecošus logus" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Parlūkprogramma bloķēja)" diff --git a/rainloop/v/0.0.0/langs/nl.ini b/rainloop/v/0.0.0/langs/nl.ini index 2af0541e6..c9cad7098 100644 --- a/rainloop/v/0.0.0/langs/nl.ini +++ b/rainloop/v/0.0.0/langs/nl.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Plaats antwoorden in de map van het originele bericht LABEL_SHOW_IMAGES = "Afbeeldingen altijd weergeven in het bericht" LABEL_SHOW_ANIMATION = "Toon animaties" LABEL_MESSAGE_PER_PAGE = "berichten op pagina" -LABEL_CHROME_NOTIFICATION = "Notificaties" +LABEL_NOTIFICATIONS = "Notificaties" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Toon nieuwe berichten popup" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Geblokkeerd door de browser)" diff --git a/rainloop/v/0.0.0/langs/no.ini b/rainloop/v/0.0.0/langs/no.ini index c5aed8272..de0d4616d 100644 --- a/rainloop/v/0.0.0/langs/no.ini +++ b/rainloop/v/0.0.0/langs/no.ini @@ -466,7 +466,8 @@ LABEL_REPLY_SAME_FOLDER = "Plasser svar i samme mappe som meldingen du svarer p LABEL_SHOW_IMAGES = "Vis alltid eksterne bilder i meldingsteksten" LABEL_SHOW_ANIMATION = "Vis animasjon" LABEL_MESSAGE_PER_PAGE = "meldinger på hver side" -LABEL_CHROME_NOTIFICATION = "Varsler" +LABEL_NOTIFICATIONS = "Varsler" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Vis popup-varsel når du mottar en ny melding" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Blokkert av nettleseren)" diff --git a/rainloop/v/0.0.0/langs/pl.ini b/rainloop/v/0.0.0/langs/pl.ini index a6cb96466..f66e06e9f 100644 --- a/rainloop/v/0.0.0/langs/pl.ini +++ b/rainloop/v/0.0.0/langs/pl.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Umieść odpowiedź w folderze wiadomości, na któr LABEL_SHOW_IMAGES = "Zawsze wyświetlaj obrazy w wiadomościach" LABEL_SHOW_ANIMATION = "Odtwarzaj animacje" LABEL_MESSAGE_PER_PAGE = "wiadomości na stronie" -LABEL_CHROME_NOTIFICATION = "Powiadomienia" +LABEL_NOTIFICATIONS = "Powiadomienia" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Wyświetlaj powiadomienia o nowych wiadomościach" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Zablokowane przez przeglądarkę)" diff --git a/rainloop/v/0.0.0/langs/pt-br.ini b/rainloop/v/0.0.0/langs/pt-br.ini index 913ddcd51..fd34de73c 100644 --- a/rainloop/v/0.0.0/langs/pt-br.ini +++ b/rainloop/v/0.0.0/langs/pt-br.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Colocar resposta na mesma pasta da mensagem respondid LABEL_SHOW_IMAGES = "Sempre exibir imagens no corpo da mensagem" LABEL_SHOW_ANIMATION = "Mostrar animação" LABEL_MESSAGE_PER_PAGE = "Mensagens por Página" -LABEL_CHROME_NOTIFICATION = "Notificações" +LABEL_NOTIFICATIONS = "Notificações" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Mostrar notificação popup para novas mensagens" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Bloqueado pelo navegador)" diff --git a/rainloop/v/0.0.0/langs/pt-pt.ini b/rainloop/v/0.0.0/langs/pt-pt.ini index 26eac7634..972786887 100644 --- a/rainloop/v/0.0.0/langs/pt-pt.ini +++ b/rainloop/v/0.0.0/langs/pt-pt.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Colocar respostas na pasta de mensagens respondidas p LABEL_SHOW_IMAGES = "Sempre exibir imagens no corpo da mensagem" LABEL_SHOW_ANIMATION = "Mostrar animação" LABEL_MESSAGE_PER_PAGE = "Página de mensagens" -LABEL_CHROME_NOTIFICATION = "Notificações" +LABEL_NOTIFICATIONS = "Notificações" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Mostrar as novas mensagens de notificação" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Bloqueado pelo navegador)" diff --git a/rainloop/v/0.0.0/langs/ro.ini b/rainloop/v/0.0.0/langs/ro.ini index 38f27b204..b51cdceb8 100644 --- a/rainloop/v/0.0.0/langs/ro.ini +++ b/rainloop/v/0.0.0/langs/ro.ini @@ -466,7 +466,8 @@ LABEL_REPLY_SAME_FOLDER = "Răspunsurile în același folder cu originalul" LABEL_SHOW_IMAGES = "Arată imaginile externe în corpul mesajului, fără avertisment" LABEL_SHOW_ANIMATION = "Utilizați animația" LABEL_MESSAGE_PER_PAGE = "mesaje pe o pagină" -LABEL_CHROME_NOTIFICATION = "Notificări" +LABEL_NOTIFICATIONS = "Notificări" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Afișați notificări desktop pentru mesaje noi" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(browser-ul blocat)" diff --git a/rainloop/v/0.0.0/langs/ru.ini b/rainloop/v/0.0.0/langs/ru.ini index 429e6d5b5..13de3b20d 100644 --- a/rainloop/v/0.0.0/langs/ru.ini +++ b/rainloop/v/0.0.0/langs/ru.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Помещать ответы в ту же папку LABEL_SHOW_IMAGES = "Показывать внешние изображения в теле письма без предупреждения" LABEL_SHOW_ANIMATION = "Использовать анимацию" LABEL_MESSAGE_PER_PAGE = "сообщений на одной странице" -LABEL_CHROME_NOTIFICATION = "Уведомления" +LABEL_NOTIFICATIONS = "Уведомления" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Показывать уведомления о новых сообщениях в всплывающих подсказках" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Блокировано браузером)" diff --git a/rainloop/v/0.0.0/langs/sk.ini b/rainloop/v/0.0.0/langs/sk.ini index 428c8c803..c226d6afe 100644 --- a/rainloop/v/0.0.0/langs/sk.ini +++ b/rainloop/v/0.0.0/langs/sk.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Umiestňovať odpovede do priečinka so správou ktor LABEL_SHOW_IMAGES = "Vždy zobrazovať obrázky v tele správy" LABEL_SHOW_ANIMATION = "Animovať" LABEL_MESSAGE_PER_PAGE = "správ na stranu" -LABEL_CHROME_NOTIFICATION = "Notifikácie" +LABEL_NOTIFICATIONS = "Notifikácie" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Zobrazovať upozornenia na nové správy" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Zablokované prehliadačom)" diff --git a/rainloop/v/0.0.0/langs/sv.ini b/rainloop/v/0.0.0/langs/sv.ini index ae0c495ad..10d83ad87 100644 --- a/rainloop/v/0.0.0/langs/sv.ini +++ b/rainloop/v/0.0.0/langs/sv.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Placera svar i samma mapp som mottagna meddelandet." LABEL_SHOW_IMAGES = "Visa alltid bilder i mail" LABEL_SHOW_ANIMATION = "Visa animeringar" LABEL_MESSAGE_PER_PAGE = "meddelanden per sida" -LABEL_CHROME_NOTIFICATION = "Aviseringar" +LABEL_NOTIFICATIONS = "Aviseringar" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Visa nya meddelande-aviseringar som popup-fönster" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Blockat av webbläsaren)" diff --git a/rainloop/v/0.0.0/langs/tr.ini b/rainloop/v/0.0.0/langs/tr.ini index 34920a4cd..30726c799 100644 --- a/rainloop/v/0.0.0/langs/tr.ini +++ b/rainloop/v/0.0.0/langs/tr.ini @@ -465,7 +465,8 @@ LABEL_REPLY_SAME_FOLDER = "Klasördeki cevapları mesajlarda göster" LABEL_SHOW_IMAGES = "Herzaman gelen maillerdeki resimleri görüntüle." LABEL_SHOW_ANIMATION = "Animasyonu göster" LABEL_MESSAGE_PER_PAGE = "messages on page" -LABEL_CHROME_NOTIFICATION = "Bildirimler" +LABEL_NOTIFICATIONS = "Bildirimler" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Yeni mesajları pop-up ile göster" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Tarayıcınız tarafından engellendi)" diff --git a/rainloop/v/0.0.0/langs/ua.ini b/rainloop/v/0.0.0/langs/ua.ini index dd1dc5a9c..57b2eedc3 100644 --- a/rainloop/v/0.0.0/langs/ua.ini +++ b/rainloop/v/0.0.0/langs/ua.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "Поміщати відповіді в ту ж тек LABEL_SHOW_IMAGES = "Показувати зовнішні зображення в тілі листа без попередження" LABEL_SHOW_ANIMATION = "Використовувати анімацію" LABEL_MESSAGE_PER_PAGE = "повідомлень на одній сторінці" -LABEL_CHROME_NOTIFICATION = "Сповіщення" +LABEL_NOTIFICATIONS = "Сповіщення" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "Показувати сповіщення про нові повідомлення у підказках" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(Заблоковано браузером)" diff --git a/rainloop/v/0.0.0/langs/zh-cn.ini b/rainloop/v/0.0.0/langs/zh-cn.ini index 5c57f45df..942ce8b8d 100644 --- a/rainloop/v/0.0.0/langs/zh-cn.ini +++ b/rainloop/v/0.0.0/langs/zh-cn.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "将回复的邮件放置到其回复的邮件所在 LABEL_SHOW_IMAGES = "总是显示外部图片信息" LABEL_SHOW_ANIMATION = "显示动画" LABEL_MESSAGE_PER_PAGE = "封邮件每页" -LABEL_CHROME_NOTIFICATION = "通知" +LABEL_NOTIFICATIONS = "通知" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "显示新邮件弹窗" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(被浏览器阻止)" diff --git a/rainloop/v/0.0.0/langs/zh-tw.ini b/rainloop/v/0.0.0/langs/zh-tw.ini index a65b4b66d..6f4b0f07a 100644 --- a/rainloop/v/0.0.0/langs/zh-tw.ini +++ b/rainloop/v/0.0.0/langs/zh-tw.ini @@ -467,7 +467,8 @@ LABEL_REPLY_SAME_FOLDER = "將回復的郵件放置到其回復的郵件所在 LABEL_SHOW_IMAGES = "總是顯示外部圖片資訊" LABEL_SHOW_ANIMATION = "顯示動畫" LABEL_MESSAGE_PER_PAGE = "封郵件每頁" -LABEL_CHROME_NOTIFICATION = "通知" +LABEL_NOTIFICATIONS = "通知" +LABEL_SOUND_NOTIFICATION = "Sound notification" LABEL_CHROME_NOTIFICATION_DESC = "顯示新郵件彈窗" LABEL_CHROME_NOTIFICATION_DESC_DENIED = "(被瀏覽器阻止)" diff --git a/vendors/buzz/buzz.js b/vendors/buzz/buzz.js new file mode 100644 index 000000000..5bcd33ede --- /dev/null +++ b/vendors/buzz/buzz.js @@ -0,0 +1,719 @@ + // ---------------------------------------------------------------------------- + // Buzz, a Javascript HTML5 Audio library + // v1.1.8 - Built 2015-01-12 11:08 + // Licensed under the MIT license. + // http://buzz.jaysalvat.com/ + // ---------------------------------------------------------------------------- + // Copyright (C) 2010-2015 Jay Salvat + // http://jaysalvat.com/ + // ---------------------------------------------------------------------------- + +(function(context, factory) { + "use strict"; + if (typeof module !== "undefined" && module.exports) { + module.exports = factory(); + } else if (typeof define === "function" && define.amd) { + define([], factory); + } else { + context.buzz = factory(); + } +})(this, function() { + "use strict"; + var AudioContext = window.AudioContext || window.webkitAudioContext; + var buzz = { + audioCtx: window.AudioContext ? new AudioContext() : null, + defaults: { + autoplay: false, + duration: 5e3, + formats: [], + loop: false, + placeholder: "--", + preload: "metadata", + volume: 80, + webAudioApi: false, + document: window.document + }, + types: { + mp3: "audio/mpeg", + ogg: "audio/ogg", + wav: "audio/wav", + aac: "audio/aac", + m4a: "audio/x-m4a" + }, + sounds: [], + el: document.createElement("audio"), + sound: function(src, options) { + options = options || {}; + var doc = options.document || buzz.defaults.document; + var pid = 0, events = [], eventsOnce = {}, supported = buzz.isSupported(); + this.load = function() { + if (!supported) { + return this; + } + this.sound.load(); + return this; + }; + this.play = function() { + if (!supported) { + return this; + } + this.sound.play(); + return this; + }; + this.togglePlay = function() { + if (!supported) { + return this; + } + if (this.sound.paused) { + this.sound.play(); + } else { + this.sound.pause(); + } + return this; + }; + this.pause = function() { + if (!supported) { + return this; + } + this.sound.pause(); + return this; + }; + this.isPaused = function() { + if (!supported) { + return null; + } + return this.sound.paused; + }; + this.stop = function() { + if (!supported) { + return this; + } + this.setTime(0); + this.sound.pause(); + return this; + }; + this.isEnded = function() { + if (!supported) { + return null; + } + return this.sound.ended; + }; + this.loop = function() { + if (!supported) { + return this; + } + this.sound.loop = "loop"; + this.bind("ended.buzzloop", function() { + this.currentTime = 0; + this.play(); + }); + return this; + }; + this.unloop = function() { + if (!supported) { + return this; + } + this.sound.removeAttribute("loop"); + this.unbind("ended.buzzloop"); + return this; + }; + this.mute = function() { + if (!supported) { + return this; + } + this.sound.muted = true; + return this; + }; + this.unmute = function() { + if (!supported) { + return this; + } + this.sound.muted = false; + return this; + }; + this.toggleMute = function() { + if (!supported) { + return this; + } + this.sound.muted = !this.sound.muted; + return this; + }; + this.isMuted = function() { + if (!supported) { + return null; + } + return this.sound.muted; + }; + this.setVolume = function(volume) { + if (!supported) { + return this; + } + if (volume < 0) { + volume = 0; + } + if (volume > 100) { + volume = 100; + } + this.volume = volume; + this.sound.volume = volume / 100; + return this; + }; + this.getVolume = function() { + if (!supported) { + return this; + } + return this.volume; + }; + this.increaseVolume = function(value) { + return this.setVolume(this.volume + (value || 1)); + }; + this.decreaseVolume = function(value) { + return this.setVolume(this.volume - (value || 1)); + }; + this.setTime = function(time) { + if (!supported) { + return this; + } + var set = true; + this.whenReady(function() { + if (set === true) { + set = false; + this.sound.currentTime = time; + } + }); + return this; + }; + this.getTime = function() { + if (!supported) { + return null; + } + var time = Math.round(this.sound.currentTime * 100) / 100; + return isNaN(time) ? buzz.defaults.placeholder : time; + }; + this.setPercent = function(percent) { + if (!supported) { + return this; + } + return this.setTime(buzz.fromPercent(percent, this.sound.duration)); + }; + this.getPercent = function() { + if (!supported) { + return null; + } + var percent = Math.round(buzz.toPercent(this.sound.currentTime, this.sound.duration)); + return isNaN(percent) ? buzz.defaults.placeholder : percent; + }; + this.setSpeed = function(duration) { + if (!supported) { + return this; + } + this.sound.playbackRate = duration; + return this; + }; + this.getSpeed = function() { + if (!supported) { + return null; + } + return this.sound.playbackRate; + }; + this.getDuration = function() { + if (!supported) { + return null; + } + var duration = Math.round(this.sound.duration * 100) / 100; + return isNaN(duration) ? buzz.defaults.placeholder : duration; + }; + this.getPlayed = function() { + if (!supported) { + return null; + } + return timerangeToArray(this.sound.played); + }; + this.getBuffered = function() { + if (!supported) { + return null; + } + return timerangeToArray(this.sound.buffered); + }; + this.getSeekable = function() { + if (!supported) { + return null; + } + return timerangeToArray(this.sound.seekable); + }; + this.getErrorCode = function() { + if (supported && this.sound.error) { + return this.sound.error.code; + } + return 0; + }; + this.getErrorMessage = function() { + if (!supported) { + return null; + } + switch (this.getErrorCode()) { + case 1: + return "MEDIA_ERR_ABORTED"; + + case 2: + return "MEDIA_ERR_NETWORK"; + + case 3: + return "MEDIA_ERR_DECODE"; + + case 4: + return "MEDIA_ERR_SRC_NOT_SUPPORTED"; + + default: + return null; + } + }; + this.getStateCode = function() { + if (!supported) { + return null; + } + return this.sound.readyState; + }; + this.getStateMessage = function() { + if (!supported) { + return null; + } + switch (this.getStateCode()) { + case 0: + return "HAVE_NOTHING"; + + case 1: + return "HAVE_METADATA"; + + case 2: + return "HAVE_CURRENT_DATA"; + + case 3: + return "HAVE_FUTURE_DATA"; + + case 4: + return "HAVE_ENOUGH_DATA"; + + default: + return null; + } + }; + this.getNetworkStateCode = function() { + if (!supported) { + return null; + } + return this.sound.networkState; + }; + this.getNetworkStateMessage = function() { + if (!supported) { + return null; + } + switch (this.getNetworkStateCode()) { + case 0: + return "NETWORK_EMPTY"; + + case 1: + return "NETWORK_IDLE"; + + case 2: + return "NETWORK_LOADING"; + + case 3: + return "NETWORK_NO_SOURCE"; + + default: + return null; + } + }; + this.set = function(key, value) { + if (!supported) { + return this; + } + this.sound[key] = value; + return this; + }; + this.get = function(key) { + if (!supported) { + return null; + } + return key ? this.sound[key] : this.sound; + }; + this.bind = function(types, func) { + if (!supported) { + return this; + } + types = types.split(" "); + var self = this, efunc = function(e) { + func.call(self, e); + }; + for (var t = 0; t < types.length; t++) { + var type = types[t], idx = type; + type = idx.split(".")[0]; + events.push({ + idx: idx, + func: efunc + }); + this.sound.addEventListener(type, efunc, true); + } + return this; + }; + this.unbind = function(types) { + if (!supported) { + return this; + } + types = types.split(" "); + for (var t = 0; t < types.length; t++) { + var idx = types[t], type = idx.split(".")[0]; + for (var i = 0; i < events.length; i++) { + var namespace = events[i].idx.split("."); + if (events[i].idx === idx || namespace[1] && namespace[1] === idx.replace(".", "")) { + this.sound.removeEventListener(type, events[i].func, true); + events.splice(i, 1); + } + } + } + return this; + }; + this.bindOnce = function(type, func) { + if (!supported) { + return this; + } + var self = this; + eventsOnce[pid++] = false; + this.bind(type + "." + pid, function() { + if (!eventsOnce[pid]) { + eventsOnce[pid] = true; + func.call(self); + } + self.unbind(type + "." + pid); + }); + return this; + }; + this.trigger = function(types, detail) { + if (!supported) { + return this; + } + types = types.split(" "); + for (var t = 0; t < types.length; t++) { + var idx = types[t]; + for (var i = 0; i < events.length; i++) { + var eventType = events[i].idx.split("."); + if (events[i].idx === idx || eventType[0] && eventType[0] === idx.replace(".", "")) { + var evt = doc.createEvent("HTMLEvents"); + evt.initEvent(eventType[0], false, true); + evt.originalEvent = detail; + this.sound.dispatchEvent(evt); + } + } + } + return this; + }; + this.fadeTo = function(to, duration, callback) { + if (!supported) { + return this; + } + if (duration instanceof Function) { + callback = duration; + duration = buzz.defaults.duration; + } else { + duration = duration || buzz.defaults.duration; + } + var from = this.volume, delay = duration / Math.abs(from - to), self = this; + this.play(); + function doFade() { + setTimeout(function() { + if (from < to && self.volume < to) { + self.setVolume(self.volume += 1); + doFade(); + } else if (from > to && self.volume > to) { + self.setVolume(self.volume -= 1); + doFade(); + } else if (callback instanceof Function) { + callback.apply(self); + } + }, delay); + } + this.whenReady(function() { + doFade(); + }); + return this; + }; + this.fadeIn = function(duration, callback) { + if (!supported) { + return this; + } + return this.setVolume(0).fadeTo(100, duration, callback); + }; + this.fadeOut = function(duration, callback) { + if (!supported) { + return this; + } + return this.fadeTo(0, duration, callback); + }; + this.fadeWith = function(sound, duration) { + if (!supported) { + return this; + } + this.fadeOut(duration, function() { + this.stop(); + }); + sound.play().fadeIn(duration); + return this; + }; + this.whenReady = function(func) { + if (!supported) { + return null; + } + var self = this; + if (this.sound.readyState === 0) { + this.bind("canplay.buzzwhenready", function() { + func.call(self); + }); + } else { + func.call(self); + } + }; + this.addSource = function(src) { + var self = this, source = doc.createElement("source"); + source.src = src; + if (buzz.types[getExt(src)]) { + source.type = buzz.types[getExt(src)]; + } + this.sound.appendChild(source); + source.addEventListener("error", function(e) { + self.sound.networkState = 3; + self.trigger("sourceerror", e); + }); + return source; + }; + function timerangeToArray(timeRange) { + var array = [], length = timeRange.length - 1; + for (var i = 0; i <= length; i++) { + array.push({ + start: timeRange.start(i), + end: timeRange.end(i) + }); + } + return array; + } + function getExt(filename) { + return filename.split(".").pop(); + } + if (supported && src) { + for (var i in buzz.defaults) { + if (buzz.defaults.hasOwnProperty(i)) { + if (options[i] === undefined) { + options[i] = buzz.defaults[i]; + } + } + } + this.sound = doc.createElement("audio"); + if (options.webAudioApi && buzz.audioCtx) { + this.source = buzz.audioCtx.createMediaElementSource(this.sound); + this.source.connect(buzz.audioCtx.destination); + } + if (src instanceof Array) { + for (var j in src) { + if (src.hasOwnProperty(j)) { + this.addSource(src[j]); + } + } + } else if (options.formats.length) { + for (var k in options.formats) { + if (options.formats.hasOwnProperty(k)) { + this.addSource(src + "." + options.formats[k]); + } + } + } else { + this.addSource(src); + } + if (options.loop) { + this.loop(); + } + if (options.autoplay) { + this.sound.autoplay = "autoplay"; + } + if (options.preload === true) { + this.sound.preload = "auto"; + } else if (options.preload === false) { + this.sound.preload = "none"; + } else { + this.sound.preload = options.preload; + } + this.setVolume(options.volume); + buzz.sounds.push(this); + } + }, + group: function(sounds) { + sounds = argsToArray(sounds, arguments); + this.getSounds = function() { + return sounds; + }; + this.add = function(soundArray) { + soundArray = argsToArray(soundArray, arguments); + for (var a = 0; a < soundArray.length; a++) { + sounds.push(soundArray[a]); + } + }; + this.remove = function(soundArray) { + soundArray = argsToArray(soundArray, arguments); + for (var a = 0; a < soundArray.length; a++) { + for (var i = 0; i < sounds.length; i++) { + if (sounds[i] === soundArray[a]) { + sounds.splice(i, 1); + break; + } + } + } + }; + this.load = function() { + fn("load"); + return this; + }; + this.play = function() { + fn("play"); + return this; + }; + this.togglePlay = function() { + fn("togglePlay"); + return this; + }; + this.pause = function(time) { + fn("pause", time); + return this; + }; + this.stop = function() { + fn("stop"); + return this; + }; + this.mute = function() { + fn("mute"); + return this; + }; + this.unmute = function() { + fn("unmute"); + return this; + }; + this.toggleMute = function() { + fn("toggleMute"); + return this; + }; + this.setVolume = function(volume) { + fn("setVolume", volume); + return this; + }; + this.increaseVolume = function(value) { + fn("increaseVolume", value); + return this; + }; + this.decreaseVolume = function(value) { + fn("decreaseVolume", value); + return this; + }; + this.loop = function() { + fn("loop"); + return this; + }; + this.unloop = function() { + fn("unloop"); + return this; + }; + this.setSpeed = function(speed) { + fn("setSpeed", speed); + return this; + }; + this.setTime = function(time) { + fn("setTime", time); + return this; + }; + this.set = function(key, value) { + fn("set", key, value); + return this; + }; + this.bind = function(type, func) { + fn("bind", type, func); + return this; + }; + this.unbind = function(type) { + fn("unbind", type); + return this; + }; + this.bindOnce = function(type, func) { + fn("bindOnce", type, func); + return this; + }; + this.trigger = function(type) { + fn("trigger", type); + return this; + }; + this.fade = function(from, to, duration, callback) { + fn("fade", from, to, duration, callback); + return this; + }; + this.fadeIn = function(duration, callback) { + fn("fadeIn", duration, callback); + return this; + }; + this.fadeOut = function(duration, callback) { + fn("fadeOut", duration, callback); + return this; + }; + function fn() { + var args = argsToArray(null, arguments), func = args.shift(); + for (var i = 0; i < sounds.length; i++) { + sounds[i][func].apply(sounds[i], args); + } + } + function argsToArray(array, args) { + return array instanceof Array ? array : Array.prototype.slice.call(args); + } + }, + all: function() { + return new buzz.group(buzz.sounds); + }, + isSupported: function() { + return !!buzz.el.canPlayType; + }, + isOGGSupported: function() { + return !!buzz.el.canPlayType && buzz.el.canPlayType('audio/ogg; codecs="vorbis"'); + }, + isWAVSupported: function() { + return !!buzz.el.canPlayType && buzz.el.canPlayType('audio/wav; codecs="1"'); + }, + isMP3Supported: function() { + return !!buzz.el.canPlayType && buzz.el.canPlayType("audio/mpeg;"); + }, + isAACSupported: function() { + return !!buzz.el.canPlayType && (buzz.el.canPlayType("audio/x-m4a;") || buzz.el.canPlayType("audio/aac;")); + }, + toTimer: function(time, withHours) { + var h, m, s; + h = Math.floor(time / 3600); + h = isNaN(h) ? "--" : h >= 10 ? h : "0" + h; + m = withHours ? Math.floor(time / 60 % 60) : Math.floor(time / 60); + m = isNaN(m) ? "--" : m >= 10 ? m : "0" + m; + s = Math.floor(time % 60); + s = isNaN(s) ? "--" : s >= 10 ? s : "0" + s; + return withHours ? h + ":" + m + ":" + s : m + ":" + s; + }, + fromTimer: function(time) { + var splits = time.toString().split(":"); + if (splits && splits.length === 3) { + time = parseInt(splits[0], 10) * 3600 + parseInt(splits[1], 10) * 60 + parseInt(splits[2], 10); + } + if (splits && splits.length === 2) { + time = parseInt(splits[0], 10) * 60 + parseInt(splits[1], 10); + } + return time; + }, + toPercent: function(value, total, decimal) { + var r = Math.pow(10, decimal || 0); + return Math.round(value * 100 / total * r) / r; + }, + fromPercent: function(percent, total, decimal) { + var r = Math.pow(10, decimal || 0); + return Math.round(total / 100 * percent * r) / r; + } + }; + return buzz; +}); \ No newline at end of file diff --git a/vendors/buzz/buzz.min.js b/vendors/buzz/buzz.min.js new file mode 100644 index 000000000..86cbfec4e --- /dev/null +++ b/vendors/buzz/buzz.min.js @@ -0,0 +1,11 @@ + // ---------------------------------------------------------------------------- + // Buzz, a Javascript HTML5 Audio library + // v1.1.8 - Built 2015-01-12 11:08 + // Licensed under the MIT license. + // http://buzz.jaysalvat.com/ + // ---------------------------------------------------------------------------- + // Copyright (C) 2010-2015 Jay Salvat + // http://jaysalvat.com/ + // ---------------------------------------------------------------------------- + +(function(t,e){"use strict";"undefined"!=typeof module&&module.exports?module.exports=e():"function"==typeof define&&define.amd?define([],e):t.buzz=e()})(this,function(){"use strict";var t=window.AudioContext||window.webkitAudioContext,e={audioCtx:window.AudioContext?new t:null,defaults:{autoplay:!1,duration:5e3,formats:[],loop:!1,placeholder:"--",preload:"metadata",volume:80,webAudioApi:!1,document:window.document},types:{mp3:"audio/mpeg",ogg:"audio/ogg",wav:"audio/wav",aac:"audio/aac",m4a:"audio/x-m4a"},sounds:[],el:document.createElement("audio"),sound:function(t,n){function i(t){for(var e=[],n=t.length-1,i=0;n>=i;i++)e.push({start:t.start(i),end:t.end(i)});return e}function u(t){return t.split(".").pop()}n=n||{};var s=n.document||e.defaults.document,r=0,o=[],a={},h=e.isSupported();if(this.load=function(){return h?(this.sound.load(),this):this},this.play=function(){return h?(this.sound.play(),this):this},this.togglePlay=function(){return h?(this.sound.paused?this.sound.play():this.sound.pause(),this):this},this.pause=function(){return h?(this.sound.pause(),this):this},this.isPaused=function(){return h?this.sound.paused:null},this.stop=function(){return h?(this.setTime(0),this.sound.pause(),this):this},this.isEnded=function(){return h?this.sound.ended:null},this.loop=function(){return h?(this.sound.loop="loop",this.bind("ended.buzzloop",function(){this.currentTime=0,this.play()}),this):this},this.unloop=function(){return h?(this.sound.removeAttribute("loop"),this.unbind("ended.buzzloop"),this):this},this.mute=function(){return h?(this.sound.muted=!0,this):this},this.unmute=function(){return h?(this.sound.muted=!1,this):this},this.toggleMute=function(){return h?(this.sound.muted=!this.sound.muted,this):this},this.isMuted=function(){return h?this.sound.muted:null},this.setVolume=function(t){return h?(0>t&&(t=0),t>100&&(t=100),this.volume=t,this.sound.volume=t/100,this):this},this.getVolume=function(){return h?this.volume:this},this.increaseVolume=function(t){return this.setVolume(this.volume+(t||1))},this.decreaseVolume=function(t){return this.setVolume(this.volume-(t||1))},this.setTime=function(t){if(!h)return this;var e=!0;return this.whenReady(function(){e===!0&&(e=!1,this.sound.currentTime=t)}),this},this.getTime=function(){if(!h)return null;var t=Math.round(100*this.sound.currentTime)/100;return isNaN(t)?e.defaults.placeholder:t},this.setPercent=function(t){return h?this.setTime(e.fromPercent(t,this.sound.duration)):this},this.getPercent=function(){if(!h)return null;var t=Math.round(e.toPercent(this.sound.currentTime,this.sound.duration));return isNaN(t)?e.defaults.placeholder:t},this.setSpeed=function(t){return h?(this.sound.playbackRate=t,this):this},this.getSpeed=function(){return h?this.sound.playbackRate:null},this.getDuration=function(){if(!h)return null;var t=Math.round(100*this.sound.duration)/100;return isNaN(t)?e.defaults.placeholder:t},this.getPlayed=function(){return h?i(this.sound.played):null},this.getBuffered=function(){return h?i(this.sound.buffered):null},this.getSeekable=function(){return h?i(this.sound.seekable):null},this.getErrorCode=function(){return h&&this.sound.error?this.sound.error.code:0},this.getErrorMessage=function(){if(!h)return null;switch(this.getErrorCode()){case 1:return"MEDIA_ERR_ABORTED";case 2:return"MEDIA_ERR_NETWORK";case 3:return"MEDIA_ERR_DECODE";case 4:return"MEDIA_ERR_SRC_NOT_SUPPORTED";default:return null}},this.getStateCode=function(){return h?this.sound.readyState:null},this.getStateMessage=function(){if(!h)return null;switch(this.getStateCode()){case 0:return"HAVE_NOTHING";case 1:return"HAVE_METADATA";case 2:return"HAVE_CURRENT_DATA";case 3:return"HAVE_FUTURE_DATA";case 4:return"HAVE_ENOUGH_DATA";default:return null}},this.getNetworkStateCode=function(){return h?this.sound.networkState:null},this.getNetworkStateMessage=function(){if(!h)return null;switch(this.getNetworkStateCode()){case 0:return"NETWORK_EMPTY";case 1:return"NETWORK_IDLE";case 2:return"NETWORK_LOADING";case 3:return"NETWORK_NO_SOURCE";default:return null}},this.set=function(t,e){return h?(this.sound[t]=e,this):this},this.get=function(t){return h?t?this.sound[t]:this.sound:null},this.bind=function(t,e){if(!h)return this;t=t.split(" ");for(var n=this,i=function(t){e.call(n,t)},u=0;t.length>u;u++){var s=t[u],r=s;s=r.split(".")[0],o.push({idx:r,func:i}),this.sound.addEventListener(s,i,!0)}return this},this.unbind=function(t){if(!h)return this;t=t.split(" ");for(var e=0;t.length>e;e++)for(var n=t[e],i=n.split(".")[0],u=0;o.length>u;u++){var s=o[u].idx.split(".");(o[u].idx===n||s[1]&&s[1]===n.replace(".",""))&&(this.sound.removeEventListener(i,o[u].func,!0),o.splice(u,1))}return this},this.bindOnce=function(t,e){if(!h)return this;var n=this;return a[r++]=!1,this.bind(t+"."+r,function(){a[r]||(a[r]=!0,e.call(n)),n.unbind(t+"."+r)}),this},this.trigger=function(t,e){if(!h)return this;t=t.split(" ");for(var n=0;t.length>n;n++)for(var i=t[n],u=0;o.length>u;u++){var r=o[u].idx.split(".");if(o[u].idx===i||r[0]&&r[0]===i.replace(".","")){var a=s.createEvent("HTMLEvents");a.initEvent(r[0],!1,!0),a.originalEvent=e,this.sound.dispatchEvent(a)}}return this},this.fadeTo=function(t,n,i){function u(){setTimeout(function(){t>s&&t>o.volume?(o.setVolume(o.volume+=1),u()):s>t&&o.volume>t?(o.setVolume(o.volume-=1),u()):i instanceof Function&&i.apply(o)},r)}if(!h)return this;n instanceof Function?(i=n,n=e.defaults.duration):n=n||e.defaults.duration;var s=this.volume,r=n/Math.abs(s-t),o=this;return this.play(),this.whenReady(function(){u()}),this},this.fadeIn=function(t,e){return h?this.setVolume(0).fadeTo(100,t,e):this},this.fadeOut=function(t,e){return h?this.fadeTo(0,t,e):this},this.fadeWith=function(t,e){return h?(this.fadeOut(e,function(){this.stop()}),t.play().fadeIn(e),this):this},this.whenReady=function(t){if(!h)return null;var e=this;0===this.sound.readyState?this.bind("canplay.buzzwhenready",function(){t.call(e)}):t.call(e)},this.addSource=function(t){var n=this,i=s.createElement("source");return i.src=t,e.types[u(t)]&&(i.type=e.types[u(t)]),this.sound.appendChild(i),i.addEventListener("error",function(t){n.sound.networkState=3,n.trigger("sourceerror",t)}),i},h&&t){for(var d in e.defaults)e.defaults.hasOwnProperty(d)&&void 0===n[d]&&(n[d]=e.defaults[d]);if(this.sound=s.createElement("audio"),n.webAudioApi&&e.audioCtx&&(this.source=e.audioCtx.createMediaElementSource(this.sound),this.source.connect(e.audioCtx.destination)),t instanceof Array)for(var l in t)t.hasOwnProperty(l)&&this.addSource(t[l]);else if(n.formats.length)for(var c in n.formats)n.formats.hasOwnProperty(c)&&this.addSource(t+"."+n.formats[c]);else this.addSource(t);n.loop&&this.loop(),n.autoplay&&(this.sound.autoplay="autoplay"),this.sound.preload=n.preload===!0?"auto":n.preload===!1?"none":n.preload,this.setVolume(n.volume),e.sounds.push(this)}},group:function(t){function e(){for(var e=n(null,arguments),i=e.shift(),u=0;t.length>u;u++)t[u][i].apply(t[u],e)}function n(t,e){return t instanceof Array?t:Array.prototype.slice.call(e)}t=n(t,arguments),this.getSounds=function(){return t},this.add=function(e){e=n(e,arguments);for(var i=0;e.length>i;i++)t.push(e[i])},this.remove=function(e){e=n(e,arguments);for(var i=0;e.length>i;i++)for(var u=0;t.length>u;u++)if(t[u]===e[i]){t.splice(u,1);break}},this.load=function(){return e("load"),this},this.play=function(){return e("play"),this},this.togglePlay=function(){return e("togglePlay"),this},this.pause=function(t){return e("pause",t),this},this.stop=function(){return e("stop"),this},this.mute=function(){return e("mute"),this},this.unmute=function(){return e("unmute"),this},this.toggleMute=function(){return e("toggleMute"),this},this.setVolume=function(t){return e("setVolume",t),this},this.increaseVolume=function(t){return e("increaseVolume",t),this},this.decreaseVolume=function(t){return e("decreaseVolume",t),this},this.loop=function(){return e("loop"),this},this.unloop=function(){return e("unloop"),this},this.setSpeed=function(t){return e("setSpeed",t),this},this.setTime=function(t){return e("setTime",t),this},this.set=function(t,n){return e("set",t,n),this},this.bind=function(t,n){return e("bind",t,n),this},this.unbind=function(t){return e("unbind",t),this},this.bindOnce=function(t,n){return e("bindOnce",t,n),this},this.trigger=function(t){return e("trigger",t),this},this.fade=function(t,n,i,u){return e("fade",t,n,i,u),this},this.fadeIn=function(t,n){return e("fadeIn",t,n),this},this.fadeOut=function(t,n){return e("fadeOut",t,n),this}},all:function(){return new e.group(e.sounds)},isSupported:function(){return!!e.el.canPlayType},isOGGSupported:function(){return!!e.el.canPlayType&&e.el.canPlayType('audio/ogg; codecs="vorbis"')},isWAVSupported:function(){return!!e.el.canPlayType&&e.el.canPlayType('audio/wav; codecs="1"')},isMP3Supported:function(){return!!e.el.canPlayType&&e.el.canPlayType("audio/mpeg;")},isAACSupported:function(){return!!e.el.canPlayType&&(e.el.canPlayType("audio/x-m4a;")||e.el.canPlayType("audio/aac;"))},toTimer:function(t,e){var n,i,u;return n=Math.floor(t/3600),n=isNaN(n)?"--":n>=10?n:"0"+n,i=e?Math.floor(t/60%60):Math.floor(t/60),i=isNaN(i)?"--":i>=10?i:"0"+i,u=Math.floor(t%60),u=isNaN(u)?"--":u>=10?u:"0"+u,e?n+":"+i+":"+u:i+":"+u},fromTimer:function(t){var e=(""+t).split(":");return e&&3===e.length&&(t=3600*parseInt(e[0],10)+60*parseInt(e[1],10)+parseInt(e[2],10)),e&&2===e.length&&(t=60*parseInt(e[0],10)+parseInt(e[1],10)),t},toPercent:function(t,e,n){var i=Math.pow(10,n||0);return Math.round(100*t/e*i)/i},fromPercent:function(t,e,n){var i=Math.pow(10,n||0);return Math.round(e/100*t*i)/i}};return e}); \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index fa6f6529f..e6300ec27 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -10,7 +10,7 @@ module.exports = { path: __dirname + '/rainloop/v/0.0.0/static/js/', filename: '[name].js', publicPath: 'rainloop/v/0.0.0/static/js/', - chunkFilename: '[chunkhash].chunk.js' + chunkFilename: '[chunkhash].subapp.js' }, plugins: [ // new webpack.optimize.CommonsChunkPlugin('common.js'), @@ -38,6 +38,7 @@ module.exports = { 'hasher': 'window.hasher', 'Jua': 'window.Jua', 'Autolinker': 'window.Autolinker', + 'buzz': 'window.buzz', 'ssm': 'window.ssm', 'key': 'window.key', '_': 'window._',