Skip to content

Commit 9646e6a

Browse files
authored
Merge pull request #2725 from StoDevX/extract-animated-searchbox
Remove Course filters from Redux and refactor
2 parents 5529aa9 + 9b6c915 commit 9646e6a

File tree

16 files changed

+463
-470
lines changed

16 files changed

+463
-470
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
"htmlparser2": "3.9.2",
9090
"keyword-search": "0.1.1",
9191
"lodash": "4.17.10",
92+
"mem": "3.0.1",
9293
"moment": "2.22.2",
9394
"moment-timezone": "0.5.21",
9495
"p-props": "1.2.0",
@@ -109,7 +110,7 @@
109110
"react-native-restart": "0.0.6",
110111
"react-native-safari-view": "2.1.0",
111112
"react-native-search-bar": "3.4.2",
112-
"react-native-searchbar": "https://github.com/MosesEsan/react-native-searchbar.git#setValue-function",
113+
"react-native-searchbar-controlled": "1.0.0",
113114
"react-native-tableview-simple": "0.17.5",
114115
"react-native-typography": "1.3.0",
115116
"react-native-vector-icons": "5.0.0",

source/flux/parts/courses.js

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,13 @@ import {
1414
formatFilterCombo,
1515
} from '../../views/sis/course-search/lib/format-filter-combo'
1616

17-
const UPDATE_COURSE_FILTERS = 'courses/UPDATE_COURSE_FILTERS'
1817
const LOAD_CACHED_COURSES = 'courses/LOAD_CACHED_COURSES'
1918
const COURSES_LOADED = 'courses/COURSES_LOADED'
2019

2120
type Dispatch<A: Action> = (action: A | Promise<A> | ThunkAction<A>) => any
2221
type GetState = () => ReduxState
2322
type ThunkAction<A: Action> = (dispatch: Dispatch<A>, getState: GetState) => any
2423

25-
type UpdateCourseFiltersAction = {|
26-
type: 'courses/UPDATE_COURSE_FILTERS',
27-
payload: Array<FilterType>,
28-
|}
29-
export function updateCourseFilters(
30-
filters: FilterType[],
31-
): UpdateCourseFiltersAction {
32-
return {type: UPDATE_COURSE_FILTERS, payload: filters}
33-
}
34-
3524
const UPDATE_RECENT_FILTERS = 'courses/UPDATE_RECENT_FILTERS'
3625

