Allow searching on keyword/tag/label #419

This commit is contained in:
the-djmaze 2022-10-05 11:32:06 +02:00
parent fba1c59f84
commit 875dae0755
42 changed files with 789 additions and 712 deletions

View file

@ -8,7 +8,7 @@ import { encodeHtml, plainToHtml, cleanHtml } from 'Common/Html';
import { isArray, arrayLength, forEachObjectEntry } from 'Common/Utils';
import { serverRequestRaw, proxy } from 'Common/Links';
import { FolderUserStore } from 'Stores/User/Folder';
import { FolderUserStore, isAllowedKeyword } from 'Stores/User/Folder';
import { SettingsUserStore } from 'Stores/User/Settings';
import { FileInfo } from 'Common/File';
@ -30,40 +30,6 @@ const
return result;
},
ignoredTags = [
// rfc5788
'$forwarded',
'$mdnsent',
'$submitpending',
'$submitted',
// rfc9051
'$junk',
'$notjunk',
'$phishing',
// Mailo
'sent',
// KMail
'$attachment',
'$encrypted',
'$error',
'$ignored',
'$invitation',
'$queued',
'$replied',
'$sent',
'$signed',
'$todo',
'$watched',
// GMail
'$replied',
'$attachment',
'$notphishing',
'junk',
'nonjunk',
// Others
'$readreceipt'
],
toggleTag = (message, keyword) => {
const lower = keyword.toLowerCase(),
isSet = message.flags().includes(lower);
@ -161,16 +127,16 @@ export class MessageModel extends AbstractModel {
// isPhishing: () => this.flags().includes('$phishing'),
tagsToHTML: () => this.flags().map(value =>
('\\' == value[0] || ignoredTags.includes(value))
? ''
: '<span class="focused msgflag-'+value+'">' + i18n('MESSAGE_TAGS/'+value,0,value) + '</span>'
isAllowedKeyword(value)
? '<span class="focused msgflag-'+value+'">' + i18n('MESSAGE_TAGS/'+value,0,value) + '</span>'
: ''
).join(' '),
tagOptions: () => {
const tagOptions = [];
FolderUserStore.currentFolder().permanentFlags.forEach(value => {
let lower = value.toLowerCase();
if ('\\' != value[0] && !ignoredTags.includes(lower)) {
if (isAllowedKeyword(value)) {
let lower = value.toLowerCase();
tagOptions.push({
css: 'msgflag-' + lower,
value: value,

View file

@ -9,7 +9,45 @@ import { getFolderInboxName, getFolderFromCacheList } from 'Common/Cache';
import { Settings, SettingsCapa } from 'Common/Globals';
//import Remote from 'Remote/User/Fetch'; // Circular dependency
export const FolderUserStore = new class {
export const
ignoredKeywords = [
// rfc5788
'$forwarded',
'$mdnsent',
'$submitpending',
'$submitted',
// rfc9051
'$junk',
'$notjunk',
'$phishing',
// Mailo
'sent',
// KMail
'$attachment',
'$encrypted',
'$error',
'$ignored',
'$invitation',
'$queued',
'$replied',
'$sent',
'$signed',
'$todo',
'$watched',
// GMail
'$replied',
'$attachment',
'$notphishing',
'junk',
'nonjunk',
// Others
'$readreceipt'
],
isAllowedKeyword = value => '\\' != value[0] && !ignoredKeywords.includes(value.toLowerCase()),
FolderUserStore = new class {
constructor() {
const self = this;
addObservablesTo(self, {

View file

@ -1,12 +1,10 @@
import { koComputable } from 'External/ko';
import { i18n, trigger as translatorTrigger } from 'Common/Translator';
import { pString } from 'Common/Utils';
import { MessagelistUserStore } from 'Stores/User/Messagelist';
import { AbstractViewPopup } from 'Knoin/AbstractViews';
import { FolderUserStore } from 'Stores/User/Folder';
import { FolderUserStore, isAllowedKeyword } from 'Stores/User/Folder';
export class AdvancedSearchPopupView extends AbstractViewPopup {
constructor() {
@ -17,6 +15,7 @@ export class AdvancedSearchPopupView extends AbstractViewPopup {
to: '',
subject: '',
text: '',
keyword: '',
repliedValue: -1,
selectedDateValue: -1,
selectedTreeValue: '',
@ -26,39 +25,58 @@ export class AdvancedSearchPopupView extends AbstractViewPopup {
unseen: false
});
this.showMultisearch = koComputable(() => FolderUserStore.hasCapability('MULTISEARCH'));
this.addComputables({
showMultisearch: () => FolderUserStore.hasCapability('MULTISEARCH'),
this.repliedOptions = koComputable(() => {
translatorTrigger();
return [
{ id: -1, name: '' },
{ id: 1, name: i18n('GLOBAL/YES') },
{ id: 0, name: i18n('GLOBAL/NO') }
];
});
// Almost the same as MessageModel.tagOptions
keywords: () => {
const keywords = [{value:'',label:''}];
FolderUserStore.currentFolder().permanentFlags.forEach(value => {
if (isAllowedKeyword(value)) {
let lower = value.toLowerCase();
keywords.push({
value: value,
label: i18n('MESSAGE_TAGS/'+lower, 0, lower)
});
}
});
return keywords
},
this.selectedDates = koComputable(() => {
translatorTrigger();
let prefix = 'SEARCH/LABEL_DATE_';
return [
{ id: -1, name: i18n(prefix + 'ALL') },
{ id: 3, name: i18n(prefix + '3_DAYS') },
{ id: 7, name: i18n(prefix + '7_DAYS') },
{ id: 30, name: i18n(prefix + 'MONTH') },
{ id: 90, name: i18n(prefix + '3_MONTHS') },
{ id: 180, name: i18n(prefix + '6_MONTHS') },
{ id: 365, name: i18n(prefix + 'YEAR') }
];
});
showKeywords: () => FolderUserStore.currentFolder().permanentFlags().some(isAllowedKeyword),
this.selectedTree = koComputable(() => {
translatorTrigger();
let prefix = 'SEARCH/LABEL_SUBFOLDERS_';
return [
{ id: '', name: i18n(prefix + 'NONE') },
{ id: 'subtree-one', name: i18n(prefix + 'SUBTREE_ONE') },
{ id: 'subtree', name: i18n(prefix + 'SUBTREE') }
];
repliedOptions: () => {
translatorTrigger();
return [
{ id: -1, name: '' },
{ id: 1, name: i18n('GLOBAL/YES') },
{ id: 0, name: i18n('GLOBAL/NO') }
];
},
selectedDates: () => {
translatorTrigger();
let prefix = 'SEARCH/LABEL_DATE_';
return [
{ id: -1, name: i18n(prefix + 'ALL') },
{ id: 3, name: i18n(prefix + '3_DAYS') },
{ id: 7, name: i18n(prefix + '7_DAYS') },
{ id: 30, name: i18n(prefix + 'MONTH') },
{ id: 90, name: i18n(prefix + '3_MONTHS') },
{ id: 180, name: i18n(prefix + '6_MONTHS') },
{ id: 365, name: i18n(prefix + 'YEAR') }
];
},
selectedTree: () => {
translatorTrigger();
let prefix = 'SEARCH/LABEL_SUBFOLDERS_';
return [
{ id: '', name: i18n(prefix + 'NONE') },
{ id: 'subtree-one', name: i18n(prefix + 'SUBTREE_ONE') },
{ id: 'subtree', name: i18n(prefix + 'SUBTREE') }
];
}
});
}
@ -81,6 +99,7 @@ export class AdvancedSearchPopupView extends AbstractViewPopup {
append('to', self.to().trim());
append('subject', self.subject().trim());
append('text', self.text().trim());
append('keyword', self.keyword());
append('in', self.selectedTreeValue());
if (-1 < self.selectedDateValue()) {
let d = new Date();
@ -88,7 +107,7 @@ export class AdvancedSearchPopupView extends AbstractViewPopup {
append('since', d.toISOString().split('T')[0]);
}
let result = new URLSearchParams(data).toString();
let result = new URLSearchParams(data).toString().replace('%24','$');
if (self.hasAttachment()) {
result += '&attachment';
@ -116,6 +135,7 @@ export class AdvancedSearchPopupView extends AbstractViewPopup {
self.to(pString(params.get('to')));
self.subject(pString(params.get('subject')));
self.text(pString(params.get('text')));
self.keyword(pString(params.get('keyword')));
self.selectedTreeValue(pString(params.get('in')));
// self.selectedDateValue(params.get('since'));
self.selectedDateValue(-1);