diff --git a/web/pages/components/config/constants.tsx b/web/pages/components/config/constants.tsx index 48e950594..503b3e882 100644 --- a/web/pages/components/config/constants.tsx +++ b/web/pages/components/config/constants.tsx @@ -184,6 +184,27 @@ export const TEXTFIELD_DEFAULTS = { label: 'Display in the Owncast Directory?', tip: 'Turn this ON if you want to show up in the Owncast directory at https://directory.owncast.online.', } + }, + + videoSettings: { + numberOfPlaylistItems: { + apiPath: '/webserverport', // tbd + defaultValue: 4, + maxLength: 6, + placeholder: '4', + label: 'Segment Length', + tip: '', + required: true, + }, + segmentLengthSeconds: { + apiPath: '/webserverport', // tbd + defaultValue: 5, + maxLength: 6, + placeholder: '5', + label: 'Number of segments', + tip: '', + required: true, + }, } } diff --git a/web/pages/components/config/form-textfield.tsx b/web/pages/components/config/form-textfield.tsx index fcdaf7efa..50ba29c12 100644 --- a/web/pages/components/config/form-textfield.tsx +++ b/web/pages/components/config/form-textfield.tsx @@ -30,6 +30,7 @@ export const TEXTFIELD_TYPE_TEXT = 'default'; export const TEXTFIELD_TYPE_PASSWORD = 'password'; // Input.Password export const TEXTFIELD_TYPE_NUMBER = 'numeric'; export const TEXTFIELD_TYPE_TEXTAREA = 'textarea'; +export const TEXTFIELD_TYPE_URL = 'url'; export default function TextField(props: TextFieldProps) { @@ -79,9 +80,14 @@ export default function TextField(props: TextFieldProps) { // if field is required but value is empty, or equals initial value, then don't show submit/update button. otherwise clear out any result messaging and display button. const handleChange = (e: any) => { const val = type === TEXTFIELD_TYPE_NUMBER ? e : e.target.value; - if ((required && (val === '' || val === null)) || val === initialValue) { + + // https://developer.mozilla.org/en-US/docs/Web/API/ValidityState + const hasValidity = type !== TEXTFIELD_TYPE_NUMBER && e.target.validity.valid; + + if ((required && (val === '' || val === null)) || val === initialValue || !hasValidity) { setHasChanged(false); } else { + // show submit button resetStates(); setHasChanged(true); setFieldValueForSubmit(val); @@ -138,6 +144,20 @@ export default function TextField(props: TextFieldProps) { }; } else if (type === TEXTFIELD_TYPE_NUMBER) { Field = InputNumber; + fieldProps = { + type: 'number', + min: 0, + max: (10**maxLength) - 1, + onKeyDown: (e: React.KeyboardEvent) => { + if (e.target.value.length > maxLength - 1 ) + e.preventDefault() + return false; + } + }; + } else if (type === TEXTFIELD_TYPE_URL) { + fieldProps = { + type: 'url', + }; } return ( diff --git a/web/pages/config-public-details.tsx b/web/pages/config-public-details.tsx index 47b91e8cb..2531dba5b 100644 --- a/web/pages/config-public-details.tsx +++ b/web/pages/config-public-details.tsx @@ -1,7 +1,7 @@ import React, { useContext, useEffect } from 'react'; import { Typography, Form } from 'antd'; -import TextField, { TEXTFIELD_TYPE_TEXTAREA } from './components/config/form-textfield'; +import TextField, { TEXTFIELD_TYPE_TEXTAREA, TEXTFIELD_TYPE_URL } from './components/config/form-textfield'; import EditInstanceTags from './components/config/edit-tags'; import EditDirectoryDetails from './components/config/edit-directory'; @@ -73,6 +73,7 @@ export default function PublicFacingDetails() { fieldName="instanceUrl" {...extraProps} configPath="yp" + type={TEXTFIELD_TYPE_URL} onSubmit={handleSubmitInstanceUrl} /> diff --git a/web/pages/config-server-details.tsx b/web/pages/config-server-details.tsx index 1f89fccb0..9f9567fe9 100644 --- a/web/pages/config-server-details.tsx +++ b/web/pages/config-server-details.tsx @@ -48,7 +48,7 @@ export default function ConfigServerDetails() { layout="vertical" > - + diff --git a/web/styles/config.scss b/web/styles/config.scss index acf8f1044..af413041f 100644 --- a/web/styles/config.scss +++ b/web/styles/config.scss @@ -50,6 +50,10 @@ .field { width: 18rem; + &.ant-input-number { + width: 8em; + } + } .info-tip { margin-right: .75rem; diff --git a/web/types/config-section.ts b/web/types/config-section.ts index 136edd457..ce4159d32 100644 --- a/web/types/config-section.ts +++ b/web/types/config-section.ts @@ -70,5 +70,5 @@ export interface ConfigDetails { streamKey: string; webServerPort: string; yp: ConfigDirectoryFields; - videoSettings: VideoSettingsFields; // tbd + videoSettings: VideoSettingsFields; }