Added: resize messages list vertical

This commit is contained in:
djmaze 2021-11-05 10:20:06 +01:00
parent 5188a88e95
commit 263e595ba2
10 changed files with 450 additions and 465 deletions

View file

@ -1,7 +1,7 @@
import 'External/User/ko'; import 'External/User/ko';
import { isArray, arrayLength, pString, forEachObjectValue } from 'Common/Utils'; import { isArray, arrayLength, pString, forEachObjectValue } from 'Common/Utils';
import { delegateRunOnDestroy, mailToHelper } from 'Common/UtilsUser'; import { delegateRunOnDestroy, mailToHelper, setLayoutResizer } from 'Common/UtilsUser';
import { import {
Capa, Capa,
@ -10,7 +10,6 @@ import {
} from 'Common/Enums'; } from 'Common/Enums';
import { import {
Layout,
FolderType, FolderType,
SetSystemFoldersNotification, SetSystemFoldersNotification,
MessageSetAction, MessageSetAction,
@ -679,83 +678,11 @@ class AppUser extends AbstractApp {
Local.set(ClientSideKeyName.ExpandedFolders, aExpandedList); Local.set(ClientSideKeyName.ExpandedFolders, aExpandedList);
} }
setLayoutResizer(source, target, sClientSideKeyName, mode) { initLeftSideLayoutResizer() {
if (mode) {
source.classList.add('resizable');
if (!source.querySelector('.resizer')) {
const resizer = createElement('div', {'class':'resizer'}),
cssint = s => parseFloat(getComputedStyle(source, null).getPropertyValue(s).replace('px', ''));
source.append(resizer);
resizer.addEventListener('mousedown', {
source: source,
mode: mode,
handleEvent: function(e) {
if ('mousedown' == e.type) {
e.preventDefault();
this.pos = ('width' == this.mode) ? e.pageX : e.pageY;
this.min = cssint('min-'+this.mode);
this.max = cssint('max-'+this.mode);
this.org = cssint(this.mode);
addEventListener('mousemove', this);
addEventListener('mouseup', this);
} else if ('mousemove' == e.type) {
const length = this.org + (('width' == this.mode ? e.pageX : e.pageY) - this.pos);
if (length >= this.min && length <= this.max ) {
this.source.style[this.mode] = length + 'px';
}
} else if ('mouseup' == e.type) {
removeEventListener('mousemove', this);
removeEventListener('mouseup', this);
}
}
});
if ('width' == mode) {
source.observer = new ResizeObserver(() => {
target.style.left = source.offsetWidth + 'px';
Local.set(sClientSideKeyName, source.offsetWidth);
});
} else {
source.observer = new ResizeObserver(() => {
target.style.top = (4 + source.offsetTop + source.offsetHeight) + 'px';
Local.set(sClientSideKeyName, source.offsetHeight);
});
}
}
source.observer.observe(source, { box: 'border-box' });
const length = Local.get(sClientSideKeyName);
if (length) {
if ('width' == mode) {
source.style.width = length + 'px';
} else {
source.style.height = length + 'px';
}
}
} else {
source.observer && source.observer.disconnect();
source.classList.remove('resizable');
target.removeAttribute('style');
source.removeAttribute('style');
}
}
initHorizontalLayoutResizer() {
const top = doc.querySelector('.b-message-list-wrapper'),
bottom = doc.querySelector('.b-message-view-wrapper'),
fToggle = () => {
this.setLayoutResizer(top, bottom, ClientSideKeyName.MessageListSize,
(ThemeStore.isMobile() || Layout.BottomPreview !== SettingsUserStore.layout()) ? null : 'height');
};
if (top && bottom) {
fToggle();
addEventListener('rl-layout', fToggle);
}
}
initVerticalLayoutResizer() {
const left = elementById('rl-left'), const left = elementById('rl-left'),
right = elementById('rl-right'), right = elementById('rl-right'),
fToggle = () => fToggle = () =>
this.setLayoutResizer(left, right, ClientSideKeyName.FolderListSize, setLayoutResizer(left, right, ClientSideKeyName.FolderListSize,
(ThemeStore.isMobile() || leftPanelDisabled()) ? null : 'width'); (ThemeStore.isMobile() || leftPanelDisabled()) ? null : 'width');
if (left && right) { if (left && right) {
fToggle(); fToggle();
@ -868,7 +795,7 @@ class AppUser extends AbstractApp {
); );
SettingsUserStore.delayLogout(); SettingsUserStore.delayLogout();
setTimeout(() => this.initVerticalLayoutResizer(), 1); setTimeout(() => this.initLeftSideLayoutResizer(), 1);
setInterval(this.reloadTime(), 60000); setInterval(this.reloadTime(), 60000);

View file

@ -5,21 +5,23 @@ import { isArray } from 'Common/Utils';
import { createElement } from 'Common/Globals'; import { createElement } from 'Common/Globals';
import { FolderUserStore } from 'Stores/User/Folder'; import { FolderUserStore } from 'Stores/User/Folder';
import { SettingsUserStore } from 'Stores/User/Settings'; import { SettingsUserStore } from 'Stores/User/Settings';
import * as Local from 'Storage/Client';
export const
/** /**
* @param {(string|number)} value * @param {(string|number)} value
* @param {boolean=} includeZero = true * @param {boolean=} includeZero = true
* @returns {boolean} * @returns {boolean}
*/ */
export function isPosNumeric(value) { isPosNumeric = (value) => {
return null != value && /^[0-9]*$/.test(value.toString()); return null != value && /^[0-9]*$/.test(value.toString());
} },
/** /**
* @param {string} html * @param {string} html
* @returns {string} * @returns {string}
*/ */
export function htmlToPlain(html) { htmlToPlain = (html) => {
let pos = 0, let pos = 0,
limit = 800, limit = 800,
iP1 = 0, iP1 = 0,
@ -112,14 +114,14 @@ export function htmlToPlain(html) {
} }
return text.replace(/__bq__start__|__bq__end__/gm, '').trim(); return text.replace(/__bq__start__|__bq__end__/gm, '').trim();
} },
/** /**
* @param {string} plain * @param {string} plain
* @param {boolean} findEmailAndLinksInText = false * @param {boolean} findEmailAndLinksInText = false
* @returns {string} * @returns {string}
*/ */
export function plainToHtml(plain) { plainToHtml = (plain) => {
plain = plain.toString().replace(/\r/g, ''); plain = plain.toString().replace(/\r/g, '');
plain = plain.replace(/^>[> ]>+/gm, ([match]) => (match ? match.replace(/[ ]+/g, '') : match)); plain = plain.replace(/^>[> ]>+/gm, ([match]) => (match ? match.replace(/[ ]+/g, '') : match));
@ -170,12 +172,7 @@ export function plainToHtml(plain) {
.replace(/~~~blockquote~~~[\s]*/g, '<blockquote>') .replace(/~~~blockquote~~~[\s]*/g, '<blockquote>')
.replace(/[\s]*~~~\/blockquote~~~/g, '</blockquote>') .replace(/[\s]*~~~\/blockquote~~~/g, '</blockquote>')
.replace(/\n/g, '<br/>'); .replace(/\n/g, '<br/>');
} },
rl.Utils = {
htmlToPlain: htmlToPlain,
plainToHtml: plainToHtml
};
/** /**
* @param {Array=} aDisabled * @param {Array=} aDisabled
@ -185,14 +182,14 @@ rl.Utils = {
* @param {boolean=} bNoSelectSelectable Used in FolderCreatePopupView * @param {boolean=} bNoSelectSelectable Used in FolderCreatePopupView
* @returns {Array} * @returns {Array}
*/ */
export function folderListOptionsBuilder( folderListOptionsBuilder = (
aDisabled, aDisabled,
aHeaderLines, aHeaderLines,
fRenameCallback, fRenameCallback,
fDisableCallback, fDisableCallback,
bNoSelectSelectable, bNoSelectSelectable,
aList = FolderUserStore.folderList() aList = FolderUserStore.folderList()
) { ) => {
const const
aResult = [], aResult = [],
sDeepPrefix = '\u00A0\u00A0\u00A0', sDeepPrefix = '\u00A0\u00A0\u00A0',
@ -238,23 +235,23 @@ export function folderListOptionsBuilder(
foldersWalk(aList); foldersWalk(aList);
return aResult; return aResult;
} },
/** /**
* Call the Model/CollectionModel onDestroy() to clear knockout functions/objects * Call the Model/CollectionModel onDestroy() to clear knockout functions/objects
* @param {Object|Array} objectOrObjects * @param {Object|Array} objectOrObjects
* @returns {void} * @returns {void}
*/ */
export function delegateRunOnDestroy(objectOrObjects) { delegateRunOnDestroy = (objectOrObjects) => {
objectOrObjects && (isArray(objectOrObjects) ? objectOrObjects : [objectOrObjects]).forEach( objectOrObjects && (isArray(objectOrObjects) ? objectOrObjects : [objectOrObjects]).forEach(
obj => obj.onDestroy && obj.onDestroy() obj => obj.onDestroy && obj.onDestroy()
); );
} },
/** /**
* @returns {function} * @returns {function}
*/ */
export function computedPaginatorHelper(koCurrentPage, koPageCount) { computedPaginatorHelper = (koCurrentPage, koPageCount) => {
return () => { return () => {
const currentPage = koCurrentPage(), const currentPage = koCurrentPage(),
pageCount = koPageCount(), pageCount = koPageCount(),
@ -335,13 +332,13 @@ export function computedPaginatorHelper(koCurrentPage, koPageCount) {
return result; return result;
}; };
} },
/** /**
* @param {string} mailToUrl * @param {string} mailToUrl
* @returns {boolean} * @returns {boolean}
*/ */
export function mailToHelper(mailToUrl) { mailToHelper = (mailToUrl) => {
if ( if (
mailToUrl && mailToUrl &&
'mailto:' === 'mailto:' ===
@ -397,9 +394,78 @@ export function mailToHelper(mailToUrl) {
} }
return false; return false;
} },
export function showMessageComposer(params = []) showMessageComposer = (params = []) =>
{ {
rl.app.showMessageComposer(params); rl.app.showMessageComposer(params);
},
setLayoutResizer = (source, target, sClientSideKeyName, mode) =>
{
if (source.layoutResizer && source.layoutResizer.mode != mode) {
target.removeAttribute('style');
source.removeAttribute('style');
} }
if (mode) {
source.classList.add('resizable');
if (!source.layoutResizer) {
const resizer = createElement('div', {'class':'resizer'}),
size = {},
cssint = s => {
let value = getComputedStyle(source, null)[s].replace('px', '');
if (value.includes('%')) {
value = source.parentElement['width'==resizer.mode ? 'offsetWidth' : 'offsetHeight']
* value.replace('%', '') / 100;
}
return parseFloat(value);
};
source.layoutResizer = resizer;
source.append(resizer);
resizer.addEventListener('mousedown', {
handleEvent: function(e) {
if ('mousedown' == e.type) {
e.preventDefault();
size.pos = ('width' == resizer.mode) ? e.pageX : e.pageY;
size.min = cssint('min-'+resizer.mode);
size.max = cssint('max-'+resizer.mode);
size.org = cssint(resizer.mode);
addEventListener('mousemove', this);
addEventListener('mouseup', this);
} else if ('mousemove' == e.type) {
const length = size.org + (('width' == resizer.mode ? e.pageX : e.pageY) - size.pos);
if (length >= size.min && length <= size.max ) {
source.style[resizer.mode] = length + 'px';
}
} else if ('mouseup' == e.type) {
removeEventListener('mousemove', this);
removeEventListener('mouseup', this);
}
}
});
source.observer = new ResizeObserver(() => {
if ('width' == resizer.mode) {
target.style.left = source.offsetWidth + 'px';
Local.set(sClientSideKeyName, source.offsetWidth);
} else {
target.style.top = (4 + source.offsetTop + source.offsetHeight) + 'px';
Local.set(sClientSideKeyName, source.offsetHeight);
}
});
}
source.layoutResizer.mode = mode;
source.observer.observe(source, { box: 'border-box' });
const length = Local.get(sClientSideKeyName);
if (length) {
source.style[mode] = length + 'px';
}
} else {
source.observer && source.observer.disconnect();
source.classList.remove('resizable');
}
};
rl.Utils = {
htmlToPlain: htmlToPlain,
plainToHtml: plainToHtml
};

View file

@ -305,7 +305,6 @@ export const
hasher.init(); hasher.init();
setTimeout(() => $htmlCL.remove('rl-started-trigger'), 100); setTimeout(() => $htmlCL.remove('rl-started-trigger'), 100);
setTimeout(() => $htmlCL.add('rl-started-delay'), 200);
const c = elementById('rl-content'), l = elementById('rl-loading'); const c = elementById('rl-content'), l = elementById('rl-loading');
c && (c.hidden = false); c && (c.hidden = false);

View file

@ -1,8 +1,11 @@
import { Scope } from 'Common/Enums'; import { Scope } from 'Common/Enums';
import { Layout, ClientSideKeyName } from 'Common/EnumsUser';
import { doc, leftPanelDisabled, moveAction, Settings } from 'Common/Globals'; import { doc, leftPanelDisabled, moveAction, Settings } from 'Common/Globals';
import { pString, pInt } from 'Common/Utils'; import { pString, pInt } from 'Common/Utils';
import { setLayoutResizer } from 'Common/UtilsUser';
import { getFolderFromCacheList, getFolderFullNameRaw, getFolderInboxName } from 'Common/Cache'; import { getFolderFromCacheList, getFolderFullNameRaw, getFolderInboxName } from 'Common/Cache';
import { i18n } from 'Common/Translator'; import { i18n } from 'Common/Translator';
import { SettingsUserStore } from 'Stores/User/Settings';
import { AppUserStore } from 'Stores/User/App'; import { AppUserStore } from 'Stores/User/App';
import { AccountUserStore } from 'Stores/User/Account'; import { AccountUserStore } from 'Stores/User/Account';
@ -99,7 +102,23 @@ export class MailBoxUserScreen extends AbstractScreen {
* @returns {void} * @returns {void}
*/ */
onBuild() { onBuild() {
setTimeout(() => rl.app.initHorizontalLayoutResizer(), 1); setTimeout(() => {
// initMailboxLayoutResizer
const top = doc.querySelector('.RL-MailMessageList'),
bottom = doc.querySelector('.RL-MailMessageView'),
fToggle = () => {
let layout = SettingsUserStore.layout();
setLayoutResizer(top, bottom, ClientSideKeyName.MessageListSize,
(ThemeStore.isMobile() || Layout.NoPreview === layout)
? null
: (Layout.SidePreview === layout ? 'width' : 'height')
);
};
if (top && bottom) {
fToggle();
addEventListener('rl-layout', fToggle);
}
}, 1);
doc.addEventListener('click', event => doc.addEventListener('click', event =>
event.target.closest('#rl-right') && moveAction(false) event.target.closest('#rl-right') && moveAction(false)

View file

@ -8,8 +8,6 @@
100% {transform: translateX(0)} 100% {transform: translateX(0)}
} }
html.rl-started-delay {
#rl-left { #rl-left {
transition: width 0.3s ease-out; transition: width 0.3s ease-out;
} }
@ -18,11 +16,6 @@ html.rl-started-delay {
transition: left 0.3s ease-out, right 0.3s ease-out; transition: left 0.3s ease-out, right 0.3s ease-out;
} }
#rl-sub-right {
transition: left 0.3s ease-out;
}
}
@media screen and (min-width: 1000px) { @media screen and (min-width: 1000px) {
html.rl-started-trigger .b-login-content { html.rl-started-trigger .b-login-content {

View file

@ -68,7 +68,9 @@ html:not(.rl-left-panel-disabled) #rl-left.resizable {
min-width: 155px; min-width: 155px;
max-width: 350px; max-width: 350px;
} }
#rl-left > .resizer {
#rl-left > .resizer,
.rl-side-preview-pane .RL-MailMessageList > .resizer {
cursor: ew-resize; cursor: ew-resize;
height: 100%; height: 100%;
right: 0; right: 0;
@ -105,13 +107,17 @@ html:not(.rl-left-panel-disabled) #rl-left.resizable {
} }
} }
.b-message-list-wrapper.resizable { .rl-side-preview-pane .RL-MailMessageList.resizable {
resize: vertical; resize: horizontal;
overflow: hidden; min-width: 320px;
min-height: 200px; max-width: 60%;
max-height: 500px;
} }
.b-message-list-wrapper > .resizer { .rl-bottom-preview-pane .RL-MailMessageList.resizable {
resize: vertical;
min-height: 200px;
max-height: 60%;
}
.rl-bottom-preview-pane .RL-MailMessageList > .resizer {
cursor: ns-resize; cursor: ns-resize;
height: 5px; height: 5px;
left: 0; left: 0;
@ -120,7 +126,7 @@ html:not(.rl-left-panel-disabled) #rl-left.resizable {
} }
html:not(.rl-left-panel-disabled) #rl-left.resizable > .resizer, html:not(.rl-left-panel-disabled) #rl-left.resizable > .resizer,
.b-message-list-wrapper > .resizer { .RL-MailMessageList > .resizer {
display: block; display: block;
} }
@ -129,18 +135,18 @@ html:not(.rl-left-panel-disabled) #rl-left.resizable > .resizer,
left: @rlLeftWidth; left: @rlLeftWidth;
} }
#rl-sub-left { .RL-MailMessageList {
position: absolute; position: absolute;
top: 0; top: 50px;
bottom: 0; bottom: @rlBottomMargin;
left: 0; left: 0;
width: 50%; width: 50%;
} }
#rl-sub-right { .RL-MailMessageView {
position: absolute; position: absolute;
top: 0; top: 50px + @rlLowMargin;
bottom: 0; bottom: 13px;
right: 0; right: 0;
left: 50%; left: 50%;
@ -244,11 +250,11 @@ html:not(.rl-left-panel-disabled) #rl-left.resizable > .resizer,
left: @rlLeftWidth + 20; left: @rlLeftWidth + 20;
} }
#rl-sub-left { .RL-MailMessageList {
width: 40%; width: 40%;
} }
#rl-sub-right { .RL-MailMessageView {
left: 40%; left: 40%;
} }
} }
@ -304,45 +310,34 @@ html.rl-left-panel-disabled {
html.rl-mobile, html.rl-mobile,
html.rl-no-preview-pane { html.rl-no-preview-pane {
#rl-sub-left { .RL-MailMessageList {
right: @rlBottomMargin !important; right: @rlBottomMargin !important;
width: inherit; width: inherit;
} }
#rl-sub-right { .RL-MailMessageView {
left: 0 !important; left: 0 !important;
} }
} }
html.rl-mobile #rl-left > .resizer, html.rl-mobile #rl-left > .resizer,
html.rl-side-preview-pane:not(.rl-mobile) #rl-right .resizer { html.rl-no-preview-pane #rl-right .resizer,
html.rl-mobile #rl-right .resizer {
display: none !important; display: none !important;
} }
html.rl-bottom-preview-pane:not(.rl-mobile) { html.rl-bottom-preview-pane:not(.rl-mobile) {
#rl-sub-left { .RL-MailMessageList {
right: @rlBottomMargin !important; right: @rlBottomMargin !important;
width: inherit;
.b-message-list-wrapper {
bottom: inherit; bottom: inherit;
width: inherit;
height: 300px; height: 300px;
box-shadow: none;
}
} }
#rl-sub-right { .RL-MailMessageView {
left: 0 !important; left: 0 !important;
.b-message-view-wrapper {
top: 356px; top: 356px;
left: 0;
right: 5px;
box-shadow: none;
}
} }
} }

