Skip to content

Commit dfcb70b

Browse files
committed
clean up the Webcams view and make it respond to rotations
1 parent e559b55 commit dfcb70b

File tree

1 file changed

+71
-75
lines changed

1 file changed

+71
-75
lines changed

source/views/streaming/webcams.js

Lines changed: 71 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -14,136 +14,129 @@ import {
1414
Dimensions,
1515
Platform,
1616
} from 'react-native'
17+
import {Column} from '../components/layout'
1718
import {TabBarIcon} from '../components/tabbar-icon'
1819
import {Touchable} from '../components/touchable'
1920
import * as c from '../components/colors'
20-
import {data as webcams} from '../../../docs/webcams.json'
21+
import * as defaultData from '../../../docs/webcams.json'
2122
import {webcamImages} from '../../../images/webcam-images'
2223
import {trackedOpenUrl} from '../components/open-url'
2324
import LinearGradient from 'react-native-linear-gradient'
25+
import {partitionByIndex} from '../../lib/partition-by-index'
26+
27+
type WebcamType = {
28+
streamUrl: string,
29+
pageUrl: string,
30+
name: string,
31+
thumbnail: string,
32+
accentColor: [number, number, number],
33+
}
34+
35+
type DProps = {
36+
webcams: Array<WebcamType>,
37+
}
38+
39+
type Props = {
40+
webcams: Array<WebcamType>,
41+
}
2442

