Merge commit '371c32b815dfca0b201e185b282fa726f5b4220a' into patch/5.0.x

This commit is contained in:
harukin-expo-dev-env 2024-09-16 16:08:32 +00:00
commit 628d2a42c9
100 changed files with 18667 additions and 39344 deletions

109
App.js
View File

@ -1,30 +1,28 @@
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 { UpdateAsync } from "./UpdateAsync.js";
import TNDView from "./ndView";
import { AppContainer } from "./Apps";
import { UpdateAsync } from "./UpdateAsync";
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 { BusAndTrainDataProvider } from "./stateBox/useBusAndTrainData.js";
import { AllTrainDiagramProvider } from "./stateBox/useAllTrainDiagram.js";
import { CurrentTrainProvider } from "./stateBox/useCurrentTrain";
import { AreaInfoProvider } from "./stateBox/useAreaInfo";
import { BusAndTrainDataProvider } from "./stateBox/useBusAndTrainData";
import { AllTrainDiagramProvider } from "./stateBox/useAllTrainDiagram";
import { SheetProvider } from "react-native-actions-sheet";
import "./components/ActionSheetComponents/sheets.js";
import { TrainDelayDataProvider } from "./stateBox/useTrainDelayData.js";
import "./components/ActionSheetComponents/sheets";
import { TrainDelayDataProvider } from "./stateBox/useTrainDelayData";
import { SafeAreaProvider } from "react-native-safe-area-context";
import { DeviceOrientationChangeProvider } from "./stateBox/useDeviceOrientationChange.js";
import { TrainMenuProvider } from "./stateBox/useTrainMenu.js";
import { DeviceOrientationChangeProvider } from "./stateBox/useDeviceOrientationChange";
import { TrainMenuProvider } from "./stateBox/useTrainMenu";
import { buildProvidersTree } from "./lib/providerTreeProvider";
import { StationListProvider } from "./stateBox/useStationList";
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 +31,26 @@ if (Platform.OS === "android") {
export default function App() {
useEffect(() => UpdateAsync(), []);
const ProviderTree = buildProvidersTree([
StationListProvider,
FavoriteStationProvider,
TrainDelayDataProvider,
CurrentTrainProvider,
AreaInfoProvider,
AllTrainDiagramProvider,
BusAndTrainDataProvider,
TrainMenuProvider,
SheetProvider,
AppContainer,
]);
return (
<DeviceOrientationChangeProvider>
<SafeAreaProvider>
<GestureHandlerRootView style={{ flex: 1 }}>
<FavoriteStationProvider>
<TrainDelayDataProvider>
<CurrentTrainProvider>
<AreaInfoProvider>
<AllTrainDiagramProvider>
<BusAndTrainDataProvider>
<TrainMenuProvider>
<SheetProvider>
<AppContainer />
</SheetProvider>
</TrainMenuProvider>
</BusAndTrainDataProvider>
</AllTrainDiagramProvider>
</AreaInfoProvider>
</CurrentTrainProvider>
</TrainDelayDataProvider>
</FavoriteStationProvider>
<ProviderTree />
</GestureHandlerRootView>
</SafeAreaProvider>
</DeviceOrientationChangeProvider>
);
}
export function AppContainer() {
const { areaInfo } = useAreaInfo();
const navigationRef = React.useRef();
return (
<NavigationContainer name="Root" style={{ flex: 1 }} ref={navigationRef}>
<Tab.Navigator
tabBarOptions={{ keyboardHidesTabBar: Platform.OS === "android" }}
initialRouteName="login"
lazy={false}
>
<Tab.Screen
name="login"
options={{
tabBarLabel: "位置情報",
headerTransparent: true,
gestureEnabled: true,
tabBarIcon: initIcon("barchart", "AntDesign"),
}}
>
{(props) => <Top {...props} navigationRef={navigationRef} />}
</Tab.Screen>
<Tab.Screen
name="menuPage"
options={{
tabBarLabel: "リンク",
headerTransparent: true,
gestureEnabled: true,
tabBarIcon: initIcon("radio", "Ionicons"),
}}
component={MenuPage}
/>
<Tab.Screen
name="home"
options={{
tabBarLabel: "運行情報",
headerTransparent: true,
gestureEnabled: true,
tabBarIcon: initIcon("train", "Ionicons"),
tabBarBadge: areaInfo ? "!" : undefined,
}}
>
{(props) => <TNDView {...props} />}
</Tab.Screen>
</Tab.Navigator>
</NavigationContainer>
);
}

60
Apps.js Normal file
View File

@ -0,0 +1,60 @@
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";
import { MenuPage } from "./MenuPage";
import { useAreaInfo } from "./stateBox/useAreaInfo";
import "./components/ActionSheetComponents/sheets";
export function AppContainer() {
const Tab = createBottomTabNavigator();
const { areaInfo, areaIconBadgeText, isInfo } = useAreaInfo();
const navigationRef = React.useRef();
const getTabProps = (name, label, icon, iconFamily, tabBarBadge, style) => ({
name,
options: {
tabBarLabel: label,
headerTransparent: true,
gestureEnabled: true,
tabBarIcon: initIcon(icon, iconFamily),
tabBarBadge,
tabBarBadgeStyle: style,
},
});
return (
<NavigationContainer name="Root" style={{ flex: 1 }} ref={navigationRef}>
<Tab.Navigator
tabBarOptions={{ keyboardHidesTabBar: Platform.OS === "android" }}
initialRouteName="login"
lazy={false}
>
<Tab.Screen
{...getTabProps("login", "位置情報", "barchart", "AntDesign")}
children={(props) => <Top {...props} navigationRef={navigationRef} />}
/>
<Tab.Screen
{...getTabProps("menuPage", "リンク", "radio", "Ionicons")}
component={MenuPage}
/>
<Tab.Screen
{...getTabProps(
"home",
"運行情報",
"train",
"Ionicons",
areaInfo ? areaIconBadgeText : undefined,
isInfo && {
backgroundColor: "#00b8ff",
color: "white",
}
)}
children={(props) => <TNDView {...props} />}
/>
</Tab.Navigator>
</NavigationContainer>
);
}

View File

@ -9,10 +9,10 @@ import HowTo from "./howto";
import Menu from "./menu";
import Setting from "./components/Settings/settings";
import { useFavoriteStation } from "./stateBox/useFavoriteStation";
import { optionData } from "./lib/stackOption.js";
import CurrentTrainListView from "./components/CurrentTrainListView.js";
import AllTrainDiagramView from "./components/AllTrainDiagramView.js";
import { useCurrentTrain } from "./stateBox/useCurrentTrain.js";
import { optionData } from "./lib/stackOption";
import CurrentTrainListView from "./components/CurrentTrainListView";
import AllTrainDiagramView from "./components/AllTrainDiagramView";
import { useCurrentTrain } from "./stateBox/useCurrentTrain";
import { useNavigation } from "@react-navigation/native";
const Stack = createStackNavigator();
@ -73,7 +73,7 @@ export function MenuPage() {
<Stack.Screen
name="howto"
options={optionData}
children={(props) => <HowTo {...props} />}
component={HowTo}
/>
</Stack.Navigator>
);

View File

@ -1,10 +1,12 @@
import React from "react";
import React, { FC } from "react";
import { Platform, StatusBar, View } from "react-native";
export default function StatusbarDetect() {
const StatusbarDetect: FC = () => {
if (Platform.OS == "ios") {
return <StatusBar barStyle="dark-content" />;
} else if (Platform.OS == "android") {
return <View />;
}
}
};
export default StatusbarDetect;

77
Top.js
View File

@ -3,68 +3,53 @@ import {
createStackNavigator,
TransitionPresets,
} from "@react-navigation/stack";
import { getStationList2 } from "./lib/getStationList2";
import Apps from "./components/Apps";
import TrainBase from "./components/trainbaseview";
import HowTo from "./howto";
import News from "./components/news.js";
import TrainMenu from "./components/trainMenu.js";
import FavoriteList from "./components/FavoriteList.js";
import { optionData } from "./lib/stackOption.js";
import News from "./components/news";
import TrainMenu from "./components/trainMenu";
import FavoriteList from "./components/FavoriteList";
import { optionData } from "./lib/stackOption";
import { useNavigation } from "@react-navigation/native";
import { useCurrentTrain } from "./stateBox/useCurrentTrain.js";
import { AS } from "./storageControl.js";
import { useCurrentTrain } from "./stateBox/useCurrentTrain";
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 } =
useTrainMenu();
const { injectJavaScript, setInjectJavaScript, mapSwitch } = useTrainMenu();
const goToFavoriteList = () => navigate("favoriteList");
useEffect(() => {
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" });
}, []);
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 (
<Stack.Navigator>

1
assets/StationSign.json Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -1 +1,224 @@
{"type":"FeatureCollection","features":[{"properties":{"name":"五十崎","uri":"https://uedayou.net/jrslod/四国旅客鉄道/内子線/五十崎","color":"FBAF18"},"type":"Feature","geometry":{"type":"LineString","coordinates":[[132.63672,33.53833],[132.63599,33.53782]]}},{"properties":{"name":"五十崎","uri":"https://uedayou.net/jrslod/四国旅客鉄道/内子線/五十崎"},"type":"Feature","geometry":{"type":"Point","coordinates":[132.63599,33.53782]}},{"properties":{"name":"内子","uri":"https://uedayou.net/jrslod/四国旅客鉄道/内子線/内子","color":"FBAF18"},"type":"Feature","geometry":{"type":"LineString","coordinates":[[132.64634,33.55023],[132.64618,33.54873]]}},{"properties":{"name":"内子","uri":"https://uedayou.net/jrslod/四国旅客鉄道/内子線/内子"},"type":"Feature","geometry":{"type":"Point","coordinates":[132.64634,33.55023]}},{"properties":{"name":"喜多山","uri":"https://uedayou.net/jrslod/四国旅客鉄道/内子線/喜多山","color":"FBAF18"},"type":"Feature","geometry":{"type":"LineString","coordinates":[[132.61103,33.53326],[132.61184,33.53359]]}},{"properties":{"name":"喜多山","uri":"https://uedayou.net/jrslod/四国旅客鉄道/内子線/喜多山"},"type":"Feature","geometry":{"type":"Point","coordinates":[132.61103,33.53326]}},{"properties":{"name":"新谷","uri":"https://uedayou.net/jrslod/四国旅客鉄道/内子線/新谷","color":"FBAF18"},"type":"Feature","geometry":{"type":"LineString","coordinates":[[132.59812,33.53417],[132.59894,33.53414]]}},{"properties":{"name":"新谷","uri":"https://uedayou.net/jrslod/四国旅客鉄道/内子線/新谷"},"type":"Feature","geometry":{"type":"Point","coordinates":[132.59812,33.53417]}},{"properties":{"name":"内子線","uri":"https://uedayou.net/jrslod/四国旅客鉄道/内子線","color":"FBAF18"},"type":"Feature","geometry":{"type":"MultiLineString","coordinates":[[[132.61103,33.53326],[132.61184,33.53359]],[[132.63672,33.53833],[132.63599,33.53782]],[[132.59894,33.53414],[132.60008,33.53411],[132.60062,33.5341],[132.60165,33.53407],[132.60238,33.53402],[132.603,33.53393],[132.60436,33.53374],[132.60653,33.53343],[132.60837,33.53317],[132.60913,33.53306],[132.60942,33.53306],[132.60975,33.53306],[132.6103,33.53312],[132.61055,33.53315],[132.61086,33.53321],[132.61103,33.53326]],[[132.64634,33.55023],[132.64618,33.54873]],[[132.59812,33.53417],[132.59894,33.53414]],[[132.64618,33.54873],[132.64615,33.54836],[132.64606,33.5477],[132.64603,33.54735],[132.64593,33.54665],[132.64581,33.54616],[132.64569,33.54575],[132.64547,33.54524],[132.64527,33.54496],[132.64488,33.54449],[132.64463,33.54425],[132.64453,33.54415],[132.64379,33.54359],[132.64294,33.54293],[132.64204,33.54222],[132.64181,33.54204],[132.64106,33.54147],[132.63989,33.54055],[132.63898,33.53985],[132.63788,33.53906],[132.63691,33.53844],[132.6368,33.53838],[132.63672,33.53833]],[[132.63599,33.53782],[132.63492,33.53712],[132.63383,33.53646],[132.63354,33.53631],[132.63319,33.53621],[132.6323,33.53609],[132.63157,33.53597],[132.63102,33.53585],[132.63058,33.53569],[132.63016,33.53549],[132.62986,33.53527],[132.6297,33.53515],[132.62939,33.5348],[132.62913,33.53449],[132.62893,33.5343],[132.62862,33.53407],[132.62839,33.53393],[132.62791,33.53379],[132.62699,33.53356],[132.62575,33.53327],[132.62491,33.53313],[132.62449,33.53306],[132.62386,33.53307],[132.62341,33.53308],[132.6231,33.53306],[132.62248,33.53291],[132.62207,33.5328],[132.62171,33.53272],[132.62149,33.53271],[132.62126,33.53273],[132.62069,33.53283],[132.6203,33.53286],[132.61996,33.53288],[132.61954,33.5329],[132.61937,33.53292],[132.61913,33.53298],[132.6187,33.53311],[132.61841,33.53319],[132.61808,33.53329],[132.61675,33.53368],[132.6161,33.53387],[132.61546,33.53407],[132.615,33.53419],[132.61486,33.53421],[132.61474,33.53419],[132.61458,33.53417],[132.61428,33.5341],[132.61409,33.53407],[132.61341,33.53401],[132.6131,33.53397],[132.61285,33.5339],[132.61221,33.53373],[132.61184,33.53359]]]}}]}
{
"type": "FeatureCollection",
"features": [
{
"properties": {
"name": "新谷",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/内子線/新谷",
"color": "FBAF18"
},
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[132.59812, 33.53417],
[132.59894, 33.53414]
]
}
},
{
"properties": {
"name": "新谷",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/内子線/新谷"
},
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [132.59812, 33.53417] }
},
{
"properties": {
"name": "喜多山",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/内子線/喜多山",
"color": "FBAF18"
},
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[132.61103, 33.53326],
[132.61184, 33.53359]
]
}
},
{
"properties": {
"name": "喜多山",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/内子線/喜多山"
},
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [132.61103, 33.53326] }
},
{
"properties": {
"name": "五十崎",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/内子線/五十崎",
"color": "FBAF18"
},
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[132.63672, 33.53833],
[132.63599, 33.53782]
]
}
},
{
"properties": {
"name": "五十崎",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/内子線/五十崎"
},
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [132.63599, 33.53782] }
},
{
"properties": {
"name": "内子",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/内子線/内子",
"color": "FBAF18"
},
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[132.64634, 33.55023],
[132.64618, 33.54873]
]
}
},
{
"properties": {
"name": "内子",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/内子線/内子"
},
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [132.64634, 33.55023] }
},
{
"properties": {
"name": "内子線",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/内子線",
"color": "FBAF18"
},
"type": "Feature",
"geometry": {
"type": "MultiLineString",
"coordinates": [
[
[132.61103, 33.53326],
[132.61184, 33.53359]
],
[
[132.63672, 33.53833],
[132.63599, 33.53782]
],
[
[132.59894, 33.53414],
[132.60008, 33.53411],
[132.60062, 33.5341],
[132.60165, 33.53407],
[132.60238, 33.53402],
[132.603, 33.53393],
[132.60436, 33.53374],
[132.60653, 33.53343],
[132.60837, 33.53317],
[132.60913, 33.53306],
[132.60942, 33.53306],
[132.60975, 33.53306],
[132.6103, 33.53312],
[132.61055, 33.53315],
[132.61086, 33.53321],
[132.61103, 33.53326]
],
[
[132.64634, 33.55023],
[132.64618, 33.54873]
],
[
[132.59812, 33.53417],
[132.59894, 33.53414]
],
[
[132.64618, 33.54873],
[132.64615, 33.54836],
[132.64606, 33.5477],
[132.64603, 33.54735],
[132.64593, 33.54665],
[132.64581, 33.54616],
[132.64569, 33.54575],
[132.64547, 33.54524],
[132.64527, 33.54496],
[132.64488, 33.54449],
[132.64463, 33.54425],
[132.64453, 33.54415],
[132.64379, 33.54359],
[132.64294, 33.54293],
[132.64204, 33.54222],
[132.64181, 33.54204],
[132.64106, 33.54147],
[132.63989, 33.54055],
[132.63898, 33.53985],
[132.63788, 33.53906],
[132.63691, 33.53844],
[132.6368, 33.53838],
[132.63672, 33.53833]
],
[
[132.63599, 33.53782],
[132.63492, 33.53712],
[132.63383, 33.53646],
[132.63354, 33.53631],
[132.63319, 33.53621],
[132.6323, 33.53609],
[132.63157, 33.53597],
[132.63102, 33.53585],
[132.63058, 33.53569],
[132.63016, 33.53549],
[132.62986, 33.53527],
[132.6297, 33.53515],
[132.62939, 33.5348],
[132.62913, 33.53449],
[132.62893, 33.5343],
[132.62862, 33.53407],
[132.62839, 33.53393],
[132.62791, 33.53379],
[132.62699, 33.53356],
[132.62575, 33.53327],
[132.62491, 33.53313],
[132.62449, 33.53306],
[132.62386, 33.53307],
[132.62341, 33.53308],
[132.6231, 33.53306],
[132.62248, 33.53291],
[132.62207, 33.5328],
[132.62171, 33.53272],
[132.62149, 33.53271],
[132.62126, 33.53273],
[132.62069, 33.53283],
[132.6203, 33.53286],
[132.61996, 33.53288],
[132.61954, 33.5329],
[132.61937, 33.53292],
[132.61913, 33.53298],
[132.6187, 33.53311],
[132.61841, 33.53319],
[132.61808, 33.53329],
[132.61675, 33.53368],
[132.6161, 33.53387],
[132.61546, 33.53407],
[132.615, 33.53419],
[132.61486, 33.53421],
[132.61474, 33.53419],
[132.61458, 33.53417],
[132.61428, 33.5341],
[132.61409, 33.53407],
[132.61341, 33.53401],
[132.6131, 33.53397],
[132.61285, 33.5339],
[132.61221, 33.53373],
[132.61184, 33.53359]
]
]
}
}
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,256 @@
{
"type": "FeatureCollection",
"features": [
{
"properties": {
"name": "児島",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/本四備讃線/児島",
"color": "0073BC"
},
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[133.80748, 34.46183],
[133.8079, 34.4638]
]
}
},
{
"properties": {
"name": "児島",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/本四備讃線/児島"
},
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [133.80748, 34.46183] }
},
{
"properties": {
"name": "宇多津",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/本四備讃線/宇多津",
"color": "0073BC"
},
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[133.81324, 34.30552],
[133.81426, 34.30712]
]
}
},
{
"properties": {
"name": "宇多津",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/本四備讃線/宇多津"
},
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [133.81324, 34.30552] }
},
{
"properties": {
"name": "本四備讃線",
"uri": "https://uedayou.net/jrslod/四国旅客鉄道/本四備讃線",
"color": "0073BC"
},
"type": "Feature",
"geometry": {
"type": "MultiLineString",
"coordinates": [
[
[133.81426, 34.30712],
[133.81504, 34.30838],
[133.81622, 34.31028],
[133.81778, 34.31274]
],
[
[133.81324, 34.30552],
[133.81426, 34.30712]
],
[
[133.80748, 34.46183],
[133.8079, 34.4638]
],
[
[133.80745, 34.46169],
[133.80748, 34.46183]
],
[
[133.80745, 34.46169],
[133.80735, 34.46116],
[133.80723, 34.46026],
[133.80714, 34.45964],
[133.807, 34.45809],
[133.80697, 34.45769],
[133.80697, 34.45753],
[133.80693, 34.45694],
[133.80691, 34.4557],
[133.80692, 34.45548],
[133.80691, 34.45543],
[133.80693, 34.45494],
[133.80696, 34.45464],
[133.80704, 34.45385],
[133.80714, 34.45314],
[133.8072, 34.45271],
[133.80727, 34.45221],
[133.80737, 34.45148],
[133.80742, 34.45102],
[133.80745, 34.45087],
[133.80762, 34.44957],
[133.80765, 34.4494],
[133.80779, 34.44837],
[133.80789, 34.44765],
[133.80793, 34.44736],
[133.80804, 34.4467],
[133.80813, 34.44589],
[133.80828, 34.4445],
[133.80825, 34.4442],
[133.80833, 34.44366],
[133.80837, 34.44336],
[133.8084, 34.44309],
[133.80842, 34.44263],
[133.80842, 34.44233],
[133.80842, 34.44203],
[133.8084, 34.44183],
[133.8083, 34.44071],
[133.80828, 34.44059],
[133.80819, 34.4399],
[133.80807, 34.43932],
[133.80763, 34.43745],
[133.80731, 34.4362],
[133.80714, 34.43555],
[133.80706, 34.43527],
[133.80691, 34.4346],
[133.80643, 34.43278],
[133.80594, 34.43084],
[133.8057, 34.42991],
[133.80545, 34.42891],
[133.8054, 34.42866],
[133.805, 34.42706],
[133.80491, 34.42672],
[133.80491, 34.4267],
[133.80463, 34.42556],
[133.80445, 34.42488],
[133.80435, 34.42447],
[133.8043, 34.4243],
[133.80403, 34.42323],
[133.804, 34.4231],
[133.8039, 34.42246],
[133.80386, 34.42206],
[133.80385, 34.42197],
[133.80384, 34.42187],
[133.80382, 34.42161],
[133.80383, 34.42155],
[133.80383, 34.42146],
[133.80382, 34.4212],
[133.80383, 34.42093],
[133.80384, 34.42074],
[133.8039, 34.42026],
[133.80393, 34.41992],
[133.80403, 34.41939],
[133.80425, 34.41856],
[133.80446, 34.41786],
[133.80506, 34.41631],
[133.80553, 34.41514],
[133.80581, 34.41441],
[133.80615, 34.41329],
[133.80657, 34.41181],
[133.80675, 34.41122],
[133.8068, 34.41106],
[133.80715, 34.40959],
[133.80768, 34.40746],
[133.8082, 34.40555],
[133.80908, 34.4024],
[133.80918, 34.40207],
[133.80999, 34.39922],
[133.81061, 34.39702],
[133.81079, 34.39659],
[133.8111, 34.39597],
[133.8114, 34.39544],
[133.81192, 34.39468],
[133.81254, 34.39392],
[133.8126, 34.39384],
[133.81397, 34.39239],
[133.81532, 34.39103],
[133.81581, 34.39044],
[133.81636, 34.38977],
[133.81687, 34.38902],
[133.81732, 34.38818],
[133.81775, 34.38715],
[133.81804, 34.38621],
[133.81811, 34.386],
[133.81902, 34.38312],
[133.81974, 34.38088],
[133.8208, 34.37748],
[133.82082, 34.37741],
[133.82236, 34.3725],
[133.8236, 34.36876],
[133.82361, 34.36872],
[133.82487, 34.365],
[133.82609, 34.3614],
[133.82654, 34.36006],
[133.82729, 34.35785],
[133.82828, 34.35487],
[133.82839, 34.35449],
[133.82854, 34.35392],
[133.82861, 34.35335],
[133.82865, 34.35271],
[133.8286, 34.35153],
[133.82857, 34.35127],
[133.82854, 34.35097],
[133.82835, 34.34966],
[133.82809, 34.34812],
[133.8277, 34.34593],
[133.82715, 34.34275],
[133.82707, 34.34234],
[133.82665, 34.33997],
[133.82636, 34.33823],
[133.82627, 34.33756],
[133.82627, 34.33706],
[133.82626, 34.3366],
[133.82642, 34.33542],
[133.82657, 34.33461],
[133.82678, 34.33343],
[133.82688, 34.33296],
[133.82703, 34.33215],
[133.82724, 34.33088],
[133.82714, 34.33036],
[133.8271, 34.33009],
[133.82706, 34.3297],
[133.82702, 34.32933],
[133.8268, 34.3284],
[133.82653, 34.32749],
[133.82626, 34.32674],
[133.82574, 34.32565],
[133.82473, 34.32388],
[133.82344, 34.32159],
[133.82326, 34.32129],
[133.82235, 34.31973],
[133.82224, 34.31954]
],
[
[133.81778, 34.31274],
[133.81853, 34.31395],
[133.82015, 34.31632],
[133.82147, 34.31828],
[133.82224, 34.31954]
],
[
[133.82224, 34.31954],
[133.82207, 34.31872],
[133.82199, 34.31824],
[133.82198, 34.31764],
[133.82204, 34.31701],
[133.82219, 34.31661],
[133.8226, 34.31597],
[133.82315, 34.31523],
[133.8237, 34.31472],
[133.8241, 34.3144],
[133.82457, 34.31411],
[133.82565, 34.31357]
]
]
}
}
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,9 +2,8 @@ import React, { useRef } from "react";
import { Platform } from "react-native";
import ActionSheet from "react-native-actions-sheet";
import { EachTrainInfoCore } from "./EachTrainInfoCore";
export const EachTrainInfo = (props) => {
if (!props.payload) return <></>;
export const EachTrainInfo = ({ payload }) => {
if (!payload) return <></>;
const actionSheetRef = useRef(null);
return (
<ActionSheet
@ -17,7 +16,7 @@ export const EachTrainInfo = (props) => {
//useBottomSafeAreaPadding={Platform.OS == "android"}
>
<EachTrainInfoCore {...{ actionSheetRef, ...props.payload }} />
<EachTrainInfoCore {...{ actionSheetRef, ...payload }} />
</ActionSheet>
);
};

View File

@ -1,8 +1,8 @@
import React from "react";
import React, { FC } from "react";
import { View, Text, TouchableWithoutFeedback } from "react-native";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import { Linking } from "react-native";
export const DataFromButton = ({ i }) => {
export const DataFromButton: FC<{ i: string }> = ({ i }) => {
const [station, se, time] = i.split(",");
return (
<TouchableWithoutFeedback

View File

@ -1,17 +1,17 @@
import React from "react";
import { View, Text } from "react-native";
import React, { CSSProperties, FC } from "react";
import { View, Text, StyleProp, TextStyle, ViewStyle } from "react-native";
export const StateBox = ({ text, title, style, mode }) => (
type stateBox = {
text: string;
title: string;
style?: ViewStyle;
mode?: number;
};
export const StateBox: FC<stateBox> = ({ text, title, style, mode }) => (
<View style={{ ...(mode == 2 ? boxStyle2 : boxStyle), ...style }}>
<Text style={{ fontSize: 12, color: "#0099CC" }}>{title}</Text>
<View style={{ flex: 1 }} />
<View
style={{
color: "#0099CC",
textAlign: "right",
flexDirection: mode == 2 ? "row" : "column",
}}
>
<View style={{ flexDirection: mode == 2 ? "row" : "column" }}>
{text?.match("") ? (
<>
<Text style={mode == 2 ? boxTextStyle2 : boxTextStyle}>
@ -30,27 +30,27 @@ export const StateBox = ({ text, title, style, mode }) => (
</View>
</View>
);
const boxStyle = {
const boxStyle: ViewStyle = {
flex: 1,
backgroundColor: "white",
borderRadius: 10,
padding: 10,
margin: 10,
};
const boxStyle2 = {
const boxStyle2: ViewStyle = {
flex: 1,
backgroundColor: "white",
borderRadius: 10,
padding: 5,
margin: 5,
};
const boxTextStyle2 = {
const boxTextStyle2: TextStyle = {
fontSize: 18,
color: "#0099CC",
textAlign: "right",
};
const boxTextStyle = {
const boxTextStyle: TextStyle = {
fontSize: 25,
color: "#0099CC",
textAlign: "right",

View File

@ -5,7 +5,6 @@ import { useDeviceOrientationChange } from "../../../stateBox/useDeviceOrientati
import { getStationList2 } from "../../../lib/getStationList2";
import { useCurrentTrain } from "../../../stateBox/useCurrentTrain";
import { SheetManager } from "react-native-actions-sheet";
import { useNavigation } from "@react-navigation/native";
export const TrainDataView = ({
currentTrainData,

View File

@ -1,7 +1,6 @@
import React, { useEffect, useMemo, useState } from "react";
import {
View,
LayoutAnimation,
Text,
TouchableOpacity,
StyleSheet,
@ -9,7 +8,6 @@ import {
BackHandler,
Linking,
} from "react-native";
import { Ionicons } from "@expo/vector-icons";
import { SheetManager } from "react-native-actions-sheet";
import { AS } from "../../storageControl";
import trainList from "../../assets/originData/trainList";
@ -33,19 +31,21 @@ import { getType } from "../../lib/eachTrainInfoCoreLib/getType";
import { searchSpecialTrain } from "../../lib/eachTrainInfoCoreLib/searchSpecialTrain";
import { openBackTrainInfo } from "../../lib/eachTrainInfoCoreLib/openBackTrainInfo";
import { ShowSpecialTrain } from "./EachTrainInfo/ShowSpecialTrain";
import { useNavigation } from "@react-navigation/native";
import { useTrainMenu } from "../../stateBox/useTrainMenu";
import { HeaderText } from "./EachTrainInfoCore/HeaderText";
import { useStationList } from "../../stateBox/useStationList";
export const EachTrainInfoCore = ({
actionSheetRef,
data,
originalStationList,
openStationACFromEachTrainInfo,
from,
setTrainInfo,
navigate,
}) => {
// const [actionSheetHorizonalScroll, setActionSheetHorizonalScroll] = useState(false);
const { currentTrain } = useCurrentTrain();
const { originalStationList } = useStationList();
const { setTrainInfo } = useTrainMenu();
const [currentTrainData, setCurrentTrainData] = useState();
// const [actionSheetHorizonalScroll, setActionSheetHorizonalScroll] = useState(false);
@ -91,7 +91,7 @@ export const EachTrainInfoCore = ({
);
// 使用例
const stopStationIDList = trainData.map((i, index) => {
const stopStationIDList = trainData.map((i) => {
const [station, se, time] = i.split(",");
const Stations = stationList.map((a) =>
a.filter((d) => d.StationName == station)
@ -132,7 +132,7 @@ export const EachTrainInfoCore = ({
}
}, [data.limited, trainData]);
const { height, width } = useWindowDimensions();
const { height } = useWindowDimensions();
const { isLandscape } = useDeviceOrientationChange();
const [trueTrainID, setTrueTrainID] = useState();
@ -217,7 +217,7 @@ export const EachTrainInfoCore = ({
.then((d) => {
if (d) setTrainPositionSwitch(d);
})
.catch((d) => AS.setItem("trainPositionSwitch", "false"));
.catch(() => AS.setItem("trainPositionSwitch", "false"));
}, []);
const openTrainInfo = (d) => {
@ -236,10 +236,9 @@ export const EachTrainInfoCore = ({
}${TrainNumber}`,
},
navigate,
originalStationList,
from: from == "LED" ? "LED2" : "NearTrainDiagramView",
};
if (setTrainInfo) {
if (isLandscape) {
setTrainInfo(payload.data);
} else {
SheetManager.hide("EachTrainInfo").then(() => {
@ -279,36 +278,17 @@ export const EachTrainInfoCore = ({
/>
</View>
)}
<View style={{ padding: 10, flexDirection: "row", alignItems: "center" }}>
<Text style={{ fontSize: 20, fontWeight: "bold", color: "white" }}>
{trainName}
</Text>
<View style={{ flex: 1 }} />
<Text style={{ fontSize: 20, fontWeight: "bold", color: "white" }}>
{showHeadStation.map((d) => `${headStation[d].id} + `)}
{data.trainNum}
{showTailStation.map((d) => ` + ${tailStation[d].id}`)}
</Text>
<HeaderText
data={data}
trainData={trainData}
showHeadStation={showHeadStation}
showTailStation={showTailStation}
headStation={headStation}
tailStation={tailStation}
navigate={navigate}
from={from}
/>
{data.limited != undefined &&
getType(data.limited.split(":")[0]) &&
!data.limited.split(":")[1].match("サンポート") && (
<Ionicons
name="subway"
color="white"
size={30}
style={{ margin: 5 }}
onPress={() => {
LayoutAnimation.easeInEaseOut(); //setLoadingDelayData(true);
navigate("trainbase", {
info: "train.html?tn=" + data.trainNum,
from,
});
SheetManager.hide("EachTrainInfo");
}}
/>
)}
</View>
<DynamicHeaderScrollView
from={from}
styles={styles}

View File

@ -0,0 +1,73 @@
import React, { CSSProperties, FC, useEffect, useMemo, useState } from "react";
import { Text, View, LayoutAnimation, TextStyle } from "react-native";
import { Ionicons } from "@expo/vector-icons";
import { SheetManager } from "react-native-actions-sheet";
import { getType } from "../../../lib/eachTrainInfoCoreLib/getType";
import { migrateTrainName } from "../../../lib/eachTrainInfoCoreLib/migrateTrainName";
import { TrainIconStatus } from "./trainIconStatus";
import { TrainViewIcon } from "./trainViewIcon";
type Props = {
data: { trainNum: string; limited: string };
trainData: string[];
showHeadStation: number[];
showTailStation: number[];
headStation: { id: string }[];
tailStation: { id: string }[];
navigate: any;
from: string;
};
const textConfig: TextStyle = {
fontSize: 20,
fontWeight: "bold",
color: "white",
};
export const HeaderText: FC<Props> = ({
data,
trainData,
showHeadStation,
showTailStation,
headStation,
tailStation,
navigate,
from,
}) => {
const trainName = useMemo(() => {
if (!data.limited) return "";
const limitedArray = data.limited.split(":");
const type = getType(limitedArray[0]);
switch (true) {
case !!limitedArray[1]:
// 特急の場合は、列車名を取得
return type + migrateTrainName(limitedArray[1]);
case trainData.length == 0:
// 特急以外の場合は、列車番号を取得
return type;
default:
// 行先がある場合は、行先を取得
return (
type +
migrateTrainName(
trainData[trainData.length - 1].split(",")[0] + "行き"
)
);
}
}, [data.limited, trainData]);
return (
<View style={{ padding: 10, flexDirection: "row", alignItems: "center" }}>
<TrainIconStatus {...{ data, navigate, from}}/>
<Text style={textConfig}>{trainName}</Text>
<View style={{ flex: 1 }} />
<Text style={textConfig}>
{showHeadStation.map((d) => `${headStation[d].id} + `)}
{data.trainNum}
{showTailStation.map((d) => ` + ${tailStation[d].id}`)}
</Text>
<TrainViewIcon {...{ data, navigate, from }} />
</View>
);
};

View File

@ -0,0 +1,94 @@
import React, { ComponentProps, FC, useEffect, useState } from "react";
import { View, Image, TouchableOpacity } from "react-native";
import { Ionicons } from "@expo/vector-icons";
import dayjs from "dayjs";
import { useInterval } from "../../../lib/useInterval";
import { Icon } from "@expo/vector-icons/build/createIconSet";
import { SheetManager } from "react-native-actions-sheet";
type GlyphNames = ComponentProps<typeof Ionicons>["name"];
type Props = {
data: { trainNum: string; limited: string };
navigate: any;
from: string;
};
type apt = {
name: GlyphNames;
color: string;
};
export const TrainIconStatus: FC<Props> = ({ data, navigate, from }) => {
const [trainIcon, setTrainIcon] = useState(null);
const [anpanmanStatus, setAnpanmanStatus] = useState<apt>();
useEffect(() => {
if (!data.trainNum) return;
switch (data.trainNum) {
case "32D":
case "36D":
case "44D":
case "48D":
case "56D":
case "33D":
case "37D":
case "45D":
case "49D":
case "57D":
setTrainIcon(
`https://n8n.haruk.in/webhook/dosan-anpanman-pictures.png?trainNum=${
data.trainNum
}&day=${dayjs().format("yyyy-MM-DD")}`
);
fetch(
`https://n8n.haruk.in/webhook/dosan-anpanman?trainNum=${
data.trainNum
}&month=${dayjs().format("M")}&day=${dayjs().format("D")}`
)
.then((d) => d.json())
.then((d) => {
console.log(d);
if (d.trainStatus == "") {
//setAnpanmanStatus({name:"checkmark-circle-outline",color:"blue"});
} else if (d.trainStatus == "▲") {
setAnpanmanStatus({ name: "warning-outline", color: "yellow" });
} else if (d.trainStatus == "×") {
setAnpanmanStatus({ name: "close-circle-outline", color: "red" });
}
});
break;
}
}, [data.trainNum]);
const [move, setMove] = useState(true);
useInterval(
() => {
// anpanmanStatusがデータを持っているなら実行
if (anpanmanStatus) setMove(!move);
},
1000,
true
);
return (
<>
{trainIcon && (
<TouchableOpacity
onPress={() => {
navigate("howto", {
info: "https://www.jr-eki.com/aptrain/naani/dosan/jikoku.html",
goTo: from == "LED" ? "menu" : from,
});
SheetManager.hide("EachTrainInfo");
}}
>
{move ? (
<Image
source={{ uri: trainIcon }}
style={{ height: 30, width: 30, margin: 5 }}
resizeMethod="resize"
/>
) : (
<Ionicons {...anpanmanStatus} size={30} style={{ margin: 5 }} />
)}
</TouchableOpacity>
)}
</>
);
};

View File

@ -0,0 +1,41 @@
import React, { FC, useEffect, useState } from "react";
import { Ionicons } from "@expo/vector-icons";
import { LayoutAnimation } from "react-native";
import { SheetManager } from "react-native-actions-sheet";
import { getType } from "../../../lib/eachTrainInfoCoreLib/getType";
type Props = {
data: { trainNum: string; limited: string };
navigate: any;
from: string;
};
export const TrainViewIcon: FC<Props> = ({ data, navigate, from }) => {
const [isTrainView, setIsTrainView] = useState(false);
//トレインビュー表示対象(特急、マリン)かを判定
useEffect(() => {
if (!data.limited) return;
setIsTrainView(
getType(data.limited.split(":")[0]) &&
!data.limited.split(":")[1].match("サンポート")
);
}, [data.limited]);
const onPressTrainView = () => {
LayoutAnimation.easeInEaseOut(); //setLoadingDelayData(true);
navigate("trainbase", {
info: "train.html?tn=" + data.trainNum,
from,
});
SheetManager.hide("EachTrainInfo");
};
return isTrainView ? (
<Ionicons
name="subway"
color="white"
size={30}
style={{ margin: 5 }}
onPress={onPressTrainView}
/>
) : (
<></>
);
};

View File

@ -15,7 +15,6 @@ import Sign from "../../components/駅名表/Sign";
import { TicketBox } from "../atom/TicketBox";
import { widthPercentageToDP as wp } from "react-native-responsive-screen";
import lineColorList from "../../assets/originData/lineColorList";
import { getPDFViewURL } from "../../lib/getPdfViewURL";
import { useBusAndTrainData } from "../../stateBox/useBusAndTrainData";
import { AS } from "../../storageControl";
@ -24,7 +23,6 @@ export const StationDeteilView = (props) => {
if (!props.payload) return <></>;
const {
currentStation,
originalStationList,
navigate,
onExit,
goTo,
@ -100,7 +98,6 @@ export const StationDeteilView = (props) => {
>
<Sign
currentStation={currentStation}
originalStationList={originalStationList}
oP={() => {
usePDFView == "true"
? Linking.openURL(currentStation[0].StationTimeTable)
@ -115,13 +112,6 @@ export const StationDeteilView = (props) => {
/>
</View>
)}
{/* {currentStation &&
currentStation.map((d) => (
<NexPreStationLine
currentStation={d}
originalStationList={originalStationList}
/>
))} */}
{currentStation &&
currentStation[0].JrHpUrl &&
currentStation[0].StationNumber != "M12" && (
@ -131,7 +121,6 @@ export const StationDeteilView = (props) => {
info:
currentStation[0].JrHpUrl.replace("/index.html", "/") +
"/kounai_map.html",
goTo,
useShow,
});
@ -231,140 +220,6 @@ export const StationDeteilView = (props) => {
);
};
const StationName = (props) => {
const { stringData, ss } = props;
return (
<View style={ss}>
<Text style={styleSheet.下枠駅名}>{stringData.Station_JP}</Text>
<Text style={styleSheet.下枠駅名}>{stringData.Station_EN}</Text>
</View>
);
};
const NexPreStationLine = ({ currentStation, originalStationList }) => {
const [preStation, setPreStation] = useState();
const [nexStation, setNexStation] = useState();
const [lineName, setLineName] = useState();
useEffect(() => {
getPreNextStation(currentStation);
}, [currentStation]);
useEffect(() => {
if (!currentStation) return () => {};
getPreNextStation(currentStation);
}, []);
const getPreNextStation = (now) => {
const lineList = [
"予讃線(高松-松山間)[Y]",
"予讃線(松山-宇和島間)[U]",
"予讃線/愛ある伊予灘線(向井原-伊予大洲間)[S]",
"土讃線(多度津-高知間)[D]",
"土讃線(高知-窪川間)[K]",
"高徳線(高松-徳島間)[T]",
"徳島線(徳島-阿波池田間)[B]",
"鳴門線(池谷-鳴門間)[N]",
"瀬戸大橋線(児島-宇多津間)[M]",
];
let returnData;
lineList.forEach((d) => {
let cache = originalStationList[d].findIndex(
(data) => data.StationNumber == now.StationNumber
);
if (cache != -1) {
returnData = [
originalStationList[d][cache - 1],
originalStationList[d][cache + 1],
d,
];
}
});
setPreStation(returnData[0]);
setNexStation(returnData[1]);
setLineName(returnData[2]);
};
return (
<View
style={{
height: 50,
backgroundColor: lineName
? lineColorList[lineName.split("[")[1].replace("]", "")]
: "red",
flexDirection: "row",
alignContent: "center",
alignItems: "center",
}}
>
<View style={styleSheet.下枠フレーム}>
{preStation ? (
<>
<Text style={styleSheet.下枠左右マーク}></Text>
{preStation.StationNumber ? (
<View style={styleSheet.下枠駅ナンバー}>
<View style={{ flex: 1 }} />
<Text
style={{
fontSize: parseInt("10%"),
color: "white",
}}
>
{preStation.StationNumber}
</Text>
<View style={{ flex: 1 }} />
</View>
) : (
<></>
)}
<StationName
stringData={preStation}
ss={{ flex: 1, alignItems: "flex-start" }}
/>
</>
) : (
<></>
)}
</View>
<Text
style={{
fontSize: parseInt("10%"),
color: "white",
textAlign: "center",
}}
>
{lineName &&
lineName
.split("(")
.map((d, index) => (index == 1 ? "(" + d : d))
.join("\n")}
</Text>
<View style={styleSheet.下枠フレーム}>
{nexStation ? (
<>
<StationName
stringData={nexStation}
ss={{ flex: 1, alignItems: "flex-end" }}
/>
{nexStation.StationNumber ? (
<View style={styleSheet.下枠駅ナンバー}>
<View style={{ flex: 1 }} />
<Text style={{ fontSize: parseInt("15%"), color: "white" }}>
{nexStation.StationNumber}
</Text>
<View style={{ flex: 1 }} />
</View>
) : (
<></>
)}
<Text style={styleSheet.下枠左右マーク}></Text>
</>
) : (
<></>
)}
</View>
</View>
);
};
const 駅構内図 = (props) => {
const [open, setOpen] = useState(false);
@ -439,85 +294,4 @@ const Handler = () => {
return () => backHandler.remove();
}, []);
return <></>;
};
const styleSheet = {
外枠: {
width: wp("80%"),
height: (wp("80%") / 20) * 9,
borderColor: "#2E94BB",
borderWidth: 1,
backgroundColor: "white",
},
下帯: {
position: "absolute",
bottom: "0%",
left: "0%",
width: "100%",
height: "30%",
backgroundColor: "#2E94BB",
},
JRStyle: {
position: "absolute",
top: "2%",
left: "2%",
fontWeight: "bold",
fontSize: parseInt("30%"),
color: "#2E94BB",
},
stationNameAreaOverWrap: {
position: "absolute",
top: "10%",
alignContent: "center",
flexDirection: "row",
},
Station_JP: {
fontWeight: "bold",
fontSize: parseInt("40%"),
color: "#005170",
},
Station_EN: {
fontWeight: "bold",
fontSize: parseInt("15%"),
color: "#005170",
},
下帯内容: {
position: "absolute",
bottom: "0%",
height: "30%",
width: "100%",
alignItems: "center",
flexDirection: "column",
},
下枠フレーム: {
flex: 1,
flexDirection: "row",
alignContent: "center",
height: wp("10%"),
},
下枠左右マーク: {
fontWeight: "bold",
fontSize: parseInt("20%"),
color: "white",
paddingHorizontal: 10,
textAlignVertical: "center",
},
下枠駅ナンバー: {
alignContent: "center",
alignItems: "center",
width: wp("8%"),
height: wp("8%"),
margin: wp("1%"),
borderColor: "white",
borderWidth: parseInt("2%"),
borderRadius: parseInt("100%"),
},
下枠駅名: {
fontWeight: "bold",
fontSize: parseInt("15%"),
color: "white",
flex: 1,
paddingHorizontal: 0,
marginVertical: 0,
textAlignVertical: "center",
},
};
};

View File

@ -1,42 +1,26 @@
import React, { useEffect, useRef } from "react";
import {
View,
LayoutAnimation,
ScrollView,
Linking,
Text,
TouchableOpacity,
Platform,
BackHandler,
} from "react-native";
import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
import ActionSheet, {
SheetManager,
useScrollHandlers,
} from "react-native-actions-sheet";
import LottieView from "lottie-react-native";
import ActionSheet, { SheetManager } from "react-native-actions-sheet";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import ViewShot from "react-native-view-shot";
import * as Sharing from "expo-sharing";
import { useTrainDelayData } from "../../stateBox/useTrainDelayData";
import { useTrainMenu } from "../../stateBox/useTrainMenu";
import lineColorList from "../../assets/originData/lineColorList";
import { stationIDPair } from "../../lib/getStationList2";
import { lineListPair } from "../../lib/getStationList";
export const TrainMenuLineSelector = () => {
const { getTime, delayData, loadingDelayData, setLoadingDelayData } =
useTrainDelayData();
const {
selectedLine,
setSelectedLine,
mapsStationData: stationData,
setMapsStationData,
} = useTrainMenu();
const actionSheetRef = useRef(null);
const scrollHandlers = useScrollHandlers("scrollview-1", actionSheetRef);
const insets = useSafeAreaInsets();
const viewShot = useRef(null);
const platformIs = Platform.OS == "android";
return (
<ActionSheet

View File

@ -12,20 +12,13 @@ import {
import { useAllTrainDiagram } from "../stateBox/useAllTrainDiagram";
import { customTrainDataDetector } from "./custom-train-data";
import { getStationList } from "../lib/getStationList";
import { getTrainType } from "../lib/getTrainType";
import { SheetManager } from "react-native-actions-sheet";
import { useNavigation } from "@react-navigation/native";
import { BigButton } from "./atom/BigButton";
export default function AllTrainDiagramView() {
const { navigate } = useNavigation();
const { allTrainDiagram } = useAllTrainDiagram();
const [originalStationList, setOriginalStationList] = useState(); // 第一要素
const [keyList, setKeyList] = useState(); // 第二要素
useEffect(() => getStationList().then(setOriginalStationList), []);
useEffect(
() => allTrainDiagram && setKeyList(Object.keys(allTrainDiagram)),
[]
);
const { keyList } = useAllTrainDiagram();
const [input, setInput] = useState(""); // 文字入力
const [keyBoardVisible, setKeyBoardVisible] = useState(false);
@ -51,16 +44,12 @@ export default function AllTrainDiagramView() {
parseInt(d.replace("M", "").replace("D", "")) - train.trainNumDistance;
TrainNumber = timeInfo + "号";
}
const type = getTrainType(train.type).data;
const limited = `${type}:${train.trainName}${TrainNumber}`;
const payload = {
data: {
trainNum: d,
limited: `${getTrainType(train.type).data}:${
train.trainName
}${TrainNumber}`,
},
data: { trainNum: d, limited },
navigate,
originalStationList,
from: "AllTrainDiagramView",
from: "AllTrainIDList",
};
SheetManager.show("EachTrainInfo", {
payload,
@ -71,11 +60,9 @@ export default function AllTrainDiagramView() {
<FlatList
style={{ flex: 1 }}
data={keyList?.filter((d) => d.includes(input))}
renderItem={({ item }) => (
<Item openTrainInfo={openTrainInfo} id={item} />
)}
renderItem={({ item }) => <Item {...{ openTrainInfo, id: item }} />}
keyExtractor={(item) => item}
initialNumToRender={100}
//initialNumToRender={100}
/>
<KeyboardAvoidingView
behavior="padding"
@ -97,39 +84,22 @@ export default function AllTrainDiagramView() {
>
<TextInput
placeholder="列番を入力してフィルタリングします。"
onFocus={() => {
setKeyBoardVisible(true);
}}
onFocus={() => setKeyBoardVisible(true)}
onEndEditing={() => {}}
onChange={(ret) => {
setInput(ret.nativeEvent.text);
}}
onChange={(ret) => setInput(ret.nativeEvent.text)}
value={input}
style={{ flex: 1 }}
/>
</View>
</KeyboardAvoidingView>
<TouchableOpacity
<BigButton
onPress={() => navigate("menu")}
string="閉じる"
style={{
padding: 10,
flexDirection: "row",
borderColor: "white",
borderWidth: 1,
margin: 10,
borderRadius: 5,
alignItems: "center",
display:
Platform.OS === "ios" ? "flex" : keyBoardVisible ? "none" : "flex",
}}
onPress={() => navigate("menu")}
>
<View style={{ flex: 1 }} />
<Text style={{ fontSize: 25, fontWeight: "bold", color: "white" }}>
閉じる
</Text>
<View style={{ flex: 1 }} />
</TouchableOpacity>
/>
</View>
);
}

View File

@ -1,20 +1,14 @@
import React, { useEffect, useState } from "react";
import React from "react";
import {
View,
Platform,
Text,
TouchableOpacity,
useWindowDimensions,
LayoutAnimation,
} from "react-native";
import Constants from "expo-constants";
import { Ionicons } from "@expo/vector-icons";
import * as Updates from "expo-updates";
import { AS } from "../storageControl";
import { news } from "../config/newsUpdate";
import { getStationList, lineList } from "../lib/getStationList";
import { injectJavascriptData } from "../lib/webViewInjectjavascript";
import { lineList } from "../lib/getStationList";
import { useCurrentTrain } from "../stateBox/useCurrentTrain";
import { useDeviceOrientationChange } from "../stateBox/useDeviceOrientationChange";
import { SheetManager } from "react-native-actions-sheet";
@ -24,6 +18,11 @@ import { EachTrainInfoCore } from "../components/ActionSheetComponents/EachTrain
import { useNavigation } from "@react-navigation/native";
import { useTrainMenu } from "../stateBox/useTrainMenu";
import { AppsWebView } from "./Apps/WebView";
import { NewMenu } from "./Apps/NewMenu";
import { MapsButton } from "./Apps/MapsButton";
import { ReloadButton } from "./Apps/ReloadButton";
import { LandscapeBackButton } from "./Apps/LandscapeBackButton";
import { useStationList } from "../stateBox/useStationList";
/*
import StatusbarDetect from '../StatusbarDetect';
var Status = StatusbarDetect(); */
@ -36,57 +35,9 @@ export default function Apps() {
const { navigate } = useNavigation();
const { isLandscape } = useDeviceOrientationChange();
const handleLayout = () => {};
const { setInjectJavaScript, mapsStationData: stationData } = useTrainMenu();
//画面表示関連
const [iconSetting, setIconSetting] = useState(undefined);
const [mapSwitch, setMapSwitch] = useState(undefined);
const [stationMenu, setStationMenu] = useState(undefined);
const [LoadError, setLoadError] = useState(false);
//列車情報表示関連
const [trainInfo, setTrainInfo] = useState({
trainNum: undefined,
limited: undefined,
trainData: undefined,
});
//駅情報画面用
const [originalStationList, setOriginalStationList] = useState();
const [trainMenu, setTrainMenu] = useState("true");
useEffect(() => getStationList().then(setOriginalStationList), []);
//地図表示テキスト
const injectJavascript = injectJavascriptData(
mapSwitch,
iconSetting,
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(() => {
//ニュース表示
AS.getItem("status")
.then((d) => {
if (d != news) navigate("news");
})
.catch(() => navigate("news"));
}, []);
useEffect(() => {
//列車アイコンスイッチ
ASCore({ k: "iconSwitch", s: setIconSetting, d: "true" });
//地図スイッチ
ASCore({ k: "mapSwitch", s: setMapSwitch, d: "false" });
//駅メニュースイッチ
ASCore({ k: "stationSwitch", s: setStationMenu, d: "true" });
//列車メニュースイッチ
ASCore({ k: "trainSwitch", s: setTrainMenu, d: "true" });
}, []);
const { originalStationList } = useStationList();
const { setInjectJavaScript, mapSwitch, trainInfo, setTrainInfo } =
useTrainMenu();
const openStationACFromEachTrainInfo = async (stationName) => {
await SheetManager.hide("EachTrainInfo");
@ -104,8 +55,7 @@ export default function Apps() {
if (returnDataBase.length) {
const payload = {
currentStation: returnDataBase,
originalStationList: originalStationList,
navigate: navigate,
navigate,
goTo: "Apps",
useShow: () => SheetManager.show("StationDetailView", { payload }),
onExit: () => SheetManager.hide("StationDetailView"),
@ -126,9 +76,6 @@ export default function Apps() {
>
{!trainInfo.trainNum && isLandscape ? (
<TrainMenu
webview={webview}
stationData={stationData}
navigation={{ navigate: null }}
style={{
width: (width / 100) * 40,
height: "100%",
@ -138,12 +85,8 @@ export default function Apps() {
) : null}
{/* {Status} */}
<AppsWebView
originalStationList={originalStationList}
{...{
setLoadError,
setTrainInfo,
openStationACFromEachTrainInfo,
injectJavascript,
}}
/>
{isLandscape && trainInfo.trainNum && (
@ -157,10 +100,8 @@ export default function Apps() {
<EachTrainInfoCore
{...{
data: trainInfo.trainNum ? trainInfo : undefined,
originalStationList,
openStationACFromEachTrainInfo,
from: "Train",
setTrainInfo,
navigate,
}}
/>
@ -172,7 +113,6 @@ export default function Apps() {
setInjectJavaScript("");
navigate("trainMenu", { webview });
}}
mapSwitch={mapSwitch == "true" ? "flex" : "none"}
/>
)}
{isLandscape && trainInfo.trainNum && (
@ -191,206 +131,10 @@ export default function Apps() {
<ReloadButton
onPress={() => Updates.reloadAsync()}
right={isLandscape && trainInfo.trainNum ? (width / 100) * 40 : 0}
LoadError={LoadError}
/>
) : (
<NewMenu
webview={webview}
isLandscape={isLandscape}
LoadError={LoadError}
mapSwitch={mapSwitch}
/>
<NewMenu />
)}
</View>
);
}
const NewMenu = ({ webview, LoadError }) => {
const { width } = useWindowDimensions();
return (
<View
style={{
position: "absolute",
top,
width,
height: 54,
backgroundColor: "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
flexDirection: "row",
}}
>
<TouchableOpacity
activeOpacity={1}
style={{
flex: 1,
height: 54,
backgroundColor: "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
borderRightWidth: 0,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
flexDirection: "row",
}}
onPress={() => {
webview.current?.injectJavaScript(`AccordionClassEvent()`);
}}
>
<>
<View
style={{
width: 54,
height: 54,
backgroundColor: "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
}}
>
<View style={{ flex: 1 }} />
<Ionicons name="menu" color="white" size={30} />
<View style={{ flex: 1 }} />
</View>
<View style={{ flex: 1 }} />
<Text style={{ color: "white", fontSize: 20 }}>メニュー</Text>
<View style={{ flex: 1 }}></View>
</>
</TouchableOpacity>
<TouchableOpacity
onPress={() => Updates.reloadAsync()}
style={{
width: 54,
height: 54,
backgroundColor: LoadError ? "red" : "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
}}
>
<View style={{ flex: 1 }} />
<Ionicons name="reload" color="white" size={30} />
<View style={{ flex: 1 }} />
</TouchableOpacity>
</View>
);
};
const MapsButton = ({ onPress, mapSwitch }) => {
const styles = {
touch: {
position: "absolute",
top,
left: 10,
width: 50,
height: 50,
backgroundColor: "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
borderRadius: 50,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
display: mapSwitch,
},
text: {
textAlign: "center",
width: "auto",
height: "auto",
textAlignVertical: "center",
fontWeight: "bold",
color: "white",
fontSize: 20,
},
};
return (
<TouchableOpacity onPress={onPress} style={styles.touch}>
<View style={{ flex: 1 }} />
<Text style={styles.text}></Text>
<View style={{ flex: 1 }} />
</TouchableOpacity>
);
};
const LandscapeBackButton = ({ onPress }) => {
const styles = {
touch: {
position: "absolute",
left: 10,
width: 50,
height: 50,
backgroundColor: "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
borderRadius: 50,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
display: "flex",
},
text: {
textAlign: "center",
width: "auto",
height: "auto",
textAlignVertical: "center",
fontWeight: "bold",
color: "white",
},
};
return (
<TouchableOpacity onPress={onPress} style={styles.touch}>
<View style={{ flex: 1 }} />
<Ionicons name="arrow-back" color="white" size={30} />
<View style={{ flex: 1 }} />
</TouchableOpacity>
);
};
const ReloadButton = ({ onPress, mapSwitch, LoadError = false, right }) => {
const styles = {
touch: {
position: "absolute",
top,
right: 10 + right,
width: 50,
height: 50,
backgroundColor: LoadError ? "red" : "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
borderRadius: 50,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
display: mapSwitch,
},
text: {
textAlign: "center",
width: "auto",
height: "auto",
textAlignVertical: "center",
fontWeight: "bold",
color: "white",
},
};
return (
<TouchableOpacity onPress={onPress} style={styles.touch}>
<View style={{ flex: 1 }} />
<Ionicons name="reload" color="white" size={30} />
<View style={{ flex: 1 }} />
</TouchableOpacity>
);
};

View File

@ -0,0 +1,48 @@
import React, { FC } from "react";
import {
View,
TouchableOpacity,
TouchableOpacityProps,
TextStyle,
} from "react-native";
import { Ionicons } from "@expo/vector-icons";
export const LandscapeBackButton: FC<{
onPress: () => void;
}> = ({ onPress }) => {
type stylesType = {
touch: TouchableOpacityProps["style"];
text: TextStyle;
};
const styles: stylesType = {
touch: {
position: "absolute",
left: 10,
width: 50,
height: 50,
backgroundColor: "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
borderRadius: 50,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
display: "flex",
},
text: {
textAlign: "center",
width: "auto",
height: "auto",
textAlignVertical: "center",
fontWeight: "bold",
color: "white",
},
};
return (
<TouchableOpacity onPress={onPress} style={styles.touch}>
<View style={{ flex: 1 }} />
<Ionicons name="arrow-back" color="white" size={30} />
<View style={{ flex: 1 }} />
</TouchableOpacity>
);
};

View File

@ -0,0 +1,58 @@
import React, { FC } from "react";
import {
View,
Text,
TouchableOpacity,
Platform,
TouchableOpacityProps,
TextStyle,
} from "react-native";
import Constants from "expo-constants";
import { useTrainMenu } from "../../stateBox/useTrainMenu";
const top = Platform.OS == "ios" ? Constants.statusBarHeight : 0;
type MapsButtonProps = {
onPress: () => void;
};
type stylesType = {
touch: TouchableOpacityProps["style"];
text: TextStyle;
};
export const MapsButton: FC<MapsButtonProps> = ({ onPress }) => {
const { mapSwitch } = useTrainMenu();
const styles: stylesType = {
touch: {
position: "absolute",
top,
left: 10,
width: 50,
height: 50,
backgroundColor: "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
borderRadius: 50,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
display: mapSwitch == "true" ? "flex" : "none",
},
text: {
textAlign: "center",
width: "auto",
height: "auto",
textAlignVertical: "center",
fontWeight: "bold",
color: "white",
fontSize: 20,
},
};
return (
<TouchableOpacity onPress={onPress} style={styles.touch}>
<View style={{ flex: 1 }} />
<Text style={styles.text}></Text>
<View style={{ flex: 1 }} />
</TouchableOpacity>
);
};

View File

@ -0,0 +1,94 @@
import React from "react";
import { View, Text, TouchableOpacity, useWindowDimensions, Platform } from "react-native";
import { Ionicons } from "@expo/vector-icons";
import * as Updates from "expo-updates";
import Constants from "expo-constants";
import { useCurrentTrain } from "../../stateBox/useCurrentTrain";
import { useTrainMenu } from "../../stateBox/useTrainMenu";
const top = Platform.OS == "ios" ? Constants.statusBarHeight : 0;
export const NewMenu = () => {
const { webview } = useCurrentTrain();
const { width } = useWindowDimensions();
const { LoadError } = useTrainMenu();
return (
<View
style={{
position: "absolute",
top,
width,
height: 54,
backgroundColor: "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
flexDirection: "row",
}}
>
<TouchableOpacity
activeOpacity={1}
style={{
flex: 1,
height: 54,
backgroundColor: "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
borderRightWidth: 0,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
flexDirection: "row",
}}
onPress={() => {
webview.current?.injectJavaScript(`AccordionClassEvent()`);
}}
>
<>
<View
style={{
width: 54,
height: 54,
backgroundColor: "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
}}
>
<View style={{ flex: 1 }} />
<Ionicons name="menu" color="white" size={30} />
<View style={{ flex: 1 }} />
</View>
<View style={{ flex: 1 }} />
<Text style={{ color: "white", fontSize: 20 }}></Text>
<View style={{ flex: 1 }}></View>
</>
</TouchableOpacity>
<TouchableOpacity
onPress={() => Updates.reloadAsync()}
style={{
width: 54,
height: 54,
backgroundColor: LoadError ? "red" : "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
}}
>
<View style={{ flex: 1 }} />
<Ionicons name="reload" color="white" size={30} />
<View style={{ flex: 1 }} />
</TouchableOpacity>
</View>
);
};

View File

@ -0,0 +1,58 @@
import React, { FC } from "react";
import {
View,
TouchableOpacity,
Platform,
TouchableOpacityProps,
TextStyle,
} from "react-native";
import { Ionicons } from "@expo/vector-icons";
import Constants from "expo-constants";
import { useTrainMenu } from "../../stateBox/useTrainMenu";
const top = Platform.OS == "ios" ? Constants.statusBarHeight : 0;
type stylesType = {
touch: TouchableOpacityProps["style"];
text: TextStyle;
};
type ReloadButton = {
onPress: () => void;
right: number;
}
export const ReloadButton:FC<ReloadButton> = ({ onPress, right }) => {
const { mapSwitch, LoadError = false } = useTrainMenu();
const styles: stylesType = {
touch: {
position: "absolute",
top,
right: 10 + right,
width: 50,
height: 50,
backgroundColor: LoadError ? "red" : "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
borderRadius: 50,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
display: mapSwitch,
},
text: {
textAlign: "center",
width: "auto",
height: "auto",
textAlignVertical: "center",
fontWeight: "bold",
color: "white",
},
};
return (
<TouchableOpacity onPress={onPress} style={styles.touch}>
<View style={{ flex: 1 }} />
<Ionicons name="reload" color="white" size={30} />
<View style={{ flex: 1 }} />
</TouchableOpacity>
);
};

View File

@ -12,18 +12,20 @@ import { SheetManager } from "react-native-actions-sheet";
import { useNavigation } from "@react-navigation/native";
import { useTrainMenu } from "../../stateBox/useTrainMenu";
import { stationNamePair } from "../../lib/getStationList2";
export const AppsWebView = ({
originalStationList,
setLoadError,
setTrainInfo,
openStationACFromEachTrainInfo,
injectJavascript,
}) => {
import { useStationList } from "../../stateBox/useStationList";
export const AppsWebView = ({ openStationACFromEachTrainInfo }) => {
const { webview, currentTrain } = useCurrentTrain();
const { navigate } = useNavigation();
const { favoriteStation } = useFavoriteStation();
const { isLandscape } = useDeviceOrientationChange();
const { setSelectedLine, mapsStationData: stationData } = useTrainMenu();
const { originalStationList } = useStationList();
const {
setSelectedLine,
mapsStationData: stationData,
setLoadError,
setTrainInfo,
injectJavascript,
} = useTrainMenu();
var urlcache = "";
let once = false;
@ -76,7 +78,6 @@ export const AppsWebView = ({
if (returnDataBase.length) {
const payload = {
currentStation: returnDataBase,
originalStationList: originalStationList,
navigate: navigate,
goTo: "Apps",
useShow: () =>
@ -102,7 +103,6 @@ export const AppsWebView = ({
const payload = {
data: { trainNum, limited },
navigate,
originalStationList,
openStationACFromEachTrainInfo,
};
SheetManager.show("EachTrainInfo", { payload });

View File

@ -1,53 +1,15 @@
import React, { useRef } from "react";
import { View, Text, TouchableOpacity, Linking } from "react-native";
import MapView, { Marker } from "react-native-maps";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import React from "react";
import { View, Text } from "react-native";
import { useCurrentTrain } from "../stateBox/useCurrentTrain";
import { useNavigation } from "@react-navigation/native";
import { BigButton } from "./atom/BigButton";
export default function CurrentTrainListView() {
const { navigate } = useNavigation();
const { currentTrain } = useCurrentTrain();
return (
<View style={{ height: "100%", backgroundColor: "#0099CC" }}>
{currentTrain && currentTrain.map((d) => <Text>{d.num}</Text>)}
<TouchableOpacity
style={{
padding: 10,
flexDirection: "row",
borderColor: "white",
borderWidth: 1,
margin: 10,
borderRadius: 5,
alignItems: "center",
}}
onPress={() => navigate("menu")}
>
<View style={{ flex: 1 }} />
<Text style={{ fontSize: 25, fontWeight: "bold", color: "white" }}>
閉じる
</Text>
<View style={{ flex: 1 }} />
</TouchableOpacity>
<BigButton onPress={() => navigate("menu")} string="閉じる" />
</View>
);
}
const UsefulBox = (props) => {
const { icon, backgroundColor, flex, onPressButton, children } = props;
return (
<TouchableOpacity
style={{
flex: flex,
backgroundColor: backgroundColor,
padding: 10,
alignItems: "center",
margin: 2,
}}
onPress={onPressButton}
>
<MaterialCommunityIcons name={icon} color="white" size={50} />
<Text style={{ color: "white", fontWeight: "bold", fontSize: 18 }}>
{children}
</Text>
</TouchableOpacity>
);
};

View File

@ -40,7 +40,7 @@ export const DynamicHeaderScrollView = (props) => {
}, [headerSize]);
const viewHeader = useMemo(() => {
switch (from) {
case "AllTrainDiagramView":
case "AllTrainIDList":
case "NearTrainDiagramView":
case "LED2":
return true;

View File

@ -7,6 +7,7 @@ import { useCurrentTrain } from "../stateBox/useCurrentTrain";
import { useNavigation } from "@react-navigation/native";
import { useTrainMenu } from "../stateBox/useTrainMenu";
import { FavoriteListItem } from "./atom/FavoriteListItem";
import { BigButton } from "./atom/BigButton";
export default function FavoriteList() {
const { favoriteStation } = useFavoriteStation();
const { webview } = useCurrentTrain();
@ -78,24 +79,7 @@ export default function FavoriteList() {
>
お気に入り登録した駅のうち位置情報システムで移動可能な駅が表示されていますタップすることで位置情報システムの当該の駅に移動します
</Text>
<TouchableOpacity
style={{
padding: 10,
flexDirection: "row",
borderColor: "white",
borderWidth: 1,
margin: 10,
borderRadius: 5,
alignItems: "center",
}}
onPress={() => goBack()}
>
<View style={{ flex: 1 }} />
<Text style={{ fontSize: 25, fontWeight: "bold", color: "white" }}>
閉じる
</Text>
<View style={{ flex: 1 }} />
</TouchableOpacity>
<BigButton onPress={() => goBack()} string="閉じる" />
</View>
);
}

View File

@ -271,6 +271,23 @@ export const FixedContentBottom = (props) => {
</Text>
</TextBox>
<Text style={{ fontWeight: "bold", fontSize: 20 }}>その他</Text>
<TextBox
backgroundColor="linear-gradient(120deg, rgba(247,135,54,0.208) 0%, rgba(54,125,247,0.208) 100%)"
flex={1}
onPressButton={() =>
props.navigate("howto", {
info: "https://xprocess.haruk.in/tags/JR%E5%9B%9B%E5%9B%BD%E5%88%97%E8%BB%8A%E4%BD%8D%E7%BD%AE%E6%83%85%E5%A0%B1%E3%82%A2%E3%83%97%E3%83%AA/",
goTo: "menu",
})
}
>
<Text style={{ color: "black", fontWeight: "bold", fontSize: 20 }}>
アプリの更新情報
</Text>
<Text style={{ color: "black", fontSize: 18 }}>
過去のアプリの更新履歴が表示できます
</Text>
</TextBox>
<TextBox
backgroundColor="black"
flex={1}

View File

@ -12,7 +12,7 @@ import * as Updates from "expo-updates";
import { useWindowDimensions } from "react-native";
import { ListItem } from "native-base";
const versionCode = "5.3.2";
const versionCode = "5.4";
export const SettingTopPage = ({ navigate, testNFC, updateAndReload }) => {
const { width } = useWindowDimensions();

View File

@ -0,0 +1,32 @@
import React, { FC } from "react";
import { Marker } from "react-native-maps";
type Props = {
index: number;
indexBase: number;
latlng: string[];
D: any;
d: string;
navigate: (screen: string) => void;
webview: any;
};
export const MapPin: FC<Props> = (props) => {
const { index, indexBase, latlng, D, d, navigate, webview } = props;
return (
<Marker
key={index + indexBase}
coordinate={{
latitude: parseFloat(latlng[0]),
longitude: parseFloat(latlng[1]),
}}
onPress={() => {
webview.current?.injectJavaScript(
`MoveDisplayStation('${d}_${D.MyStation}_${D.Station_JP}');
document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");`
);
if (navigate) navigate("Apps");
}}
image={require("../../assets/reccha-small.png")}
></Marker>
);
};

View File

@ -0,0 +1,35 @@
import React, { FC } from "react";
import { View, TouchableOpacity, TouchableOpacityProps } from "react-native";
import { Ionicons } from "@expo/vector-icons";
type Props = {
onPress: () => void;
top: number;
mapSwitch: "flex" | "none";
};
export const MapsButton: FC<Props> = ({ onPress, top, mapSwitch }) => {
const styles: TouchableOpacityProps["style"] = {
position: "absolute",
top,
left: 10,
width: 50,
height: 50,
backgroundColor: "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
borderRadius: 50,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
display: mapSwitch,
};
return (
<TouchableOpacity onPress={onPress} style={styles}>
<View style={{ flex: 1 }} />
<Ionicons name="close" color="white" size={30} />
<View style={{ flex: 1 }} />
</TouchableOpacity>
);
};

View File

@ -0,0 +1,32 @@
import React, { FC } from "react";
import { Text, TouchableOpacity } from "react-native";
import { MaterialCommunityIcons } from "@expo/vector-icons";
type Props = {
icon: keyof typeof MaterialCommunityIcons.glyphMap;
backgroundColor: string;
flex: number;
onPressButton: () => void;
children: string;
};
export const UsefulBox: FC<Props> = (props) => {
const { icon, backgroundColor, flex, onPressButton, children } = props;
return (
<TouchableOpacity
style={{
flex: flex,
backgroundColor: backgroundColor,
padding: 5,
alignItems: "center",
margin: 2,
}}
onPress={onPressButton}
>
<MaterialCommunityIcons name={icon} color="white" size={50} />
<Text style={{ color: "white", fontWeight: "bold", fontSize: 16 }}>
{children}
</Text>
</TouchableOpacity>
);
};

View File

@ -0,0 +1,41 @@
import React, { FC } from "react";
import {
Text,
TextStyle,
TouchableOpacity,
View,
ViewStyle,
} from "react-native";
type Props = {
onPress: () => void;
string: string;
style?: ViewStyle;
tS?: TextStyle;
children?: any;
};
export const BigButton: FC<Props> = (props) => {
const { onPress, string, style, tS, children } = props;
return (
<TouchableOpacity
style={{
padding: 10,
flexDirection: "row",
borderColor: "white",
borderWidth: 1,
margin: 10,
borderRadius: 5,
alignItems: "center",
...style,
}}
onPress={onPress}
>
<View style={{ flex: 1 }} />
{children}
<Text style={{ fontSize: 25, fontWeight: "bold", color: "white", ...tS }}>
{string}
</Text>
<View style={{ flex: 1 }} />
</TouchableOpacity>
);
};

View File

@ -1,4 +1,4 @@
export const customTrainDataDetector = (TrainNumber) => {
export const customTrainDataDetector = (TrainNumber: string) => {
switch (TrainNumber) {
//しおかぜメイン
//8000 ノーマル
@ -627,7 +627,7 @@ export const customTrainDataDetector = (TrainNumber) => {
break;
}
};
export const getJRF = (num) => {
export const getJRF = (num: string) => {
switch (num) {
case "71":
return "東京(タ)→高松(タ)\\n";
@ -657,7 +657,6 @@ export const getJRF = (num) => {
case "9070":
return "臨時貨物\\n";
default:
JRF = true;
return null;
}
};

View File

@ -1,44 +0,0 @@
import React from "react";
import { View, Text, TouchableOpacity } from "react-native";
import { WebView } from "react-native-webview";
import StatusbarDetect from "../StatusbarDetect";
import { AS } from "../storageControl";
import { news } from "../config/newsUpdate";
import { useNavigation } from "@react-navigation/native";
var Status = StatusbarDetect();
export default function News() {
const { navigate } = useNavigation();
return (
<View style={{ height: "100%", backgroundColor: "#0099CC" }}>
<WebView
useWebKit={true}
source={{
uri: `https://nexcloud.haruk.in/sites/press-harukin/JRShikokuApps/${news}`,
}}
mixedContentMode={"compatibility"}
javaScriptEnabled={true}
/>
<TouchableOpacity
style={{
padding: 10,
flexDirection: "row",
borderColor: "white",
borderWidth: 1,
margin: 10,
borderRadius: 5,
alignItems: "center",
}}
onPress={() => {
AS.setItem("status", news);
navigate("Apps");
}}
>
<View style={{ flex: 1 }} />
<Text style={{ fontSize: 25, fontWeight: "bold", color: "white" }}>
更新情報を閉じる
</Text>
<View style={{ flex: 1 }} />
</TouchableOpacity>
</View>
);
}

30
components/news.tsx Normal file
View File

@ -0,0 +1,30 @@
import React, { FC } from "react";
import { View } from "react-native";
import { WebView } from "react-native-webview";
import { AS } from "../storageControl";
import { news } from "../config/newsUpdate";
import { useNavigation } from "@react-navigation/native";
import { BigButton } from "./atom/BigButton";
const News: FC = () => {
const { navigate } = useNavigation();
return (
<View style={{ height: "100%", backgroundColor: "#0099CC" }}>
<WebView
useWebKit={true}
source={{
uri: `https://xprocess.haruk.in/${news}`,
}}
mixedContentMode={"compatibility"}
javaScriptEnabled={true}
/>
<BigButton
onPress={() => {
AS.setItem("status", news);
navigate("Apps");
}}
string="更新情報を閉じる"
/>
</View>
);
};
export default News;

View File

@ -1,7 +1,6 @@
import React, { useRef, useState, useEffect } from "react";
import { View, Text, TouchableOpacity, Linking, Platform } from "react-native";
import React, { useRef, useState, useEffect, useLayoutEffect } from "react";
import { View, Text, TouchableOpacity, Linking } from "react-native";
import MapView, { Marker } from "react-native-maps";
import Constants from "expo-constants";
import { MaterialCommunityIcons, Ionicons } from "@expo/vector-icons";
import { useCurrentTrain } from "../stateBox/useCurrentTrain";
import { useNavigation } from "@react-navigation/native";
@ -10,6 +9,9 @@ import { stationIDPair } from "../lib/getStationList2";
import { lineListPair } from "../lib/getStationList";
import { SheetManager } from "react-native-actions-sheet";
import { useTrainMenu } from "../stateBox/useTrainMenu";
import { MapPin } from "./TrainMenu/MapPin";
import { UsefulBox } from "./TrainMenu/UsefulBox";
import { MapsButton } from "./TrainMenu/MapsButton";
export default function TrainMenu({ style }) {
const { webview } = useCurrentTrain();
const mapRef = useRef();
@ -24,8 +26,8 @@ export default function TrainMenu({ style }) {
} = useTrainMenu();
useEffect(() => {
const stationPinData = [];
Object.keys(stationData).map((d, indexBase) => {
stationData[d].map((D, index) => {
Object.keys(stationData).forEach((d, indexBase) => {
stationData[d].forEach((D, index) => {
if (!D.StationMap) return null;
if (selectedLine && selectedLine != d) return;
const latlng = D.StationMap.replace(
@ -44,7 +46,7 @@ export default function TrainMenu({ style }) {
});
setStationPin(stationPinData);
}, [stationData, selectedLine]);
useEffect(() => {
useLayoutEffect(() => {
mapRef.current.fitToCoordinates(
stationPin.map(({ latlng }) => ({
latitude: parseFloat(latlng[0]),
@ -207,80 +209,4 @@ export default function TrainMenu({ style }) {
/>
</View>
);
}
const UsefulBox = (props) => {
const { icon, backgroundColor, flex, onPressButton, children } = props;
return (
<TouchableOpacity
style={{
flex: flex,
backgroundColor: backgroundColor,
padding: 5,
alignItems: "center",
margin: 2,
}}
onPress={onPressButton}
>
<MaterialCommunityIcons name={icon} color="white" size={50} />
<Text style={{ color: "white", fontWeight: "bold", fontSize: 16 }}>
{children}
</Text>
</TouchableOpacity>
);
};
const MapPin = ({ index, indexBase, latlng, D, d, navigate, webview }) => {
return (
<Marker
key={index + indexBase}
coordinate={{
latitude: parseFloat(latlng[0]),
longitude: parseFloat(latlng[1]),
}}
onPress={() => {
webview.current?.injectJavaScript(
`MoveDisplayStation('${d}_${D.MyStation}_${D.Station_JP}');
document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");`
);
if (navigate) navigate("Apps");
}}
image={require("../assets/reccha-small.png")}
></Marker>
);
};
const MapsButton = ({ onPress, top, mapSwitch }) => {
const styles = {
touch: {
position: "absolute",
top,
left: 10,
width: 50,
height: 50,
backgroundColor: "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
borderRadius: 50,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
display: mapSwitch,
},
text: {
textAlign: "center",
width: "auto",
height: "auto",
textAlignVertical: "center",
fontWeight: "bold",
color: "white",
},
};
return (
<TouchableOpacity onPress={onPress} style={styles.touch}>
<View style={{ flex: 1 }} />
<Ionicons name="close" color="white" size={30} />
<View style={{ flex: 1 }} />
</TouchableOpacity>
);
};
}

View File

@ -1,14 +1,9 @@
import React, { Component, useRef } from "react";
import {
StatusBar,
Platform,
View,
TouchableOpacity,
Text,
} from "react-native";
import React, { useRef } from "react";
import { StatusBar, Platform, View } from "react-native";
import { WebView } from "react-native-webview";
import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import { useNavigation } from "@react-navigation/native";
import { BigButton } from "./atom/BigButton";
export default function TrainBase({ route }) {
const { info, from } = route.params;
@ -37,28 +32,17 @@ export default function TrainBase({ route }) {
setSupportMultipleWindows={false}
onMessage={(event) => {}}
/>
{(from == "LED" || from == "LED2" || from == "AllTrainDiagramView") && (
<TouchableOpacity
style={{
padding: 10,
flexDirection: "row",
borderColor: "black",
borderWidth: 1,
margin: 10,
borderRadius: 5,
alignItems: "center",
}}
{(from == "LED" || from == "LED2" || from == "AllTrainIDList") && (
<BigButton
style={{ borderColor: "black" }}
tS={{ color: "black" }}
string="閉じる"
onPress={() =>
navigate(from == "AllTrainDiagramView" ? "AllTrainIDList" : "menu")
navigate(from == "AllTrainIDList" ? "AllTrainIDList" : "menu")
}
>
<View style={{ flex: 1 }} />
<MaterialCommunityIcons name="close" color="black" size={30} />
<Text style={{ fontSize: 25, fontWeight: "bold", color: "black" }}>
閉じる
</Text>
<View style={{ flex: 1 }} />
</TouchableOpacity>
</BigButton>
)}
</View>
);

View File

@ -0,0 +1,137 @@
import React, { FC, useEffect, useState } from "react";
import { Linking, TouchableOpacity } from "react-native";
import { checkDuplicateTrainData } from "../../lib/checkDuplicateTrainData";
import { getTrainDelayStatus } from "../../lib/getTrainDelayStatus";
import { getTrainType } from "../../lib/getTrainType";
import { useCurrentTrain } from "../../stateBox/useCurrentTrain";
import { SheetManager } from "react-native-actions-sheet";
import { Description } from "./LED_inside_Component/Description";
import { DependTime } from "./LED_inside_Component/DependTime";
import { LastStation } from "./LED_inside_Component/LastStation";
import { StatusAndDelay } from "./LED_inside_Component/StatusAndDelay";
import { TrainName } from "./LED_inside_Component/TrainName";
type Props = {
d: {
train: string;
lastStation: string;
time: string;
};
trainIDSwitch: boolean;
trainDescriptionSwitch: boolean;
station: {
Station_JP: string;
};
customTrainDataDetector: (trainID: string) => {
trainName: string;
trainNumDistance?: number;
type: string;
info: string;
};
navigate: (screen: string, data?: any) => void;
openStationACFromEachTrainInfo: (station: string) => void;
};
export const EachData: FC<Props> = (props) => {
const {
d,
trainIDSwitch,
trainDescriptionSwitch,
station,
customTrainDataDetector,
navigate,
openStationACFromEachTrainInfo,
} = props;
const { currentTrain } = useCurrentTrain();
const openTrainInfo = (d: {
train: string;
lastStation: string;
time: string;
}) => {
let TrainNumber = "";
if (train.trainNumDistance != undefined) {
const timeInfo =
parseInt(d.train.replace("M", "").replace("D", "")) -
train.trainNumDistance;
TrainNumber = timeInfo + "号";
}
const payload = {
data: {
trainNum: d.train,
limited: `${getTrainType(train.type).data}:${
train.trainName
}${TrainNumber}`,
},
navigate,
openStationACFromEachTrainInfo,
from: "LED",
};
SheetManager.show("EachTrainInfo", {
payload,
});
};
const [train, setTrain] = useState(customTrainDataDetector(d.train));
useEffect(() => {
setTrain(customTrainDataDetector(d.train));
}, [currentTrain, d.train, trainDescriptionSwitch]);
// 土讃線複数存在対策
const currentTrainData = checkDuplicateTrainData(
currentTrain.filter((a) => a.num == d.train)
);
const trainDelayStatus = `${getTrainDelayStatus(
currentTrainData,
station.Station_JP
)}`;
const trainPositionText = currentTrainData?.Pos.match("")
? `現在地:${
currentTrainData?.Pos.replace("(下り)", "")
.replace("(上り)", "")
.split("")[currentTrainData?.Direction == 1 ? 0 : 1]
}${
currentTrainData?.Pos.replace("(下り)", "")
.replace("(上り)", "")
.split("")[currentTrainData?.Direction == 1 ? 1 : 0]
}`
: `現在地:${currentTrainData?.Pos}`;
return (
<>
<TouchableOpacity
style={{
alignContent: "center",
alignItems: "center",
width: "94%",
marginVertical: 5,
marginHorizontal: "3%",
backgroundColor: "#000",
flexDirection: "row",
}}
onPress={() => openTrainInfo(d)}
>
<TrainName
trainName={train.trainName}
trainNumDistance={train.trainNumDistance}
trainIDSwitch={trainIDSwitch}
trainID={d.train}
type={train.type}
/>
<LastStation lastStation={d.lastStation} />
<DependTime time={d.time} />
<StatusAndDelay trainDelayStatus={trainDelayStatus} />
</TouchableOpacity>
{trainDescriptionSwitch && (
<Description
info={`${
trainIDSwitch ? currentTrainData?.PosNum : trainPositionText
}`}
onLongClick={() => {
Linking.openURL(
"https://nexcloud.haruk.in/apps/forms/s/TEkBQW5WLcYjLyAzGxncQLtw"
);
}}
/>
)}
{trainDescriptionSwitch && !!train.info && (
<Description info={train.info} />
)}
</>
);
};

View File

@ -0,0 +1,38 @@
import { View } from "react-native";
import { SwitchBox } from "./SwitchBox";
export const Footer = (props) => {
const {
trainIDSwitch,
setTrainIDSwitch,
trainDescriptionSwitch,
setTrainDescriptionSwitch,
finalSwitch,
setFinalSwitch,
} = props;
return (
<View style={{ flexDirection: "row", padding: 10, alignItems: "center" }}>
<SwitchBox
value={trainIDSwitch}
setValue={setTrainIDSwitch}
setKey="LEDSettings/trainIDSwitch"
title="種別名 / 列番"
/>
<View style={{ flex: 1 }} />
<SwitchBox
value={trainDescriptionSwitch}
setValue={setTrainDescriptionSwitch}
setKey="LEDSettings/trainDescriptionSwitch"
title="列車情報"
/>
<View style={{ flex: 1 }} />
<SwitchBox
value={finalSwitch}
setValue={setFinalSwitch}
setKey="LEDSettings/finalSwitch"
title="当駅止表示"
/>
</View>
);
};

View File

@ -0,0 +1,48 @@
import { View, Text } from "react-native";
import { useCurrentTrain } from "../../../stateBox/useCurrentTrain";
import LottieView from "lottie-react-native";
import { Ionicons } from "@expo/vector-icons";
export const Header = ({ getCurrentTrain }) => {
const { currentTrainLoading, setCurrentTrainLoading } = useCurrentTrain();
return (
<View
style={{
alignContent: "center",
alignItems: "center",
width: "100%",
marginVertical: 10,
flexDirection: "row",
}}
>
<View style={{ flex: 1 }}></View>
<View style={{}}>
<Text style={{ fontSize: 25, color: "white", fontWeight: "bold" }}>
次の列車
</Text>
<Text style={{ fontSize: 15, color: "white" }}>Next Train</Text>
</View>
<View style={{ flex: 1, flexDirection: "row-reverse" }}>
{currentTrainLoading == "loading" ? (
<LottieView
autoPlay
loop
style={{ width: 40, height: 40, marginRight: 30 }}
source={require("../../../assets/51690-loading-diamonds.json")}
/>
) : currentTrainLoading == "error" ? (
<Ionicons
name="reload"
color="white"
size={30}
style={{ marginRight: 30 }}
onPress={() => {
setCurrentTrainLoading("loading");
getCurrentTrain();
}}
/>
) : null}
</View>
</View>
);
};

View File

@ -0,0 +1,25 @@
import { Text } from "react-native";
import { Switch } from "react-native-elements";
import { AS } from "../../../storageControl";
export const SwitchBox = (props) => {
const { value, setValue, setKey, title } = props;
const textStyle = {
alignItems: "center",
alignContent: "center",
textAlign: "center",
textAlignVertical: "center",
color: "white",
};
return (
<>
<Text style={textStyle}>{title}</Text>
<Switch
value={value}
onValueChange={(v) => {
AS.setItem(setKey, v.toString());
setValue(v);
}}
/>
</>
);
};

View File

@ -0,0 +1,14 @@
import React, { FC } from "react";
import { Text, TextStyle, View } from "react-native";
const descriptionStyle: TextStyle = {
fontSize: parseInt("16%"),
fontWeight: "bold",
};
type Props = {
time: string;
};
export const DependTime: FC<Props> = ({ time }) => (
<View style={{ flex: 3 }}>
<Text style={{ ...descriptionStyle, color: "white" }}>{time}</Text>
</View>
);

View File

@ -0,0 +1,47 @@
import React, { FC } from "react";
import { Text, TextStyle, View, TouchableOpacity } from "react-native";
const descriptionStyle: TextStyle = {
fontSize: parseInt("16%"),
fontWeight: "bold",
};
type Props = {
info: string;
numberOfLines?: number;
onClick?: () => void;
onLongClick?: () => void;
};
export const Description:FC<Props> = ({ info, numberOfLines = 0, onClick, onLongClick }) => (
<TouchableOpacity
style={{
alignContent: "center",
alignItems: "center",
width: "94%",
marginVertical: 5,
marginHorizontal: "3%",
backgroundColor: "#000",
flexDirection: "row",
overflow: "hidden",
}}
onPress={onClick}
onLongPress={onLongClick}
>
<View style={{ flex: 4, flexDirection: "row" }}>
{numberOfLines == 1 ? (
<Text style={{ ...descriptionStyle, color: "red" }}>
&gt;{" "}
</Text>
) : (
<Text style={{ ...descriptionStyle, color: "green" }}> &gt; </Text>
)}
<Text
style={{ ...descriptionStyle, color: "green" }}
numberOfLines={numberOfLines}
>
{info}
</Text>
</View>
</TouchableOpacity>
);

View File

@ -0,0 +1,21 @@
import React, { FC } from "react";
import { Text, View } from "react-native";
type Props = {
lastStation: string;
};
export const LastStation: FC<Props> = ({ lastStation }) => {
return (
<View style={{ flex: 4, flexDirection: "row" }}>
<Text
style={{
fontSize: lastStation.length > 4 ? parseInt("12%") : parseInt("16%"),
color: "white",
fontWeight: "bold",
}}
>
{lastStation}
</Text>
</View>
);
};

View File

@ -0,0 +1,18 @@
import React, { FC } from "react";
import { Text, TextStyle, View } from "react-native";
const descriptionStyle: TextStyle = {
fontSize: parseInt("16%"),
fontWeight: "bold",
};
type Props = {
trainDelayStatus: string;
};
export const StatusAndDelay: FC<Props> = ({ trainDelayStatus }) => {
return (
<View style={{ flex: 4 }}>
<Text style={{ ...descriptionStyle, color: "white", paddingLeft: 1 }}>
{trainDelayStatus}
</Text>
</View>
);
};

View File

@ -0,0 +1,33 @@
import React, { FC } from "react";
import { Text, View } from "react-native";
import { getTrainType } from "../../../lib/getTrainType";
type Props = {
trainName: string;
trainNumDistance?: number;
trainIDSwitch: boolean;
trainID: string;
type: string;
};
export const TrainName: FC<Props> = (props) => {
const { trainName, trainNumDistance, trainIDSwitch, trainID, type } = props;
const { name, color } = getTrainType(type);
const TrainNumber =
trainNumDistance != undefined
? `${
parseInt(trainID.replace("M", "").replace("D", "")) - trainNumDistance
}`
: "";
return (
<View style={{ flex: 9 }}>
<Text
style={{
fontSize: trainName.length > 6 ? parseInt("12%") : parseInt("16%"),
color: color,
fontWeight: "bold",
}}
>
{trainIDSwitch ? trainID : `${name} ${trainName}${TrainNumber}`}
</Text>
</View>
);
};

View File

@ -1,19 +1,18 @@
import React, { useState, useEffect } from "react";
import { View, Text, TouchableOpacity } from "react-native";
import { Switch } from "react-native-elements";
import { View } from "react-native";
import { widthPercentageToDP as wp } from "react-native-responsive-screen";
import LottieView from "lottie-react-native";
import { Ionicons } from "@expo/vector-icons";
import { customTrainDataDetector } from "../custom-train-data";
import { useInterval } from "../../lib/useInterval";
import { objectIsEmpty } from "../../lib/objectIsEmpty";
import { getTrainType } from "../../lib/getTrainType";
import { getTrainDelayStatus } from "../../lib/getTrainDelayStatus";
import { checkDuplicateTrainData } from "../../lib/checkDuplicateTrainData";
import { useCurrentTrain } from "../../stateBox/useCurrentTrain";
import { useAreaInfo } from "../../stateBox/useAreaInfo";
import { SheetManager } from "react-native-actions-sheet";
import { AS } from "../../storageControl";
import { Footer } from "./LED_Vision_Component/Footer";
import { Header } from "./LED_Vision_Component/Header";
import { Description } from "./LED_inside_Component/Description";
import { EachData } from "./EachData";
/**
*
@ -50,7 +49,6 @@ export default function LED_vision(props) {
trainDiagram,
getCurrentTrain,
navigate,
originalStationList,
openStationACFromEachTrainInfo,
} = props;
const { currentTrain } = useCurrentTrain();
@ -58,30 +56,18 @@ export default function LED_vision(props) {
const [finalSwitch, setFinalSwitch] = useState(false);
const [trainIDSwitch, setTrainIDSwitch] = useState(false);
const [trainDescriptionSwitch, setTrainDescriptionSwitch] = useState(false);
const { areaInfo } = useAreaInfo();
const [isInfoArea, setIsInfoArea] = useState(false);
const { areaInfo, areaStationID } = useAreaInfo();
useEffect(() => {
AS.getItem("LEDSettings/trainIDSwitch").then((data) => {
console.log(data);
if (data == "true") {
setTrainIDSwitch(true);
} else {
setTrainIDSwitch(false);
}
setTrainIDSwitch(data === "true");
});
AS.getItem("LEDSettings/trainDescriptionSwitch").then((data) => {
if (data == "true") {
setTrainDescriptionSwitch(true);
} else {
setTrainDescriptionSwitch(false);
}
setTrainDescriptionSwitch(data == "true");
});
AS.getItem("LEDSettings/finalSwitch").then((data) => {
if (data == "true") {
setFinalSwitch(true);
} else {
setFinalSwitch(false);
}
setFinalSwitch(data == "true");
});
}, []);
@ -93,11 +79,12 @@ export default function LED_vision(props) {
}
let returnData = {};
Object.keys(trainDiagram).forEach((key) => {
if (trainDiagram[key].match(station.Station_JP + ",")) {
if (trainDiagram[key].match(station[0].Station_JP + ",")) {
returnData[key] = trainDiagram[key];
}
});
setStationDiagram(returnData);
setIsInfoArea(station.some((s) => areaStationID.includes(s.StationNumber)));
}, [trainDiagram, station]);
const [trainTimeAndNumber, setTrainTimeAndNumber] = useState(null);
@ -105,7 +92,7 @@ export default function LED_vision(props) {
useEffect(() => {
//現在の駅に停車する列車から時刻を切り出してLEDベースにフォーマット
if (objectIsEmpty(stationDiagram)) return () => {};
const getTimeData = getTime(stationDiagram, station);
const getTimeData = getTime(stationDiagram, station[0]);
setTrainTimeAndNumber(getTimeData);
}, [stationDiagram]);
@ -166,11 +153,7 @@ export default function LED_vision(props) {
date.setHours(parseInt(data[0]));
date.setMinutes(parseInt(data[1]) + parseInt(delay));
if (!(newDate > date)) {
return true;
}
return false;
return !(newDate > date);
};
const [areaString, setAreaString] = useState("");
@ -179,11 +162,7 @@ export default function LED_vision(props) {
useInterval(
() => {
if (areaInfo != "") {
if (areaStringLength < move) {
setMove(0);
} else {
setMove(move + 1);
}
setMove(areaStringLength < move ? 0 : move + 1);
}
},
350,
@ -220,17 +199,18 @@ export default function LED_vision(props) {
<Header getCurrentTrain={getCurrentTrain} />
{selectedTrain.map((d) => (
<EachData
d={d}
trainIDSwitch={trainIDSwitch}
trainDescriptionSwitch={trainDescriptionSwitch}
station={station}
customTrainDataDetector={customTrainDataDetector}
navigate={navigate}
originalStationList={originalStationList}
openStationACFromEachTrainInfo={openStationACFromEachTrainInfo}
{...{
d,
trainIDSwitch,
trainDescriptionSwitch,
customTrainDataDetector,
navigate,
openStationACFromEachTrainInfo,
}}
station={station[0]}
/>
))}
{areaString != "" && (
{areaString != "" && isInfoArea && (
<Description
numberOfLines={1}
info={areaString.replaceAll("\n", "").replaceAll("\r", "")}
@ -239,302 +219,15 @@ export default function LED_vision(props) {
)}
<Footer
trainIDSwitch={trainIDSwitch}
setTrainIDSwitch={setTrainIDSwitch}
trainDescriptionSwitch={trainDescriptionSwitch}
setTrainDescriptionSwitch={setTrainDescriptionSwitch}
finalSwitch={finalSwitch}
setFinalSwitch={setFinalSwitch}
{...{
trainIDSwitch,
setTrainIDSwitch,
trainDescriptionSwitch,
setTrainDescriptionSwitch,
finalSwitch,
setFinalSwitch,
}}
/>
</View>
);
}
const Header = ({ getCurrentTrain }) => {
const { currentTrainLoading, setCurrentTrainLoading } = useCurrentTrain();
return (
<View
style={{
alignContent: "center",
alignItems: "center",
width: "100%",
marginVertical: 10,
flexDirection: "row",
}}
>
<View style={{ flex: 1 }}></View>
<View style={{}}>
<Text style={{ fontSize: 25, color: "white", fontWeight: "bold" }}>
次の列車
</Text>
<Text style={{ fontSize: 15, color: "white" }}>Next Train</Text>
</View>
<View style={{ flex: 1, flexDirection: "row-reverse" }}>
{currentTrainLoading == "loading" ? (
<LottieView
autoPlay
loop
style={{ width: 40, height: 40, marginRight: 30 }}
source={require("../../assets/51690-loading-diamonds.json")}
/>
) : currentTrainLoading == "error" ? (
<Ionicons
name="reload"
color="white"
size={30}
style={{ marginRight: 30 }}
onPress={() => {
setCurrentTrainLoading("loading");
getCurrentTrain();
}}
/>
) : null}
</View>
</View>
);
};
const Footer = (props) => {
const {
trainIDSwitch,
setTrainIDSwitch,
trainDescriptionSwitch,
setTrainDescriptionSwitch,
finalSwitch,
setFinalSwitch,
} = props;
const textStyle = {
alignItems: "center",
alignContent: "center",
textAlign: "center",
textAlignVertical: "center",
color: "white",
};
return (
<View style={{ flexDirection: "row", padding: 10, alignItems: "center" }}>
<Text style={textStyle}>種別名 / 列番</Text>
<Switch
value={trainIDSwitch}
onValueChange={(value) => {
AS.setItem("LEDSettings/trainIDSwitch", value.toString());
setTrainIDSwitch(value);
}}
/>
<View style={{ flex: 1 }} />
<Text style={textStyle}>列車情報</Text>
<Switch
value={trainDescriptionSwitch}
onValueChange={(value) => {
AS.setItem("LEDSettings/trainDescriptionSwitch", value.toString());
setTrainDescriptionSwitch(value);
}}
/>
<View style={{ flex: 1 }} />
<Text style={textStyle}>当駅止表示</Text>
<Switch
value={finalSwitch}
onValueChange={(value) => {
AS.setItem("LEDSettings/finalSwitch", value.toString());
setFinalSwitch(value);
}}
/>
</View>
);
};
const EachData = ({
d,
trainIDSwitch,
trainDescriptionSwitch,
station,
customTrainDataDetector,
navigate,
originalStationList,
openStationACFromEachTrainInfo,
}) => {
const { currentTrain } = useCurrentTrain();
const openTrainInfo = (d) => {
let TrainNumber = "";
if (train.trainNumDistance != undefined) {
const timeInfo =
parseInt(d.train.replace("M", "").replace("D", "")) -
train.trainNumDistance;
TrainNumber = timeInfo + "号";
}
const payload = {
data: {
trainNum: d.train,
limited: `${getTrainType(train.type).data}:${
train.trainName
}${TrainNumber}`,
},
navigate,
originalStationList,
openStationACFromEachTrainInfo,
from: "LED",
};
SheetManager.show("EachTrainInfo", {
payload,
});
};
const [train, setTrain] = useState(customTrainDataDetector(d.train));
useEffect(() => {
setTrain(customTrainDataDetector(d.train));
}, [currentTrain, d.train, trainDescriptionSwitch]);
// 土讃線複数存在対策
const currentTrainData = checkDuplicateTrainData(
currentTrain.filter((a) => a.num == d.train)
);
const trainDelayStatus = getTrainDelayStatus(
currentTrainData,
station.Station_JP
);
const trainPositionText = currentTrainData?.Pos.match("")
? `現在地:${
currentTrainData?.Pos.replace("(下り)", "")
.replace("(上り)", "")
.split("")[currentTrainData?.Direction == 1 ? 0 : 1]
}${
currentTrainData?.Pos.replace("(下り)", "")
.replace("(上り)", "")
.split("")[currentTrainData?.Direction == 1 ? 1 : 0]
}間を走行中`
: `現在地:${currentTrainData?.Pos}`;
return (
<>
<TouchableOpacity
style={{
alignContent: "center",
alignItems: "center",
width: "94%",
marginVertical: 5,
marginHorizontal: "3%",
backgroundColor: "#000",
flexDirection: "row",
}}
onPress={() => openTrainInfo(d)}
>
<TrainName
trainName={train.trainName}
trainNumDistance={train.trainNumDistance}
trainIDSwitch={trainIDSwitch}
trainID={d.train}
type={train.type}
/>
<LastStation lastStation={d.lastStation} />
<DependTime time={d.time} />
<StatusAndDelay trainDelayStatus={trainDelayStatus} />
</TouchableOpacity>
{trainDescriptionSwitch && <Description info={`${trainPositionText}`} />}
{trainDescriptionSwitch && !!train.info && (
<Description info={train.info} />
)}
</>
);
};
const TrainName = ({
trainName,
trainNumDistance,
trainIDSwitch,
trainID,
type,
}) => {
const { name, color } = getTrainType(type);
let TrainNumber =
trainNumDistance != undefined
? `${
parseInt(trainID.replace("M", "").replace("D", "")) - trainNumDistance
}`
: "";
return (
<View style={{ flex: 9 }}>
<Text
style={{
fontSize: trainName.length > 6 ? parseInt("12%") : parseInt("16%"),
color: color,
fontWeight: "bold",
}}
>
{trainIDSwitch ? trainID : `${name} ${trainName}${TrainNumber}`}
</Text>
</View>
);
};
const LastStation = ({ lastStation }) => {
return (
<View style={{ flex: 4, flexDirection: "row" }}>
<Text
style={{
fontSize: lastStation.length > 4 ? parseInt("12%") : parseInt("16%"),
color: "white",
fontWeight: "bold",
}}
>
{lastStation}
</Text>
</View>
);
};
const DependTime = ({ time }) => (
<View style={{ flex: 3 }}>
<Text
style={{
fontSize: parseInt("16%"),
color: "white",
fontWeight: "bold",
}}
>
{time}
</Text>
</View>
);
const StatusAndDelay = ({ trainDelayStatus }) => {
return (
<View style={{ flex: 4 }}>
<Text
style={{
fontSize: parseInt("16%"),
color: "white",
fontWeight: "bold",
paddingLeft: 1,
}}
>
{trainDelayStatus}
</Text>
</View>
);
};
const Description = ({ info, numberOfLines = 0, onClick }) => (
<TouchableOpacity
style={{
alignContent: "center",
alignItems: "center",
width: "94%",
marginVertical: 5,
marginHorizontal: "3%",
backgroundColor: "#000",
flexDirection: "row",
}}
onPress={onClick}
>
<View style={{ flex: 4 }}>
<Text
style={{
fontSize: parseInt("16%"),
color: "green",
fontWeight: "bold",
}}
numberOfLines={numberOfLines}
>
{" "}
&gt; {info}
</Text>
</View>
</TouchableOpacity>
);

View File

@ -0,0 +1,42 @@
import React, { FC, useEffect } from "react";
import { Platform, Text } from "react-native";
import { useFavoriteStation } from "../../stateBox/useFavoriteStation";
type Props = {
currentStation: any[];
isMatsuyama: boolean;
};
export const AddressText: FC<Props> = (props) => {
const { currentStation, isMatsuyama } = props;
const {lodAddMigration} = useFavoriteStation();
const [stationAddress, setStationAddress] = React.useState("");
useEffect(() => {
if (!!currentStation[0].jslodApi) {
fetch(`${currentStation[0].jslodApi}.json`)
.then((response) => response.json())
.then((data) => {
const c =
data[currentStation[0].jslodApi][
"http://dbpedia.org/ontology/address"
][0]["value"];
setStationAddress(c);
});
}else{
lodAddMigration();
}
}, [currentStation]);
return (
<Text
style={{
fontSize: parseInt("10%"),
color: isMatsuyama ? "white" : "#005170",
position: "absolute",
bottom: isMatsuyama ? Platform.OS === "ios"?"25.5%":"26.5%" : "0%",
textAlign: "center",
width: "100%",
fontWeight: "bold",
}}
>
{stationAddress}
</Text>
);
};

View File

@ -0,0 +1,30 @@
import React, { FC, useEffect, useRef, useState } from "react";
import LottieView from "lottie-react-native";
type Props = {
progress: number;
};
export const LottieDelayView: FC<Props> = ({ progress }) => {
const lottieRef = useRef<LottieView>();
const [progressState, setProgressState] = useState(undefined);
useEffect(() => {
if (progress == 0) {
lottieRef.current.play(progressState !== undefined ? 35 : 7, 7);
} else {
lottieRef.current.play(progressState !== undefined ? 7 : 35, 35);
}
}, [progress]);
return (
<LottieView
progress={progressState}
speed={1.4}
style={{ width: 80, height: 80 }}
loop={false}
source={require("../../assets/939-star.json")}
ref={lottieRef}
onAnimationFinish={(isCanceled) => {
setProgressState(progress);
}}
/>
);
};

View File

@ -0,0 +1,113 @@
import React, { CSSProperties, FC } from "react";
import { widthPercentageToDP as wp } from "react-native-responsive-screen";
import { Platform, Text, TextStyle, View, ViewStyle } from "react-native";
import { StationName } from "./StationName";
import lineColorList from "../../assets/originData/lineColorList";
export const NextPreStationLine = ({ nexStation, preStation, isMatsuyama }) => {
return (
<View style={}>
<View style={}>
{!!preStation && (
<>
<BottomSideArrow isMatsuyama={isMatsuyama} children={"◀"} />
{!!preStation.StationNumber && (
<BottomStationNumberView
isMatsuyama={isMatsuyama}
children={preStation.StationNumber}
/>
)}
<StationName
stringData={preStation}
ss={{ flex: 1, alignItems: "flex-start" }}
/>
</>
)}
</View>
<View style={}>
{!!nexStation && (
<>
<StationName
stringData={nexStation}
ss={{ flex: 1, alignItems: "flex-end" }}
/>
{!!nexStation.StationNumber && (
<BottomStationNumberView
isMatsuyama={isMatsuyama}
children={nexStation.StationNumber}
/>
)}
<BottomSideArrow isMatsuyama={isMatsuyama} children={"▶"} />
</>
)}
</View>
</View>
);
};
type FCimport = {
isMatsuyama: boolean;
children: string;
};
const BottomSideArrow: FC<FCimport> = ({ isMatsuyama, children }) => {
return !isMatsuyama && <Text style={}>{children}</Text>;
};
const BottomStationNumberView: FC<FCimport> = ({ isMatsuyama, children }) => {
const lineID = children.slice(0, 1);
const lineName = children.slice(1);
return (
<View
style={{
...(isMatsuyama ? 下枠駅ナンバーB : 下枠駅ナンバー),
borderColor: lineColorList[lineID],
}}
>
<View style={{ flex: 1 }} />
<Text
style={{
fontSize: parseInt(Platform.OS === "ios" ? "8%" : "10%"),
color: "black",
textAlign: "center",
fontWeight: "bold",
}}
>
{lineID + "\n" + lineName}
</Text>
<View style={{ flex: 1 }} />
</View>
);
};
const 下枠フレーム: ViewStyle = {
flex: 1,
flexDirection: "row",
alignContent: "center",
alignItems: "center",
};
const 下枠左右マーク: TextStyle = {
fontWeight: "bold",
fontSize: parseInt("20%"),
color: "white",
paddingHorizontal: 5,
textAlignVertical: "center",
};
const 下枠駅ナンバー: ViewStyle = {
alignContent: "center",
alignItems: "center",
width: wp("8%"),
height: wp("8%"),
margin: wp("1%"),
backgroundColor: "white",
borderWidth: parseInt("3%"),
borderRadius: parseInt("100%"),
};
const 下枠駅ナンバーB: ViewStyle = {
alignContent: "center",
alignItems: "center",
width: wp("7%"),
height: wp("7%"),
margin: wp("2%"),
backgroundColor: "white",
borderWidth: parseInt("3%"),
borderRadius: parseInt("100%"),
};

View File

@ -7,18 +7,18 @@ import { useInterval } from "../../lib/useInterval";
import { AS } from "../../storageControl";
import { useFavoriteStation } from "../../stateBox/useFavoriteStation";
import lineColorList from "../../assets/originData/lineColorList";
import { StationNameArea } from "./StationNameArea";
import { StationNumberMaker } from "./StationNumberMaker";
import { NextPreStationLine } from "./NextPreStationLine";
import { LottieDelayView } from "./LottieDelayView";
import { AddressText } from "./AddressText";
import { useStationList } from "../../stateBox/useStationList";
export default function Sign(props) {
const {
currentStation,
originalStationList,
oP,
oLP,
isCurrentStation = false,
} = props;
const { currentStation, oP, oLP, isCurrentStation = false } = props;
const { favoriteStation, setFavoriteStation } = useFavoriteStation();
const [nexPrePosition, setNexPrePosition] = useState(0);
const { originalStationList } = useStationList();
const [preStation, setPreStation] = useState();
const [nexStation, setNexStation] = useState();
@ -61,6 +61,8 @@ export default function Sign(props) {
useEffect(() => {
setNexPrePosition(0);
getPreNextStation(currentStation[0]);
if (currentStation.length == 1) return () => {};
getPreNextStation(currentStation[1]);
}, [currentStation]);
useEffect(() => {
@ -91,308 +93,132 @@ export default function Sign(props) {
];
}
});
setPreStation(returnData[0]);
setNexStation(returnData[1]);
if (now.Station_JP == "宇多津" && now.StationNumber == null) {
if (returnData[1]) setPreStation(returnData[1]);
if (returnData[0]) setNexStation(returnData[0]);
} else {
if (returnData[0]) setPreStation(returnData[0]);
if (returnData[1]) setNexStation(returnData[1]);
}
};
const isMatsuyama = currentStation[0].StationNumber == "Y55";
//const isMatsuyama = true;
const favoliteChanger = () => {
if (testButtonStatus) {
const otherData = favoriteStation.filter((d) => {
const compare = JSON.stringify(d);
const current = JSON.stringify(currentStation);
return compare !== current;
});
AS.setItem("favoriteStation", JSON.stringify(otherData));
setFavoriteStation(otherData);
} else {
let ret = favoriteStation;
ret.push(currentStation);
AS.setItem("favoriteStation", JSON.stringify(ret));
setFavoriteStation(ret);
}
setTestButtonStatus(!testButtonStatus);
};
const lottieRef = useRef();
return (
<TouchableOpacity style={styleSheet.外枠} onPress={oP} onLongPress={oLP}>
<StationNumberMaker currentStation={currentStation} />
<StationNameArea currentStation={currentStation} />
<TouchableOpacity
style={styleSheet[isMatsuyama ? "外枠B" : "外枠"]}
onPress={oP}
onLongPress={oLP}
>
{isMatsuyama && (
<LottieView
autoPlay
loop
style={{
width: wp("80%"),
height: (wp("80%") / 20) * 9,
backgroundColor: "#fff",
}}
source={require("../../assets/StationSign.json")}
/>
)}
<StationNumberMaker {...{ currentStation, isMatsuyama }} />
<StationNameArea {...{ currentStation, isMatsuyama }} />
{isCurrentStation ? (
<TouchableOpacity style={{ position: "absolute", right: 0, top: 0 }}>
<View style={{ position: "absolute", right: 0, top: 0 }}>
<MaterialCommunityIcons
name="crosshairs-gps"
style={{ padding: 5 }}
color="#2E94BB"
color="#0099CC"
size={30}
/>
</TouchableOpacity>
</View>
) : (
<TouchableOpacity
style={{ position: "absolute", right: -15, top: -20 }}
onPress={() => {
if (testButtonStatus) {
const otherData = favoriteStation.filter((d) => {
const compare = JSON.stringify(d);
const current = JSON.stringify(currentStation);
if (compare !== current) {
return true;
} else {
return false;
}
});
AS.setItem("favoriteStation", JSON.stringify(otherData));
setFavoriteStation(otherData);
} else {
let ret = favoriteStation;
ret.push(currentStation);
AS.setItem("favoriteStation", JSON.stringify(ret));
setFavoriteStation(ret);
}
setTestButtonStatus(!testButtonStatus);
}}
onPress={favoliteChanger}
>
<LottieDelayView
progress={testButtonStatus ? 1 : 0}
speed={1.4}
style={{ width: 80, height: 80 }}
source={require("../../assets/939-star.json")}
lottieRef={lottieRef}
loop={false}
/>
<LottieDelayView progress={testButtonStatus ? 1 : 0} />
</TouchableOpacity>
)}
<Text style={styleSheet.JRStyle}>JR</Text>
<View style={styleSheet.下帯} />
<View style={styleSheet.下帯内容}>
<NexPreStationLine preStation={preStation} nexStation={nexStation} />
<View style={styleSheet[isMatsuyama ? "下帯B" : "下帯"]} />
<View style={styleSheet[isMatsuyama ? "下帯内容B" : "下帯内容"]}>
<NextPreStationLine {...{ nexStation, preStation, isMatsuyama }} />
</View>
<AddressText {...{ currentStation, isMatsuyama }} />
</TouchableOpacity>
);
}
const LottieDelayView = ({
progress,
speed,
style,
source,
lottieRef,
loop,
}) => {
const [progressState, setProgressState] = useState(undefined);
useEffect(() => {
if (progress == 0) {
lottieRef.current.play(progressState !== undefined ? 35 : 7, 7);
} else {
lottieRef.current.play(progressState !== undefined ? 7 : 35, 35);
}
}, [progress]);
return (
<LottieView
progress={progressState}
speed={speed}
style={style}
source={source}
ref={lottieRef}
loop={loop}
onAnimationFinish={(isCanceled) => {
setProgressState(progress);
}}
/>
);
};
const NexPreStationLine = ({ nexStation, preStation }) => {
return (
<View style={styleSheet.下枠フレーム}>
<View style={styleSheet.下枠フレーム}>
{preStation ? (
<>
<Text style={styleSheet.下枠左右マーク}></Text>
{preStation.StationNumber ? (
<View style={styleSheet.下枠駅ナンバー}>
<View style={{ flex: 1 }} />
<Text
style={{
fontSize: parseInt("10%"),
color: "white",
}}
>
{preStation.StationNumber}
</Text>
<View style={{ flex: 1 }} />
</View>
) : (
<></>
)}
<StationName
stringData={preStation}
ss={{ flex: 1, alignItems: "flex-start" }}
/>
</>
) : (
<></>
)}
</View>
<View style={styleSheet.下枠フレーム}>
{nexStation ? (
<>
<StationName
stringData={nexStation}
ss={{ flex: 1, alignItems: "flex-end" }}
/>
{nexStation.StationNumber ? (
<View style={styleSheet.下枠駅ナンバー}>
<View style={{ flex: 1 }} />
<Text style={{ fontSize: parseInt("10%"), color: "white" }}>
{nexStation.StationNumber}
</Text>
<View style={{ flex: 1 }} />
</View>
) : (
<></>
)}
<Text style={styleSheet.下枠左右マーク}></Text>
</>
) : (
<></>
)}
</View>
</View>
);
};
const StationNumberMaker = (props) => {
const getTop = (array, index) => {
if (array.length == 1) return 20;
else if (index == 0) return 5;
else if (index == 1) return 35;
else return 20;
};
return props.currentStation
.filter((d) => (d.StationNumber ? true : false))
.map((d, index, array) => {
const lineID = d.StationNumber.slice(0, 1);
const lineName = d.StationNumber.slice(1);
return (
<View
style={{
position: "absolute",
alignContent: "center",
alignItems: "center",
top: getTop(array, index) + "%",
right: "10%",
width: wp("10%"),
height: wp("10%"),
borderColor: lineColorList[lineID],
borderWidth: parseInt("3%"),
borderRadius: parseInt("100%"),
}}
key={array[index].StationNumber}
>
<View style={{ flex: 1 }} />
<Text
style={{
fontSize: parseInt("13%"),
margin: 0,
padding: 0,
textAlign: "center",
}}
>
{lineID + "\n" + lineName}
</Text>
<View style={{ flex: 1 }} />
</View>
);
});
};
const StationNameArea = (props) => {
const { currentStation } = props;
return (
<View style={styleSheet.stationNameAreaOverWrap}>
<View style={{ flex: 1 }} />
<View style={{ alignItems: "center" }}>
{/* <Text style={{fontWeight:"bold",fontSize:parseInt("15%"),color:"#005170"}}>{stationName.今.LineName}</Text> */}
<Text style={styleSheet.Station_JP}>
{currentStation[0].Station_JP}
</Text>
<Text style={styleSheet.Station_EN}>
{currentStation[0].Station_EN}
</Text>
</View>
<View style={{ flex: 1 }} />
</View>
);
};
const StationName = (props) => {
const { stringData, ss } = props;
return (
<View style={ss}>
<Text style={styleSheet.下枠駅名}>{stringData.Station_JP}</Text>
<Text style={styleSheet.下枠駅名}>{stringData.Station_EN}</Text>
</View>
);
};
const styleSheet = {
外枠: {
width: wp("80%"),
height: (wp("80%") / 20) * 9,
borderColor: "#2E94BB",
borderColor: "#0099CC",
borderWidth: 1,
backgroundColor: "white",
},
外枠B: {
width: wp("80%"),
height: (wp("80%") / 20) * 9,
borderWidth: 0,
},
下帯: {
position: "absolute",
bottom: "8%",
left: "0%",
width: "100%",
height: "27%",
backgroundColor: "#0099CC",
},
下帯B: {
position: "absolute",
bottom: "0%",
left: "0%",
width: "100%",
height: "30%",
backgroundColor: "#2E94BB",
height: "26%",
backgroundColor: "#454545",
},
JRStyle: {
position: "absolute",
top: "2%",
left: "2%",
fontWeight: "bold",
fontSize: parseInt("30%"),
color: "#2E94BB",
},
stationNameAreaOverWrap: {
position: "absolute",
top: "10%",
alignContent: "center",
flexDirection: "row",
},
Station_JP: {
fontWeight: "bold",
fontSize: parseInt("40%"),
color: "#005170",
},
Station_EN: {
fontWeight: "bold",
fontSize: parseInt("15%"),
color: "#005170",
fontSize: parseInt("25%"),
color: "#0099CC",
},
下帯内容: {
position: "absolute",
bottom: "0%",
height: "30%",
bottom: "8%",
height: "27%",
width: "100%",
alignItems: "center",
flexDirection: "column",
},
下枠フレーム: {
flex: 1,
flexDirection: "row",
alignContent: "center",
下帯内容B: {
position: "absolute",
bottom: "0%",
height: "26%",
width: "100%",
alignItems: "center",
},
下枠左右マーク: {
fontWeight: "bold",
fontSize: parseInt("20%"),
color: "white",
paddingHorizontal: 10,
textAlignVertical: "center",
},
下枠駅ナンバー: {
alignContent: "center",
alignItems: "center",
width: wp("8%"),
height: wp("8%"),
margin: wp("1%"),
borderColor: "white",
borderWidth: parseInt("2%"),
borderRadius: parseInt("100%"),
},
下枠駅名: {
fontWeight: "bold",
fontSize: parseInt("15%"),
color: "white",
flex: 1,
textAlignVertical: "center",
flexDirection: "column",
},
};

View File

@ -0,0 +1,22 @@
import React, { FC } from "react";
import { Platform, Text, TextStyle, View } from "react-native";
export const StationName: FC<{
stringData: { Station_JP: string; Station_EN: string };
ss: TextStyle;
}> = (props) => {
const { stringData, ss } = props;
return (
<View style={ss}>
<Text style={styleSheet}>{stringData.Station_JP}</Text>
<Text style={styleSheet}>{stringData.Station_EN}</Text>
</View>
);
};
const styleSheet: TextStyle = {
fontWeight: "bold",
fontSize: Platform.OS === "ios" ? parseInt("14%") : parseInt("15%"),
color: "white",
flex: 1,
textAlignVertical: "center",
};

View File

@ -0,0 +1,42 @@
import React, { CSSProperties } from "react";
import { Platform, Text, TextStyle, View, ViewStyle } from "react-native";
export const StationNameArea = (props) => {
const { currentStation, isMatsuyama } = props;
const stationNameAreaOverWrap: ViewStyle = {
position: "absolute",
top: "10%",
alignContent: "center",
flexDirection: "row",
height: "50%",
width: "100%",
};
const Station_JP: TextStyle = {
letterSpacing: currentStation[0].Station_JP.length < 4 ? 15 : 0,
// iOSの場合、letterSPacingで末尾の文字の後ろにもpaddingが入るため、paddingLeftを設定
paddingLeft: currentStation[0].Station_JP.length < 4 &&Platform.OS === "ios" ? 15 : 0,
fontWeight: "bold",
fontSize: parseInt(currentStation[0].Station_JP.length < 6 ? "40%" : "25%"),
color: isMatsuyama ? "white" : "#005170",
};
const Station_EN: TextStyle = {
fontWeight: "bold",
fontSize: parseInt("15%"),
color: isMatsuyama ? "white" : "#005170",
};
return (
<View style={stationNameAreaOverWrap}>
<View style={{ flex: 1 }} />
<View style={{ alignItems: "center",flexDirection:"column" }}>
<View style={{ flex: 1 }} />
{/* <Text style={{fontWeight:"bold",fontSize:parseInt("15%"),color:"#005170"}}>{stationName.今.LineName}</Text> */}
<Text style={Station_JP}>{currentStation[0].Station_JP}</Text>
<Text style={Station_EN}>{currentStation[0].Station_EN}</Text>
<View style={{ flex: 1 }} />
</View>
<View style={{ flex: 1 }} />
</View>
);
};

View File

@ -0,0 +1,53 @@
import React from "react";
import { Text, View } from "react-native";
import { widthPercentageToDP as wp } from "react-native-responsive-screen";
import lineColorList from "../../assets/originData/lineColorList";
export const StationNumberMaker = (props) => {
const { currentStation, isMatsuyama } = props;
const getTop = (array: number[], index: number) => {
if (array.length == 1) return 20;
else if (index == 0) return 5;
else if (index == 1) return 35;
else return 20;
};
return currentStation
.filter((d) => (d.StationNumber ? true : false))
.map((d, index, array) => {
const lineID = d.StationNumber.slice(0, 1);
const lineName = d.StationNumber.slice(1);
return (
<View
style={{
position: "absolute",
alignContent: "center",
alignItems: "center",
top: `${getTop(array, index)}%`,
right: "10%",
width: wp("10%"),
height: wp("10%"),
borderColor: lineColorList[lineID],
backgroundColor: "white",
borderWidth: parseInt("3%"),
borderRadius: parseInt("100%"),
}}
key={array[index].StationNumber}
>
<View style={{ flex: 1 }} />
<Text
style={{
fontSize: parseInt("13%"),
margin: 0,
padding: 0,
textAlign: "center",
color: "black",
fontWeight: "bold",
}}
>
{lineID + "\n" + lineName}
</Text>
<View style={{ flex: 1 }} />
</View>
);
});
};

View File

@ -1 +0,0 @@
export const news = "2024-6-4";

1
config/newsUpdate.ts Normal file
View File

@ -0,0 +1 @@
export const news = "2024-9-29";

View File

@ -1,7 +1,7 @@
const WEBVIEW = "WEBVIEW";
import React, { Component } from "react";
import { StatusBar, View, TouchableOpacity, Text } from "react-native";
import React from "react";
import { View } from "react-native";
import { WebView } from "react-native-webview";
import { BigButton } from "./components/atom/BigButton";
export default ({ navigation: { navigate }, route }) => {
const { info, goTo, useShow } = route.params;
const onExit = () => {
@ -9,30 +9,13 @@ export default ({ navigation: { navigate }, route }) => {
useShow && useShow();
};
return (
<View style={styles.View}>
<View style={styles}>
<WebView
useWebKit
source={{ uri: info.replace("http://", "https://") }}
/>
<TouchableOpacity style={styles.touch} onPress={onExit}>
<View style={{ flex: 1 }} />
<Text style={{ fontSize: 25, fontWeight: "bold", color: "white" }}>
閉じる
</Text>
<View style={{ flex: 1 }} />
</TouchableOpacity>
<BigButton onPress={onExit} string="閉じる" />
</View>
);
};
const styles = {
View: { height: "100%", backgroundColor: "#0099CC" },
touch: {
padding: 10,
flexDirection: "row",
borderColor: "white",
borderWidth: 1,
margin: 10,
borderRadius: 5,
alignItems: "center",
},
};
const styles = { height: "100%", backgroundColor: "#0099CC" };

View File

@ -116,6 +116,7 @@ export const getStationList = async (props) => {
if (element.properties.name == stationName) {
data.lat = element.geometry.coordinates[1];
data.lng = element.geometry.coordinates[0];
data.jslodApi = element.properties.uri;
}
});
return data;
@ -182,6 +183,7 @@ export const getStationList = async (props) => {
JrHpUrl: "http://www.jr-shikoku.co.jp/01_trainbus/kakueki/sakaide/",
lat: 34.313222,
lng: 133.856325,
jslodApi: "https://uedayou.net/jrslod/四国旅客鉄道/予讃線/坂出",
},
{
@ -196,6 +198,7 @@ export const getStationList = async (props) => {
JrHpUrl: "http://www.jr-odekake.net/eki/top.php?id=0651304",
lat: 34.462562,
lng: 133.807809,
jslodApi: "https://uedayou.net/jrslod/四国旅客鉄道/本四備讃線/児島",
},
{
Station_JP: "宇多津",
@ -209,6 +212,7 @@ export const getStationList = async (props) => {
JrHpUrl: "http://www.jr-shikoku.co.jp/01_trainbus/kakueki/utazu/",
lat: 34.306379,
lng: 133.813784,
jslodApi: "https://uedayou.net/jrslod/四国旅客鉄道/本四備讃線/宇多津",
},
];
status = stationList;

View File

@ -7,7 +7,7 @@ import koutoku from "../assets/originData/koutoku";
import tokushima from "../assets/originData/tokushima";
import naruto from "../assets/originData/naruto";
import seto from "../assets/originData/seto";
export const getStationList2 = async (props) => {
export const getStationList2 = async () => {
return {
yosan,
uwajima,

View File

@ -1,5 +1,12 @@
export const getTrainDelayStatus = (current, Station_JP) => {
if (!current) return () => {};
type getTrainDelayStatus = (
current: { delay: number | "入線" | string; Pos: string },
Station_JP: string
) => string | number;
export const getTrainDelayStatus: getTrainDelayStatus = (
current,
Station_JP
) => {
if (!current) return "";
const delay = current.delay;
switch (true) {
case delay === "入線":
@ -8,7 +15,7 @@ export const getTrainDelayStatus = (current, Station_JP) => {
} else {
return "発車前";
}
case isNaN(delay):
case Number.isNaN(delay):
return delay;
case delay === 0:
return "定刻通り";

View File

@ -1,4 +1,25 @@
export const getTrainType = (nameString) => {
type nameString =
| "Rapid"
| "LTDEXP"
| "NightLTDEXP"
| "SPCL"
| "Normal"
| string;
type colorString = "aqua" | "red" | "blue" | "white";
type trainTypeString =
| "快速"
| "特急"
| "寝台特急"
| "臨時"
| "普通列車"
| "その他";
type trainTypeDataString = "rapid" | "express" | "normal";
type getTrainType = (d: nameString) => {
color: colorString;
name: trainTypeString;
data: trainTypeDataString;
};
export const getTrainType: getTrainType = (nameString) => {
switch (nameString) {
case "Rapid":
return { color: "aqua", name: "快速", data: "rapid" };

View File

@ -1,7 +1,8 @@
import React from "react";
import { Ionicons, AntDesign } from "@expo/vector-icons";
export const initIcon = (name, type) => {
type name = keyof typeof Ionicons.glyphMap & keyof typeof AntDesign.glyphMap;
type type = "Ionicons" | "AntDesign";
export const initIcon = (name: name, type:type) => {
switch (type) {
case "Ionicons":
return ({ focused, color, size }) => (

View File

@ -1,3 +0,0 @@
export const objectIsEmpty = (obj) => {
return !Object.keys(obj).length;
};

3
lib/objectIsEmpty.ts Normal file
View File

@ -0,0 +1,3 @@
export const objectIsEmpty = (obj:object) => {
return !Object.keys(obj).length;
};

View File

@ -1,4 +1,4 @@
export const parseAllTrainDiagram = (text) => {
export const parseAllTrainDiagram = (text:string) => {
const val = text.replace("[\r\n", "").split(",\r\n");
let trainDiagram = {};
val.forEach((element) => {

View File

@ -0,0 +1,25 @@
export const buildProvidersTree = (providers) => {
// 基本ケース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 }) => (
<FirstProvider>
<SecondProvider {...{ children }} />
</FirstProvider>
),
...providers,
]);
};

View File

@ -1,16 +1,16 @@
import { useEffect, useRef, useState } from "react";
// type Control = {
// start: () => void;
// stop: () => void;
// };
type Control = {
start: () => void;
stop: () => void;
};
// type State = 'RUNNING' | 'STOPPED';
type State = "RUNNING" | "STOPPED";
// type Fn = () => void;
type Fn = () => void;
export const useInterval = (fn, interval, autostart = true) => {
const onUpdateRef = useRef();
export const useInterval = (fn: Fn, interval: number, autostart = true) => {
const onUpdateRef = useRef<Fn>();
const [state, setState] = useState("RUNNING");
const start = () => {
setState("RUNNING");

View File

@ -1,6 +1,10 @@
import { getJRF } from "../components/custom-train-data";
export const injectJavascriptData = (
type InjectJavascriptData = (
a: string,
b: string,
c: string,
d: string
) => string;
export const injectJavascriptData: InjectJavascriptData = (
mapSwitch,
iconSetting,
stationMenu,
@ -193,7 +197,7 @@ export const injectJavascriptData = (
case "45D":
case "49D":
case "57D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s2700apr.png');
setStationIcon(element.querySelector("img"),'https://n8n.haruk.in/webhook/dosan-anpanman-pictures.png?trainNum='+);
break;
@ -779,7 +783,9 @@ const setStationMenuDialog = new MutationObserver( (mutations) => {
}
}
const data2 =[];
document.querySelectorAll('#disp > div > div > div > div > font > div').forEach(d=>data2.push(d))
document.querySelectorAll('#disp > div > div > div > div > font > div').forEach(d=>{
if(!!d.onclick) data2.push(d);
})
for(let d of data2 ){
if(!d.offclick){

62
menu.js
View File

@ -23,17 +23,19 @@ import { TitleBar } from "./components/Menu/TitleBar";
import { FixedContentBottom } from "./components/Menu/FixedContentBottom";
import { UsefulBox } from "./components/atom/UsefulBox";
import { getStationList, lineList } from "./lib/getStationList";
import { lineList } from "./lib/getStationList";
import useInterval from "./lib/useInterval";
import { HeaderConfig } from "./lib/HeaderConfig";
import { useFavoriteStation } from "./stateBox/useFavoriteStation";
import { SheetManager } from "react-native-actions-sheet";
import { useTrainDelayData } from "./stateBox/useTrainDelayData";
import { useNavigation } from "@react-navigation/native";
import { useStationList } from "./stateBox/useStationList";
export default function Menu({ getCurrentTrain }) {
const { navigate } = useNavigation();
const { favoriteStation } = useFavoriteStation();
const { originalStationList } = useStationList();
//位置情報
const [locationStatus, setLocationStatus] = useState(null);
@ -90,9 +92,6 @@ export default function Menu({ getCurrentTrain }) {
const [currentStation, setCurrentStation] = useState(undefined); //第三要素
const [originalStationList, setOriginalStationList] = useState([]); // 第一要素
useEffect(() => getStationList().then(setOriginalStationList), []);
const carouselRef = useRef();
const [selectedCurrentStation, setSelectedCurrentStation] = useState(0);
@ -138,6 +137,21 @@ export default function Menu({ getCurrentTrain }) {
setTrainDiagram(trainList);
});
}, []);
const oPSign = () => {
const payload = {
currentStation:
originalStationList &&
allStationData.length != 0 &&
allStationData[selectedCurrentStation],
navigate: navigate,
goTo: "menu",
useShow: () => SheetManager.show("StationDetailView", { payload }),
onExit: () => SheetManager.hide("StationDetailView"),
};
SheetManager.show("StationDetailView", { payload });
};
return (
<View
style={{
@ -160,9 +174,7 @@ export default function Menu({ getCurrentTrain }) {
enableMomentum
callbackOffsetMargin={1000}
activeAnimationOptions={0.3}
onSnapToItem={(d) => {
setSelectedCurrentStation(d);
}}
onSnapToItem={setSelectedCurrentStation}
renderItem={({ item }) => {
return (
<View
@ -171,29 +183,8 @@ export default function Menu({ getCurrentTrain }) {
>
<Sign
currentStation={item}
originalStationList={originalStationList}
isCurrentStation={item == currentStation}
oP={() => {
const payload = {
currentStation:
originalStationList &&
allStationData.length != 0 &&
allStationData[selectedCurrentStation],
originalStationList: originalStationList,
navigate: navigate,
goTo: "menu",
useShow: () =>
SheetManager.show("StationDetailView", {
payload,
}),
onExit: () => {
SheetManager.hide("StationDetailView");
},
};
SheetManager.show("StationDetailView", {
payload,
});
}}
oP={oPSign}
/>
</View>
);
@ -205,12 +196,11 @@ export default function Menu({ getCurrentTrain }) {
allStationData[selectedCurrentStation] && (
<LED_vision
station={
originalStationList && allStationData[selectedCurrentStation][0]
originalStationList && allStationData[selectedCurrentStation]
}
trainDiagram={trainDiagram}
getCurrentTrain={getCurrentTrain}
navigate={navigate}
originalStationList={originalStationList}
openStationACFromEachTrainInfo={() => {}}
/>
)}
@ -264,14 +254,8 @@ const TopMenuButton = () => {
};
const JRSTraInfoBox = () => {
const {
getTime,
setGetTime,
delayData,
setDelayData,
loadingDelayData,
setLoadingDelayData,
} = useTrainDelayData();
const { getTime, delayData, loadingDelayData, setLoadingDelayData } =
useTrainDelayData();
const styles = {
touch: {
backgroundColor: "#0099CC",

View File

@ -6,12 +6,15 @@ const initialState = {
const AllTrainDiagramContext = createContext(initialState);
export const useAllTrainDiagram = () => {
return useContext(AllTrainDiagramContext);
};
export const useAllTrainDiagram = () => useContext(AllTrainDiagramContext);
export const AllTrainDiagramProvider = ({ children }) => {
const [allTrainDiagram, setAllTrainDiagram] = useState();
const [keyList, setKeyList] = useState(); // 第二要素
useEffect(
() => allTrainDiagram && setKeyList(Object.keys(allTrainDiagram)),
[allTrainDiagram]
);
const customData = {};
useEffect(() => {
fetch(
@ -55,7 +58,7 @@ export const AllTrainDiagramProvider = ({ children }) => {
return (
<AllTrainDiagramContext.Provider
value={{ allTrainDiagram, setAllTrainDiagram }}
value={{ allTrainDiagram, setAllTrainDiagram,keyList }}
>
{children}
</AllTrainDiagramContext.Provider>

View File

@ -1,8 +1,11 @@
import React, { createContext, useContext, useState, useEffect } from "react";
import useInterval from "../lib/useInterval";
const initialState = {
areaInfo: "",
setAreainfo: () => {},
areaIconBadgeText: "",
areaStationID: [],
};
const AreaInfoContext = createContext(initialState);
@ -11,18 +14,383 @@ export const useAreaInfo = () => {
return useContext(AreaInfoContext);
};
const setoStationID = [
"Y00",
"Y01",
"Y02",
"Y03",
"Y04",
"Y05",
"Y06",
"Y07",
"Y08",
"Y09",
"Y10",
"Y11",
"Y12",
];
const yosan1StationID = [
"Y12",
"Y13",
"Y14",
"Y15",
"Y16",
"Y17",
"Y18",
"Y19",
"Y20",
"Y21",
"Y22",
"Y23",
"Y24",
"Y25",
"Y26",
"Y27",
"Y28",
"Y29",
"Y30",
"Y31",
"Y32",
"Y33",
"Y34",
"Y35",
"Y36",
"Y37",
"Y38",
"Y39",
"Y40",
"Y41",
"Y42",
"Y43",
"Y44",
"Y45",
"Y46",
"Y47",
"Y48",
"Y49",
"Y50",
"Y51",
"Y52",
"Y53",
"Y54",
"Y55",
];
const yosan2StationID = [
"U00",
"U01",
"U02",
"U02-1",
"U03",
"U04",
"U05",
"U06",
"U07",
"U08",
"U09",
"U10",
"U11",
"U12",
"U13",
"U14",
"U15",
"U16",
"U17",
"U18",
"U19",
"U20",
"U21",
"U22",
"U23",
"U24",
"U25",
"U26",
"U27",
"U28",
"S06",
"S07",
"S08",
"S09",
"S10",
"S11",
"S12",
"S13",
"S14",
"S15",
"S16",
"S17",
"S18",
];
const dosan1StationID = [
"D12",
"D13",
"D14",
"D15",
"D16",
"D17",
"D18",
"D19",
"D20",
"D21",
"D22",
"D23",
"D24",
"D25",
"D26",
"D27",
"D28",
"D29",
"D30",
"D31",
"D32",
"D33",
"D34",
"D35",
"D36",
"D37",
"D38",
"D39",
"D40",
"D41",
"D42",
"D43",
"D44",
"D45",
];
const dosan2StationID = [
"K00",
"K01",
"K02",
"K03",
"K04",
"K05",
"K06",
"K07",
"K08",
"K08-1",
"K09",
"K10",
"K11",
"K12",
"K13",
"K14",
"K15",
"K16",
"K17",
"K18",
"K19",
"K20",
"K21",
"K22",
"K23",
"K24",
"K25",
"K26",
];
const kotokuStationID = [
"T00",
"T01",
"T02",
"T03",
"T04",
"T05",
"T06",
"T07",
"T08",
"T09",
"T10",
"T11",
"T12",
"T13",
"T14",
"T15",
"T16",
"T17",
"T18",
"T19",
"T20",
"T21",
"T22",
"T23",
"T24",
"T25",
"T26",
"T27",
"T28",
];
const mugiStationID = [
"T00",
"M00",
"M01",
"M02",
"M03",
"M04",
"M05",
"M06",
"M07",
"M08",
"M09",
"M10",
"M11",
"M12",
"M13",
"M14",
"M15",
"M16",
"M17",
"M18",
"M19",
"M20",
"M21",
"M22",
"M23",
"M24",
"M25",
"M26",
"M27",
];
const tokushimaStationID = [
"T00",
"T01",
"B00",
"B01",
"B02",
"B03",
"B04",
"B05",
"B06",
"B07",
"B08",
"B09",
"B10",
"B11",
"B12",
"B13",
"B14",
"B15",
"B16",
"B17",
"B18",
"B19",
"B20",
"B21",
"B22",
"B23",
"B24",
"B25",
];
const narutoStationID = [
"T00",
"T01",
"T02",
"T03",
"T04",
"N04",
"N05",
"N06",
"N07",
"N08",
"N09",
"N10",
];
const yodoStationID = [
"K26",
"U28",
"U27",
"G27",
"G28",
"G29",
"G30",
"G31",
"G32",
"G33",
"G34",
"G35",
"G36",
"G37",
"G38",
"G39",
"G40",
"G41",
"G42",
"G43",
"G44",
"G45",
"G46",
"G47",
];
const areaStationPair = {
seto: { id: "Y", stationID: setoStationID },
yosan1: { id: "Y", stationID: yosan1StationID },
yosan2: { id: "U,S", stationID: yosan2StationID },
dosan1: { id: "D", stationID: dosan1StationID },
dosan2: { id: "K", stationID: dosan2StationID },
kotoku: { id: "T", stationID: kotokuStationID },
mugi: { id: "M", stationID: mugiStationID },
tokushima: { id: "B", stationID: tokushimaStationID },
naruto: { id: "N", stationID: narutoStationID },
yodo: { id: "G", stationID: yodoStationID },
};
export const AreaInfoProvider = ({ children }) => {
const [areaInfo, setAreaInfo] = useState("");
const getAreaData = () =>
const [areaIconBadgeText, setAreaIconBadgeText] = useState("");
const [areaStationID, setAreaStationID] = useState([]);
const [isInfo, setIsInfo] = useState(false);
const getAreaData = () => {
fetch(
"https://script.google.com/macros/s/AKfycbz80LcaEUrhnlEsLkJy0LG2IRO3DBVQhfNmN1d_0f_HvtsujNQpxM90SrV9yKWH_JG1Ww/exec"
)
.then((d) => d.text())
.then((d) => setAreaInfo(d));
fetch("https://n8n.haruk.in/webhook/jr-shikoku-trainfo-flag")
.then((d) => d.json())
.then((d) => {
if (!d.data) return;
const lineInfo = d.data.filter((e) => e.area != "genelic");
const genelicInfo = d.data.filter((e) => e.area == "genelic");
const text = lineInfo
.filter((e) => e.status)
.map((e) => {
return `${areaStationPair[e.area].id}`;
});
let stationIDList = [];
lineInfo
.filter((e) => e.status)
.forEach((e) => {
stationIDList = stationIDList.concat(
areaStationPair[e.area].stationID
);
});
const info = genelicInfo[0].status.includes("nodelay") ? true : false;
setIsInfo(info);
setAreaStationID(stationIDList);
setAreaIconBadgeText(
text.length == 0 ? (info ? "i" : "!") : text.join(",")
);
});
};
useEffect(getAreaData, []);
useInterval(getAreaData, 60000); //60秒毎に全在線列車取得
return (
<AreaInfoContext.Provider value={{ areaInfo, setAreaInfo }}>
<AreaInfoContext.Provider
value={{
areaInfo,
setAreaInfo,
areaIconBadgeText,
areaStationID,
isInfo,
setIsInfo,
}}
>
{children}
</AreaInfoContext.Provider>
);

View File

@ -6,9 +6,11 @@ import React, {
useLayoutEffect,
} from "react";
import { AS } from "../storageControl";
import { useStationList } from "./useStationList";
const initialState = {
favoriteStation: [],
setFavoriteStation: () => {},
lodAddMigration: () => {},
};
const FavoriteStationContext = createContext(initialState);
@ -19,6 +21,13 @@ export const useFavoriteStation = () => {
export const FavoriteStationProvider = ({ children }) => {
const [favoriteStation, setFavoriteStation] = useState([]);
const { getStationData } = useStationList();
const lodAddMigration = () => {
const migration = favoriteStation.map((d) => {
return getStationData(d[0].Station_JP);
});
setFavoriteStation(migration);
};
useEffect(() => {
AS.getItem("favoriteStation")
.then((d) => {
@ -29,7 +38,7 @@ export const FavoriteStationProvider = ({ children }) => {
}, []);
return (
<FavoriteStationContext.Provider
value={{ favoriteStation, setFavoriteStation }}
value={{ favoriteStation, setFavoriteStation, lodAddMigration }}
>
{children}
</FavoriteStationContext.Provider>

View File

@ -0,0 +1,53 @@
import React, {
createContext,
useContext,
useState,
useEffect,
FC,
} from "react";
import { getStationList } from "../lib/getStationList";
type initialStateType = {
originalStationList: any[];
setOriginalStationList: React.Dispatch<React.SetStateAction<any[]>>;
getStationData: (id: string) => void;
};
const initialState = {
originalStationList: [],
setOriginalStationList: () => {},
getStationData: () => {},
};
const StationListContext = createContext<initialStateType>(initialState);
type Props = {
children: React.ReactNode;
};
export const useStationList = () => {
return useContext(StationListContext);
};
export const StationListProvider: FC<Props> = ({ children }) => {
const [originalStationList, setOriginalStationList] = useState<any[]>([]);
useEffect(() => {
getStationList().then(setOriginalStationList);
}, []);
const getStationData: (name: string) => void = (name) => {
const returnArray = [];
Object.keys(originalStationList).forEach((key) => {
originalStationList[key].forEach((station) => {
if (station.Station_JP === name) {
if (!!station.jslodApi) returnArray.push(station);
}
});
});
return returnArray;
};
return (
<StationListContext.Provider
value={{ originalStationList, setOriginalStationList, getStationData }}
>
{children}
</StationListContext.Provider>
);
};

View File

@ -1,4 +1,10 @@
import React, { createContext, useContext, useState } from "react";
import React, { createContext, useContext, useState, useEffect } from "react";
import { AS, ASCore } from "../storageControl";
import { getStationList2 } from "../lib/getStationList2";
import { injectJavascriptData } from "../lib/webViewInjectjavascript";
const initialState = {
selectedLine: undefined,
setSelectedLine: () => {},
@ -6,6 +12,23 @@ const initialState = {
setMapsStationData: () => {},
injectJavaScript: "",
setInjectJavaScript: () => {},
iconSetting: undefined,
setIconSetting: () => {},
mapSwitch: undefined,
setMapSwitch: () => {},
stationMenu: undefined,
setStationMenu: () => {},
LoadError: false,
setLoadError: () => {},
trainInfo: {
trainNum: undefined,
limited: undefined,
trainData: undefined,
},
setTrainInfo: () => {},
trainMenu: "true",
setTrainMenu: () => {},
injectJavascript: "",
};
const TrainMenuContext = createContext(initialState);
@ -19,6 +42,52 @@ export const TrainMenuProvider = ({ children }) => {
const [mapsStationData, setMapsStationData] = useState(undefined);
const [injectJavaScript, setInjectJavaScript] = useState();
useEffect(() => getStationList2().then(setMapsStationData), []);
//画面表示関連
const [iconSetting, setIconSetting] = useState(undefined);
const [mapSwitch, setMapSwitch] = useState(undefined);
const [stationMenu, setStationMenu] = useState(undefined);
const [LoadError, setLoadError] = useState(false);
//列車情報表示関連
const [trainInfo, setTrainInfo] = useState({
trainNum: undefined,
limited: undefined,
trainData: undefined,
});
//駅情報画面用
const [trainMenu, setTrainMenu] = useState("true");
//地図表示テキスト
const injectJavascript = injectJavascriptData(
mapSwitch,
iconSetting,
stationMenu,
trainMenu
);
useEffect(() => {
//ニュース表示
AS.getItem("status")
.then((d) => {
if (d != news) navigate("news");
})
.catch(() => navigate("news"));
}, []);
useEffect(() => {
//列車アイコンスイッチ
ASCore({ k: "iconSwitch", s: setIconSetting, d: "true", u: true });
//地図スイッチ
ASCore({ k: "mapSwitch", s: setMapSwitch, d: "false", u: true });
//駅メニュースイッチ
ASCore({ k: "stationSwitch", s: setStationMenu, d: "true", u: true });
//列車メニュースイッチ
ASCore({ k: "trainSwitch", s: setTrainMenu, d: "true", u: true });
}, []);
return (
<TrainMenuContext.Provider
value={{
@ -28,6 +97,19 @@ export const TrainMenuProvider = ({ children }) => {
setMapsStationData,
injectJavaScript,
setInjectJavaScript,
iconSetting,
setIconSetting,
mapSwitch,
setMapSwitch,
stationMenu,
setStationMenu,
LoadError,
setLoadError,
trainInfo,
setTrainInfo,
trainMenu,
setTrainMenu,
injectJavascript,
}}
>
{children}

View File

@ -1,15 +0,0 @@
import storage from "./storageConfig.js";
export const AS = {
getItem: (key) => storage.load({ key }),
setItem: (key, data) =>
storage.save({
key, // Note: Do not use underscore("_") in key!
data,
// if expires not specified, the defaultExpires will be applied instead.
// if set to null, then it will never expire.
expires: null,
}),
removeItem: (key) => storage.remove({ key }),
};

25
storageControl.ts Normal file
View File

@ -0,0 +1,25 @@
import storage from "./storageConfig";
import * as Updates from "expo-updates";
export const AS = {
getItem: (key: string) => storage.load({ key }),
setItem: (key: string, data: any) =>
storage.save({
key, // Note: Do not use underscore("_") in key!
data,
// if expires not specified, the defaultExpires will be applied instead.
// if set to null, then it will never expire.
expires: null,
}),
removeItem: (key: string) => storage.remove({ key }),
};
type ASCoreProps = (s: { k: any; s: any; d: any; u: any }) => Promise<any>;
export const ASCore: ASCoreProps = ({ 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()));