22
33import * as React from 'react'
44import {
5- Dimensions ,
6- Image ,
7- ScrollView ,
8- StyleSheet ,
9- Text ,
10- View ,
5+ Dimensions ,
6+ Image ,
7+ ScrollView ,
8+ StyleSheet ,
9+ Text ,
10+ View ,
11+ Platform ,
1112} from 'react-native'
13+ import noop from 'lodash/noop'
1214import * as c from '../../components/colors'
1315import { TabBarIcon } from '../../components/tabbar-icon'
1416import { callPhone } from '../../components/call-phone'
@@ -17,9 +19,11 @@ import type {TopLevelViewPropsType} from '../../types'
1719import { StreamPlayer } from './player'
1820import type { PlayState , HtmlAudioError , Viewport } from './types'
1921import { ActionButton , ShowCalendarButton , CallButton } from './buttons'
22+ import { openUrl } from '../../components/open-url'
2023
2124const image = require ( '../../../../images/streaming/ksto/ksto-logo.png' )
2225const stationNumber = '+15077863602'
26+ const kstoLiveUrl = 'https://www.stolaf.edu/multimedia/play/embed/ksto.html'
2327
2428type Props = TopLevelViewPropsType
2529
@@ -31,152 +35,168 @@ type State = {
3135}
3236
3337export class KSTOView extends React . PureComponent < Props , State > {
34- static navigationOptions = {
35- tabBarLabel : 'KSTO' ,
36- tabBarIcon : TabBarIcon ( 'radio' ) ,
37- }
38-
39- state = {
40- playState : 'paused' ,
41- streamError : null ,
42- uplinkError : null ,
43- viewport : Dimensions . get ( 'window' ) ,
44- }
45-
46- componentWillMount ( ) {
47- Dimensions . addEventListener ( 'change' , this . handleResizeEvent )
48- }
49-
50- componentWillUnmount ( ) {
51- Dimensions . removeEventListener ( 'change' , this . handleResizeEvent )
52- }
53-
54- handleResizeEvent = ( event : { window : { width : number , height : number } } ) => {
55- this . setState ( ( ) => ( { viewport : event . window } ) )
56- }
57-
58- play = ( ) => {
59- this . setState ( ( ) => ( { playState : 'checking' } ) )
60- }
61-
62- pause = ( ) => {
63- this . setState ( ( ) => ( { playState : 'paused' } ) )
64- }
65-
66- handleStreamPlay = ( ) => {
67- this . setState ( ( ) => ( { playState : 'playing' } ) )
68- }
69-
70- handleStreamPause = ( ) => {
71- this . setState ( ( ) => ( { playState : 'paused' } ) )
72- }
73-
74- handleStreamEnd = ( ) => {
75- this . setState ( ( ) => ( { playState : 'paused' } ) )
76- }
77-
78- handleStreamError = ( e : { code : number , message : string } ) => {
79- this . setState ( ( ) => ( { streamError : e , playState : 'paused' } ) )
80- }
81-
82- openSchedule = ( ) => {
83- this . props . navigation . navigate ( 'KSTOScheduleView' )
84- }
85-
86- callStation = ( ) => {
87- callPhone ( stationNumber )
88- }
89-
90- renderPlayButton = ( state : PlayState ) => {
91- switch ( state ) {
92- case 'paused' :
93- return (
94- < ActionButton icon = "ios-play" onPress = { this . play } text = "Listen" />
95- )
96-
97- case 'checking' :
98- return (
99- < ActionButton icon = "ios-more" onPress = { this . pause } text = "Starting" />
100- )
101-
102- case 'playing' :
103- return (
104- < ActionButton icon = "ios-pause" onPress = { this . pause } text = "Pause" />
105- )
106-
107- default :
108- return < ActionButton icon = "ios-bug" onPress = { ( ) => { } } text = "Error" />
109- }
110- }
111-
112- render ( ) {
113- const sideways = this . state . viewport . width > this . state . viewport . height
114-
115- const logoWidth = Math . min (
116- this . state . viewport . width / 1.5 ,
117- this . state . viewport . height / 1.75 ,
118- )
119-
120- const logoSize = {
121- width : logoWidth ,
122- height : logoWidth ,
123- }
124-
125- const error = this . state . uplinkError ? (
126- < Text style = { styles . status } > { this . state . uplinkError } </ Text >
127- ) : this . state . streamError ? (
128- < Text style = { styles . status } >
129- Error Code { this . state . streamError . code } :{ ' ' }
130- { this . state . streamError . message }
131- </ Text >
132- ) : null
133-
134- return (
135- < ScrollView
136- contentContainerStyle = { [ styles . root , sideways && landscape . root ] }
137- >
138- < View style = { [ styles . logoWrapper , sideways && landscape . logoWrapper ] } >
139- < Image
140- resizeMode = "contain"
141- source = { image }
142- style = { [ styles . logo , logoSize ] }
143- />
144- </ View >
145-
146- < View style = { styles . container } >
147- < View style = { styles . titleWrapper } >
148- < Text selectable = { true } style = { styles . heading } >
149- St. Olaf College Radio
150- </ Text >
151- < Text selectable = { true } style = { styles . subHeading } >
152- KSTO 93.1 FM
153- </ Text >
154-
155- { error }
156- </ View >
157-
158- < Row >
159- { this . renderPlayButton ( this . state . playState ) }
160- < View style = { styles . spacer } />
161- < CallButton onPress = { this . callStation } />
162- < View style = { styles . spacer } />
163- < ShowCalendarButton onPress = { this . openSchedule } />
164- </ Row >
165-
166- < StreamPlayer
167- onEnded = { this . handleStreamEnd }
168- // onWaiting={this.handleStreamWait}
169- onError = { this . handleStreamError }
170- // onStalled={this.handleStreamStall}
171- onPause = { this . handleStreamPause }
172- onPlay = { this . handleStreamPlay }
173- playState = { this . state . playState }
174- style = { styles . webview }
175- />
176- </ View >
177- </ ScrollView >
178- )
179- }
38+ static navigationOptions = {
39+ tabBarLabel : 'KSTO' ,
40+ tabBarIcon : TabBarIcon ( 'radio' ) ,
41+ }
42+
43+ state = {
44+ playState : 'paused' ,
45+ streamError : null ,
46+ uplinkError : null ,
47+ viewport : Dimensions . get ( 'window' ) ,
48+ }
49+
50+ componentWillMount ( ) {
51+ Dimensions . addEventListener ( 'change' , this . handleResizeEvent )
52+ }
53+
54+ componentWillUnmount ( ) {
55+ Dimensions . removeEventListener ( 'change' , this . handleResizeEvent )
56+ }
57+
58+ handleResizeEvent = ( event : { window : { width : number , height : number } } ) => {
59+ this . setState ( ( ) => ( { viewport : event . window } ) )
60+ }
61+
62+ play = ( ) => {
63+ this . setState ( ( ) => ( { playState : 'checking' } ) )
64+ }
65+
66+ pause = ( ) => {
67+ this . setState ( ( ) => ( { playState : 'paused' } ) )
68+ }
69+
70+ handleStreamPlay = ( ) => {
71+ this . setState ( ( ) => ( { playState : 'playing' } ) )
72+ }
73+
74+ handleStreamPause = ( ) => {
75+ this . setState ( ( ) => ( { playState : 'paused' } ) )
76+ }
77+
78+ handleStreamEnd = ( ) => {
79+ this . setState ( ( ) => ( { playState : 'paused' } ) )
80+ }
81+
82+ handleStreamError = ( e : { code : number , message : string } ) => {
83+ this . setState ( ( ) => ( { streamError : e , playState : 'paused' } ) )
84+ }
85+
86+ openSchedule = ( ) => {
87+ this . props . navigation . navigate ( 'KSTOScheduleView' )
88+ }
89+
90+ callStation = ( ) => {
91+ callPhone ( stationNumber )
92+ }
93+
94+ openStreamWebsite = ( ) => {
95+ openUrl ( kstoLiveUrl )
96+ }
97+
98+ renderPlayButton = ( state : PlayState ) => {
99+ if ( Platform . OS === 'android' ) {
100+ return (
101+ < ActionButton
102+ icon = "ios-planet"
103+ onPress = { this . openStreamWebsite }
104+ text = "Open"
105+ />
106+ )
107+ }
108+
109+ switch ( state ) {
110+ case 'paused' :
111+ return (
112+ < ActionButton icon = "ios-play" onPress = { this . play } text = "Listen" />
113+ )
114+
115+ case 'checking' :
116+ return (
117+ < ActionButton icon = "ios-more" onPress = { this . pause } text = "Starting" />
118+ )
119+
120+ case 'playing' :
121+ return (
122+ < ActionButton icon = "ios-pause" onPress = { this . pause } text = "Pause" />
123+ )
124+
125+ default :
126+ return < ActionButton icon = "ios-bug" onPress = { noop } text = "Error" />
127+ }
128+ }
129+
130+ render ( ) {
131+ const sideways = this . state . viewport . width > this . state . viewport . height
132+
133+ const logoWidth = Math . min (
134+ this . state . viewport . width / 1.5 ,
135+ this . state . viewport . height / 1.75 ,
136+ )
137+
138+ const logoSize = {
139+ width : logoWidth ,
140+ height : logoWidth ,
141+ }
142+
143+ const error = this . state . uplinkError ? (
144+ < Text style = { styles . status } > { this . state . uplinkError } </ Text >
145+ ) : this . state . streamError ? (
146+ < Text style = { styles . status } >
147+ Error Code { this . state . streamError . code } :{ ' ' }
148+ { this . state . streamError . message }
149+ </ Text >
150+ ) : null
151+
152+ return (
153+ < ScrollView
154+ contentContainerStyle = { [ styles . root , sideways && landscape . root ] }
155+ >
156+ < View style = { [ styles . logoWrapper , sideways && landscape . logoWrapper ] } >
157+ < Image
158+ resizeMode = "contain"
159+ source = { image }
160+ style = { [ styles . logo , logoSize ] }
161+ />
162+ </ View >
163+
164+ < View style = { styles . container } >
165+ < View style = { styles . titleWrapper } >
166+ < Text selectable = { true } style = { styles . heading } >
167+ St. Olaf College Radio
168+ </ Text >
169+ < Text selectable = { true } style = { styles . subHeading } >
170+ KSTO 93.1 FM
171+ </ Text >
172+
173+ { error }
174+ </ View >
175+
176+ < Row >
177+ { this . renderPlayButton ( this . state . playState ) }
178+ < View style = { styles . spacer } />
179+ < CallButton onPress = { this . callStation } />
180+ < View style = { styles . spacer } />
181+ < ShowCalendarButton onPress = { this . openSchedule } />
182+ </ Row >
183+
184+ { Platform . OS !== 'android' ? (
185+ < StreamPlayer
186+ onEnded = { this . handleStreamEnd }
187+ // onWaiting={this.handleStreamWait}
188+ onError = { this . handleStreamError }
189+ // onStalled={this.handleStreamStall}
190+ onPause = { this . handleStreamPause }
191+ onPlay = { this . handleStreamPlay }
192+ playState = { this . state . playState }
193+ style = { styles . webview }
194+ />
195+ ) : null }
196+ </ View >
197+ </ ScrollView >
198+ )
199+ }
180200}
181201
182202const styles = StyleSheet . create ( {
0 commit comments