Welcome page branding option

This commit is contained in:
RainLoop Team 2015-04-10 02:05:49 +04:00
parent acb013fbb5
commit 351c12c002
50 changed files with 531 additions and 160 deletions

View file

@ -1219,6 +1219,11 @@
kn.showScreenPopup(require('View/Popup/TwoFactorConfiguration'), [true]); kn.showScreenPopup(require('View/Popup/TwoFactorConfiguration'), [true]);
}; };
AppUser.prototype.bootstartWelcomePopup = function (sUrl)
{
kn.showScreenPopup(require('View/Popup/WelcomePage'), [sUrl]);
};
AppUser.prototype.bootstartLoginScreen = function () AppUser.prototype.bootstartLoginScreen = function ()
{ {
Globals.$html.removeClass('rl-user-auth').addClass('rl-user-no-auth'); Globals.$html.removeClass('rl-user-auth').addClass('rl-user-no-auth');
@ -1416,6 +1421,13 @@
Plugins.runHook('rl-start-user-screens'); Plugins.runHook('rl-start-user-screens');
Events.pub('rl.bootstart-user-screens'); Events.pub('rl.bootstart-user-screens');
if (Settings.settingsGet('WelcomePageUrl'))
{
_.delay(function () {
self.bootstartWelcomePopup(Settings.settingsGet('WelcomePageUrl'));
}, 1000);
}
if (!!Settings.settingsGet('AccountSignMe') && window.navigator.registerProtocolHandler) if (!!Settings.settingsGet('AccountSignMe') && window.navigator.registerProtocolHandler)
{ {
_.delay(function () { _.delay(function () {

View file

@ -5,6 +5,7 @@
var var
_ = require('_'), _ = require('_'),
$ = require('$'),
AbstractComponent = require('Component/Abstract') AbstractComponent = require('Component/Abstract')
; ;
@ -20,13 +21,26 @@
{ {
AbstractComponent.call(this); AbstractComponent.call(this);
if (oParams.component && oParams.component.templateNodes && oParams.element) if (oParams.component && oParams.component.templateNodes && oParams.element &&
oParams.element[0] && oParams.element[0].outerHTML)
{ {
oParams.element.text(''); var sScript = oParams.element[0].outerHTML;
if (oParams.component.templateNodes[0] && oParams.component.templateNodes[0].nodeValue) sScript = sScript
.replace(/<x-script/i, '<script')
.replace(/<b><\/b><\/x-script>/i, '</script>')
;
if (sScript)
{ {
oParams.element.text('');
oParams.element.replaceWith( oParams.element.replaceWith(
$('<script></script>').text(oParams.component.templateNodes[0].nodeValue)); $(sScript).text(oParams.component.templateNodes[0] &&
oParams.component.templateNodes[0].nodeValue ?
oParams.component.templateNodes[0].nodeValue : ''));
}
else
{
oParams.element.remove();
} }
} }
} }

42
dev/External/ko.js vendored
View file

@ -57,16 +57,16 @@
'init': function (oElement, fValueAccessor) { 'init': function (oElement, fValueAccessor) {
var var
$oEl = null,
bi18n = true, bi18n = true,
sValue = '', sValue = '',
Translator = null, Translator = null,
$oEl = $(oElement),
bMobile = 'on' === ($oEl.data('tooltip-mobile') || 'off'),
Globals = require('Common/Globals') Globals = require('Common/Globals')
; ;
if (!Globals.bMobileDevice) if (!Globals.bMobileDevice || bMobile)
{ {
$oEl = $(oElement);
bi18n = 'on' === ($oEl.data('tooltip-i18n') || 'on'); bi18n = 'on' === ($oEl.data('tooltip-i18n') || 'on');
sValue = bi18n ? ko.unwrap(fValueAccessor()) : fValueAccessor()(); sValue = bi18n ? ko.unwrap(fValueAccessor()) : fValueAccessor()();
@ -74,6 +74,7 @@
{ {
oElement.__opentip = new Opentip(oElement, { oElement.__opentip = new Opentip(oElement, {
'style': 'rainloopTip', 'style': 'rainloopTip',
'showOn': 'mouseover click',
'element': oElement, 'element': oElement,
'tipJoint': $oEl.data('tooltip-join') || 'bottom' 'tipJoint': $oEl.data('tooltip-join') || 'bottom'
}); });
@ -120,12 +121,14 @@
var var
bi18n = true, bi18n = true,
sValue = '', sValue = '',
$oEl = $(oElement),
bMobile = 'on' === ($oEl.data('tooltip-mobile') || 'off'),
Globals = require('Common/Globals') Globals = require('Common/Globals')
; ;
if (!Globals.bMobileDevice && oElement.__opentip) if ((!Globals.bMobileDevice || bMobile) && oElement.__opentip)
{ {
bi18n = 'on' === ($(oElement).data('tooltip-i18n') || 'on'); bi18n = 'on' === ($oEl.data('tooltip-i18n') || 'on');
sValue = bi18n ? ko.unwrap(fValueAccessor()) : fValueAccessor()(); sValue = bi18n ? ko.unwrap(fValueAccessor()) : fValueAccessor()();
if (sValue) if (sValue)
@ -150,6 +153,8 @@
oElement.__opentip = new Opentip(oElement, { oElement.__opentip = new Opentip(oElement, {
'style': 'rainloopTestTip', 'style': 'rainloopTestTip',
'showOn': 'mouseover click',
'hideOn': 'mouseout click',
'element': oElement, 'element': oElement,
'tipJoint': $oEl.data('tooltip-join') || 'top' 'tipJoint': $oEl.data('tooltip-join') || 'top'
}); });
@ -183,21 +188,20 @@
} }
else else
{ {
if ($oEl.is(':visible')) _.delay(function () {
{ if ($oEl.is(':visible'))
oOpenTips.activate(); {
oOpenTips.setContent(sValue); oOpenTips.activate();
oOpenTips.setContent(sValue);
_.delay(function () {
oOpenTips.show(); oOpenTips.show();
}, 100); }
} else
else {
{ oOpenTips.hide();
oOpenTips.hide(); oOpenTips.setContent('');
oOpenTips.setContent(''); oOpenTips.deactivate();
oOpenTips.deactivate(); }
} }, 100);
} }
} }
} }

View file

@ -89,7 +89,6 @@
}, 500); }, 500);
}; };
UserAjaxUserPromises.prototype.folderDelete = function (sFolderFullNameRaw, fTrigger) UserAjaxUserPromises.prototype.folderDelete = function (sFolderFullNameRaw, fTrigger)
{ {
return this.postRequest('FolderDelete', fTrigger, { return this.postRequest('FolderDelete', fTrigger, {
@ -113,6 +112,11 @@
}); });
}; };
UserAjaxUserPromises.prototype.welcomeClose = function ()
{
return this.postRequest('WelcomeClose');
};
// UserAjaxUserPromises.prototype.messageList = function (sFolderFullNameRaw, iOffset, iLimit, sSearch, fTrigger) // UserAjaxUserPromises.prototype.messageList = function (sFolderFullNameRaw, iOffset, iLimit, sSearch, fTrigger)
// { // {
// sFolderFullNameRaw = Utils.pString(sFolderFullNameRaw); // sFolderFullNameRaw = Utils.pString(sFolderFullNameRaw);

View file

@ -7,7 +7,8 @@
_ = require('_'), _ = require('_'),
ko = require('ko'), ko = require('ko'),
Utils = require('Common/Utils') Utils = require('Common/Utils'),
Translator = require('Common/Translator')
; ;
/** /**
@ -47,6 +48,21 @@
this.userCss = ko.observable(Settings.settingsGet('UserCss')); this.userCss = ko.observable(Settings.settingsGet('UserCss'));
this.userCss.trigger = ko.observable(Enums.SaveSettingsStep.Idle); this.userCss.trigger = ko.observable(Enums.SaveSettingsStep.Idle);
this.welcomePageUrl = ko.observable(Settings.settingsGet('WelcomePageUrl'));
this.welcomePageUrl.trigger = ko.observable(Enums.SaveSettingsStep.Idle);
this.welcomePageDisplay = ko.observable(Settings.settingsGet('WelcomePageDisplay'));
this.welcomePageDisplay.trigger = ko.observable(Enums.SaveSettingsStep.Idle);
this.welcomePageDisplay.options = ko.computed(function () {
Translator.trigger();
return [
{'optValue': 'none', 'optText': Translator.i18n('TAB_BRANDING/OPTION_WELCOME_PAGE_DISPLAY_NONE')},
{'optValue': 'once', 'optText': Translator.i18n('TAB_BRANDING/OPTION_WELCOME_PAGE_DISPLAY_ONCE')},
{'optValue': 'always', 'optText': Translator.i18n('TAB_BRANDING/OPTION_WELCOME_PAGE_DISPLAY_ALWAYS')}
];
});
this.loginPowered = ko.observable(!!Settings.settingsGet('LoginPowered')); this.loginPowered = ko.observable(!!Settings.settingsGet('LoginPowered'));
} }
@ -69,7 +85,9 @@
f5 = Utils.settingsSaveHelperSimpleFunction(self.loginCss.trigger, self), f5 = Utils.settingsSaveHelperSimpleFunction(self.loginCss.trigger, self),
f6 = Utils.settingsSaveHelperSimpleFunction(self.userLogo.trigger, self), f6 = Utils.settingsSaveHelperSimpleFunction(self.userLogo.trigger, self),
f7 = Utils.settingsSaveHelperSimpleFunction(self.loginBackground.trigger, self), f7 = Utils.settingsSaveHelperSimpleFunction(self.loginBackground.trigger, self),
f8 = Utils.settingsSaveHelperSimpleFunction(self.userCss.trigger, self) f8 = Utils.settingsSaveHelperSimpleFunction(self.userCss.trigger, self),
f9 = Utils.settingsSaveHelperSimpleFunction(self.welcomePageUrl.trigger, self),
f10 = Utils.settingsSaveHelperSimpleFunction(self.welcomePageDisplay.trigger, self)
; ;
self.title.subscribe(function (sValue) { self.title.subscribe(function (sValue) {
@ -120,6 +138,18 @@
}); });
}); });
self.welcomePageUrl.subscribe(function (sValue) {
Remote.saveAdminConfig(f9, {
'WelcomePageUrl': Utils.trim(sValue)
});
});
self.welcomePageDisplay.subscribe(function (sValue) {
Remote.saveAdminConfig(f10, {
'WelcomePageDisplay': Utils.trim(sValue)
});
});
self.loginPowered.subscribe(function (bValue) { self.loginPowered.subscribe(function (bValue) {
Remote.saveAdminConfig(null, { Remote.saveAdminConfig(null, {
'LoginPowered': bValue ? '1' : '0' 'LoginPowered': bValue ? '1' : '0'

View file

@ -16,6 +16,7 @@
{ {
this.oSettings = window['rainloopAppData'] || {}; this.oSettings = window['rainloopAppData'] || {};
this.oSettings = Utils.isNormal(this.oSettings) ? this.oSettings : {}; this.oSettings = Utils.isNormal(this.oSettings) ? this.oSettings : {};
// window.console.log(this.oSettings);
} }
SettingsStorage.prototype.oSettings = null; SettingsStorage.prototype.oSettings = null;

View file

@ -54,6 +54,7 @@
@import "Components.less"; @import "Components.less";
@import "SystemDropDown.less"; @import "SystemDropDown.less";
@import "Login.less"; @import "Login.less";
@import "WelcomPage.less";
@import "Ask.less"; @import "Ask.less";
@import "Shortcuts.less"; @import "Shortcuts.less";
@import "FolderList.less"; @import "FolderList.less";

View file

@ -103,5 +103,9 @@
.legend { .legend {
width: 670px; width: 670px;
} }
.nav-tabs {
width: 670px;
}
} }
} }

View file

@ -0,0 +1,9 @@
.popups {
.b-welcom-page-content {
.modal-header {
background-color: #fff;
}
}
}

View file

@ -162,6 +162,7 @@
this.testingDone(false); this.testingDone(false);
this.testingImapError(false); this.testingImapError(false);
this.testingSieveError(false);
this.testingSmtpError(false); this.testingSmtpError(false);
this.testing(true); this.testing(true);
@ -295,26 +296,29 @@
this.testingDone(true); this.testingDone(true);
this.testingImapError(true !== oData.Result.Imap); this.testingImapError(true !== oData.Result.Imap);
this.testingSmtpError(true !== oData.Result.Smtp);
this.testingSieveError(true !== oData.Result.Sieve); this.testingSieveError(true !== oData.Result.Sieve);
this.testingSmtpError(true !== oData.Result.Smtp);
if (this.testingImapError() && oData.Result.Imap) if (this.testingImapError() && oData.Result.Imap)
{ {
bImap = true; bImap = true;
this.testingImapErrorDesc('');
this.testingImapErrorDesc(oData.Result.Imap); this.testingImapErrorDesc(oData.Result.Imap);
} }
if (this.testingSmtpError() && oData.Result.Smtp)
{
this.testingSmtpErrorDesc(oData.Result.Smtp);
}
if (this.testingSieveError() && oData.Result.Sieve) if (this.testingSieveError() && oData.Result.Sieve)
{ {
bSieve = true; bSieve = true;
this.testingSieveErrorDesc('');
this.testingSieveErrorDesc(oData.Result.Sieve); this.testingSieveErrorDesc(oData.Result.Sieve);
} }
if (this.testingSmtpError() && oData.Result.Smtp)
{
this.testingSmtpErrorDesc('');
this.testingSmtpErrorDesc(oData.Result.Smtp);
}
if (this.sieveSettings()) if (this.sieveSettings())
{ {
if (!bSieve && bImap) if (!bSieve && bImap)
@ -333,8 +337,8 @@
else else
{ {
this.testingImapError(true); this.testingImapError(true);
this.testingSmtpError(true);
this.testingSieveError(true); this.testingSieveError(true);
this.testingSmtpError(true);
this.sieveSettings(false); this.sieveSettings(false);
} }
}; };
@ -365,8 +369,8 @@
this.testing(false); this.testing(false);
this.testingDone(false); this.testingDone(false);
this.testingImapError(false); this.testingImapError(false);
this.testingSmtpError(false);
this.testingSieveError(false); this.testingSieveError(false);
this.testingSmtpError(false);
}; };
DomainPopupView.prototype.onHide = function () DomainPopupView.prototype.onHide = function ()

View file

@ -0,0 +1,62 @@
(function () {
'use strict';
var
_ = require('_'),
ko = require('ko'),
Promises = require('Promises/User/Ajax'),
kn = require('Knoin/Knoin'),
AbstractView = require('Knoin/AbstractView')
;
/**
* @constructor
* @extends AbstractView
*/
function WelcomePagePopupView()
{
AbstractView.call(this, 'Popups', 'PopupsWelcomePage');
this.welcomePageURL = ko.observable('');
this.closeFocused = ko.observable(false);
kn.constructorEnd(this);
}
kn.extendAsViewModel(['View/Popup/WelcomePage', 'WelcomePagePopupViewModel'], WelcomePagePopupView);
_.extend(WelcomePagePopupView.prototype, AbstractView.prototype);
WelcomePagePopupView.prototype.clearPopup = function ()
{
this.welcomePageURL('');
this.closeFocused(false);
};
/**
* @param {string} sUrl
*/
WelcomePagePopupView.prototype.onShow = function (sUrl)
{
this.clearPopup();
this.welcomePageURL(sUrl);
};
WelcomePagePopupView.prototype.onShowWithDelay = function ()
{
this.closeFocused(true);
};
WelcomePagePopupView.prototype.onHide = function ()
{
Promises.welcomeClose();
};
module.exports = WelcomePagePopupView;
}());

View file

@ -843,7 +843,7 @@
; ;
// exit fullscreen, back // exit fullscreen, back
key('esc', Enums.KeyState.MessageView, _.bind(this.escShortcuts, this)); key('esc, backspace', Enums.KeyState.MessageView, _.bind(this.escShortcuts, this));
// fullscreen // fullscreen
key('enter', Enums.KeyState.MessageView, function () { key('enter', Enums.KeyState.MessageView, function () {

View file

@ -121,7 +121,7 @@ cfg.paths.js = {
openpgp: { openpgp: {
name: 'openpgp.js', name: 'openpgp.js',
src: [ src: [
'vendors/openpgp/openpgp-0.10.1.min.js' 'vendors/openpgp/openpgp-0.7.2.min.js'
] ]
}, },
encrypt: { encrypt: {

View file

@ -2,7 +2,7 @@
"name": "RainLoop", "name": "RainLoop",
"title": "RainLoop Webmail", "title": "RainLoop Webmail",
"version": "1.8.3", "version": "1.8.3",
"release": "295", "release": "297",
"description": "Simple, modern & fast web-based email client", "description": "Simple, modern & fast web-based email client",
"homepage": "http://rainloop.net", "homepage": "http://rainloop.net",
"main": "gulpfile.js", "main": "gulpfile.js",

View file

@ -232,7 +232,7 @@ class HtmlUtils
{ {
if ($oElement) if ($oElement)
{ {
if (\preg_match('/http[s]?:\/\//i', $sUrl)) if (\preg_match('/http[s]?:\/\//i', $sUrl) || '//' === \substr($sUrl, 0, 2))
{ {
$bHasExternals = true; $bHasExternals = true;
if (!$bDoNotReplaceExternalUrl) if (!$bDoNotReplaceExternalUrl)
@ -452,7 +452,7 @@ class HtmlUtils
foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement) foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement)
{ {
if (\in_array(\strtolower($oElement->tagName), array('svg', 'head', 'link', if (\in_array(\strtolower($oElement->tagName), array('svg', 'head', 'link',
'base', 'meta', 'title', 'style', 'script', 'bgsound', 'keygen', 'source', 'base', 'meta', 'title', 'style', 'x-script', 'script', 'bgsound', 'keygen', 'source',
'object', 'embed', 'applet', 'mocha', 'iframe', 'frame', 'frameset', 'video', 'audio')) && isset($oElement->parentNode)) 'object', 'embed', 'applet', 'mocha', 'iframe', 'frame', 'frameset', 'video', 'audio')) && isset($oElement->parentNode))
{ {
@$oElement->parentNode->removeChild($oElement); @$oElement->parentNode->removeChild($oElement);
@ -546,8 +546,8 @@ class HtmlUtils
// } // }
foreach (array( foreach (array(
'id', 'class', 'contenteditable', 'designmode', 'formaction', 'data-bind', 'xmlns', 'id', 'class', 'contenteditable', 'designmode', 'formaction',
'srcset' 'data-bind', 'xmlns', 'srcset'
) as $sAttr) ) as $sAttr)
{ {
@$oElement->removeAttribute($sAttr); @$oElement->removeAttribute($sAttr);
@ -566,7 +566,8 @@ class HtmlUtils
if ($oElement->hasAttribute('href')) if ($oElement->hasAttribute('href'))
{ {
$sHref = \trim($oElement->getAttribute('href')); $sHref = \trim($oElement->getAttribute('href'));
if (!\preg_match('/^(http[s]?|ftp|skype|mailto):/i', $sHref)) if (!\preg_match('/^(http[s]?|ftp|skype|mailto):/i', $sHref) ||
'//' !== \substr($sHref, 0, 2))
{ {
$oElement->setAttribute('data-x-broken-href', $sHref); $oElement->setAttribute('data-x-broken-href', $sHref);
$oElement->setAttribute('href', 'javascript:false'); $oElement->setAttribute('href', 'javascript:false');
@ -594,7 +595,8 @@ class HtmlUtils
} }
else else
{ {
if (\preg_match('/http[s]?:\/\//i', $sSrc)) if (\preg_match('/^http[s]?:\/\//i', $sSrc) ||
'//' === \substr($sSrc, 0, 2))
{ {
if ($bDoNotReplaceExternalUrl) if ($bDoNotReplaceExternalUrl)
{ {
@ -615,7 +617,7 @@ class HtmlUtils
$bHasExternals = true; $bHasExternals = true;
} }
else if ('data:image/' === \strtolower(\substr(\trim($sSrc), 0, 11))) else if ('data:image/' === \strtolower(\substr($sSrc, 0, 11)))
{ {
$oElement->setAttribute('src', $sSrc); $oElement->setAttribute('src', $sSrc);
} }
@ -745,7 +747,7 @@ class HtmlUtils
{ {
$oElement->removeAttribute('data-x-additional-src'); $oElement->removeAttribute('data-x-additional-src');
} }
if ($oElement->hasAttribute('data-x-additional-style-url')) if ($oElement->hasAttribute('data-x-additional-style-url'))
{ {
$oElement->removeAttribute('data-x-additional-style-url'); $oElement->removeAttribute('data-x-additional-style-url');

View file

@ -1286,6 +1286,8 @@ class Actions
'LoginCss' => '', 'LoginCss' => '',
'UserLogo' => '', 'UserLogo' => '',
'UserCss' => '', 'UserCss' => '',
'WelcomePageUrl' => '',
'WelcomePageDisplay' => 'none',
'IncludeCss' => '', 'IncludeCss' => '',
'IncludeBackground' => '', 'IncludeBackground' => '',
'Token' => $oConfig->Get('security', 'csrf_protection', false) ? \RainLoop\Utils::GetCsrfToken() : '', 'Token' => $oConfig->Get('security', 'csrf_protection', false) ? \RainLoop\Utils::GetCsrfToken() : '',
@ -1352,6 +1354,8 @@ class Actions
$aResult['LoginPowered'] = !!$oConfig->Get('branding', 'login_powered', true); $aResult['LoginPowered'] = !!$oConfig->Get('branding', 'login_powered', true);
$aResult['UserLogo'] = $oConfig->Get('branding', 'user_logo', ''); $aResult['UserLogo'] = $oConfig->Get('branding', 'user_logo', '');
$aResult['UserCss'] = $oConfig->Get('branding', 'user_css', ''); $aResult['UserCss'] = $oConfig->Get('branding', 'user_css', '');
$aResult['WelcomePageUrl'] = $oConfig->Get('branding', 'welcome_page_url', '');
$aResult['WelcomePageDisplay'] = \strtolower($oConfig->Get('branding', 'welcome_page_display', 'none'));
} }
$aResult['LoadingDescriptionEsc'] = \htmlspecialchars($aResult['LoadingDescription'], ENT_QUOTES|ENT_IGNORE, 'UTF-8'); $aResult['LoadingDescriptionEsc'] = \htmlspecialchars($aResult['LoadingDescription'], ENT_QUOTES|ENT_IGNORE, 'UTF-8');
@ -1414,6 +1418,24 @@ class Actions
$oSettings = $this->SettingsProvider()->Load($oAccount); $oSettings = $this->SettingsProvider()->Load($oAccount);
$oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount);
if (!$oAccount->IsAdditionalAccount() && !empty($aResult['WelcomePageUrl']) &&
('once' === $aResult['WelcomePageDisplay'] || 'always' === $aResult['WelcomePageDisplay']))
{
if ('once' === $aResult['WelcomePageDisplay'])
{
if ($aResult['WelcomePageUrl'] === $oSettings->GetConf('LastWelcomePage', ''))
{
$aResult['WelcomePageUrl'] = '';
$aResult['WelcomePageDisplay'] = '';
}
}
}
else
{
$aResult['WelcomePageUrl'] = '';
$aResult['WelcomePageDisplay'] = '';
}
} }
else else
{ {
@ -1424,6 +1446,9 @@ class Actions
$aResult['DevEmail'] = $oConfig->Get('labs', 'dev_email', ''); $aResult['DevEmail'] = $oConfig->Get('labs', 'dev_email', '');
$aResult['DevPassword'] = $oConfig->Get('labs', 'dev_password', ''); $aResult['DevPassword'] = $oConfig->Get('labs', 'dev_password', '');
$aResult['WelcomePageUrl'] = '';
$aResult['WelcomePageDisplay'] = '';
} }
$aResult['AllowGoogleSocial'] = (bool) $oConfig->Get('social', 'google_enable', false); $aResult['AllowGoogleSocial'] = (bool) $oConfig->Get('social', 'google_enable', false);
@ -3247,7 +3272,11 @@ class Actions
$this->setConfigFromParams($oConfig, 'Title', 'webmail', 'title', 'string'); $this->setConfigFromParams($oConfig, 'Title', 'webmail', 'title', 'string');
$this->setConfigFromParams($oConfig, 'LoadingDescription', 'webmail', 'loading_description', 'string'); $this->setConfigFromParams($oConfig, 'LoadingDescription', 'webmail', 'loading_description', 'string');
if ($this->HasOneOfActionParams(array('LoginLogo', 'LoginBackground', 'LoginDescription', 'LoginCss', 'LoginPowered', 'UserLogo', 'UserCss')) && $this->PremType()) if ($this->HasOneOfActionParams(array(
'LoginLogo', 'LoginBackground', 'LoginDescription', 'LoginCss', 'LoginPowered',
'UserLogo', 'UserCss',
'WelcomePageUrl', 'WelcomePageDisplay'
)) && $this->PremType())
{ {
$this->setConfigFromParams($oConfig, 'LoginLogo', 'branding', 'login_logo', 'string'); $this->setConfigFromParams($oConfig, 'LoginLogo', 'branding', 'login_logo', 'string');
$this->setConfigFromParams($oConfig, 'LoginBackground', 'branding', 'login_background', 'string'); $this->setConfigFromParams($oConfig, 'LoginBackground', 'branding', 'login_background', 'string');
@ -3257,6 +3286,9 @@ class Actions
$this->setConfigFromParams($oConfig, 'UserLogo', 'branding', 'user_logo', 'string'); $this->setConfigFromParams($oConfig, 'UserLogo', 'branding', 'user_logo', 'string');
$this->setConfigFromParams($oConfig, 'UserCss', 'branding', 'user_css', 'string'); $this->setConfigFromParams($oConfig, 'UserCss', 'branding', 'user_css', 'string');
$this->setConfigFromParams($oConfig, 'WelcomePageUrl', 'branding', 'welcome_page_url', 'string');
$this->setConfigFromParams($oConfig, 'WelcomePageDisplay', 'branding', 'welcome_page_display', 'string');
} }
$this->setConfigFromParams($oConfig, 'TokenProtection', 'security', 'csrf_protection', 'bool'); $this->setConfigFromParams($oConfig, 'TokenProtection', 'security', 'csrf_protection', 'bool');
@ -4810,6 +4842,25 @@ class Actions
return $this->DefaultResponse(__FUNCTION__, true); return $this->DefaultResponse(__FUNCTION__, true);
} }
/**
* @return array
*/
public function DoWelcomeClose()
{
$oAccount = $this->getAccountFromToken();
if ($oAccount && !$oAccount->IsAdditionalAccount())
{
$oSettings = $this->SettingsProvider()->Load($oAccount);
$oSettings->SetConf('LastWelcomePage',
$this->Config()->Get('branding', 'welcome_page_url', ''));
return $this->DefaultResponse(__FUNCTION__,
$this->SettingsProvider()->Save($oAccount, $oSettings));
}
return $this->FalseResponse(__FUNCTION__);
}
/** /**
* @return array * @return array
*/ */
@ -8509,6 +8560,9 @@ class Actions
$sHtml = $this->Plugins()->ProcessTemplate($sName, $sHtml); $sHtml = $this->Plugins()->ProcessTemplate($sName, $sHtml);
$sHtml = \preg_replace('/\{\{INCLUDE\/([a-zA-Z]+)\/PLACE\}\}/', '', $sHtml); $sHtml = \preg_replace('/\{\{INCLUDE\/([a-zA-Z]+)\/PLACE\}\}/', '', $sHtml);
$sHtml = \preg_replace('/<script/i', '<x-script', $sHtml);
$sHtml = \preg_replace('/<\/script>/i', '</x-script>', $sHtml);
return \RainLoop\Utils::ClearHtmlOutput($sHtml); return \RainLoop\Utils::ClearHtmlOutput($sHtml);
} }

View file

@ -88,8 +88,10 @@ class Application extends \RainLoop\Config\AbstractConfig
'login_desc' => array(''), 'login_desc' => array(''),
'login_css' => array(''), 'login_css' => array(''),
'login_powered' => array(true), 'login_powered' => array(true),
'user_logo' => array(''), 'user_logo' => array(''),
'user_css' => array('') 'user_css' => array(''),
'welcome_page_url' => array(''),
'welcome_page_display' => array('none')
), ),
'contacts' => array( 'contacts' => array(

View file

@ -29,114 +29,164 @@
</div> </div>
</div> </div>
<br /> <br />
<div class="form-horizontal" data-bind="css: {'disabled-form': !capa()}"> <ul class="nav nav-tabs">
<div class="legend" data-i18n="TAB_BRANDING/LEGEND_LOGIN"></div> <li class="active">
<div class="control-group"> <a class="i18n" data-i18n="TAB_BRANDING/LEGEND_LOGIN"
<label class="control-label" data-i18n="TAB_BRANDING/LABEL_LOGIN_LOGO"></label> href="#branding-login-section-id" data-toggle="tab"></a>
<div class="controls"> </li>
<div data-bind="component: { <li>
name: 'Input', <a class="i18n" data-i18n="TAB_BRANDING/LEGEND_USER"
params: { href="#branding-user-section-id" data-toggle="tab"></a>
value: loginLogo, </li>
trigger: loginLogo.trigger, <li>
placeholder: 'https://', <a class="i18n" data-i18n="TAB_BRANDING/LEGEND_WELCOME_PAGE"
size: 5, href="#branding-welcome-page-section-id" data-toggle="tab"></a>
enable: capa </li>
} </ul>
}"></div> <br />
</div> <div class="row">
</div> <div class="tab-content span12">
<div class="control-group"> <div class="tab-pane active" id="branding-login-section-id">
<label class="control-label" data-i18n="TAB_BRANDING/LABEL_LOGIN_DESCRIPTION"></label>
<div class="controls"> <div class="form-horizontal" data-bind="css: {'disabled-form': !capa()}">
<div data-bind="component: { <div class="control-group">
name: 'Input', <label class="control-label" data-i18n="TAB_BRANDING/LABEL_LOGIN_LOGO"></label>
params: { <div class="controls">
value: loginDescription, <div data-bind="component: {
trigger: loginDescription.trigger, name: 'Input',
size: 5, params: {
enable: capa value: loginLogo,
} trigger: loginLogo.trigger,
}"></div> placeholder: 'https://',
</div> size: 5,
</div> enable: capa
<div class="control-group"> }
<label class="control-label" data-i18n="TAB_BRANDING/LABEL_LOGIN_BACKGROUND"></label> }"></div>
<div class="controls">
<div data-bind="component: {
name: 'Input',
params: {
value: loginBackground,
trigger: loginBackground.trigger,
placeholder: 'https://',
size: 5,
enable: capa
}
}"></div>
</div>
</div>
<div class="control-group">
<label class="control-label" data-i18n="TAB_BRANDING/LABEL_LOGIN_CUSTOM_CSS"></label>
<div class="controls">
<div class="custom-css-wrapper" data-bind="component: {
name: 'TextArea',
params: {
value: loginCss,
trigger: loginCss.trigger,
width: 495,
enable: capa,
rows: 7
}
}"></div>
</div>
</div>
<div class="control-group">
<div class="controls">
<div data-bind="component: {
name: 'Checkbox',
params: {
enable: capa,
label: 'TAB_BRANDING/LABEL_LOGIN_SHOW_POWERED_LINK',
value: loginPowered
}
}"></div>
</div>
</div>
<div class="legend" data-i18n="TAB_BRANDING/LEGEND_USER"></div>
<!--
<div class="control-group">
<label class="control-label" data-i18n="TAB_BRANDING/LABEL_USER_LOGO"></label>
<div class="controls">
<div data-bind="component: {
name: 'Input',
params: {
value: userLogo,
trigger: userLogo.trigger,
placeholder: 'https://',
size: 5,
enable: capa
}
}"></div>
</div>
</div>
-->
<div class="control-group">
<label class="control-label" data-i18n="TAB_BRANDING/LABEL_USER_CUSTOM_CSS"></label>
<div class="controls">
<div class="custom-css-wrapper" data-bind="component: {
name: 'TextArea',
params: {
value: userCss,
trigger: userCss.trigger,
width: 495,
enable: capa,
rows: 7
}
}"></div>
</div>
</div>
<div class="row" data-bind="visible: !capa()">
<div class="alert span8" style="margin-top: 10px;" data-i18n="[html]TAB_BRANDING/HTML_ALERT_PREMIUM"></div>
</div> </div>
</div> </div>
<div class="control-group">
<label class="control-label" data-i18n="TAB_BRANDING/LABEL_LOGIN_DESCRIPTION"></label>
<div class="controls">
<div data-bind="component: {
name: 'Input',
params: {
value: loginDescription,
trigger: loginDescription.trigger,
size: 5,
enable: capa
}
}"></div>
</div>
</div>
<div class="control-group">
<label class="control-label" data-i18n="TAB_BRANDING/LABEL_LOGIN_BACKGROUND"></label>
<div class="controls">
<div data-bind="component: {
name: 'Input',
params: {
value: loginBackground,
trigger: loginBackground.trigger,
placeholder: 'https://',
size: 5,
enable: capa
}
}"></div>
</div>
</div>
<div class="control-group">
<label class="control-label" data-i18n="TAB_BRANDING/LABEL_LOGIN_CUSTOM_CSS"></label>
<div class="controls">
<div class="custom-css-wrapper" data-bind="component: {
name: 'TextArea',
params: {
value: loginCss,
trigger: loginCss.trigger,
width: 495,
enable: capa,
rows: 7
}
}"></div>
</div>
</div>
<div class="control-group">
<div class="controls">
<div data-bind="component: {
name: 'Checkbox',
params: {
enable: capa,
label: 'TAB_BRANDING/LABEL_LOGIN_SHOW_POWERED_LINK',
value: loginPowered
}
}"></div>
</div>
</div>
</div>
</div>
<div class="tab-pane" id="branding-user-section-id">
<div class="form-horizontal" data-bind="css: {'disabled-form': !capa()}">
<div class="control-group">
<label class="control-label" data-i18n="TAB_BRANDING/LABEL_USER_CUSTOM_CSS"></label>
<div class="controls">
<div class="custom-css-wrapper" data-bind="component: {
name: 'TextArea',
params: {
value: userCss,
trigger: userCss.trigger,
width: 495,
enable: capa,
rows: 7
}
}"></div>
</div>
</div>
</div>
</div>
<div class="tab-pane active" id="branding-welcome-page-section-id">
<div class="form-horizontal" data-bind="css: {'disabled-form': !capa()}">
<div class="control-group">
<label class="control-label" data-i18n="TAB_BRANDING/LABEL_WELCOME_PAGE_URL"></label>
<div class="controls">
<div data-bind="component: {
name: 'Input',
params: {
value: welcomePageUrl,
trigger: welcomePageUrl.trigger,
placeholder: 'https://',
size: 5,
enable: capa
}
}"></div>
</div>
</div>
<div class="control-group">
<label class="control-label" data-i18n="TAB_BRANDING/LABEL_WELCOME_PAGE_DISPLAY"></label>
<div class="controls">
<div data-bind="component: {
name: 'Select',
params: {
options: welcomePageDisplay.options,
value: welcomePageDisplay,
trigger: welcomePageDisplay.trigger,
optionsText: 'optText',
optionsValue: 'optValue',
size: 2,
enable: capa
}
}"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row" data-bind="visible: !capa()">
<div class="alert span8" style="margin-top: 10px;" data-i18n="[html]TAB_BRANDING/HTML_ALERT_PREMIUM"></div>
</div>
</div> </div>

View file

@ -0,0 +1,22 @@
<div class="popups">
<div class="modal hide b-welcom-page-content g-ui-user-select-none"
data-bind="modal: modalVisibility" style="width: 600px">
<div class="modal-body" style="height: 450px; padding: 0">
<div data-bind="if:welcomePageURL" style="height: 100%; width: 100%; margin: 0; padding: 0; position: relative">
<iframe src="javascript:1;" tabindex="-1" frameborder="0"
style="border: none; width: 100%; height: 100%; position: absolute; top: 0px; left: 0px; right: 0px; bottom: 0px;"
data-bind="attr: {'src': welcomePageURL}"></iframe>
</div>
</div>
<div class="modal-footer">
<button class="btn" data-bind="command: cancelCommand, hasFocus: closeFocused">
<i class="icon-remove"></i>
&nbsp;&nbsp;
<span class="i18n" data-i18n="POPUPS_WELCOME_PAGE/BUTTON_CLOSE"></span>
</button>
</div>
</div>
</div>

View file

@ -108,7 +108,8 @@
<span class="flag-name" data-bind="text: languageFullName, click: selectLanguage"></span> <span class="flag-name" data-bind="text: languageFullName, click: selectLanguage"></span>
</label> </label>
</div> </div>
</div> {{INCLUDE/BottomFooter/PLACE}}
</center> </center>
</div>
<div class="loginAfter"></div> <div class="loginAfter"></div>
</div> </div>

View file

@ -173,7 +173,7 @@
</div> </div>
<div class="mainDelimiter footerDelimiter"></div> <div class="mainDelimiter footerDelimiter"></div>
<div class="b-footer thm-message-list-bottom-toolbar"> <div class="b-footer thm-message-list-bottom-toolbar">
<span data-tooltip-i18n="off" data-bind="visible: 0 < userUsageProc(), tooltip: quotaTooltip" class="e-quota"> <span data-tooltip-i18n="off" data-tooltip-mobile="on" data-bind="visible: 0 < userUsageProc(), tooltip: quotaTooltip" class="e-quota">
<span data-bind="text: userUsageProc"></span>% <span data-bind="text: userUsageProc"></span>%
</span> </span>
<div class="pull-right"> <div class="pull-right">

View file

@ -62,6 +62,13 @@ LABEL_LOGIN_SHOW_POWERED_LINK = "Show \"Powered by RainLoop\" link"
LEGEND_USER = "User" LEGEND_USER = "User"
LABEL_USER_LOGO = "Logo" LABEL_USER_LOGO = "Logo"
LABEL_USER_CUSTOM_CSS = "Custom CSS" LABEL_USER_CUSTOM_CSS = "Custom CSS"
LEGEND_WELCOME_PAGE = "Welcome page"
LABEL_WELCOME_PAGE_TITLE = "Title"
LABEL_WELCOME_PAGE_URL = "URL"
LABEL_WELCOME_PAGE_DISPLAY = "Display"
OPTION_WELCOME_PAGE_DISPLAY_NONE = "None"
OPTION_WELCOME_PAGE_DISPLAY_ONCE = "Once"
OPTION_WELCOME_PAGE_DISPLAY_ALWAYS = "Always"
HTML_ALERT_PREMIUM = "This functionality is available for <strong><a href=\"#/licensing\">Premium</a></strong> subscribers." HTML_ALERT_PREMIUM = "This functionality is available for <strong><a href=\"#/licensing\">Premium</a></strong> subscribers."
[TAB_CONTACTS] [TAB_CONTACTS]

View file

@ -61,6 +61,13 @@ LABEL_LOGIN_SHOW_POWERED_LINK = "Показывать ссылку \"Powered by
LEGEND_USER = "Экран пользователя" LEGEND_USER = "Экран пользователя"
LABEL_USER_LOGO = "Логотип" LABEL_USER_LOGO = "Логотип"
LABEL_USER_CUSTOM_CSS = "Кастомный CSS" LABEL_USER_CUSTOM_CSS = "Кастомный CSS"
LEGEND_WELCOME_PAGE = "Приветствие"
LABEL_WELCOME_PAGE_TITLE = "Название"
LABEL_WELCOME_PAGE_URL = "URL"
LABEL_WELCOME_PAGE_DISPLAY = "Показывать"
OPTION_WELCOME_PAGE_DISPLAY_NONE = "Никогда"
OPTION_WELCOME_PAGE_DISPLAY_ONCE = "Один раз"
OPTION_WELCOME_PAGE_DISPLAY_ALWAYS = "Всегда"
HTML_ALERT_PREMIUM = "Эти функции доступны для <strong><a href=\"#/licensing\">премиум</a></strong> подписчиков." HTML_ALERT_PREMIUM = "Эти функции доступны для <strong><a href=\"#/licensing\">премиум</a></strong> подписчиков."
[TAB_CONTACTS] [TAB_CONTACTS]

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Mark as important"
BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Да" BUTTON_YES = "Да"
BUTTON_NO = "Не" BUTTON_NO = "Не"

View file

@ -238,6 +238,9 @@ BUTTON_MARK_AS_IMPORTANT = "Označit jako důležité"
BUTTON_OPEN_PGP = "OpenPGP (jen Plain Text)" BUTTON_OPEN_PGP = "OpenPGP (jen Plain Text)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Ano" BUTTON_YES = "Ano"
BUTTON_NO = "Ne" BUTTON_NO = "Ne"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Als Wichtig markieren"
BUTTON_OPEN_PGP = "OpenPGP (nur bei unformatiertem Text)" BUTTON_OPEN_PGP = "OpenPGP (nur bei unformatiertem Text)"
BUTTON_REQUEST_DSN = "Übermittlungsstatus anfordern" BUTTON_REQUEST_DSN = "Übermittlungsstatus anfordern"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Ja" BUTTON_YES = "Ja"
BUTTON_NO = "Nein" BUTTON_NO = "Nein"
@ -705,4 +708,4 @@ NO_COOKIE_DESC = "Ihr Browser unterstützt Cookies nicht.
Aktivieren Sie bitte die Cookie-Unterstützung in Ihrem Browser und versuchen Sie es erneut." Aktivieren Sie bitte die Cookie-Unterstützung in Ihrem Browser und versuchen Sie es erneut."
BAD_BROWSER_TITLE = "Ihr Browser ist veraltet." BAD_BROWSER_TITLE = "Ihr Browser ist veraltet."
BAD_BROWSER_DESC = "Um alle Funktionen dieser Anwendung nutzen zu können, BAD_BROWSER_DESC = "Um alle Funktionen dieser Anwendung nutzen zu können,
sollten Sie einen der folgenden Browser herunterladen und installieren:" sollten Sie einen der folgenden Browser herunterladen und installieren:"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Mark as important"
BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Yes" BUTTON_YES = "Yes"
BUTTON_NO = "No" BUTTON_NO = "No"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Mark as important"
BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Yes" BUTTON_YES = "Yes"
BUTTON_NO = "No" BUTTON_NO = "No"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Mark as important"
BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Sí" BUTTON_YES = "Sí"
BUTTON_NO = "No" BUTTON_NO = "No"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Marquer comme important"
BUTTON_OPEN_PGP = "OpenPGP (Texte non-formatté uniquement)" BUTTON_OPEN_PGP = "OpenPGP (Texte non-formatté uniquement)"
BUTTON_REQUEST_DSN = "Demander un accusé de réception" BUTTON_REQUEST_DSN = "Demander un accusé de réception"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Oui" BUTTON_YES = "Oui"
BUTTON_NO = "Non" BUTTON_NO = "Non"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Mark as important"
BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Igen" BUTTON_YES = "Igen"
BUTTON_NO = "Nem" BUTTON_NO = "Nem"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Mark as important"
BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Yes" BUTTON_YES = "Yes"
BUTTON_NO = "No" BUTTON_NO = "No"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Marca come importante"
BUTTON_OPEN_PGP = "OpenPGP (Solo testo semplice)" BUTTON_OPEN_PGP = "OpenPGP (Solo testo semplice)"
BUTTON_REQUEST_DSN = "Richiedi conferma del ricevimento" BUTTON_REQUEST_DSN = "Richiedi conferma del ricevimento"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Si" BUTTON_YES = "Si"
BUTTON_NO = "No" BUTTON_NO = "No"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Mark as important"
BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "はい" BUTTON_YES = "はい"
BUTTON_NO = "いいえ" BUTTON_NO = "いいえ"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Mark as important"
BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Yes" BUTTON_YES = "Yes"
BUTTON_NO = "No" BUTTON_NO = "No"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Žymėti svarbiu"
BUTTON_OPEN_PGP = "OpenPGP (Tik paprastas tekstas)" BUTTON_OPEN_PGP = "OpenPGP (Tik paprastas tekstas)"
BUTTON_REQUEST_DSN = "Prašyti laiško gavimo pažymos" BUTTON_REQUEST_DSN = "Prašyti laiško gavimo pažymos"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Taip" BUTTON_YES = "Taip"
BUTTON_NO = "Ne" BUTTON_NO = "Ne"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Mark as important"
BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Yes" BUTTON_YES = "Yes"
BUTTON_NO = "No" BUTTON_NO = "No"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Marker als belangrijk"
BUTTON_OPEN_PGP = "OpenPGP (allen bij Platte Tekst)" BUTTON_OPEN_PGP = "OpenPGP (allen bij Platte Tekst)"
BUTTON_REQUEST_DSN = "Ontvangstbevestiging vragen" BUTTON_REQUEST_DSN = "Ontvangstbevestiging vragen"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Ja" BUTTON_YES = "Ja"
BUTTON_NO = "Nee" BUTTON_NO = "Nee"

View file

@ -238,6 +238,9 @@ BUTTON_MARK_AS_IMPORTANT = "Mark as important"
BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Ja" BUTTON_YES = "Ja"
BUTTON_NO = "Nei" BUTTON_NO = "Nei"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Oznacz jako ważną"
BUTTON_OPEN_PGP = "OpenPGP (Tylko zwykły tekst)" BUTTON_OPEN_PGP = "OpenPGP (Tylko zwykły tekst)"
BUTTON_REQUEST_DSN = "Żądaj potwierdzenia dostarczenia" BUTTON_REQUEST_DSN = "Żądaj potwierdzenia dostarczenia"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Tak" BUTTON_YES = "Tak"
BUTTON_NO = "Nie" BUTTON_NO = "Nie"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Marcar como importante"
BUTTON_OPEN_PGP = "OpenPGP (Somente Texto)" BUTTON_OPEN_PGP = "OpenPGP (Somente Texto)"
BUTTON_REQUEST_DSN = "Pedir recibo de entrega" BUTTON_REQUEST_DSN = "Pedir recibo de entrega"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Sim" BUTTON_YES = "Sim"
BUTTON_NO = "Não" BUTTON_NO = "Não"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Marcar como importante"
BUTTON_OPEN_PGP = "OpenPGP (apenas texto simples)" BUTTON_OPEN_PGP = "OpenPGP (apenas texto simples)"
BUTTON_REQUEST_DSN = "Pedir um recibo de entrega" BUTTON_REQUEST_DSN = "Pedir um recibo de entrega"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Sim" BUTTON_YES = "Sim"
BUTTON_NO = "Não" BUTTON_NO = "Não"

View file

@ -238,6 +238,9 @@ BUTTON_MARK_AS_IMPORTANT = "Mark as important"
BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Da" BUTTON_YES = "Da"
BUTTON_NO = "Nu" BUTTON_NO = "Nu"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Отметить как важное"
BUTTON_OPEN_PGP = "OpenPGP (только обычный текст)" BUTTON_OPEN_PGP = "OpenPGP (только обычный текст)"
BUTTON_REQUEST_DSN = "Запросить уведомление о доставке" BUTTON_REQUEST_DSN = "Запросить уведомление о доставке"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Да" BUTTON_YES = "Да"
BUTTON_NO = "Нет" BUTTON_NO = "Нет"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Mark as important"
BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Áno" BUTTON_YES = "Áno"
BUTTON_NO = "Nie" BUTTON_NO = "Nie"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Markera som viktigt"
BUTTON_OPEN_PGP = "OpenPGP (Endast enkel text)" BUTTON_OPEN_PGP = "OpenPGP (Endast enkel text)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Ja" BUTTON_YES = "Ja"
BUTTON_NO = "Nej" BUTTON_NO = "Nej"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Mark as important"
BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Evet" BUTTON_YES = "Evet"
BUTTON_NO = "Hayır" BUTTON_NO = "Hayır"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Mark as important"
BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "Так" BUTTON_YES = "Так"
BUTTON_NO = "Ні" BUTTON_NO = "Ні"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Mark as important"
BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "是" BUTTON_YES = "是"
BUTTON_NO = "否" BUTTON_NO = "否"

View file

@ -239,6 +239,9 @@ BUTTON_MARK_AS_IMPORTANT = "Mark as important"
BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)" BUTTON_OPEN_PGP = "OpenPGP (Plain Text Only)"
BUTTON_REQUEST_DSN = "Request a delivery receipt" BUTTON_REQUEST_DSN = "Request a delivery receipt"
[POPUPS_WELCOME_PAGE]
BUTTON_CLOSE = "Close"
[POPUPS_ASK] [POPUPS_ASK]
BUTTON_YES = "是" BUTTON_YES = "是"
BUTTON_NO = "否" BUTTON_NO = "否"