View file

@ -12,10 +12,11 @@ html.rl-no-preview-pane {
} }
.messageList { .messageList {
height: 100%;
.toolbar { .toolbar {
position: absolute; position: absolute;
top: 0; top: -50px;
right: 0; right: 0;
left: 0; left: 0;
height: 30px; height: 30px;
@ -59,13 +60,8 @@ html.rl-no-preview-pane {
} }
.b-message-list-wrapper { .b-message-list-wrapper {
position: absolute;
top: 50px;
right: 0;
left: 0;
bottom: @rlBottomMargin;
border: 1px solid @rlMainDarkColor; border: 1px solid @rlMainDarkColor;
height: 100%;
box-shadow: @rlMainShadow; box-shadow: @rlMainShadow;
border-radius: @rlMainBorderRadius; border-radius: @rlMainBorderRadius;

View file

@ -3,10 +3,11 @@
} }
.messageView { .messageView {
height: 100%;
.toolbar { .toolbar {
position: absolute; position: absolute;
top: 0; top: -50px - @rlLowMargin;
right: 0; right: 0;
left: 0; left: 0;
height: 30px; height: 30px;
@ -15,19 +16,10 @@
} }
.b-content { .b-content {
position: absolute;
margin: 0;
top: 50px + @rlLowMargin;
bottom: @rlLowMargin + @rlBottomMargin;
right: @rlLowMargin;
left: -2px;
/*overflow: hidden;*/
border: 1px solid @rlMainDarkColor;
border-radius: @rlMainBorderRadius;
background-color: #fff; background-color: #fff;
border: 1px solid @rlMainDarkColor;
border-radius: @rlMainBorderRadius;
height: 100%;
.b-message-view-checked-helper { .b-message-view-checked-helper {
text-align: center; text-align: center;

View file

@ -1,4 +1,4 @@
<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, 'focused': messageListFocused() }"> data-bind="css: {'message-selected': isMessageSelected, 'focused': messageListFocused() }">
<div class="toolbar"> <div class="toolbar">
<div class="btn-toolbar"> <div class="btn-toolbar">

View file

@ -1,4 +1,3 @@
<div id="rl-sub-right">
<div class="messageView" data-bind="css: {'message-selected': isMessageSelected, 'focused': messageFocused}"> <div class="messageView" data-bind="css: {'message-selected': isMessageSelected, 'focused': messageFocused}">
<div class="toolbar top-toolbar g-ui-user-select-none"> <div class="toolbar top-toolbar g-ui-user-select-none">
<div class="messageButtons btn-toolbar"> <div class="messageButtons btn-toolbar">
@ -321,4 +320,3 @@
</div> </div>
</div> </div>
</div> </div>
</div>