From 5b9493f87cef86c573593455844d330472d49e70 Mon Sep 17 00:00:00 2001 From: Glenn <33450392+glenn2223@users.noreply.github.com> Date: Mon, 29 Aug 2022 00:26:40 +0100 Subject: [PATCH 1/4] Add sort functionality The update brings some basic sort functionality to the thread. As I'm limited by the DB, you only have date and subject, from and size would require some extra fields (unread is possible, though we already have the unread "folder") --- .../thread-list/lib/thread-list-store.ts | 2 + .../lib/search-query-subscription.ts | 23 +++- .../thread-search/lib/thread-search-bar.tsx | 125 +++++++++++------- .../styles/thread-search-bar.less | 14 +- app/src/mailbox-perspective.ts | 27 +++- 5 files changed, 141 insertions(+), 50 deletions(-) diff --git a/app/internal_packages/thread-list/lib/thread-list-store.ts b/app/internal_packages/thread-list/lib/thread-list-store.ts index 956c72ab1f..61e114a009 100644 --- a/app/internal_packages/thread-list/lib/thread-list-store.ts +++ b/app/internal_packages/thread-list/lib/thread-list-store.ts @@ -20,6 +20,8 @@ class ThreadListStore extends MailspringStore { super(); this.listenTo(FocusedPerspectiveStore, this._onPerspectiveChanged); this.createListDataSource(); + + AppEnv.config.observe('core.lastUsedOrder', () => this.createListDataSource()); } dataSource = () => { diff --git a/app/internal_packages/thread-search/lib/search-query-subscription.ts b/app/internal_packages/thread-search/lib/search-query-subscription.ts index e169e1776b..9833278622 100644 --- a/app/internal_packages/thread-search/lib/search-query-subscription.ts +++ b/app/internal_packages/thread-search/lib/search-query-subscription.ts @@ -7,6 +7,7 @@ import { ComponentRegistry, MutableQuerySubscription, } from 'mailspring-exports'; +import { SortOrder } from 'src/flux/attributes'; class SearchQuerySubscription extends MutableQuerySubscription { _searchQuery: string; @@ -46,9 +47,29 @@ class SearchQuerySubscription extends MutableQuerySubscription { console.info('Failed to parse local search query, falling back to generic query', e); dbQuery = dbQuery.search(this._searchQuery); } + + let order = Thread.attributes.lastMessageReceivedTimestamp.descending(); + + const orderBy: string | undefined = AppEnv.config.get('core.lastUsedOrder'); + if (orderBy) { + switch (orderBy) { + case '2': + order = Thread.attributes.subject.ascending(); + break; + + case '3': + order = Thread.attributes.subject.descending(); + break; + + case '0': + order = Thread.attributes.lastMessageReceivedTimestamp.ascending(); + break; + } + } + dbQuery = dbQuery .background() - .order(Thread.attributes.lastMessageReceivedTimestamp.descending()) + .order(order) .limit(1000); this.replaceQuery(dbQuery); diff --git a/app/internal_packages/thread-search/lib/thread-search-bar.tsx b/app/internal_packages/thread-search/lib/thread-search-bar.tsx index 5657df1972..343bac2c9e 100644 --- a/app/internal_packages/thread-search/lib/thread-search-bar.tsx +++ b/app/internal_packages/thread-search/lib/thread-search-bar.tsx @@ -1,6 +1,12 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { ListensToFluxStore, RetinaImg, KeyCommandsRegion } from 'mailspring-component-kit'; +import { + ListensToFluxStore, + RetinaImg, + KeyCommandsRegion, + DropdownMenu, + Flexbox, +} from 'mailspring-component-kit'; import { localized, Actions, @@ -41,6 +47,7 @@ interface ThreadSearchBarState { description: any; }; selectedIdx: number; + lastSortBy: string; } class ThreadSearchBar extends Component { @@ -61,6 +68,7 @@ class ThreadSearchBar extends Component { - // If the user is in list mode, we need to clear the selection because the - // thread action bar appears over the search bar. Kind of a hack. - if (WorkspaceStore.layoutMode() === 'list') { - AppEnv.commands.dispatch('multiselect-list:deselect-all'); - } - Actions.popSheet(); - this._fieldEl.focus(); - }, - }} - > - {isSearching ? ( - - ) : ( - this._fieldEl.focus()} - /> - )} - (this._fieldEl = el)} - value={showPlaceholder ? this._placeholder() : query} - onKeyDown={this._onKeyDown} - onFocus={this._onFocus} - onBlur={this._onBlur} - onChange={this._onSearchQueryChanged} - /> - {showX && ( - + { + // If the user is in list mode, we need to clear the selection because the + // thread action bar appears over the search bar. Kind of a hack. + if (WorkspaceStore.layoutMode() === 'list') { + AppEnv.commands.dispatch('multiselect-list:deselect-all'); + } + Actions.popSheet(); + this._fieldEl.focus(); + }, + }} + > + {isSearching ? ( + + ) : ( + this._fieldEl.focus()} + /> + )} + (this._fieldEl = el)} + value={showPlaceholder ? this._placeholder() : query} + onKeyDown={this._onKeyDown} + onFocus={this._onFocus} + onBlur={this._onBlur} + onChange={this._onSearchQueryChanged} /> - )} - {this.state.suggestions.length > 0 && - this.state.focused && ( + {showX && ( + + )} + {this.state.suggestions.length > 0 && this.state.focused && (
{suggestions.map((s, idx) => (
)} - + + x.id === (this.state.lastSortBy || '1'))[0]} + defaultSelectedIndex={Number.parseInt(this.state.lastSortBy) || -1} + itemKey={item => item.id} + itemContent={item => item.name} + onSelect={this._onSortSelect} + style={{ order: 100 }} + /> + ); } + + private _onSortSelect = (item: any) => { + this.setState({ lastSortBy: item.id }); + AppEnv.config.set('core.lastUsedOrder', item.id); + }; } export default ListensToFluxStore(ThreadSearchBar, { diff --git a/app/internal_packages/thread-search/styles/thread-search-bar.less b/app/internal_packages/thread-search/styles/thread-search-bar.less index 59d564351c..af8272f473 100644 --- a/app/internal_packages/thread-search/styles/thread-search-bar.less +++ b/app/internal_packages/thread-search/styles/thread-search-bar.less @@ -3,9 +3,13 @@ @token-color: @accent-primary; +.thread-search-container { + order: -100; + width: 100%; +} + .thread-search-bar { position: relative; - order: -100; overflow: visible; z-index: 100; width: 450px; @@ -125,3 +129,11 @@ } } } + +.btn.thread-search-sort { + box-shadow: @shadow-border !important; + height: 23px; + margin-left: 5px; + margin-top: 5px; + white-space: nowrap; +} \ No newline at end of file diff --git a/app/src/mailbox-perspective.ts b/app/src/mailbox-perspective.ts index 3309484532..944b18490c 100644 --- a/app/src/mailbox-perspective.ts +++ b/app/src/mailbox-perspective.ts @@ -20,6 +20,7 @@ import { Folder } from './flux/models/folder'; import { Task } from './flux/tasks/task'; import * as Actions from './flux/actions'; import { QuerySubscription } from 'mailspring-exports'; +import { SortOrder } from './flux/attributes'; let WorkspaceStore = null; let ChangeStarredTask = null; @@ -384,7 +385,31 @@ class CategoryMailboxPerspective extends MailboxPerspective { .where([Thread.attributes.categories.containsAny(this.categories().map(c => c.id))]) .limit(0); - if (this.isSent()) { + const orderBy: string | undefined = AppEnv.config.get('core.lastUsedOrder'); + + if (orderBy) { + let order: SortOrder; + + switch (orderBy) { + case '2': + order = Thread.attributes.subject.ascending(); + break; + + case '3': + order = Thread.attributes.subject.descending(); + break; + + case '0': + order = Thread.attributes.lastMessageReceivedTimestamp.ascending(); + break; + + default: + order = Thread.attributes.lastMessageReceivedTimestamp.descending(); + break; + } + + query.order(order); + } else if (this.isSent()) { query.order(Thread.attributes.lastMessageSentTimestamp.descending()); } From 0bb1e3874c6fbcf03a71fd035b58dfa37d18571b Mon Sep 17 00:00:00 2001 From: Glenn <33450392+glenn2223@users.noreply.github.com> Date: Fri, 2 Sep 2022 13:53:40 +0100 Subject: [PATCH 2/4] Prepare localisation for drop down Prepare for localisation on the subject drop down --- .../thread-search/lib/thread-search-bar.tsx | 8 ++++---- app/lang/en.json | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/internal_packages/thread-search/lib/thread-search-bar.tsx b/app/internal_packages/thread-search/lib/thread-search-bar.tsx index 343bac2c9e..547f78cf59 100644 --- a/app/internal_packages/thread-search/lib/thread-search-bar.tsx +++ b/app/internal_packages/thread-search/lib/thread-search-bar.tsx @@ -334,10 +334,10 @@ class ThreadSearchBar extends Component Date: Fri, 2 Sep 2022 14:16:13 +0100 Subject: [PATCH 3/4] Do case insensitive sorting Adjusted attribute/query so that sorting can be case insensitive --- app/src/flux/attributes/attribute-string.ts | 2 ++ app/src/flux/attributes/attribute.ts | 1 + app/src/flux/attributes/sort-order.ts | 5 ++++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/flux/attributes/attribute-string.ts b/app/src/flux/attributes/attribute-string.ts index cf1b6e746d..91a34ad2f7 100644 --- a/app/src/flux/attributes/attribute-string.ts +++ b/app/src/flux/attributes/attribute-string.ts @@ -10,6 +10,8 @@ String attributes can be queries using `equal`, `not`, and `startsWith`. Matchin Section: Database */ export class AttributeString extends Attribute { + applyCaseInsensitivity = true; + toJSON(val) { return val; } diff --git a/app/src/flux/attributes/attribute.ts b/app/src/flux/attributes/attribute.ts index 7af09417ce..8bde610a40 100644 --- a/app/src/flux/attributes/attribute.ts +++ b/app/src/flux/attributes/attribute.ts @@ -15,6 +15,7 @@ export class Attribute { public jsonKey: string; public queryable: boolean; public loadFromColumn: boolean; + public applyCaseInsensitivity = false; constructor({ modelKey, diff --git a/app/src/flux/attributes/sort-order.ts b/app/src/flux/attributes/sort-order.ts index 042d3b2d6f..aef3be37f4 100644 --- a/app/src/flux/attributes/sort-order.ts +++ b/app/src/flux/attributes/sort-order.ts @@ -18,6 +18,7 @@ Section: Database export class SortOrder { public attr: Attribute; public direction: 'ASC' | 'DESC'; + public collation: string; constructor(attr: Attribute, direction: 'ASC' | 'DESC' = 'DESC') { this.attr = attr; @@ -25,7 +26,9 @@ export class SortOrder { } orderBySQL(klass: typeof Model) { - return `\`${klass.name}\`.\`${this.attr.tableColumn}\` ${this.direction}`; + return `\`${klass.name}\`.\`${this.attr.tableColumn}\` ${ + this.attr.applyCaseInsensitivity ? 'COLLATE NOCASE' : '' + } ${this.direction}`; } attribute() { From f8e4a04eb2b531d339d25301ba532feb14afbc0f Mon Sep 17 00:00:00 2001 From: Glenn <33450392+glenn2223@users.noreply.github.com> Date: Tue, 20 Sep 2022 15:29:46 +0100 Subject: [PATCH 4/4] Fix for draggable region Applied a fix that makes the draggable region in the thread toolbar work again --- .../thread-search/styles/thread-search-bar.less | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/internal_packages/thread-search/styles/thread-search-bar.less b/app/internal_packages/thread-search/styles/thread-search-bar.less index af8272f473..24efad0746 100644 --- a/app/internal_packages/thread-search/styles/thread-search-bar.less +++ b/app/internal_packages/thread-search/styles/thread-search-bar.less @@ -6,6 +6,7 @@ .thread-search-container { order: -100; width: 100%; + flex: 1; } .thread-search-bar { @@ -136,4 +137,4 @@ margin-left: 5px; margin-top: 5px; white-space: nowrap; -} \ No newline at end of file +}