7 changed files with 254 additions and 43 deletions
@ -0,0 +1,185 @@ |
|||||||
|
import React, { useContext, useState } from 'react'; |
||||||
|
import { Typography, Slider, } from 'antd'; |
||||||
|
import { ServerStatusContext } from '../../../utils/server-status-context'; |
||||||
|
import { API_VIDEO_SEGMENTS, SUCCESS_STATES, RESET_TIMEOUT,postConfigUpdateToAPI } from './constants'; |
||||||
|
|
||||||
|
const { Title } = Typography; |
||||||
|
|
||||||
|
// numberOfSegments
|
||||||
|
// secondsPerSegment
|
||||||
|
/* |
||||||
|
|
||||||
|
2 segments, 2 seconds |
||||||
|
3 segments, 3 seconds |
||||||
|
3 segments, 4 seconds |
||||||
|
4 segments, 4 seconds <- default |
||||||
|
8 segments, 4 seconds |
||||||
|
10 segments, 4 seconds |
||||||
|
|
||||||
|
Lowest latancy, less reliability |
||||||
|
-> Highest latancy, higher reliability |
||||||
|
*/ |
||||||
|
const DEFAULT_OPTION = 3; |
||||||
|
|
||||||
|
const SLIDER_OPTIONS = [ |
||||||
|
{ |
||||||
|
numberOfSegments: 2, |
||||||
|
secondsPerSegment: 2, |
||||||
|
}, |
||||||
|
{ |
||||||
|
numberOfSegments: 3, |
||||||
|
secondsPerSegment: 3, |
||||||
|
}, |
||||||
|
{ |
||||||
|
numberOfSegments: 3, |
||||||
|
secondsPerSegment: 4, |
||||||
|
}, |
||||||
|
{ |
||||||
|
numberOfSegments: 4, |
||||||
|
secondsPerSegment: 4, |
||||||
|
}, |
||||||
|
{ |
||||||
|
numberOfSegments: 8, |
||||||
|
secondsPerSegment: 4, |
||||||
|
}, |
||||||
|
{ |
||||||
|
numberOfSegments: 10, |
||||||
|
secondsPerSegment: 4, |
||||||
|
}, |
||||||
|
]; |
||||||
|
|
||||||
|
const SLIDER_MARKS = { |
||||||
|
0: '1', |
||||||
|
1: '2', |
||||||
|
2: '3', |
||||||
|
3: '4', |
||||||
|
4: '5', |
||||||
|
5: '6', |
||||||
|
}; |
||||||
|
|
||||||
|
const SLIDER_COMMENTS = { |
||||||
|
0: 'Lowest latency, but least reliability', |
||||||
|
1: 'Low latency, some reliability', |
||||||
|
2: 'Lower latency, some reliability', |
||||||
|
3: 'Optimal latency and reliability (Default)', |
||||||
|
4: 'High latency, better reliability', |
||||||
|
5: 'Highest latency, higher reliability', |
||||||
|
}; |
||||||
|
|
||||||
|
interface SegmentToolTipProps { |
||||||
|
value: string; |
||||||
|
} |
||||||
|
|
||||||
|
function SegmentToolTip({ value }: SegmentToolTipProps) { |
||||||
|
return ( |
||||||
|
<span className="segment-tip">{value}</span> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
function findSelectedOption(videoSettings) { |
||||||
|
const { numberOfSegments, secondsPerSegment } = videoSettings; |
||||||
|
let selected = DEFAULT_OPTION; |
||||||
|
SLIDER_OPTIONS.map((option, index) => { |
||||||
|
if ( |
||||||
|
(option.numberOfSegments === numberOfSegments && |
||||||
|
option.secondsPerSegment === secondsPerSegment) || |
||||||
|
option.numberOfSegments === numberOfSegments |
||||||
|
) { |
||||||
|
selected = index; |
||||||
|
} |
||||||
|
return option; |
||||||
|
}); |
||||||
|
return selected; |
||||||
|
} |
||||||
|
|
||||||
|
export default function VideoSegmentsEditor() { |
||||||
|
const [submitStatus, setSubmitStatus] = useState(null); |
||||||
|
const [submitStatusMessage, setSubmitStatusMessage] = useState(''); |
||||||
|
|
||||||
|
const serverStatusData = useContext(ServerStatusContext); |
||||||
|
const { serverConfig, setFieldInConfigState } = serverStatusData || {}; |
||||||
|
const { videoSettings } = serverConfig || {}; |
||||||
|
|
||||||
|
let resetTimer = null; |
||||||
|
|
||||||
|
if (!videoSettings) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
const selectedOption = findSelectedOption(videoSettings); |
||||||
|
|
||||||
|
const resetStates = () => { |
||||||
|
setSubmitStatus(null); |
||||||
|
setSubmitStatusMessage(''); |
||||||
|
resetTimer = null; |
||||||
|
clearTimeout(resetTimer); |
||||||
|
} |
||||||
|
|
||||||
|
// posts all the variants at once as an array obj
|
||||||
|
const postUpdateToAPI = async (postValue: any) => { |
||||||
|
await postConfigUpdateToAPI({ |
||||||
|
apiPath: API_VIDEO_SEGMENTS, |
||||||
|
data: { value: postValue }, |
||||||
|
onSuccess: () => { |
||||||
|
setFieldInConfigState({ |
||||||
|
fieldName: 'numberOfSegments', |
||||||
|
value: postValue.numberOfSegments, |
||||||
|
path: 'videoSettings' |
||||||
|
}); |
||||||
|
setFieldInConfigState({ |
||||||
|
fieldName: 'secondsPerSegment', |
||||||
|
value: postValue.secondsPerSegment, |
||||||
|
path: 'videoSettings', |
||||||
|
}); |
||||||
|
|
||||||
|
setSubmitStatus('success'); |
||||||
|
setSubmitStatusMessage('Variants updated.'); |
||||||
|
resetTimer = setTimeout(resetStates, RESET_TIMEOUT); |
||||||
|
}, |
||||||
|
onError: (message: string) => { |
||||||
|
setSubmitStatus('error'); |
||||||
|
setSubmitStatusMessage(message); |
||||||
|
resetTimer = setTimeout(resetStates, RESET_TIMEOUT); |
||||||
|
}, |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
const { |
||||||
|
icon: newStatusIcon = null, |
||||||
|
message: newStatusMessage = '', |
||||||
|
} = SUCCESS_STATES[submitStatus] || {}; |
||||||
|
|
||||||
|
const statusMessage = ( |
||||||
|
<div className={`status-message ${submitStatus || ''}`}> |
||||||
|
{newStatusIcon} {newStatusMessage} {submitStatusMessage} |
||||||
|
</div> |
||||||
|
); |
||||||
|
|
||||||
|
const handleSegmentChange = value => { |
||||||
|
const postData = SLIDER_OPTIONS[value]; |
||||||
|
postUpdateToAPI(postData); |
||||||
|
}; |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="module-container config-video-segements-conatiner"> |
||||||
|
<Title level={3}>Video Tolerance</Title> |
||||||
|
<p> |
||||||
|
There are trade-offs when cosidering video latency and reliability. Blah blah .. better wording here needed. |
||||||
|
</p> |
||||||
|
<br /><br /> |
||||||
|
<div className="segment-slider"> |
||||||
|
<Slider |
||||||
|
tooltipVisible |
||||||
|
tipFormatter={value => <SegmentToolTip value={SLIDER_COMMENTS[value]} />} |
||||||
|
onChange={handleSegmentChange} |
||||||
|
min={0} |
||||||
|
max={SLIDER_OPTIONS.length - 1} |
||||||
|
marks={SLIDER_MARKS} |
||||||
|
defaultValue={DEFAULT_OPTION} |
||||||
|
value={selectedOption} |
||||||
|
/> |
||||||
|
</div> |
||||||
|
{statusMessage} |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
Loading…
Reference in new issue