118 lines
3.8 KiB
TypeScript
118 lines
3.8 KiB
TypeScript
import React from "react";
|
|
import { Alert, BackHandler, View } from "react-native";
|
|
import { WebView } from "react-native-webview";
|
|
import { BigButton } from "./components/atom/BigButton";
|
|
import { useFocusEffect, useNavigation } from "@react-navigation/native";
|
|
import { useThemeColors } from "@/lib/theme";
|
|
import { AS } from "./storageControl";
|
|
import { STORAGE_KEYS } from "@/constants";
|
|
import {
|
|
DEFAULT_JR_DATA_SYSTEM_ENV,
|
|
normalizeJrDataSystemEnvironment,
|
|
rewriteJrDataSystemUrl,
|
|
} from "@/lib/jrDataSystemEnvironment";
|
|
|
|
export default ({ route }) => {
|
|
if (!route.params) {
|
|
return null;
|
|
}
|
|
const { uri, useExitButton = true } = route.params;
|
|
const { goBack } = useNavigation();
|
|
const { fixed } = useThemeColors();
|
|
const webViewRef = React.useRef<WebView>(null);
|
|
const [canGoBack, setCanGoBack] = React.useState(false);
|
|
const [selectedEnvironment, setSelectedEnvironment] = React.useState(
|
|
DEFAULT_JR_DATA_SYSTEM_ENV,
|
|
);
|
|
const [resolvedUri, setResolvedUri] = React.useState("");
|
|
const [isEnvironmentReady, setIsEnvironmentReady] = React.useState(false);
|
|
const hasAlerted = React.useRef(false);
|
|
|
|
React.useEffect(() => {
|
|
let isMounted = true;
|
|
|
|
const applyEnvironment = (value: unknown) => {
|
|
if (!isMounted) return;
|
|
const nextEnvironment = normalizeJrDataSystemEnvironment(value);
|
|
setSelectedEnvironment(nextEnvironment);
|
|
setResolvedUri(
|
|
rewriteJrDataSystemUrl(
|
|
typeof uri === "string" ? uri : "",
|
|
nextEnvironment,
|
|
),
|
|
);
|
|
setIsEnvironmentReady(true);
|
|
};
|
|
|
|
AS.getItem(STORAGE_KEYS.JR_DATA_SYSTEM_ENV)
|
|
.then(applyEnvironment)
|
|
.catch(() => applyEnvironment(DEFAULT_JR_DATA_SYSTEM_ENV));
|
|
|
|
return () => {
|
|
isMounted = false;
|
|
};
|
|
}, [uri]);
|
|
|
|
useFocusEffect(
|
|
React.useCallback(() => {
|
|
const onHardwareBack = () => {
|
|
if (canGoBack) {
|
|
webViewRef.current?.goBack();
|
|
return true;
|
|
}
|
|
goBack();
|
|
return true;
|
|
};
|
|
|
|
const subscription = BackHandler.addEventListener("hardwareBackPress", onHardwareBack);
|
|
return () => subscription.remove();
|
|
}, [canGoBack, goBack])
|
|
);
|
|
return (
|
|
<View style={{ height: "100%", backgroundColor: fixed.primary }}>
|
|
{isEnvironmentReady && (
|
|
<WebView
|
|
source={{ uri: resolvedUri }}
|
|
contentMode="mobile"
|
|
allowsBackForwardNavigationGestures
|
|
ref={webViewRef}
|
|
onShouldStartLoadWithRequest={(request) => {
|
|
if (request.isTopFrame === false) {
|
|
return true;
|
|
}
|
|
|
|
const rewrittenUrl = rewriteJrDataSystemUrl(
|
|
request.url,
|
|
selectedEnvironment,
|
|
);
|
|
if (rewrittenUrl !== request.url) {
|
|
setResolvedUri(rewrittenUrl);
|
|
return false;
|
|
}
|
|
return true;
|
|
}}
|
|
onNavigationStateChange={(navState) => {
|
|
setCanGoBack(navState.canGoBack);
|
|
if (navState.url === "https://unyohub.2pd.jp/integration/succeeded.php") {
|
|
webViewRef.current?.goBack();
|
|
if (!hasAlerted.current) {
|
|
hasAlerted.current = true;
|
|
Alert.alert("鉄道運用HUBへの投稿完了", "運用HUBからのこのアプリへのデータ反映には暫く時間がかかりますので、しばらくお待ちください。", [
|
|
{ text: "完了" },
|
|
]);
|
|
}
|
|
}
|
|
}}
|
|
onMessage={(event) => {
|
|
const { data } = event.nativeEvent;
|
|
const { type } = JSON.parse(data);
|
|
if (type === "back") return webViewRef.current?.goBack();
|
|
if (type === "windowClose") return goBack();
|
|
}}
|
|
/>
|
|
)}
|
|
{useExitButton && <BigButton onPress={goBack} string="閉じる" />}
|
|
</View>
|
|
);
|
|
};
|