Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: Replace search field focus state with middleware #1914

Merged
merged 2 commits into from
Feb 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion desktop/menus/edit-menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const buildEditMenu = settings => {
{
label: 'Search &Notes…',
accelerator: 'CommandOrControl+F',
click: appCommandSender({ action: 'setSearchFocus' }),
click: appCommandSender({ action: 'focusSearchField' }),
},
{
type: 'separator',
Expand Down
8 changes: 6 additions & 2 deletions lib/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export type OwnProps = {
export type DispatchProps = {
createNote: () => any;
closeNote: () => any;
focusSearchField: () => any;
selectNote: (note: T.NoteEntity) => any;
};

Expand Down Expand Up @@ -107,8 +108,7 @@ const mapDispatchToProps: S.MapDispatch<
resetAuth: () => dispatch(reduxActions.auth.reset()),
selectNote: (note: T.NoteEntity) => dispatch(actions.ui.selectNote(note)),
setAuthorized: () => dispatch(reduxActions.auth.setAuthorized()),
setSearchFocus: () =>
dispatch(actionCreators.setSearchFocus({ searchFocus: true })),
focusSearchField: () => dispatch(actions.ui.focusSearchField()),
setSimperiumConnectionStatus: connected =>
dispatch(toggleSimperiumConnectionStatus(connected)),
selectNote: note => dispatch(actions.ui.selectNote(note)),
Expand Down Expand Up @@ -254,6 +254,10 @@ export const App = connect(
return window.print();
}

if ('focusSearchField' === command.action) {
return this.props.focusSearchField();
}

const canRun = overEvery(
isObject,
o => o.action !== null,
Expand Down
7 changes: 0 additions & 7 deletions lib/flux/app-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ const initialState: AppState = {
showNavigation: false,
dialogs: [],
nextDialogKey: 0,
searchFocus: false,
unsyncedNoteIds: [], // note bucket only
};

Expand Down Expand Up @@ -277,12 +276,6 @@ export const actionMap = new ActionMap({
});
},

setSearchFocus(state: AppState, { searchFocus = true }) {
return update(state, {
searchFocus: { $set: searchFocus },
});
},

markdownNote: {
creator({ noteBucket, note, markdown: shouldEnableMarkdown }) {
const updated = toggleSystemTag(note, 'markdown', shouldEnableMarkdown);
Expand Down
35 changes: 23 additions & 12 deletions lib/search-field/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, { Component, createRef, FormEvent, KeyboardEvent } from 'react';
import { connect } from 'react-redux';
import SmallCrossIcon from '../icons/cross-small';
import appState from '../flux/app-state';
import { tracks } from '../analytics';
import { State } from '../state';
import { search } from '../state/ui/actions';

const { setSearchFocus } = appState.actionCreators;
import { registerSearchField } from '../state/ui/search-field-middleware';

const { recordEvent } = tracks;
const KEY_ESC = 27;

Expand All @@ -18,20 +18,33 @@ export class SearchField extends Component<ConnectedProps> {

inputField = createRef<HTMLInputElement>();

componentDidUpdate() {
const { searchFocus, onSearchFocused } = this.props;
componentDidMount() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we are making a mistake adding more componentDidMounts to the app, at very least this should be: UNSAFE_componentWillMount

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That being said, let's merge this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad DidMount is fine.

registerSearchField(this.focus);
}

blur = () => {
if (!this.inputField.current) {
return;
}

this.inputField.current.blur();
};

focus = (operation = 'focus-only') => {
if (!this.inputField.current) {
return;
}

if (searchFocus && this.inputField.current) {
if ('select' === operation) {
this.inputField.current.select();
this.inputField.current.focus();
onSearchFocused();
}
}
this.inputField.current.focus();
};

interceptEsc = (event: KeyboardEvent) => {
if (KEY_ESC === event.keyCode) {
if (this.props.searchQuery === '' && this.inputField.current) {
this.inputField.current.blur();
if (this.props.searchQuery === '') {
this.blur();
}
this.clearQuery();
}
Expand Down Expand Up @@ -82,7 +95,6 @@ const mapStateToProps = ({
}: State) => ({
isTagSelected: !!state.tag,
placeholder: listTitle,
searchFocus: state.searchFocus,
searchQuery,
});

Expand All @@ -91,7 +103,6 @@ const mapDispatchToProps = dispatch => ({
dispatch(search(query));
recordEvent('list_notes_searched');
},
onSearchFocused: () => dispatch(setSearchFocus({ searchFocus: false })),
});

export default connect(mapStateToProps, mapDispatchToProps)(SearchField);
3 changes: 2 additions & 1 deletion lib/state/action-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export type SetWPToken = Action<'setWPToken', { token: string }>;
export type CreateNote = Action<'CREATE_NOTE'>;
export type CloseNote = Action<'CLOSE_NOTE'>;
export type FilterNotes = Action<'FILTER_NOTES', { notes: T.NoteEntity[] }>;
export type FocusSearchField = Action<'FOCUS_SEARCH_FIELD'>;
export type Search = Action<'SEARCH', { searchQuery: string }>;
export type SetAuth = Action<'AUTH_SET', { status: AuthState }>;
export type SetUnsyncedNoteIds = Action<
Expand All @@ -76,6 +77,7 @@ export type ActionType =
| CloseNote
| LegacyAction
| FilterNotes
| FocusSearchField
| Search
| SelectNote
| SetAccountName
Expand Down Expand Up @@ -191,7 +193,6 @@ type LegacyAction =
| Action<'App.selectTagAndSElectFirstNote'>
| Action<'App.selectTrash'>
| Action<'App.setRevision', { revision: T.NoteEntity }>
| Action<'App.setSearchFocus', { searchFocus: boolean }>
| Action<'App.setShouldPrintNote', { shouldPrint: boolean }>
| Action<'App.setUnsyncedNoteIds', { noteIds: T.EntityId[] }>
| Action<'App.showAllNotes'>
Expand Down
4 changes: 2 additions & 2 deletions lib/state/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { omit } from 'lodash';
import appState from '../flux/app-state';

import uiMiddleware from './ui/middleware';
import searchFieldMiddleware from './ui/search-field-middleware';

import auth from './auth/reducer';
import settings from './settings/reducer';
Expand All @@ -35,7 +36,6 @@ export type AppState = {
preferences?: T.Preferences;
previousIndex: number;
revision: T.NoteEntity | null;
searchFocus: boolean;
showNavigation: boolean;
tags: T.TagEntity[];
tag?: T.TagEntity;
Expand Down Expand Up @@ -66,7 +66,7 @@ export const store = createStore<State, A.ActionType, {}, {}>(
[path]: omit(state[path], 'focusModeEnabled'),
}),
}),
applyMiddleware(thunk, uiMiddleware)
applyMiddleware(thunk, uiMiddleware, searchFieldMiddleware)
)
);

Expand Down
4 changes: 4 additions & 0 deletions lib/state/ui/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ export const filterNotes: A.ActionCreator<A.FilterNotes> = (
notes,
});

export const focusSearchField: A.ActionCreator<A.FocusSearchField> = () => ({
type: 'FOCUS_SEARCH_FIELD',
});

export const setUnsyncedNoteIds: A.ActionCreator<A.SetUnsyncedNoteIds> = (
noteIds: T.EntityId[]
) => ({
Expand Down
26 changes: 26 additions & 0 deletions lib/state/ui/search-field-middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as A from '../action-types';
import * as S from '../';

const searchFields = new Set<Function>();

export const registerSearchField = (focus: Function) => searchFields.add(focus);

export const middleware: S.Middleware = () => {
return next => (action: A.ActionType) => {
const result = next(action);

switch (action.type) {
case 'SEARCH':
searchFields.forEach(focus => focus());
break;

case 'FOCUS_SEARCH_FIELD':
searchFields.forEach(focus => focus('select'));
break;
}

return result;
};
};

export default middleware;
3 changes: 0 additions & 3 deletions lib/tag-suggestions/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import React, { Component, Fragment } from 'react';
import { connect } from 'react-redux';
import appState from '../flux/app-state';
import { tracks } from '../analytics';
import { search } from '../state/ui/actions';
import filterAtMost from '../utils/filter-at-most';

import * as S from '../state';
import * as T from '../types';

const { setSearchFocus } = appState.actionCreators;
const { recordEvent } = tracks;

type StateProps = {
Expand Down Expand Up @@ -121,7 +119,6 @@ const mapDispatchToProps: S.MapDispatch<DispatchProps> = dispatch => ({
onSearch: query => {
dispatch(search(query));
recordEvent('list_notes_searched');
dispatch(setSearchFocus({ searchFocus: true }));
},
});

Expand Down