diff --git a/README.md b/README.md index 9b49d43e..7c56b44e 100644 --- a/README.md +++ b/README.md @@ -22,4 +22,12 @@ There's a ton of them, but these are worth mentioning because they sort of affec * `React` - Object oriented components with basic lifecycle callbacks rendered by state and prop changes. * `Redux` - Sane formal *global* scope. This is not a replacement for component state, which is the best way to store local component level variables and trigger re-renders. Redux state is for global state that many unrelated components care about. No free-form editing, only specific pre-defined actions. [Redux DevTools](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=en) can be very helpful. * `@material-ui` - Lots of fully featured highly customizable components for building the UIs with. Theming system with global and per-component overrides of any CSS values. - * `react-router-redux` - the newer one, 5.x.... Mindlessly simple routing with convenient global access due to redux \ No newline at end of file + * `react-router-redux` - the newer one, 5.x.... Mindlessly simple routing with convenient global access due to redux + + ## How things work +The current playback is tracked not by storing the current offset, but instead storing the local time that the player began, the offset it began at, and the playback rate. Any time any of these values change, it rebases them all back to the current time. It means that at any arbitrary moment you can calculate the current offset with... +```js +(Date.now() - state.startTime) * state.playSpeed + state.offset +``` + +With this central authority on current offset time, it becomes much easier to have each data source keep themselves in sync instead of trying to manage synchronizing all of them. \ No newline at end of file diff --git a/src/App.jsx b/src/App.jsx index 1ea21aa4..1420722f 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -122,6 +122,7 @@ class App extends Component { return this.renderLoading(); } + //TODO: refactor const showLogin = !MyCommaAuth.isAuthenticated() && !getZoom(window.location.pathname); let content = ( diff --git a/src/actions/history.js b/src/actions/history.js index ae007601..9d59ada3 100644 --- a/src/actions/history.js +++ b/src/actions/history.js @@ -1,6 +1,6 @@ import { LOCATION_CHANGE } from 'connected-react-router'; import { getDongleID, getZoom, getSegmentRange, getPrimeNav } from '../url'; -import { primeNav, selectDevice, pushTimelineRange, checkRoutesData, updateSegmentRange } from './index'; +import { primeNav, selectDevice, pushTimelineRange, updateSegmentRange } from './index'; import { drives as Drives } from '@commaai/api'; export const onHistoryMiddleware = ({ dispatch, getState }) => (next) => async (action) => { @@ -21,6 +21,7 @@ export const onHistoryMiddleware = ({ dispatch, getState }) => (next) => async ( const pathZoom = getZoom(action.payload.location.pathname); if (pathZoom !== state.zoom) { const [start, end] = [pathZoom.start, pathZoom.end]; + //TODO: Get this out of the middleware Drives.getRoutesSegments(pathDongleId, start, end).then((routesData) => { if (routesData && routesData.length > 0) { const log_id = routesData[0].fullname.split('|')[1]; @@ -36,8 +37,7 @@ export const onHistoryMiddleware = ({ dispatch, getState }) => (next) => async ( const pathSegmentRange = getSegmentRange(action.payload.location.pathname); if (pathSegmentRange !== state.segmentRange) { - // dispatch(pushTimelineRange(pathSegmentRange?.log_id, pathSegmentRange?.start, pathSegmentRange?.end, false)); - dispatch(pushTimelineRange(state.segmentRange.log_id, null, null, false)); + dispatch(pushTimelineRange(pathSegmentRange?.log_id, pathSegmentRange?.start, pathSegmentRange?.end, false)); } const pathPrimeNav = getPrimeNav(action.payload.location.pathname); diff --git a/src/actions/index.js b/src/actions/index.js index 9ffddcca..5acc68c6 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -75,7 +75,6 @@ export function checkRoutesData() { }; }); - console.log('Fetched routes metadata', routes.length, fetchRange.start, fetchRange.end); dispatch({ type: Types.ACTION_ROUTES_METADATA, dongleId, @@ -125,11 +124,9 @@ function updateTimeline(state, dispatch, log_id, start, end, allowPathChange) { dispatch(push(desiredPath)); } } - console.log("updateTimeline", log_id, start, end, allowPathChange); } -export function popTimelineRange(allowPathChange = true) { - console.log("popTimelineRange"); +export function popTimelineRange(log_id, allowPathChange = true) { return (dispatch, getState) => { const state = getState(); if (state.zoom.previous) { @@ -138,7 +135,7 @@ export function popTimelineRange(allowPathChange = true) { }); const { start, end } = state.zoom.previous; - updateTimeline(state, dispatch, start, end, allowPathChange); + updateTimeline(state, dispatch, log_id, start, end, allowPathChange); } }; } @@ -148,8 +145,6 @@ export function pushTimelineRange(log_id, start, end, allowPathChange = true) { return (dispatch, getState) => { const state = getState(); - console.log("pushTimelineRange", state); - if (state.zoom?.start !== start || state.zoom?.end !== end || state.segmentRange?.log_id !== log_id) { dispatch({ type: Types.TIMELINE_PUSH_SELECTION, diff --git a/src/components/DriveView/index.jsx b/src/components/DriveView/index.jsx index 5bdc77e8..289feb01 100644 --- a/src/components/DriveView/index.jsx +++ b/src/components/DriveView/index.jsx @@ -20,9 +20,8 @@ class DriveView extends Component { onBack(zoom, currentRoute) { if (zoom.previous) { - this.props.dispatch(popTimelineRange()); + this.props.dispatch(popTimelineRange(currentRoute?.log_id)); } else if (currentRoute) { - console.log("on back"); this.props.dispatch( pushTimelineRange(currentRoute.log_id, null, null), ); diff --git a/src/components/explorer.jsx b/src/components/explorer.jsx index 358bf55a..5ba74805 100644 --- a/src/components/explorer.jsx +++ b/src/components/explorer.jsx @@ -179,7 +179,7 @@ class ExplorerApp extends Component { } render() { - const { classes, zoom, currentRoute, devices, dongleId } = this.props; + const { classes, currentRoute, devices, dongleId } = this.props; const { drawerIsOpen, pairLoading, pairError, pairDongleId, windowWidth } = this.state; const noDevicesUpsell = (devices?.length === 0 && !dongleId); diff --git a/src/initialState.js b/src/initialState.js index 443fe11b..b5d00a7d 100644 --- a/src/initialState.js +++ b/src/initialState.js @@ -1,4 +1,4 @@ -import { getDongleID, getSegmentRange, getPrimeNav, getZoom } from './url'; +import { getDongleID, getSegmentRange, getPrimeNav } from './url'; export function getDefaultFilter() { const d = new Date(); diff --git a/src/reducers/globalState.js b/src/reducers/globalState.js index 18b5ffb0..271712cf 100644 --- a/src/reducers/globalState.js +++ b/src/reducers/globalState.js @@ -266,7 +266,6 @@ export default function reducer(_state, action) { } break; case Types.TIMELINE_PUSH_SELECTION: { - console.log("TIMELINE_PUSH_SELECTION", state); if (!state.zoom || !action.start || !action.end || action.start < state.zoom.start || action.end > state.zoom.end) { state.files = null; } @@ -292,6 +291,12 @@ export default function reducer(_state, action) { end: state.currentRoute.end_time_utc_millis, }; + if (!state.loop) { + state.loop = { + startTime: state.zoom.start, + duration: state.zoom.end - state.zoom.start, + }; + } } else { state.zoom = null; state.loop = null; @@ -362,22 +367,22 @@ export default function reducer(_state, action) { }; } - console.log("FOUND CURRENT ROUTE", state.currentRoute, state.segmentRange, state.zoom); - state.segmentRange = { log_id: curr.log_id, start: state.currentRoute.start_time_utc_millis, end: state.currentRoute.end_time_utc_millis, }; + + if (!state.loop) { + state.loop = { + startTime: state.zoom.start, + duration: state.zoom.end - state.zoom.start, + }; + } } } break; case Types.ACTION_UPDATE_SEGMENT_RANGE: { - console.log("ACTION_UPDATE_SEGMENT_RANGE"); - const r = state.routes?.find((route) => route.log_id === action.log_id); - - console.log("r", r); - state.segmentRange = { log_id: action.log_id, start: action.start, diff --git a/src/timeline/playback.js b/src/timeline/playback.js index d5d31548..acb381f5 100644 --- a/src/timeline/playback.js +++ b/src/timeline/playback.js @@ -44,9 +44,7 @@ export function reducer(_state, action) { } break; case Types.ACTION_LOOP: - - console.log('loop', action.start, action.end, state); - if (action.start && action.end) { + if (action.start !== null && action.start !== undefined && action.end !== null && action.end !== undefined) { state.loop = { startTime: action.start, duration: action.end - action.start, diff --git a/src/timeline/segments.js b/src/timeline/segments.js index 16cd0718..71e9910d 100644 --- a/src/timeline/segments.js +++ b/src/timeline/segments.js @@ -2,17 +2,17 @@ export function getSegmentFetchRange(state) { return state.filter; - if (!state.zoom) { - return { - start: 0, - end: state.currentRoute ? state.currentRoute.duration : 0, - }; - } + // if (!state.zoom) { + // return { + // start: 0, + // end: state.currentRoute ? state.currentRoute.duration : 0, + // }; + // } - return { - start: state.zoom.start, - end: state.zoom.end, - }; + // return { + // start: state.zoom.start, + // end: state.zoom.end, + // }; } export function hasRoutesData(state) {