⚡️ Reduce the refresh on passages update to the TtwPassage component
This commit is contained in:
@@ -1,41 +1,15 @@
|
||||
import { VoidComponent, createEffect, createResource, createSignal, ParentComponent, ParentProps, Show, useContext, For } from 'solid-js';
|
||||
import { VoidComponent, createResource, ParentComponent, ParentProps, Show, useContext, For } from 'solid-js';
|
||||
import { createDateNow, getTime } from '@solid-primitives/date';
|
||||
import { AnimationOptions } from '@motionone/types';
|
||||
import { Motion } from "@motionone/solid";
|
||||
|
||||
import { Line, Passage, Passages, TrafficStatus } from './types';
|
||||
import { Line, TrafficStatus } from './types';
|
||||
import { renderLineTransportMode, renderLinePicto } from './utils';
|
||||
import { BusinessDataContext, BusinessDataStore } from "./businessData";
|
||||
|
||||
import styles from './passagesPanel.module.css';
|
||||
|
||||
|
||||
const TtwPassage: VoidComponent<{ passage: Passage, style: string, fontSize: number }> = (props) => {
|
||||
|
||||
const [dateNow] = createDateNow(5000);
|
||||
|
||||
const refTs = props.passage.expectedDepartTs !== null ? props.passage.expectedDepartTs : props.passage.expectedArrivalTs;
|
||||
const ttwSec = refTs - (getTime(dateNow()) / 1000);
|
||||
const isApproaching = ttwSec <= 60;
|
||||
|
||||
const transition: AnimationOptions = { duration: 3, repeat: Infinity };
|
||||
return (
|
||||
<div class={props.style}>
|
||||
<svg viewBox={`0 0 215 ${props.fontSize}`}>
|
||||
<Motion.text
|
||||
x="100%" y="55%"
|
||||
dominant-baseline="middle" text-anchor="end"
|
||||
font-size={props.fontSize} style={{ fill: "#000000" }}
|
||||
initial={isApproaching ? undefined : false}
|
||||
animate={{ opacity: [1, 0, 1] }}
|
||||
transition={transition}>
|
||||
{Math.floor(ttwSec / 60)} min
|
||||
</Motion.text>
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const UnavailablePassage: VoidComponent<{ style: string }> = (props) => {
|
||||
const textStyle = { fill: "#000000" };
|
||||
|
||||
@@ -50,8 +24,47 @@ const UnavailablePassage: VoidComponent<{ style: string }> = (props) => {
|
||||
);
|
||||
}
|
||||
|
||||
const TtwPassage: VoidComponent<{ line: Line, destination: string, index: number, style: string, fontSize: number, fallbackStyle: string }> = (props) => {
|
||||
|
||||
const businessDataContext: BusinessDataStore | undefined = useContext(BusinessDataContext);
|
||||
if (businessDataContext === undefined)
|
||||
return <div />;
|
||||
|
||||
const { getDestinationPassages } = businessDataContext;
|
||||
|
||||
const [dateNow] = createDateNow(10000);
|
||||
|
||||
const transition: AnimationOptions = { duration: 3, repeat: Infinity };
|
||||
|
||||
return (() => {
|
||||
const passage = getDestinationPassages(props.line.id, props.destination)[props.index];
|
||||
|
||||
const refTs = passage !== undefined ? (passage.expectedDepartTs !== null ? passage.expectedDepartTs : passage.expectedArrivalTs) : 0;
|
||||
const ttwSec = refTs - (getTime(dateNow()) / 1000);
|
||||
const isApproaching = ttwSec <= 60;
|
||||
|
||||
return (
|
||||
<Show when={passage !== undefined} fallback=<UnavailablePassage style={props.fallbackStyle} />>
|
||||
<div class={props.style}>
|
||||
<svg viewBox={`0 0 215 ${props.fontSize}`}>
|
||||
<Motion.text
|
||||
x="100%" y="55%"
|
||||
dominant-baseline="middle" text-anchor="end"
|
||||
font-size={props.fontSize} style={{ fill: "#000000" }}
|
||||
initial={isApproaching ? undefined : false}
|
||||
animate={{ opacity: [1, 0, 1] }}
|
||||
transition={transition}>
|
||||
{Math.floor(ttwSec / 60)} min
|
||||
</Motion.text>
|
||||
</svg>
|
||||
</div>
|
||||
</Show>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/* TODO: Manage end of service */
|
||||
const DestinationPassages: VoidComponent<{ passages: Passage[], line: Line, destination: string }> = (props) => {
|
||||
const DestinationPassages: VoidComponent<{ line: Line, destination: string }> = (props) => {
|
||||
|
||||
/* TODO: Find where to get data to compute traffic status. */
|
||||
const trafficStatusColor = new Map<TrafficStatus, string>([
|
||||
@@ -62,10 +75,6 @@ const DestinationPassages: VoidComponent<{ passages: Passage[], line: Line, dest
|
||||
[TrafficStatus.BYPASSED, "#ffffff"]
|
||||
]);
|
||||
|
||||
const passagesLength = props.passages.length;
|
||||
const firstPassage = passagesLength > 0 ? props.passages[0] : undefined;
|
||||
const secondPassage = passagesLength > 1 ? props.passages[1] : undefined;
|
||||
|
||||
// TODO: Manage traffic status
|
||||
// const trafficStatusStyle = { fill: trafficStatusColor.get(props.line.trafficStatus) };
|
||||
const trafficStatusStyle = { fill: trafficStatusColor.get(TrafficStatus.UNKNOWN) };
|
||||
@@ -88,17 +97,15 @@ const DestinationPassages: VoidComponent<{ passages: Passage[], line: Line, dest
|
||||
<circle cx="50%" cy="50%" r="24" stroke="#231f20" stroke-width="3" style={trafficStatusStyle} />
|
||||
</svg>
|
||||
</div>
|
||||
<Show when={firstPassage !== undefined} fallback=<UnavailablePassage style={styles.unavailableFirstPassage} />>
|
||||
<TtwPassage style={styles.firstPassage} passage={firstPassage} fontSize={50} />
|
||||
</Show>
|
||||
<Show when={secondPassage !== undefined} fallback=<UnavailablePassage style={styles.unavailableSecondPassage} />>
|
||||
<TtwPassage style={styles.secondPassage} passage={secondPassage} fontSize={45} />
|
||||
</Show>
|
||||
<TtwPassage line={props.line} destination={props.destination} index={0} style={styles.firstPassage}
|
||||
fontSize={50} fallbackStyle={styles.unavailableFirstPassage} />
|
||||
<TtwPassage line={props.line} destination={props.destination} index={1} style={styles.secondPassage}
|
||||
fontSize={45} fallbackStyle={styles.unavailableSecondPassage} />
|
||||
</div >
|
||||
);
|
||||
}
|
||||
|
||||
export type PassagesPanelComponentProps = ParentProps & { passages: Passages, show: boolean };
|
||||
export type PassagesPanelComponentProps = ParentProps & { stopId: number, lineIds: string[], show: boolean };
|
||||
export type PassagesPanelComponent = ParentComponent<PassagesPanelComponentProps>;
|
||||
export const PassagesPanel: PassagesPanelComponent = (props) => {
|
||||
|
||||
@@ -106,29 +113,23 @@ export const PassagesPanel: PassagesPanelComponent = (props) => {
|
||||
if (businessDataContext === undefined)
|
||||
return <div />;
|
||||
|
||||
const { getLine } = businessDataContext;
|
||||
const { getLine, getLineDestinations } = businessDataContext;
|
||||
|
||||
const getLines = async (lineIds: string[]): Promise<Line[]> => {
|
||||
const lines = await Promise.all<Promise<Line>[]>(lineIds.map((lineId) => getLine(lineId)));
|
||||
return lines;
|
||||
}
|
||||
|
||||
const [lineIds, setLinesIds] = createSignal<string[]>([]);
|
||||
const [lines] = createResource<Line[], string[]>(lineIds, getLines);
|
||||
|
||||
createEffect(async () => {
|
||||
setLinesIds(Object.keys(props.passages));
|
||||
});
|
||||
const [lines] = createResource<Line[], string[]>(props.lineIds, getLines);
|
||||
|
||||
return (
|
||||
<div classList={{ [styles.passagesContainer]: true, [styles.displayed]: props.show }} >
|
||||
<Show when={lines() !== undefined} >
|
||||
<For each={lines()}>
|
||||
{(line) =>
|
||||
<Show when={props.passages[line.id]}>
|
||||
<For each={Object.keys(props.passages[line.id])}>
|
||||
<Show when={getLineDestinations(line.id) !== undefined}>
|
||||
<For each={getLineDestinations(line.id)}>
|
||||
{(destination) =>
|
||||
<DestinationPassages passages={props.passages[line.id][destination]} line={line} destination={destination} />
|
||||
<DestinationPassages line={line} destination={destination} />
|
||||
}
|
||||
</For>
|
||||
</Show>
|
||||
|
Reference in New Issue
Block a user