mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
CompactComposer support older browsers and a different idea to modify the dialog for #1498
This commit is contained in:
parent
0d34d0b25b
commit
70b1a93108
3 changed files with 49 additions and 51 deletions
|
|
@ -6,15 +6,15 @@ class CompactComposerPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
NAME = 'Compact Composer',
|
NAME = 'Compact Composer',
|
||||||
AUTHOR = 'Sergey Mosin',
|
AUTHOR = 'Sergey Mosin',
|
||||||
URL = 'https://github.com/the-djmaze/snappymail/pull/1466',
|
URL = 'https://github.com/the-djmaze/snappymail/pull/1466',
|
||||||
VERSION = '1.0.2',
|
VERSION = '1.0.3-beta',
|
||||||
RELEASE = '2024-02-23',
|
RELEASE = '2024-03-19',
|
||||||
REQUIRED = '2.34.0',
|
REQUIRED = '2.34.0',
|
||||||
LICENSE = 'AGPL v3',
|
LICENSE = 'AGPL v3',
|
||||||
DESCRIPTION = 'WYSIWYG editor with a compact toolbar';
|
DESCRIPTION = 'WYSIWYG editor with a compact toolbar';
|
||||||
|
|
||||||
public function Init(): void
|
public function Init(): void
|
||||||
{
|
{
|
||||||
$this->addTemplate('templates/PopupsCompactCompose.html');
|
// $this->addTemplate('templates/PopupsCompactCompose.html');
|
||||||
$this->addCss('css/composer.css');
|
$this->addCss('css/composer.css');
|
||||||
$this->addJs('js/squire-raw.js');
|
$this->addJs('js/squire-raw.js');
|
||||||
$this->addJs('js/parsel.js');
|
$this->addJs('js/parsel.js');
|
||||||
|
|
|
||||||
|
|
@ -14,34 +14,26 @@
|
||||||
|
|
||||||
const doc = win.document;
|
const doc = win.document;
|
||||||
|
|
||||||
// If a user (or admin) selected the CompactComposer we need to
|
addEventListener('rl-view-model', e => {
|
||||||
// replace PopupsCompose template with PopupsCompactCompose template.
|
const vm = e.detail;
|
||||||
// --
|
if ('PopupsCompose' === vm.viewModelTemplateID && rl.settings.get('editorWysiwyg') === 'CompactComposer') {
|
||||||
// This might break some plugins if they query/change PopupsCompose template
|
vm.querySelector('.tabs label[for="tab-body"]').dataset.bind = "visible: canMailvelope";
|
||||||
// before this code is called. They should instead listen for
|
// Now move the attachments tab to the bottom of the screen
|
||||||
// 'rl-view-model.create' to work properly.
|
const
|
||||||
if (rl.settings.get('editorWysiwyg') === 'CompactComposer') {
|
input = vm.querySelector('.tabs input[value="attachments"]'),
|
||||||
const compactTemplate = doc.getElementById('PopupsCompactCompose');
|
label = vm.querySelector('.tabs label[for="tab-attachments"]'),
|
||||||
if (!compactTemplate) {
|
area = vm.querySelector('.tabs .attachmentAreaParent');
|
||||||
console.error('CompactComposer: PopupsCompactCompose template not found');
|
input.remove();
|
||||||
return;
|
label.remove();
|
||||||
|
area.remove();
|
||||||
|
area.classList.add('compact');
|
||||||
|
area.querySelector('.b-attachment-place').dataset.bind = "visible: addAttachmentEnabled(), css: {dragAndDropOver: dragAndDropVisible}";
|
||||||
|
vm.viewModelDom.append(area);
|
||||||
|
// There is a better way to do this probably,
|
||||||
|
// but we need this for drag and drop to work
|
||||||
|
e.detail.attachmentsArea = e.detail.bodyArea;
|
||||||
}
|
}
|
||||||
const originalTemplate = doc.getElementById('PopupsCompose');
|
});
|
||||||
if (originalTemplate) {
|
|
||||||
originalTemplate.id = 'PopupsCompose_replaced';
|
|
||||||
} else {
|
|
||||||
console.warn('CompactComposer: PopupsCompose template not found');
|
|
||||||
}
|
|
||||||
compactTemplate.id = 'PopupsCompose';
|
|
||||||
|
|
||||||
addEventListener('rl-view-model.create', e => {
|
|
||||||
if (e.detail.viewModelTemplateID === 'PopupsCompose') {
|
|
||||||
// There is a better way to do this probably,
|
|
||||||
// but we need this for drag and drop to work
|
|
||||||
e.detail.attachmentsArea = e.detail.bodyArea;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const
|
const
|
||||||
removeElements = 'HEAD,LINK,META,NOSCRIPT,SCRIPT,TEMPLATE,TITLE',
|
removeElements = 'HEAD,LINK,META,NOSCRIPT,SCRIPT,TEMPLATE,TITLE',
|
||||||
|
|
@ -155,7 +147,7 @@
|
||||||
this.toolbar = toolbar;
|
this.toolbar = toolbar;
|
||||||
|
|
||||||
toolbar.className = 'squire-toolbar btn-toolbar';
|
toolbar.className = 'squire-toolbar btn-toolbar';
|
||||||
const actions = this.#makeActions(squire, toolbar);
|
const actions = this.makeActions(squire, toolbar);
|
||||||
|
|
||||||
this.squire.addEventListener('willPaste', pasteSanitizer);
|
this.squire.addEventListener('willPaste', pasteSanitizer);
|
||||||
this.squire.addEventListener('pasteImage', (e) => {
|
this.squire.addEventListener('pasteImage', (e) => {
|
||||||
|
|
@ -300,10 +292,11 @@
|
||||||
* @param {Squire} squire
|
* @param {Squire} squire
|
||||||
* @param {HTMLDivElement} toolbar
|
* @param {HTMLDivElement} toolbar
|
||||||
* @returns {Array}
|
* @returns {Array}
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
#makeActions(squire, toolbar) {
|
makeActions(squire, toolbar) {
|
||||||
|
|
||||||
const clr = this.#makeClr();
|
const clr = this.makeClr();
|
||||||
const doClr = name => input => {
|
const doClr = name => input => {
|
||||||
// https://github.com/the-djmaze/snappymail/issues/826
|
// https://github.com/the-djmaze/snappymail/issues/826
|
||||||
clr.style.left = (input.offsetLeft + input.parentNode.offsetLeft) + 'px';
|
clr.style.left = (input.offsetLeft + input.parentNode.offsetLeft) + 'px';
|
||||||
|
|
@ -640,11 +633,14 @@
|
||||||
actions: actions
|
actions: actions
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
this.indicators = this.#addActionsToParent(actions, toolbar);
|
this.indicators = this.addActionsToParent(actions, toolbar);
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
#makeClr() {
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
makeClr() {
|
||||||
/**@type {HTMLInputElement} clr*/
|
/**@type {HTMLInputElement} clr*/
|
||||||
const clr = createElement('input');
|
const clr = createElement('input');
|
||||||
clr.type = 'color';
|
clr.type = 'color';
|
||||||
|
|
@ -675,8 +671,9 @@
|
||||||
/**
|
/**
|
||||||
* @param {Array} items
|
* @param {Array} items
|
||||||
* @param {HTMLElement} parent
|
* @param {HTMLElement} parent
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
#addActionsToParent(items, parent) {
|
addActionsToParent(items, parent) {
|
||||||
const indicators = [];
|
const indicators = [];
|
||||||
items.forEach(item => {
|
items.forEach(item => {
|
||||||
let element, event;
|
let element, event;
|
||||||
|
|
@ -688,7 +685,7 @@
|
||||||
group.className += ' squire-html-mode-item';
|
group.className += ' squire-html-mode-item';
|
||||||
}
|
}
|
||||||
if (item.items) {
|
if (item.items) {
|
||||||
indicators.push(...this.#addActionsToParent(item.items, group));
|
indicators.push(...this.addActionsToParent(item.items, group));
|
||||||
}
|
}
|
||||||
parent.append(group);
|
parent.append(group);
|
||||||
return indicators;
|
return indicators;
|
||||||
|
|
@ -720,7 +717,7 @@
|
||||||
menu.setAttribute('role', 'menu');
|
menu.setAttribute('role', 'menu');
|
||||||
|
|
||||||
if (item.items) {
|
if (item.items) {
|
||||||
indicators.push(...this.#addActionsToParent(item.items, menu));
|
indicators.push(...this.addActionsToParent(item.items, menu));
|
||||||
}
|
}
|
||||||
menuWrap.appendChild(menu);
|
menuWrap.appendChild(menu);
|
||||||
parent.append(menuWrap);
|
parent.append(menuWrap);
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<label data-bind="css: {'error-to': emptyToError}, tooltipErrorTip: emptyToErrorTooltip"
|
<label data-bind="css: {'error-to': emptyToError}, tooltipErrorTip: emptyToErrorTooltip"
|
||||||
data-i18n="GLOBAL/TO"></label>
|
data-i18n="GLOBAL/TO"></label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" data-bind="emailsTags: to, autoCompleteSource: emailsSource">
|
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" data-bind="emailsTags: to, autoCompleteSource: emailsSource">
|
||||||
|
|
@ -146,7 +146,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<button class="btn fontastic" id="composeUploadButton"
|
<button class="btn fontastic" id="composeUploadButton"
|
||||||
data-bind="visible: addAttachmentEnabled()" data-i18n="[title]COMPOSE/ATTACH_FILES">
|
data-bind="visible: addAttachmentEnabled()" data-i18n="[title]COMPOSE/ATTACH_FILES">
|
||||||
⁺📎
|
⁺📎
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -156,24 +156,25 @@
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<input type="radio" name="tabs" value="body" id="tab-body" data-bind="checked: viewArea">
|
<input type="radio" name="tabs" value="body" id="tab-body" data-bind="checked: viewArea">
|
||||||
<label for="tab-body"
|
<label for="tab-body"
|
||||||
role="tab"
|
role="tab"
|
||||||
aria-selected="true"
|
aria-selected="true"
|
||||||
aria-controls="panel1"
|
aria-controls="panel1"
|
||||||
data-bind="visible: canMailvelope"
|
data-bind="visible: canMailvelope"
|
||||||
tabindex="0">
|
tabindex="0">
|
||||||
<i class="icon-file-text"></i>
|
<i class="icon-file-text"></i>
|
||||||
<span data-i18n="GLOBAL/TEXT"></span>
|
<span data-i18n="GLOBAL/TEXT"></span>
|
||||||
</label>
|
</label>
|
||||||
<div class="tab-content" role="tabpanel" aria-hidden="false" style="grid-column-end:3">
|
<div class="tab-content" role="tabpanel" aria-hidden="false" style="grid-column-end:3">
|
||||||
<div class="textAreaParent" data-bind="initDom: editorArea, attr:{spellcheck:allowSpellcheck()?'true':'false'}"></div>
|
<div class="textAreaParent" data-bind="initDom: editorArea, attr:{spellcheck:allowSpellcheck()?'true':'false'}"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="radio" name="tabs" value="mailvelope" id="tab-mailvelope" data-bind="checked: viewArea">
|
<input type="radio" name="tabs" value="mailvelope" id="tab-mailvelope" data-bind="checked: viewArea">
|
||||||
<label for="tab-mailvelope"
|
<label for="tab-mailvelope"
|
||||||
role="tab"
|
role="tab"
|
||||||
aria-selected="false"
|
aria-selected="false"
|
||||||
aria-controls="panel3"
|
aria-controls="panel3"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
data-bind="visible: canMailvelope">
|
data-bind="visible: canMailvelope">
|
||||||
<i class="mailvelope-icon"></i>
|
<i class="mailvelope-icon"></i>
|
||||||
<span>Mailvelope</span>
|
<span>Mailvelope</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
@ -183,7 +184,7 @@
|
||||||
|
|
||||||
<div class="attachmentAreaParent compact">
|
<div class="attachmentAreaParent compact">
|
||||||
<div class="b-attachment-place" data-bind="visible: addAttachmentEnabled(), css: {dragAndDropOver: dragAndDropVisible}"
|
<div class="b-attachment-place" data-bind="visible: addAttachmentEnabled(), css: {dragAndDropOver: dragAndDropVisible}"
|
||||||
data-i18n="COMPOSE/ATTACH_DROP_FILES_DESC"></div>
|
data-i18n="COMPOSE/ATTACH_DROP_FILES_DESC"></div>
|
||||||
<ul class="attachmentList" data-bind="foreach: attachments">
|
<ul class="attachmentList" data-bind="foreach: attachments">
|
||||||
<li class="attachmentItem" data-bind="attr: { title: title }, css: { waiting: waiting, error: '' !== error() }">
|
<li class="attachmentItem" data-bind="attr: { title: title }, css: { waiting: waiting, error: '' !== error() }">
|
||||||
<div class="attachmentIcon">
|
<div class="attachmentIcon">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue