Merge branch 'master' into OwnCloud

This commit is contained in:
djmaze 2021-07-20 20:47:44 +02:00
commit 2aed429e5d
78 changed files with 831 additions and 934 deletions

View file

@ -10,7 +10,7 @@
1. Install node.js - `https://nodejs.org/download/` 1. Install node.js - `https://nodejs.org/download/`
2. Install yarn - `https://yarnpkg.com/en/docs/install` 2. Install yarn - `https://yarnpkg.com/en/docs/install`
3. Install gulp - `npm install gulp -g` 3. Install gulp - `npm install gulp -g`
4. Fork snappymail - `https://github.com/the-djmaze/snappymail/issues/new#fork-destination-box` 4. Fork snappymail from https://github.com/the-djmaze/snappymail
5. Clone snappymail - `git clone git@github.com:USERNAME/snappymail.git snappymail` 5. Clone snappymail - `git clone git@github.com:USERNAME/snappymail.git snappymail`
6. `cd snappymail` 6. `cd snappymail`
7. Install install all dependencies - `yarn install` 7. Install install all dependencies - `yarn install`

View file

@ -38,7 +38,6 @@ import {
} from 'Common/Cache'; } from 'Common/Cache';
import { import {
userBackground,
mailBox, mailBox,
root, root,
openPgpWorkerJs, openPgpWorkerJs,
@ -81,6 +80,8 @@ import { ComposePopupView } from 'View/Popup/Compose';
import { FolderSystemPopupView } from 'View/Popup/FolderSystem'; import { FolderSystemPopupView } from 'View/Popup/FolderSystem';
import { AskPopupView } from 'View/Popup/Ask'; import { AskPopupView } from 'View/Popup/Ask';
import { timeToNode } from 'Common/Momentor';
// Every 5 minutes // Every 5 minutes
const refreshFolders = 300000; const refreshFolders = 300000;
@ -110,16 +111,6 @@ class AppUser extends AbstractApp {
lastTime = currentTime; lastTime = currentTime;
}, interval); }, interval);
if (SettingsGet('UserBackgroundHash')) {
setTimeout(() => {
const img = userBackground(SettingsGet('UserBackgroundHash'));
if (img) {
$htmlCL.add('UserBackground');
doc.body.style.backgroundImage = "url("+img+")";
}
}, 1000);
}
const fn = (ev=>$htmlCL.toggle('rl-ctrl-key-pressed', ev.ctrlKey)).debounce(500); const fn = (ev=>$htmlCL.toggle('rl-ctrl-key-pressed', ev.ctrlKey)).debounce(500);
['keydown','keyup'].forEach(t => doc.addEventListener(t, fn)); ['keydown','keyup'].forEach(t => doc.addEventListener(t, fn));
@ -1020,7 +1011,14 @@ class AppUser extends AbstractApp {
this.hideLoading(); this.hideLoading();
} }
setInterval(() => dispatchEvent(new CustomEvent('reload-time')), 60000); setInterval(this.reloadTime(), 60000);
}
reloadTime()
{
setTimeout(() =>
doc.querySelectorAll('[data-bind*="moment:"]').forEach(element => timeToNode(element))
, 1)
} }
showMessageComposer(params = []) showMessageComposer(params = [])

View file

