Skip to content

Commit

Permalink
Make users to search content in messages (draft)
Browse files Browse the repository at this point in the history
Signed-off-by: Mikhail Sazanov <m@sazanof.ru>
  • Loading branch information
Mikhail Sazanov committed Jun 1, 2022
1 parent 38e1f29 commit 58b931c
Show file tree
Hide file tree
Showing 6 changed files with 581 additions and 44 deletions.
14 changes: 10 additions & 4 deletions css/mail.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@
}

.emptycontent {
margin-top: 0px;
margin-top: 24px;
margin-bottom: 10px;
}
.emptycontent > h2 {
padding-top: 20px;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}

.container {
Expand Down
7 changes: 7 additions & 0 deletions lib/Db/MessageMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,13 @@ public function findIdsByQuery(Mailbox $mailbox, SearchQuery $query, ?int $limit
$qb->expr()->eq('m.mailbox_id', $qb->createNamedParameter($mailbox->getId()), IQueryBuilder::PARAM_INT)
);

if (!empty($query->getTags())) {
$select->innerJoin('m', 'mail_message_tags', 'tags', 'm.message_id = tags.imap_message_id');
$select->andWhere(
$qb->expr()->in('tags.tag_id', $qb->createNamedParameter($query->getTags(), IQueryBuilder::PARAM_STR_ARRAY))
);
}

if (!empty($query->getFrom())) {
$select->andWhere(
$qb->expr()->in('r0.email', $qb->createNamedParameter($query->getFrom(), IQueryBuilder::PARAM_STR_ARRAY))
Expand Down
8 changes: 7 additions & 1 deletion lib/Service/Search/FilterStringParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,13 @@ private function parseFilterToken(SearchQuery $query, string $token): bool {
$query->addBcc($param);
return true;
case 'subject':
$query->addSubject($param);
// from frontend part subject:My+search+text
$subject = str_replace('+',' ',$param);
$query->addSubject($subject);
return true;
case 'tags':
$tags = is_array($param) ? $param : explode(',',$param);
$query->setTags($tags);
return true;
}

Expand Down
22 changes: 22 additions & 0 deletions lib/Service/Search/SearchQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ class SearchQuery {
/** @var string[] */
private $textTokens = [];

/** @var array[] */
private $tags = [];

/**
* @return int|null
* @psalm-mutation-free
Expand Down Expand Up @@ -154,4 +157,23 @@ public function getTextTokens(): array {
public function addTextToken(string $textToken): void {
$this->textTokens[] = $textToken;
}

/**
* Get tags to search query
*
* @return array
*/
public function getTags(): array {
return $this->tags;
}

/**
* Set tags to search query
*
* @param array $tags
* @return void
*/
public function setTags(array $tags): void {
$this->tags = $tags;
}
}
92 changes: 53 additions & 39 deletions src/components/Mailbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,34 @@
-->

<template>
<Error v-if="error"
:error="t('mail', 'Could not open mailbox')"
message=""
role="alert" />
<Loading v-else-if="loadingEnvelopes" :hint="t('mail', 'Loading messages …')" role="alert" />
<Loading
v-else-if="loadingCacheInitialization"
:hint="t('mail', 'Loading messages …')"
:slow-hint="t('mail', 'Indexing your messages. This can take a bit longer for larger mailboxes.')" />
<EmptyMailboxSection v-else-if="isPriorityInbox && !hasMessages" key="empty" />
<EmptyMailbox v-else-if="!hasMessages" key="empty" />
<EnvelopeList
v-else
:account="account"
:mailbox="mailbox"
:search-query="searchQuery"
:envelopes="envelopesToShow"
:refreshing="refreshing"
:loading-more="loadingMore"
:load-more-button="showLoadMore"
@delete="onDelete"
@loadMore="loadMore" />
<div>
<SearchMessages
v-if="!mailbox.isUnified"
:mailbox="mailbox"
@searchChanged="onUpdateSearchQuery" />
<Error v-if="error"
:error="t('mail', 'Could not open mailbox')"
message=""
role="alert" />
<Loading v-else-if="loadingEnvelopes" :hint="t('mail', 'Loading messages …')" role="alert" />
<Loading
v-else-if="loadingCacheInitialization"
:hint="t('mail', 'Loading messages …')"
:slow-hint="t('mail', 'Indexing your messages. This can take a bit longer for larger mailboxes.')" />
<EmptyMailboxSection v-else-if="isPriorityInbox && !hasMessages" key="empty" />
<EmptyMailbox v-else-if="!hasMessages" key="empty" />
<EnvelopeList
v-else
:account="account"
:mailbox="mailbox"
:search-query="searchQuery"
:envelopes="envelopesToShow"
:refreshing="refreshing"
:loading-more="loadingMore"
:load-more-button="showLoadMore"
@delete="onDelete"
@loadMore="loadMore" />
</div>
</template>

<script>
Expand All @@ -60,6 +66,7 @@ import EmptyMailboxSection from './EmptyMailboxSection'
import { showError } from '@nextcloud/dialogs'
import NoTrashMailboxConfiguredError
from '../errors/NoTrashMailboxConfiguredError'
import SearchMessages from './SearchMessages'

export default {
name: 'Mailbox',
Expand All @@ -69,6 +76,7 @@ export default {
EnvelopeList,
Error,
Loading,
SearchMessages,
},
mixins: [isMobile],
props: {
Expand Down Expand Up @@ -109,6 +117,7 @@ export default {
},
data() {
return {
query: this.searchQuery,
error: false,
refreshing: false,
loadingMore: false,
Expand All @@ -121,7 +130,7 @@ export default {
},
computed: {
envelopes() {
return this.$store.getters.getEnvelopes(this.mailbox.databaseId, this.searchQuery)
return this.$store.getters.getEnvelopes(this.mailbox.databaseId, this.query)
},
envelopesToShow() {
if (this.paginate === 'manual' && !this.expanded) {
Expand Down Expand Up @@ -164,11 +173,12 @@ export default {
mailbox() {
this.loadEnvelopes()
.then(() => {
logger.debug(`syncing mailbox ${this.mailbox.databaseId} (${this.searchQuery}) after mailbox change`)
logger.debug(`syncing mailbox ${this.mailbox.databaseId} (${this.query}) after mailbox change`)
this.sync(false)
})
},
searchQuery() {
this.query = this.searchQuery
this.loadEnvelopes()
},
},
Expand All @@ -181,7 +191,7 @@ export default {
async mounted() {
this.loadEnvelopes()
.then(() => {
logger.debug(`syncing mailbox ${this.mailbox.databaseId} (${this.searchQuery}) after mount`)
logger.debug(`syncing mailbox ${this.mailbox.databaseId} (${this.query}) after mount`)
this.sync(false)
})
},
Expand All @@ -196,7 +206,7 @@ export default {
this.loadingCacheInitialization = true
this.error = false

logger.debug(`syncing mailbox ${this.mailbox.databaseId} (${this.searchQuery}) during cache initalization`)
logger.debug(`syncing mailbox ${this.mailbox.databaseId} (${this.query}) during cache initalization`)
this.sync(true)
.then(() => {
this.loadingCacheInitialization = false
Expand All @@ -205,15 +215,15 @@ export default {
})
},
async loadEnvelopes() {
logger.debug(`Fetching envelopes for mailbox ${this.mailbox.databaseId} (${this.searchQuery})`, this.mailbox)
logger.debug(`Fetching envelopes for mailbox ${this.mailbox.databaseId} (${this.query})`, this.mailbox)
this.loadingEnvelopes = true
this.loadingCacheInitialization = false
this.error = false

try {
const envelopes = await this.$store.dispatch('fetchEnvelopes', {
mailboxId: this.mailbox.databaseId,
query: this.searchQuery,
query: this.query,
limit: this.initialPageSize,
})

Expand Down Expand Up @@ -251,25 +261,25 @@ export default {
} catch (error) {
await matchError(error, {
[MailboxLockedError.getName()]: async(error) => {
logger.info(`Mailbox ${this.mailbox.databaseId} (${this.searchQuery}) is locked`, { error })
logger.info(`Mailbox ${this.mailbox.databaseId} (${this.query}) is locked`, { error })

await wait(15 * 1000)
// Keep trying
await this.loadEnvelopes()
},
[MailboxNotCachedError.getName()]: async(error) => {
logger.info(`Mailbox ${this.mailbox.databaseId} (${this.searchQuery}) not cached. Triggering initialization`, { error })
logger.info(`Mailbox ${this.mailbox.databaseId} (${this.query}) not cached. Triggering initialization`, { error })
this.loadingEnvelopes = false

try {
await this.initializeCache()
} catch (error) {
logger.error(`Could not initialize cache of mailbox ${this.mailbox.databaseId} (${this.searchQuery})`, { error })
logger.error(`Could not initialize cache of mailbox ${this.mailbox.databaseId} (${this.query})`, { error })
this.error = error
}
},
default: (error) => {
logger.error(`Could not fetch envelopes of mailbox ${this.mailbox.databaseId} (${this.searchQuery})`, { error })
logger.error(`Could not fetch envelopes of mailbox ${this.mailbox.databaseId} (${this.query})`, { error })
this.loadingEnvelopes = false
this.error = error
},
Expand All @@ -289,7 +299,7 @@ export default {
try {
const envelopes = await this.$store.dispatch('fetchNextEnvelopePage', {
mailboxId: this.mailbox.databaseId,
query: this.searchQuery,
query: this.query,
})
if (envelopes.length === 0) {
logger.info('envelope list end reached')
Expand Down Expand Up @@ -378,7 +388,7 @@ export default {
)
break
case 'refresh':
logger.debug(`syncing mailbox ${this.mailbox.databaseId} (${this.searchQuery}) per shortcut`)
logger.debug(`syncing mailbox ${this.mailbox.databaseId} (${this.query}) per shortcut`)
this.sync(false)

break
Expand All @@ -397,15 +407,15 @@ export default {
},
async sync(init = false) {
if (this.refreshing) {
logger.debug(`already sync'ing mailbox ${this.mailbox.databaseId} (${this.searchQuery}), aborting`, { init })
logger.debug(`already sync'ing mailbox ${this.mailbox.databaseId} (${this.query}), aborting`, { init })
return
}

this.refreshing = true
try {
await this.$store.dispatch('syncEnvelopes', {
mailboxId: this.mailbox.databaseId,
query: this.searchQuery,
query: this.query,
init,
})
} catch (error) {
Expand All @@ -419,7 +429,7 @@ export default {
})
} finally {
this.refreshing = false
logger.debug(`finished sync'ing mailbox ${this.mailbox.databaseId} (${this.searchQuery})`, { init })
logger.debug(`finished sync'ing mailbox ${this.mailbox.databaseId} (${this.query})`, { init })
}
},
// onDelete(id): Load more message and navigate to other message if needed
Expand All @@ -428,7 +438,7 @@ export default {
// Get a new message
this.$store.dispatch('fetchNextEnvelopes', {
mailboxId: this.mailbox.databaseId,
query: this.searchQuery,
query: this.query,
quantity: 1,
})
const idx = findIndex(propEq('databaseId', id), this.envelopes)
Expand Down Expand Up @@ -472,7 +482,7 @@ export default {
return
}
try {
logger.debug(`syncing mailbox ${this.mailbox.databaseId} (${this.searchQuery}) in background`)
logger.debug(`syncing mailbox ${this.mailbox.databaseId} (${this.query}) in background`)
await this.sync(false)
} catch (error) {
logger.error('Background sync failed: ' + error.message, { error })
Expand All @@ -482,6 +492,10 @@ export default {
clearInterval(this.loadMailboxInterval)
this.loadMailboxInterval = undefined
},
onUpdateSearchQuery(query) {
this.query = query
this.loadEnvelopes()
},
},
}
</script>
Expand Down
Loading

0 comments on commit 58b931c

Please # to comment.