in src/components/Timeline/useTimelineControls.ts [39:135]
export function timelineControlsReducer(state: TimelineControlsState, action: TimelineAction): TimelineControlsState {
switch (action.type) {
case 'update': {
const end = state.max > action.end ? state.max : action.end;
if (state.controlled) {
return {
...state,
max: end,
min: action.start,
timelineStart: action.start > state.timelineStart ? action.start : state.timelineStart,
timelineEnd: end < state.timelineEnd ? end : state.timelineEnd,
};
} else {
return {
...state,
max: action.mode === 'left' ? action.end : end,
min: action.start,
timelineEnd: action.mode === 'left' ? action.end : end,
timelineStart: action.start,
controlled: false,
};
}
}
case 'move':
// Check if any of the edges of scroll bar are out of bounds
if (startOrEndOutOfBounds(state, action.value)) {
return {
...state,
timelineStart: startOutOfBounds(state, action.value)
? state.min
: state.max - (state.timelineEnd - state.timelineStart),
timelineEnd: endOutOfBounds(state, action.value)
? state.max
: state.min + (state.timelineEnd - state.timelineStart),
};
} else {
// Other wise just change start and end position of scrollbar
return updateGraph(state, action.value);
}
case 'zoomIn': {
const change = getZoomAmount(state);
if (state.timelineEnd - change <= state.timelineStart + change) return state;
return { ...updateGraph(state, change, -change), controlled: true };
}
case 'zoomOut': {
const change = getZoomAmount(state);
if (zoomOverTotalLength(state, change)) {
return resetTimeline(state);
} else if (startOrEndOutOfBounds(state, -change, change)) {
return {
...state,
timelineStart: startOutOfBounds(state, -change)
? state.min
: state.max - (state.timelineEnd - state.timelineStart + change),
timelineEnd: endOutOfBounds(state, change)
? state.max
: state.min + (state.timelineEnd - state.timelineStart + change),
};
} else {
return updateGraph(state, -change, change);
}
}
case 'setZoom':
const newVals = {
timelineEnd: action.end <= action.start ? action.start : action.end,
timelineStart: action.start >= action.end ? action.end : action.start,
};
return {
...state,
...newVals,
controlled: newVals.timelineEnd - newVals.timelineStart >= (state.max - state.min) * 0.97 ? false : true,
};
case 'resetZoom':
return resetTimeline(state);
case 'setControlled':
return { ...state, controlled: action.value };
case 'incrementTimelineLength':
return {
...state,
max: new Date().getTime(),
timelineEnd: state.controlled ? state.timelineEnd : new Date().getTime(),
};
case 'reset':
return { ...state, controlled: false, min: 0, max: 0, timelineStart: 0, timelineEnd: 0 };
}
return state;
}