@ -70,14 +70,6 @@ export function change(email) {
return serverRequest('Change') + encodeURIComponent(email) + '/'; return serverRequest('Change') + encodeURIComponent(email) + '/';
} }
/**
* @param {string} hash
* @returns {string}
*/
export function userBackground(hash) {
return serverRequestRaw('UserBackground', hash);
}
/** /**
* @param {string} lang * @param {string} lang
* @param {boolean} isAdmin * @param {boolean} isAdmin

View file

@ -1,4 +1,3 @@
import { doc } from 'Common/Globals';
import { i18n } from 'Common/Translator'; import { i18n } from 'Common/Translator';
export function timestampToString(timeStampInUTC, formatStr) { export function timestampToString(timeStampInUTC, formatStr) {
@ -53,8 +52,3 @@ export function timeToNode(element, time) {
console.error(e); console.error(e);
} }
} }
addEventListener('reload-time', () => setTimeout(() =>
doc.querySelectorAll('[data-bind*="moment:"]').forEach(element => timeToNode(element))
, 1)
);

View file

@ -1,6 +1,15 @@
import ko from 'ko'; import ko from 'ko';
import { isArray } from 'Common/Utils'; import { isArray } from 'Common/Utils';
/*
oCallbacks:
ItemSelect
MiddleClick
AutoSelect
ItemGetUid
UpOrDown
*/
export class Selector { export class Selector {
/** /**
* @param {koProperty} koList * @param {koProperty} koList
@ -209,11 +218,9 @@ export class Selector {
itemSelected(item) { itemSelected(item) {
if (this.isListChecked()) { if (this.isListChecked()) {
if (!item) { item || (this.oCallbacks.ItemSelect || (()=>{}))(null);
(this.oCallbacks.onItemSelect || (()=>{}))(item || null);
}
} else if (item) { } else if (item) {
(this.oCallbacks.onItemSelect || (()=>{}))(item); (this.oCallbacks.ItemSelect || (()=>{}))(item);
} }
} }
@ -226,13 +233,16 @@ export class Selector {
this.oContentScrollable = contentScrollable; this.oContentScrollable = contentScrollable;
if (contentScrollable) { if (contentScrollable) {
let getItem = selector => {
let el = event.target.closestWithin(selector, contentScrollable);
return el ? ko.dataFor(el) : null;
};
contentScrollable.addEventListener('click', event => { contentScrollable.addEventListener('click', event => {
let el = event.target.closestWithin(this.sItemSelector, contentScrollable); let el = event.target.closestWithin(this.sItemSelector, contentScrollable);
el && this.actionClick(ko.dataFor(el), event); el && this.actionClick(ko.dataFor(el), event);
el = event.target.closestWithin(this.sItemCheckedSelector, contentScrollable); const item = getItem(this.sItemCheckedSelector);
if (el) {
const item = ko.dataFor(el);
if (item) { if (item) {
if (event.shiftKey) { if (event.shiftKey) {
this.actionClick(item, event); this.actionClick(item, event);
@ -241,6 +251,15 @@ export class Selector {
item.checked(!item.checked()); item.checked(!item.checked());
} }
} }
});
contentScrollable.addEventListener('auxclick', event => {
if (1 == event.button) {
const item = getItem(this.sItemSelector);
if (item) {
this.focusedItem(item);
(this.oCallbacks.MiddleClick || (()=>{}))(item);
}
} }
}); });
@ -271,7 +290,7 @@ export class Selector {
* @returns {boolean} * @returns {boolean}
*/ */
autoSelect() { autoSelect() {
return !!(this.oCallbacks.onAutoSelect || (()=>true))(); return !!(this.oCallbacks.AutoSelect || (()=>true))();
} }
/** /**
@ -281,7 +300,7 @@ export class Selector {
getItemUid(item) { getItemUid(item) {
let uid = ''; let uid = '';
const getItemUidCallback = this.oCallbacks.onItemGetUid || null; const getItemUidCallback = this.oCallbacks.ItemGetUid || null;
if (getItemUidCallback && item) { if (getItemUidCallback && item) {
uid = getItemUidCallback(item); uid = getItemUidCallback(item);
} }
@ -312,7 +331,7 @@ export class Selector {
} else if (++i < listLen) { } else if (++i < listLen) {
result = list[i]; result = list[i];
} }
result || (this.oCallbacks.onUpUpOrDownDown || (()=>true))('ArrowUp' === sEventKey); result || (this.oCallbacks.UpOrDown || (()=>true))('ArrowUp' === sEventKey);
} else if ('Home' === sEventKey) { } else if ('Home' === sEventKey) {
result = list[0]; result = list[0];
} else if ('End' === sEventKey) { } else if ('End' === sEventKey) {

View file

@ -140,7 +140,7 @@ export function reload(admin, language) {
// reload the data // reload the data
if (init()) { if (init()) {
i18nToNodes(doc); i18nToNodes(doc);
dispatchEvent(new CustomEvent('reload-time')); admin || rl.app.reloadTime();
trigger(!trigger()); trigger(!trigger());
} }
script.remove(); script.remove();

View file

@ -524,13 +524,6 @@ export class MessageModel extends AbstractModel {
} }
} }
storeDataInDom() {
if (this.body) {
this.body.rlIsHtml = !!this.isHtml();
this.body.rlHasImages = !!this.hasImages();
}
}
fetchDataFromDom() { fetchDataFromDom() {
if (this.body) { if (this.body) {
this.isHtml(!!this.body.rlIsHtml); this.isHtml(!!this.body.rlIsHtml);

View file

@ -2,9 +2,9 @@ import ko from 'ko';
import { SaveSettingsStep, UploadErrorCode, Capa } from 'Common/Enums'; import { SaveSettingsStep, UploadErrorCode, Capa } from 'Common/Enums';
import { changeTheme, convertThemeName } from 'Common/Utils'; import { changeTheme, convertThemeName } from 'Common/Utils';
import { userBackground, themePreviewLink, serverRequest } from 'Common/Links'; import { themePreviewLink, serverRequest } from 'Common/Links';
import { i18n } from 'Common/Translator'; import { i18n } from 'Common/Translator';
import { doc, $htmlCL, Settings } from 'Common/Globals'; import { Settings } from 'Common/Globals';
import { ThemeStore } from 'Stores/Theme'; import { ThemeStore } from 'Stores/Theme';
@ -38,16 +38,6 @@ export class ThemesUserSettings {
Theme: value Theme: value
}); });
}); });
this.background.hash.subscribe((value) => {
if (!value) {
$htmlCL.remove('UserBackground');
doc.body.removeAttribute('style');
} else {
$htmlCL.add('UserBackground');
doc.body.style.backgroundImage = "url("+userBackground(value)+")";
}
});
} }
onBuild() { onBuild() {

View file

@ -1,6 +1,7 @@
import ko from 'ko'; import ko from 'ko';
import { $htmlCL, leftPanelDisabled, Settings, SettingsGet } from 'Common/Globals'; import { doc, $htmlCL, leftPanelDisabled, Settings, SettingsGet } from 'Common/Globals';
import { isArray } from 'Common/Utils'; import { isArray } from 'Common/Utils';
import { serverRequestRaw } from 'Common/Links';
export const ThemeStore = { export const ThemeStore = {
themes: ko.observableArray(), themes: ko.observableArray(),
@ -25,3 +26,13 @@ export const ThemeStore = {
ThemeStore.theme = ko.observable('').extend({ limitedList: ThemeStore.themes }); ThemeStore.theme = ko.observable('').extend({ limitedList: ThemeStore.themes });
ThemeStore.isMobile.subscribe(value => $htmlCL.toggle('rl-mobile', value)); ThemeStore.isMobile.subscribe(value => $htmlCL.toggle('rl-mobile', value));
ThemeStore.userBackgroundHash.subscribe(value => {
if (value) {
$htmlCL.add('UserBackground');
doc.body.style.backgroundImage = "url("+serverRequestRaw('UserBackground', value)+")";
} else {
$htmlCL.remove('UserBackground');
doc.body.removeAttribute('style');
}
});

View file

@ -2,7 +2,7 @@ import ko from 'ko';
import { Scope, Notification } from 'Common/Enums'; import { Scope, Notification } from 'Common/Enums';
import { MessageSetAction } from 'Common/EnumsUser'; import { MessageSetAction } from 'Common/EnumsUser';
import { doc, createElement, elementById } from 'Common/Globals'; import { doc, $htmlCL, createElement, elementById } from 'Common/Globals';
import { isNonEmptyArray, pInt, pString, addObservablesTo, addSubscribablesTo } from 'Common/Utils'; import { isNonEmptyArray, pInt, pString, addObservablesTo, addSubscribablesTo } from 'Common/Utils';
import { plainToHtml } from 'Common/UtilsUser'; import { plainToHtml } from 'Common/UtilsUser';
@ -186,6 +186,8 @@ export const MessageUserStore = new class {
} }
}, },
listLoadingAnimation: value => $htmlCL.toggle('list-loading', value),
listLoading: value => listLoading: value =>
this.listCompleteLoading(value || this.listIsNotCompleted()), this.listCompleteLoading(value || this.listIsNotCompleted()),
@ -220,7 +222,7 @@ export const MessageUserStore = new class {
} }
}); });
this.purgeMessageBodyCacheThrottle = this.purgeMessageBodyCache.throttle(30000); this.purgeMessageBodyCache = this.purgeMessageBodyCache.throttle(30000);
} }
purgeMessageBodyCache() { purgeMessageBodyCache() {
@ -428,16 +430,12 @@ export const MessageUserStore = new class {
); );
} }
setMessage(data, cached) { setMessage(data, cached, oMessage) {
let isNew = false, let isNew = false,
body = null,
json = data && data.Result, json = data && data.Result,
id = '',
plain = '',
resultHtml = '',
messagesDom = this.messagesBodiesDom(), messagesDom = this.messagesBodiesDom(),
selectedMessage = this.selectorMessageSelected(), selectedMessage = this.selectorMessageSelected(),
message = this.message(); message = oMessage || this.message();
if ( if (
json && json &&
@ -447,7 +445,7 @@ export const MessageUserStore = new class {
) { ) {
const threads = message.threads(); const threads = message.threads();
if (message.uid !== json.Uid && 1 < threads.length && threads.includes(json.Uid)) { if (message.uid !== json.Uid && 1 < threads.length && threads.includes(json.Uid)) {
message = MessageModel.reviveFromJson(json); message = oMessage ? null : MessageModel.reviveFromJson(json);
if (message) { if (message) {
message.threads(threads); message.threads(threads);
MessageFlagsCache.initMessage(message); MessageFlagsCache.initMessage(message);
@ -460,7 +458,7 @@ export const MessageUserStore = new class {
} }
if (message && message.uid === json.Uid) { if (message && message.uid === json.Uid) {
this.messageError(''); oMessage || this.messageError('');
if (cached) { if (cached) {
delete json.IsSeen; delete json.IsSeen;
@ -475,6 +473,7 @@ export const MessageUserStore = new class {
addRequestedMessage(message.folder, message.uid); addRequestedMessage(message.folder, message.uid);
if (messagesDom) { if (messagesDom) {
let body = null,
id = 'rl-mgs-' + message.hash.replace(/[^a-zA-Z0-9]/g, ''); id = 'rl-mgs-' + message.hash.replace(/[^a-zA-Z0-9]/g, '');
const textBody = elementById(id); const textBody = elementById(id);
@ -483,7 +482,9 @@ export const MessageUserStore = new class {
message.fetchDataFromDom(); message.fetchDataFromDom();
messagesDom.append(textBody); messagesDom.append(textBody);
} else { } else {
let isHtml = !!json.Html; let isHtml = !!json.Html,
plain = '',
resultHtml = '<pre></pre>';
if (isHtml) { if (isHtml) {
resultHtml = json.Html.toString(); resultHtml = json.Html.toString();
if (SettingsUserStore.removeColors()) { if (SettingsUserStore.removeColors()) {
@ -508,8 +509,6 @@ export const MessageUserStore = new class {
} else { } else {
resultHtml = '<pre>' + resultHtml + '</pre>'; resultHtml = '<pre>' + resultHtml + '</pre>';
} }
} else {
resultHtml = '<pre>' + resultHtml + '</pre>';
} }
body = Element.fromHTML('<div id="' + id + '" hidden="" class="b-text-part ' body = Element.fromHTML('<div id="' + id + '" hidden="" class="b-text-part '
@ -517,22 +516,25 @@ export const MessageUserStore = new class {
+ findEmailAndLinks(resultHtml) + findEmailAndLinks(resultHtml)
+ '</div>'); + '</div>');
if (isHtml) {
// Drop Microsoft Office style properties // Drop Microsoft Office style properties
const rgbRE = /rgb\((\d+),\s*(\d+),\s*(\d+)\)/g, const rgbRE = /rgb\((\d+),\s*(\d+),\s*(\d+)\)/g,
hex = n => ('0' + parseInt(n).toString(16)).slice(-2); hex = n => ('0' + parseInt(n).toString(16)).slice(-2);
body.querySelectorAll('[style*=mso]').forEach(el => body.querySelectorAll('[style*=mso]').forEach(el =>
el.setAttribute('style', el.style.cssText.replace(rgbRE, (m,r,g,b) => '#' + hex(r) + hex(g) + hex(b))) el.setAttribute('style', el.style.cssText.replace(rgbRE, (m,r,g,b) => '#' + hex(r) + hex(g) + hex(b)))
); );
}
body.rlIsHtml = isHtml;
body.rlHasImages = !!json.HasExternals;
message.body = body; message.body = body;
message.isHtml(isHtml); message.isHtml(isHtml);
message.hasImages(!!json.HasExternals); message.hasImages(body.rlHasImages);
messagesDom.append(body); messagesDom.append(body);
message.storeDataInDom();
if (json.HasInternals) { if (json.HasInternals) {
message.showInternalImages(); message.showInternalImages();
} }
@ -541,12 +543,12 @@ export const MessageUserStore = new class {
message.showExternalImages(); message.showExternalImages();
} }
this.purgeMessageBodyCacheThrottle(); this.purgeMessageBodyCache();
} }
this.messageActiveDom(message.body); oMessage || this.messageActiveDom(message.body);
this.hideMessageBodies(); oMessage || this.hideMessageBodies();
if (body) { if (body) {
this.initOpenPgpControls(body, message); this.initOpenPgpControls(body, message);
@ -554,7 +556,8 @@ export const MessageUserStore = new class {
this.initBlockquoteSwitcher(body); this.initBlockquoteSwitcher(body);
} }
message.body.hidden = false; oMessage || (message.body.hidden = false);
oMessage && message.viewPopupMessage();
} }
MessageFlagsCache.initMessage(message); MessageFlagsCache.initMessage(message);
@ -563,8 +566,6 @@ export const MessageUserStore = new class {
} }
if (isNew) { if (isNew) {
message = this.message();
if ( if (
selectedMessage && selectedMessage &&
message && message &&
@ -613,20 +614,20 @@ export const MessageUserStore = new class {
} }
} }
populateMessageBody(oMessage) { populateMessageBody(oMessage, preload) {
if (oMessage) { if (oMessage) {
this.hideMessageBodies(); preload || this.hideMessageBodies();
this.messageLoading(true); preload || this.messageLoading(true);
Remote.message((iError, oData, bCached) => { Remote.message((iError, oData, bCached) => {
if (iError) { if (iError) {
if (Notification.RequestAborted !== iError) { if (Notification.RequestAborted !== iError && !preload) {
this.message(null); this.message(null);
this.messageError(getNotification(iError)); this.messageError(getNotification(iError));
} }
} else { } else {
this.setMessage(oData, bCached); this.setMessage(oData, bCached, preload ? oMessage : null);
} }
this.messageLoading(false); preload || this.messageLoading(false);
}, oMessage.folder, oMessage.uid); }, oMessage.folder, oMessage.uid);
} }
} }

View file

@ -23,20 +23,19 @@
@import "Ui.less"; @import "Ui.less";
@import "Main.less"; @import "Main.less";
@import "LayoutAdmin.less";
@import "Components.less"; @import "Components.less";
@import "Login.less"; @import "Login.less";
@import "Ask.less"; @import "Ask.less";
@import "Languages.less"; @import "Languages.less";
@import "Admin.less"; @import "Admin/Layout.less";
@import "AdminGeneral.less"; @import "Admin/General.less";
@import "AdminBranding.less"; @import "Admin/Branding.less";
@import "AdminDomains.less"; @import "Admin/Domains.less";
@import "AdminDomain.less"; @import "Admin/Domain.less";
@import "AdminPackages.less"; @import "Admin/Packages.less";
@import "AdminPlugin.less"; @import "Admin/Plugin.less";
@import "AdminAbout.less"; @import "Admin/About.less";
@import "Animations.less"; @import "Animations.less";

View file

@ -24,45 +24,39 @@
@import "Ui.less"; @import "Ui.less";
@import "Main.less"; @import "Main.less";
@import "Layout.less";
@import "Components.less"; @import "Components.less";
@import "Login.less"; @import "Login.less";
@import "Ask.less"; @import "Ask.less";
@import "Languages.less"; @import "Languages.less";
@import "SystemDropDown.less"; @import "User/Layout.less";
@import "Shortcuts.less"; @import "User/SystemDropDown.less";
@import "FolderList.less"; @import "User/Shortcuts.less";
/* @import "User/FolderList.less";
@import "FolderClear.less"; @import "User/Filter.less";
@import "FolderCreate.less"; @import "User/Template.less";
@import "FolderSystem.less"; @import "User/OpenPgpKey.less";
@import "Account.less"; @import "User/Identity.less";
*/ @import "User/AdvancedSearch.less";
@import "Filter.less"; @import "User/Attachmnets.less";
@import "Template.less"; @import "User/MessageList.less";
@import "OpenPgpKey.less"; @import "User/MessageView.less";
@import "Identity.less"; @import "User/Contacts.less";
@import "AdvancedSearch.less"; @import "User/Compose.less";
@import "Attachmnets.less"; @import "User/EmailAddresses.less";
@import "MessageList.less";
@import "MessageView.less";
@import "Contacts.less";
@import "Compose.less";
@import "EmailAddresses.less";
@import "Settings.less"; @import "User/Settings.less";
@import "SettingsGeneral.less"; @import "User/SettingsGeneral.less";
@import "SettingsAccounts.less"; @import "User/SettingsAccounts.less";
@import "SettingsTemplates.less"; @import "User/SettingsTemplates.less";
@import "SettingsOpenPGP.less"; @import "User/SettingsOpenPGP.less";
@import "SettingsFolders.less"; @import "User/SettingsFolders.less";
@import "SettingsThemes.less"; @import "User/SettingsThemes.less";
@import "SettingsFilters.less"; @import "User/SettingsFilters.less";
@import "SquireUI.less"; @import "User/SquireUI.less";
@import "AnimationsUser.less"; @import "User/Animations.less";
@import "Animations.less"; @import "Animations.less";
@import "_End.less"; @import "_End.less";

View file

@ -1,4 +0,0 @@
.b-account-add-content {
.modal-header {
}
}

View file

@ -1,6 +1,6 @@
.b-domain-alias-content { .b-domain-alias-content {
&.modal { &.modal {
width: 330px; max-width: 330px;
} }
.error-desc { .error-desc {
@ -11,7 +11,7 @@
.b-domain-content { .b-domain-content {
&.modal { &.modal {
width: 810px; max-width: 810px;
} }
.modal-body { .modal-body {

View file

@ -1,7 +1,25 @@
.UserBackground body {
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
#rl-left, #rl-right {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: 0;
margin: 0;
border: 0;
z-index: 0;
}
#rl-left { #rl-left {
overflow: auto; overflow: auto;
padding-top: 50px + @rlLowMargin + 10px; padding-top: 50px + @rlLowMargin + 10px;
width: @rlLeftWidth;
nav { nav {
a { a {
@ -26,6 +44,11 @@
} }
} }
#rl-right {
z-index: 1;
left: @rlLeftWidth;
}
.b-admin-right { .b-admin-right {
.b-toolbar { .b-toolbar {
@ -67,3 +90,56 @@
padding-left: 12px; padding-left: 12px;
padding-right: 12px; padding-right: 12px;
} }
#rl-popups > .rl-view-model {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 1100;
overflow: auto;
background-color: rgba(0,0,0,0.3);
}
#rl-settings-subscreen {
padding: 20px;
}
/* desktop */
@media screen and (min-width: 1000px) {
.toggleLeft {
display: none;
}
}
/* desktop-large */
@media screen and (min-width: 1401px) {
#rl-left {
width: @rlLeftWidth + 20;
}
#rl-right {
left: @rlLeftWidth + 20;
}
}
/* mobile and tablet */
@media screen and (max-width: 999px) {
#rl-settings-subscreen {
padding: 10px;
}
html:not(.rl-left-panel-disabled) #rl-right {
right: 5-@rlLeftWidth;
}
html.rl-left-panel-disabled {
#rl-left {
width: 0 !important;
}
#rl-right {
left: 5px !important;
}
}
}

View file

@ -1,7 +1,7 @@
.b-plugin-content { .b-plugin-content {
&.modal { &.modal {
width: 660px; max-width: 660px;
} }
.modal-body { .modal-body {

View file

@ -1,24 +0,0 @@
.b-admin-plugins-list-table {
max-width: 620px; /* span8 */
&.disabled {
opacity: 0.5;
}
.disabled {
opacity: 0.5;
}
}
.b-admin-plugin-property {
.help-block {
display: block; // account for any element using help-block
font-style: italic;
opacity: 0.5;
margin-bottom: 5px;
}
.controls {
width: 470px;
}
}

View file

@ -1,4 +0,0 @@
.b-folder-clear-content {
.modal-header {
}
}

View file

@ -1,4 +0,0 @@
.b-folder-create-content {
.modal-header {
}
}

View file

@ -1,4 +0,0 @@
.b-folder-system-content {
.modal-header {
}
}

View file

@ -1,16 +1,15 @@
.b-languages-content { .b-languages-content {
&.modal { &.modal {
width: 700px; max-width: 700px;
} }
.lang-item { label {
display: inline-block; display: inline-block;
padding: 5px 15px; padding: 5px 15px;
margin: 2px 5px; margin: 2px 5px;
width: 180px; width: 180px;
background-color: rgba(128, 128, 128, 0.1); background-color: rgba(128, 128, 128, 0.1);
text-align: left;
border: 1px solid transparent; border: 1px solid transparent;
border-radius: 3px; border-radius: 3px;
position: relative; position: relative;
@ -26,7 +25,6 @@
} }
&.selected::after { &.selected::after {
content: "✔"; content: "✔";
color: #080;
position: absolute; position: absolute;
right: 4px; right: 4px;
font-family: snappymail; font-family: snappymail;
@ -39,7 +37,7 @@
} }
@media screen and (max-width: 999px) { @media screen and (max-width: 999px) {
.b-languages-content .lang-item { .b-languages-content label {
width: calc(100% - 40px); width: calc(100% - 40px);
} }
} }

View file

@ -1,80 +0,0 @@
.UserBackground body {
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
#rl-left, #rl-right {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: 0;
margin: 0;
border: 0;
z-index: 0;
}
#rl-left {
width: @rlLeftWidth;
}
#rl-right {
z-index: 1;
left: @rlLeftWidth;
}
#rl-popups > .rl-view-model {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 1100;
overflow: auto;
background-color: rgba(0,0,0,0.3);
}
#rl-settings-subscreen {
padding: 20px;
}
/* desktop */
@media screen and (min-width: 1000px) {
.toggleLeft {
display: none;
}
}
/* desktop-large */
@media screen and (min-width: 1401px) {
#rl-left {
width: @rlLeftWidth + 20;
}
#rl-right {
left: @rlLeftWidth + 20;
}
}
/* mobile and tablet */
@media screen and (max-width: 999px) {
#rl-settings-subscreen {
padding: 10px;
}
html:not(.rl-left-panel-disabled) #rl-right {
right: 5-@rlLeftWidth;
}
html.rl-left-panel-disabled {
#rl-left {
width: 0 !important;
}
#rl-right {
left: 5px !important;
}
}
}

