Skip to content

Commit

Permalink
Move search to Redux
Browse files Browse the repository at this point in the history
  • Loading branch information
belcherj committed Feb 10, 2020
1 parent 1632c11 commit f1fd6dd
Show file tree
Hide file tree
Showing 14 changed files with 159 additions and 126 deletions.
7 changes: 0 additions & 7 deletions lib/flux/app-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ const toggleSystemTag = (

const initialState: AppState = {
editorMode: 'edit',
filter: '',
previousIndex: -1,
notes: null,
tags: [],
Expand Down Expand Up @@ -191,12 +190,6 @@ export const actionMap = new ActionMap({
});
},

search(state: AppState, { filter }: { filter: string }) {
return update(state, {
filter: { $set: filter },
});
},

newNote: {
creator({
noteBucket,
Expand Down
41 changes: 28 additions & 13 deletions lib/note-content-editor.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { ContentState, Editor, EditorState, Modifier } from 'draft-js';
import MultiDecorator from 'draft-js-multidecorators';
import { compact, get, invoke, noop } from 'lodash';
Expand All @@ -26,16 +27,23 @@ import insertOrRemoveCheckboxes from './editor/insert-or-remove-checkboxes';
import { getIpcRenderer } from './utils/electron';
import analytics from './analytics';

import * as S from './state';

const TEXT_DELIMITER = '\n';

export default class NoteContentEditor extends Component {
type StateProps = {
searchQuery: string;
};

type Props = StateProps;

class NoteContentEditor extends Component<Props> {
static propTypes = {
content: PropTypes.shape({
text: PropTypes.string.isRequired,
hasRemoteUpdate: PropTypes.bool.isRequired,
version: PropTypes.string,
}),
filter: PropTypes.string.isRequired,
noteId: PropTypes.string,
onChangeContent: PropTypes.func.isRequired,
spellCheckEnabled: PropTypes.bool.isRequired,
Expand All @@ -62,23 +70,24 @@ export default class NoteContentEditor extends Component {
);
};

generateDecorators = filter => {
generateDecorators = (searchQuery: string) => {
return new MultiDecorator(
compact([
filterHasText(filter) && matchingTextDecorator(searchPattern(filter)),
filterHasText(searchQuery) &&
matchingTextDecorator(searchPattern(searchQuery)),
checkboxDecorator(this.replaceRangeWithText),
])
);
};

createNewEditorState = (text, filter) => {
createNewEditorState = (text: string, searchQuery: string) => {
const newEditorState = EditorState.createWithContent(
ContentState.createFromText(text, TEXT_DELIMITER),
this.generateDecorators(filter)
this.generateDecorators(searchQuery)
);

// Focus the editor for a new, empty note when not searching
if (text === '' && filter === '') {
if (text === '' && searchQuery === '') {
return EditorState.moveFocusToEnd(newEditorState);
}
return newEditorState;
Expand All @@ -87,7 +96,7 @@ export default class NoteContentEditor extends Component {
state = {
editorState: this.createNewEditorState(
this.props.content.text,
this.props.filter
this.props.searchQuery
),
};

Expand Down Expand Up @@ -152,7 +161,7 @@ export default class NoteContentEditor extends Component {
};

componentDidUpdate(prevProps) {
const { content, filter, noteId, spellCheckEnabled } = this.props;
const { content, searchQuery, noteId, spellCheckEnabled } = this.props;
const { editorState } = this.state;

// To immediately reflect the changes to the spell check setting,
Expand All @@ -171,16 +180,16 @@ export default class NoteContentEditor extends Component {
content.version !== prevProps.content.version
) {
this.setState({
editorState: this.createNewEditorState(content.text, filter),
editorState: this.createNewEditorState(content.text, searchQuery),
});
return;
}

// If filter changes, re-set decorators
if (filter !== prevProps.filter) {
// If searchQuery changes, re-set decorators
if (searchQuery !== prevProps.searchQuery) {
this.setState({
editorState: EditorState.set(editorState, {
decorator: this.generateDecorators(filter),
decorator: this.generateDecorators(searchQuery),
}),
});
}
Expand Down Expand Up @@ -320,3 +329,9 @@ export default class NoteContentEditor extends Component {
);
}
}

const mapStateToProps: S.MapState<StateProps> = ({ ui: { searchQuery } }) => ({
searchQuery,
});

export default connect(mapStateToProps)(NoteContentEditor);
7 changes: 0 additions & 7 deletions lib/note-detail/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export class NoteDetail extends Component {

static propTypes = {
dialogs: PropTypes.array.isRequired,
filter: PropTypes.string.isRequired,
fontSize: PropTypes.number,
onChangeContent: PropTypes.func.isRequired,
syncNote: PropTypes.func.isRequired,
Expand Down Expand Up @@ -57,8 +56,6 @@ export class NoteDetail extends Component {

focusEditor = () => this.focusContentEditor && this.focusContentEditor();

saveEditorRef = ref => (this.editor = ref);

isValidNote = note => note && note.id;

componentWillReceiveProps(nextProps) {
Expand Down Expand Up @@ -185,7 +182,6 @@ export class NoteDetail extends Component {
render() {
const {
note,
filter,
fontSize,
previewingMarkdown,
spellCheckEnabled,
Expand Down Expand Up @@ -222,13 +218,11 @@ export class NoteDetail extends Component {
style={divStyle}
>
<NoteContentEditor
ref={this.saveEditorRef}
spellCheckEnabled={spellCheckEnabled}
storeFocusEditor={this.storeFocusContentEditor}
storeHasFocus={this.storeEditorHasFocus}
noteId={get(note, 'id', null)}
content={content}
filter={filter}
onChangeContent={this.saveNote}
/>
</div>
Expand All @@ -242,7 +236,6 @@ export class NoteDetail extends Component {

const mapStateToProps = ({ appState: state, ui, settings }) => ({
dialogs: state.dialogs,
filter: state.filter,
note: state.revision || ui.note,
shouldPrint: state.shouldPrint,
showNoteInfo: state.showNoteInfo,
Expand Down
4 changes: 1 addition & 3 deletions lib/note-editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export class NoteEditor extends Component<Props> {
editorMode: PropTypes.oneOf(['edit', 'markdown']),
isEditorActive: PropTypes.bool.isRequired,
isSmallScreen: PropTypes.bool.isRequired,
filter: PropTypes.string.isRequired,
noteBucket: PropTypes.object.isRequired,
fontSize: PropTypes.number,
onNoteClosed: PropTypes.func.isRequired,
Expand Down Expand Up @@ -145,7 +144,7 @@ export class NoteEditor extends Component<Props> {
<NoteDetail
storeFocusEditor={this.storeFocusEditor}
storeHasFocus={this.storeEditorHasFocus}
filter={this.props.filter}
note={revision}
noteBucket={noteBucket}
previewingMarkdown={
this.markdownEnabled() && editorMode === 'markdown'
Expand Down Expand Up @@ -174,7 +173,6 @@ const mapStateToProps: S.MapState<StateProps> = ({
ui: { note },
}) => ({
allTags: state.tags,
filter: state.filter,
fontSize: settings.fontSize,
editorMode: state.editorMode,
isEditorActive: !state.showNavigation,
Expand Down
39 changes: 16 additions & 23 deletions lib/note-list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ const getRowHeight = rowHeightCache(computeRowHeight);
* @see react-virtual/list
*
* @param {Object[]} notes list of filtered notes
* @param {String} filter search filter
* @param {String} searchQuery search searchQuery
* @param {String} noteDisplay list view style: comfy, condensed, expanded
* @param {Number} selectedNoteId id of currently selected note
* @param {Function} onSelectNote used to change the current note selection
Expand All @@ -202,7 +202,7 @@ const getRowHeight = rowHeightCache(computeRowHeight);
const renderNote = (
notes,
{
filter,
searchQuery,
noteDisplay,
selectedNoteId,
onNoteOpened,
Expand Down Expand Up @@ -244,7 +244,7 @@ const renderNote = (
'published-note': isPublished,
});

const decorators = [checkboxDecorator, makeFilterDecorator(filter)];
const decorators = [checkboxDecorator, makeFilterDecorator(searchQuery)];

const selectNote = () => {
onSelectNote(note.id);
Expand Down Expand Up @@ -288,12 +288,12 @@ const renderNote = (
* @see renderNote
*
* @param {Object[]} notes list of filtered notes
* @param {String} filter search filter
* @param {String} searchQuery search filter
* @param {Number} tagResultsFound number of tag matches to display
* @returns {Object[]} modified notes list
*/
const createCompositeNoteList = (notes, filter, tagResultsFound) => {
if (filter.length === 0 || tagResultsFound === 0) {
const createCompositeNoteList = (notes, searchQuery, tagResultsFound) => {
if (searchQuery.length === 0 || tagResultsFound === 0) {
return notes;
}

Expand All @@ -311,7 +311,6 @@ export class NoteList extends Component<Props> {

static propTypes = {
closeNote: PropTypes.func.isRequired,
filter: PropTypes.string.isRequired,
tagResultsFound: PropTypes.number.isRequired,
isSmallScreen: PropTypes.bool.isRequired,
notes: PropTypes.array.isRequired,
Expand Down Expand Up @@ -339,16 +338,10 @@ export class NoteList extends Component<Props> {
}

componentDidUpdate(prevProps) {
const {
closeNote,
filter,
notes,
onSelectNote,
selectedNoteId,
} = this.props;
const { closeNote, searchQuery, notes, selectedNoteId } = this.props;

if (
prevProps.filter !== this.props.filter ||
prevProps.searchQuery !== searchQuery ||
prevProps.noteDisplay !== this.props.noteDisplay ||
prevProps.notes !== notes ||
prevProps.selectedNoteContent !== this.props.selectedNoteContent
Expand All @@ -357,7 +350,7 @@ export class NoteList extends Component<Props> {
}

// Deselect the currently selected note if it doesn't match the search query
if (filter !== prevProps.filter) {
if (searchQuery !== prevProps.searchQuery) {
const selectedNotePassesFilter = notes.some(
note => note.id === selectedNoteId
);
Expand Down Expand Up @@ -406,7 +399,7 @@ export class NoteList extends Component<Props> {

render() {
const {
filter,
searchQuery,
hasLoaded,
selectedNoteId,
onNoteOpened,
Expand All @@ -422,7 +415,7 @@ export class NoteList extends Component<Props> {
const listItemsClasses = classNames('note-list-items', noteDisplay);

const renderNoteRow = renderNote(notes, {
filter,
searchQuery,
noteDisplay,
onNoteOpened,
onSelectNote,
Expand Down Expand Up @@ -467,7 +460,7 @@ export class NoteList extends Component<Props> {
notes={notes}
rowCount={notes.length}
rowHeight={getRowHeight(notes, {
filter,
searchQuery,
noteDisplay,
tagResultsFound,
width,
Expand Down Expand Up @@ -499,10 +492,10 @@ const { recordEvent } = tracks;

const mapStateToProps: S.MapState<StateProps> = ({
appState: state,
ui: { filteredNotes, note },
ui: { filteredNotes, note, searchQuery },
settings: { noteDisplay },
}) => {
const tagResultsFound = getMatchingTags(state.tags, state.filter).length;
const tagResultsFound = getMatchingTags(state.tags, searchQuery).length;
const selectedNote = note;
const selectedNoteId = selectedNote?.id;
const selectedNoteIndex = filteredNotes.findIndex(
Expand All @@ -517,7 +510,7 @@ const mapStateToProps: S.MapState<StateProps> = ({

const compositeNoteList = createCompositeNoteList(
filteredNotes,
state.filter,
searchQuery,
tagResultsFound
);

Expand Down Expand Up @@ -545,12 +538,12 @@ const mapStateToProps: S.MapState<StateProps> = ({
selectedNote && getNoteTitleAndPreview(selectedNote).preview;

return {
filter: state.filter,
hasLoaded: state.notes !== null,
nextNote,
noteDisplay,
notes: compositeNoteList,
prevNote,
searchQuery,
selectedNotePreview,
selectedNoteContent: get(selectedNote, 'data.content'),
selectedNoteId,
Expand Down

0 comments on commit f1fd6dd

Please sign in to comment.