mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-09-20 15:45:55 +08:00
This commit is contained in:
parent
add9cb14aa
commit
302f2847b8
123
dev/External/User/ko.js
vendored
123
dev/External/User/ko.js
vendored
|
@ -1,7 +1,28 @@
|
||||||
const ko = window.ko,
|
const ko = window.ko,
|
||||||
rlContentType = 'application/x-rainloop-action',
|
|
||||||
validTransfer = data => ['move','copy'].includes(data.dropEffect) // effectAllowed
|
rlContentType = 'rainloop/action',
|
||||||
&& data.getData('application/x-rainloop-messages');
|
|
||||||
|
// In Chrome we have no access to getData unless it's the 'drop' event
|
||||||
|
getDragAction = e => dragData && e.dataTransfer.types.includes(rlContentType) ? dragData.action : false,
|
||||||
|
setDragAction = (e, action, effect, data, img) => {
|
||||||
|
dragData = {
|
||||||
|
action: action,
|
||||||
|
data: data
|
||||||
|
};
|
||||||
|
e.dataTransfer.setData(rlContentType, action);
|
||||||
|
e.dataTransfer.setData('Text', rlContentType+'/'+action);
|
||||||
|
e.dataTransfer.setDragImage(img, 0, 0);
|
||||||
|
e.dataTransfer.effectAllowed = effect;
|
||||||
|
},
|
||||||
|
|
||||||
|
dragTimer = {
|
||||||
|
id: 0,
|
||||||
|
stop: () => clearTimeout(dragTimer.id),
|
||||||
|
start: fn => dragTimer.id = setTimeout(fn, 500)
|
||||||
|
};
|
||||||
|
|
||||||
|
let dragImage,
|
||||||
|
dragData;
|
||||||
|
|
||||||
ko.bindingHandlers.editor = {
|
ko.bindingHandlers.editor = {
|
||||||
init: (element, fValueAccessor) => {
|
init: (element, fValueAccessor) => {
|
||||||
|
@ -85,26 +106,49 @@ ko.bindingHandlers.emailsTags = {
|
||||||
ko.bindingHandlers.dragmessages = {
|
ko.bindingHandlers.dragmessages = {
|
||||||
init: (element, fValueAccessor) => {
|
init: (element, fValueAccessor) => {
|
||||||
if (!rl.settings.app('mobile')) {
|
if (!rl.settings.app('mobile')) {
|
||||||
element.addEventListener("dragstart", e => fValueAccessor()(e));
|
element.addEventListener("dragstart", e => {
|
||||||
|
let data = fValueAccessor()(e);
|
||||||
|
dragImage || (dragImage = document.getElementById('messagesDragImage'));
|
||||||
|
if (data && dragImage) {
|
||||||
|
dragImage.querySelector('.text').textContent = data.uids.length;
|
||||||
|
let img = dragImage.querySelector('.icon-white');
|
||||||
|
img.classList.toggle('icon-copy', e.ctrlKey);
|
||||||
|
img.classList.toggle('icon-mail', !e.ctrlKey);
|
||||||
|
|
||||||
|
// Else Chrome doesn't show it
|
||||||
|
dragImage.style.left = e.clientX + 'px';
|
||||||
|
dragImage.style.top = e.clientY + 'px';
|
||||||
|
dragImage.style.right = 'auto';
|
||||||
|
|
||||||
|
setDragAction(e, 'messages', e.ctrlKey ? 'copy' : 'move', data, dragImage);
|
||||||
|
|
||||||
|
// Remove the Chrome visibility
|
||||||
|
dragImage.style.cssText = '';
|
||||||
|
} else {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
}, false);
|
||||||
|
element.addEventListener("dragend", () => dragData = null);
|
||||||
|
element.setAttribute('draggable', true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Drop selected messages on folder
|
// Drop selected messages on folder
|
||||||
const dragTimer = {
|
|
||||||
id: 0,
|
|
||||||
stop: () => clearTimeout(this.id),
|
|
||||||
start: fn => this.id = setTimeout(fn, 500)
|
|
||||||
};
|
|
||||||
ko.bindingHandlers.dropmessages = {
|
ko.bindingHandlers.dropmessages = {
|
||||||
init: (element, fValueAccessor) => {
|
init: (element, fValueAccessor) => {
|
||||||
if (!rl.settings.app('mobile')) {
|
if (!rl.settings.app('mobile')) {
|
||||||
const folder = fValueAccessor(),
|
const folder = fValueAccessor(),
|
||||||
// folder = ko.dataFor(element),
|
// folder = ko.dataFor(element),
|
||||||
|
fnStop = e => {
|
||||||
|
e.preventDefault();
|
||||||
|
element.classList.remove('droppableHover');
|
||||||
|
dragTimer.stop();
|
||||||
|
},
|
||||||
fnHover = e => {
|
fnHover = e => {
|
||||||
if (validTransfer(e.dataTransfer)) {
|
if ('messages' === getDragAction(e)) {
|
||||||
dragTimer.stop();
|
fnStop(e);
|
||||||
e.preventDefault();
|
|
||||||
element.classList.add('droppableHover');
|
element.classList.add('droppableHover');
|
||||||
if (folder && folder.collapsed()) {
|
if (folder && folder.collapsed()) {
|
||||||
dragTimer.start(() => {
|
dragTimer.start(() => {
|
||||||
|
@ -116,18 +160,13 @@ ko.bindingHandlers.dropmessages = {
|
||||||
};
|
};
|
||||||
element.addEventListener("dragenter", fnHover);
|
element.addEventListener("dragenter", fnHover);
|
||||||
element.addEventListener("dragover", fnHover);
|
element.addEventListener("dragover", fnHover);
|
||||||
element.addEventListener("dragleave", e => {
|
element.addEventListener("dragleave", fnStop);
|
||||||
e.preventDefault();
|
|
||||||
element.classList.remove('droppableHover');
|
|
||||||
dragTimer.stop();
|
|
||||||
});
|
|
||||||
element.addEventListener("drop", e => {
|
element.addEventListener("drop", e => {
|
||||||
const data = JSON.parse(validTransfer(e.dataTransfer));
|
fnStop(e);
|
||||||
if (data) {
|
if ('messages' === getDragAction(e) && ['move','copy'].includes(e.dataTransfer.effectAllowed)) {
|
||||||
data.copy = data.copy && event.ctrlKey;
|
let data = dragData.data;
|
||||||
e.preventDefault();
|
|
||||||
if (folder && data && data.folder && Array.isArray(data.uids)) {
|
if (folder && data && data.folder && Array.isArray(data.uids)) {
|
||||||
rl.app.moveMessagesToFolder(data.folder, data.uids, folder.fullNameRaw, data.copy);
|
rl.app.moveMessagesToFolder(data.folder, data.uids, folder.fullNameRaw, data.copy && e.ctrlKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -135,41 +174,40 @@ ko.bindingHandlers.dropmessages = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let sortableElement = null,
|
|
||||||
isSortableData = data => 'move' === data.dropEffect && 'sortable' === data.getData(rlContentType);
|
|
||||||
ko.bindingHandlers.sortableItem = {
|
ko.bindingHandlers.sortableItem = {
|
||||||
init: (element, fValueAccessor) => {
|
init: (element, fValueAccessor) => {
|
||||||
let options = ko.utils.unwrapObservable(fValueAccessor()) || {},
|
let options = ko.utils.unwrapObservable(fValueAccessor()) || {},
|
||||||
parent = element.parentNode,
|
parent = element.parentNode,
|
||||||
fnHover = e => {
|
fnHover = e => {
|
||||||
if (isSortableData(e.dataTransfer)) {
|
if ('sortable' === getDragAction(e)) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
let node = (e.target.closest ? e.target : e.target.parentNode).closest('[draggable]');
|
let node = (e.target.closest ? e.target : e.target.parentNode).closest('[draggable]');
|
||||||
if (node && node !== sortableElement && parent.contains(node)) {
|
if (node && node !== dragData.data && parent.contains(node)) {
|
||||||
let rect = node.getBoundingClientRect();
|
let rect = node.getBoundingClientRect();
|
||||||
if (rect.top + (rect.height / 2) <= e.clientY) {
|
if (rect.top + (rect.height / 2) <= e.clientY) {
|
||||||
if (node.nextElementSibling !== sortableElement) {
|
if (node.nextElementSibling !== dragData.data) {
|
||||||
node.after(sortableElement);
|
node.after(dragData.data);
|
||||||
}
|
}
|
||||||
} else if (node.previousElementSibling !== sortableElement) {
|
} else if (node.previousElementSibling !== dragData.data) {
|
||||||
node.before(sortableElement);
|
node.before(dragData.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
element.addEventListener("dragstart", e => {
|
element.addEventListener("dragstart", e => {
|
||||||
sortableElement = element;
|
dragData = {
|
||||||
e.dataTransfer.setData(rlContentType, 'sortable');
|
action: 'sortable',
|
||||||
e.dataTransfer.setDragImage(element, 0, 0);
|
element: element
|
||||||
e.dataTransfer.effectAllowed = 'move';
|
};
|
||||||
|
setDragAction(e, 'sortable', 'move', element, element);
|
||||||
element.style.opacity = 0.25;
|
element.style.opacity = 0.25;
|
||||||
});
|
});
|
||||||
element.addEventListener("dragend", e => {
|
element.addEventListener("dragend", e => {
|
||||||
element.style.opacity = null;
|
element.style.opacity = null;
|
||||||
if (isSortableData(e.dataTransfer)) {
|
if ('sortable' === getDragAction(e)) {
|
||||||
let row = parent.rows[options.list.indexOf(ko.dataFor(element))];
|
let row = parent.rows[options.list.indexOf(ko.dataFor(element))];
|
||||||
if (row != sortableElement) {
|
if (row != dragData.data) {
|
||||||
row.before(sortableElement);
|
row.before(dragData.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -178,17 +216,18 @@ ko.bindingHandlers.sortableItem = {
|
||||||
parent.addEventListener("dragenter", fnHover);
|
parent.addEventListener("dragenter", fnHover);
|
||||||
parent.addEventListener("dragover", fnHover);
|
parent.addEventListener("dragover", fnHover);
|
||||||
parent.addEventListener("drop", e => {
|
parent.addEventListener("drop", e => {
|
||||||
if (isSortableData(e.dataTransfer)) {
|
if ('sortable' === getDragAction(e)) {
|
||||||
e.dataTransfer.clearData();
|
dragData.data.style.opacity = null;
|
||||||
let data = ko.dataFor(sortableElement),
|
e.preventDefault();
|
||||||
|
let data = ko.dataFor(dragData.data),
|
||||||
from = options.list.indexOf(data),
|
from = options.list.indexOf(data),
|
||||||
to = [...parent.children].indexOf(sortableElement);
|
to = [...parent.children].indexOf(dragData.data);
|
||||||
if (from != to) {
|
if (from != to) {
|
||||||
let arr = options.list();
|
let arr = options.list();
|
||||||
arr.splice(to, 0, ...arr.splice(from, 1));
|
arr.splice(to, 0, ...arr.splice(from, 1));
|
||||||
options.list(arr);
|
options.list(arr);
|
||||||
}
|
}
|
||||||
e.preventDefault();
|
dragData = null;
|
||||||
options.afterMove && options.afterMove();
|
options.afterMove && options.afterMove();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -45,8 +45,6 @@ const
|
||||||
canBeMovedHelper = (self) => self.canBeMoved(),
|
canBeMovedHelper = (self) => self.canBeMoved(),
|
||||||
ifvisible = window.ifvisible;
|
ifvisible = window.ifvisible;
|
||||||
|
|
||||||
let dragImage;
|
|
||||||
|
|
||||||
@view({
|
@view({
|
||||||
name: 'View/User/MailBox/MessageList',
|
name: 'View/User/MailBox/MessageList',
|
||||||
type: ViewType.Right,
|
type: ViewType.Right,
|
||||||
|
@ -479,39 +477,16 @@ class MessageListMailBoxUserView extends AbstractViewNext {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dragStart(event) {
|
getDragData(event) {
|
||||||
const item = ko.dataFor(document.elementFromPoint(event.clientX, event.clientY));
|
const item = ko.dataFor(document.elementFromPoint(event.clientX, event.clientY));
|
||||||
item && item.checked(true);
|
item && item.checked && item.checked(true);
|
||||||
|
|
||||||
dragImage || (dragImage = document.getElementById('messagesDragImage'));
|
|
||||||
|
|
||||||
const uids = MessageStore.messageListCheckedOrSelectedUidsWithSubMails();
|
const uids = MessageStore.messageListCheckedOrSelectedUidsWithSubMails();
|
||||||
item && !uids.includes(item.uid) && uids.push(item.uid);
|
item && !uids.includes(item.uid) && uids.push(item.uid);
|
||||||
if (dragImage && uids.length) {
|
return uids.length ? {
|
||||||
dragImage.querySelector('.text').textContent = uids.length;
|
copy: event.ctrlKey,
|
||||||
let img = dragImage.querySelector('.icon-white');
|
folder: FolderStore.currentFolderFullNameRaw(),
|
||||||
img.classList.toggle('icon-copy', event.ctrlKey);
|
uids: uids
|
||||||
img.classList.toggle('icon-mail', !event.ctrlKey);
|
} : null;
|
||||||
|
|
||||||
// Else Chrome doesn't show it
|
|
||||||
dragImage.style.left = event.clientX + 'px';
|
|
||||||
dragImage.style.top = event.clientY + 'px';
|
|
||||||
dragImage.style.right = 'auto';
|
|
||||||
|
|
||||||
let action = event.ctrlKey ? 'copy' : 'move';
|
|
||||||
event.dataTransfer.setData('application/x-rainloop-messages', JSON.stringify({
|
|
||||||
copy: event.ctrlKey,
|
|
||||||
folder: FolderStore.currentFolderFullNameRaw(),
|
|
||||||
uids: uids
|
|
||||||
}));
|
|
||||||
event.dataTransfer.setDragImage(dragImage, 0, 0);
|
|
||||||
event.dataTransfer.effectAllowed = action;
|
|
||||||
|
|
||||||
// Remove the Chrome visibility
|
|
||||||
dragImage.style.cssText = '';
|
|
||||||
} else {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -198,7 +198,7 @@
|
||||||
<div class="listEmptySearchList" data-bind="visible: !dragOver() && 0 === messageList().length && !messageListCompleteLoadingThrottle() && '' === messageListError() && '' !== messageListSearch()">
|
<div class="listEmptySearchList" data-bind="visible: !dragOver() && 0 === messageList().length && !messageListCompleteLoadingThrottle() && '' === messageListError() && '' !== messageListSearch()">
|
||||||
<span class="i18n" data-i18n="MESSAGE_LIST/EMPTY_SEARCH_LIST"></span>
|
<span class="i18n" data-i18n="MESSAGE_LIST/EMPTY_SEARCH_LIST"></span>
|
||||||
</div>
|
</div>
|
||||||
<div draggable="true" data-bind="dragmessages: dragStart">
|
<div data-bind="dragmessages: getDragData">
|
||||||
<div class="messageListPlace" data-bind="template: { name: messageListItemTemplate(), foreach: messageList }"></div>
|
<div class="messageListPlace" data-bind="template: { name: messageListItemTemplate(), foreach: messageList }"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="messagesDragImage"><span class="text"></span> <i class="icon-mail icon-white"></i></div>
|
<div id="messagesDragImage"><span class="text"></span> <i class="icon-mail icon-white"></i></div>
|
||||||
|
|
Loading…
Reference in a new issue