Skip to content

Commit

Permalink
Move Search state to redux (#1881)
Browse files Browse the repository at this point in the history
This moves the search state to Redux from flux.

Removed ref prop that wasn't being used
Renamed filter to searchQuery which better describes what it is and increases the ability to find instances of where it is used in the future.
Removed props from components that only pass them through
  • Loading branch information
belcherj committed Feb 13, 2020
1 parent d2d7f04 commit d28c963
Show file tree
Hide file tree
Showing 14 changed files with 161 additions and 138 deletions.
7 changes: 0 additions & 7 deletions lib/flux/app-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ const toggleSystemTag = (
};

const initialState: AppState = {
filter: '',
previousIndex: -1,
notes: null,
tags: [],
Expand Down Expand Up @@ -179,12 +178,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 @@ -55,8 +54,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 @@ -177,7 +174,6 @@ export class NoteDetail extends Component {
render() {
const {
note,
filter,
fontSize,
previewingMarkdown,
spellCheckEnabled,
Expand Down Expand Up @@ -214,13 +210,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 @@ -234,7 +228,6 @@ export class NoteDetail extends Component {

const mapStateToProps = ({ appState: state, ui, settings }) => ({
dialogs: state.dialogs,
filter: state.filter,
note: state.revision || ui.note,
showNoteInfo: state.showNoteInfo,
spellCheckEnabled: settings.spellCheckEnabled,
Expand Down
3 changes: 0 additions & 3 deletions lib/note-editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export class NoteEditor extends Component<Props> {
closeNote: PropTypes.func.isRequired,
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 @@ -148,7 +147,6 @@ export class NoteEditor extends Component<Props> {
<NoteDetail
storeFocusEditor={this.storeFocusEditor}
storeHasFocus={this.storeEditorHasFocus}
filter={this.props.filter}
noteBucket={noteBucket}
previewingMarkdown={this.markdownEnabled() && !editMode}
onChangeContent={this.props.onUpdateContent}
Expand All @@ -175,7 +173,6 @@ const mapStateToProps: S.MapState<StateProps> = ({
ui: { note, editMode },
}) => ({
allTags: state.tags,
filter: state.filter,
fontSize: settings.fontSize,
editMode,
isEditorActive: !state.showNavigation,
Expand Down
47 changes: 15 additions & 32 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,32 +338,16 @@ export class NoteList extends Component<Props> {
}

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

if (
prevProps.filter !== this.props.filter ||
prevProps.searchQuery !== searchQuery ||
prevProps.noteDisplay !== this.props.noteDisplay ||
prevProps.notes !== notes ||
prevProps.selectedNoteContent !== this.props.selectedNoteContent
) {
this.recomputeHeights();
}

// Deselect the currently selected note if it doesn't match the search query
if (filter !== prevProps.filter) {
const selectedNotePassesFilter = notes.some(
note => note.id === selectedNoteId
);
if (!selectedNotePassesFilter) {
closeNote();
}
}
}

componentWillUnmount() {
Expand Down Expand Up @@ -413,7 +396,7 @@ export class NoteList extends Component<Props> {

render() {
const {
filter,
searchQuery,
hasLoaded,
selectedNoteId,
onNoteOpened,
Expand All @@ -429,7 +412,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 @@ -474,7 +457,7 @@ export class NoteList extends Component<Props> {
notes={notes}
rowCount={notes.length}
rowHeight={getRowHeight(notes, {
filter,
searchQuery,
noteDisplay,
tagResultsFound,
width,
Expand Down Expand Up @@ -506,10 +489,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 @@ -524,7 +507,7 @@ const mapStateToProps: S.MapState<StateProps> = ({

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

Expand Down Expand Up @@ -552,12 +535,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 d28c963

Please sign in to comment.