2016-08-17 06:01:20 +08:00
|
|
|
import ko from 'ko';
|
2022-10-31 05:19:52 +08:00
|
|
|
import { addObservablesTo, addComputablesTo, addSubscribablesTo } from 'External/ko';
|
2016-08-17 06:01:20 +08:00
|
|
|
|
2022-02-24 19:22:27 +08:00
|
|
|
import { Scope } from 'Common/Enums';
|
2021-01-25 05:58:06 +08:00
|
|
|
|
|
|
|
import {
|
2019-07-05 03:19:24 +08:00
|
|
|
ComposeType,
|
2022-03-14 22:42:05 +08:00
|
|
|
ClientSideKeyNameMessageHeaderFullInfo,
|
|
|
|
ClientSideKeyNameMessageAttachmentControls,
|
2019-07-05 03:19:24 +08:00
|
|
|
FolderType,
|
|
|
|
MessageSetAction
|
2021-01-25 05:58:06 +08:00
|
|
|
} from 'Common/EnumsUser';
|
2016-08-17 06:01:20 +08:00
|
|
|
|
2022-02-02 20:02:48 +08:00
|
|
|
import {
|
|
|
|
elementById,
|
|
|
|
keyScopeReal,
|
|
|
|
Settings,
|
2022-02-08 21:13:06 +08:00
|
|
|
SettingsCapa,
|
2022-03-04 21:43:58 +08:00
|
|
|
fireEvent,
|
2023-02-21 21:26:37 +08:00
|
|
|
stopEvent,
|
2022-03-09 22:08:22 +08:00
|
|
|
addShortcut,
|
2022-03-22 23:24:58 +08:00
|
|
|
registerShortcut
|
2022-02-02 20:02:48 +08:00
|
|
|
} from 'Common/Globals';
|
2016-08-17 06:01:20 +08:00
|
|
|
|
2022-03-02 16:26:30 +08:00
|
|
|
import { arrayLength } from 'Common/Utils';
|
2023-01-26 17:41:55 +08:00
|
|
|
import { download, downloadZip, mailToHelper, showMessageComposer, moveAction } from 'Common/UtilsUser';
|
2022-03-22 23:24:58 +08:00
|
|
|
import { isFullscreen, exitFullscreen, toggleFullscreen } from 'Common/Fullscreen';
|
2016-08-17 06:01:20 +08:00
|
|
|
|
2021-03-11 05:41:35 +08:00
|
|
|
import { SMAudio } from 'Common/Audio';
|
2016-08-17 06:01:20 +08:00
|
|
|
|
2019-07-05 03:19:24 +08:00
|
|
|
import { i18n } from 'Common/Translator';
|
2016-08-17 06:01:20 +08:00
|
|
|
|
2021-03-11 05:41:35 +08:00
|
|
|
import { AppUserStore } from 'Stores/User/App';
|
|
|
|
import { SettingsUserStore } from 'Stores/User/Settings';
|
|
|
|
import { AccountUserStore } from 'Stores/User/Account';
|
2022-10-06 16:42:21 +08:00
|
|
|
import { FolderUserStore, isAllowedKeyword } from 'Stores/User/Folder';
|
2021-03-11 05:41:35 +08:00
|
|
|
import { MessageUserStore } from 'Stores/User/Message';
|
2022-02-24 02:26:52 +08:00
|
|
|
import { MessagelistUserStore } from 'Stores/User/Messagelist';
|
2016-08-17 06:01:20 +08:00
|
|
|
|
|
|
|
import * as Local from 'Storage/Client';
|
|
|
|
|
2020-09-15 01:40:56 +08:00
|
|
|
import Remote from 'Remote/User/Fetch';
|
2016-08-17 06:01:20 +08:00
|
|
|
|
2022-03-04 00:34:45 +08:00
|
|
|
import { decorateKoCommands } from 'Knoin/Knoin';
|
2021-01-24 17:25:23 +08:00
|
|
|
import { AbstractViewRight } from 'Knoin/AbstractViews';
|
2016-08-17 06:01:20 +08:00
|
|
|
|
2022-01-17 22:58:23 +08:00
|
|
|
import { PgpUserStore } from 'Stores/User/Pgp';
|
|
|
|
|
2022-02-11 18:01:07 +08:00
|
|
|
import { MimeToMessage } from 'Mime/Utils';
|
2022-01-31 22:24:51 +08:00
|
|
|
|
2022-05-12 05:13:24 +08:00
|
|
|
import { MessageModel } from 'Model/Message';
|
|
|
|
|
2022-11-16 22:14:00 +08:00
|
|
|
import { showScreenPopup } from 'Knoin/Knoin';
|
|
|
|
import { OpenPgpImportPopupView } from 'View/Popup/OpenPgpImport';
|
|
|
|
import { GnuPGUserStore } from 'Stores/User/GnuPG';
|
|
|
|
import { OpenPGPUserStore } from 'Stores/User/OpenPGP';
|
|
|
|
|
2022-02-02 20:02:48 +08:00
|
|
|
const
|
|
|
|
oMessageScrollerDom = () => elementById('messageItem') || {},
|
|
|
|
|
2022-11-16 22:14:00 +08:00
|
|
|
currentMessage = MessageUserStore.message,
|
|
|
|
|
2022-12-12 18:12:48 +08:00
|
|
|
setAction = action => {
|
|
|
|
const message = currentMessage();
|
|
|
|
message && MessagelistUserStore.setAction(message.folder, action, [message]);
|
|
|
|
},
|
|
|
|
|
2022-11-16 22:14:00 +08:00
|
|
|
fetchRaw = url => rl.fetch(url).then(response => response.ok && response.text());
|
2022-01-31 22:24:51 +08:00
|
|
|
|
2021-09-23 15:41:02 +08:00
|
|
|
export class MailMessageView extends AbstractViewRight {
|
2016-08-17 06:01:20 +08:00
|
|
|
constructor() {
|
2022-03-08 19:28:16 +08:00
|
|
|
super();
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2021-03-13 00:08:58 +08:00
|
|
|
const
|
2022-03-04 00:34:45 +08:00
|
|
|
/**
|
|
|
|
* @param {Function} fExecute
|
2022-03-04 02:22:17 +08:00
|
|
|
* @param {Function} fCanExecute = true
|
2022-03-04 00:34:45 +08:00
|
|
|
* @returns {Function}
|
|
|
|
*/
|
|
|
|
createCommand = (fExecute, fCanExecute) => {
|
|
|
|
let fResult = () => {
|
2022-09-08 05:39:46 +08:00
|
|
|
fCanExecute() && fExecute.call(null);
|
2022-03-04 00:34:45 +08:00
|
|
|
return false;
|
|
|
|
};
|
2022-09-08 05:39:46 +08:00
|
|
|
fResult.canExecute = fCanExecute;
|
2022-03-04 00:34:45 +08:00
|
|
|
return fResult;
|
|
|
|
},
|
|
|
|
|
2021-03-13 00:08:58 +08:00
|
|
|
createCommandReplyHelper = type =>
|
2022-02-24 02:26:52 +08:00
|
|
|
createCommand(() => this.replyOrforward(type), this.canBeRepliedOrForwarded),
|
2021-03-13 00:08:58 +08:00
|
|
|
|
2022-09-28 00:59:07 +08:00
|
|
|
createCommandActionHelper = (folderType, bDelete) =>
|
2021-03-13 00:08:58 +08:00
|
|
|
createCommand(() => {
|
2022-01-27 00:08:10 +08:00
|
|
|
const message = currentMessage();
|
2021-09-17 20:07:52 +08:00
|
|
|
if (message) {
|
2022-09-09 23:04:52 +08:00
|
|
|
currentMessage(null);
|
2022-09-28 00:59:07 +08:00
|
|
|
rl.app.moveMessagesToFolderType(folderType, message.folder, [message.uid], bDelete);
|
2021-03-13 00:08:58 +08:00
|
|
|
}
|
|
|
|
}, this.messageVisibility);
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2022-08-31 23:31:08 +08:00
|
|
|
this.msgDefaultAction = SettingsUserStore.msgDefaultAction;
|
2022-11-15 20:13:52 +08:00
|
|
|
this.simpleAttachmentsList = SettingsUserStore.simpleAttachmentsList;
|
2022-08-31 23:31:08 +08:00
|
|
|
|
2022-10-31 05:19:52 +08:00
|
|
|
addObservablesTo(this, {
|
2022-04-25 15:40:38 +08:00
|
|
|
showAttachmentControls: !!Local.get(ClientSideKeyNameMessageAttachmentControls),
|
2020-10-26 19:54:03 +08:00
|
|
|
downloadAsZipLoading: false,
|
2022-03-14 22:42:05 +08:00
|
|
|
showFullInfo: '1' === Local.get(ClientSideKeyNameMessageHeaderFullInfo),
|
2022-02-02 20:02:48 +08:00
|
|
|
moreDropdownTrigger: false,
|
|
|
|
|
|
|
|
// viewer
|
|
|
|
viewFromShort: '',
|
2023-02-10 16:55:52 +08:00
|
|
|
dkimData: ['none', '', '']
|
2020-10-26 19:54:03 +08:00
|
|
|
});
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2017-03-02 02:38:18 +08:00
|
|
|
this.moveAction = moveAction;
|
|
|
|
|
2021-03-16 23:06:16 +08:00
|
|
|
const attachmentsActions = Settings.app('attachmentsActions');
|
2021-07-22 03:34:17 +08:00
|
|
|
this.attachmentsActions = ko.observableArray(arrayLength(attachmentsActions) ? attachmentsActions : []);
|
2016-05-01 09:07:10 +08:00
|
|
|
|
2022-09-09 16:02:40 +08:00
|
|
|
this.hasCheckedMessages = MessagelistUserStore.hasChecked;
|
2022-09-08 05:39:46 +08:00
|
|
|
this.archiveAllowed = MessagelistUserStore.archiveAllowed;
|
2022-09-08 18:16:37 +08:00
|
|
|
this.canMarkAsSpam = MessagelistUserStore.canMarkAsSpam;
|
|
|
|
this.isDraftFolder = MessagelistUserStore.isDraftFolder;
|
|
|
|
this.isSpamFolder = MessagelistUserStore.isSpamFolder;
|
2022-09-08 05:39:46 +08:00
|
|
|
|
2022-12-22 16:56:06 +08:00
|
|
|
this.message = currentMessage;
|
2022-02-24 02:26:52 +08:00
|
|
|
this.messageLoadingThrottle = MessageUserStore.loading;
|
|
|
|
this.messageError = MessageUserStore.error;
|
2015-04-25 06:15:11 +08:00
|
|
|
|
2022-03-22 18:47:17 +08:00
|
|
|
this.fullScreenMode = isFullscreen;
|
|
|
|
this.toggleFullScreen = toggleFullscreen;
|
2014-08-22 23:08:56 +08:00
|
|
|
|
2019-07-05 03:19:24 +08:00
|
|
|
this.downloadAsZipError = ko.observable(false).extend({ falseTimeout: 7000 });
|
2015-04-25 06:15:11 +08:00
|
|
|
|
2019-07-05 03:19:24 +08:00
|
|
|
this.messageDomFocused = ko.observable(false).extend({ rateLimit: 0 });
|
2013-11-16 06:21:12 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
// viewer
|
|
|
|
this.viewHash = '';
|
2014-08-20 23:03:12 +08:00
|
|
|
|
2022-10-31 05:19:52 +08:00
|
|
|
addComputablesTo(this, {
|
2022-04-25 15:40:38 +08:00
|
|
|
allowAttachmentControls: () => arrayLength(attachmentsActions) && SettingsCapa('AttachmentsActions'),
|
2020-10-26 21:44:34 +08:00
|
|
|
|
2022-06-01 03:17:09 +08:00
|
|
|
downloadAsZipAllowed: () => this.attachmentsActions.includes('zip')
|
2022-09-02 17:52:07 +08:00
|
|
|
&& (currentMessage()?.attachments || [])
|
2022-10-03 22:04:39 +08:00
|
|
|
.filter(item => item?.download /*&& !item?.isLinked()*/ && item?.checked())
|
2022-06-01 03:17:09 +08:00
|
|
|
.length,
|
2020-10-26 21:44:34 +08:00
|
|
|
|
2022-10-05 23:25:30 +08:00
|
|
|
tagsAllowed: () => FolderUserStore.currentFolder()?.tagsAllowed(),
|
2022-06-03 20:46:05 +08:00
|
|
|
|
2022-02-24 02:26:52 +08:00
|
|
|
messageVisibility: () => !MessageUserStore.loading() && !!currentMessage(),
|
2020-10-26 21:44:34 +08:00
|
|
|
|
2022-12-22 16:56:06 +08:00
|
|
|
tagsToHTML: () => currentMessage()?.flags().map(value =>
|
|
|
|
isAllowedKeyword(value)
|
|
|
|
? '<span class="focused msgflag-'+value+'">' + i18n('MESSAGE_TAGS/'+value,0,value) + '</span>'
|
|
|
|
: ''
|
|
|
|
).join(' '),
|
|
|
|
|
|
|
|
askReadReceipt: () =>
|
|
|
|
(MessagelistUserStore.isDraftFolder() || MessagelistUserStore.isSentFolder())
|
|
|
|
&& currentMessage()?.readReceipt()
|
|
|
|
&& currentMessage()?.flags().includes('$mdnsent'),
|
|
|
|
|
|
|
|
listAttachments: () => currentMessage()?.attachments()
|
|
|
|
.filter(item => SettingsUserStore.listInlineAttachments() || !item.isLinked()),
|
2023-02-20 17:49:22 +08:00
|
|
|
hasAttachments: () => this.listAttachments()?.length,
|
2022-12-22 16:56:06 +08:00
|
|
|
|
2022-09-08 05:39:46 +08:00
|
|
|
canBeRepliedOrForwarded: () => !MessagelistUserStore.isDraftFolder() && this.messageVisibility(),
|
2020-10-26 21:44:34 +08:00
|
|
|
|
2023-02-10 16:55:52 +08:00
|
|
|
viewDkimIcon: () => 'none' !== this.dkimData()[0],
|
2020-10-26 21:44:34 +08:00
|
|
|
|
2023-02-10 16:55:52 +08:00
|
|
|
dkimIconClass:() => {
|
|
|
|
switch (this.dkimData()[0]) {
|
2020-10-26 21:44:34 +08:00
|
|
|
case 'none':
|
2021-02-22 22:16:33 +08:00
|
|
|
return '';
|
2020-10-26 21:44:34 +08:00
|
|
|
case 'pass':
|
2022-11-18 04:40:35 +08:00
|
|
|
return 'icon-ok iconcolor-green'; // ✔️
|
2020-10-26 21:44:34 +08:00
|
|
|
default:
|
2022-11-18 04:40:35 +08:00
|
|
|
return 'icon-cross iconcolor-red'; // ✖ ❌
|
2020-10-26 21:44:34 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2023-02-10 16:55:52 +08:00
|
|
|
dkimTitle:() => {
|
|
|
|
const dkim = this.dkimData();
|
|
|
|
return dkim[0] ? dkim[2] || 'DKIM: ' + dkim[0] : '';
|
2020-10-26 21:44:34 +08:00
|
|
|
},
|
|
|
|
|
2023-02-08 18:39:07 +08:00
|
|
|
showWhitelistOptions: () => 'match' === SettingsUserStore.viewImages(),
|
|
|
|
|
2022-12-22 16:56:06 +08:00
|
|
|
firstUnsubsribeLink: () => currentMessage()?.unsubsribeLinks()[0] || '',
|
|
|
|
|
2022-01-27 00:08:10 +08:00
|
|
|
pgpSupported: () => currentMessage() && PgpUserStore.isSupported(),
|
2022-01-17 22:58:23 +08:00
|
|
|
|
2021-11-30 17:19:43 +08:00
|
|
|
messageListOrViewLoading:
|
2022-02-24 02:26:52 +08:00
|
|
|
() => MessagelistUserStore.isLoading() | MessageUserStore.loading()
|
2020-10-26 21:44:34 +08:00
|
|
|
});
|
|
|
|
|
2022-10-31 05:19:52 +08:00
|
|
|
addSubscribablesTo(this, {
|
2020-10-26 19:54:03 +08:00
|
|
|
message: message => {
|
|
|
|
if (message) {
|
|
|
|
if (this.viewHash !== message.hash) {
|
|
|
|
this.scrollMessageToTop();
|
|
|
|
}
|
|
|
|
this.viewHash = message.hash;
|
2022-11-22 18:23:55 +08:00
|
|
|
// TODO: make first param a user setting #683
|
2022-12-22 16:56:06 +08:00
|
|
|
this.viewFromShort(message.from.toString(false, true));
|
2023-02-10 16:55:52 +08:00
|
|
|
this.dkimData(message.dkim[0] || ['none', '', '']);
|
2020-10-26 19:54:03 +08:00
|
|
|
} else {
|
2022-02-24 02:26:52 +08:00
|
|
|
MessagelistUserStore.selectedMessage(null);
|
2020-10-26 19:54:03 +08:00
|
|
|
|
|
|
|
this.viewHash = '';
|
2016-08-17 06:01:20 +08:00
|
|
|
|
|
|
|
this.scrollMessageToTop();
|
2015-06-01 01:40:54 +08:00
|
|
|
}
|
2020-10-26 19:54:03 +08:00
|
|
|
},
|
2016-06-30 08:02:45 +08:00
|
|
|
|
2022-03-14 22:42:05 +08:00
|
|
|
showFullInfo: value => Local.set(ClientSideKeyNameMessageHeaderFullInfo, value ? '1' : '0')
|
2016-08-17 06:01:20 +08:00
|
|
|
});
|
|
|
|
|
2022-03-04 00:34:45 +08:00
|
|
|
// commands
|
|
|
|
this.replyCommand = createCommandReplyHelper(ComposeType.Reply);
|
|
|
|
this.replyAllCommand = createCommandReplyHelper(ComposeType.ReplyAll);
|
|
|
|
this.forwardCommand = createCommandReplyHelper(ComposeType.Forward);
|
|
|
|
this.forwardAsAttachmentCommand = createCommandReplyHelper(ComposeType.ForwardAsAttachment);
|
|
|
|
this.editAsNewCommand = createCommandReplyHelper(ComposeType.EditAsNew);
|
|
|
|
|
2022-09-28 00:59:07 +08:00
|
|
|
this.deleteCommand = createCommandActionHelper(FolderType.Trash);
|
|
|
|
this.deleteWithoutMoveCommand = createCommandActionHelper(FolderType.Trash, true);
|
|
|
|
this.archiveCommand = createCommandActionHelper(FolderType.Archive);
|
2022-12-15 20:49:39 +08:00
|
|
|
this.spamCommand = createCommandActionHelper(FolderType.Junk);
|
|
|
|
this.notSpamCommand = createCommandActionHelper(FolderType.Inbox);
|
2022-03-04 00:34:45 +08:00
|
|
|
|
2021-02-19 19:09:20 +08:00
|
|
|
decorateKoCommands(this, {
|
2022-12-12 18:12:48 +08:00
|
|
|
editCommand: self => self.messageVisibility(),
|
2021-11-30 17:19:43 +08:00
|
|
|
goUpCommand: self => !self.messageListOrViewLoading(),
|
|
|
|
goDownCommand: self => !self.messageListOrViewLoading()
|
2021-02-19 19:09:20 +08:00
|
|
|
});
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
2016-08-17 06:01:20 +08:00
|
|
|
|
2022-11-30 00:29:06 +08:00
|
|
|
toggleFullInfo() {
|
|
|
|
this.showFullInfo(!this.showFullInfo());
|
|
|
|
}
|
|
|
|
|
2022-02-21 22:36:34 +08:00
|
|
|
closeMessage() {
|
2022-09-09 23:04:52 +08:00
|
|
|
currentMessage(null);
|
2016-09-03 07:19:37 +08:00
|
|
|
}
|
|
|
|
|
2022-12-12 18:12:48 +08:00
|
|
|
editCommand() {
|
2022-09-09 23:04:52 +08:00
|
|
|
currentMessage() && showMessageComposer([ComposeType.Draft, currentMessage()]);
|
2016-09-03 07:19:37 +08:00
|
|
|
}
|
|
|
|
|
2022-12-12 18:12:48 +08:00
|
|
|
setUnseen() {
|
|
|
|
setAction(MessageSetAction.UnsetSeen);
|
|
|
|
currentMessage(null);
|
|
|
|
}
|
|
|
|
|
2016-09-03 07:19:37 +08:00
|
|
|
goUpCommand() {
|
2022-02-11 19:21:16 +08:00
|
|
|
fireEvent('mailbox.message-list.selector.go-up',
|
2022-09-09 23:04:52 +08:00
|
|
|
!!currentMessage() // bForceSelect
|
2022-02-11 19:21:16 +08:00
|
|
|
);
|
2016-09-03 07:19:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
goDownCommand() {
|
2022-02-11 19:21:16 +08:00
|
|
|
fireEvent('mailbox.message-list.selector.go-down',
|
2022-09-09 23:04:52 +08:00
|
|
|
!!currentMessage() // bForceSelect
|
2022-02-11 19:21:16 +08:00
|
|
|
);
|
2016-09-03 07:19:37 +08:00
|
|
|
}
|
2021-03-12 18:57:07 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
/**
|
|
|
|
* @param {string} sType
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
replyOrforward(sType) {
|
2022-01-27 00:08:10 +08:00
|
|
|
showMessageComposer([sType, currentMessage()]);
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
2016-05-01 09:07:10 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
onBuild(dom) {
|
2020-08-30 16:30:50 +08:00
|
|
|
const eqs = (ev, s) => ev.target.closestWithin(s, dom);
|
|
|
|
dom.addEventListener('click', event => {
|
|
|
|
let el = eqs(event, 'a');
|
2022-09-30 17:38:51 +08:00
|
|
|
if (el && 0 === event.button && mailToHelper(el.href)) {
|
2023-02-21 21:26:37 +08:00
|
|
|
stopEvent(event);
|
2022-09-30 17:38:51 +08:00
|
|
|
return;
|
2020-08-30 16:30:50 +08:00
|
|
|
}
|
2016-08-17 06:01:20 +08:00
|
|
|
|
2022-11-23 18:22:20 +08:00
|
|
|
if (eqs(event, '.attachmentsPlace .showPreview')) {
|
|
|
|
return;
|
2020-08-30 16:30:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
el = eqs(event, '.attachmentsPlace .showPreplay');
|
|
|
|
if (el) {
|
2023-02-21 21:26:37 +08:00
|
|
|
stopEvent(event);
|
2021-03-13 00:08:58 +08:00
|
|
|
const attachment = ko.dataFor(el);
|
2021-03-11 05:41:35 +08:00
|
|
|
if (attachment && SMAudio.supported) {
|
2019-07-05 03:19:24 +08:00
|
|
|
switch (true) {
|
2021-03-11 05:41:35 +08:00
|
|
|
case SMAudio.supportedMp3 && attachment.isMp3():
|
|
|
|
SMAudio.playMp3(attachment.linkDownload(), attachment.fileName);
|
2016-08-17 06:01:20 +08:00
|
|
|
break;
|
2021-03-11 05:41:35 +08:00
|
|
|
case SMAudio.supportedOgg && attachment.isOgg():
|
|
|
|
SMAudio.playOgg(attachment.linkDownload(), attachment.fileName);
|
2016-08-17 06:01:20 +08:00
|
|
|
break;
|
2021-03-11 05:41:35 +08:00
|
|
|
case SMAudio.supportedWav && attachment.isWav():
|
|
|
|
SMAudio.playWav(attachment.linkDownload(), attachment.fileName);
|
2016-08-17 06:01:20 +08:00
|
|
|
break;
|
|
|
|
// no default
|
|
|
|
}
|
|
|
|
}
|
2022-11-23 18:22:20 +08:00
|
|
|
return;
|
2020-08-30 16:30:50 +08:00
|
|
|
}
|
|
|
|
|
2022-11-23 18:22:20 +08:00
|
|
|
el = eqs(event, '.attachmentItem');
|
2020-08-30 16:30:50 +08:00
|
|
|
if (el) {
|
2022-11-16 22:14:00 +08:00
|
|
|
const attachment = ko.dataFor(el), url = attachment?.linkDownload();
|
|
|
|
if (url) {
|
|
|
|
if ('application/pgp-keys' == attachment.mimeType
|
|
|
|
&& (OpenPGPUserStore.isSupported() || GnuPGUserStore.isSupported())) {
|
|
|
|
fetchRaw(url).then(text =>
|
|
|
|
showScreenPopup(OpenPgpImportPopupView, [text])
|
|
|
|
);
|
|
|
|
} else if ('message/rfc822' == attachment.mimeType) {
|
2022-05-12 05:13:24 +08:00
|
|
|
// TODO
|
2022-11-16 22:14:00 +08:00
|
|
|
fetchRaw(url).then(text => {
|
|
|
|
const oMessage = new MessageModel();
|
|
|
|
MimeToMessage(text, oMessage);
|
|
|
|
// cleanHTML
|
|
|
|
oMessage.viewPopupMessage();
|
2022-05-12 05:13:24 +08:00
|
|
|
});
|
|
|
|
} else {
|
2022-11-16 22:14:00 +08:00
|
|
|
download(url, attachment.fileName);
|
2022-05-12 05:13:24 +08:00
|
|
|
}
|
|
|
|
}
|
2020-08-30 16:30:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (eqs(event, '.messageItemHeader .subjectParent .flagParent')) {
|
2022-12-12 18:12:48 +08:00
|
|
|
setAction(currentMessage()?.isFlagged() ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag);
|
2020-08-30 16:30:50 +08:00
|
|
|
}
|
|
|
|
});
|
2014-04-08 05:03:58 +08:00
|
|
|
|
2022-03-02 16:26:30 +08:00
|
|
|
keyScopeReal.subscribe(value => this.messageDomFocused(Scope.MessageView === value));
|
2014-04-08 05:03:58 +08:00
|
|
|
|
2021-08-13 02:17:37 +08:00
|
|
|
// initShortcuts
|
2014-04-08 05:03:58 +08:00
|
|
|
|
2021-04-23 16:47:24 +08:00
|
|
|
// exit fullscreen, back
|
2022-03-09 22:08:22 +08:00
|
|
|
addShortcut('escape', '', Scope.MessageView, () => {
|
2022-01-27 00:08:10 +08:00
|
|
|
if (!this.viewModelDom.hidden && currentMessage()) {
|
2021-04-23 16:47:24 +08:00
|
|
|
const preview = SettingsUserStore.usePreviewPane();
|
2022-03-22 18:47:17 +08:00
|
|
|
if (isFullscreen()) {
|
|
|
|
exitFullscreen();
|
2021-04-23 16:47:24 +08:00
|
|
|
if (preview) {
|
|
|
|
AppUserStore.focusedState(Scope.MessageList);
|
|
|
|
}
|
|
|
|
} else if (!preview) {
|
2022-09-09 23:04:52 +08:00
|
|
|
currentMessage(null);
|
2021-04-23 16:47:24 +08:00
|
|
|
} else {
|
2021-03-16 23:06:16 +08:00
|
|
|
AppUserStore.focusedState(Scope.MessageList);
|
2016-08-17 06:01:20 +08:00
|
|
|
}
|
2016-07-01 06:50:11 +08:00
|
|
|
|
2021-04-23 16:47:24 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
2016-08-17 06:01:20 +08:00
|
|
|
|
|
|
|
// fullscreen
|
2022-03-09 22:08:22 +08:00
|
|
|
addShortcut('enter,open', '', Scope.MessageView, () => {
|
2022-03-22 18:47:17 +08:00
|
|
|
isFullscreen() || toggleFullscreen();
|
2016-06-30 08:02:45 +08:00
|
|
|
return false;
|
2016-08-17 06:01:20 +08:00
|
|
|
});
|
2016-07-01 06:50:11 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
// reply
|
2022-03-04 21:43:58 +08:00
|
|
|
registerShortcut('r,mailreply', '', [Scope.MessageList, Scope.MessageView], () => {
|
2022-01-27 00:08:10 +08:00
|
|
|
if (currentMessage()) {
|
2016-08-17 06:01:20 +08:00
|
|
|
this.replyCommand();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
});
|
2016-06-30 08:02:45 +08:00
|
|
|
|
2021-08-13 02:17:37 +08:00
|
|
|
// replyAll
|
2022-03-04 21:43:58 +08:00
|
|
|
registerShortcut('a', '', [Scope.MessageList, Scope.MessageView], () => {
|
2022-01-27 00:08:10 +08:00
|
|
|
if (currentMessage()) {
|
2016-08-17 06:01:20 +08:00
|
|
|
this.replyAllCommand();
|
|
|
|
return false;
|
|
|
|
}
|
2020-10-09 16:31:44 +08:00
|
|
|
});
|
2022-03-04 21:43:58 +08:00
|
|
|
registerShortcut('mailreply', 'shift', [Scope.MessageList, Scope.MessageView], () => {
|
2022-01-27 00:08:10 +08:00
|
|
|
if (currentMessage()) {
|
2020-10-09 16:31:44 +08:00
|
|
|
this.replyAllCommand();
|
|
|
|
return false;
|
|
|
|
}
|
2016-08-17 06:01:20 +08:00
|
|
|
});
|
2014-04-08 05:03:58 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
// forward
|
2022-03-04 21:43:58 +08:00
|
|
|
registerShortcut('f,mailforward', '', [Scope.MessageList, Scope.MessageView], () => {
|
2022-01-27 00:08:10 +08:00
|
|
|
if (currentMessage()) {
|
2016-08-17 06:01:20 +08:00
|
|
|
this.forwardCommand();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// message information
|
2022-03-04 21:43:58 +08:00
|
|
|
registerShortcut('i', 'meta', [Scope.MessageList, Scope.MessageView], () => {
|
2022-11-30 00:29:06 +08:00
|
|
|
currentMessage() && this.toggleFullInfo();
|
2016-08-17 06:01:20 +08:00
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
|
|
|
// toggle message blockquotes
|
2022-03-04 21:43:58 +08:00
|
|
|
registerShortcut('b', '', [Scope.MessageList, Scope.MessageView], () => {
|
2022-01-27 00:08:10 +08:00
|
|
|
const message = currentMessage();
|
2022-09-02 17:52:07 +08:00
|
|
|
if (message?.body) {
|
2023-02-03 19:12:40 +08:00
|
|
|
message.body.querySelectorAll('details').forEach(node => node.open = !node.open);
|
2016-08-17 06:01:20 +08:00
|
|
|
return false;
|
2014-11-20 07:25:39 +08:00
|
|
|
}
|
2016-08-17 06:01:20 +08:00
|
|
|
});
|
|
|
|
|
2022-03-09 22:08:22 +08:00
|
|
|
addShortcut('arrowup,arrowleft', 'meta', [Scope.MessageList, Scope.MessageView], () => {
|
2016-08-17 06:01:20 +08:00
|
|
|
this.goUpCommand();
|
2016-06-30 08:02:45 +08:00
|
|
|
return false;
|
2016-08-17 06:01:20 +08:00
|
|
|
});
|
2016-07-01 06:50:11 +08:00
|
|
|
|
2022-03-09 22:08:22 +08:00
|
|
|
addShortcut('arrowdown,arrowright', 'meta', [Scope.MessageList, Scope.MessageView], () => {
|
2016-08-17 06:01:20 +08:00
|
|
|
this.goDownCommand();
|
|
|
|
return false;
|
|
|
|
});
|
2015-04-14 02:45:09 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
// delete
|
2022-03-09 22:08:22 +08:00
|
|
|
addShortcut('delete', '', Scope.MessageView, () => {
|
2020-09-26 06:02:29 +08:00
|
|
|
this.deleteCommand();
|
|
|
|
return false;
|
|
|
|
});
|
2022-03-09 22:08:22 +08:00
|
|
|
addShortcut('delete', 'shift', Scope.MessageView, () => {
|
2020-09-26 06:02:29 +08:00
|
|
|
this.deleteWithoutMoveCommand();
|
|
|
|
return false;
|
2016-08-17 06:01:20 +08:00
|
|
|
});
|
2015-04-14 02:45:09 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
// change focused state
|
2022-03-09 22:08:22 +08:00
|
|
|
addShortcut('arrowleft', '', Scope.MessageView, () => {
|
2022-03-22 18:47:17 +08:00
|
|
|
if (!isFullscreen() && currentMessage() && SettingsUserStore.usePreviewPane()
|
2022-02-02 20:02:48 +08:00
|
|
|
&& !oMessageScrollerDom().scrollLeft) {
|
2021-03-16 23:06:16 +08:00
|
|
|
AppUserStore.focusedState(Scope.MessageList);
|
2020-09-26 06:02:29 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
2022-03-09 22:08:22 +08:00
|
|
|
addShortcut('tab', 'shift', Scope.MessageView, () => {
|
2022-03-22 18:47:17 +08:00
|
|
|
if (!isFullscreen() && currentMessage() && SettingsUserStore.usePreviewPane()) {
|
2021-03-16 23:06:16 +08:00
|
|
|
AppUserStore.focusedState(Scope.MessageList);
|
2016-08-17 06:01:20 +08:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
2023-02-20 17:49:22 +08:00
|
|
|
|
|
|
|
MessageUserStore.bodiesDom(dom.querySelector('.bodyText'));
|
2016-08-17 06:01:20 +08:00
|
|
|
}
|
2016-06-30 08:02:45 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
scrollMessageToTop() {
|
2023-02-22 21:57:29 +08:00
|
|
|
oMessageScrollerDom().scrollTop = 0;
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
2016-08-17 06:01:20 +08:00
|
|
|
|
|
|
|
scrollMessageToLeft() {
|
2022-02-02 20:02:48 +08:00
|
|
|
oMessageScrollerDom().scrollLeft = 0;
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
2015-04-25 06:15:11 +08:00
|
|
|
|
2022-04-25 15:40:38 +08:00
|
|
|
toggleAttachmentControls() {
|
|
|
|
const b = !this.showAttachmentControls();
|
|
|
|
this.showAttachmentControls(b);
|
|
|
|
Local.set(ClientSideKeyNameMessageAttachmentControls, b);
|
|
|
|
}
|
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
downloadAsZip() {
|
2022-10-13 05:08:28 +08:00
|
|
|
const hashes = (currentMessage()?.attachments || [])
|
2022-10-03 22:04:39 +08:00
|
|
|
.map(item => item?.checked() /*&& !item?.isLinked()*/ ? item.download : '')
|
2021-01-22 19:23:20 +08:00
|
|
|
.filter(v => v);
|
2023-02-25 21:16:04 +08:00
|
|
|
downloadZip(
|
|
|
|
currentMessage().subject(),
|
|
|
|
hashes,
|
2023-01-26 17:41:55 +08:00
|
|
|
() => this.downloadAsZipError(true),
|
|
|
|
this.downloadAsZipLoading
|
|
|
|
);
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
2015-04-14 02:45:09 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
/**
|
|
|
|
* @param {MessageModel} oMessage
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
2021-08-13 02:17:37 +08:00
|
|
|
showImages() {
|
2022-02-02 20:02:48 +08:00
|
|
|
currentMessage().showExternalImages();
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
|
|
|
|
2023-02-07 17:23:10 +08:00
|
|
|
whitelistText(txt) {
|
|
|
|
let value = (SettingsUserStore.viewImagesWhitelist().trim() + '\n' + txt).trim();
|
2023-02-10 16:55:52 +08:00
|
|
|
/*
|
|
|
|
if ('pass' === currentMessage().spf[0]?.[0]) value += '+spf';
|
|
|
|
if ('pass' === currentMessage().dkim[0]?.[0]) value += '+dkim';
|
|
|
|
if ('pass' === currentMessage().dmarc[0]?.[0]) value += '+dmarc';
|
|
|
|
*/
|
2023-02-07 17:23:10 +08:00
|
|
|
SettingsUserStore.viewImagesWhitelist(value);
|
|
|
|
Remote.saveSetting('ViewImagesWhitelist', value);
|
|
|
|
currentMessage().showExternalImages(1);
|
|
|
|
}
|
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
/**
|
|
|
|
* @returns {string}
|
|
|
|
*/
|
|
|
|
printableCheckedMessageCount() {
|
2022-09-28 05:46:13 +08:00
|
|
|
const cnt = MessagelistUserStore.listCheckedOrSelectedUidsWithSubMails().size;
|
2021-03-13 00:08:58 +08:00
|
|
|
return 0 < cnt ? (100 > cnt ? cnt : '99+') : '';
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
2014-04-13 08:32:07 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
/**
|
|
|
|
* @param {MessageModel} oMessage
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
2021-08-13 02:17:37 +08:00
|
|
|
readReceipt() {
|
2022-01-27 00:08:10 +08:00
|
|
|
let oMessage = currentMessage()
|
2022-02-02 20:02:48 +08:00
|
|
|
if (oMessage.readReceipt()) {
|
2022-05-31 23:12:29 +08:00
|
|
|
Remote.request('SendReadReceiptMessage', iError => {
|
|
|
|
if (!iError) {
|
|
|
|
oMessage.flags.push('$mdnsent');
|
|
|
|
// oMessage.flags.valueHasMutated();
|
|
|
|
}
|
|
|
|
}, {
|
2023-01-25 01:58:25 +08:00
|
|
|
messageFolder: oMessage.folder,
|
|
|
|
messageUid: oMessage.uid,
|
|
|
|
readReceipt: oMessage.readReceipt(),
|
2022-06-02 05:21:59 +08:00
|
|
|
subject: i18n('READ_RECEIPT/SUBJECT', { SUBJECT: oMessage.subject() }),
|
2023-01-25 01:58:25 +08:00
|
|
|
plain: i18n('READ_RECEIPT/BODY', { 'READ-RECEIPT': AccountUserStore.email() })
|
2021-12-03 06:15:24 +08:00
|
|
|
});
|
2016-08-17 06:01:20 +08:00
|
|
|
}
|
2016-06-30 08:02:45 +08:00
|
|
|
}
|
2022-01-17 22:58:23 +08:00
|
|
|
|
2022-10-05 23:25:30 +08:00
|
|
|
newTag() {
|
|
|
|
let message = currentMessage();
|
|
|
|
if (message) {
|
2022-10-06 16:42:21 +08:00
|
|
|
let keyword = prompt(i18n('MESSAGE/NEW_TAG'), '')?.replace(/[\s\\]+/g, '');
|
|
|
|
if (keyword.length && isAllowedKeyword(keyword)) {
|
2022-10-05 23:25:30 +08:00
|
|
|
message.toggleTag(keyword);
|
|
|
|
FolderUserStore.currentFolder().permanentFlags.push(keyword);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-02 20:02:48 +08:00
|
|
|
pgpDecrypt() {
|
|
|
|
const oMessage = currentMessage();
|
|
|
|
PgpUserStore.decrypt(oMessage).then(result => {
|
2022-11-02 02:14:08 +08:00
|
|
|
if (result) {
|
2022-11-05 19:04:56 +08:00
|
|
|
oMessage.pgpDecrypted(true);
|
2022-11-02 02:14:08 +08:00
|
|
|
if (result.data) {
|
|
|
|
MimeToMessage(result.data, oMessage);
|
|
|
|
oMessage.html() ? oMessage.viewHtml() : oMessage.viewPlain();
|
|
|
|
if (result.signatures?.length) {
|
|
|
|
oMessage.pgpSigned(true);
|
|
|
|
oMessage.pgpVerified({
|
|
|
|
signatures: result.signatures,
|
|
|
|
success: !!result.signatures.length
|
|
|
|
});
|
|
|
|
}
|
2022-02-03 17:17:18 +08:00
|
|
|
}
|
2022-11-01 19:05:44 +08:00
|
|
|
} else {
|
|
|
|
// TODO: translate
|
|
|
|
alert('Decryption failed, canceled or not possible');
|
2022-02-01 18:45:20 +08:00
|
|
|
}
|
2022-11-01 19:05:44 +08:00
|
|
|
})
|
|
|
|
.catch(e => console.error(e));
|
2022-01-17 22:58:23 +08:00
|
|
|
}
|
|
|
|
|
2022-02-02 21:36:49 +08:00
|
|
|
pgpVerify(/*self, event*/) {
|
|
|
|
const oMessage = currentMessage()/*, ctrl = event.target.closest('.openpgp-control')*/;
|
|
|
|
PgpUserStore.verify(oMessage).then(result => {
|
|
|
|
if (result) {
|
|
|
|
oMessage.pgpVerified(result);
|
2022-11-02 02:14:08 +08:00
|
|
|
} else {
|
|
|
|
alert('Verification failed or no valid public key found');
|
2022-02-02 21:36:49 +08:00
|
|
|
}
|
2022-02-02 22:24:32 +08:00
|
|
|
/*
|
2022-09-02 17:52:07 +08:00
|
|
|
if (result?.success) {
|
2022-02-09 22:43:14 +08:00
|
|
|
i18n('OPENPGP/GOOD_SIGNATURE', {
|
2022-02-02 22:24:32 +08:00
|
|
|
USER: validKey.user + ' (' + validKey.id + ')'
|
|
|
|
});
|
|
|
|
message.getText()
|
|
|
|
} else {
|
|
|
|
const keyIds = arrayLength(signingKeyIds) ? signingKeyIds : null,
|
|
|
|
additional = keyIds
|
2022-09-02 17:52:07 +08:00
|
|
|
? keyIds.map(item => item?.toHex?.()).filter(v => v).join(', ')
|
2022-02-02 22:24:32 +08:00
|
|
|
: '';
|
|
|
|
|
2022-02-09 22:43:14 +08:00
|
|
|
i18n('OPENPGP/ERROR', {
|
2022-02-02 22:24:32 +08:00
|
|
|
ERROR: 'message'
|
|
|
|
}) + (additional ? ' (' + additional + ')' : '');
|
|
|
|
}
|
|
|
|
*/
|
2022-02-02 21:36:49 +08:00
|
|
|
});
|
2022-01-17 22:58:23 +08:00
|
|
|
}
|
2022-01-20 23:38:27 +08:00
|
|
|
|
2016-08-17 06:01:20 +08:00
|
|
|
}
|