<commit_before>import * as React from 'react'
import {useCallback, useState} from 'react'
import {Image, ScrollView, StyleSheet, Text, View, useWindowDimensions} from 'react-native'
import noop from 'lodash/noop'
import * as c from '@frogpond/colors'
import {callPhone} from '../../../components/call-phone'
import {Row} from '@frogpond/layout'
import type {TopLevelViewPropsType} from '../../types'
import {StreamPlayer} from './player'
import type {HtmlAudioError, PlayState} from './types'
import {useTheme} from './theme'
import {ActionButton, CallButton, ShowCalendarButton} from './buttons'
import {openUrl} from '@frogpond/open-url'

// If you want to fix the inline player, switch to `true`
const ALLOW_INLINE_PLAYER = false

type PlayButtonProps = {
	state: PlayState
	onPlay: () => unknown
	onPause: () => unknown
	onLink: () => unknown
}

function PlayButton(props: PlayButtonProps): JSX.Element {
	const {state, onPlay, onPause, onLink} = props

	if (!ALLOW_INLINE_PLAYER) {
		return <ActionButton icon="ios-planet" onPress={onLink} text="Open" />
	}

	switch (state) {
		case 'paused':
			return <ActionButton icon="ios-play" onPress={onPlay} text="Listen" />

		case 'checking':
			return (
				<ActionButton icon="code-working" onPress={onPause} text="Starting" />
			)

		case 'playing':
			return <ActionButton icon="ios-pause" onPress={onPlay} text="Pause" />

		default:
			return <ActionButton icon="ios-bug" onPress={noop} text="Error" />
	}
}

type Props = TopLevelViewPropsType & {
	image: number
	playerUrl: string
	stationNumber: string
	title: string
	scheduleViewName: string
	stationName: string
	source: {
		useEmbeddedPlayer: boolean
		embeddedPlayerUrl: string
		streamSourceUrl: string
	}
}