25-
export default class WebcamsView extends React.PureComponent {
43+
type State = {
44+
width: number,
45+
}
46+
47+
export class WebcamsView extends React.PureComponent<DProps, Props, State> {
2648
static navigationOptions = {
2749
tabBarLabel: 'Webcams',
2850
tabBarIcon: TabBarIcon('videocam'),
2951
}
3052

31-
render() {
32-
return (
33-
<ScrollView
34-
automaticallyAdjustContentInsets={false}
35-
contentInset={{bottom: 49}}
36-
contentContainerStyle={styles.gridWrapper}
37-
>
38-
{webcams.map(webcam => <Webcam key={webcam.name} info={webcam} />)}
39-
</ScrollView>
40-
)
53+
static defaultProps = {
54+
webcams: defaultData.data,
4155
}
42-
}
4356

44-
class Webcam extends React.PureComponent {
45-
props: {
46-
info: {
47-
streamUrl: string,
48-
pageUrl: string,
49-
name: string,
50-
thumbnail: string,
51-
accentColor: [number, number, number],
52-
},
57+
state = {
58+
width: Dimensions.get('window').width,
59+
}
60+
61+
componentWillMount() {
62+
Dimensions.addEventListener('change', this.handleResizeEvent)
63+
}
64+
65+
componentWillUnmount() {
66+
Dimensions.removeEventListener('change', this.handleResizeEvent)
67+
}
68+
69+
handleResizeEvent = (event: {window: {width: number}}) => {
70+
this.setState(() => ({width: event.window.width}))
5371
}
5472

5573
render() {
56-
const {name, thumbnail, streamUrl, pageUrl, accentColor} = this.props.info
74+
const columns = partitionByIndex(this.props.webcams)
5775

5876
return (
59-
<StreamThumbnail
60-
accentColor={accentColor}
61-
textColor="white"
62-
thumbnail={webcamImages[thumbnail]}
63-
title={name}
64-
url={streamUrl}
65-
infoUrl={pageUrl}
66-
/>
77+
<ScrollView contentContainerStyle={styles.gridWrapper}>
78+
{columns.map((contents, i) =>
79+
<Column key={i} style={styles.column}>
80+
{contents.map(webcam =>
81+
<StreamThumbnail
82+
key={webcam.name}
83+
webcam={webcam}
84+
textColor="white"
85+
viewportWidth={this.state.width}
86+
/>,
87+
)}
88+
</Column>,
89+
)}
90+
</ScrollView>
6791
)
6892
}
6993
}
7094

7195
class StreamThumbnail extends React.PureComponent {
7296
props: {
73-
url: string,
74-
infoUrl: string,
75-
title: string,
76-
accentColor: [number, number, number],
97+
webcam: WebcamType,
7798
textColor: 'white' | 'black',
78-
thumbnail: any,
99+
viewportWidth: number,
79100
}
80101

81102
handlePress = () => {
82-
const {url, title, infoUrl} = this.props
103+
const {streamUrl, name, pageUrl} = this.props.webcam
83104
if (Platform.OS === 'android') {
84-
trackedOpenUrl({url: infoUrl, id: `${title}WebcamView`})
105+
trackedOpenUrl({url: pageUrl, id: `${name}WebcamView`})
85106
} else {
86-
trackedOpenUrl({url, id: `${title}WebcamView`})
107+
trackedOpenUrl({url: streamUrl, id: `${name}WebcamView`})
87108
}
88109
}
89110

90111
render() {
91-
const {title, thumbnail, accentColor, textColor} = this.props
92-
93-
return (
94-
<RoundedThumbnail
95-
accentColor={accentColor}
96-
onPress={this.handlePress}
97-
textColor={textColor}
98-
thumbnail={thumbnail}
99-
title={title}
100-
/>
101-
)
102-
}
103-
}
104-
105-
class RoundedThumbnail extends React.PureComponent {
106-
props: {
107-
accentColor: [number, number, number],
108-
onPress: () => any,
109-
textColor: 'white' | 'black',
110-
thumbnail: any,
111-
title: string,
112-
}
113-
114-
render() {
115-
const {title, thumbnail, accentColor, textColor} = this.props
112+
const {textColor, viewportWidth} = this.props
113+
const {name, thumbnail, accentColor} = this.props.webcam
116114

117115
const [r, g, b] = accentColor
118116
const baseColor = `rgba(${r}, ${g}, ${b}, 1)`
119117
const startColor = `rgba(${r}, ${g}, ${b}, 0.1)`
120118
const actualTextColor = c[textColor]
121119

122-
const screenWidth = Dimensions.get('window').width
123-
124-
const width = screenWidth / 2 - CELL_MARGIN * 1.5
120+
const width = viewportWidth / 2 - CELL_MARGIN * 1.5
125121
const cellRatio = 2.15625
126122
const height = width / cellRatio
127123

128-
const style = {width, height}
129-
130124
return (
131-
<View style={[style, styles.cell, styles.rounded]}>
125+
<View style={[styles.cell, styles.rounded, {width, height}]}>
132126
<Touchable
133127
highlight={true}
134128
underlayColor={baseColor}
135129
activeOpacity={0.7}
136-
onPress={this.props.onPress}
137-
style={styles.rounded}
130+
onPress={this.handlePress}
138131
>
139-
<Image source={thumbnail} style={[styles.image, styles.rounded]}>
132+
<Image source={webcamImages[thumbnail]} style={[styles.image]}>
140133
<View style={styles.titleWrapper}>
141134
<LinearGradient
142135
colors={[startColor, baseColor]}
143136
locations={[0, 0.8]}
144137
>
145138
<Text style={[styles.titleText, {color: actualTextColor}]}>
146-
{title}
139+
{name}
147140
</Text>
148141
</LinearGradient>
149142
</View>
@@ -157,12 +150,15 @@ class RoundedThumbnail extends React.PureComponent {
157150
const CELL_MARGIN = 10
158151

159152
const styles = StyleSheet.create({
153+
column: {
154+
flex: 1,
155+
},
160156
gridWrapper: {
161157
marginHorizontal: CELL_MARGIN / 2,
162158
marginTop: CELL_MARGIN / 2,
163159
paddingBottom: CELL_MARGIN / 2,
164160

165-
alignItems: 'flex-start',
161+
alignItems: 'center',
166162
justifyContent: 'center',
167163
flexDirection: 'row',
168164
flexWrap: 'wrap',

0 commit comments

Comments
 (0)