View file

@ -20,6 +20,11 @@ body {
right: 0; right: 0;
} }
html.list-loading body {
/* cursor: wait;*/
cursor: progress;
}
html:not(.rl-mobile) { html:not(.rl-mobile) {
min-width: 700px; min-width: 700px;
} }
@ -32,10 +37,6 @@ html:not(.rl-mobile) {
} }
} }
textarea {
resize: none;
}
option:disabled { option:disabled {
color: #aaa; color: #aaa;
cursor: not-allowed; cursor: not-allowed;

View file

@ -16,32 +16,6 @@
} }
} }
.e-paginator {
.e-page {
display: inline-block;
opacity: 0.5;
text-decoration: none;
font-size: 22px;
padding: 3px;
cursor: pointer;
&:hover {
opacity: 0.8;
}
&.current {
opacity: 1;
}
&.current .e-page-number {
font-size: 115%;
text-decoration: underline;
}
}
}
.settings-save-trigger { .settings-save-trigger {
display: inline-block; display: inline-block;
@ -93,25 +67,6 @@ textarea + .settings-save-trigger {
} }
} }
.e-languages {
margin-top: 8px;
color: #333;
.flag-name {
color: #333;
border-bottom: 1px dashed #333;
cursor: pointer;
padding: 2px 0;
&:focus {
outline: 1px;
outline-style: dotted;
}
}
}
.e-action { .e-action {
cursor: pointer; cursor: pointer;
} }

