refactor: simplify CarouselTypeChanger by removing redundant onPressIn handlers fix: enhance MenuLED memoization for better performance refactor: optimize EachData component with useMemo for derived values fix: improve error handling in TrainPosition data fetching refactor: streamline AddressText component's API call with abort controller refactor: update Menu component to manage selected station state more effectively
121 lines
3.4 KiB
TypeScript
121 lines
3.4 KiB
TypeScript
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
import { InteractionManager, Text, View } from "react-native";
|
|
import LottieView from "lottie-react-native";
|
|
import { useResponsive } from "@/lib/responsive";
|
|
import { useThemeColors } from "@/lib/theme";
|
|
import type { StationProps } from "@/lib/CommonTypes";
|
|
import { LED_vision } from "@/components/発車時刻表/LED_vidion";
|
|
import { LEDFrame } from "@/components/発車時刻表/LED_Vision_Component/LEDFrame";
|
|
|
|
type MenuLEDProps = {
|
|
station: StationProps[];
|
|
};
|
|
|
|
type PreparedLED = {
|
|
key: string;
|
|
station: StationProps[];
|
|
};
|
|
|
|
const MemoizedLEDVision = React.memo(LED_vision);
|
|
|
|
const getStationRenderKey = (station: StationProps[]) =>
|
|
station
|
|
.map(({ StationNumber, Station_JP, lat, lng }) =>
|
|
[StationNumber ?? "", Station_JP, lat, lng].join(":"),
|
|
)
|
|
.join("|");
|
|
|
|
const MenuLEDComponent = ({ station }: MenuLEDProps) => {
|
|
const { colors, fixed } = useThemeColors();
|
|
const { fontScale, verticalScale } = useResponsive();
|
|
const stationKey = getStationRenderKey(station);
|
|
const latestStationRef = useRef(station);
|
|
latestStationRef.current = station;
|
|
const [preparedLED, setPreparedLED] = useState<PreparedLED>(() => ({
|
|
key: stationKey,
|
|
station,
|
|
}));
|
|
const [isLEDReady, setIsLEDReady] = useState(true);
|
|
const activeStation =
|
|
preparedLED.key === stationKey ? preparedLED.station : null;
|
|
|
|
useEffect(() => {
|
|
if (preparedLED.key === stationKey) return;
|
|
|
|
let cancelled = false;
|
|
setIsLEDReady(false);
|
|
const task = InteractionManager.runAfterInteractions(() => {
|
|
if (cancelled) return;
|
|
setPreparedLED({
|
|
key: stationKey,
|
|
station: latestStationRef.current,
|
|
});
|
|
});
|
|
|
|
return () => {
|
|
cancelled = true;
|
|
task.cancel();
|
|
};
|
|
}, [preparedLED.key, stationKey]);
|
|
|
|
const handleContentReady = useCallback(() => {
|
|
setIsLEDReady(true);
|
|
}, []);
|
|
|
|
const showLoading = activeStation === null || !isLEDReady;
|
|
const loadingMinHeight = verticalScale(180);
|
|
|
|
return (
|
|
<LEDFrame style={{ position: "relative", minHeight: loadingMinHeight }}>
|
|
{activeStation && (
|
|
<MemoizedLEDVision
|
|
station={activeStation}
|
|
embedded
|
|
onContentReady={handleContentReady}
|
|
/>
|
|
)}
|
|
{showLoading && (
|
|
<View
|
|
pointerEvents="none"
|
|
style={{
|
|
position: "absolute",
|
|
top: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
left: 0,
|
|
minHeight: loadingMinHeight,
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
backgroundColor: fixed.ledBackground,
|
|
zIndex: 1,
|
|
}}
|
|
>
|
|
<LottieView
|
|
autoPlay
|
|
loop
|
|
style={{ width: 80, height: 80 }}
|
|
source={require("@/assets/51690-loading-diamonds.json")}
|
|
/>
|
|
<Text
|
|
style={{
|
|
marginTop: 12,
|
|
color: "#fff",
|
|
fontSize: fontScale(14),
|
|
}}
|
|
>
|
|
LEDを読み込み中…
|
|
</Text>
|
|
</View>
|
|
)}
|
|
</LEDFrame>
|
|
);
|
|
};
|
|
|
|
const areMenuLEDPropsEqual = (
|
|
previous: MenuLEDProps,
|
|
next: MenuLEDProps,
|
|
) => getStationRenderKey(previous.station) === getStationRenderKey(next.station);
|
|
|
|
export const MenuLED = React.memo(MenuLEDComponent, areMenuLEDPropsEqual);
|
|
MenuLED.displayName = "MenuLED";
|