mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-30 12:39:20 +03:00
Added message tags toggle for #419
This commit is contained in:
parent
a6d97a601c
commit
70e3e6423e
19 changed files with 197 additions and 130 deletions
|
|
@ -229,11 +229,11 @@ export class AppUser extends AbstractApp {
|
|||
|
||||
setFolderHash(result.Folder, result.Hash);
|
||||
|
||||
folderFromCache.messageCountAll(result.totalEmails);
|
||||
folderFromCache.totalEmails(result.totalEmails);
|
||||
|
||||
let unreadCountChange = (folderFromCache.messageCountUnread() !== result.unreadEmails);
|
||||
let unreadCountChange = (folderFromCache.unreadEmails() !== result.unreadEmails);
|
||||
|
||||
folderFromCache.messageCountUnread(result.unreadEmails);
|
||||
folderFromCache.unreadEmails(result.unreadEmails);
|
||||
|
||||
if (unreadCountChange) {
|
||||
MessageFlagsCache.clearFolder(folderFromCache.fullName);
|
||||
|
|
|
|||
|
|
@ -38,13 +38,13 @@ fetchFolderInformation = (fCallback, folder, list = []) => {
|
|||
|
||||
if (!fetch) {
|
||||
list.forEach(messageListItem => {
|
||||
if (!MessageFlagsCache.getFor(messageListItem.folder, messageListItem.uid)) {
|
||||
if (!MessageFlagsCache.getFor(folder, messageListItem.uid)) {
|
||||
uids.push(messageListItem.uid);
|
||||
}
|
||||
|
||||
if (messageListItem.threads.length) {
|
||||
messageListItem.threads.forEach(uid => {
|
||||
if (!MessageFlagsCache.getFor(messageListItem.folder, uid)) {
|
||||
if (!MessageFlagsCache.getFor(folder, uid)) {
|
||||
uids.push(uid);
|
||||
}
|
||||
});
|
||||
|
|
@ -148,11 +148,11 @@ folderInformationMultiply = (boot = false) => {
|
|||
|
||||
setFolderHash(item.Folder, item.Hash);
|
||||
|
||||
folder.messageCountAll(item.totalEmails);
|
||||
folder.totalEmails(item.totalEmails);
|
||||
|
||||
let unreadCountChange = folder.messageCountUnread() !== item.unreadEmails;
|
||||
let unreadCountChange = folder.unreadEmails() !== item.unreadEmails;
|
||||
|
||||
folder.messageCountUnread(item.unreadEmails);
|
||||
folder.unreadEmails(item.unreadEmails);
|
||||
|
||||
if (unreadCountChange) {
|
||||
MessageFlagsCache.clearFolder(folder.fullName);
|
||||
|
|
|
|||
|
|
@ -163,11 +163,11 @@ export class FolderCollectionModel extends AbstractCollectionModel
|
|||
}
|
||||
|
||||
if (null != oFolder.totalEmails) {
|
||||
oCacheFolder.messageCountAll(oFolder.totalEmails);
|
||||
oCacheFolder.totalEmails(oFolder.totalEmails);
|
||||
}
|
||||
|
||||
if (null != oFolder.unreadEmails) {
|
||||
oCacheFolder.messageCountUnread(oFolder.unreadEmails);
|
||||
oCacheFolder.unreadEmails(oFolder.unreadEmails);
|
||||
}
|
||||
|
||||
return oCacheFolder;
|
||||
|
|
@ -258,8 +258,8 @@ export class FolderModel extends AbstractModel {
|
|||
nameForEdit: '',
|
||||
errorMsg: '',
|
||||
|
||||
privateMessageCountAll: 0,
|
||||
privateMessageCountUnread: 0,
|
||||
totalEmailsValue: 0,
|
||||
unreadEmailsValue: 0,
|
||||
|
||||
kolabType: null,
|
||||
|
||||
|
|
@ -272,6 +272,33 @@ export class FolderModel extends AbstractModel {
|
|||
|
||||
this.subFolders = ko.observableArray(new FolderCollectionModel);
|
||||
this.actionBlink = ko.observable(false).extend({ falseTimeout: 1000 });
|
||||
|
||||
this.totalEmails = koComputable({
|
||||
read: this.totalEmailsValue,
|
||||
write: (iValue) => {
|
||||
if (isPosNumeric(iValue)) {
|
||||
this.totalEmailsValue(iValue);
|
||||
} else {
|
||||
this.totalEmailsValue.valueHasMutated();
|
||||
}
|
||||
}
|
||||
})
|
||||
.extend({ notify: 'always' });
|
||||
|
||||
this.unreadEmails = koComputable({
|
||||
read: this.unreadEmailsValue,
|
||||
write: (value) => {
|
||||
if (isPosNumeric(value)) {
|
||||
this.unreadEmailsValue(value);
|
||||
} else {
|
||||
this.unreadEmailsValue.valueHasMutated();
|
||||
}
|
||||
}
|
||||
})
|
||||
.extend({ notify: 'always' });
|
||||
|
||||
this.flags = ko.observableArray();
|
||||
this.permanentFlags = ko.observableArray();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -302,30 +329,6 @@ export class FolderModel extends AbstractModel {
|
|||
|
||||
type && 'mail' != type && folder.kolabType(type);
|
||||
|
||||
folder.messageCountAll = koComputable({
|
||||
read: folder.privateMessageCountAll,
|
||||
write: (iValue) => {
|
||||
if (isPosNumeric(iValue)) {
|
||||
folder.privateMessageCountAll(iValue);
|
||||
} else {
|
||||
folder.privateMessageCountAll.valueHasMutated();
|
||||
}
|
||||
}
|
||||
})
|
||||
.extend({ notify: 'always' });
|
||||
|
||||
folder.messageCountUnread = koComputable({
|
||||
read: folder.privateMessageCountUnread,
|
||||
write: (value) => {
|
||||
if (isPosNumeric(value)) {
|
||||
folder.privateMessageCountUnread(value);
|
||||
} else {
|
||||
folder.privateMessageCountUnread.valueHasMutated();
|
||||
}
|
||||
}
|
||||
})
|
||||
.extend({ notify: 'always' });
|
||||
|
||||
folder.addComputables({
|
||||
|
||||
isInbox: () => FolderType.Inbox === folder.type(),
|
||||
|
|
@ -371,8 +374,8 @@ export class FolderModel extends AbstractModel {
|
|||
hidden: () => !folder.selectable() && (folder.isSystemFolder() | !folder.hasVisibleSubfolders()),
|
||||
|
||||
printableUnreadCount: () => {
|
||||
const count = folder.messageCountAll(),
|
||||
unread = folder.messageCountUnread(),
|
||||
const count = folder.totalEmails(),
|
||||
unread = folder.unreadEmails(),
|
||||
type = folder.type();
|
||||
|
||||
if (count) {
|
||||
|
|
@ -412,7 +415,7 @@ export class FolderModel extends AbstractModel {
|
|||
return '';
|
||||
},
|
||||
|
||||
hasUnreadMessages: () => 0 < folder.messageCountUnread() && folder.printableUnreadCount(),
|
||||
hasUnreadMessages: () => 0 < folder.unreadEmails() && folder.printableUnreadCount(),
|
||||
|
||||
hasSubscribedUnreadMessagesSubfolders: () =>
|
||||
!!folder.subFolders().find(
|
||||
|
|
@ -427,7 +430,7 @@ export class FolderModel extends AbstractModel {
|
|||
|
||||
edited: value => value && folder.nameForEdit(folder.name()),
|
||||
|
||||
messageCountUnread: unread => {
|
||||
unreadEmails: unread => {
|
||||
if (FolderType.Inbox === folder.type()) {
|
||||
fireEvent('mailbox.inbox-unread-count', unread);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ import { AbstractModel } from 'Knoin/AbstractModel';
|
|||
|
||||
import PreviewHTML from 'Html/PreviewMessage.html';
|
||||
|
||||
import Remote from 'Remote/User/Fetch';
|
||||
|
||||
const
|
||||
// eslint-disable-next-line max-len
|
||||
url = /(^|[\s\n]|\/?>)(https:\/\/[-A-Z0-9+\u0026\u2019#/%?=()~_|!:,.;]*[-A-Z0-9+\u0026#/%=~()_|])/gi,
|
||||
|
|
@ -32,6 +34,25 @@ const
|
|||
return result;
|
||||
},
|
||||
|
||||
toggleTag = (message, keyword) => {
|
||||
const lower = keyword.toLowerCase(),
|
||||
isSet = message.flags().includes(lower);
|
||||
Remote.request('MessageSetKeyword', iError => {
|
||||
if (!iError) {
|
||||
if (isSet) {
|
||||
message.flags.remove(lower);
|
||||
} else {
|
||||
message.flags.push(lower);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
Folder: message.folder,
|
||||
Uids: message.uid,
|
||||
Keyword: keyword,
|
||||
SetAction: isSet ? 0 : 1
|
||||
})
|
||||
},
|
||||
|
||||
replyHelper = (emails, unic, localEmails) => {
|
||||
emails.forEach(email => {
|
||||
if (undefined === unic[email.email]) {
|
||||
|
|
@ -91,6 +112,14 @@ export class MessageModel extends AbstractModel {
|
|||
this.unsubsribeLinks = ko.observableArray();
|
||||
this.flags = ko.observableArray();
|
||||
|
||||
const ignoredTags = [
|
||||
'$sent',
|
||||
'$signed',
|
||||
'$error',
|
||||
'$queued',
|
||||
'$forwarded'
|
||||
];
|
||||
|
||||
this.addComputables({
|
||||
attachmentIconClass: () => FileInfo.getAttachmentsIconClass(this.attachments()),
|
||||
threadsLen: () => this.threads().length,
|
||||
|
|
@ -107,7 +136,25 @@ export class MessageModel extends AbstractModel {
|
|||
('\\' == value[0] || '$forwarded' == value)
|
||||
? ''
|
||||
: '<span class="focused msgflag-'+value+'">' + i18n('MESSAGE_TAGS/'+value,0,value) + '</span>'
|
||||
).join(' ')
|
||||
).join(' '),
|
||||
|
||||
tagOptions: () => {
|
||||
const tagOptions = [];
|
||||
FolderUserStore.currentFolder().permanentFlags.forEach(value => {
|
||||
let lower = value.toLowerCase();
|
||||
if ('\\' != value[0] && !ignoredTags.includes(lower)) {
|
||||
tagOptions.push({
|
||||
css: 'msgflag-' + lower,
|
||||
value: value,
|
||||
checked: this.flags().includes(lower),
|
||||
label: i18n('MESSAGE_TAGS/'+lower, 0, lower),
|
||||
toggle: (/*obj*/) => toggleTag(this, value)
|
||||
});
|
||||
}
|
||||
});
|
||||
return tagOptions
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,15 +16,16 @@ export class MessageCollectionModel extends AbstractCollectionModel
|
|||
this.Filtered
|
||||
this.Folder
|
||||
this.FolderHash
|
||||
this.Limit
|
||||
this.FolderInfo
|
||||
this.totalEmails
|
||||
this.unreadEmails
|
||||
this.MessageResultCount
|
||||
this.UidNext
|
||||
this.ThreadUid
|
||||
this.NewMessages
|
||||
this.Offset
|
||||
this.Limit
|
||||
this.Search
|
||||
this.ThreadUid
|
||||
this.UidNext
|
||||
}
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ export class UserSettingsFolders /*extends AbstractViewSettings*/ {
|
|||
&& folderToRemove.canBeDeleted()
|
||||
&& folderToRemove.askDelete()
|
||||
) {
|
||||
if (0 < folderToRemove.privateMessageCountAll()) {
|
||||
if (0 < folderToRemove.totalEmails()) {
|
||||
// FolderUserStore.folderListError(getNotification(Notification.CantDeleteNonEmptyFolder));
|
||||
folderToRemove.errorMsg(getNotification(Notification.CantDeleteNonEmptyFolder));
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -186,27 +186,29 @@ MessagelistUserStore.reload = (bDropPagePosition = false, bDropCurrenFolderCache
|
|||
let unreadCountChange = false;
|
||||
|
||||
const
|
||||
folder = getFolderFromCacheList(collection.Folder);
|
||||
|
||||
folder = getFolderFromCacheList(collection.Folder),
|
||||
folderInfo = collection.FolderInfo;
|
||||
if (folder && !bCached) {
|
||||
folder.expires = Date.now();
|
||||
|
||||
setFolderHash(collection.Folder, collection.FolderHash);
|
||||
|
||||
if (null != collection.totalEmails) {
|
||||
folder.messageCountAll(collection.totalEmails);
|
||||
if (null != folderInfo.totalEmails) {
|
||||
folder.totalEmails(folderInfo.totalEmails);
|
||||
}
|
||||
|
||||
if (null != collection.unreadEmails) {
|
||||
if (pInt(folder.messageCountUnread()) !== pInt(collection.unreadEmails)) {
|
||||
if (null != folderInfo.unreadEmails) {
|
||||
if (pInt(folder.unreadEmails()) !== pInt(folderInfo.unreadEmails)) {
|
||||
unreadCountChange = true;
|
||||
MessageFlagsCache.clearFolder(folder.fullName);
|
||||
}
|
||||
|
||||
folder.messageCountUnread(collection.unreadEmails);
|
||||
folder.unreadEmails(folderInfo.unreadEmails);
|
||||
}
|
||||
|
||||
MessagelistUserStore.initUidNextAndNewMessages(folder.fullName, collection.UidNext, collection.NewMessages);
|
||||
folder.flags(folderInfo.Flags);
|
||||
folder.permanentFlags(folderInfo.PermanentFlags);
|
||||
|
||||
MessagelistUserStore.initUidNextAndNewMessages(folder.fullName, folderInfo.UidNext, collection.NewMessages);
|
||||
}
|
||||
|
||||
MessagelistUserStore.count(collection.MessageResultCount);
|
||||
|
|
@ -280,7 +282,7 @@ MessagelistUserStore.setAction = (sFolderFullName, iSetAction, messages) => {
|
|||
|
||||
folder = getFolderFromCacheList(sFolderFullName);
|
||||
if (folder) {
|
||||
folder.messageCountUnread(folder.messageCountUnread() - alreadyUnread + length);
|
||||
folder.unreadEmails(folder.unreadEmails() - alreadyUnread + length);
|
||||
}
|
||||
|
||||
Remote.request('MessageSetSeen', null, {
|
||||
|
|
@ -335,13 +337,13 @@ MessagelistUserStore.removeMessagesFromList = (
|
|||
messages.forEach(item => item && item.isUnseen() && ++unseenCount);
|
||||
|
||||
if (fromFolder && !copy) {
|
||||
fromFolder.messageCountAll(
|
||||
0 <= fromFolder.messageCountAll() - uidForRemove.length ? fromFolder.messageCountAll() - uidForRemove.length : 0
|
||||
fromFolder.totalEmails(
|
||||
0 <= fromFolder.totalEmails() - uidForRemove.length ? fromFolder.totalEmails() - uidForRemove.length : 0
|
||||
);
|
||||
|
||||
if (0 < unseenCount) {
|
||||
fromFolder.messageCountUnread(
|
||||
0 <= fromFolder.messageCountUnread() - unseenCount ? fromFolder.messageCountUnread() - unseenCount : 0
|
||||
fromFolder.unreadEmails(
|
||||
0 <= fromFolder.unreadEmails() - unseenCount ? fromFolder.unreadEmails() - unseenCount : 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -351,9 +353,9 @@ MessagelistUserStore.removeMessagesFromList = (
|
|||
unseenCount = 0;
|
||||
}
|
||||
|
||||
toFolder.messageCountAll(toFolder.messageCountAll() + uidForRemove.length);
|
||||
toFolder.totalEmails(toFolder.totalEmails() + uidForRemove.length);
|
||||
if (0 < unseenCount) {
|
||||
toFolder.messageCountUnread(toFolder.messageCountUnread() + unseenCount);
|
||||
toFolder.unreadEmails(toFolder.unreadEmails() + unseenCount);
|
||||
}
|
||||
|
||||
toFolder.actionBlink(true);
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ html.rl-no-preview-pane {
|
|||
.messageTags {
|
||||
margin-top: 6px;
|
||||
}
|
||||
.messageTags * * {
|
||||
.messageTags span span {
|
||||
border: 1px solid #808080;
|
||||
padding: 2px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ export class FolderClearPopupView extends AbstractViewPopup {
|
|||
|
||||
this.clearingProcess(true);
|
||||
|
||||
folderToClear.messageCountAll(0);
|
||||
folderToClear.messageCountUnread(0);
|
||||
folderToClear.totalEmails(0);
|
||||
folderToClear.unreadEmails(0);
|
||||
|
||||
setFolderHash(folderToClear.fullName, '');
|
||||
|
||||
|
|
|
|||
|
|
@ -487,9 +487,9 @@ export class MailMessageList extends AbstractViewRight {
|
|||
});
|
||||
|
||||
if (iThreadUid) {
|
||||
folder.messageCountUnread(Math.max(0, folder.messageCountUnread() - cnt));
|
||||
folder.unreadEmails(Math.max(0, folder.unreadEmails() - cnt));
|
||||
} else {
|
||||
folder.messageCountUnread(0);
|
||||
folder.unreadEmails(0);
|
||||
}
|
||||
|
||||
MessageFlagsCache.clearFolder(sFolderFullName);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue