Marker time input (#242)

* Use duration input for marker time

* Allow reset to current time

* Validate input
This commit is contained in:
WithoutPants 2019-12-05 04:47:17 +11:00 committed by Leopere
parent 85935f022a
commit fe7bf59906
2 changed files with 135 additions and 11 deletions

View file

@ -0,0 +1,127 @@
import React, { FunctionComponent, useState, useEffect } from "react";
import { InputGroup, ButtonGroup, Button, IInputGroupProps, HTMLInputProps, ControlGroup } from "@blueprintjs/core";
import { TextUtils } from "../../utils/text";
import { FIXED, NUMERIC_INPUT } from "@blueprintjs/core/lib/esm/common/classes";
interface IProps {
disabled?: boolean
numericValue: number
onValueChange(valueAsNumber: number): void
onReset?(): void
}
export const DurationInput: FunctionComponent<HTMLInputProps & IProps> = (props: IProps) => {
const [value, setValue] = useState<string>(secondsToString(props.numericValue));
useEffect(() => {
setValue(secondsToString(props.numericValue));
}, [props.numericValue]);
function secondsToString(seconds : number) {
let ret = TextUtils.secondsToTimestamp(seconds);
if (ret.startsWith("00:")) {
ret = ret.substr(3);
if (ret.startsWith("0")) {
ret = ret.substr(1);
}
}
return ret;
}
function stringToSeconds(v : string) {
if (!v) {
return 0;
}
let splits = v.split(":");
if (splits.length > 3) {
return 0;
}
let seconds = 0;
let factor = 1;
while(splits.length > 0) {
let thisSplit = splits.pop();
if (thisSplit == undefined) {
return 0;
}
let thisInt = parseInt(thisSplit, 10);
if (isNaN(thisInt)) {
return 0;
}
seconds += factor * thisInt;
factor *= 60;
}
return seconds;
}
function increment() {
let seconds = stringToSeconds(value);
seconds += 1;
props.onValueChange(seconds);
}
function decrement() {
let seconds = stringToSeconds(value);
seconds -= 1;
props.onValueChange(seconds);
}
function renderButtons() {
return (
<ButtonGroup
vertical={true}
className={FIXED}
>
<Button
icon="chevron-up"
disabled={props.disabled}
onClick={() => increment()}
/>
<Button
icon="chevron-down"
disabled={props.disabled}
onClick={() => decrement()}
/>
</ButtonGroup>
)
}
function onReset() {
if (props.onReset) {
props.onReset();
}
}
function maybeRenderReset() {
if (props.onReset) {
return (
<Button
icon="time"
onClick={() => onReset()}
/>
)
}
}
return (
<ControlGroup className={NUMERIC_INPUT}>
<InputGroup
disabled={props.disabled}
value={value}
onChange={(e : any) => setValue(e.target.value)}
onBlur={() => props.onValueChange(stringToSeconds(value))}
placeholder="hh:mm:ss"
rightElement={maybeRenderReset()}
/>
{renderButtons()}
</ControlGroup>
)
};

View file

@ -19,6 +19,7 @@ import { MarkerTitleSuggest } from "../../select/MarkerTitleSuggest";
import { WallPanel } from "../../Wall/WallPanel";
import { SceneHelpers } from "../helpers";
import { ErrorUtils } from "../../../utils/errors";
import { DurationInput } from "../../Shared/DurationInput";
interface ISceneMarkersPanelProps {
scene: GQL.SceneDataFragment;
@ -148,14 +149,10 @@ export const SceneMarkersPanel: FunctionComponent<ISceneMarkersPanelProps> = (pr
}
function renderSecondsField(fieldProps: FieldProps<IFormFields>) {
return (
<NumericInput
placeholder="Seconds"
fill={true}
allowNumericCharactersOnly={true}
name={fieldProps.field.name}
onValueChange={(_, s) => fieldProps.form.setFieldValue("seconds", s)}
onBlur={fieldProps.field.onBlur}
value={fieldProps.field.value}
<DurationInput
onValueChange={(s) => fieldProps.form.setFieldValue("seconds", s)}
onReset={() => fieldProps.form.setFieldValue("seconds", Math.round(jwplayer.getPosition()))}
numericValue={fieldProps.field.value}
/>
);
}
@ -197,7 +194,7 @@ export const SceneMarkersPanel: FunctionComponent<ISceneMarkersPanelProps> = (pr
<FormGroup label="Scene Marker Title" labelFor="title" className="column is-full">
<Field name="title" render={renderTitleField} />
</FormGroup>
<FormGroup label="Seconds" labelFor="seconds" className="column is-half">
<FormGroup label="Time" labelFor="seconds" className="column is-half">
<Field name="seconds" render={renderSecondsField} />
</FormGroup>
<FormGroup label="Primary Tag" labelFor="primaryTagId" className="column is-half">
@ -228,11 +225,11 @@ export const SceneMarkersPanel: FunctionComponent<ISceneMarkersPanelProps> = (pr
}
return (
<Collapse isOpen={isEditorOpen}>
<Formik
{isEditorOpen ? <Formik
initialValues={initialValues}
onSubmit={onSubmit}
render={renderFormFields}
/>
/> : undefined}
</Collapse>
);
}