feat: edit duration in cuesheet

This commit is contained in:
Carlos Valente
2024-12-20 12:44:56 +01:00
committed by Carlos Valente
parent c445c42f8a
commit 88b114020b
8 changed files with 216 additions and 45 deletions
@@ -15,6 +15,7 @@ export default function useReactiveTextInput(
options?: {
submitOnEnter?: boolean;
submitOnCtrlEnter?: boolean;
onCancelUpdate?: () => void;
},
): UseReactiveTextInputReturn {
const [text, setText] = useState<string>(initialText);
@@ -47,7 +48,9 @@ export default function useReactiveTextInput(
const handleSubmit = useCallback(
(valueToSubmit: string) => {
// No need to update if it hasn't changed
if (valueToSubmit !== initialText) {
if (valueToSubmit === initialText) {
options?.onCancelUpdate?.();
} else {
const cleanVal = valueToSubmit.trim();
submitCallback(cleanVal);
if (cleanVal !== valueToSubmit) {
@@ -56,7 +59,7 @@ export default function useReactiveTextInput(
}
setTimeout(() => ref.current?.blur()); // Immediate timeout to ensure text is set before bluring
},
[initialText, ref, submitCallback],
[initialText, options, ref, submitCallback],
);
/**
@@ -66,8 +69,9 @@ export default function useReactiveTextInput(
const handleEscape = useCallback(() => {
// No need to update if it hasn't changed
setText(initialText);
options?.onCancelUpdate?.();
setTimeout(() => ref.current?.blur()); // Immediate timeout to ensure text is set before bluring
}, [initialText, ref]);
}, [initialText, options, ref]);
const keyHandler = useMemo(() => {
const hotKeys: HotkeyItem[] = [['Escape', handleEscape, { preventDefault: true }]];
+48 -31
View File
@@ -7,6 +7,8 @@ import {
OntimeEvent,
OntimeRundownEntry,
RundownCached,
TimeField,
TimeStrategy,
TransientEventPayload,
} from 'ontime-types';
import { dayInMs, MILLIS_PER_SECOND, parseUserTime, reorderArray, swapEventData } from 'ontime-utils';
@@ -214,13 +216,56 @@ export const useEventAction = () => {
[updateEvent],
);
type TimeField = 'timeStart' | 'timeEnd' | 'duration';
/**
* Updates time of existing event
* @param eventId {string} - id of the event
* @param field {TimeField} - field to update
* @param value {string} - new value string to be parsed
* @param lockOnUpdate {boolean} - whether we will apply the lock / release on update
*/
const updateTimer = useCallback(
async (eventId: string, field: TimeField, value: string) => {
const getPreviousEnd = (): number => {
async (eventId: string, field: TimeField, value: string, lockOnUpdate?: boolean) => {
let newValMillis = 0;
// check for previous keyword
if (value === 'p' || value === 'prev' || value === 'previous') {
newValMillis = getPreviousEnd();
// check for adding time keyword
} else if (value.startsWith('+') || value.startsWith('p+') || value.startsWith('p +')) {
// TODO: is this logic solid?
const remainingString = value.substring(1);
newValMillis = getPreviousEnd() + parseUserTime(remainingString);
} else {
newValMillis = parseUserTime(value);
}
// dont allow timer values over 23:59:59
const cappedMillis = Math.min(newValMillis, dayInMs - MILLIS_PER_SECOND);
const newEvent = {
id: eventId,
[field]: cappedMillis,
};
// check if we should lock the field
if (lockOnUpdate) {
if (field === 'timeEnd') {
newEvent.timeStrategy = TimeStrategy.LockEnd;
} else if (field === 'duration') {
newEvent.timeStrategy = TimeStrategy.LockDuration;
} else if (field === 'timeStart' && value === '') {
// if user removes the time start, we should link to the previous
newEvent.linkStart = 'true';
}
}
try {
await _updateEventMutation.mutateAsync(newEvent);
} catch (error) {
logAxiosError('Error updating event', error);
}
function getPreviousEnd(): number {
const cachedRundown = queryClient.getQueryData<RundownCached>(RUNDOWN);
if (!cachedRundown?.order || !cachedRundown?.rundown) {
@@ -240,34 +285,6 @@ export const useEventAction = () => {
}
}
return previousEnd;
};
let newValMillis = 0;
// check for previous keyword
if (value === 'p' || value === 'prev' || value === 'previous') {
newValMillis = getPreviousEnd();
// check for adding time keyword
} else if (value.startsWith('+') || value.startsWith('p+') || value.startsWith('p +')) {
// TODO: is this logic solid?
const remainingString = value.substring(1);
newValMillis = getPreviousEnd() + parseUserTime(remainingString);
} else {
newValMillis = parseUserTime(value);
}
// dont allow timer values over 23:59:59
const cappedMillis = Math.min(newValMillis, dayInMs - MILLIS_PER_SECOND);
const newEvent = {
id: eventId,
[field]: cappedMillis,
};
try {
await _updateEventMutation.mutateAsync(newEvent);
} catch (error) {
logAxiosError('Error updating event', error);
}
},
[_updateEventMutation, queryClient],