Mailspring/internal_packages/thread-search/lib/search-store.es6
Juan Tejada d3dcf89e9f feat(event-search): Add event search to calendar
Summary:
This commit adds the ability to perform event search in the calendar window.
To achieve this, SearchBar has been moved from the thread-search package to be a part
of the nylas-component-kit, and reused by both thread-search and nylas-calendar

When an event is selected from search results, the calendar view is moved to the selected
event. Depends on D3396 to open the event popover.

Test Plan: Manual

Reviewers: halla, bengotow

Reviewed By: bengotow

Differential Revision: https://phab.nylas.com/D3424
2016-11-15 17:27:31 -08:00

210 lines
5.9 KiB
JavaScript

import NylasStore from 'nylas-store';
import {
Thread,
Actions,
ContactStore,
AccountStore,
DatabaseStore,
ComponentRegistry,
FocusedPerspectiveStore,
} from 'nylas-exports';
import SearchActions from './search-actions';
import SearchMailboxPerspective from './search-mailbox-perspective';
// Stores should closely match the needs of a particular part of the front end.
// For example, we might create a "MessageStore" that observes this store
// for changes in selectedThread, "DatabaseStore" for changes to the underlying database,
// and vends up the array used for that view.
class SearchStore extends NylasStore {
constructor() {
super();
this._searchQuery = FocusedPerspectiveStore.current().searchQuery || "";
this._searchSuggestionsVersion = 1;
this._isSearching = false;
this._extensionData = []
this._clearResults();
this.listenTo(FocusedPerspectiveStore, this._onPerspectiveChanged);
this.listenTo(SearchActions.querySubmitted, this._onQuerySubmitted);
this.listenTo(SearchActions.queryChanged, this._onQueryChanged);
this.listenTo(SearchActions.searchBlurred, this._onSearchBlurred);
this.listenTo(SearchActions.searchCompleted, this._onSearchCompleted);
}
query() {
return this._searchQuery;
}
queryPopulated() {
return this._searchQuery && this._searchQuery.trim().length > 0;
}
suggestions() {
return this._suggestions;
}
isSearching() {
return this._isSearching;
}
_onSearchCompleted = () => {
this._isSearching = false;
this.trigger();
}
_onPerspectiveChanged = () => {
this._searchQuery = FocusedPerspectiveStore.current().searchQuery || "";
this.trigger();
}
_onQueryChanged = (query) => {
this._searchQuery = query;
if (this._searchQuery.length <= 1) {
this.trigger()
return
}
this._compileResults();
setTimeout(() => this._rebuildResults(), 0);
}
_onQuerySubmitted = (query) => {
this._searchQuery = query;
const current = FocusedPerspectiveStore.current();
if (this.queryPopulated()) {
this._isSearching = true;
if (this._perspectiveBeforeSearch == null) {
this._perspectiveBeforeSearch = current;
}
const next = new SearchMailboxPerspective(current.accountIds, this._searchQuery.trim());
Actions.focusMailboxPerspective(next);
} else if (current instanceof SearchMailboxPerspective) {
if (this._perspectiveBeforeSearch) {
Actions.focusMailboxPerspective(this._perspectiveBeforeSearch);
this._perspectiveBeforeSearch = null;
} else {
Actions.focusDefaultMailboxPerspectiveForAccounts(AccountStore.accounts());
}
}
this._clearResults();
}
_onSearchBlurred = () => {
this._clearResults();
}
_clearResults() {
this._searchSuggestionsVersion = 1;
this._threadResults = [];
this._contactResults = [];
this._suggestions = [];
this.trigger();
}
_rebuildResults() {
if (!this.queryPopulated()) {
this._clearResults();
return;
}
this._searchSuggestionsVersion += 1;
const searchExtensions = ComponentRegistry.findComponentsMatching({
role: "SearchBarResults",
})
Promise.map(searchExtensions, (ext) => {
return Promise.props({
label: ext.searchLabel(),
suggestions: ext.fetchSearchSuggestions(this._searchQuery),
})
}).then((extensionData = []) => {
this._extensionData = extensionData;
this._compileResults();
})
this._fetchThreadResults();
this._fetchContactResults();
}
_fetchContactResults() {
const version = this._searchSuggestionsVersion;
ContactStore.searchContacts(this._searchQuery, {limit: 10}).then(contacts => {
if (version !== this._searchSuggestionsVersion) {
return;
}
this._contactResults = contacts;
this._compileResults();
});
}
_fetchThreadResults() {
if (this._fetchingThreadResultsVersion) { return; }
this._fetchingThreadResultsVersion = this._searchSuggestionsVersion;
const {accountIds} = FocusedPerspectiveStore.current();
let dbQuery = DatabaseStore.findAll(Thread).distinct()
if (Array.isArray(accountIds) && accountIds.length === 1) {
dbQuery = dbQuery.where({accountId: accountIds[0]})
}
dbQuery = dbQuery
.search(this._searchQuery)
.order(Thread.attributes.lastMessageReceivedTimestamp.descending())
.limit(4);
dbQuery.then(results => {
// We've fetched the latest thread results - display them!
if (this._searchSuggestionsVersion === this._fetchingThreadResultsVersion) {
this._fetchingThreadResultsVersion = null;
this._threadResults = results;
this._compileResults();
// We're behind and need to re-run the search for the latest results
} else if (this._searchSuggestionsVersion > this._fetchingThreadResultsVersion) {
this._fetchingThreadResultsVersion = null;
this._fetchThreadResults();
} else {
this._fetchingThreadResultsVersion = null;
}
}
);
}
_compileResults() {
this._suggestions = [];
this._suggestions.push({
label: `Message Contains: ${this._searchQuery}`,
value: this._searchQuery,
});
if (this._threadResults.length) {
this._suggestions.push({divider: 'Threads'});
for (const thread of this._threadResults) {
this._suggestions.push({thread});
}
}
if (this._contactResults.length) {
this._suggestions.push({divider: 'People'});
for (const contact of this._contactResults) {
this._suggestions.push({
contact: contact,
value: contact.email,
});
}
}
if (this._extensionData.length) {
for (const {label, suggestions} of this._extensionData) {
this._suggestions.push({divider: label});
this._suggestions = this._suggestions.concat(suggestions)
}
}
this.trigger();
}
}
export default new SearchStore();