diff --git a/App.js b/App.js index 38e843f..44d2de1 100644 --- a/App.js +++ b/App.js @@ -1,17 +1,12 @@ import React, { useEffect } from "react"; -import { NavigationContainer } from "@react-navigation/native"; -import { createBottomTabNavigator } from "@react-navigation/bottom-tabs"; import { Platform, UIManager } from "react-native"; import { GestureHandlerRootView } from "react-native-gesture-handler"; +import { AppContainer } from "./Apps.js"; import { UpdateAsync } from "./UpdateAsync.js"; -import TNDView from "./ndView"; import { LogBox } from "react-native"; -import { initIcon } from "./lib/initIcon"; import { FavoriteStationProvider } from "./stateBox/useFavoriteStation"; -import { Top } from "./Top.js"; -import { MenuPage } from "./MenuPage.js"; import { CurrentTrainProvider } from "./stateBox/useCurrentTrain.js"; -import { useAreaInfo, AreaInfoProvider } from "./stateBox/useAreaInfo.js"; +import { AreaInfoProvider } from "./stateBox/useAreaInfo.js"; import { BusAndTrainDataProvider } from "./stateBox/useBusAndTrainData.js"; import { AllTrainDiagramProvider } from "./stateBox/useAllTrainDiagram.js"; import { SheetProvider } from "react-native-actions-sheet"; @@ -20,11 +15,13 @@ import { TrainDelayDataProvider } from "./stateBox/useTrainDelayData.js"; import { SafeAreaProvider } from "react-native-safe-area-context"; import { DeviceOrientationChangeProvider } from "./stateBox/useDeviceOrientationChange.js"; import { TrainMenuProvider } from "./stateBox/useTrainMenu.js"; +import { buildProvidersTree } from "./lib/providerTreeProvider.js"; + LogBox.ignoreLogs([ "ViewPropTypes will be removed", "ColorPropType will be removed", ]); -const Tab = createBottomTabNavigator(); + if (Platform.OS === "android") { if (UIManager.setLayoutAnimationEnabledExperimental) { UIManager.setLayoutAnimationEnabledExperimental(true); @@ -33,77 +30,25 @@ if (Platform.OS === "android") { export default function App() { useEffect(() => UpdateAsync(), []); + + const ProviderTree = buildProvidersTree([ + FavoriteStationProvider, + TrainDelayDataProvider, + CurrentTrainProvider, + AreaInfoProvider, + AllTrainDiagramProvider, + BusAndTrainDataProvider, + TrainMenuProvider, + SheetProvider, + AppContainer, + ]); return ( - - - - - - - - - - - - - - - - - + ); } -export function AppContainer() { - const { areaInfo, areaIconBadgeText } = useAreaInfo(); - const navigationRef = React.useRef(); - return ( - - - - {(props) => } - - - - - {(props) => } - - - - ); -} diff --git a/Apps.js b/Apps.js new file mode 100644 index 0000000..9f4a261 --- /dev/null +++ b/Apps.js @@ -0,0 +1,55 @@ +import React from "react"; +import { NavigationContainer } from "@react-navigation/native"; +import { createBottomTabNavigator } from "@react-navigation/bottom-tabs"; +import { Platform } from "react-native"; +import TNDView from "./ndView"; +import { initIcon } from "./lib/initIcon"; +import { Top } from "./Top.js"; +import { MenuPage } from "./MenuPage.js"; +import { useAreaInfo } from "./stateBox/useAreaInfo.js"; +import "./components/ActionSheetComponents/sheets.js"; + +export function AppContainer() { + const Tab = createBottomTabNavigator(); + const { areaInfo, areaIconBadgeText } = useAreaInfo(); + const navigationRef = React.useRef(); + const getTabProps = (name, label, icon, iconFamily, tabBarBadge) => ({ + name, + options: { + tabBarLabel: label, + headerTransparent: true, + gestureEnabled: true, + tabBarIcon: initIcon(icon, iconFamily), + tabBarBadge, + }, + }); + return ( + + + } + /> + + + } + /> + + + ); +} diff --git a/Top.js b/Top.js index bb9aa87..b2bd3bf 100644 --- a/Top.js +++ b/Top.js @@ -13,13 +13,12 @@ import FavoriteList from "./components/FavoriteList.js"; import { optionData } from "./lib/stackOption.js"; import { useNavigation } from "@react-navigation/native"; import { useCurrentTrain } from "./stateBox/useCurrentTrain.js"; -import { AS } from "./storageControl.js"; +import { ASCore } from "./storageControl.js"; import { useTrainMenu } from "./stateBox/useTrainMenu"; const Stack = createStackNavigator(); export const Top = ({ navigationRef }) => { const { webview } = useCurrentTrain(); - const navigation = useNavigation(); - const { navigate, addListener } = navigation; + const { navigate, addListener } = useNavigation(); //地図用 const { setMapsStationData, injectJavaScript, setInjectJavaScript } = @@ -29,42 +28,43 @@ export const Top = ({ navigationRef }) => { getStationList2().then(setMapsStationData); }, []); const [mapSwitch, setMapSwitch] = React.useState("false"); - const ASCore = ({ k, s, d }) => - AS.getItem(k) - .then((d) => (d ? s(d) : AS.setItem(k, d))) - .catch(() => AS.setItem(k, d)); useEffect(() => { //地図スイッチ ASCore({ k: "mapSwitch", s: setMapSwitch, d: "false" }); }, []); + + const goToFavoriteList = () => navigate("favoriteList"); + useEffect(() => { - const unsubscribe = addListener("tabLongPress", () => - navigate("favoriteList") - ); + const unsubscribe = addListener("tabLongPress", goToFavoriteList); return unsubscribe; - }, [navigation]); - useEffect(() => { - const unsubscribe = navigation.addListener("tabPress", () => { - if (navigationRef.current?.getCurrentRoute().name == "Apps") { - if (mapSwitch == "true") { - navigation.navigate("trainMenu"); - setInjectJavaScript(""); - } else { - webview.current?.injectJavaScript(`AccordionClassEvent()`); - } + }, [{ navigate, addListener }]); + + + const goToTrainMenu = () => { + if (navigationRef.current?.getCurrentRoute().name == "Apps") { + if (mapSwitch == "true") { + navigate("trainMenu"); + setInjectJavaScript(""); } else { - if (mapSwitch == "true") { - if (injectJavaScript) { - webview.current?.injectJavaScript(injectJavaScript); - setInjectJavaScript(""); - } - } - navigation.navigate("Apps"); + webview.current?.injectJavaScript(`AccordionClassEvent()`); } - }); + } else { + if (mapSwitch == "true") { + if (injectJavaScript) { + webview.current?.injectJavaScript(injectJavaScript); + setInjectJavaScript(""); + } + } + navigate("Apps"); + } + }; + + useEffect(() => { + const unsubscribe = addListener("tabPress", goToTrainMenu); return unsubscribe; - }, [navigation, mapSwitch, injectJavaScript]); + }, [{ navigate, addListener }, mapSwitch, injectJavaScript]); return ( diff --git a/components/Apps.js b/components/Apps.js index 38a188b..1b33f12 100644 --- a/components/Apps.js +++ b/components/Apps.js @@ -11,7 +11,7 @@ import Constants from "expo-constants"; import { Ionicons } from "@expo/vector-icons"; import * as Updates from "expo-updates"; -import { AS } from "../storageControl"; +import { AS, ASCore } from "../storageControl"; import { news } from "../config/newsUpdate"; import { getStationList, lineList } from "../lib/getStationList"; import { injectJavascriptData } from "../lib/webViewInjectjavascript"; @@ -36,7 +36,7 @@ export default function Apps() { const { navigate } = useNavigation(); const { isLandscape } = useDeviceOrientationChange(); const handleLayout = () => {}; - const { setInjectJavaScript, mapsStationData: stationData } = useTrainMenu(); + const { setInjectJavaScript, mapsStationData } = useTrainMenu(); //画面表示関連 const [iconSetting, setIconSetting] = useState(undefined); @@ -63,10 +63,6 @@ export default function Apps() { stationMenu, trainMenu ); - const ASCore = ({ k, s, d }) => - AS.getItem(k) - .then((d) => (d ? s(d) : AS.setItem(k, d).then(Updates.reloadAsync))) - .catch(() => AS.setItem(k, d).then(Updates.reloadAsync)); useEffect(() => { //ニュース表示 @@ -79,13 +75,13 @@ export default function Apps() { useEffect(() => { //列車アイコンスイッチ - ASCore({ k: "iconSwitch", s: setIconSetting, d: "true" }); + ASCore({ k: "iconSwitch", s: setIconSetting, d: "true", u: true }); //地図スイッチ - ASCore({ k: "mapSwitch", s: setMapSwitch, d: "false" }); + ASCore({ k: "mapSwitch", s: setMapSwitch, d: "false", u: true }); //駅メニュースイッチ - ASCore({ k: "stationSwitch", s: setStationMenu, d: "true" }); + ASCore({ k: "stationSwitch", s: setStationMenu, d: "true", u: true }); //列車メニュースイッチ - ASCore({ k: "trainSwitch", s: setTrainMenu, d: "true" }); + ASCore({ k: "trainSwitch", s: setTrainMenu, d: "true", u: true }); }, []); const openStationACFromEachTrainInfo = async (stationName) => { @@ -127,7 +123,7 @@ export default function Apps() { {!trainInfo.trainNum && isLandscape ? ( ) : ( - + )} ); } -const NewMenu = ({ webview, LoadError }) => { +const NewMenu = ({ LoadError }) => { + const { webview } = useCurrentTrain(); const { width } = useWindowDimensions(); return ( { + // 基本ケース:ContextProviderが1つしか残っていない場合、それを返して終了する + if (providers.length === 1) { + return providers[0]; + } + + // 配列から最初の2つのContextProviderを取り出す + const FirstProvider = providers.shift(); + const SecondProvider = providers.shift(); + + // 十分な数のContextProviderがあるかどうかを確認 + if (FirstProvider === undefined || SecondProvider === undefined) { + throw new Error("ContextProviderが不足しています"); + } + + // 最初の2つのContextProviderをネストした新しいContextProviderを作成し、再帰する + return buildProvidersTree([ + ({ children }) => ( + + {children} + + ), + ...providers, + ]); +}; diff --git a/storageControl.js b/storageControl.js index 939a943..31feacb 100644 --- a/storageControl.js +++ b/storageControl.js @@ -1,4 +1,5 @@ import storage from "./storageConfig.js"; +import * as Updates from "expo-updates"; export const AS = { getItem: (key) => storage.load({ key }), @@ -13,3 +14,9 @@ export const AS = { }), removeItem: (key) => storage.remove({ key }), }; +export const ASCore = ({ k, s, d, u }) => + AS.getItem(k) + .then((d) => + d ? s(d) : AS.setItem(k, d).then(() => u && Updates.reloadAsync()) + ) + .catch(() => AS.setItem(k, d).then(() => u && Updates.reloadAsync()));