Skip to content

Commit a50cc6c

Browse files
Implement a basic search UI
1 parent 325158c commit a50cc6c

File tree

6 files changed

+139
-2
lines changed

6 files changed

+139
-2
lines changed

src/app.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,19 @@ import { Navigator } from 'react-native'
33
import { setTheme, MKColor } from 'react-native-material-kit'
44
import HomeScreen from './screens/HomeScreen'
55
import PlaylistScreen from './screens/PlaylistScreen'
6+
import SearchStore from './stores/SearchStore'
7+
import SearchScreen from './screens/SearchScreen'
68
import SettingsScreen from './screens/SettingsScreen'
79
import SettingsStore from './stores/SettingsStore'
810
import ThemeStore from './stores/ThemeStore'
911
import TrackStore from './stores/TrackStore'
1012
import WebSocketStore from './stores/WebSocketStore'
1113

14+
const searchStore = new SearchStore()
1215
const settingsStore = new SettingsStore()
1316
const themeStore = new ThemeStore()
1417
const trackStore = new TrackStore()
15-
const webSocketStore = new WebSocketStore(trackStore, themeStore)
18+
const webSocketStore = new WebSocketStore(trackStore, themeStore, searchStore)
1619

1720
setTheme({
1821
primaryColor: MKColor.Orange,
@@ -51,6 +54,9 @@ export default class App extends Component {
5154
case 'settings': {
5255
return (<SettingsScreen navigator={navigator} settingsStore={settingsStore} themeStore={themeStore} />)
5356
}
57+
case 'search': {
58+
return (<SearchScreen navigator={navigator} themeStore={themeStore} webSocketStore={webSocketStore} searchStore={searchStore} />)
59+
}
5460
default:
5561
case 'remote': {
5662
return (<HomeScreen trackStore={trackStore} webSocketStore={webSocketStore} navigator={navigator} settingsStore={settingsStore} themeStore={themeStore} />)

src/components/Toolbar.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ export default class Toolbar extends Component {
1616
_actionSelected = (actionIndex) => {
1717
switch (actionIndex) {
1818
case 0: {
19+
this.props.navigator.push({
20+
name: 'search'
21+
})
22+
break
23+
}
24+
case 1: {
1925
this.props.navigator.push({
2026
name: 'settings'
2127
})
@@ -34,6 +40,9 @@ export default class Toolbar extends Component {
3440
render () {
3541
const { color, title, settingsMenu, showDrawer, drawerFunction } = this.props
3642
const actions = [
43+
{
44+
title: 'Search'
45+
},
3746
{
3847
title: 'Settings'
3948
}

src/screens/SearchScreen.js

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import React, { Component, PropTypes } from 'react'
2+
import { ScrollView, StatusBar, StyleSheet, TextInput, View } from 'react-native'
3+
import { observer } from 'mobx-react/native'
4+
// import Zeroconf from 'react-native-zeroconf'
5+
import Toolbar from '../components/Toolbar'
6+
import SongList from '../components/SongList'
7+
8+
@observer
9+
export default class SearchScreen extends Component {
10+
static propTypes = {
11+
navigator: PropTypes.object,
12+
searchStore: PropTypes.object,
13+
settingsStore: PropTypes.object,
14+
themeStore: PropTypes.object,
15+
webSocketStore: PropTypes.object
16+
}
17+
18+
constructor (...args) {
19+
super(...args)
20+
this.state = {
21+
searchText: ''
22+
}
23+
}
24+
25+
_handleTrackPress = (track) => {
26+
const searchText = this.props.searchStore.searchText
27+
return () => {
28+
this.props.webSocketStore.sendSearchAndPlayResult(searchText, track)
29+
}
30+
}
31+
32+
_updateSearchText = (searchText) => {
33+
this.props.searchStore.setSearchText(searchText)
34+
}
35+
36+
_search = () => {
37+
this.props.webSocketStore.sendSearch(this.props.searchStore.searchText)
38+
}
39+
40+
render () {
41+
const { searchStore, themeStore } = this.props
42+
return (
43+
<View style={[styles.container, { backgroundColor: themeStore.backgroundColor() }]}>
44+
<StatusBar animated backgroundColor={themeStore.barColor()} />
45+
<Toolbar title={'Search'} navigator={this.props.navigator} color={themeStore.barColor()} />
46+
<View style={styles.content}>
47+
<View style={styles.settingsContent}>
48+
<TextInput
49+
style={{ color: themeStore.foreColor() }}
50+
autoCorrect={true}
51+
defaultValue={searchStore.searchText}
52+
keyboardType="web-search"
53+
underlineColorAndroid={themeStore.highlightColor()}
54+
placeholder="Search text here..."
55+
placeholderTextColor={themeStore.foreColor()}
56+
onChangeText={this._updateSearchText}
57+
onSubmitEditing={this._search}
58+
/>
59+
</View>
60+
<ScrollView>
61+
<SongList black={!(themeStore.themeEnabled && themeStore.themeType === 'FULL')} data={searchStore.trackDataStore} handlePress={this._handleTrackPress} />
62+
</ScrollView>
63+
</View>
64+
</View>
65+
)
66+
}
67+
}
68+
69+
const styles = StyleSheet.create({
70+
container: {
71+
flex: 1,
72+
alignSelf: 'stretch'
73+
},
74+
content: {
75+
flex: 1
76+
},
77+
controlBar: {
78+
flex: 0,
79+
height: 100,
80+
elevation: 4
81+
},
82+
settingsContent: {
83+
margin: 20
84+
}
85+
})

src/screens/SettingsScreen.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export default class SettingsScreen extends Component {
3636
keyboardType="numeric"
3737
underlineColorAndroid={themeStore.highlightColor()}
3838
placeholder="GPMDP IP Address"
39+
placeholderTextColor={themeStore.foreColor()}
3940
onChangeText={this._ipChanged}
4041
/>
4142
</View>

src/stores/SearchStore.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { observable } from 'mobx'
2+
import { ListView } from 'react-native'
3+
4+
export default class SearchStore {
5+
@observable searchText = ''
6+
@observable albums = []
7+
@observable artists = []
8+
tracks = []
9+
@observable trackDataStore = new ListView.DataSource({ rowHasChanged: (r1, r2) => JSON.stringify(r1) !== JSON.stringify(r2) })
10+
11+
setSearchText = (newSearchText) => {
12+
this.searchText = newSearchText
13+
}
14+
15+
setSearchResults = (results) => {
16+
this.albums = results.albums
17+
this.artists = results.artists
18+
this.tracks = results.tracks
19+
this.trackDataStore = this.trackDataStore.cloneWithRows(this.tracks.map((track) => Object.assign({}, track, { duration: track.duration * 1000 })))
20+
}
21+
}

src/stores/WebSocketStore.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const TEST_IP_ADDRESS = '192.168.1.60'
66
export const TEST_PORT = 5672
77

88
export default class WebSocketStore {
9+
searchStore
910
themeStore
1011
trackStore
1112
@observable ipAddress
@@ -16,7 +17,8 @@ export default class WebSocketStore {
1617
@observable lastMessage = null
1718
shouldReconnect = false
1819

19-
constructor (trackStore, themeStore, port = TEST_PORT) {
20+
constructor (trackStore, themeStore, searchStore, port = TEST_PORT) {
21+
this.searchStore = searchStore
2022
this.trackStore = trackStore
2123
this.themeStore = themeStore
2224
this.port = port
@@ -144,6 +146,11 @@ export default class WebSocketStore {
144146
this.trackStore.updateQueue(payload)
145147
break
146148
}
149+
case 'search-results': {
150+
this.searchStore.setSearchText(payload.searchText)
151+
this.searchStore.setSearchResults(payload)
152+
break
153+
}
147154
case 'settings:theme': {
148155
this.themeStore.setThemeEnabled(payload)
149156
this.trackStore.forceUpdatePlaylists()
@@ -202,6 +209,14 @@ export default class WebSocketStore {
202209
this._sendMessage({ namespace: 'playback', method: 'toggleRepeat' })
203210
}
204211

212+
sendSearch = (searchText) => {
213+
this._sendMessage({ namespace: 'search', method: 'performSearch', arguments: [searchText] })
214+
}
215+
216+
sendSearchAndPlayResult = (searchText, result) => {
217+
this._sendMessage({ namespace: 'search', method: 'performSearchAndPlayResult', arguments: [searchText, result] })
218+
}
219+
205220
sendSetTime = (time) => {
206221
this._sendMessage({ namespace: 'playback', method: 'setPlaybackTime', arguments: [time] })
207222
this.trackStore.stop()

0 commit comments

Comments
 (0)