import * as React from 'react' ; import { StyleSheet , SectionList } from 'react-native' ; import { timezone } from '@frogpond/constants' ; import * as c from '@frogpond/colors' ; import { ListSeparator , ListSectionHeader } from '@frogpond/lists' ; import { NoticeView , LoadingView } from '@frogpond/notice' ; import { TabBarIcon } from '@frogpond/navigation-tabs' ; import { StreamRow } from './row' ; import toPairs from 'lodash/toPairs' ; import groupBy from 'lodash/groupBy' ; import moment from 'moment-timezone' ; import type { Moment } from 'moment-timezone' ; import { toLaxTitleCase as titleCase } from '@frogpond/titlecase' ; import type { StreamType } from './types' ; import { API } from '@frogpond/api' ; import { fetch } from '@frogpond/fetch' ; const styles = StyleSheet . create ( { listContainer : { backgroundColor : c . white , } , contentContainer : { flexGrow : 1 , } , } ) ; type Props = unknown ; type State = { error ? : string ; loading : boolean ; refreshing : boolean ; streams : Array < { title : string ; data : Array < StreamType > ; } > ; } ; export class StreamListView extends React . PureComponent < Props , State > { static navigationOptions = { tabBarLabel : 'Streaming' , tabBarIcon : TabBarIcon ( 'recording' ) , } ; state = { error : null , loading : true , refreshing : false , streams : [ ] , } ; componentDidMount ( ) { this . getStreams ( ) . then ( ( ) => { this . setState ( ( ) => ( { loading : false } ) ) ; } ) ; } refresh = async ( ) : Promise < void > => { this . setState ( ( ) => ( { refreshing : true } ) ) ; await this . getStreams ( true ) ; this . setState ( ( ) => ( { refreshing : false } ) ) ; } ; getStreams = async ( reload ? , date = moment . tz ( timezone ( ) ) ) => { let dateFrom = date . format ( 'YYYY-MM-DD' ) ; let dateTo = date . clone ( ) . add ( 2 , 'month' ) . format ( 'YYYY-MM-DD' ) ; let data = await fetch ( API ( '/streams/upcoming' ) , { searchParams : { sort : 'ascending' , dateFrom , dateTo , } , delay : reload ? 500 : 0 , } ) . json < Array < StreamType > > ( ) ; data = data . filter ( ( stream ) => stream . category !== 'athletics' ) . map ( ( stream ) => { let date = moment ( stream . starttime ) ; let dateGroup = date . format ( 'dddd, MMMM Do' ) ; let group = stream . status . toLowerCase ( ) !== 'live' ? dateGroup : 'Live' ; return { ... stream , category : titleCase ( stream . category ) , date : date , $groupBy : group , } ; } ) ; let grouped = groupBy ( data , ( j ) => j . $groupBy ) ; let mapped = toPairs ( grouped ) . map ( ( [ title , data ] ) => ( { title , data } ) ) ; this . setState ( ( ) => ( { streams : mapped } ) ) ; } ; keyExtractor = ( item ) => item . eid ; renderSectionHeader = ( { section : { title } } ) => ( < ListSectionHeader title = { title } / > ) ; renderItem = ( { item } ) => < StreamRow stream = { item } />; render ( ) { if ( this . state . loading ) { return < LoadingView />; } if ( this . state . error ) { return < NoticeView text = { `Error: ${ this . state . error }` } />; } return ( < SectionList ItemSeparatorComponent = { ListSeparator } ListEmptyComponent = { < NoticeView text = "No Streams" / > } contentContainerStyle = { styles . contentContainer } keyExtractor = { this . keyExtractor } onRefresh = { this . refresh } refreshing = { this . state . refreshing } renderItem = { this . renderItem } renderSectionHeader = { this . renderSectionHeader } sections = { this . state . streams } style = { styles . listContainer } / > ) ; } }