export function RadioControllerView(props: Props): JSX.Element {
	const theme = useTheme()
	const {
		source,
		title,
		stationName,
		image,
		navigation,
		scheduleViewName,
		stationNumber,
		playerUrl,
	} = props

	let [playState, setPlayState] = useState<PlayState>('paused')
	let [streamError, setStreamError] = useState<HtmlAudioError | null>(null)

	let play = () => {
		setPlayState('checking')
	}

	let pause = () => {
		setPlayState('paused')
	}

	let handleStreamPlay = () => {
		setPlayState('playing')
	}

	let handleStreamPause = () => {
		setPlayState('paused')
	}

	let handleStreamEnd = () => {
		setPlayState('paused')
	}

	let handleStreamError = (e: {code: number; message: string}) => {
		setStreamError(e)
		setPlayState('paused')
	}

	let openSchedule = useCallback(() => {
		navigation.navigate(scheduleViewName)
	}, [navigation, scheduleViewName])

	let callStation = useCallback(() => {
		callPhone(stationNumber)
	}, [stationNumber])

	let openStreamWebsite = useCallback(() => {
		openUrl(playerUrl)
	}, [playerUrl])

	let error = streamError ? (
		<Text style={styles.status}>
			Error Code {streamError.code}: {streamError.message}
		</Text>
	) : null

	let textColor = {color: theme.textColor}
	let titleBlock = (
		<View style={styles.titleWrapper}>
			<Text selectable={true} style={[styles.heading, textColor]}>
				{title}
			</Text>
			<Text selectable={true} style={[styles.subHeading, textColor]}>
				{stationName}
			</Text>

			{error}
		</View>
	)

	let controlsBlock = (
		<Row>
			<PlayButton
				onLink={openStreamWebsite}
				onPause={pause}
				onPlay={play}
				state={playState}
			/>
			<View style={styles.spacer} />
			<CallButton onPress={callStation} />
			<View style={styles.spacer} />
			<ShowCalendarButton onPress={openSchedule} />
		</Row>
	)

	let playerBlock = ALLOW_INLINE_PLAYER ? (
		<StreamPlayer
			embeddedPlayerUrl={source.embeddedPlayerUrl}
			onEnded={handleStreamEnd}
			// onWaiting={this.handleStreamWait}
			onError={handleStreamError}
			// onStalled={this.handleStreamStall}
			onPause={handleStreamPause}
			onPlay={handleStreamPlay}
			playState={playState}
			streamSourceUrl={source.streamSourceUrl}
			style={styles.webview}
			useEmbeddedPlayer={source.useEmbeddedPlayer}
		/>
	) : null

	let {width, height} = useWindowDimensions()

	let sideways = width > height

	let logoSmallestDimension = Math.min(width / 1.5, height / 1.75)
	let logoSize = {
		width: logoSmallestDimension,
		height: logoSmallestDimension,
	}

	let root = [styles.root, sideways && landscape.root]
	let logoBorderColor = {borderColor: theme.imageBorderColor}
	let logoBg = {backgroundColor: theme.imageBackgroundColor}
	let logo = [styles.logoBorder, logoSize, logoBorderColor, logoBg]
	let logoWrapper = [
		styles.logoWrapper,
		sideways && landscape.logoWrapper,
	]

	return (
		<ScrollView contentContainerStyle={root}>
			<View style={logoWrapper}><commit_msg>prettier, removal of TopLevelViewPropsType, and navigation hook<commit_after>import * as React from 'react'
import {useCallback, useState} from 'react'
import {
	Image,
	ScrollView,
	StyleSheet,
	Text,
	View,
	useWindowDimensions,
} from 'react-native'
import noop from 'lodash/noop'
import * as c from '@frogpond/colors'
import {callPhone} from '../../../components/call-phone'
import {Row} from '@frogpond/layout'
import {StreamPlayer} from './player'
import type {HtmlAudioError, PlayState} from './types'
import {useTheme} from './theme'
import {ActionButton, CallButton, ShowCalendarButton} from './buttons'
import {openUrl} from '@frogpond/open-url'
import {useNavigation} from '@react-navigation/native'

// If you want to fix the inline player, switch to `true`
const ALLOW_INLINE_PLAYER = false

type PlayButtonProps = {
	state: PlayState
	onPlay: () => unknown
	onPause: () => unknown
	onLink: () => unknown
}

function PlayButton(props: PlayButtonProps): JSX.Element {
	const {state, onPlay, onPause, onLink} = props

	if (!ALLOW_INLINE_PLAYER) {
		return <ActionButton icon="ios-planet" onPress={onLink} text="Open" />
	}

	switch (state) {
		case 'paused':
			return <ActionButton icon="ios-play" onPress={onPlay} text="Listen" />

		case 'checking':
			return (
				<ActionButton icon="code-working" onPress={onPause} text="Starting" />
			)

		case 'playing':
			return <ActionButton icon="ios-pause" onPress={onPlay} text="Pause" />

		default:
			return <ActionButton icon="ios-bug" onPress={noop} text="Error" />
	}
}

type Props = {
	image: number
	playerUrl: string
	stationNumber: string
	title: string
	scheduleViewName: string
	stationName: string
	source: {
		useEmbeddedPlayer: boolean
		embeddedPlayerUrl: string
		streamSourceUrl: string
	}
}

export function RadioControllerView(props: Props): JSX.Element {
	const theme = useTheme()
	const {
		source,
		title,
		stationName,
		image,
		scheduleViewName,
		stationNumber,
		playerUrl,
	} = props

	let navigation = useNavigation()

	let [playState, setPlayState] = useState<PlayState>('paused')
	let [streamError, setStreamError] = useState<HtmlAudioError | null>(null)

	let play = () => {
		setPlayState('checking')
	}

	let pause = () => {
		setPlayState('paused')
	}

	let handleStreamPlay = () => {
		setPlayState('playing')
	}

	let handleStreamPause = () => {
		setPlayState('paused')
	}

	let handleStreamEnd = () => {
		setPlayState('paused')
	}

	let handleStreamError = (e: {code: number; message: string}) => {
		setStreamError(e)
		setPlayState('paused')
	}

	let openSchedule = useCallback(() => {
		navigation.navigate(scheduleViewName)
	}, [navigation, scheduleViewName])

	let callStation = useCallback(() => {
		callPhone(stationNumber)
	}, [stationNumber])

	let openStreamWebsite = useCallback(() => {
		openUrl(playerUrl)
	}, [playerUrl])

	let error = streamError ? (
		<Text style={styles.status}>
			Error Code {streamError.code}: {streamError.message}
		</Text>
	) : null

	let textColor = {color: theme.textColor}
	let titleBlock = (
		<View style={styles.titleWrapper}>
			<Text selectable={true} style={[styles.heading, textColor]}>
				{title}
			</Text>
			<Text selectable={true} style={[styles.subHeading, textColor]}>
				{stationName}
			</Text>

			{error}
		</View>
	)

	let controlsBlock = (
		<Row>
			<PlayButton
				onLink={openStreamWebsite}
				onPause={pause}
				onPlay={play}
				state={playState}
			/>
			<View style={styles.spacer} />
			<CallButton onPress={callStation} />
			<View style={styles.spacer} />
			<ShowCalendarButton onPress={openSchedule} />
		</Row>
	)

	let playerBlock = ALLOW_INLINE_PLAYER ? (
		<StreamPlayer
			embeddedPlayerUrl={source.embeddedPlayerUrl}
			onEnded={handleStreamEnd}
			// onWaiting={this.handleStreamWait}
			onError={handleStreamError}
			// onStalled={this.handleStreamStall}
			onPause={handleStreamPause}
			onPlay={handleStreamPlay}
			playState={playState}
			streamSourceUrl={source.streamSourceUrl}
			style={styles.webview}
			useEmbeddedPlayer={source.useEmbeddedPlayer}
		/>
	) : null

	let {width, height} = useWindowDimensions()

	let sideways = width > height

	let logoSmallestDimension = Math.min(width / 1.5, height / 1.75)
	let logoSize = {
		width: logoSmallestDimension,
		height: logoSmallestDimension,
	}

	let root = [styles.root, sideways && landscape.root]
	let logoBorderColor = {borderColor: theme.imageBorderColor}
	let logoBg = {backgroundColor: theme.imageBackgroundColor}
	let logo = [styles.logoBorder, logoSize, logoBorderColor, logoBg]
	let logoWrapper = [styles.logoWrapper, sideways && landscape.logoWrapper]

	return (
		<ScrollView contentContainerStyle={root}>
			<View style={logoWrapper}>
{'fraction_non_alphanumeric': 0.13567301519366573, 'fraction_numerical': 0.0010699764605178687, 'mean_word_length': 4.576968973747016, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4729259', 'n_tokens_mistral': 3363, 'n_tokens_neox': 3032, 'n_words': 683}