- Add `currentTrainMetadata.ts` to manage carrying forward official position metadata between train snapshots. - Introduce `lineDisplayName.ts` for mapping line IDs to display names. - Create `officialPositionCache.ts` for parsing and serializing official position data with cache validation. - Enhance `officialPositionService.ts` to support persistent caching of official positions and improve resolver functionality. - Update `requestCoordinator.ts` to allow cancellation of polling requests without disposing of the coordinator. - Modify `trainTimeFiltering.ts` to incorporate line ID context when checking for duplicate train data. - Refactor `useCurrentTrain.tsx` to support polling for current train data with official position enrichment. - Add tests for new features, including persistent cache behavior and handling of ambiguous train data.
88 lines
2.3 KiB
TypeScript
88 lines
2.3 KiB
TypeScript
import React, { FC } from "react";
|
|
import { Text, TouchableOpacity } from "react-native";
|
|
import { SheetManager } from "react-native-actions-sheet";
|
|
import { useThemeColors } from "@/lib/theme";
|
|
import {
|
|
buildOfficialPositionEditUrl,
|
|
type OfficialPositionEditFrom,
|
|
} from "@/lib/officialPositionEditUrl";
|
|
import { useNotification } from "@/stateBox/useNotifications";
|
|
import { useTrainMenu } from "@/stateBox/useTrainMenu";
|
|
import type { NavigateFunction } from "@/types";
|
|
|
|
type Props = {
|
|
positionId?: string | null;
|
|
navigate: NavigateFunction;
|
|
from?: OfficialPositionEditFrom;
|
|
closeEachTrainInfo?: boolean;
|
|
compact?: boolean;
|
|
};
|
|
|
|
/**
|
|
* Admin-only entry point to the canonical OfficialPosition Frontend page.
|
|
*
|
|
* The button is rendered only after Native permission and environment config
|
|
* are ready. The Frontend performs its own permission check again after the
|
|
* WebView opens the URL.
|
|
*/
|
|
export const OfficialPositionEditButton: FC<Props> = ({
|
|
positionId,
|
|
navigate,
|
|
from,
|
|
closeEachTrainInfo = false,
|
|
compact = false,
|
|
}) => {
|
|
const {
|
|
updatePermission,
|
|
officialPositionConfig,
|
|
officialPositionConfigReady,
|
|
} = useTrainMenu();
|
|
const { expoPushToken } = useNotification();
|
|
const { fixed, colors } = useThemeColors();
|
|
|
|
const uri = officialPositionConfigReady
|
|
? buildOfficialPositionEditUrl(
|
|
positionId,
|
|
expoPushToken,
|
|
officialPositionConfig,
|
|
from,
|
|
)
|
|
: undefined;
|
|
|
|
if (!updatePermission || !uri) return null;
|
|
|
|
return (
|
|
<TouchableOpacity
|
|
accessibilityRole="button"
|
|
accessibilityLabel="Official Positionを編集"
|
|
onPress={() => {
|
|
if (closeEachTrainInfo) SheetManager.hide("EachTrainInfo");
|
|
navigate("generalWebView", {
|
|
uri,
|
|
useExitButton: false,
|
|
});
|
|
}}
|
|
style={{
|
|
minHeight: compact ? 0 : 40,
|
|
minWidth: compact ? 0 : 68,
|
|
paddingHorizontal: compact ? 0 : 12,
|
|
marginHorizontal: 4,
|
|
borderRadius: 6,
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
backgroundColor: compact ? "transparent" : fixed.primary,
|
|
}}
|
|
>
|
|
<Text
|
|
style={{
|
|
color: fixed.textOnPrimary,
|
|
fontSize: compact ? 12 : 14,
|
|
fontWeight: "bold",
|
|
}}
|
|
>
|
|
編集
|
|
</Text>
|
|
</TouchableOpacity>
|
|
);
|
|
};
|