View file

@ -1,6 +1,6 @@
.b-advanced-search-content { .b-advanced-search-content {
&.modal { &.modal {
width: 780px; max-width: 780px;
} }
.control-label { .control-label {
width: 110px; width: 110px;

View file

@ -43,15 +43,6 @@
transition: opacity 0.3s linear; transition: opacity 0.3s linear;
} }
.messageList {
.messageListItem {
transition: max-height 400ms ease;
}
.listDragOver {
transition: all 400ms ease;
}
}
.b-list-content { .b-list-content {
.e-contact-item { .e-contact-item {
transition: max-height 400ms ease; transition: max-height 400ms ease;

View file

@ -1,7 +1,7 @@
@contacts-popup-left-width: 220px; @contacts-popup-left-width: 25%;
.b-contacts-content { .RL-PopupsContacts {
.control-group { .control-group {
.control-label { .control-label {
@ -10,11 +10,8 @@
} }
} }
&.modal { .modal {
position: absolute;
right: 0;
bottom: 0; bottom: 0;
left: 0;
width: auto; width: auto;
min-width: 550px; min-width: 550px;
max-width: 900px; max-width: 900px;
@ -36,8 +33,8 @@
border-bottom: 1px solid rgba(128,128,128,0.4); border-bottom: 1px solid rgba(128,128,128,0.4);
.e-search { .e-search {
margin-top: 7px; margin: 7px 0 0;
width: @contacts-popup-left-width - 20; width: calc(100% - 20px);
} }
} }
@ -268,18 +265,3 @@
} }
} }
} }
@media screen and (max-width: 700px) {
.b-contacts-content {
.b-list-content, .b-list-toolbar, .b-list-footer-toolbar {
width: 170px;
}
.b-list-toolbar .e-search {
width: 150px;
}
.b-view-content-toolbar, .b-view-content {
left: 170px;
}
}
}

View file

@ -1,7 +1,7 @@
.b-identity-content { .b-identity-content {
&.modal { &.modal {
width: 770px; max-width: 770px;
} }
.modal-body { .modal-body {

View file

@ -371,3 +371,24 @@ html:not(.rl-mobile) .show-mobile {
html.rl-mobile .width100-on-mobile { html.rl-mobile .width100-on-mobile {
width: 100% !important; width: 100% !important;
} }
.e-paginator {
.e-page {
opacity: 0.5;
text-decoration: none;
font-size: 22px;
padding: 3px;
cursor: pointer;
&:hover {
opacity: 0.8;
}
&.current {
opacity: 1;
font-size: 25px;
cursor: default;
}
}
}

View file

@ -198,7 +198,29 @@ html.rl-no-preview-pane {
} }
} }
.messageListItem { &.message-focused {
.b-message-list-wrapper {
background-color: #000;
}
.b-content {
opacity: 0.97;
}
}
}
.hideMessageListCheckbox {
.checkboxCheckAll {
visibility: hidden;
}
.checkboxMessage {
display: none;
}
}
.messageListItem {
display: flex;
flex-wrap: wrap;
position: relative; position: relative;
font-size: 12px; font-size: 12px;
@ -213,6 +235,12 @@ html.rl-no-preview-pane {
z-index: 100; z-index: 100;
> * {
display: flex;
flex: 0 0 auto;
order: 0;
}
&.focused { &.focused {
background-color: rgba(128, 128, 128, 0.1); background-color: rgba(128, 128, 128, 0.1);
border-left-color: #ccc; border-left-color: #ccc;
@ -405,27 +433,23 @@ html.rl-no-preview-pane {
&.flagged .flagOff, &.hasFlaggedSubMessage .flagOff { &.flagged .flagOff, &.hasFlaggedSubMessage .flagOff {
display: none; display: none;
} }
} }
&.message-focused { html.rl-ctrl-key-pressed .messageListItem {
.b-message-list-wrapper { cursor: copy;
background-color: #000; }
}
.b-content {
opacity: 0.97;
}
}
&.hideMessageListCheckbox { @media screen and (min-width: 1000px) {
.checkboxMessage, .checkboxCheckAll { .messageList {
visibility: hidden; .listDragOver {
transition: all 400ms ease;
} }
} }
} }
/* desktop-large */ /* desktop-large */
@media screen and (min-width: 1401px) { @media screen and (min-width: 1401px) {
.messageList .messageListItem { .messageListItem {
font-size: 13px; font-size: 13px;
time { time {
font-size: 13px; font-size: 13px;
@ -448,18 +472,6 @@ html .messageList .line-loading {
top: 0; top: 0;
} }
.messageListItem {
display: flex;
flex-wrap: wrap;
> * {
display: flex;
flex: 0 0 auto;
order: 0;
}
}
.rl-side-preview-pane, .rl-mobile { .rl-side-preview-pane, .rl-mobile {
.messageListItem { .messageListItem {
@ -471,7 +483,6 @@ html .messageList .line-loading {
.subjectParent { .subjectParent {
flex: 1 0 auto; flex: 1 0 auto;
line-height: 16px; line-height: 16px;
margin-left: 30px;
order: 1; order: 1;
width: calc(100% - 120px); width: calc(100% - 120px);
} }
@ -492,9 +503,13 @@ html .messageList .line-loading {
order: 3; order: 3;
} }
} }
.b-message-list-wrapper:not(.hideMessageListCheckbox) .subjectParent {
margin-left: 30px;
}
} }
html:not(.rl-mobile):not(.rl-side-preview-pane) .messageList { html:not(.rl-mobile):not(.rl-side-preview-pane) {
.messageListItem { .messageListItem {

View file

@ -1,6 +1,6 @@
.b-open-pgp-key-view-content, .b-open-pgp-key-generate-content { .b-open-pgp-key-view-content, .b-open-pgp-key-generate-content {
&.modal { &.modal {
width: 570px; max-width: 570px;
} }
} }
@ -13,7 +13,7 @@
.b-compose-open-pgp-content { .b-compose-open-pgp-content {
&.modal { &.modal {
width: 800px; max-width: 800px;
} }
.key-list { .key-list {
@ -97,7 +97,7 @@
.b-message-open-pgp-content { .b-message-open-pgp-content {
&.modal { &.modal {
width: 700px; max-width: 700px;
} }
.key-list { .key-list {
@ -134,7 +134,7 @@
.b-open-pgp-key-add-content { .b-open-pgp-key-add-content {
&.modal { &.modal {
width: 645px; max-width: 645px;
} }
.inputKey { .inputKey {
font-family: var(--fontMono); font-family: var(--fontMono);

View file

@ -1,7 +1,7 @@
.rl-view-model { .rl-view-model {
.b-shortcuts-content { .b-shortcuts-content {
&.modal { &.modal {
width: 700px; max-width: 700px;
} }
} }
} }

View file

@ -1,7 +1,7 @@
.b-template-add-content { .b-template-add-content {
&.modal { &.modal {
width: 750px; max-width: 750px;
} }
.e-template-place { .e-template-place {

View file

@ -12,12 +12,7 @@ label.inline, span.inline {
line-height: @baseLineHeight * 2; line-height: @baseLineHeight * 2;
color: @grayDark; color: @grayDark;
border: 0; border: 0;
border-bottom: 1px solid #e5e5e5; border-bottom: 1px solid @dropdownDividerTop;
small {
font-size: @baseLineHeight * .75;
color: @grayLight;
}
} }
.legend + .control-group { .legend + .control-group {
@ -40,30 +35,19 @@ label.inline, span.inline {
.alert a { .alert a {
text-decoration: underline; text-decoration: underline;
color: #c09853; color: @warningText;
} }
.alert.alert-info a { .alert.alert-info a {
color: #3a87ad; color: @infoText;
} }
.alert.alert-error a { .alert.alert-error a {
color: #b94a48; color: @errorText;
}
.form-horizontal.long-label .control-group {
.control-label {
width: 160px;
}
} }
/* mobile and tablet */ /* mobile and tablet */
@media screen and (max-width: 999px) { @media screen and (max-width: 999px) {
.modal {
width: calc(100% - 20px);
}
.form-horizontal { .form-horizontal {
.control-group { .control-group {
.control-label { .control-label {

View file

@ -63,7 +63,8 @@
margin: -1px -2px; margin: -1px -2px;
} }
.icon-spinner:not(.not-animated) { .icon-spinner:not(.not-animated),
.list-loading .icon-spinner.not-animated {
border-color: transparent; border-color: transparent;
border-top-color: #999; border-top-color: #999;
animation: rotation .8s infinite ease-in-out; animation: rotation .8s infinite ease-in-out;

View file

@ -79,14 +79,14 @@ class ContactsPopupView extends AbstractViewPopup {
'.e-contact-item.focused' '.e-contact-item.focused'
); );
this.selector.on('onItemSelect', contact => { this.selector.on('ItemSelect', contact => {
this.populateViewContact(contact || null); this.populateViewContact(contact);
if (!contact) { if (!contact) {
this.emptySelection(true); this.emptySelection(true);
} }
}); });
this.selector.on('onItemGetUid', contact => contact ? contact.generateUid() : ''); this.selector.on('ItemGetUid', contact => contact ? contact.generateUid() : '');
this.bDropPageAfterDelete = false; this.bDropPageAfterDelete = false;

View file

@ -55,7 +55,7 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
this.bPrefetch = false; this.bPrefetch = false;
this.emptySubjectValue = ''; this.emptySubjectValue = '';
this.iGoToUpUpOrDownDownTimeout = 0; this.iGoToUpOrDownTimeout = 0;
this.newMoveToFolder = !!SettingsGet('NewMoveToFolder'); this.newMoveToFolder = !!SettingsGet('NewMoveToFolder');
@ -86,7 +86,6 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
this.messageListCheckedOrSelected = MessageUserStore.listCheckedOrSelected; this.messageListCheckedOrSelected = MessageUserStore.listCheckedOrSelected;
this.messageListCompleteLoadingThrottle = MessageUserStore.listCompleteLoading; this.messageListCompleteLoadingThrottle = MessageUserStore.listCompleteLoading;
this.messageListCompleteLoadingThrottleForAnimation = MessageUserStore.listLoadingAnimation;
initOnStartOrLangChange(() => this.emptySubjectValue = i18n('MESSAGE_LIST/EMPTY_SUBJECT_TEXT')); initOnStartOrLangChange(() => this.emptySubjectValue = i18n('MESSAGE_LIST/EMPTY_SUBJECT_TEXT'));
@ -191,13 +190,15 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
'.messageListItem.focused' '.messageListItem.focused'
); );
this.selector.on('onItemSelect', message => MessageUserStore.selectMessage(message)); this.selector.on('ItemSelect', message => MessageUserStore.selectMessage(message));
this.selector.on('onItemGetUid', message => (message ? message.generateUid() : '')); this.selector.on('MiddleClick', message => MessageUserStore.populateMessageBody(message, true));
this.selector.on('onAutoSelect', () => this.useAutoSelect()); this.selector.on('ItemGetUid', message => (message ? message.generateUid() : ''));
this.selector.on('onUpUpOrDownDown', v => this.goToUpUpOrDownDown(v)); this.selector.on('AutoSelect', () => this.useAutoSelect());
this.selector.on('UpOrDown', v => this.goToUpOrDown(v));
addEventListener('mailbox.message-list.selector.go-down', addEventListener('mailbox.message-list.selector.go-down',
e => this.selector.newSelectPosition('ArrowDown', false, e.detail) e => this.selector.newSelectPosition('ArrowDown', false, e.detail)
@ -351,13 +352,13 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
showMessageComposer(); showMessageComposer();
} }
goToUpUpOrDownDown(up) { goToUpOrDown(up) {
if (MessageUserStore.listChecked().length) { if (MessageUserStore.listChecked().length) {
return false; return false;
} }
clearTimeout(this.iGoToUpUpOrDownDownTimeout); clearTimeout(this.iGoToUpOrDownTimeout);
this.iGoToUpUpOrDownDownTimeout = setTimeout(() => { this.iGoToUpOrDownTimeout = setTimeout(() => {
let prev, next, temp, current; let prev, next, temp, current;
this.messageListPaginator().find(item => { this.messageListPaginator().find(item => {
@ -668,31 +669,31 @@ export class MessageListMailBoxUserView extends AbstractViewRight {
} }
onBuild(dom) { onBuild(dom) {
const eqs = (ev, s) => ev.target.closestWithin(s, dom); const eqs = (ev, s) => ev.target.closestWithin('.messageList '+s, dom);
this.selector.init(dom.querySelector('.b-content'), Scope.MessageList); this.selector.init(dom.querySelector('.b-content'), Scope.MessageList);
dom.addEventListener('click', event => { dom.addEventListener('click', event => {
ThemeStore.isMobile() && leftPanelDisabled(true); ThemeStore.isMobile() && leftPanelDisabled(true);
if (eqs(event, '.messageList .b-message-list-wrapper') && Scope.MessageView === AppUserStore.focusedState()) { if (eqs(event, '.b-message-list-wrapper') && Scope.MessageView === AppUserStore.focusedState()) {
AppUserStore.focusedState(Scope.MessageList); AppUserStore.focusedState(Scope.MessageList);
} }
let el = eqs(event, '.e-paginator .e-page'); let el = eqs(event, '.e-paginator .e-page');
el && this.gotoPage(ko.dataFor(el)); el && this.gotoPage(ko.dataFor(el));
eqs(event, '.messageList .checkboxCheckAll') && this.checkAll(!this.checkAll()); eqs(event, '.checkboxCheckAll') && this.checkAll(!this.checkAll());
el = eqs(event, '.messageList .messageListItem .flagParent'); el = eqs(event, '.messageListItem .flagParent');
el && this.flagMessages(ko.dataFor(el)); el && this.flagMessages(ko.dataFor(el));
el = eqs(event, '.messageList .messageListItem .threads-len'); el = eqs(event, '.messageListItem .threads-len');
el && this.gotoThread(ko.dataFor(el)); el && this.gotoThread(ko.dataFor(el));
}); });
dom.addEventListener('dblclick', event => { dom.addEventListener('dblclick', event => {
let el = eqs(event, '.messageList .messageListItem .actionHandle'); let el = eqs(event, '.messageListItem .actionHandle');
el && this.gotoThread(ko.dataFor(el)); el && this.gotoThread(ko.dataFor(el));
}); });

View file

@ -67,6 +67,7 @@
"rimraf": "3.0.2" "rimraf": "3.0.2"
}, },
"dependencies": { "dependencies": {
"gulp-group-css-media-queries": "^1.2.2",
"gulp-rollup-2": "^1.2.1", "gulp-rollup-2": "^1.2.1",
"rollup": "^2.38.0", "rollup": "^2.38.0",
"rollup-plugin-external-globals": "^0.6.1", "rollup-plugin-external-globals": "^0.6.1",

View file

@ -6,9 +6,9 @@ class ChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
{ {
const const
NAME = 'Change Password', NAME = 'Change Password',
VERSION = '2.1', VERSION = '2.2',
RELEASE = '2021-03-18', RELEASE = '2021-07-20',
REQUIRED = '2.4.0', REQUIRED = '2.5.0',
CATEGORY = 'Security', CATEGORY = 'Security',
DESCRIPTION = 'This plugin allows you to change passwords of email accounts'; DESCRIPTION = 'This plugin allows you to change passwords of email accounts';
@ -23,6 +23,7 @@ class ChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
{ {
$this->UseLangs(true); // start use langs folder $this->UseLangs(true); // start use langs folder
$this->addCss('style.less');
$this->addJs('js/ChangePasswordUserSettings.js'); // add js file $this->addJs('js/ChangePasswordUserSettings.js'); // add js file
$this->addJsonHook('ChangePassword', 'ChangePassword'); $this->addJsonHook('ChangePassword', 'ChangePassword');
$this->addTemplate('templates/SettingsChangePassword.html'); $this->addTemplate('templates/SettingsChangePassword.html');

View file

@ -0,0 +1,5 @@
.form-horizontal.change-password .control-group {
.control-label {
width: 160px;
}
}

View file

@ -1,5 +1,5 @@
<div class="b-settings-general g-ui-user-select-none"> <div class="b-settings-general g-ui-user-select-none">
<div class="form-horizontal long-label"> <div class="form-horizontal change-password">
<div class="legend" data-i18n="SETTINGS_CHANGE_PASSWORD/LEGEND_CHANGE_PASSWORD"></div> <div class="legend" data-i18n="SETTINGS_CHANGE_PASSWORD/LEGEND_CHANGE_PASSWORD"></div>
<div class="row"> <div class="row">
<div class="span6"> <div class="span6">

View file

@ -106,6 +106,15 @@ class Application extends \RainLoop\Config\AbstractConfig
protected function defaultValues() : array protected function defaultValues() : array
{ {
$value = \ini_get('upload_max_filesize');
$upload_max_filesize = \intval($value);
switch (\strtoupper(\substr($value, -1))) {
case 'G': $upload_max_filesize *= 1024;
case 'M': $upload_max_filesize *= 1024;
case 'K': $upload_max_filesize *= 1024;
}
$upload_max_filesize = $upload_max_filesize / 1024 / 1024;
return array( return array(
'webmail' => array( 'webmail' => array(
@ -127,7 +136,7 @@ class Application extends \RainLoop\Config\AbstractConfig
'messages_per_page' => array(20, 'Number of messages displayed on page by default'), 'messages_per_page' => array(20, 'Number of messages displayed on page by default'),
'attachment_size_limit' => array(25, 'File size limit (MB) for file upload on compose screen 'attachment_size_limit' => array(\min($upload_max_filesize, 25), 'File size limit (MB) for file upload on compose screen
0 for unlimited.') 0 for unlimited.')
), ),

View file

@ -4,7 +4,7 @@ namespace RainLoop\Plugins;
class Helper class Helper
{ {
static public function ValidateWildcardValues(string $sString, string $sWildcardValues, string &$sFoundedValue) : bool static public function ValidateWildcardValues(string $sString, string $sWildcardValues, string &$sFoundedValue = null) : bool
{ {
$sFoundedValue = ''; $sFoundedValue = '';

View file

@ -1,5 +1,3 @@
<div class="e-paginator g-ui-user-select-none" data-bind="foreach: $data"> <div class="e-paginator g-ui-user-select-none" data-bind="foreach: $data">
<a class="e-page" data-bind="css: { 'current': current, 'custom': custom }, title: title"> <a class="e-page" data-bind="css: { 'current': current, 'custom': custom }, title: title, text: name"></a>
<span class="e-page-number" data-bind="text: name"></span>
</a>
</div> </div>

View file

@ -3,12 +3,10 @@
<button type="button" class="close" data-bind="command: cancelCommand">×</button> <button type="button" class="close" data-bind="command: cancelCommand">×</button>
<h3 data-i18n="POPUPS_LANGUAGES/TITLE_LANGUAGES"></h3> <h3 data-i18n="POPUPS_LANGUAGES/TITLE_LANGUAGES"></h3>
</div> </div>
<div class="modal-body" style="min-height: 150px;"> <div class="modal-body" style="min-height: 150px;" data-bind="foreach: languages">
<div data-bind="foreach: languages"> <label data-bind="click: function () { $root.changeLanguage(key); }, css: {'selected': selected, 'user': user},
<label class="lang-item" data-bind="click: function () { $root.changeLanguage(key); }, css: {'selected': selected, 'user': user},
attr: { title: $root.languageTooltipName(key) }, attr: { title: $root.languageTooltipName(key) },
text: fullName"> text: fullName">
</label> </label>
</div> </div>
</div>
</div> </div>

View file

@ -1,6 +1,5 @@
<div id="rl-sub-left"> <div id="rl-sub-left" class="messageList g-ui-user-select-none"
<div class="messageList g-ui-user-select-none" data-bind="css: {'message-selected': isMessageSelected, 'message-focused': !messageListFocused() }">
data-bind="css: {'message-selected': isMessageSelected, 'message-focused': !messageListFocused(), 'hideMessageListCheckbox': !useCheckboxesInList() }">
<div class="toolbar"> <div class="toolbar">
<div class="btn-toolbar"> <div class="btn-toolbar">
<a class="btn btn-thin-2 fontastic show-mobile" data-bind="click: hideLeft, visible: !leftPanelDisabled()"></a> <a class="btn btn-thin-2 fontastic show-mobile" data-bind="click: hideLeft, visible: !leftPanelDisabled()"></a>
@ -8,8 +7,8 @@
<a class="btn buttonCompose show-mobile" data-bind="click: composeClick, css: {'btn-warning': composeInEdit, 'btn-success': !composeInEdit()}, visible: allowComposer && mobileCheckedStateHide()" data-i18n="[title]FOLDER_LIST/BUTTON_NEW_MESSAGE"> <a class="btn buttonCompose show-mobile" data-bind="click: composeClick, css: {'btn-warning': composeInEdit, 'btn-success': !composeInEdit()}, visible: allowComposer && mobileCheckedStateHide()" data-i18n="[title]FOLDER_LIST/BUTTON_NEW_MESSAGE">
<i class="icon-paper-plane"></i> <i class="icon-paper-plane"></i>
</a> </a>
<a class="btn buttonReload" data-bind="command: reloadCommand, visible: allowReload && mobileCheckedStateHide()" data-i18n="[title]MESSAGE_LIST/BUTTON_RELOAD"> <a class="btn" data-bind="command: reloadCommand, visible: allowReload && mobileCheckedStateHide()" data-i18n="[title]MESSAGE_LIST/BUTTON_RELOAD">
<i class="icon-spinner" data-bind="css: {'not-animated': !messageListCompleteLoadingThrottleForAnimation()}"></i> <i class="icon-spinner not-animated"></i>
</a> </a>
<!-- ko if: !newMoveToFolder --> <!-- ko if: !newMoveToFolder -->
<div class="btn-group dropdown colored-toggle hide-mobile" data-bind="visible: allowMessageListActions, registerBootstrapDropdown: true, openDropdownTrigger: moveDropdownTrigger"> <div class="btn-group dropdown colored-toggle hide-mobile" data-bind="visible: allowMessageListActions, registerBootstrapDropdown: true, openDropdownTrigger: moveDropdownTrigger">
@ -156,7 +155,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="b-message-list-wrapper"> <div class="b-message-list-wrapper" data-bind="css: {'hideMessageListCheckbox': !useCheckboxesInList() }">
<div class="second-toolbar thm-message-list-top-toolbar"> <div class="second-toolbar thm-message-list-top-toolbar">
<div class="form-inline"> <div class="form-inline">
<i class="checkboxCheckAll fontastic" data-bind="text: checkAll() ? (isIncompleteChecked() ? '▣' : '☑') : '☐'"></i> <i class="checkboxCheckAll fontastic" data-bind="text: checkAll() ? (isIncompleteChecked() ? '▣' : '☑') : '☐'"></i>
@ -254,5 +253,4 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</div> </div>

View file

@ -1,4 +1,4 @@
<div class="modal fade b-contacts-content" data-bind="modal: modalVisibility"> <div class="modal fade">
<div class="modal-header b-header-toolbar g-ui-user-select-none"> <div class="modal-header b-header-toolbar g-ui-user-select-none">
<button type="button" class="close" data-bind="command: cancelCommand">×</button> <button type="button" class="close" data-bind="command: cancelCommand">×</button>
@ -48,7 +48,7 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="b-list-toolbar"> <div class="b-list-toolbar">
<input type="search" class="span3 e-search" placeholder="Search" autocorrect="off" autocapitalize="off" data-i18n="[placeholder]GLOBAL/SEARCH" data-bind="value: search" /> <input type="search" class="e-search" placeholder="Search" autocorrect="off" autocapitalize="off" data-i18n="[placeholder]GLOBAL/SEARCH" data-bind="value: search" />
</div> </div>
<div class="b-list-content g-ui-user-select-none" data-bind="css: {'hideContactListCheckbox': !useCheckboxesInList()}"> <div class="b-list-content g-ui-user-select-none" data-bind="css: {'hideContactListCheckbox': !useCheckboxesInList()}">
<div class="content"> <div class="content">

View file

@ -121,7 +121,7 @@
border-bottom-color: #444; border-bottom-color: #444;
} }
.messageList .messageListItem { .messageListItem {
border-left-color: #111; border-left-color: #111;
color: #EEE; color: #EEE;
} }

View file

@ -8,6 +8,7 @@ const eol = require('gulp-eol');
const livereload = require('gulp-livereload'); const livereload = require('gulp-livereload');
const filter = require('gulp-filter'); const filter = require('gulp-filter');
const expect = require('gulp-expect-file'); const expect = require('gulp-expect-file');
const gcmq = require('gulp-group-css-media-queries');
const { config } = require('./config'); const { config } = require('./config');
const { del } = require('./common'); const { del } = require('./common');
@ -85,6 +86,7 @@ const cssBootMin = () => {
const cssMainMin = () => { const cssMainMin = () => {
return gulp return gulp
.src(config.paths.staticCSS + config.paths.css.main.name) .src(config.paths.staticCSS + config.paths.css.main.name)
.pipe(gcmq())
.pipe(cleanCss()) .pipe(cleanCss())
.pipe(rename({ suffix: '.min' })) .pipe(rename({ suffix: '.min' }))
.pipe(eol('\n', true)) .pipe(eol('\n', true))
@ -94,6 +96,7 @@ const cssMainMin = () => {
const cssAdminMin = () => { const cssAdminMin = () => {
return gulp return gulp
.src(config.paths.staticCSS + config.paths.css.admin.name) .src(config.paths.staticCSS + config.paths.css.admin.name)
.pipe(gcmq())
.pipe(cleanCss()) .pipe(cleanCss())
.pipe(rename({ suffix: '.min' })) .pipe(rename({ suffix: '.min' }))
.pipe(eol('\n', true)) .pipe(eol('\n', true))

View file

@ -45,9 +45,6 @@
.btn-group > .btn-small { .btn-group > .btn-small {
font-size: 12px; font-size: 12px;
} }
.btn-group > .btn-large {
font-size: 16px;
}
// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match // Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match
.btn-group > .btn:first-child { .btn-group > .btn:first-child {
@ -61,17 +58,6 @@
border-top-right-radius: 3px; border-top-right-radius: 3px;
border-bottom-right-radius: 3px; border-bottom-right-radius: 3px;
} }
// Reset corners for large buttons
.btn-group > .btn.large:first-child {
margin-left: 0;
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
}
.btn-group > .btn.large:last-child,
.btn-group > .large.dropdown-toggle {
border-top-right-radius: 6px;
border-bottom-right-radius: 6px;
}
// On hover/focus/active, bring the proper btn to front // On hover/focus/active, bring the proper btn to front
.btn-group > .btn:hover, .btn-group > .btn:hover,
@ -84,17 +70,6 @@
// Split button dropdowns // Split button dropdowns
// ---------------------- // ----------------------
// Give the line between buttons some depth
.btn-group > .btn + .dropdown-toggle {
padding-left: 8px;
padding-right: 8px;
box-shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
}
.btn-group > .btn-large + .dropdown-toggle {
padding-left: 12px;
padding-right: 12px;
}
.btn-group.open { .btn-group.open {
// The clickable button for toggling the menu // The clickable button for toggling the menu

View file

@ -65,9 +65,6 @@
line-height: normal; line-height: normal;
border-radius: 5px; border-radius: 5px;
} }
.btn-large [class^="icon-"] {
margin-top: 2px;
}
// Small // Small
.btn-small { .btn-small {
@ -75,9 +72,6 @@
font-size: @baseFontSize - 2px; font-size: @baseFontSize - 2px;
line-height: @baseLineHeight - 2px; line-height: @baseLineHeight - 2px;
} }
.btn-small [class^="icon-"] {
margin-top: 0;
}
// Block button // Block button
.btn-block { .btn-block {
@ -87,9 +81,6 @@
padding-right: 0; padding-right: 0;
box-sizing: border-box; box-sizing: border-box;
} }
.btn-block + .btn-block {
margin-top: 5px;
}
// Alternate buttons // Alternate buttons

View file

@ -92,11 +92,3 @@
background-color: transparent; background-color: transparent;
cursor: default; cursor: default;
} }
// Open state for the dropdown
// ---------------------------
.open {
& > .dropdown-menu {
display: block;
}
}

View file

@ -29,12 +29,6 @@ legend {
color: @grayDark; color: @grayDark;
border: 0; border: 0;
border-bottom: 1px solid #e5e5e5; border-bottom: 1px solid #e5e5e5;
// Small
small {
font-size: @baseLineHeight * .75;
color: @grayLight;
}
} }
// Identify controls by their labels // Identify controls by their labels
@ -84,6 +78,7 @@ textarea {
// Reset height since textareas have rows // Reset height since textareas have rows
textarea { textarea {
height: auto; height: auto;
resize: none;
} }
// Everything else // Everything else
textarea, textarea,

View file

@ -104,9 +104,6 @@
vertical-align: top; vertical-align: top;
} }
// Set the container width
.container { .span(@gridColumns); }
// generate .spanX // generate .spanX
.spanX (@gridColumns); .spanX (@gridColumns);
} }

View file

@ -5,10 +5,11 @@
// Base modal // Base modal
.modal { .modal {
position: relative; position: absolute;
z-index: @zindexModal; z-index: @zindexModal;
overflow: hidden; overflow: hidden;
width: 560px; width: calc(100% - 20px);
max-width: 560px;
margin: 10px auto; margin: 10px auto;
background-color: @white; background-color: @white;
border: 1px solid rgba(0,0,0,.3); border: 1px solid rgba(0,0,0,.3);
@ -16,6 +17,8 @@
box-shadow: 0 5px 80px rgba(0,0,0,0.3); box-shadow: 0 5px 80px rgba(0,0,0,0.3);
background-clip: padding-box; background-clip: padding-box;
top: 0; top: 0;
left: 0;
right: 0;
} }
.modal-header { .modal-header {

View file

@ -12,12 +12,6 @@
background-color: @tableBackground; background-color: @tableBackground;
border-collapse: collapse; border-collapse: collapse;
border-spacing: 0; border-spacing: 0;
}
// BASELINE STYLES
// ---------------
.table {
width: 100%; width: 100%;
margin-bottom: @baseLineHeight; margin-bottom: @baseLineHeight;
// Cells // Cells

View file

@ -871,6 +871,30 @@ cross-spawn@^6.0.5:
shebang-command "^1.2.0" shebang-command "^1.2.0"
which "^1.2.9" which "^1.2.9"
css-parse@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/css-parse/-/css-parse-2.0.0.tgz#a468ee667c16d81ccf05c58c38d2a97c780dbfd4"
integrity sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=
dependencies:
css "^2.0.0"
css-stringify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/css-stringify/-/css-stringify-2.0.0.tgz#2ef33dcf498c3d3ee82bd73d0a01ac28628cd0fa"
integrity sha1-LvM9z0mMPT7oK9c9CgGsKGKM0Po=
dependencies:
css "^2.0.0"
css@^2.0.0:
version "2.2.4"
resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929"
integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==
dependencies:
inherits "^2.0.3"
source-map "^0.6.1"
source-map-resolve "^0.5.2"
urix "^0.1.0"
d@1, d@^1.0.1: d@1, d@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
@ -1603,6 +1627,14 @@ graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6:
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
group-css-media-queries@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/group-css-media-queries/-/group-css-media-queries-1.4.1.tgz#8e54cb31cc45a9c5e08eb838940b8a28038d7175"
integrity sha1-jlTLMcxFqcXgjrg4lAuKKAONcXU=
dependencies:
css-parse "^2.0.0"
css-stringify "^2.0.0"
gulp-cached@1.1.1: gulp-cached@1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/gulp-cached/-/gulp-cached-1.1.1.tgz#fe7cd4f87f37601e6073cfedee5c2bdaf8b6acce" resolved "https://registry.yarnpkg.com/gulp-cached/-/gulp-cached-1.1.1.tgz#fe7cd4f87f37601e6073cfedee5c2bdaf8b6acce"
@ -1697,6 +1729,15 @@ gulp-filter@6.0.0:
plugin-error "^1.0.1" plugin-error "^1.0.1"
streamfilter "^3.0.0" streamfilter "^3.0.0"
gulp-group-css-media-queries@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/gulp-group-css-media-queries/-/gulp-group-css-media-queries-1.2.2.tgz#c0436b9474086cbe1ab3eb5bc1a3afef4d6b37d6"
integrity sha512-uOs8aJ5TV12aRstfc6pn107edDT2XSY7KNAU721Dz+gKHu/AUIlAaOdFdo9n/eHWqfb9QWMArrM8fiPOCqZPGg==
dependencies:
group-css-media-queries "^1.4.1"
plugin-error "^1.0.1"
through2 "^2.0.3"
gulp-header@2.0.9: gulp-header@2.0.9:
version "2.0.9" version "2.0.9"
resolved "https://registry.yarnpkg.com/gulp-header/-/gulp-header-2.0.9.tgz#8b432c4d4379dee6788845b16785b09c7675af84" resolved "https://registry.yarnpkg.com/gulp-header/-/gulp-header-2.0.9.tgz#8b432c4d4379dee6788845b16785b09c7675af84"
@ -3695,7 +3736,7 @@ snapdragon@^0.8.1:
source-map-resolve "^0.5.0" source-map-resolve "^0.5.0"
use "^3.1.0" use "^3.1.0"
source-map-resolve@^0.5.0: source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
version "0.5.3" version "0.5.3"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"
integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==