mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-28 19:49:20 +03:00
Added: resize messages list vertical
This commit is contained in:
parent
5188a88e95
commit
263e595ba2
10 changed files with 450 additions and 465 deletions
|
|
@ -1,7 +1,7 @@
|
|||
import 'External/User/ko';
|
||||
|
||||
import { isArray, arrayLength, pString, forEachObjectValue } from 'Common/Utils';
|
||||
import { delegateRunOnDestroy, mailToHelper } from 'Common/UtilsUser';
|
||||
import { delegateRunOnDestroy, mailToHelper, setLayoutResizer } from 'Common/UtilsUser';
|
||||
|
||||
import {
|
||||
Capa,
|
||||
|
|
@ -10,7 +10,6 @@ import {
|
|||
} from 'Common/Enums';
|
||||
|
||||
import {
|
||||
Layout,
|
||||
FolderType,
|
||||
SetSystemFoldersNotification,
|
||||
MessageSetAction,
|
||||
|
|
@ -679,83 +678,11 @@ class AppUser extends AbstractApp {
|
|||
Local.set(ClientSideKeyName.ExpandedFolders, aExpandedList);
|
||||
}
|
||||
|
||||
setLayoutResizer(source, target, sClientSideKeyName, mode) {
|
||||
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() {
|
||||
initLeftSideLayoutResizer() {
|
||||
const left = elementById('rl-left'),
|
||||
right = elementById('rl-right'),
|
||||
fToggle = () =>
|
||||
this.setLayoutResizer(left, right, ClientSideKeyName.FolderListSize,
|
||||
setLayoutResizer(left, right, ClientSideKeyName.FolderListSize,
|
||||
(ThemeStore.isMobile() || leftPanelDisabled()) ? null : 'width');
|
||||
if (left && right) {
|
||||
fToggle();
|
||||
|
|
@ -868,7 +795,7 @@ class AppUser extends AbstractApp {
|
|||
);
|
||||
SettingsUserStore.delayLogout();
|
||||
|
||||
setTimeout(() => this.initVerticalLayoutResizer(), 1);
|
||||
setTimeout(() => this.initLeftSideLayoutResizer(), 1);
|
||||
|
||||
setInterval(this.reloadTime(), 60000);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,21 +5,23 @@ import { isArray } from 'Common/Utils';
|
|||
import { createElement } from 'Common/Globals';
|
||||
import { FolderUserStore } from 'Stores/User/Folder';
|
||||
import { SettingsUserStore } from 'Stores/User/Settings';
|
||||
import * as Local from 'Storage/Client';
|
||||
|
||||
export const
|
||||
/**
|
||||
* @param {(string|number)} value
|
||||
* @param {boolean=} includeZero = true
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isPosNumeric(value) {
|
||||
isPosNumeric = (value) => {
|
||||
return null != value && /^[0-9]*$/.test(value.toString());
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} html
|
||||
* @returns {string}
|
||||
*/
|
||||
export function htmlToPlain(html) {
|
||||
htmlToPlain = (html) => {
|
||||
let pos = 0,
|
||||
limit = 800,
|
||||
iP1 = 0,
|
||||
|
|
@ -112,14 +114,14 @@ export function htmlToPlain(html) {
|
|||
}
|
||||
|
||||
return text.replace(/__bq__start__|__bq__end__/gm, '').trim();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} plain
|
||||
* @param {boolean} findEmailAndLinksInText = false
|
||||
* @returns {string}
|
||||
*/
|
||||
export function plainToHtml(plain) {
|
||||
plainToHtml = (plain) => {
|
||||
plain = plain.toString().replace(/\r/g, '');
|
||||
plain = plain.replace(/^>[> ]>+/gm, ([match]) => (match ? match.replace(/[ ]+/g, '') : match));
|
||||
|
||||
|
|
@ -170,12 +172,7 @@ export function plainToHtml(plain) {
|
|||
.replace(/~~~blockquote~~~[\s]*/g, '<blockquote>')
|
||||
.replace(/[\s]*~~~\/blockquote~~~/g, '</blockquote>')
|
||||
.replace(/\n/g, '<br/>');
|
||||
}
|
||||
|
||||
rl.Utils = {
|
||||
htmlToPlain: htmlToPlain,
|
||||
plainToHtml: plainToHtml
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Array=} aDisabled
|
||||
|
|
@ -185,14 +182,14 @@ rl.Utils = {
|
|||
* @param {boolean=} bNoSelectSelectable Used in FolderCreatePopupView
|
||||
* @returns {Array}
|
||||
*/
|
||||
export function folderListOptionsBuilder(
|
||||
folderListOptionsBuilder = (
|
||||
aDisabled,
|
||||
aHeaderLines,
|
||||
fRenameCallback,
|
||||
fDisableCallback,
|
||||
bNoSelectSelectable,
|
||||
aList = FolderUserStore.folderList()
|
||||
) {
|
||||
) => {
|
||||
const
|
||||
aResult = [],
|
||||
sDeepPrefix = '\u00A0\u00A0\u00A0',
|
||||
|
|
@ -238,23 +235,23 @@ export function folderListOptionsBuilder(
|
|||
foldersWalk(aList);
|
||||
|
||||
return aResult;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Call the Model/CollectionModel onDestroy() to clear knockout functions/objects
|
||||
* @param {Object|Array} objectOrObjects
|
||||
* @returns {void}
|
||||
*/
|
||||
export function delegateRunOnDestroy(objectOrObjects) {
|
||||
delegateRunOnDestroy = (objectOrObjects) => {
|
||||
objectOrObjects && (isArray(objectOrObjects) ? objectOrObjects : [objectOrObjects]).forEach(
|
||||
obj => obj.onDestroy && obj.onDestroy()
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @returns {function}
|
||||
*/
|
||||
export function computedPaginatorHelper(koCurrentPage, koPageCount) {
|
||||
computedPaginatorHelper = (koCurrentPage, koPageCount) => {
|
||||
return () => {
|
||||
const currentPage = koCurrentPage(),
|
||||
pageCount = koPageCount(),
|
||||
|
|
@ -335,13 +332,13 @@ export function computedPaginatorHelper(koCurrentPage, koPageCount) {
|
|||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} mailToUrl
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function mailToHelper(mailToUrl) {
|
||||
mailToHelper = (mailToUrl) => {
|
||||
if (
|
||||
mailToUrl &&
|
||||
'mailto:' ===
|
||||
|
|
@ -397,9 +394,78 @@ export function mailToHelper(mailToUrl) {
|
|||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
export function showMessageComposer(params = [])
|
||||
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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -305,7 +305,6 @@ export const
|
|||
hasher.init();
|
||||
|
||||
setTimeout(() => $htmlCL.remove('rl-started-trigger'), 100);
|
||||
setTimeout(() => $htmlCL.add('rl-started-delay'), 200);
|
||||
|
||||
const c = elementById('rl-content'), l = elementById('rl-loading');
|
||||
c && (c.hidden = false);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
import { Scope } from 'Common/Enums';
|
||||
import { Layout, ClientSideKeyName } from 'Common/EnumsUser';
|
||||
import { doc, leftPanelDisabled, moveAction, Settings } from 'Common/Globals';
|
||||
import { pString, pInt } from 'Common/Utils';
|
||||
import { setLayoutResizer } from 'Common/UtilsUser';
|
||||
import { getFolderFromCacheList, getFolderFullNameRaw, getFolderInboxName } from 'Common/Cache';
|
||||
import { i18n } from 'Common/Translator';
|
||||
import { SettingsUserStore } from 'Stores/User/Settings';
|
||||
|
||||
import { AppUserStore } from 'Stores/User/App';
|
||||
import { AccountUserStore } from 'Stores/User/Account';
|
||||
|
|
@ -99,7 +102,23 @@ export class MailBoxUserScreen extends AbstractScreen {
|
|||
* @returns {void}
|
||||
*/
|
||||
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 =>
|
||||
event.target.closest('#rl-right') && moveAction(false)
|
||||
|
|
|
|||
|
|
@ -8,19 +8,12 @@
|
|||
100% {transform: translateX(0)}
|
||||
}
|
||||
|
||||
html.rl-started-delay {
|
||||
#rl-left {
|
||||
transition: width 0.3s ease-out;
|
||||
}
|
||||
|
||||
#rl-left {
|
||||
transition: width 0.3s ease-out;
|
||||
}
|
||||
|
||||
#rl-right {
|
||||
transition: left 0.3s ease-out, right 0.3s ease-out;
|
||||
}
|
||||
|
||||
#rl-sub-right {
|
||||
transition: left 0.3s ease-out;
|
||||
}
|
||||
#rl-right {
|
||||
transition: left 0.3s ease-out, right 0.3s ease-out;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1000px) {
|
||||
|
|
|
|||
|
|
@ -68,7 +68,9 @@ html:not(.rl-left-panel-disabled) #rl-left.resizable {
|
|||
min-width: 155px;
|
||||
max-width: 350px;
|
||||
}
|
||||
#rl-left > .resizer {
|
||||
|
||||
#rl-left > .resizer,
|
||||
.rl-side-preview-pane .RL-MailMessageList > .resizer {
|
||||
cursor: ew-resize;
|
||||
height: 100%;
|
||||
right: 0;
|
||||
|
|
@ -105,13 +107,17 @@ html:not(.rl-left-panel-disabled) #rl-left.resizable {
|
|||
}
|
||||
}
|
||||
|
||||
.b-message-list-wrapper.resizable {
|
||||
resize: vertical;
|
||||
overflow: hidden;
|
||||
min-height: 200px;
|
||||
max-height: 500px;
|
||||
.rl-side-preview-pane .RL-MailMessageList.resizable {
|
||||
resize: horizontal;
|
||||
min-width: 320px;
|
||||
max-width: 60%;
|
||||
}
|
||||
.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;
|
||||
height: 5px;
|
||||
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,
|
||||
.b-message-list-wrapper > .resizer {
|
||||
.RL-MailMessageList > .resizer {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
|
@ -129,18 +135,18 @@ html:not(.rl-left-panel-disabled) #rl-left.resizable > .resizer,
|
|||
left: @rlLeftWidth;
|
||||
}
|
||||
|
||||
#rl-sub-left {
|
||||
.RL-MailMessageList {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
top: 50px;
|
||||
bottom: @rlBottomMargin;
|
||||
left: 0;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
#rl-sub-right {
|
||||
.RL-MailMessageView {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
top: 50px + @rlLowMargin;
|
||||
bottom: 13px;
|
||||
right: 0;
|
||||
left: 50%;
|
||||
|
||||
|
|
@ -244,11 +250,11 @@ html:not(.rl-left-panel-disabled) #rl-left.resizable > .resizer,
|
|||
left: @rlLeftWidth + 20;
|
||||
}
|
||||
|
||||
#rl-sub-left {
|
||||
.RL-MailMessageList {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
#rl-sub-right {
|
||||
.RL-MailMessageView {
|
||||
left: 40%;
|
||||
}
|
||||
}
|
||||
|
|
@ -304,45 +310,34 @@ html.rl-left-panel-disabled {
|
|||
html.rl-mobile,
|
||||
html.rl-no-preview-pane {
|
||||
|
||||
#rl-sub-left {
|
||||
.RL-MailMessageList {
|
||||
right: @rlBottomMargin !important;
|
||||
width: inherit;
|
||||
}
|
||||
|
||||
#rl-sub-right {
|
||||
.RL-MailMessageView {
|
||||
left: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
html.rl-bottom-preview-pane:not(.rl-mobile) {
|
||||
|
||||
#rl-sub-left {
|
||||
.RL-MailMessageList {
|
||||
right: @rlBottomMargin !important;
|
||||
bottom: inherit;
|
||||
width: inherit;
|
||||
|
||||
.b-message-list-wrapper {
|
||||
bottom: inherit;
|
||||
height: 300px;
|
||||
|
||||
box-shadow: none;
|
||||
}
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
#rl-sub-right {
|
||||
|
||||
.RL-MailMessageView {
|
||||
left: 0 !important;
|
||||
|
||||
.b-message-view-wrapper {
|
||||
top: 356px;
|
||||
left: 0;
|
||||
right: 5px;
|
||||
box-shadow: none;
|
||||
}
|
||||
top: 356px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@ html.rl-no-preview-pane {
|
|||
}
|
||||
|
||||
.messageList {
|
||||
height: 100%;
|
||||
|
||||
.toolbar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
top: -50px;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height: 30px;
|
||||
|
|
@ -59,13 +60,8 @@ html.rl-no-preview-pane {
|
|||
}
|
||||
|
||||
.b-message-list-wrapper {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: @rlBottomMargin;
|
||||
|
||||
border: 1px solid @rlMainDarkColor;
|
||||
height: 100%;
|
||||
|
||||
box-shadow: @rlMainShadow;
|
||||
border-radius: @rlMainBorderRadius;
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@
|
|||
}
|
||||
|
||||
.messageView {
|
||||
height: 100%;
|
||||
|
||||
.toolbar {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
top: -50px - @rlLowMargin;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height: 30px;
|
||||
|
|
@ -15,19 +16,10 @@
|
|||
}
|
||||
|
||||
.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;
|
||||
border: 1px solid @rlMainDarkColor;
|
||||
border-radius: @rlMainBorderRadius;
|
||||
height: 100%;
|
||||
|
||||
.b-message-view-checked-helper {
|
||||
text-align: center;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue