Merge commit 'af30d1cbb0ffac53805f28107b3564535219e541' into develop
This commit is contained in:
commit
7395c7e8f4
2
App.js
2
App.js
@ -18,6 +18,7 @@ import { TrainMenuProvider } from "./stateBox/useTrainMenu";
|
|||||||
import { buildProvidersTree } from "./lib/providerTreeProvider";
|
import { buildProvidersTree } from "./lib/providerTreeProvider";
|
||||||
import { StationListProvider } from "./stateBox/useStationList";
|
import { StationListProvider } from "./stateBox/useStationList";
|
||||||
import { NotificationProvider } from "./stateBox/useNotifications";
|
import { NotificationProvider } from "./stateBox/useNotifications";
|
||||||
|
import { UserPositionProvider } from "./stateBox/useUserPosition";
|
||||||
|
|
||||||
LogBox.ignoreLogs([
|
LogBox.ignoreLogs([
|
||||||
"ViewPropTypes will be removed",
|
"ViewPropTypes will be removed",
|
||||||
@ -36,6 +37,7 @@ export default function App() {
|
|||||||
const ProviderTree = buildProvidersTree([
|
const ProviderTree = buildProvidersTree([
|
||||||
AllTrainDiagramProvider,
|
AllTrainDiagramProvider,
|
||||||
NotificationProvider,
|
NotificationProvider,
|
||||||
|
UserPositionProvider,
|
||||||
StationListProvider,
|
StationListProvider,
|
||||||
FavoriteStationProvider,
|
FavoriteStationProvider,
|
||||||
TrainDelayDataProvider,
|
TrainDelayDataProvider,
|
||||||
|
50
MenuPage.js
50
MenuPage.js
@ -1,5 +1,10 @@
|
|||||||
import React, { useEffect } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { createStackNavigator } from "@react-navigation/stack";
|
import { createStackNavigator } from "@react-navigation/stack";
|
||||||
|
import { useWindowDimensions, Platform } from "react-native";
|
||||||
|
import Constants from "expo-constants";
|
||||||
|
|
||||||
|
import { Dimensions, StatusBar } from "react-native";
|
||||||
|
|
||||||
import { SheetManager } from "react-native-actions-sheet";
|
import { SheetManager } from "react-native-actions-sheet";
|
||||||
import { AS } from "./storageControl";
|
import { AS } from "./storageControl";
|
||||||
import TrainBase from "./components/trainbaseview";
|
import TrainBase from "./components/trainbaseview";
|
||||||
@ -10,14 +15,15 @@ import Setting from "./components/Settings/settings";
|
|||||||
import { useFavoriteStation } from "./stateBox/useFavoriteStation";
|
import { useFavoriteStation } from "./stateBox/useFavoriteStation";
|
||||||
import { optionData } from "./lib/stackOption";
|
import { optionData } from "./lib/stackOption";
|
||||||
import AllTrainDiagramView from "./components/AllTrainDiagramView";
|
import AllTrainDiagramView from "./components/AllTrainDiagramView";
|
||||||
import { useCurrentTrain } from "./stateBox/useCurrentTrain";
|
|
||||||
import { useNavigation } from "@react-navigation/native";
|
import { useNavigation } from "@react-navigation/native";
|
||||||
import { news } from "./config/newsUpdate";
|
import { news } from "./config/newsUpdate";
|
||||||
|
import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs";
|
||||||
const Stack = createStackNavigator();
|
const Stack = createStackNavigator();
|
||||||
|
|
||||||
export function MenuPage() {
|
export function MenuPage() {
|
||||||
const { favoriteStation, setFavoriteStation } = useFavoriteStation();
|
const { favoriteStation, setFavoriteStation } = useFavoriteStation();
|
||||||
const { getCurrentTrain } = useCurrentTrain();
|
const { height, width } = useWindowDimensions();
|
||||||
|
const tabBarHeight = useBottomTabBarHeight();
|
||||||
const navigation = useNavigation();
|
const navigation = useNavigation();
|
||||||
const { addListener } = navigation;
|
const { addListener } = navigation;
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -42,8 +48,34 @@ export function MenuPage() {
|
|||||||
})
|
})
|
||||||
.catch((error) => console.error("Error fetching icon setting:", error));
|
.catch((error) => console.error("Error fetching icon setting:", error));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const scrollRef = useRef(null);
|
||||||
|
const [mapMode, setMapMode] = useState(false);
|
||||||
|
const [mapHeight, setMapHeight] = useState(0);
|
||||||
|
useEffect(() => {
|
||||||
|
const MapHeight =
|
||||||
|
height -
|
||||||
|
tabBarHeight +
|
||||||
|
(Platform.OS == "android" ? Constants.statusBarHeight : 0) -
|
||||||
|
100 -
|
||||||
|
((((width / 100) * 80) / 20) * 9 + 10 + 30);
|
||||||
|
setMapHeight(MapHeight);
|
||||||
|
}, [height, tabBarHeight, width]);
|
||||||
|
const [MapFullHeight, setMapFullHeight] = useState(0);
|
||||||
|
useEffect(() => {
|
||||||
|
const MapFullHeight =
|
||||||
|
height -
|
||||||
|
tabBarHeight +
|
||||||
|
(Platform.OS == "android" ? Constants.statusBarHeight : 0);
|
||||||
|
setMapFullHeight(MapFullHeight);
|
||||||
|
}, [height, tabBarHeight, width]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribe = addListener("tabPress", (e) => {
|
const unsubscribe = addListener("tabPress", (e) => {
|
||||||
|
scrollRef.current.scrollTo({
|
||||||
|
y: mapHeight - 80,
|
||||||
|
animated: true,
|
||||||
|
});
|
||||||
|
setMapMode(false);
|
||||||
AS.getItem("favoriteStation")
|
AS.getItem("favoriteStation")
|
||||||
.then((d) => {
|
.then((d) => {
|
||||||
const returnData = JSON.parse(d);
|
const returnData = JSON.parse(d);
|
||||||
@ -55,7 +87,7 @@ export function MenuPage() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return unsubscribe;
|
return unsubscribe;
|
||||||
}, [navigation]);
|
}, [navigation, mapHeight]);
|
||||||
return (
|
return (
|
||||||
<Stack.Navigator>
|
<Stack.Navigator>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
@ -65,7 +97,15 @@ export function MenuPage() {
|
|||||||
gestureEnabled: true,
|
gestureEnabled: true,
|
||||||
headerTransparent: true,
|
headerTransparent: true,
|
||||||
}}
|
}}
|
||||||
children={() => <Menu getCurrentTrain={getCurrentTrain} />}
|
children={() => (
|
||||||
|
<Menu
|
||||||
|
scrollRef={scrollRef}
|
||||||
|
mapHeight={mapHeight}
|
||||||
|
MapFullHeight={MapFullHeight}
|
||||||
|
mapMode={mapMode}
|
||||||
|
setMapMode={setMapMode}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<Stack.Screen name="news" options={optionData} component={News} />
|
<Stack.Screen name="news" options={optionData} component={News} />
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
|
@ -2,19 +2,14 @@ import React, { useState, useEffect } from "react";
|
|||||||
import {
|
import {
|
||||||
View,
|
View,
|
||||||
Linking,
|
Linking,
|
||||||
Text,
|
|
||||||
TouchableOpacity,
|
|
||||||
BackHandler,
|
BackHandler,
|
||||||
Platform,
|
Platform,
|
||||||
|
useWindowDimensions,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
import AutoHeightImage from "react-native-auto-height-image";
|
|
||||||
import { FontAwesome, Foundation, Ionicons } from "@expo/vector-icons";
|
|
||||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||||
import ActionSheet, { SheetManager } from "react-native-actions-sheet";
|
import ActionSheet, { SheetManager } from "react-native-actions-sheet";
|
||||||
import Sign from "../../components/駅名表/Sign";
|
import Sign from "../../components/駅名表/Sign";
|
||||||
|
|
||||||
import { TicketBox } from "../atom/TicketBox";
|
|
||||||
import { widthPercentageToDP as wp } from "react-native-responsive-screen";
|
|
||||||
import { getPDFViewURL } from "../../lib/getPdfViewURL";
|
import { getPDFViewURL } from "../../lib/getPdfViewURL";
|
||||||
import { useBusAndTrainData } from "../../stateBox/useBusAndTrainData";
|
import { useBusAndTrainData } from "../../stateBox/useBusAndTrainData";
|
||||||
import { AS } from "../../storageControl";
|
import { AS } from "../../storageControl";
|
||||||
@ -27,13 +22,14 @@ import { StationTimeTableButton } from "./StationDeteilView/StationTimeTableButt
|
|||||||
export const StationDeteilView = (props) => {
|
export const StationDeteilView = (props) => {
|
||||||
if (!props.payload) return <></>;
|
if (!props.payload) return <></>;
|
||||||
const { currentStation, navigate, onExit, goTo, useShow } = props.payload;
|
const { currentStation, navigate, onExit, goTo, useShow } = props.payload;
|
||||||
|
const { width } = useWindowDimensions();
|
||||||
const { busAndTrainData } = useBusAndTrainData();
|
const { busAndTrainData } = useBusAndTrainData();
|
||||||
const [trainBus, setTrainBus] = useState();
|
const [trainBus, setTrainBus] = useState();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!currentStation) return () => {};
|
if (!currentStation) return () => {};
|
||||||
const data = busAndTrainData.filter((d) =>
|
const data = busAndTrainData.filter(
|
||||||
d.name === currentStation[0].Station_JP
|
(d) => d.name === currentStation[0].Station_JP
|
||||||
);
|
);
|
||||||
if (data.length == 0) {
|
if (data.length == 0) {
|
||||||
setTrainBus();
|
setTrainBus();
|
||||||
@ -89,73 +85,74 @@ export const StationDeteilView = (props) => {
|
|||||||
</View>
|
</View>
|
||||||
<View>
|
<View>
|
||||||
{currentStation && (
|
{currentStation && (
|
||||||
<View style={{ margin: 10, marginHorizontal: wp("10%") }}>
|
<>
|
||||||
<Sign
|
<View style={{ margin: 10, marginHorizontal: width * 0.1 }}>
|
||||||
currentStation={currentStation}
|
<Sign
|
||||||
oP={() => {
|
stationID={currentStation[0].StationNumber}
|
||||||
usePDFView == "true"
|
oP={() => {
|
||||||
? Linking.openURL(currentStation[0].StationTimeTable)
|
usePDFView == "true"
|
||||||
: navigate("howto", {
|
? Linking.openURL(currentStation[0].StationTimeTable)
|
||||||
info,
|
: navigate("howto", {
|
||||||
|
info,
|
||||||
|
goTo,
|
||||||
|
useShow,
|
||||||
|
});
|
||||||
|
onExit();
|
||||||
|
}}
|
||||||
|
oLP={() =>
|
||||||
|
Linking.openURL(currentStation[0].StationTimeTable)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
{currentStation[0].JrHpUrl &&
|
||||||
|
currentStation[0].StationNumber != "M12" && (
|
||||||
|
<駅構内図 //児島例外/
|
||||||
|
navigate={navigate}
|
||||||
|
goTo={goTo}
|
||||||
|
useShow={useShow}
|
||||||
|
address={currentStation[0].JrHpUrl}
|
||||||
|
onExit={onExit}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<View style={{ flexDirection: "row" }}>
|
||||||
|
{!currentStation[0].JrHpUrl || (
|
||||||
|
<WebSiteButton
|
||||||
|
navigate={navigate}
|
||||||
|
info={currentStation[0].JrHpUrl}
|
||||||
|
goTo={goTo}
|
||||||
|
useShow={useShow}
|
||||||
|
onExit={onExit}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{!currentStation[0].StationTimeTable || (
|
||||||
|
<StationTimeTableButton
|
||||||
|
info={info}
|
||||||
|
address={currentStation[0].StationTimeTable}
|
||||||
|
usePDFView={usePDFView}
|
||||||
|
navigate={navigate}
|
||||||
|
onExit={onExit}
|
||||||
|
goTo={goTo}
|
||||||
|
useShow={useShow}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{!currentStation[0].StationMap || (
|
||||||
|
<StationMapButton stationMap={currentStation[0].StationMap} />
|
||||||
|
)}
|
||||||
|
{!trainBus || (
|
||||||
|
<TrainBusButton
|
||||||
|
address={trainBus.address}
|
||||||
|
press={() => {
|
||||||
|
navigate("howto", {
|
||||||
|
info: trainBus.address,
|
||||||
goTo,
|
goTo,
|
||||||
useShow,
|
useShow,
|
||||||
});
|
});
|
||||||
onExit();
|
onExit();
|
||||||
}}
|
}}
|
||||||
oLP={() => Linking.openURL(currentStation[0].StationTimeTable)}
|
/>
|
||||||
/>
|
)}
|
||||||
</View>
|
</View>
|
||||||
)}
|
</>
|
||||||
{currentStation &&
|
|
||||||
currentStation[0].JrHpUrl &&
|
|
||||||
currentStation[0].StationNumber != "M12" && (
|
|
||||||
<駅構内図 //児島例外/
|
|
||||||
navigate={navigate}
|
|
||||||
goTo={goTo}
|
|
||||||
useShow={useShow}
|
|
||||||
address={currentStation[0].JrHpUrl}
|
|
||||||
onExit={onExit}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{currentStation && (
|
|
||||||
<View style={{ flexDirection: "row" }}>
|
|
||||||
{!currentStation[0].JrHpUrl || (
|
|
||||||
<WebSiteButton
|
|
||||||
navigate={navigate}
|
|
||||||
info={currentStation[0].JrHpUrl}
|
|
||||||
goTo={goTo}
|
|
||||||
useShow={useShow}
|
|
||||||
onExit={onExit}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{!currentStation[0].StationTimeTable || (
|
|
||||||
<StationTimeTableButton
|
|
||||||
info={info}
|
|
||||||
address={currentStation[0].StationTimeTable}
|
|
||||||
usePDFView={usePDFView}
|
|
||||||
navigate={navigate}
|
|
||||||
onExit={onExit}
|
|
||||||
goTo={goTo}
|
|
||||||
useShow={useShow}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{!currentStation[0].StationMap || (
|
|
||||||
<StationMapButton stationMap={currentStation[0].StationMap} />
|
|
||||||
)}
|
|
||||||
{!trainBus || (
|
|
||||||
<TrainBusButton
|
|
||||||
address={trainBus.address}
|
|
||||||
press={() => {
|
|
||||||
navigate("howto", {
|
|
||||||
info: trainBus.address,
|
|
||||||
goTo,
|
|
||||||
useShow,
|
|
||||||
});
|
|
||||||
onExit();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
129
components/Menu/Carousel/CarouselBox.tsx
Normal file
129
components/Menu/Carousel/CarouselBox.tsx
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
import Sign from "@/components/駅名表/Sign";
|
||||||
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
|
import { AS } from "@/storageControl";
|
||||||
|
import { useWindowDimensions, View, LayoutAnimation } from "react-native";
|
||||||
|
import Carousel, { ICarouselInstance } from "react-native-reanimated-carousel";
|
||||||
|
import { SheetManager } from "react-native-actions-sheet";
|
||||||
|
import { StationNumber } from "../StationPagination";
|
||||||
|
import { SimpleDot } from "../SimpleDot";
|
||||||
|
export const CarouselBox = ({
|
||||||
|
originalStationList,
|
||||||
|
listUpStation,
|
||||||
|
nearPositionStation,
|
||||||
|
setListIndex,
|
||||||
|
listIndex,
|
||||||
|
navigate,
|
||||||
|
}) => {
|
||||||
|
const carouselRef = useRef<ICarouselInstance>(null);
|
||||||
|
const { height, width } = useWindowDimensions();
|
||||||
|
const [dotButton, setDotButton] = useState(false);
|
||||||
|
const oPSign = () => {
|
||||||
|
const payload = {
|
||||||
|
currentStation: listUpStation[listIndex],
|
||||||
|
navigate,
|
||||||
|
goTo: "menu",
|
||||||
|
//@ts-ignore
|
||||||
|
useShow: () => SheetManager.show("StationDetailView", { payload }),
|
||||||
|
onExit: () => SheetManager.hide("StationDetailView"),
|
||||||
|
};
|
||||||
|
//@ts-ignore
|
||||||
|
SheetManager.show("StationDetailView", { payload });
|
||||||
|
};
|
||||||
|
const oLPSign = () => {
|
||||||
|
LayoutAnimation.configureNext({
|
||||||
|
duration: 600,
|
||||||
|
update: { type: "spring", springDamping: 0.5 },
|
||||||
|
});
|
||||||
|
AS.setItem(
|
||||||
|
"CarouselSettings/activeDotSettings",
|
||||||
|
!dotButton ? "true" : "false"
|
||||||
|
);
|
||||||
|
setDotButton(!dotButton);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
AS.getItem("CarouselSettings/activeDotSettings").then((data) => {
|
||||||
|
setDotButton(data === "true");
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
useEffect(() => {
|
||||||
|
if (!carouselRef.current) return;
|
||||||
|
carouselRef?.current.scrollTo({
|
||||||
|
count: listIndex - carouselRef.current.getCurrentIndex(),
|
||||||
|
animated: true,
|
||||||
|
});
|
||||||
|
}, [listIndex]);
|
||||||
|
const RenderItem = ({ item, index }) => {
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
backgroundColor: "#0000",
|
||||||
|
width,
|
||||||
|
flexDirection: "row",
|
||||||
|
marginLeft: 0,
|
||||||
|
marginRight: 0,
|
||||||
|
}}
|
||||||
|
key={item[0].StationNumber}
|
||||||
|
>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<Sign
|
||||||
|
stationID={item[0].StationNumber}
|
||||||
|
isCurrentStation={item == nearPositionStation}
|
||||||
|
oP={oPSign}
|
||||||
|
oLP={oLPSign}
|
||||||
|
/>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<View style={{ flex: 1, paddingTop: 10 }}>
|
||||||
|
<Carousel
|
||||||
|
ref={carouselRef}
|
||||||
|
data={listUpStation}
|
||||||
|
height={(((width / 100) * 80) / 20) * 9 + 10}
|
||||||
|
pagingEnabled={true}
|
||||||
|
snapEnabled={true}
|
||||||
|
loop={false}
|
||||||
|
width={width}
|
||||||
|
style={{ width: width, alignContent: "center" }}
|
||||||
|
mode="parallax"
|
||||||
|
modeConfig={{
|
||||||
|
parallaxScrollingScale: 1,
|
||||||
|
parallaxScrollingOffset: 100,
|
||||||
|
parallaxAdjacentItemScale: 0.8,
|
||||||
|
}}
|
||||||
|
onSnapToItem={setListIndex}
|
||||||
|
renderItem={RenderItem}
|
||||||
|
/>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{originalStationList &&
|
||||||
|
listUpStation.map((d, index) => {
|
||||||
|
const active = index == listIndex;
|
||||||
|
const numberKey = d[0].StationNumber + index;
|
||||||
|
return dotButton ? (
|
||||||
|
<StationNumber
|
||||||
|
onPress={() => setListIndex(index)}
|
||||||
|
currentStation={d}
|
||||||
|
active={active}
|
||||||
|
key={numberKey}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<SimpleDot
|
||||||
|
onPress={() => setListIndex(index)}
|
||||||
|
active={active}
|
||||||
|
key={numberKey}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
142
components/Menu/Carousel/CarouselTypeChanger.tsx
Normal file
142
components/Menu/Carousel/CarouselTypeChanger.tsx
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
import { AS } from "@/storageControl";
|
||||||
|
import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs";
|
||||||
|
import React, { useEffect, useRef } from "react";
|
||||||
|
import { View, TouchableOpacity, Text, LayoutAnimation } from "react-native";
|
||||||
|
import Ionicons from "react-native-vector-icons/Ionicons";
|
||||||
|
|
||||||
|
export const CarouselTypeChanger = ({
|
||||||
|
locationStatus,
|
||||||
|
position,
|
||||||
|
mapsRef,
|
||||||
|
stationListMode,
|
||||||
|
setStationListMode,
|
||||||
|
setSelectedCurrentStation,
|
||||||
|
mapMode,
|
||||||
|
setMapMode,
|
||||||
|
}) => {
|
||||||
|
const tabBarHeight = useBottomTabBarHeight();
|
||||||
|
const returnToDefaultMode = ()=>{
|
||||||
|
LayoutAnimation.configureNext({
|
||||||
|
duration: 300,
|
||||||
|
create: {
|
||||||
|
type: LayoutAnimation.Types.easeInEaseOut,
|
||||||
|
property: LayoutAnimation.Properties.opacity,
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
type: LayoutAnimation.Types.easeInEaseOut,
|
||||||
|
property: LayoutAnimation.Properties.opacity,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
setMapMode(false);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<View style={{ width: "100%", height: 40, flexDirection: "row", position: mapMode ? "absolute" : "relative", bottom: mapMode ? 0 : undefined}} key={"carouselTypeChanger"} >
|
||||||
|
<TouchableOpacity
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: stationListMode == "position" ? "#0099CC" : "#0099CC80",
|
||||||
|
padding: 5,
|
||||||
|
alignItems: "center",
|
||||||
|
flexDirection: "row",
|
||||||
|
marginHorizontal: 5,
|
||||||
|
borderTopLeftRadius: 20,
|
||||||
|
borderTopRightRadius: 20,
|
||||||
|
borderBottomLeftRadius: mapMode ? 0 : 20,
|
||||||
|
borderBottomRightRadius: mapMode ? 0 : 20,
|
||||||
|
}}
|
||||||
|
disabled={!locationStatus}
|
||||||
|
|
||||||
|
onPressIn={() =>{
|
||||||
|
if (!position) return;
|
||||||
|
returnToDefaultMode();
|
||||||
|
setStationListMode("position");
|
||||||
|
AS.setItem("stationListMode", "position");
|
||||||
|
setSelectedCurrentStation(0);
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
if (!position) return;
|
||||||
|
returnToDefaultMode();
|
||||||
|
setStationListMode("position");
|
||||||
|
AS.setItem("stationListMode", "position");
|
||||||
|
setSelectedCurrentStation(0);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Ionicons
|
||||||
|
name="locate-outline"
|
||||||
|
size={14}
|
||||||
|
color="white"
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
/>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
color: "white",
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: "bold",
|
||||||
|
flex: 1,
|
||||||
|
textAlign: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
現在地基準
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={{
|
||||||
|
padding: 5,
|
||||||
|
alignItems: "center",
|
||||||
|
flexDirection: "row",
|
||||||
|
marginHorizontal: 5,
|
||||||
|
borderRadius: 50,
|
||||||
|
}}
|
||||||
|
onPressIn={() => returnToDefaultMode()}
|
||||||
|
>
|
||||||
|
<Ionicons
|
||||||
|
name={!mapMode ? "menu" : "chevron-up-outline"}
|
||||||
|
size={30}
|
||||||
|
color="#0099CC"
|
||||||
|
style={{ marginHorizontal: 5 }}
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: stationListMode == "favorite" ? "#0099CC" : "#0099CC80",
|
||||||
|
padding: 5,
|
||||||
|
alignItems: "center",
|
||||||
|
flexDirection: "row",
|
||||||
|
marginHorizontal: 5,
|
||||||
|
borderTopLeftRadius: 20,
|
||||||
|
borderTopRightRadius: 20,
|
||||||
|
borderBottomLeftRadius: mapMode ? 0 : 20,
|
||||||
|
borderBottomRightRadius: mapMode ? 0 : 20,
|
||||||
|
}}
|
||||||
|
onPressIn={() => {
|
||||||
|
returnToDefaultMode();
|
||||||
|
// お気に入りリスト更新
|
||||||
|
setStationListMode("favorite");
|
||||||
|
AS.setItem("stationListMode", "favorite");
|
||||||
|
setSelectedCurrentStation(0);
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
returnToDefaultMode();
|
||||||
|
// お気に入りリスト更新
|
||||||
|
setStationListMode("favorite");
|
||||||
|
AS.setItem("stationListMode", "favorite");
|
||||||
|
setSelectedCurrentStation(0);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Ionicons name="star" size={14} color="white" style={{ margin: 5 }} />
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
color: "white",
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: "bold",
|
||||||
|
flex: 1,
|
||||||
|
textAlign: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
お気に入りリスト
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
111
components/Menu/JRSTraInfoBox.tsx
Normal file
111
components/Menu/JRSTraInfoBox.tsx
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
TouchableOpacity,
|
||||||
|
ScrollView,
|
||||||
|
StyleProp,
|
||||||
|
ViewStyle,
|
||||||
|
} from "react-native";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { SheetManager } from "react-native-actions-sheet";
|
||||||
|
import LottieView from "lottie-react-native";
|
||||||
|
import { useTrainDelayData } from "@/stateBox/useTrainDelayData";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
export const JRSTraInfoBox = () => {
|
||||||
|
const { getTime, delayData, loadingDelayData, setLoadingDelayData } =
|
||||||
|
useTrainDelayData();
|
||||||
|
const styles: { [key: string]: StyleProp<ViewStyle> } = {
|
||||||
|
touch: {
|
||||||
|
backgroundColor: "#0099CC",
|
||||||
|
borderRadius: 5,
|
||||||
|
margin: 10,
|
||||||
|
borderColor: "black",
|
||||||
|
borderWidth: 2,
|
||||||
|
overflow: "hidden",
|
||||||
|
},
|
||||||
|
scroll: {
|
||||||
|
backgroundColor: "#0099CC",
|
||||||
|
borderRadius: 5,
|
||||||
|
maxHeight: 300,
|
||||||
|
},
|
||||||
|
bottom: {
|
||||||
|
position: "absolute",
|
||||||
|
top: 250,
|
||||||
|
alignItems: "center",
|
||||||
|
width: "100%",
|
||||||
|
height: 50,
|
||||||
|
backgroundColor: "#007FCC88",
|
||||||
|
},
|
||||||
|
box: {
|
||||||
|
padding: 10,
|
||||||
|
backgroundColor: "white",
|
||||||
|
borderBottomLeftRadius: 5,
|
||||||
|
borderBottomRightRadius: 5,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => SheetManager.show("JRSTraInfo")}
|
||||||
|
style={styles.touch}
|
||||||
|
>
|
||||||
|
<ScrollView scrollEnabled={false} style={styles.scroll}>
|
||||||
|
<View
|
||||||
|
style={{ padding: 10, flexDirection: "row", alignItems: "center" }}
|
||||||
|
>
|
||||||
|
<Text style={{ fontSize: 30, fontWeight: "bold", color: "white" }}>
|
||||||
|
列車遅延速報EX
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<Text style={{ fontSize: 30, fontWeight: "bold", color: "white" }}>
|
||||||
|
{getTime ? dayjs(getTime).format("HH:mm") : NaN}
|
||||||
|
</Text>
|
||||||
|
<Ionicons
|
||||||
|
name="reload"
|
||||||
|
color="white"
|
||||||
|
size={30}
|
||||||
|
style={{ margin: 5 }}
|
||||||
|
onPress={() => setLoadingDelayData(true)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
<View style={styles.box}>
|
||||||
|
{loadingDelayData ? (
|
||||||
|
<View style={{ alignItems: "center" }}>
|
||||||
|
<LottieView
|
||||||
|
autoPlay
|
||||||
|
loop
|
||||||
|
style={{ width: 150, height: 150, backgroundColor: "#fff" }}
|
||||||
|
source={require("@/assets/51690-loading-diamonds.json")}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
) : delayData ? (
|
||||||
|
delayData.map((d, index, array) => {
|
||||||
|
let data = d.split(" ");
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{ flexDirection: "row" }}
|
||||||
|
key={data[1] + "key" + index}
|
||||||
|
>
|
||||||
|
<Text style={{ flex: 15, fontSize: 18 }}>
|
||||||
|
{data[0].replace("\n", "")}
|
||||||
|
</Text>
|
||||||
|
<Text style={{ flex: 5, fontSize: 18 }}>{data[1]}</Text>
|
||||||
|
<Text style={{ flex: 6, fontSize: 18 }}>{data[3]}</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
<Text>現在、5分以上の遅れはありません。</Text>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
<View style={styles.bottom}>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<Text style={{ color: "white", fontWeight: "bold", fontSize: 20 }}>
|
||||||
|
詳細を見る
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
};
|
@ -1,18 +1,25 @@
|
|||||||
import { View, TouchableOpacity, Linking } from "react-native";
|
import { View, TouchableOpacity, Linking,Platform, Image, useWindowDimensions } from "react-native";
|
||||||
import AutoHeightImage from "react-native-auto-height-image";
|
import Constants from "expo-constants";
|
||||||
import { widthPercentageToDP as wp } from "react-native-responsive-screen";
|
|
||||||
|
|
||||||
export const TitleBar = () => {
|
export const TitleBar = () => {
|
||||||
|
const { width } = useWindowDimensions();
|
||||||
return (
|
return (
|
||||||
<View style={{ alignItems: "center" }}>
|
<View
|
||||||
|
style={{
|
||||||
|
alignItems: "center",
|
||||||
|
position: "absolute",
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
zIndex: 100,
|
||||||
|
paddingTop: Platform.OS == "ios" ? Constants.statusBarHeight : 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={() => Linking.openURL("https://www.jr-shikoku.co.jp")}
|
onPress={() => Linking.openURL("https://www.jr-shikoku.co.jp")}
|
||||||
>
|
>
|
||||||
<AutoHeightImage
|
<Image source={require("../../assets/Header.png")} style={{ width: width, resizeMode: "contain", backgroundColor: "white", height: 80 }} />
|
||||||
source={require("../../assets/Header.png")}
|
|
||||||
resizeMode="contain"
|
|
||||||
width={wp("100%")}
|
|
||||||
/>
|
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
52
components/Menu/TopMenuButton.tsx
Normal file
52
components/Menu/TopMenuButton.tsx
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Linking, View } from "react-native";
|
||||||
|
import { UsefulBox } from "@/components/TrainMenu/UsefulBox";
|
||||||
|
import MaterialCommunityIcons from "@expo/vector-icons/build/MaterialCommunityIcons";
|
||||||
|
export const TopMenuButton = () => {
|
||||||
|
const buttonList:{
|
||||||
|
backgroundColor: string;
|
||||||
|
icon: keyof typeof MaterialCommunityIcons.glyphMap;
|
||||||
|
onPress: () => void;
|
||||||
|
title: string;
|
||||||
|
}[] = [
|
||||||
|
{
|
||||||
|
backgroundColor: "#F89038",
|
||||||
|
icon: "train-car",
|
||||||
|
onPress: () =>
|
||||||
|
Linking.openURL("https://www.jr-shikoku.co.jp/01_trainbus/sp/"),
|
||||||
|
title: "駅・鉄道情報",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
backgroundColor: "#EA4752",
|
||||||
|
icon: "google-spreadsheet",
|
||||||
|
onPress: () =>
|
||||||
|
Linking.openURL(
|
||||||
|
"https://www.jr-shikoku.co.jp/01_trainbus/jikoku/sp/#mainprice-box"
|
||||||
|
),
|
||||||
|
title: "運賃表",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
backgroundColor: "#91C31F",
|
||||||
|
icon: "clipboard-list-outline",
|
||||||
|
onPress: () => Linking.openURL("https://www.jr-shikoku.co.jp/e5489/"),
|
||||||
|
title: "予約",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{ flexDirection: "row" }}>
|
||||||
|
{buttonList.map((d, index) => (
|
||||||
|
<UsefulBox
|
||||||
|
backgroundColor={d.backgroundColor}
|
||||||
|
icon={d.icon}
|
||||||
|
flex={1}
|
||||||
|
onPressButton={d.onPress}
|
||||||
|
key={index + d.icon}
|
||||||
|
>
|
||||||
|
{d.title}
|
||||||
|
</UsefulBox>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
@ -1,22 +0,0 @@
|
|||||||
import { TouchableOpacity, Text } from "react-native";
|
|
||||||
import { MaterialCommunityIcons } from "@expo/vector-icons";
|
|
||||||
export 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>
|
|
||||||
);
|
|
||||||
};
|
|
@ -16,6 +16,8 @@ import { TrainPosition } from "./LED_inside_Component/TrainPosition";
|
|||||||
import { TrainPositionDataPush } from "./LED_inside_Component/TrainPositionDataPush";
|
import { TrainPositionDataPush } from "./LED_inside_Component/TrainPositionDataPush";
|
||||||
import { TrainPositionDataDelete } from "./LED_inside_Component/TrainPositionDataDelete";
|
import { TrainPositionDataDelete } from "./LED_inside_Component/TrainPositionDataDelete";
|
||||||
import { useStationList } from "../../stateBox/useStationList";
|
import { useStationList } from "../../stateBox/useStationList";
|
||||||
|
import useInterval from "@/lib/useInterval";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
d: {
|
d: {
|
||||||
@ -117,26 +119,46 @@ export const EachData: FC<Props> = (props) => {
|
|||||||
const [descInput, setDescInput] = useState("");
|
const [descInput, setDescInput] = useState("");
|
||||||
const [stationInput, setStationInput] = useState("");
|
const [stationInput, setStationInput] = useState("");
|
||||||
const [stationNumberInput, setStationNumberInput] = useState("");
|
const [stationNumberInput, setStationNumberInput] = useState("");
|
||||||
|
|
||||||
|
const [isShow, setIsShow] = useState(true);
|
||||||
|
const [isDepartureNow, setIsDepartureNow] = useState(false);
|
||||||
|
useEffect(()=>{
|
||||||
|
const currentTime = dayjs();
|
||||||
|
const trainTime = currentTime.set("hour", parseInt(d.time.split(":")[0])).set("minute", parseInt(d.time.split(":")[1]));
|
||||||
|
const diff = trainTime.diff(currentTime, "minute");
|
||||||
|
if (diff < 2) setIsDepartureNow(true);
|
||||||
|
else setIsDepartureNow(false);
|
||||||
|
return()=>{
|
||||||
|
setIsDepartureNow(false);
|
||||||
|
setIsShow(true);
|
||||||
|
}
|
||||||
|
}, [d.time,currentTrainData]);
|
||||||
|
useInterval(()=>{
|
||||||
|
if (isDepartureNow) {
|
||||||
|
setIsShow(!isShow);
|
||||||
|
|
||||||
|
}
|
||||||
|
}, 800);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TrainPositionDataDelete
|
<TrainPositionDataDelete
|
||||||
dialog={deleteDialog}
|
dialog={deleteDialog}
|
||||||
setDialog={setDeleteDialog}
|
setDialog={setDeleteDialog}
|
||||||
currentTrainData={currentTrainData}
|
{...{ currentTrainData, stationInput, stationNumberInput }}
|
||||||
stationInput={stationInput}
|
|
||||||
stationNumberInput={stationNumberInput}
|
|
||||||
/>
|
/>
|
||||||
<TrainPositionDataPush
|
<TrainPositionDataPush
|
||||||
dialog={dialog}
|
dialog={dialog}
|
||||||
setDialog={setDialog}
|
setDialog={setDialog}
|
||||||
currentTrainData={currentTrainData}
|
{...{
|
||||||
stationInput={stationInput}
|
currentTrainData,
|
||||||
stationNumberInput={stationNumberInput}
|
stationInput,
|
||||||
posInput={posInput}
|
stationNumberInput,
|
||||||
descInput={descInput}
|
posInput,
|
||||||
setPosInput={setPosInput}
|
descInput,
|
||||||
setDescInput={setDescInput}
|
setPosInput,
|
||||||
station={station}
|
setDescInput,
|
||||||
|
station,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={{
|
style={{
|
||||||
@ -147,8 +169,10 @@ export const EachData: FC<Props> = (props) => {
|
|||||||
marginHorizontal: "3%",
|
marginHorizontal: "3%",
|
||||||
backgroundColor: "#000",
|
backgroundColor: "#000",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
|
opacity: isShow ? 1 : 0.5,
|
||||||
}}
|
}}
|
||||||
onPress={() => openTrainInfo(d)}
|
onPress={() => openTrainInfo(d)}
|
||||||
|
key={ d.train + "-eachData" }
|
||||||
>
|
>
|
||||||
<TrainName
|
<TrainName
|
||||||
trainName={train.trainName}
|
trainName={train.trainName}
|
||||||
@ -161,6 +185,9 @@ export const EachData: FC<Props> = (props) => {
|
|||||||
<DependTime time={d.time} />
|
<DependTime time={d.time} />
|
||||||
<StatusAndDelay trainDelayStatus={trainDelayStatus} />
|
<StatusAndDelay trainDelayStatus={trainDelayStatus} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
{!!isDepartureNow && (
|
||||||
|
<Description info={d.lastStation == "当駅止" ? "この列車は当駅止です。間もなく到着します。":"列車の出発時刻です。"} key={d.train + "-description"} />
|
||||||
|
)}
|
||||||
{trainDescriptionSwitch && (
|
{trainDescriptionSwitch && (
|
||||||
<TrainPosition
|
<TrainPosition
|
||||||
trainIDSwitch={trainIDSwitch}
|
trainIDSwitch={trainIDSwitch}
|
||||||
@ -179,7 +206,7 @@ export const EachData: FC<Props> = (props) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{trainDescriptionSwitch && !!train.info && (
|
{trainDescriptionSwitch && !!train.info && (
|
||||||
<Description info={train.info} />
|
<Description info={train.info} key={d.train + "-description"} />
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -3,8 +3,8 @@ import { useCurrentTrain } from "../../../stateBox/useCurrentTrain";
|
|||||||
import LottieView from "lottie-react-native";
|
import LottieView from "lottie-react-native";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
|
||||||
export const Header = ({ getCurrentTrain }) => {
|
export const Header = () => {
|
||||||
const { currentTrainLoading, setCurrentTrainLoading } = useCurrentTrain();
|
const { currentTrainLoading, setCurrentTrainLoading,getCurrentTrain } = useCurrentTrain();
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { View } from "react-native";
|
import { View, useWindowDimensions } from "react-native";
|
||||||
import { widthPercentageToDP as wp } from "react-native-responsive-screen";
|
import dayjs from "dayjs";
|
||||||
import { useInterval } from "../../lib/useInterval";
|
import { useInterval } from "../../lib/useInterval";
|
||||||
import { objectIsEmpty } from "../../lib/objectIsEmpty";
|
import { objectIsEmpty } from "../../lib/objectIsEmpty";
|
||||||
import { useCurrentTrain } from "../../stateBox/useCurrentTrain";
|
import { useCurrentTrain } from "../../stateBox/useCurrentTrain";
|
||||||
@ -10,8 +10,8 @@ import { Footer } from "./LED_Vision_Component/Footer";
|
|||||||
import { Header } from "./LED_Vision_Component/Header";
|
import { Header } from "./LED_Vision_Component/Header";
|
||||||
import { Description } from "./LED_inside_Component/Description";
|
import { Description } from "./LED_inside_Component/Description";
|
||||||
import { EachData } from "./EachData";
|
import { EachData } from "./EachData";
|
||||||
|
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
|
||||||
|
import { trainPosition } from "@/lib/trainPositionTextArray";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -43,13 +43,7 @@ import { EachData } from "./EachData";
|
|||||||
* 9062D 四国まんなか千年ものがたり(臨時?)
|
* 9062D 四国まんなか千年ものがたり(臨時?)
|
||||||
*/
|
*/
|
||||||
export default function LED_vision(props) {
|
export default function LED_vision(props) {
|
||||||
const {
|
const { station, navigate, openStationACFromEachTrainInfo } = props;
|
||||||
station,
|
|
||||||
trainDiagram,
|
|
||||||
getCurrentTrain,
|
|
||||||
navigate,
|
|
||||||
openStationACFromEachTrainInfo,
|
|
||||||
} = props;
|
|
||||||
const { currentTrain } = useCurrentTrain();
|
const { currentTrain } = useCurrentTrain();
|
||||||
const [stationDiagram, setStationDiagram] = useState({}); //当該駅の全時刻表
|
const [stationDiagram, setStationDiagram] = useState({}); //当該駅の全時刻表
|
||||||
const [finalSwitch, setFinalSwitch] = useState(false);
|
const [finalSwitch, setFinalSwitch] = useState(false);
|
||||||
@ -57,36 +51,40 @@ export default function LED_vision(props) {
|
|||||||
const [trainDescriptionSwitch, setTrainDescriptionSwitch] = useState(false);
|
const [trainDescriptionSwitch, setTrainDescriptionSwitch] = useState(false);
|
||||||
const [isInfoArea, setIsInfoArea] = useState(false);
|
const [isInfoArea, setIsInfoArea] = useState(false);
|
||||||
const { areaInfo, areaStationID } = useAreaInfo();
|
const { areaInfo, areaStationID } = useAreaInfo();
|
||||||
|
const { allTrainDiagram } = useAllTrainDiagram();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
AS.getItem("LEDSettings/trainIDSwitch").then((data) => {
|
AS.getItem("LEDSettings/trainIDSwitch").then((data) => {
|
||||||
setTrainIDSwitch(data === "true");
|
setTrainIDSwitch(data === "true");
|
||||||
});
|
});
|
||||||
AS.getItem("LEDSettings/trainDescriptionSwitch").then((data) => {
|
AS.getItem("LEDSettings/trainDescriptionSwitch").then((data) => {
|
||||||
setTrainDescriptionSwitch(data == "true");
|
setTrainDescriptionSwitch(data === "true");
|
||||||
});
|
});
|
||||||
AS.getItem("LEDSettings/finalSwitch").then((data) => {
|
AS.getItem("LEDSettings/finalSwitch").then((data) => {
|
||||||
setFinalSwitch(data == "true");
|
setFinalSwitch(data === "true");
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 現在の駅に停車するダイヤを作成する副作用[列車ダイヤと現在駅情報]
|
// 現在の駅に停車するダイヤを作成する副作用[列車ダイヤと現在駅情報]
|
||||||
if (!trainDiagram) {
|
if (!allTrainDiagram) {
|
||||||
setStationDiagram({});
|
setStationDiagram({});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let returnData = {};
|
let returnData = {};
|
||||||
Object.keys(trainDiagram).forEach((key) => {
|
Object.keys(allTrainDiagram).forEach((key) => {
|
||||||
if (trainDiagram[key].match(station[0].Station_JP + ",")) {
|
if (allTrainDiagram[key].match(station[0].Station_JP + ",")) {
|
||||||
returnData[key] = trainDiagram[key];
|
returnData[key] = allTrainDiagram[key];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
setStationDiagram(returnData);
|
setStationDiagram(returnData);
|
||||||
setIsInfoArea(station.some((s) => areaStationID.includes(s.StationNumber)));
|
setIsInfoArea(station.some((s) => areaStationID.includes(s.StationNumber)));
|
||||||
}, [trainDiagram, station]);
|
}, [allTrainDiagram, station]);
|
||||||
|
|
||||||
const [trainTimeAndNumber, setTrainTimeAndNumber] = useState(null);
|
/*
|
||||||
|
{lastStation: "当駅止", time: "12:34", train: "1234M"}
|
||||||
|
*/
|
||||||
|
const [trainTimeAndNumber, setTrainTimeAndNumber] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
//現在の駅に停車する列車から時刻を切り出してLEDベースにフォーマット
|
//現在の駅に停車する列車から時刻を切り出してLEDベースにフォーマット
|
||||||
@ -100,34 +98,36 @@ export default function LED_vision(props) {
|
|||||||
if (!trainTimeAndNumber) return () => {};
|
if (!trainTimeAndNumber) return () => {};
|
||||||
if (!currentTrain) return () => {};
|
if (!currentTrain) return () => {};
|
||||||
const data = trainTimeAndNumber
|
const data = trainTimeAndNumber
|
||||||
.filter((d) => currentTrain.map((m) => m.num).includes(d.train))
|
.filter((d) => currentTrain.map((m) => m.num).includes(d.train)) //現在の列車に絞る[ToDo]
|
||||||
.filter(timeFiltering)
|
.filter(timeFiltering)
|
||||||
.filter((d) => !!finalSwitch || d.lastStation != "当駅止");
|
.filter((d) => !!finalSwitch || d.lastStation != "当駅止");
|
||||||
setSelectedTrain(data);
|
setSelectedTrain(data);
|
||||||
}, [trainTimeAndNumber, currentTrain, finalSwitch]);
|
}, [trainTimeAndNumber, currentTrain, finalSwitch]);
|
||||||
|
|
||||||
const getTime = (stationDiagram, station) => {
|
const getTime = (stationDiagram, station) => {
|
||||||
const returnData = Object.keys(stationDiagram).map((trainNum) => {
|
const returnData = Object.keys(stationDiagram)
|
||||||
let trainData = {};
|
.map((trainNum) => {
|
||||||
stationDiagram[trainNum].split("#").forEach((data) => {
|
let trainData = {};
|
||||||
if (data.match("着")) {
|
stationDiagram[trainNum].split("#").forEach((data) => {
|
||||||
trainData.lastStation = data.split(",着,")[0];
|
if (data.match("着")) {
|
||||||
}
|
trainData.lastStation = data.split(",着,")[0];
|
||||||
if (data.split(",")[0] === station.Station_JP) {
|
|
||||||
if (data.match(",発,")) {
|
|
||||||
trainData.time = data.split(",発,")[1];
|
|
||||||
} else if(data.match(",着,")){
|
|
||||||
trainData.time = data.split(",着,")[1];
|
|
||||||
trainData.lastStation = "当駅止";
|
|
||||||
}
|
}
|
||||||
}
|
if (data.split(",")[0] === station.Station_JP) {
|
||||||
});
|
if (data.match(",発,")) {
|
||||||
return {
|
trainData.time = data.split(",発,")[1];
|
||||||
train: trainNum,
|
} else if (data.match(",着,")) {
|
||||||
time: trainData.time,
|
trainData.time = data.split(",着,")[1];
|
||||||
lastStation: trainData.lastStation,
|
trainData.lastStation = "当駅止";
|
||||||
};
|
}
|
||||||
}).filter((d) => d.time);
|
}
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
train: trainNum,
|
||||||
|
time: trainData.time,
|
||||||
|
lastStation: trainData.lastStation,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter((d) => d.time);
|
||||||
return returnData.sort((a, b) => {
|
return returnData.sort((a, b) => {
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case parseInt(a.time.split(":")[0]) < parseInt(b.time.split(":")[0]):
|
case parseInt(a.time.split(":")[0]) < parseInt(b.time.split(":")[0]):
|
||||||
@ -145,16 +145,40 @@ export default function LED_vision(props) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const timeFiltering = (d) => {
|
const timeFiltering = (d) => {
|
||||||
const date = new Date();
|
|
||||||
const newDate = new Date();
|
|
||||||
let data = d.time.split(":");
|
|
||||||
let delay = isNaN(currentTrain.filter((t) => t.num == d.train)[0].delay)
|
|
||||||
? 0
|
|
||||||
: currentTrain.filter((t) => t.num == d.train)[0].delay;
|
|
||||||
|
|
||||||
date.setHours(parseInt(data[0]));
|
const baseTime = 2;
|
||||||
date.setMinutes(parseInt(data[1]) + parseInt(delay));
|
|
||||||
return !(newDate > date);
|
if (currentTrain.filter((t) => t.num == d.train).length == 0) {
|
||||||
|
const date = dayjs();
|
||||||
|
const trainTime = date
|
||||||
|
.hour(parseInt(d.time.split(":")[0]))
|
||||||
|
.minute(parseInt(d.time.split(":")[1]));
|
||||||
|
|
||||||
|
if (date.isAfter(trainTime)) {
|
||||||
|
return false;
|
||||||
|
} else if (trainTime.diff(date) < baseTime * 60 * 60 * 1000) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
const Pos = trainPosition(
|
||||||
|
currentTrain.filter((t) => t.num == d.train)[0]
|
||||||
|
);
|
||||||
|
const nextPos = Pos.isBetween ? Pos.Pos.to : Pos.Pos.Pos;
|
||||||
|
const PrePos = Pos.isBetween ? Pos.Pos.from : "";
|
||||||
|
if (station[0].Station_JP == nextPos) {
|
||||||
|
if(d.lastStation != "当駅止") return true;
|
||||||
|
} else if (station[0].Station_JP == PrePos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const date = dayjs();
|
||||||
|
let [h, m] = d.time.split(":");
|
||||||
|
let delay = isNaN(currentTrain.filter((t) => t.num == d.train)[0].delay)
|
||||||
|
? 0
|
||||||
|
: currentTrain.filter((t) => t.num == d.train)[0].delay;
|
||||||
|
const db = date.hour(parseInt(h)).minute(parseInt(m) + parseInt(delay));
|
||||||
|
return !date.isAfter(db);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const [areaString, setAreaString] = useState("");
|
const [areaString, setAreaString] = useState("");
|
||||||
@ -186,18 +210,19 @@ export default function LED_vision(props) {
|
|||||||
}
|
}
|
||||||
setAreaStringLength(areaInfo.length);
|
setAreaStringLength(areaInfo.length);
|
||||||
}, [areaInfo]);
|
}, [areaInfo]);
|
||||||
|
const { width } = useWindowDimensions();
|
||||||
|
const adjustedWidth = width * 0.98;
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
width: wp("98%"),
|
width: adjustedWidth,
|
||||||
/* height: wp("98%")/10*9, */ backgroundColor: "#432",
|
/* height: wp("98%")/10*9, */ backgroundColor: "#432",
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
margin: 10,
|
margin: 10,
|
||||||
marginHorizontal: wp("1%"),
|
marginHorizontal: width * 0.01,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Header getCurrentTrain={getCurrentTrain} />
|
<Header />
|
||||||
{selectedTrain.map((d) => (
|
{selectedTrain.map((d) => (
|
||||||
<EachData
|
<EachData
|
||||||
{...{
|
{...{
|
||||||
|
@ -1,9 +1,22 @@
|
|||||||
import React, { CSSProperties, FC } from "react";
|
import React, { CSSProperties, FC } from "react";
|
||||||
import { widthPercentageToDP as wp } from "react-native-responsive-screen";
|
import {
|
||||||
import { Platform, Text, TextStyle, View, ViewStyle } from "react-native";
|
Platform,
|
||||||
|
Text,
|
||||||
|
TextStyle,
|
||||||
|
useWindowDimensions,
|
||||||
|
View,
|
||||||
|
ViewStyle,
|
||||||
|
} from "react-native";
|
||||||
import { StationName } from "./StationName";
|
import { StationName } from "./StationName";
|
||||||
import lineColorList from "../../assets/originData/lineColorList";
|
import lineColorList from "../../assets/originData/lineColorList";
|
||||||
export const NextPreStationLine = ({ nexStation, preStation, isMatsuyama }) => {
|
export const NextPreStationLine = ({ nexStation, preStation, isMatsuyama }) => {
|
||||||
|
const 下枠フレーム: ViewStyle = {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: "row",
|
||||||
|
alignContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={下枠フレーム}>
|
<View style={下枠フレーム}>
|
||||||
<View style={下枠フレーム}>
|
<View style={下枠フレーム}>
|
||||||
@ -49,12 +62,40 @@ type FCimport = {
|
|||||||
children: string;
|
children: string;
|
||||||
};
|
};
|
||||||
const BottomSideArrow: FC<FCimport> = ({ isMatsuyama, children }) => {
|
const BottomSideArrow: FC<FCimport> = ({ isMatsuyama, children }) => {
|
||||||
|
const 下枠左右マーク: TextStyle = {
|
||||||
|
fontWeight: "bold",
|
||||||
|
fontSize: parseInt("20%"),
|
||||||
|
color: "white",
|
||||||
|
paddingHorizontal: 5,
|
||||||
|
textAlignVertical: "center",
|
||||||
|
};
|
||||||
return !isMatsuyama && <Text style={下枠左右マーク}>{children}</Text>;
|
return !isMatsuyama && <Text style={下枠左右マーク}>{children}</Text>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const BottomStationNumberView: FC<FCimport> = ({ isMatsuyama, children }) => {
|
const BottomStationNumberView: FC<FCimport> = ({ isMatsuyama, children }) => {
|
||||||
|
const { width } = useWindowDimensions();
|
||||||
const lineID = children.slice(0, 1);
|
const lineID = children.slice(0, 1);
|
||||||
const lineName = children.slice(1);
|
const lineName = children.slice(1);
|
||||||
|
const 下枠駅ナンバー: ViewStyle = {
|
||||||
|
alignContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
width: width * 0.08,
|
||||||
|
height: width * 0.08,
|
||||||
|
margin: width * 0.01,
|
||||||
|
backgroundColor: "white",
|
||||||
|
borderWidth: parseInt("3%"),
|
||||||
|
borderRadius: parseInt("100%"),
|
||||||
|
};
|
||||||
|
const 下枠駅ナンバーB: ViewStyle = {
|
||||||
|
alignContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
width: width * 0.07,
|
||||||
|
height: width * 0.07,
|
||||||
|
margin: width * 0.02,
|
||||||
|
backgroundColor: "white",
|
||||||
|
borderWidth: parseInt("3%"),
|
||||||
|
borderRadius: parseInt("100%"),
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
@ -77,37 +118,3 @@ const BottomStationNumberView: FC<FCimport> = ({ isMatsuyama, children }) => {
|
|||||||
</View>
|
</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%"),
|
|
||||||
};
|
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
import React, { useRef, useState, useEffect, useLayoutEffect } from "react";
|
import React, { useRef, useState, useEffect, useLayoutEffect } from "react";
|
||||||
import { View, Text, TouchableOpacity } from "react-native";
|
import {
|
||||||
import { widthPercentageToDP as wp } from "react-native-responsive-screen";
|
View,
|
||||||
|
Text,
|
||||||
|
TouchableOpacity,
|
||||||
|
useWindowDimensions,
|
||||||
|
} from "react-native";
|
||||||
import { MaterialCommunityIcons } from "@expo/vector-icons";
|
import { MaterialCommunityIcons } from "@expo/vector-icons";
|
||||||
import LottieView from "lottie-react-native";
|
import LottieView from "lottie-react-native";
|
||||||
import { useInterval } from "../../lib/useInterval";
|
import { useInterval } from "../../lib/useInterval";
|
||||||
@ -15,7 +19,14 @@ import { AddressText } from "./AddressText";
|
|||||||
import { useStationList } from "../../stateBox/useStationList";
|
import { useStationList } from "../../stateBox/useStationList";
|
||||||
|
|
||||||
export default function Sign(props) {
|
export default function Sign(props) {
|
||||||
const { currentStation, oP, oLP, isCurrentStation = false } = props;
|
const { oP, oLP, isCurrentStation = false, stationID } = props;
|
||||||
|
|
||||||
|
const { width, height } = useWindowDimensions();
|
||||||
|
const { getStationDataFromId } = useStationList();
|
||||||
|
if (!stationID) {
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
const [currentStationData] = useState(getStationDataFromId(stationID));
|
||||||
const { favoriteStation, setFavoriteStation } = useFavoriteStation();
|
const { favoriteStation, setFavoriteStation } = useFavoriteStation();
|
||||||
const [nexPrePosition, setNexPrePosition] = useState(0);
|
const [nexPrePosition, setNexPrePosition] = useState(0);
|
||||||
const { originalStationList } = useStationList();
|
const { originalStationList } = useStationList();
|
||||||
@ -26,48 +37,40 @@ export default function Sign(props) {
|
|||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
const isFavorite = favoriteStation.filter((d) => {
|
const isFavorite = favoriteStation.filter((d) => {
|
||||||
const compare = JSON.stringify(d);
|
const compare = JSON.stringify(d);
|
||||||
const current = JSON.stringify(currentStation);
|
const current = JSON.stringify(currentStationData);
|
||||||
if (compare === current) {
|
return compare === current;
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
setTestButtonStatus(isFavorite.length == 0 ? false : true);
|
setTestButtonStatus(isFavorite.length == 0 ? false : true);
|
||||||
}, [favoriteStation, currentStation]);
|
}, [favoriteStation, currentStationData]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const isFavorite = favoriteStation.filter((d) => {
|
const isFavorite = favoriteStation.filter((d) => {
|
||||||
const compare = JSON.stringify(d);
|
const compare = JSON.stringify(d);
|
||||||
const current = JSON.stringify(currentStation);
|
const current = JSON.stringify(currentStationData);
|
||||||
if (compare === current) {
|
return compare === current;
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
setTestButtonStatus(isFavorite.length == 0 ? false : true);
|
setTestButtonStatus(isFavorite.length == 0 ? false : true);
|
||||||
}, [favoriteStation, currentStation]);
|
}, [favoriteStation, currentStationData]);
|
||||||
|
|
||||||
useInterval(() => {
|
useInterval(() => {
|
||||||
if (currentStation.length == 1) {
|
if (currentStationData.length == 1) {
|
||||||
setNexPrePosition(0);
|
setNexPrePosition(0);
|
||||||
return () => {};
|
return () => {};
|
||||||
}
|
}
|
||||||
setNexPrePosition(
|
setNexPrePosition(
|
||||||
nexPrePosition + 1 == currentStation.length ? 0 : nexPrePosition + 1
|
nexPrePosition + 1 == currentStationData.length ? 0 : nexPrePosition + 1
|
||||||
);
|
);
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setNexPrePosition(0);
|
setNexPrePosition(0);
|
||||||
getPreNextStation(currentStation[0]);
|
getPreNextStation(currentStationData[0]);
|
||||||
if (currentStation.length == 1) return () => {};
|
if (currentStationData.length == 1) return () => {};
|
||||||
getPreNextStation(currentStation[1]);
|
getPreNextStation(currentStationData[1]);
|
||||||
}, [currentStation]);
|
}, [currentStationData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!currentStation[nexPrePosition]) return () => {};
|
if (!currentStationData[nexPrePosition]) return () => {};
|
||||||
getPreNextStation(currentStation[nexPrePosition]);
|
getPreNextStation(currentStationData[nexPrePosition]);
|
||||||
}, [nexPrePosition]);
|
}, [nexPrePosition]);
|
||||||
const getPreNextStation = (now) => {
|
const getPreNextStation = (now) => {
|
||||||
const lineList = [
|
const lineList = [
|
||||||
@ -101,25 +104,81 @@ export default function Sign(props) {
|
|||||||
if (returnData[1]) setNexStation(returnData[1]);
|
if (returnData[1]) setNexStation(returnData[1]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const isMatsuyama = currentStation[0].StationNumber == "Y55";
|
const isMatsuyama = currentStationData[0].StationNumber == "Y55";
|
||||||
//const isMatsuyama = true;
|
//const isMatsuyama = true;
|
||||||
const favoliteChanger = () => {
|
const favoliteChanger = () => {
|
||||||
if (testButtonStatus) {
|
if (testButtonStatus) {
|
||||||
const otherData = favoriteStation.filter((d) => {
|
const otherData = favoriteStation.filter((d) => {
|
||||||
const compare = JSON.stringify(d);
|
const compare = JSON.stringify(d);
|
||||||
const current = JSON.stringify(currentStation);
|
const current = JSON.stringify(currentStationData);
|
||||||
return compare !== current;
|
return compare !== current;
|
||||||
});
|
});
|
||||||
AS.setItem("favoriteStation", JSON.stringify(otherData));
|
AS.setItem("favoriteStation", JSON.stringify(otherData));
|
||||||
setFavoriteStation(otherData);
|
setFavoriteStation(otherData);
|
||||||
} else {
|
} else {
|
||||||
let ret = favoriteStation;
|
let ret = favoriteStation;
|
||||||
ret.push(currentStation);
|
ret.push(currentStationData);
|
||||||
AS.setItem("favoriteStation", JSON.stringify(ret));
|
AS.setItem("favoriteStation", JSON.stringify(ret));
|
||||||
setFavoriteStation(ret);
|
setFavoriteStation(ret);
|
||||||
}
|
}
|
||||||
setTestButtonStatus(!testButtonStatus);
|
setTestButtonStatus(!testButtonStatus);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const styleSheet = {
|
||||||
|
外枠: {
|
||||||
|
width: width * 0.8,
|
||||||
|
height: ((width * 0.8) / 20) * 9,
|
||||||
|
borderColor: "#0099CC",
|
||||||
|
borderWidth: 1,
|
||||||
|
backgroundColor: "white",
|
||||||
|
},
|
||||||
|
外枠B: {
|
||||||
|
width: width * 0.8,
|
||||||
|
height: ((width * 0.8) / 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: "26%",
|
||||||
|
backgroundColor: "#454545",
|
||||||
|
},
|
||||||
|
JRStyle: {
|
||||||
|
position: "absolute",
|
||||||
|
top: "2%",
|
||||||
|
left: "2%",
|
||||||
|
fontWeight: "bold",
|
||||||
|
fontSize: parseInt("25%"),
|
||||||
|
color: "#0099CC",
|
||||||
|
},
|
||||||
|
下帯内容: {
|
||||||
|
position: "absolute",
|
||||||
|
bottom: "8%",
|
||||||
|
height: "27%",
|
||||||
|
width: "100%",
|
||||||
|
alignItems: "center",
|
||||||
|
flexDirection: "column",
|
||||||
|
},
|
||||||
|
下帯内容B: {
|
||||||
|
position: "absolute",
|
||||||
|
bottom: "0%",
|
||||||
|
height: "26%",
|
||||||
|
width: "100%",
|
||||||
|
alignItems: "center",
|
||||||
|
flexDirection: "column",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={styleSheet[isMatsuyama ? "外枠B" : "外枠"]}
|
style={styleSheet[isMatsuyama ? "外枠B" : "外枠"]}
|
||||||
@ -131,15 +190,19 @@ export default function Sign(props) {
|
|||||||
autoPlay
|
autoPlay
|
||||||
loop
|
loop
|
||||||
style={{
|
style={{
|
||||||
width: wp("80%"),
|
width: width * 0.8,
|
||||||
height: (wp("80%") / 20) * 9,
|
height: ((width * 0.8) / 20) * 9,
|
||||||
backgroundColor: "#fff",
|
backgroundColor: "#fff",
|
||||||
}}
|
}}
|
||||||
source={require("../../assets/StationSign.json")}
|
source={require("../../assets/StationSign.json")}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<StationNumberMaker {...{ currentStation, isMatsuyama }} />
|
<StationNumberMaker
|
||||||
<StationNameArea {...{ currentStation, isMatsuyama }} />
|
{...{ currentStation: currentStationData, isMatsuyama }}
|
||||||
|
/>
|
||||||
|
<StationNameArea
|
||||||
|
{...{ currentStation: currentStationData, isMatsuyama }}
|
||||||
|
/>
|
||||||
{isCurrentStation ? (
|
{isCurrentStation ? (
|
||||||
<View style={{ position: "absolute", right: 0, top: 0 }}>
|
<View style={{ position: "absolute", right: 0, top: 0 }}>
|
||||||
<MaterialCommunityIcons
|
<MaterialCommunityIcons
|
||||||
@ -163,62 +226,7 @@ export default function Sign(props) {
|
|||||||
<View style={styleSheet[isMatsuyama ? "下帯内容B" : "下帯内容"]}>
|
<View style={styleSheet[isMatsuyama ? "下帯内容B" : "下帯内容"]}>
|
||||||
<NextPreStationLine {...{ nexStation, preStation, isMatsuyama }} />
|
<NextPreStationLine {...{ nexStation, preStation, isMatsuyama }} />
|
||||||
</View>
|
</View>
|
||||||
<AddressText {...{ currentStation, isMatsuyama }} />
|
<AddressText {...{ currentStation: currentStationData, isMatsuyama }} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const styleSheet = {
|
|
||||||
外枠: {
|
|
||||||
width: wp("80%"),
|
|
||||||
height: (wp("80%") / 20) * 9,
|
|
||||||
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: "26%",
|
|
||||||
backgroundColor: "#454545",
|
|
||||||
},
|
|
||||||
JRStyle: {
|
|
||||||
position: "absolute",
|
|
||||||
top: "2%",
|
|
||||||
left: "2%",
|
|
||||||
fontWeight: "bold",
|
|
||||||
fontSize: parseInt("25%"),
|
|
||||||
color: "#0099CC",
|
|
||||||
},
|
|
||||||
下帯内容: {
|
|
||||||
position: "absolute",
|
|
||||||
bottom: "8%",
|
|
||||||
height: "27%",
|
|
||||||
width: "100%",
|
|
||||||
alignItems: "center",
|
|
||||||
flexDirection: "column",
|
|
||||||
},
|
|
||||||
下帯内容B: {
|
|
||||||
position: "absolute",
|
|
||||||
bottom: "0%",
|
|
||||||
height: "26%",
|
|
||||||
width: "100%",
|
|
||||||
alignItems: "center",
|
|
||||||
flexDirection: "column",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Text, View } from "react-native";
|
import { Text, View } from "react-native";
|
||||||
import { widthPercentageToDP as wp } from "react-native-responsive-screen";
|
import { useWindowDimensions } from "react-native";
|
||||||
import lineColorList from "../../assets/originData/lineColorList";
|
import lineColorList from "../../assets/originData/lineColorList";
|
||||||
|
|
||||||
export const StationNumberMaker = (props) => {
|
export const StationNumberMaker = (props) => {
|
||||||
const { currentStation, isMatsuyama } = props;
|
const { currentStation, isMatsuyama } = props;
|
||||||
|
const { width } = useWindowDimensions();
|
||||||
const getTop = (array: number[], index: number) => {
|
const getTop = (array: number[], index: number) => {
|
||||||
if (array.length == 1) return 20;
|
if (array.length == 1) return 20;
|
||||||
else if (index == 0) return 5;
|
else if (index == 0) return 5;
|
||||||
@ -24,8 +25,8 @@ export const StationNumberMaker = (props) => {
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
top: `${getTop(array, index)}%`,
|
top: `${getTop(array, index)}%`,
|
||||||
right: "10%",
|
right: "10%",
|
||||||
width: wp("10%"),
|
width: (width / 100 * 10),
|
||||||
height: wp("10%"),
|
height: (width / 100 * 10),
|
||||||
borderColor: lineColorList[lineID],
|
borderColor: lineColorList[lineID],
|
||||||
backgroundColor: "white",
|
backgroundColor: "white",
|
||||||
borderWidth: parseInt("3%"),
|
borderWidth: parseInt("3%"),
|
||||||
|
614
menu.js
614
menu.js
@ -1,71 +1,101 @@
|
|||||||
import React, { useRef, useState, useEffect } from "react";
|
import React, { useRef, useState, useEffect } from "react";
|
||||||
import Carousel from "react-native-reanimated-carousel";
|
|
||||||
import {
|
import {
|
||||||
Platform,
|
Platform,
|
||||||
View,
|
View,
|
||||||
ScrollView,
|
ScrollView,
|
||||||
Linking,
|
useWindowDimensions,
|
||||||
Text,
|
|
||||||
TouchableOpacity,
|
|
||||||
LayoutAnimation,
|
LayoutAnimation,
|
||||||
Dimensions,
|
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
import Constants from "expo-constants";
|
import Constants from "expo-constants";
|
||||||
import * as Location from "expo-location";
|
import {
|
||||||
|
configureReanimatedLogger,
|
||||||
|
ReanimatedLogLevel,
|
||||||
|
} from "react-native-reanimated";
|
||||||
import StatusbarDetect from "./StatusbarDetect";
|
import StatusbarDetect from "./StatusbarDetect";
|
||||||
import { widthPercentageToDP as wp } from "react-native-responsive-screen";
|
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
|
||||||
import LottieView from "lottie-react-native";
|
|
||||||
import { parseAllTrainDiagram } from "./lib/parseAllTrainDiagram";
|
|
||||||
|
|
||||||
import LED_vision from "./components/発車時刻表/LED_vidion";
|
import LED_vision from "./components/発車時刻表/LED_vidion";
|
||||||
import Sign from "./components/駅名表/Sign";
|
|
||||||
import { TitleBar } from "./components/Menu/TitleBar";
|
import { TitleBar } from "./components/Menu/TitleBar";
|
||||||
import { FixedContentBottom } from "./components/Menu/FixedContentBottom";
|
import { FixedContentBottom } from "./components/Menu/FixedContentBottom";
|
||||||
|
|
||||||
import { UsefulBox } from "./components/atom/UsefulBox";
|
|
||||||
import { 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 { useFavoriteStation } from "./stateBox/useFavoriteStation";
|
||||||
import { SheetManager } from "react-native-actions-sheet";
|
|
||||||
import { useTrainDelayData } from "./stateBox/useTrainDelayData";
|
|
||||||
import { useNavigation } from "@react-navigation/native";
|
import { useNavigation } from "@react-navigation/native";
|
||||||
import { useStationList } from "./stateBox/useStationList";
|
import { useStationList } from "./stateBox/useStationList";
|
||||||
import { StationNumber } from "./components/Menu/StationPagination";
|
import { TopMenuButton } from "@/components/Menu/TopMenuButton";
|
||||||
import lineColorList from "./assets/originData/lineColorList";
|
import { JRSTraInfoBox } from "@/components/Menu/JRSTraInfoBox";
|
||||||
|
import MapView, { Marker } from "react-native-maps";
|
||||||
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||||
|
import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs";
|
||||||
|
import { CarouselBox } from "./components/Menu/Carousel/CarouselBox";
|
||||||
|
import { CarouselTypeChanger } from "./components/Menu/Carousel/CarouselTypeChanger";
|
||||||
|
import { useUserPosition } from "./stateBox/useUserPosition";
|
||||||
import { AS } from "./storageControl";
|
import { AS } from "./storageControl";
|
||||||
import { SimpleDot } from "./components/Menu/SimpleDot";
|
configureReanimatedLogger({
|
||||||
import { useAllTrainDiagram } from "./stateBox/useAllTrainDiagram";
|
level: ReanimatedLogLevel.error, // Set the log level to error
|
||||||
|
strict: true, // Reanimated runs in strict mode by default
|
||||||
export default function Menu({ getCurrentTrain }) {
|
});
|
||||||
const { navigate } = useNavigation();
|
export default function Menu(props) {
|
||||||
|
const { scrollRef, mapHeight, MapFullHeight, mapMode, setMapMode } = props;
|
||||||
|
const { navigate, addListener, isFocused } = useNavigation();
|
||||||
const { favoriteStation } = useFavoriteStation();
|
const { favoriteStation } = useFavoriteStation();
|
||||||
const { originalStationList } = useStationList();
|
const { originalStationList } = useStationList();
|
||||||
|
const { height, width } = useWindowDimensions();
|
||||||
//位置情報
|
const { bottom, left, right, top } = useSafeAreaInsets();
|
||||||
const [locationStatus, setLocationStatus] = useState(null);
|
const tabBarHeight = useBottomTabBarHeight();
|
||||||
|
const [stationListMode, setStationListMode] = useState(
|
||||||
|
/*<"position"|"favorite">*/ "position"
|
||||||
|
);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Platform.OS == "web") return;
|
AS.getItem("stationListMode")
|
||||||
Location.requestForegroundPermissionsAsync().then((data) => {
|
.then((res) => setStationListMode(res))
|
||||||
setLocationStatus(
|
.catch((e) => {
|
||||||
Platform.OS == "ios"
|
// AS.setItem("stationListMode", "position");
|
||||||
? data.status == "granted"
|
});
|
||||||
: data.android.accuracy == "fine"
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}, []);
|
}, []);
|
||||||
|
const mapsRef = useRef(null);
|
||||||
const getCurrentPosition = () => {
|
const returnToTop = (bool = true) => {
|
||||||
if (!locationStatus) return () => {};
|
scrollRef.current.scrollTo({
|
||||||
Location.getCurrentPositionAsync({}).then((location) =>
|
y: mapHeight > 80 ? mapHeight - 80 : 0,
|
||||||
makeCurrentStation(location)
|
animated: bool,
|
||||||
);
|
});
|
||||||
};
|
};
|
||||||
|
const goToMap = () => {
|
||||||
|
scrollRef.current.scrollTo({
|
||||||
|
y: 0,
|
||||||
|
animated: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
returnToTop(false);
|
||||||
|
}, 10);
|
||||||
|
}, [mapHeight]);
|
||||||
|
const [scrollStartPosition, setScrollStartPosition] = useState(0);
|
||||||
|
const onScrollBeginDrag = (e) => {
|
||||||
|
LayoutAnimation.configureNext({
|
||||||
|
duration: 300,
|
||||||
|
create: {
|
||||||
|
type: LayoutAnimation.Types.easeInEaseOut,
|
||||||
|
property: LayoutAnimation.Properties.opacity,
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
type: LayoutAnimation.Types.easeInEaseOut,
|
||||||
|
property: LayoutAnimation.Properties.opacity,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
setScrollStartPosition(e.nativeEvent.contentOffset.y);
|
||||||
|
setMapMode(false);
|
||||||
|
};
|
||||||
|
//現在地基準の駅名標リストアップ機能
|
||||||
|
const { position, locationStatus } = useUserPosition();
|
||||||
|
useEffect(() => {
|
||||||
|
if (!position) return () => {};
|
||||||
|
makeCurrentStation(position);
|
||||||
|
}, [position, stationListMode]);
|
||||||
const makeCurrentStation = (location) => {
|
const makeCurrentStation = (location) => {
|
||||||
if (!originalStationList) return () => {};
|
if (!originalStationList) return () => {};
|
||||||
const findStationEachLine = (selectLine) => {
|
const findStationEachLine = (selectLine) => {
|
||||||
const searchArea = 0.002;
|
const searchArea = 0.055; //検索範囲
|
||||||
const _calcDistance = (from, to) => {
|
const _calcDistance = (from, to) => {
|
||||||
let lat = Math.abs(from.lat - to.lat);
|
let lat = Math.abs(from.lat - to.lat);
|
||||||
let lng = Math.abs(from.lng - to.lng);
|
let lng = Math.abs(from.lng - to.lng);
|
||||||
@ -78,94 +108,98 @@ export default function Menu({ getCurrentTrain }) {
|
|||||||
lng: location.coords.longitude,
|
lng: location.coords.longitude,
|
||||||
}) < searchArea
|
}) < searchArea
|
||||||
);
|
);
|
||||||
|
//NearStationを距離の近い順にソート
|
||||||
|
NearStation.sort((a, b) => {
|
||||||
|
return (
|
||||||
|
_calcDistance(a, {
|
||||||
|
lat: location.coords.latitude,
|
||||||
|
lng: location.coords.longitude,
|
||||||
|
}) -
|
||||||
|
_calcDistance(b, {
|
||||||
|
lat: location.coords.latitude,
|
||||||
|
lng: location.coords.longitude,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
return NearStation;
|
return NearStation;
|
||||||
};
|
};
|
||||||
|
|
||||||
let returnDataBase = lineList
|
let _stList = lineList
|
||||||
.map((d) => findStationEachLine(originalStationList[d]))
|
.map((d) => findStationEachLine(originalStationList[d]))
|
||||||
.filter((d) => d.length > 0)
|
.filter((d) => d.length > 0)
|
||||||
.reduce((pre, current) => {
|
.reduce((pre, current) => {
|
||||||
pre.push(...current);
|
pre.push(...current);
|
||||||
return pre;
|
return pre;
|
||||||
}, []);
|
}, []);
|
||||||
if (returnDataBase.length) {
|
if (_stList.length == 0) setNearPositionStation([]);
|
||||||
let currentStation = currentStation == undefined ? [] : currentStation;
|
else {
|
||||||
if (currentStation.toString() != returnDataBase.toString()) {
|
let returnData = [];
|
||||||
setCurrentStation(returnDataBase);
|
_stList.forEach((d, index, array) => {
|
||||||
}
|
const stationName = d.Station_JP;
|
||||||
} else {
|
if (returnData.findIndex((d) => d[0].Station_JP == stationName) != -1)
|
||||||
setCurrentStation(undefined);
|
return;
|
||||||
|
returnData.push(array.filter((d2) => d2.Station_JP == stationName));
|
||||||
|
});
|
||||||
|
//returnDataを距離の近い順にソート
|
||||||
|
returnData.sort((a, b) => {
|
||||||
|
const _calcDistance = (from, to) => {
|
||||||
|
let lat = Math.abs(from.lat - to.lat);
|
||||||
|
let lng = Math.abs(from.lng - to.lng);
|
||||||
|
return Math.sqrt(lat * lat + lng * lng);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
_calcDistance(a[0], {
|
||||||
|
lat: location.coords.latitude,
|
||||||
|
lng: location.coords.longitude,
|
||||||
|
}) -
|
||||||
|
_calcDistance(b[0], {
|
||||||
|
lat: location.coords.latitude,
|
||||||
|
lng: location.coords.longitude,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
setNearPositionStation(returnData);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(getCurrentPosition, [locationStatus]);
|
const [nearPositionStation, setNearPositionStation] = useState([]); //第三要素
|
||||||
useInterval(getCurrentPosition, 5000);
|
|
||||||
|
|
||||||
const [currentStation, setCurrentStation] = useState(undefined); //第三要素
|
const [listIndex, setListIndex] = useState(0);
|
||||||
|
|
||||||
const carouselRef = useRef();
|
const [listUpStation, setListUpStation] = useState([]);
|
||||||
const [selectedCurrentStation, setSelectedCurrentStation] = useState(0);
|
|
||||||
|
|
||||||
const [allStationData, setAllStationData] = useState([]);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setAllStationData(
|
if (stationListMode == "position") {
|
||||||
[currentStation, ...favoriteStation].filter((d) => d != undefined)
|
setListUpStation(nearPositionStation.filter((d) => d != undefined));
|
||||||
);
|
} else {
|
||||||
}, [currentStation, favoriteStation]);
|
setListUpStation(favoriteStation.filter((d) => d != undefined));
|
||||||
|
}
|
||||||
|
}, [nearPositionStation, favoriteStation, stationListMode]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (allStationData.length == 0) {
|
if (listUpStation.length == 0) {
|
||||||
setSelectedCurrentStation(0);
|
setListIndex(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (allStationData[selectedCurrentStation] == undefined) {
|
if (listUpStation[listIndex] == undefined) {
|
||||||
const count = selectedCurrentStation - 1;
|
const count = listIndex - 1;
|
||||||
setSelectedCurrentStation(count);
|
setMapMode(false);
|
||||||
|
setListIndex(count);
|
||||||
}
|
}
|
||||||
}, [selectedCurrentStation, currentStation, allStationData]);
|
}, [listIndex, nearPositionStation, listUpStation]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!carouselRef.current) return;
|
if (originalStationList == undefined) return;
|
||||||
carouselRef?.current.scrollTo({
|
if (listUpStation.length == 0) return;
|
||||||
count: selectedCurrentStation - carouselRef.current.getCurrentIndex(),
|
if (listUpStation[listIndex] == undefined) return;
|
||||||
animated: true,
|
const { lat, lng } = listUpStation[listIndex][0];
|
||||||
});
|
const mapRegion = {
|
||||||
}, [selectedCurrentStation]);
|
latitude: lat,
|
||||||
|
longitude: lng,
|
||||||
//全列車ダイヤリストを作成するuseEffect
|
latitudeDelta: 0.05,
|
||||||
const { allTrainDiagram:trainDiagram} = useAllTrainDiagram();
|
longitudeDelta: 0.05,
|
||||||
|
|
||||||
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 });
|
if (mapMode) return;
|
||||||
};
|
mapsRef.current.animateToRegion(mapRegion, 1000);
|
||||||
|
}, [listIndex, nearPositionStation, listUpStation, mapsRef]);
|
||||||
|
|
||||||
const [dotButton, setDotButton] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
AS.getItem("CarouselSettings/activeDotSettings").then((data) => {
|
|
||||||
setDotButton(data === "true");
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
const oLPSign = () => {
|
|
||||||
LayoutAnimation.configureNext({
|
|
||||||
duration: 600,
|
|
||||||
update: { type: "spring", springDamping: 0.5 },
|
|
||||||
});
|
|
||||||
AS.setItem(
|
|
||||||
"CarouselSettings/activeDotSettings",
|
|
||||||
!dotButton ? "true" : "false"
|
|
||||||
);
|
|
||||||
setDotButton(!dotButton);
|
|
||||||
};
|
|
||||||
const width = Dimensions.get("window").width;
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
@ -176,246 +210,148 @@ export default function Menu({ getCurrentTrain }) {
|
|||||||
>
|
>
|
||||||
<StatusbarDetect />
|
<StatusbarDetect />
|
||||||
<TitleBar />
|
<TitleBar />
|
||||||
<ScrollView>
|
<ScrollView
|
||||||
<TopMenuButton />
|
ref={scrollRef}
|
||||||
{originalStationList.length != 0 && allStationData.length != 0 && (
|
snapToStart={false}
|
||||||
<View style={{ flex: 1, paddingTop: 10 }}>
|
snapToEnd={false}
|
||||||
<Carousel
|
decelerationRate={"normal"}
|
||||||
ref={carouselRef}
|
snapToOffsets={[mapHeight - 80]}
|
||||||
data={originalStationList && allStationData}
|
onScrollBeginDrag={onScrollBeginDrag}
|
||||||
height={(wp("80%") / 20) * 9 + 10}
|
onScrollEndDrag={(e) => {
|
||||||
pagingEnabled={true}
|
console.log(e.nativeEvent.velocity);
|
||||||
snapEnabled={true}
|
if (e.nativeEvent.contentOffset.y < mapHeight - 80) {
|
||||||
loop={false}
|
if (scrollStartPosition > e.nativeEvent.contentOffset.y) {
|
||||||
width={width}
|
goToMap();
|
||||||
style={{ width: width, alignContent: "center" }}
|
} else {
|
||||||
mode="parallax"
|
returnToTop();
|
||||||
modeConfig={{
|
}
|
||||||
parallaxScrollingScale: 1,
|
}
|
||||||
parallaxScrollingOffset: 100,
|
}}
|
||||||
parallaxAdjacentItemScale: 0.8,
|
>
|
||||||
|
<MapView
|
||||||
|
ref={mapsRef}
|
||||||
|
style={{ width: "100%", height: mapMode ? MapFullHeight : mapHeight }}
|
||||||
|
showsUserLocation={true}
|
||||||
|
loadingEnabled={true}
|
||||||
|
showsMyLocationButton={false}
|
||||||
|
moveOnMarkerPress={false}
|
||||||
|
showsCompass={false}
|
||||||
|
//provider={PROVIDER_GOOGLE}
|
||||||
|
initialRegion={{
|
||||||
|
latitude: 33.774519,
|
||||||
|
longitude: 133.533306,
|
||||||
|
latitudeDelta: 1.8, //小さくなるほどズーム
|
||||||
|
longitudeDelta: 1.8,
|
||||||
|
}}
|
||||||
|
onTouchStart={() => {
|
||||||
|
LayoutAnimation.configureNext({
|
||||||
|
duration: 300,
|
||||||
|
create: {
|
||||||
|
type: LayoutAnimation.Types.easeInEaseOut,
|
||||||
|
property: LayoutAnimation.Properties.opacity,
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
type: LayoutAnimation.Types.easeInEaseOut,
|
||||||
|
property: LayoutAnimation.Properties.opacity,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
setMapMode(true);
|
||||||
|
goToMap();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{listUpStation.map(([{ lat, lng, StationNumber }], index) => (
|
||||||
|
<Marker
|
||||||
|
key={index + StationNumber}
|
||||||
|
coordinate={{
|
||||||
|
latitude: parseFloat(lat),
|
||||||
|
longitude: parseFloat(lng),
|
||||||
}}
|
}}
|
||||||
onSnapToItem={setSelectedCurrentStation}
|
image={require("@/assets/reccha-small.png")}
|
||||||
renderItem={({ item, index }) => {
|
onPress={() => {
|
||||||
return (
|
setMapMode(false);
|
||||||
<View
|
setListIndex(index);
|
||||||
style={{
|
if (mapsRef.current) {
|
||||||
backgroundColor: "#0000",
|
mapsRef.current.animateToRegion(
|
||||||
width: width,
|
{
|
||||||
flexDirection: "row",
|
latitude: parseFloat(lat),
|
||||||
marginLeft: 0,
|
longitude: parseFloat(lng),
|
||||||
marginRight: 0,
|
latitudeDelta: 0.05,
|
||||||
}}
|
longitudeDelta: 0.05,
|
||||||
key={item[0].StationNumber}
|
},
|
||||||
>
|
1000
|
||||||
<View style={{ flex: 1 }} />
|
);
|
||||||
<Sign
|
}
|
||||||
currentStation={item}
|
LayoutAnimation.configureNext({
|
||||||
isCurrentStation={item == currentStation}
|
duration: 300,
|
||||||
oP={oPSign}
|
create: {
|
||||||
oLP={oLPSign}
|
type: LayoutAnimation.Types.easeInEaseOut,
|
||||||
/>
|
property: LayoutAnimation.Properties.opacity,
|
||||||
<View style={{ flex: 1 }} />
|
},
|
||||||
</View>
|
update: {
|
||||||
);
|
type: LayoutAnimation.Types.easeInEaseOut,
|
||||||
|
property: LayoutAnimation.Properties.opacity,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
returnToTop();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<View
|
))}
|
||||||
style={{
|
</MapView>
|
||||||
flexDirection: "row",
|
{!mapMode && (
|
||||||
justifyContent: "center",
|
<CarouselTypeChanger
|
||||||
alignContent: "center",
|
{...{
|
||||||
alignItems: "center",
|
locationStatus,
|
||||||
}}
|
position,
|
||||||
>
|
mapsRef,
|
||||||
{originalStationList &&
|
stationListMode,
|
||||||
allStationData.map((d, index) => {
|
setStationListMode,
|
||||||
const active = index == selectedCurrentStation;
|
setSelectedCurrentStation: setListIndex,
|
||||||
const numberIndex = d[0].StationNumber;
|
mapMode,
|
||||||
if (dotButton) {
|
setMapMode,
|
||||||
return (
|
}}
|
||||||
<StationNumber
|
/>
|
||||||
onPress={() => setSelectedCurrentStation(index)}
|
|
||||||
currentStation={d}
|
|
||||||
active={active}
|
|
||||||
index={numberIndex}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<SimpleDot
|
|
||||||
onPress={() => setSelectedCurrentStation(index)}
|
|
||||||
active={active}
|
|
||||||
index={numberIndex}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
)}
|
)}
|
||||||
{allStationData.length != 0 &&
|
|
||||||
originalStationList.length != 0 &&
|
{listUpStation.length != 0 && originalStationList.length != 0 && (
|
||||||
allStationData[selectedCurrentStation] && (
|
<>
|
||||||
<LED_vision
|
<CarouselBox
|
||||||
station={
|
{...{
|
||||||
originalStationList && allStationData[selectedCurrentStation]
|
originalStationList,
|
||||||
}
|
listUpStation,
|
||||||
trainDiagram={trainDiagram}
|
nearPositionStation,
|
||||||
getCurrentTrain={getCurrentTrain}
|
setListIndex,
|
||||||
navigate={navigate}
|
listIndex,
|
||||||
openStationACFromEachTrainInfo={() => {}}
|
navigate,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
{listUpStation[listIndex] && (
|
||||||
|
<LED_vision
|
||||||
|
station={listUpStation[listIndex]}
|
||||||
|
navigate={navigate}
|
||||||
|
openStationACFromEachTrainInfo={() => {}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<TopMenuButton />
|
||||||
<JRSTraInfoBox />
|
<JRSTraInfoBox />
|
||||||
<FixedContentBottom navigate={navigate} />
|
<FixedContentBottom navigate={navigate} />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
{mapMode && (
|
||||||
|
<CarouselTypeChanger
|
||||||
|
{...{
|
||||||
|
locationStatus,
|
||||||
|
position,
|
||||||
|
mapsRef,
|
||||||
|
stationListMode,
|
||||||
|
setStationListMode,
|
||||||
|
setSelectedCurrentStation: setListIndex,
|
||||||
|
mapMode,
|
||||||
|
setMapMode,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const TopMenuButton = () => {
|
|
||||||
const buttonList = [
|
|
||||||
{
|
|
||||||
backgroundColor: "#F89038",
|
|
||||||
icon: "train-car",
|
|
||||||
onPress: () =>
|
|
||||||
Linking.openURL("https://www.jr-shikoku.co.jp/01_trainbus/sp/"),
|
|
||||||
title: "駅・鉄道情報",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
backgroundColor: "#EA4752",
|
|
||||||
icon: "google-spreadsheet",
|
|
||||||
onPress: () =>
|
|
||||||
Linking.openURL(
|
|
||||||
"https://www.jr-shikoku.co.jp/01_trainbus/jikoku/sp/#mainprice-box"
|
|
||||||
),
|
|
||||||
title: "運賃表",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
backgroundColor: "#91C31F",
|
|
||||||
icon: "clipboard-list-outline",
|
|
||||||
onPress: () => Linking.openURL("https://www.jr-shikoku.co.jp/e5489/"),
|
|
||||||
title: "予約",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
return (
|
|
||||||
<View style={{ flexDirection: "row" }}>
|
|
||||||
{buttonList.map((d, index) => (
|
|
||||||
<UsefulBox
|
|
||||||
backgroundColor={d.backgroundColor}
|
|
||||||
icon={d.icon}
|
|
||||||
flex={1}
|
|
||||||
onPressButton={d.onPress}
|
|
||||||
key={index + d.icon}
|
|
||||||
>
|
|
||||||
{d.title}
|
|
||||||
</UsefulBox>
|
|
||||||
))}
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const JRSTraInfoBox = () => {
|
|
||||||
const { getTime, delayData, loadingDelayData, setLoadingDelayData } =
|
|
||||||
useTrainDelayData();
|
|
||||||
const styles = {
|
|
||||||
touch: {
|
|
||||||
backgroundColor: "#0099CC",
|
|
||||||
borderRadius: 5,
|
|
||||||
margin: 10,
|
|
||||||
borderColor: "black",
|
|
||||||
borderWidth: 2,
|
|
||||||
overflow: "hidden",
|
|
||||||
},
|
|
||||||
scroll: {
|
|
||||||
backgroundColor: "#0099CC",
|
|
||||||
borderRadius: 5,
|
|
||||||
maxHeight: 300,
|
|
||||||
},
|
|
||||||
bottom: {
|
|
||||||
position: "absolute",
|
|
||||||
top: 250,
|
|
||||||
alignItems: "center",
|
|
||||||
width: "100%",
|
|
||||||
height: 50,
|
|
||||||
backgroundColor: "#007FCC88",
|
|
||||||
},
|
|
||||||
box: {
|
|
||||||
padding: 10,
|
|
||||||
backgroundColor: "white",
|
|
||||||
borderBottomLeftRadius: 5,
|
|
||||||
borderBottomRightRadius: 5,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<TouchableOpacity
|
|
||||||
onPress={() => SheetManager.show("JRSTraInfo")}
|
|
||||||
style={styles.touch}
|
|
||||||
>
|
|
||||||
<ScrollView scrollEnabled={false} style={styles.scroll}>
|
|
||||||
<View
|
|
||||||
style={{ padding: 10, flexDirection: "row", alignItems: "center" }}
|
|
||||||
>
|
|
||||||
<Text style={{ fontSize: 30, fontWeight: "bold", color: "white" }}>
|
|
||||||
列車遅延速報EX
|
|
||||||
</Text>
|
|
||||||
<View style={{ flex: 1 }} />
|
|
||||||
<Text style={{ fontSize: 30, fontWeight: "bold", color: "white" }}>
|
|
||||||
{getTime
|
|
||||||
? getTime.toLocaleTimeString("ja-JP").split(":")[0] +
|
|
||||||
":" +
|
|
||||||
getTime.toLocaleTimeString("ja-JP").split(":")[1]
|
|
||||||
: NaN}
|
|
||||||
</Text>
|
|
||||||
<Ionicons
|
|
||||||
name="reload"
|
|
||||||
color="white"
|
|
||||||
size={30}
|
|
||||||
style={{ margin: 5 }}
|
|
||||||
onPress={() => {
|
|
||||||
setLoadingDelayData(true);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
<View style={styles.box}>
|
|
||||||
{loadingDelayData ? (
|
|
||||||
<View style={{ alignItems: "center" }}>
|
|
||||||
<LottieView
|
|
||||||
autoPlay
|
|
||||||
loop
|
|
||||||
style={{ width: 150, height: 150, backgroundColor: "#fff" }}
|
|
||||||
source={require("./assets/51690-loading-diamonds.json")}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
) : delayData ? (
|
|
||||||
delayData.map((d, index, array) => {
|
|
||||||
let data = d.split(" ");
|
|
||||||
return (
|
|
||||||
<View
|
|
||||||
style={{ flexDirection: "row" }}
|
|
||||||
key={data[1] + "key" + index}
|
|
||||||
>
|
|
||||||
<Text style={{ flex: 15, fontSize: 18 }}>
|
|
||||||
{data[0].replace("\n", "")}
|
|
||||||
</Text>
|
|
||||||
<Text style={{ flex: 5, fontSize: 18 }}>{data[1]}</Text>
|
|
||||||
<Text style={{ flex: 6, fontSize: 18 }}>{data[3]}</Text>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
) : (
|
|
||||||
<Text>現在、5分以上の遅れはありません。</Text>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</ScrollView>
|
|
||||||
<View style={styles.bottom}>
|
|
||||||
<View style={{ flex: 1 }} />
|
|
||||||
<Text style={{ color: "white", fontWeight: "bold", fontSize: 20 }}>
|
|
||||||
詳細を見る
|
|
||||||
</Text>
|
|
||||||
<View style={{ flex: 1 }} />
|
|
||||||
</View>
|
|
||||||
</TouchableOpacity>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
@ -29,10 +29,10 @@ type Props = {
|
|||||||
};
|
};
|
||||||
export const FavoriteStationProvider:FC<Props> = ({ children }) => {
|
export const FavoriteStationProvider:FC<Props> = ({ children }) => {
|
||||||
const [favoriteStation, setFavoriteStation] = useState([]);
|
const [favoriteStation, setFavoriteStation] = useState([]);
|
||||||
const { getStationData } = useStationList();
|
const { getStationDataFromName } = useStationList();
|
||||||
const lodAddMigration = () => {
|
const lodAddMigration = () => {
|
||||||
const migration = favoriteStation.map((d) => {
|
const migration = favoriteStation.map((d) => {
|
||||||
return getStationData(d[0].Station_JP);
|
return getStationDataFromName(d[0].Station_JP);
|
||||||
});
|
});
|
||||||
setFavoriteStation(migration);
|
setFavoriteStation(migration);
|
||||||
};
|
};
|
||||||
|
@ -10,13 +10,15 @@ import { lineList, getStationList } from "../lib/getStationList";
|
|||||||
type initialStateType = {
|
type initialStateType = {
|
||||||
originalStationList: any[][];
|
originalStationList: any[][];
|
||||||
setOriginalStationList: React.Dispatch<React.SetStateAction<any[]>>;
|
setOriginalStationList: React.Dispatch<React.SetStateAction<any[]>>;
|
||||||
getStationData: (id: string) => void;
|
getStationDataFromName: (id: string) => any[];
|
||||||
|
getStationDataFromId: (id: string) => any[];
|
||||||
stationList: any[];
|
stationList: any[];
|
||||||
};
|
};
|
||||||
const initialState = {
|
const initialState = {
|
||||||
originalStationList: [[]],
|
originalStationList: [[]],
|
||||||
setOriginalStationList: () => {},
|
setOriginalStationList: () => {},
|
||||||
getStationData: () => {},
|
getStationDataFromName: () => [],
|
||||||
|
getStationDataFromId: () => [],
|
||||||
stationList: [],
|
stationList: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -33,7 +35,18 @@ export const StationListProvider: FC<Props> = ({ children }) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getStationList().then(setOriginalStationList);
|
getStationList().then(setOriginalStationList);
|
||||||
}, []);
|
}, []);
|
||||||
const getStationData: (name: string) => void = (name) => {
|
const getStationDataFromId: (id: string) => any[] = (id) => {
|
||||||
|
let returnArray = [];
|
||||||
|
Object.keys(originalStationList).forEach((key) => {
|
||||||
|
originalStationList[key].forEach((station) => {
|
||||||
|
if (station.StationNumber === id) {
|
||||||
|
returnArray = [...returnArray, ...getStationDataFromName(station.Station_JP)];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return returnArray;
|
||||||
|
};
|
||||||
|
const getStationDataFromName: (name: string) => any[] = (name) => {
|
||||||
const returnArray = [];
|
const returnArray = [];
|
||||||
Object.keys(originalStationList).forEach((key) => {
|
Object.keys(originalStationList).forEach((key) => {
|
||||||
originalStationList[key].forEach((station) => {
|
originalStationList[key].forEach((station) => {
|
||||||
@ -48,19 +61,18 @@ export const StationListProvider: FC<Props> = ({ children }) => {
|
|||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
if(originalStationList.length === 0) return;
|
if(originalStationList.length === 0) return;
|
||||||
const stationList =
|
const stationList =
|
||||||
originalStationList &&
|
|
||||||
lineList.map((d) =>
|
lineList.map((d) =>
|
||||||
originalStationList[d].map((a) => ({
|
originalStationList[d].map((a) => ({
|
||||||
StationNumber: a.StationNumber,
|
StationNumber: a.StationNumber,
|
||||||
StationName: a.Station_JP,
|
StationName: a.Station_JP,
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
setStationList(stationList)
|
setStationList(stationList);
|
||||||
},[originalStationList])
|
},[originalStationList])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StationListContext.Provider
|
<StationListContext.Provider
|
||||||
value={{ originalStationList, setOriginalStationList, getStationData, stationList }}
|
value={{ originalStationList, setOriginalStationList, getStationDataFromName, getStationDataFromId, stationList }}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</StationListContext.Provider>
|
</StationListContext.Provider>
|
||||||
|
68
stateBox/useTopMenu.tsx
Normal file
68
stateBox/useTopMenu.tsx
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import React, {
|
||||||
|
createContext,
|
||||||
|
useContext,
|
||||||
|
useState,
|
||||||
|
useEffect,
|
||||||
|
FC,
|
||||||
|
} from "react";
|
||||||
|
import { lineList, getStationList } from "../lib/getStationList";
|
||||||
|
|
||||||
|
type initialStateType = {
|
||||||
|
originalStationList: any[][];
|
||||||
|
setOriginalStationList: React.Dispatch<React.SetStateAction<any[]>>;
|
||||||
|
getStationData: (id: string) => void;
|
||||||
|
stationList: any[];
|
||||||
|
};
|
||||||
|
const initialState = {
|
||||||
|
originalStationList: [[]],
|
||||||
|
setOriginalStationList: () => {},
|
||||||
|
getStationData: () => {},
|
||||||
|
stationList: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const TopMenuContext = createContext<initialStateType>(initialState);
|
||||||
|
type Props = {
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
export const useTopMenu = () => {
|
||||||
|
return useContext(TopMenuContext);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TopMenuProvider: 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;
|
||||||
|
};
|
||||||
|
const [stationList, setStationList] = useState<any[][]>([[]]);
|
||||||
|
useEffect(()=>{
|
||||||
|
if(originalStationList.length === 0) return;
|
||||||
|
const stationList =
|
||||||
|
originalStationList &&
|
||||||
|
lineList.map((d) =>
|
||||||
|
originalStationList[d].map((a) => ({
|
||||||
|
StationNumber: a.StationNumber,
|
||||||
|
StationName: a.Station_JP,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
setStationList(stationList)
|
||||||
|
},[originalStationList])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TopMenuContext.Provider
|
||||||
|
value={{ originalStationList, setOriginalStationList, getStationData, stationList }}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</TopMenuContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
@ -3,7 +3,7 @@ const initialState = {
|
|||||||
getTime: new Date(),
|
getTime: new Date(),
|
||||||
setGetTime: () => {},
|
setGetTime: () => {},
|
||||||
loadingDelayData: true,
|
loadingDelayData: true,
|
||||||
setLoadingDelayData: () => {},
|
setLoadingDelayData: (loading) => {},
|
||||||
delayData: undefined,
|
delayData: undefined,
|
||||||
setDelayData: () => {},
|
setDelayData: () => {},
|
||||||
};
|
};
|
||||||
|
76
stateBox/useUserPosition.tsx
Normal file
76
stateBox/useUserPosition.tsx
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import React, {
|
||||||
|
createContext,
|
||||||
|
useContext,
|
||||||
|
useState,
|
||||||
|
useEffect,
|
||||||
|
FC,
|
||||||
|
} from "react";
|
||||||
|
import {
|
||||||
|
LocationObject,
|
||||||
|
requestForegroundPermissionsAsync,
|
||||||
|
getCurrentPositionAsync,
|
||||||
|
} from "expo-location";
|
||||||
|
import { Platform } from "react-native";
|
||||||
|
import useInterval from "@/lib/useInterval";
|
||||||
|
|
||||||
|
type initialStateType = {
|
||||||
|
position: LocationObject | undefined;
|
||||||
|
getCurrentPosition: () => void;
|
||||||
|
locationStatus: boolean | null;
|
||||||
|
getLocationPermission: () => void;
|
||||||
|
};
|
||||||
|
const initialState = {
|
||||||
|
position: undefined,
|
||||||
|
getCurrentPosition: () => {},
|
||||||
|
locationStatus: null,
|
||||||
|
getLocationPermission: () => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
const UserPositionContext = createContext<initialStateType>(initialState);
|
||||||
|
type Props = {
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
export const useUserPosition = () => {
|
||||||
|
return useContext(UserPositionContext);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const UserPositionProvider: FC<Props> = ({ children }) => {
|
||||||
|
//位置情報
|
||||||
|
const [locationStatus, setLocationStatus] = useState<boolean | null>(null);
|
||||||
|
const [position, setPosition] = useState<LocationObject | undefined>(
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
|
||||||
|
const getLocationPermission = async () => {
|
||||||
|
return requestForegroundPermissionsAsync().then((data) => {
|
||||||
|
setLocationStatus(
|
||||||
|
Platform.OS == "ios"
|
||||||
|
? data.status == "granted"
|
||||||
|
: data.android.accuracy == "fine"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const getCurrentPosition = () => {
|
||||||
|
if (!locationStatus) return () => {};
|
||||||
|
getCurrentPositionAsync({}).then((location) => setPosition(location));
|
||||||
|
};
|
||||||
|
useEffect(() => {
|
||||||
|
if (Platform.OS == "web") return;
|
||||||
|
getLocationPermission();
|
||||||
|
}, []);
|
||||||
|
useEffect(getCurrentPosition, [locationStatus]);
|
||||||
|
useInterval(getCurrentPosition, 5000);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<UserPositionContext.Provider
|
||||||
|
value={{
|
||||||
|
position,
|
||||||
|
getCurrentPosition,
|
||||||
|
locationStatus,
|
||||||
|
getLocationPermission,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</UserPositionContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user