3726
type UpdateRecentFiltersAction = {|
@@ -151,7 +140,6 @@ export function updateRecentSearches(
151140
}
152141

153142
type Action =
154-
| UpdateCourseFiltersAction
155143
| LoadCachedCoursesAction
156144
| CoursesLoadedAction
157145
| UpdateRecentSearchesAction
@@ -160,7 +148,6 @@ type Action =
160148
| LoadRecentFiltersAction
161149

162150
export type State = {|
163-
filters: Array<FilterType>,
164151
allCourses: Array<CourseType>,
165152
readyState: 'not-loaded' | 'ready',
166153
validGEs: string[],
@@ -169,7 +156,6 @@ export type State = {|
169156
|}
170157

171158
const initialState = {
172-
filters: [],
173159
allCourses: [],
174160
readyState: 'not-loaded',
175161
validGEs: [],
@@ -179,9 +165,6 @@ const initialState = {
179165

180166
export function courses(state: State = initialState, action: Action) {
181167
switch (action.type) {
182-
case UPDATE_COURSE_FILTERS:
183-
return {...state, filters: action.payload}
184-
185168
case LOAD_RECENT_FILTERS:
186169
return {...state, recentFilters: action.payload}
187170

source/views/components/filter/filter-view.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {ScrollView, StyleSheet} from 'react-native'
44
import {type FilterType} from './types'
55
import {FilterSection} from './section'
66
import {TableView} from 'react-native-tableview-simple'
7+
import {NoticeView} from '../notice'
78

89
const styles = StyleSheet.create({
910
container: {
@@ -42,7 +43,7 @@ export class FilterView extends React.Component<Props, State> {
4243
}
4344

4445
static getDerivedStateFromProps(props: Props) {
45-
let {initialFilters: filters} = props.navigation.state.params
46+
let {initialFilters: filters = []} = props.navigation.state.params
4647
return {filters}
4748
}
4849

@@ -70,6 +71,10 @@ export class FilterView extends React.Component<Props, State> {
7071
}
7172

7273
render() {
74+
if (!this.state.filters.length) {
75+
return <NoticeView text="No filters available" />
76+
}
77+
7378
const contents = this.state.filters.map(filter => (
7479
<FilterSection
7580
key={filter.key}

source/views/components/searchable-alphabet-listview.js

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,10 @@ const styles = StyleSheet.create({
1414
},
1515
})
1616

17-
type Props = any
17+
type Props = any & {query: string}
1818

19-
export class SearchableAlphabetListView extends React.PureComponent<Props> {
20-
searchBar: any = null
21-
22-
_performSearch = (text: string | Object) => {
23-
// Android clear button returns an object
24-
if (typeof text !== 'string') {
25-
return this.props.onSearch(null)
26-
}
27-
28-
return this.props.onSearch(text)
29-
}
19+
export class SearchableAlphabetListView extends React.Component<Props> {
20+
_performSearch = (text: string) => this.props.onSearch(text)
3021

3122
// We need to make the search run slightly behind the UI,
3223
// so I'm slowing it down by 50ms. 0ms also works, but seems
@@ -36,12 +27,7 @@ export class SearchableAlphabetListView extends React.PureComponent<Props> {
3627
render() {
3728
return (
3829
<View style={styles.wrapper}>
39-
<SearchBar
40-
getRef={ref => (this.searchBar = ref)}
41-
onChangeText={this.performSearch}
42-
// if we don't use the arrow function here, searchBar ref is null...
43-
onSearchButtonPress={() => this.searchBar.unFocus()}
44-
/>
30+
<SearchBar onChange={this.performSearch} value={this.props.query} />
4531
<StyledAlphabetListView
4632
headerHeight={
4733
Platform.OS === 'ios'

source/views/components/searchbar/index.android.js

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
import * as React from 'react'
44
import {StyleSheet} from 'react-native'
55
import * as c from '../colors'
6-
import NativeSearchBar from 'react-native-searchbar'
6+
import NativeSearchBar from 'react-native-searchbar-controlled'
77
import Icon from 'react-native-vector-icons/Ionicons'
8+
import {type Props} from './types'
89

910
const iconStyles = StyleSheet.create({
1011
icon: {
@@ -23,48 +24,37 @@ const styles = StyleSheet.create({
2324
},
2425
})
2526

26-
type Props = {
27-
getRef?: any,
28-
style?: any,
29-
placeholder?: string,
30-
onChangeText: string => any,
31-
onCancel: () => any,
32-
onFocus: () => any,
33-
onSearchButtonPress: string => any,
34-
searchActive: boolean,
35-
}
36-
37-
type State = {
38-
input: string,
39-
}
40-
41-
export class SearchBar extends React.PureComponent<Props, State> {
42-
state = {
43-
input: '',
27+
export class SearchBar extends React.Component<Props> {
28+
static defaultProps = {
29+
active: false,
30+
onCancel: () => {},
31+
onChange: () => {},
32+
onFocus: () => {},
33+
onSubmit: () => {},
34+
placeholder: 'Search',
35+
value: '',
4436
}
4537

46-
updateText = input => {
47-
this.setState({input: input})
48-
}
49-
50-
onSearch = () => {
51-
this.props.onSearchButtonPress(this.state.input)
38+
handleRef = (ref: NativeSearchBar) => {
39+
this.props.getRef && this.props.getRef(ref)
5240
}
5341

5442
render() {
55-
const backButton = this.props.searchActive ? backIcon : searchIcon
43+
let backButton = this.props.active ? backIcon : searchIcon
44+
5645
return (
5746
<NativeSearchBar
58-
ref={this.props.getRef}
47+
ref={this.handleRef}
5948
backButton={backButton}
60-
closeButton={this.props.searchActive ? closeIcon : null}
49+
closeButton={this.props.active ? closeIcon : null}
6150
focusOnLayout={false}
62-
handleChangeText={this.updateText}
63-
hideX={!this.props.searchActive}
51+
handleChangeText={this.props.onChange}
52+
hideClose={!this.props.active}
53+
input={this.props.value}
6454
onBack={this.props.onCancel}
6555
onFocus={this.props.onFocus}
66-
onSubmitEditing={this.onSearch}
67-
placeholder={this.props.placeholder || 'Search'}
56+
onSubmitEditing={this.props.onSubmit}
57+
placeholder={this.props.placeholder}
6858
showOnLoad={true}
6959
style={[styles.searchbar, this.props.style]}
7060
/>

source/views/components/searchbar/index.ios.js

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,40 +4,53 @@ import * as React from 'react'
44
import {StyleSheet} from 'react-native'
55
import NativeSearchBar from 'react-native-search-bar'
66
import * as c from '../colors'
7+
import {type Props} from './types'
78

89
const styles = StyleSheet.create({
910
searchbar: {
1011
height: 44,
1112
},
1213
})
1314

14-
type PropsType = {
15-
getRef?: any,
16-
backgroundColor?: string,
17-
style?: any,
18-
placeholder?: string,
19-
onFocus?: () => any,
20-
onCancel?: () => any,
21-
onChangeText?: string => any,
22-
onSearchButtonPress: string => any,
23-
text?: string,
24-
textFieldBackgroundColor?: string,
25-
}
15+
export class SearchBar extends React.Component<Props> {
16+
static defaultProps = {
17+
backgroundColor: c.iosGray,
18+
onCancel: () => {},
19+
onChange: () => {},
20+
onFocus: () => {},
21+
onSubmit: () => {},
22+
placeholder: 'Search',
23+
textFieldBackgroundColor: c.white,
24+
value: '',
25+
}
26+
27+
_ref: ?NativeSearchBar = null
28+
29+
handleSearchButtonPress = () => {
30+
this._ref && this._ref.blur()
31+
this.props.onSubmit()
32+
}
33+
34+
handleRef = (ref: NativeSearchBar) => {
35+
this._ref = ref
36+
this.props.getRef && this.props.getRef(ref)
37+
}
2638

27-
export const SearchBar = (props: PropsType) => {
28-
return (
29-
<NativeSearchBar
30-
ref={props.getRef}
31-
barTintColor={props.backgroundColor || c.iosGray}
32-
hideBackground={true}
33-
onCancelButtonPress={props.onCancel || (() => {})}
34-
onChangeText={props.onChangeText || (() => {})}
35-
onFocus={props.onFocus || (() => {})}
36-
onSearchButtonPress={props.onSearchButtonPress || (() => {})}
37-
placeholder={props.placeholder || 'Search'}
38-
style={styles.searchbar}
39-
text={props.text || ''}
40-
textFieldBackgroundColor={props.textFieldBackgroundColor || c.white}
41-
/>
42-
)
39+
render() {
40+
return (
41+
<NativeSearchBar
42+
ref={this.handleRef}
43+
barTintColor={this.props.backgroundColor}
44+
hideBackground={true}
45+
onCancelButtonPress={this.props.onCancel}
46+
onChangeText={this.props.onChange}
47+
onFocus={this.props.onFocus}
48+
onSearchButtonPress={this.handleSearchButtonPress}
49+
placeholder={this.props.placeholder}
50+
style={styles.searchbar}
51+
text={this.props.value}
52+
textFieldBackgroundColor={this.props.textFieldBackgroundColor}
53+
/>
54+
)
55+
}
4356
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// @flow
2+
3+
export type Props = {
4+
getRef?: any,
5+
active?: boolean,
6+
backgroundColor?: string,
7+
onCancel: () => any,
8+
onChange: string => any,
9+
onFocus: () => any,
10+
onSubmit: () => any,
11+
placeholder?: string,
12+
style?: any,
13+
textFieldBackgroundColor?: string,
14+
value: string,
15+
}

source/views/dictionary/list.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ export class DictionaryView extends React.PureComponent<Props, State> {
125125
<ListSeparator key={`${sectionId}-${rowId}`} />
126126
)
127127

128-
performSearch = (text: ?string) => {
129-
this.setState(() => ({query: text ? text.toLowerCase() : ''}))
128+
performSearch = (text: string) => {
129+
this.setState(() => ({query: text}))
130130
}
131131

132132
render() {
@@ -139,7 +139,8 @@ export class DictionaryView extends React.PureComponent<Props, State> {
139139

140140
let results = this.state.allTerms
141141
if (this.state.query) {
142-
const {query, allTerms} = this.state
142+
let {query, allTerms} = this.state
143+
query = query.toLowerCase()
143144
results = allTerms.filter(term =>
144145
termToArray(term).some(word => word.startsWith(query)),
145146
)
@@ -154,6 +155,7 @@ export class DictionaryView extends React.PureComponent<Props, State> {
154155
}
155156
data={groupBy(results, item => item.word[0])}
156157
onSearch={this.performSearch}
158+
query={this.state.query}
157159
refreshControl={refreshControl}
158160
renderSeparator={this.renderSeparator}
159161
sectionHeader={this.renderSectionHeader}

0 commit comments

Comments
 (0)