mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-07 00:17:03 +03:00
parent
bc5194a494
commit
456ade5845
5 changed files with 73 additions and 56 deletions
|
|
@ -318,6 +318,7 @@ html.rl-no-preview-pane {
|
||||||
border-bottom: 1px solid var(--border-color, #bbb);
|
border-bottom: 1px solid var(--border-color, #bbb);
|
||||||
}
|
}
|
||||||
.attachmentsControls > * {
|
.attachmentsControls > * {
|
||||||
|
display: inline-block;
|
||||||
margin-right: 0.5em;
|
margin-right: 0.5em;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ class ContentSecurityPolicy extends \OCP\AppFramework\Http\ContentSecurityPolicy
|
||||||
$CSP->script
|
$CSP->script
|
||||||
));
|
));
|
||||||
$this->allowedScriptDomains = \array_diff($this->allowedScriptDomains, ["'unsafe-inline'", "'unsafe-eval'"]);
|
$this->allowedScriptDomains = \array_diff($this->allowedScriptDomains, ["'unsafe-inline'", "'unsafe-eval'"]);
|
||||||
|
|
||||||
|
// Nextcloud only sets 'strict-dynamic' when browserSupportsCspV3() ?
|
||||||
\method_exists($this, 'useStrictDynamic')
|
\method_exists($this, 'useStrictDynamic')
|
||||||
? $this->useStrictDynamic(true) // NC24+
|
? $this->useStrictDynamic(true) // NC24+
|
||||||
: $this->addAllowedScriptDomain("'strict-dynamic'");
|
: $this->addAllowedScriptDomain("'strict-dynamic'");
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,54 @@
|
||||||
(rl => {
|
(rl => {
|
||||||
// if (rl.settings.get('Nextcloud'))
|
// if (rl.settings.get('Nextcloud'))
|
||||||
|
const templateId = 'MailMessageView';
|
||||||
|
|
||||||
addEventListener('rl-view-model.create', e => {
|
addEventListener('rl-view-model.create', e => {
|
||||||
if ('MailMessageView' === e.detail.viewModelTemplateID) {
|
if (templateId === e.detail.viewModelTemplateID) {
|
||||||
|
|
||||||
|
const
|
||||||
|
template = document.getElementById(templateId),
|
||||||
|
cfg = rl.settings.get('Nextcloud'),
|
||||||
|
attachmentsControls = template.content.querySelector('.attachmentsControls'),
|
||||||
|
msgMenu = template.content.querySelector('#more-view-dropdown-id + menu');
|
||||||
|
|
||||||
|
if (attachmentsControls) {
|
||||||
|
attachmentsControls.append(Element.fromHTML(`<span>
|
||||||
|
<i class="fontastic iconcolor-red" data-bind="visible: saveNextcloudError">✖</i>
|
||||||
|
<i class="fontastic" data-bind="visible: !saveNextcloudError(),
|
||||||
|
css: {'icon-spinner': saveNextcloudLoading()}">💾</i>
|
||||||
|
<span class="g-ui-link" data-bind="click: saveNextcloud" data-i18n="NEXTCLOUD/SAVE_ATTACHMENTS"></span>
|
||||||
|
</span>`));
|
||||||
|
|
||||||
|
// https://github.com/nextcloud/calendar/issues/4684
|
||||||
|
if (cfg.CalDAV) {
|
||||||
|
attachmentsControls.append(Element.fromHTML(`<span data-bind="visible: nextcloudICS" data-icon="📅">
|
||||||
|
<span class="g-ui-link" data-bind="click: nextcloudSaveICS" data-i18n="NEXTCLOUD/SAVE_ICS"></span>
|
||||||
|
</span>`));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// https://github.com/the-djmaze/snappymail/issues/592
|
||||||
|
if (cfg.CalDAV) {
|
||||||
|
const attachmentsPlace = template.content.querySelector('.attachmentsPlace');
|
||||||
|
attachmentsPlace.after(Element.fromHTML(`
|
||||||
|
<table data-bind="if: nextcloudICS, visible: nextcloudICS"><tbody style="white-space:pre">
|
||||||
|
<tr><td>Summary</td><td data-icon="📅" data-bind="text: nextcloudICS().SUMMARY"></td></tr>
|
||||||
|
<tr><td>Organizer</td><td data-bind="text: nextcloudICS().ORGANIZER"></td></tr>
|
||||||
|
<tr><td>Start</td><td data-bind="text: nextcloudICS().DTSTART"></td></tr>
|
||||||
|
<tr><td>End</td><td data-bind="text: nextcloudICS().DTEND"></td></tr>
|
||||||
|
<tr><td>Transparency</td><td data-bind="text: nextcloudICS().TRANSP"></td></tr>
|
||||||
|
<tr data-bind="foreach: nextcloudICS().ATTENDEE">
|
||||||
|
<td></td><td data-bind="text: $data.replace(/;/g,';\\n')"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody></table>`));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if (msgMenu) {
|
||||||
|
msgMenu.append(Element.fromHTML(`<li role="presentation">
|
||||||
|
<a href="#" tabindex="-1" data-icon="📥" data-bind="click: nextcloudSaveMsg" data-i18n="NEXTCLOUD/SAVE_EML"></a>
|
||||||
|
</li>`));
|
||||||
|
}
|
||||||
|
|
||||||
let view = e.detail;
|
let view = e.detail;
|
||||||
view.saveNextcloudError = ko.observable(false).extend({ falseTimeout: 7000 });
|
view.saveNextcloudError = ko.observable(false).extend({ falseTimeout: 7000 });
|
||||||
view.saveNextcloudLoading = ko.observable(false);
|
view.saveNextcloudLoading = ko.observable(false);
|
||||||
|
|
@ -65,7 +111,7 @@
|
||||||
view.nextcloudSaveICS = () => {
|
view.nextcloudSaveICS = () => {
|
||||||
let VEVENT = view.nextcloudICS();
|
let VEVENT = view.nextcloudICS();
|
||||||
VEVENT && rl.nextcloud.selectCalendar()
|
VEVENT && rl.nextcloud.selectCalendar()
|
||||||
.then(href => href && rl.nextcloud.calendarPut(href, VEVENT.rawText));
|
.then(href => href && rl.nextcloud.calendarPut(href, VEVENT));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -73,7 +119,7 @@
|
||||||
*/
|
*/
|
||||||
view.message.subscribe(msg => {
|
view.message.subscribe(msg => {
|
||||||
view.nextcloudICS(null);
|
view.nextcloudICS(null);
|
||||||
if (msg) {
|
if (msg && cfg.CalDAV) {
|
||||||
let ics = msg.attachments.find(attachment => 'text/calendar' == attachment.mimeType);
|
let ics = msg.attachments.find(attachment => 'text/calendar' == attachment.mimeType);
|
||||||
if (ics && ics.download) {
|
if (ics && ics.download) {
|
||||||
// fetch it and parse the VEVENT
|
// fetch it and parse the VEVENT
|
||||||
|
|
@ -119,7 +165,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// METHOD:REPLY || METHOD:REQUEST
|
// METHOD:REPLY || METHOD:REQUEST
|
||||||
console.dir({VEVENT:VEVENT});
|
// console.dir({VEVENT:VEVENT});
|
||||||
if (VEVENT) {
|
if (VEVENT) {
|
||||||
VEVENT.rawText = text;
|
VEVENT.rawText = text;
|
||||||
VEVENT.isCancelled = () => VEVENT.STATUS?.includes('CANCELLED');
|
VEVENT.isCancelled = () => VEVENT.STATUS?.includes('CANCELLED');
|
||||||
|
|
@ -138,47 +184,4 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let template = document.getElementById('MailMessageView');
|
|
||||||
let cfg = rl.settings.get('Nextcloud');
|
|
||||||
|
|
||||||
const attachmentsControls = template.content.querySelector('.attachmentsControls');
|
|
||||||
if (attachmentsControls) {
|
|
||||||
attachmentsControls.append(Element.fromHTML(`<span>
|
|
||||||
<i class="fontastic iconcolor-red" data-bind="visible: saveNextcloudError">✖</i>
|
|
||||||
<i class="fontastic" data-bind="visible: !saveNextcloudError(),
|
|
||||||
css: {'icon-spinner': saveNextcloudLoading()}">💾</i>
|
|
||||||
<span class="g-ui-link" data-bind="click: saveNextcloud" data-i18n="NEXTCLOUD/SAVE_ATTACHMENTS"></span>
|
|
||||||
</span>`));
|
|
||||||
|
|
||||||
// https://github.com/nextcloud/calendar/issues/4684
|
|
||||||
if (cfg.CalDAV) {
|
|
||||||
attachmentsControls.append(Element.fromHTML(`<span data-bind="visible: nextcloudICS" data-icon="📅">
|
|
||||||
<span class="g-ui-link" data-bind="click: nextcloudSaveICS" data-i18n="NEXTCLOUD/SAVE_ICS"></span>
|
|
||||||
</span>`));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
// https://github.com/the-djmaze/snappymail/issues/592
|
|
||||||
if (cfg.CalDAV) {
|
|
||||||
const attachmentsPlace = template.content.querySelector('.attachmentsPlace');
|
|
||||||
attachmentsPlace.after(Element.fromHTML(`
|
|
||||||
<table data-bind="if: nextcloudICS, visible: nextcloudICS"><tbody style="white-space:pre">
|
|
||||||
<tr><td>Summary</td><td data-icon="📅" data-bind="text: nextcloudICS().SUMMARY"></td></tr>
|
|
||||||
<tr><td>Organizer</td><td data-bind="text: nextcloudICS().ORGANIZER"></td></tr>
|
|
||||||
<tr><td>Start</td><td data-bind="text: nextcloudICS().DTSTART"></td></tr>
|
|
||||||
<tr><td>End</td><td data-bind="text: nextcloudICS().DTEND"></td></tr>
|
|
||||||
<tr><td>Transparency</td><td data-bind="text: nextcloudICS().TRANSP"></td></tr>
|
|
||||||
<tr data-bind="foreach: nextcloudICS().ATTENDEE">
|
|
||||||
<td></td><td data-bind="text: $data.replace(/;/g,';\\n')"></td>
|
|
||||||
</tr>
|
|
||||||
</tbody></table>`));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
const msgMenu = template.content.querySelector('#more-view-dropdown-id + menu');
|
|
||||||
if (msgMenu) {
|
|
||||||
msgMenu.append(Element.fromHTML(`<li role="presentation">
|
|
||||||
<a href="#" tabindex="-1" data-icon="📥" data-bind="click: nextcloudSaveMsg" data-i18n="NEXTCLOUD/SAVE_EML"></a>
|
|
||||||
</li>`));
|
|
||||||
}
|
|
||||||
|
|
||||||
})(window.rl);
|
})(window.rl);
|
||||||
|
|
|
||||||
|
|
@ -242,6 +242,7 @@ class NextcloudFilesPopupView extends rl.pluginPopupView {
|
||||||
)
|
)
|
||||||
.then(response => (response.status < 400) ? response.json() : Promise.reject(new Error({ response })))
|
.then(response => (response.status < 400) ? response.json() : Promise.reject(new Error({ response })))
|
||||||
.then(json => {
|
.then(json => {
|
||||||
|
// PUT /ocs/v2.php/apps/files_sharing/api/v1/shares/2 {"password":"ABC09"}
|
||||||
this.select = [{url:json.ocs.data.url}];
|
this.select = [{url:json.ocs.data.url}];
|
||||||
this.close();
|
this.close();
|
||||||
});
|
});
|
||||||
|
|
@ -365,20 +366,29 @@ rl.nextcloud = {
|
||||||
}),
|
}),
|
||||||
|
|
||||||
calendarPut: (path, event) => {
|
calendarPut: (path, event) => {
|
||||||
// Validation error in iCalendar: A calendar object on a CalDAV server MUST NOT have a METHOD property.
|
davFetch('calendars', path + '/' + event.UID + '.ics', {
|
||||||
event = event.replace(/METHOD:.+\r?\n/i, '');
|
|
||||||
|
|
||||||
let m = event.match(/UID:(.+)/);
|
|
||||||
davFetch('calendars', path + '/' + m[1] + '.ics', {
|
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'text/calendar'
|
'Content-Type': 'text/calendar'
|
||||||
},
|
},
|
||||||
body: event
|
// Validation error in iCalendar: A calendar object on a CalDAV server MUST NOT have a METHOD property.
|
||||||
|
body: event.rawText
|
||||||
|
.replace('METHOD:', 'X-METHOD:')
|
||||||
|
// https://github.com/nextcloud/calendar/issues/4684
|
||||||
|
.replace('ATTENDEE:', 'X-ATTENDEE:')
|
||||||
|
.replace('ORGANIZER:', 'X-ORGANIZER:')
|
||||||
|
.replace(/RSVP=TRUE/g, 'RSVP=FALSE')
|
||||||
|
.replace(/\r?\n/g, '\r\n')
|
||||||
})
|
})
|
||||||
.then(response => (response.status < 400) ? response.text() : Promise.reject(new Error({ response })))
|
.then(response => {
|
||||||
.then(text => {
|
if (201 == response.status) {
|
||||||
console.dir({event_response:text});
|
// Created
|
||||||
|
} else if (204 == response.status) {
|
||||||
|
// Not modified
|
||||||
|
} else {
|
||||||
|
// response.text().then(text => console.error({status:response.status, body:text}));
|
||||||
|
Promise.reject(new Error({ response }));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
}
|
}
|
||||||
#V-PopupsNextcloudFiles li {
|
#V-PopupsNextcloudFiles li {
|
||||||
clear: right;
|
clear: right;
|
||||||
|
line-height: 2.5em;
|
||||||
}
|
}
|
||||||
#V-PopupsNextcloudFiles li button {
|
#V-PopupsNextcloudFiles li button {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue