UNPKG

nexle-tvguide-lib

Version:
231 lines (211 loc) 9.78 kB
import React, { PureComponent } from 'react'; import { View, Text, StyleSheet, TouchableOpacity } from 'react-native'; import { TV_GUIDE_CONSTANTS } from '../../constants'; import { formatHourMin } from '../../util'; import { debounce } from 'lodash'; import PropTypes from 'prop-types'; const ProgramTimeFrame = ({ program }) => ( `${formatHourMin(program?.startDate)} - ${formatHourMin(program?.endDate)}` ); const checkShowProgramContent = (program) => { const programDuration = program?.endDateAdjusted - program?.startDateAdjusted; if (programDuration >= TV_GUIDE_CONSTANTS.PROGRAM_MIN_DURATION_SHOW_CONTENT) return true; return false; }; const getProgramTimeType = (program) => { const now = new Date().getTime(); if (program.startDateAdjusted <= now && program.endDateAdjusted > now) { return TV_GUIDE_CONSTANTS.PROGRAM_TIME_TYPE.CURRENT; } else if (program.endDateAdjusted <= now) { return TV_GUIDE_CONSTANTS.PROGRAM_TIME_TYPE.PAST } return TV_GUIDE_CONSTANTS.PROGRAM_TIME_TYPE.FUTURE; }; class ProgramCell extends React.Component { constructor(props) { super(props); this.state = { isShowProgramContent: checkShowProgramContent(props.program), active: props.isFocused, programCellReference: React.createRef(), programWidth: Number((props.program?.endDateAdjusted - props.program?.startDateAdjusted) / TV_GUIDE_CONSTANTS.HALF_HOUR_DURATION) * props.timelineCellWidth, isCurrentProgram: getProgramTimeType(props.program), programContainerStylesFlatten: StyleSheet.flatten([styles.programContainer, props.programContainerStyles]), activeProgramStylesFlatten: StyleSheet.flatten([styles.activeProgram, { backgroundColor: props.programStylesColors.activeProgramBackgroundColor }]), currentProgramStylesFlatten: StyleSheet.flatten([styles.nowProgram, { backgroundColor: props.programStylesColors.currentProgramBacgroundColor }]), pastProgramStylesFlatten: StyleSheet.flatten([styles.defaultProgram, { backgroundColor: props.programStylesColors.pastProgramBackgroundColor }]), futureProgramStylesFlatten: StyleSheet.flatten([styles.defaultProgram, { backgroundColor: props.programStylesColors.futureProgramBackgroundColor }]), activeProgramTextStylesFlatten: StyleSheet.flatten([styles.titleActive, { color: props.programStylesColors.activeProgramTextColor }]), currentProgramTextStylesFlatten: StyleSheet.flatten([styles.title, { color: props.programStylesColors.currrentProgramTextColor }]), pastProgramTextStylesFlatten: StyleSheet.flatten([styles.titlePast, { color: props.programStylesColors.pastProgramTextColor }]), futureProgramTextStylesFlatten: StyleSheet.flatten([styles.title, { color: props.programStylesColors.futureProgramTextColor }]), } this.handleCellFocus = this.handleCellFocus.bind(this); this.handleCellBlur = this.handleCellBlur.bind(this); this.onDebounceCellFocus = this.onDebounceCellFocus(this); this.onDebounceCellBlur = this.onDebounceCellBlur(this); } shouldComponentUpdate(nextProps, nextState) { if (nextProps.isFocused !== this.props.isFocused) { return true; } if (nextState.active !== this.state.active) { return true; } if (nextProps.program !== this.props.program) { return true; } return false; } onDebounceCellFocus() { return debounce(this.handleCellFocus, TV_GUIDE_CONSTANTS.DEBOUNCE_TIME, { leading: true, trailing: false }); } onDebounceCellBlur() { return debounce(this.handleCellBlur, TV_GUIDE_CONSTANTS.DEBOUNCE_TIME, { leading: true, trailing: false }); } handleCellFocus() { const { index, lineNumber, program } = this.props; this.setState({ active: true }); this.state.programCellReference.current.setNativeProps({ hasTVPreferredFocus: true }); global.focusManager.setFocusForRoute('selectedAt', { lineNumber, index }); this.props.onFocus(index, lineNumber, program); } handleCellBlur() { this.setState({ active: false }); } componentDidUpdate(prevProps, prevState) { if (prevProps.isFocused === false && prevState.active === false && this.props.isFocused === true && this.state.active === false) { this.handleCellFocus(); } } componentDidMount() { if (this.props.isFocused) { this.handleCellFocus(); } } render() { const { program, programHeight } = this.props; const { id } = program; const { isShowProgramContent, programCellReference, active, programWidth, isCurrentProgram, activeProgramStylesFlatten, currentProgramStylesFlatten, programContainerStylesFlatten, pastProgramStylesFlatten, futureProgramStylesFlatten, activeProgramTextStylesFlatten, currentProgramTextStylesFlatten, pastProgramTextStylesFlatten, futureProgramTextStylesFlatten } = this.state; let programStylesFlatten = styles.defaultProgram; let programTextStylesFlattent = styles.title; if (isCurrentProgram === TV_GUIDE_CONSTANTS.PROGRAM_TIME_TYPE.CURRENT) { programStylesFlatten = currentProgramStylesFlatten; programTextStylesFlattent = currentProgramTextStylesFlatten; } else if (isCurrentProgram === TV_GUIDE_CONSTANTS.PROGRAM_TIME_TYPE.FUTURE) { programStylesFlatten = futureProgramStylesFlatten; programTextStylesFlattent = futureProgramTextStylesFlatten; } else { programStylesFlatten = pastProgramStylesFlatten; programTextStylesFlattent = pastProgramTextStylesFlatten; } return ( <TouchableOpacity ref={programCellReference} activeOpacity={1} onFocus={this.onDebounceCellFocus} onBlur={this.onDebounceCellBlur} style={[ programContainerStylesFlatten, active ? activeProgramStylesFlatten : programStylesFlatten, { width: programWidth, height: programHeight }, ]}> {isShowProgramContent && ( <View> <Text style={active ? activeProgramTextStylesFlatten : programTextStylesFlattent} numberOfLines={1}> {id !== -1 ? program.name : 'No program info'} </Text> <Text style={active ? activeProgramTextStylesFlatten : programTextStylesFlattent}> <ProgramTimeFrame program={program} /> </Text> </View> )} </TouchableOpacity> ); } } ProgramCell.propTypes = { program: PropTypes.shape({ name: PropTypes.string, id: PropTypes.number }), index: PropTypes.number.isRequired, lineNumber: PropTypes.number.isRequired, onFocus: PropTypes.func.isRequired, programStylesColors: PropTypes.object, programContainerStyles: PropTypes.object, } ProgramCell.defaultProps = { program: { name: '', id: -1 }, index: 0, lineNumber: 0, onFocus: () => { }, programStylesColors: { activeProgramBackgroundColor: TV_GUIDE_CONSTANTS.THEME_STYLES.ACTIVE_PROGRAM_BG_COLOR, currentProgramBacgroundColor: TV_GUIDE_CONSTANTS.THEME_STYLES.CURRENT_PROGRAM_BG_COLOR, pastProgramBackgroundColor: TV_GUIDE_CONSTANTS.THEME_STYLES.DEFAULT_PROGRAM_BG_COLOR, futureProgramBackgroundColor: TV_GUIDE_CONSTANTS.THEME_STYLES.DEFAULT_PROGRAM_BG_COLOR, activeProgramTextColor: TV_GUIDE_CONSTANTS.THEME_STYLES.FUTURE_PROGRAM_TEXT_COLOR, currrentProgramTextColor: TV_GUIDE_CONSTANTS.THEME_STYLES.PROGRAM_TEXT_COLOR, pastProgramTextColor: TV_GUIDE_CONSTANTS.THEME_STYLES.PAST_PROGRAM_TEXT_COLOR, futureProgramTextColor: TV_GUIDE_CONSTANTS.THEME_STYLES.PROGRAM_TEXT_COLOR, }, programContainerStyles: { } }; export default ProgramCell; const styles = StyleSheet.create({ activeProgram: { backgroundColor: TV_GUIDE_CONSTANTS.THEME_STYLES.ACTIVE_PROGRAM_BG_COLOR, borderColor: '#ffffff', borderWidth: 5, borderTopWidth: 5, borderStartWidth: 5, }, defaultProgram: { backgroundColor: TV_GUIDE_CONSTANTS.THEME_STYLES.DEFAULT_PROGRAM_BG_COLOR, }, nowProgram: { backgroundColor: TV_GUIDE_CONSTANTS.THEME_STYLES.CURRENT_PROGRAM_BG_COLOR, }, programContainer: { color: '#ffff', justifyContent: 'center', borderWidth: 2, borderColor: TV_GUIDE_CONSTANTS.THEME_STYLES.PROGRAM_TEXT_COLOR, }, innerView: { flex: 1, flexDirection: 'column', justifyContent: 'center', }, title: { color: TV_GUIDE_CONSTANTS.THEME_STYLES.PROGRAM_TEXT_COLOR, fontSize: TV_GUIDE_CONSTANTS.THEME_STYLES.TIME_LINE_TITLE_FONT_SIZE, fontWeight: 'bold', paddingLeft: 5 }, titleActive: { color: TV_GUIDE_CONSTANTS.THEME_STYLES.FUTURE_PROGRAM_TEXT_COLOR, fontSize: TV_GUIDE_CONSTANTS.THEME_STYLES.TIME_LINE_TITLE_FONT_SIZE, fontWeight: 'bold', paddingLeft: 5 }, titlePast: { color: TV_GUIDE_CONSTANTS.THEME_STYLES.PAST_PROGRAM_TEXT_COLOR, fontSize: TV_GUIDE_CONSTANTS.THEME_STYLES.TIME_LINE_TITLE_FONT_SIZE, fontWeight: 'bold', paddingLeft: 5 }, });