@@ -14,136 +14,129 @@ import {
1414 Dimensions ,
1515 Platform ,
1616} from 'react-native'
17+ import { Column } from '../components/layout'
1718import { TabBarIcon } from '../components/tabbar-icon'
1819import { Touchable } from '../components/touchable'
1920import * as c from '../components/colors'
20- import { data as webcams } from '../../../docs/webcams.json'
21+ import * as defaultData from '../../../docs/webcams.json'
2122import { webcamImages } from '../../../images/webcam-images'
2223import { trackedOpenUrl } from '../components/open-url'
2324import 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
7195class 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 {
157150const CELL_MARGIN = 10
158151
159152const 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