Merge commit '0efab93a1451818339bfbed97545e6782eafcb9c' into patch/5.0.x
11
App.js
@ -57,10 +57,10 @@ export default function App() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
export function AppContainer() {
|
export function AppContainer() {
|
||||||
const { areaInfo, setAreaInfo } = useAreaInfo();
|
const { areaInfo } = useAreaInfo();
|
||||||
|
const navigationRef = React.useRef();
|
||||||
return (
|
return (
|
||||||
<NavigationContainer name="Root" style={{ flex: 1 }}>
|
<NavigationContainer name="Root" style={{ flex: 1 }} ref={navigationRef}>
|
||||||
<Tab.Navigator
|
<Tab.Navigator
|
||||||
tabBarOptions={{ keyboardHidesTabBar: Platform.OS === "android" }}
|
tabBarOptions={{ keyboardHidesTabBar: Platform.OS === "android" }}
|
||||||
>
|
>
|
||||||
@ -72,8 +72,9 @@ export function AppContainer() {
|
|||||||
gestureEnabled: true,
|
gestureEnabled: true,
|
||||||
tabBarIcon: initIcon("barchart", "AntDesign"),
|
tabBarIcon: initIcon("barchart", "AntDesign"),
|
||||||
}}
|
}}
|
||||||
component={Top}
|
>
|
||||||
/>
|
{(props) => <Top {...props} navigationRef={navigationRef} />}
|
||||||
|
</Tab.Screen>
|
||||||
<Tab.Screen
|
<Tab.Screen
|
||||||
name="menuPage"
|
name="menuPage"
|
||||||
options={{
|
options={{
|
||||||
|
12
MenuPage.js
@ -7,7 +7,7 @@ import { AS } from "./storageControl";
|
|||||||
import TrainBase from "./trainbaseview";
|
import TrainBase from "./trainbaseview";
|
||||||
import HowTo from "./howto";
|
import HowTo from "./howto";
|
||||||
import Menu from "./menu";
|
import Menu from "./menu";
|
||||||
import Setting from "./components/settings.js";
|
import Setting from "./components/Settings/settings";
|
||||||
import { useFavoriteStation } from "./stateBox/useFavoriteStation";
|
import { useFavoriteStation } from "./stateBox/useFavoriteStation";
|
||||||
import { optionData } from "./lib/stackOption.js";
|
import { optionData } from "./lib/stackOption.js";
|
||||||
import CurrentTrainListView from "./components/CurrentTrainListView.js";
|
import CurrentTrainListView from "./components/CurrentTrainListView.js";
|
||||||
@ -46,7 +46,15 @@ export function MenuPage() {
|
|||||||
}}
|
}}
|
||||||
children={() => <Menu getCurrentTrain={getCurrentTrain} />}
|
children={() => <Menu getCurrentTrain={getCurrentTrain} />}
|
||||||
/>
|
/>
|
||||||
<Stack.Screen name="setting" options={optionData} component={Setting} />
|
<Stack.Screen
|
||||||
|
name="setting"
|
||||||
|
options={{
|
||||||
|
...optionData,
|
||||||
|
gestureEnabled: false,
|
||||||
|
cardOverlayEnabled: true,
|
||||||
|
}}
|
||||||
|
component={Setting}
|
||||||
|
/>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="trainbase"
|
name="trainbase"
|
||||||
options={{ ...optionData, gestureResponseDistance: { vertical: 300 } }}
|
options={{ ...optionData, gestureResponseDistance: { vertical: 300 } }}
|
||||||
|
32
Top.js
@ -12,24 +12,50 @@ import TrainMenu from "./components/trainMenu.js";
|
|||||||
import FavoriteList from "./components/FavoriteList.js";
|
import FavoriteList from "./components/FavoriteList.js";
|
||||||
import { optionData } from "./lib/stackOption.js";
|
import { optionData } from "./lib/stackOption.js";
|
||||||
import { useNavigation } from "@react-navigation/native";
|
import { useNavigation } from "@react-navigation/native";
|
||||||
|
import { useCurrentTrain } from "./stateBox/useCurrentTrain.js";
|
||||||
|
import { AS } from "./storageControl.js";
|
||||||
const Stack = createStackNavigator();
|
const Stack = createStackNavigator();
|
||||||
export const Top = () => {
|
export const Top = ({ navigationRef }) => {
|
||||||
|
const { webview, getCurrentTrain } = useCurrentTrain();
|
||||||
const navigation = useNavigation();
|
const navigation = useNavigation();
|
||||||
const { navigate, addListener } = navigation;
|
const { navigate, addListener } = navigation;
|
||||||
|
|
||||||
//地図用
|
//地図用
|
||||||
const [mapsStationData, setMapsStationData] = useState(undefined);
|
const [mapsStationData, setMapsStationData] = useState(undefined);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getStationList2().then(setMapsStationData);
|
getStationList2().then(setMapsStationData);
|
||||||
}, []);
|
}, []);
|
||||||
|
const [mapSwitch, setMapSwitch] = React.useState("false");
|
||||||
|
const ASCore = ({ k, s, d }) =>
|
||||||
|
AS.getItem(k)
|
||||||
|
.then((d) => (d ? s(d) : AS.setItem(k, d)))
|
||||||
|
.catch(() => AS.setItem(k, d));
|
||||||
|
useEffect(() => {
|
||||||
|
//地図スイッチ
|
||||||
|
ASCore({ k: "mapSwitch", s: setMapSwitch, d: "false" });
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribe = addListener("tabLongPress", (e) =>
|
const unsubscribe = addListener("tabLongPress", () =>
|
||||||
navigate("favoriteList")
|
navigate("favoriteList")
|
||||||
);
|
);
|
||||||
|
|
||||||
return unsubscribe;
|
return unsubscribe;
|
||||||
}, [navigation]);
|
}, [navigation]);
|
||||||
|
useEffect(() => {
|
||||||
|
const unsubscribe = navigation.addListener("tabPress", () => {
|
||||||
|
if (navigationRef.current?.getCurrentRoute().name == "Apps") {
|
||||||
|
if (mapSwitch == "true") {
|
||||||
|
navigation.navigate("trainMenu");
|
||||||
|
} else {
|
||||||
|
webview.current?.injectJavaScript(`AccordionClassEvent()`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
navigation.navigate("Apps");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return unsubscribe;
|
||||||
|
}, [navigation, mapSwitch]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack.Navigator>
|
<Stack.Navigator>
|
||||||
|
BIN
assets/configuration/icon_default.jpg
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
assets/configuration/icon_original.jpg
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
assets/configuration/menu_default.jpg
Normal file
After Width: | Height: | Size: 106 KiB |
BIN
assets/configuration/menu_original.jpg
Normal file
After Width: | Height: | Size: 197 KiB |
BIN
assets/configuration/station_default.jpg
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
assets/configuration/station_original.jpg
Normal file
After Width: | Height: | Size: 90 KiB |
BIN
assets/configuration/train_default.jpg
Normal file
After Width: | Height: | Size: 83 KiB |
BIN
assets/configuration/train_original.jpg
Normal file
After Width: | Height: | Size: 88 KiB |
BIN
assets/configuration/train_original_small.jpg
Normal file
After Width: | Height: | Size: 100 KiB |
@ -52,7 +52,7 @@ export const TrainDataView = ({
|
|||||||
});
|
});
|
||||||
if (!test.length) return;
|
if (!test.length) return;
|
||||||
webview.current?.injectJavaScript(
|
webview.current?.injectJavaScript(
|
||||||
`MoveDisplayStation('${test[0].line}_${test[0].station.MyStation}_${test[0].station.Station_JP}')`
|
`MoveDisplayStation('${test[0].line}_${test[0].station.MyStation}_${test[0].station.Station_JP}');setStrings();`
|
||||||
);
|
);
|
||||||
navigate("Apps");
|
navigate("Apps");
|
||||||
SheetManager.hide("EachTrainInfo");
|
SheetManager.hide("EachTrainInfo");
|
||||||
|
@ -115,13 +115,13 @@ export const StationDeteilView = (props) => {
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
{currentStation &&
|
{/* {currentStation &&
|
||||||
currentStation.map((d) => (
|
currentStation.map((d) => (
|
||||||
<NexPreStationLine
|
<NexPreStationLine
|
||||||
currentStation={d}
|
currentStation={d}
|
||||||
originalStationList={originalStationList}
|
originalStationList={originalStationList}
|
||||||
/>
|
/>
|
||||||
))}
|
))} */}
|
||||||
{currentStation &&
|
{currentStation &&
|
||||||
currentStation[0].JrHpUrl &&
|
currentStation[0].JrHpUrl &&
|
||||||
currentStation[0].StationNumber != "M12" && (
|
currentStation[0].StationNumber != "M12" && (
|
||||||
|
@ -3,19 +3,14 @@ import { TraInfoEXWidget } from "./TraInfoEXWidget";
|
|||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { ToastAndroid } from "react-native";
|
import { ToastAndroid } from "react-native";
|
||||||
|
|
||||||
const nameToWidget = {
|
export const nameToWidget = {
|
||||||
// Hello will be the **name** with which we will reference our widget.
|
// Hello will be the **name** with which we will reference our widget.
|
||||||
JR_shikoku_train_info: TraInfoEXWidget,
|
JR_shikoku_train_info: TraInfoEXWidget,
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function widgetTaskHandler(props) {
|
export const getDelayData = async () => {
|
||||||
const widgetInfo = props.widgetInfo;
|
// Fetch data from the server
|
||||||
const Widget = nameToWidget[widgetInfo.widgetName];
|
|
||||||
const time = dayjs().format("HH:mm");
|
const time = dayjs().format("HH:mm");
|
||||||
ToastAndroid.show(
|
|
||||||
`Widget Action: ${props.widgetAction} ${time}`,
|
|
||||||
ToastAndroid.SHORT
|
|
||||||
);
|
|
||||||
const delayString = await fetch(
|
const delayString = await fetch(
|
||||||
"https://script.google.com/macros/s/AKfycbyKxch7z7l8e07LXulRHqxjVoIiB13kcgvoToLE-rqlxLmLSKdlmqz0FI1F2EuA7Zfg/exec"
|
"https://script.google.com/macros/s/AKfycbyKxch7z7l8e07LXulRHqxjVoIiB13kcgvoToLE-rqlxLmLSKdlmqz0FI1F2EuA7Zfg/exec"
|
||||||
)
|
)
|
||||||
@ -27,6 +22,16 @@ export async function widgetTaskHandler(props) {
|
|||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
ToastAndroid.show(`${delayString}`, ToastAndroid.SHORT);
|
ToastAndroid.show(`${delayString}`, ToastAndroid.SHORT);
|
||||||
|
return { time, delayString };
|
||||||
|
};
|
||||||
|
export async function widgetTaskHandler(props) {
|
||||||
|
const widgetInfo = props.widgetInfo;
|
||||||
|
const Widget = nameToWidget[widgetInfo.widgetName];
|
||||||
|
ToastAndroid.show(
|
||||||
|
`Widget Action: ${JSON.stringify(props.widgetInfo.widgetId)}`,
|
||||||
|
ToastAndroid.SHORT
|
||||||
|
);
|
||||||
|
const { time, delayString } = await getDelayData();
|
||||||
switch (props.widgetAction) {
|
switch (props.widgetAction) {
|
||||||
case "WIDGET_ADDED":
|
case "WIDGET_ADDED":
|
||||||
case "WIDGET_UPDATE":
|
case "WIDGET_UPDATE":
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { ScrollView, View, Animated, LayoutAnimation } from "react-native";
|
import { ScrollView, View, Animated, LayoutAnimation } from "react-native";
|
||||||
import React, { useMemo, useState } from "react";
|
import React, { useEffect, useMemo, useState, useLayoutEffect } from "react";
|
||||||
import { useScrollHandlers } from "react-native-actions-sheet";
|
import { useScrollHandlers } from "react-native-actions-sheet";
|
||||||
|
import { AS } from "../storageControl";
|
||||||
|
|
||||||
export const DynamicHeaderScrollView = (props) => {
|
export const DynamicHeaderScrollView = (props) => {
|
||||||
const {
|
const {
|
||||||
@ -13,7 +14,30 @@ export const DynamicHeaderScrollView = (props) => {
|
|||||||
styles,
|
styles,
|
||||||
from,
|
from,
|
||||||
} = props;
|
} = props;
|
||||||
|
const [headerSize, setHeaderSize] = useState("default");
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
AS.getItem("headerSize")
|
||||||
|
.then((res) => {
|
||||||
|
if (res) {
|
||||||
|
setHeaderSize(res);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
AS.setItem("headerSize", "default");
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
useEffect(() => {
|
||||||
|
switch (headerSize) {
|
||||||
|
case "small":
|
||||||
|
setHeaderVisible(true);
|
||||||
|
return;
|
||||||
|
case "big":
|
||||||
|
case "default":
|
||||||
|
default:
|
||||||
|
setHeaderVisible(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}, [headerSize]);
|
||||||
const viewHeader = useMemo(() => {
|
const viewHeader = useMemo(() => {
|
||||||
switch (from) {
|
switch (from) {
|
||||||
case "AllTrainDiagramView":
|
case "AllTrainDiagramView":
|
||||||
@ -25,7 +49,7 @@ export const DynamicHeaderScrollView = (props) => {
|
|||||||
}
|
}
|
||||||
}, [from]);
|
}, [from]);
|
||||||
|
|
||||||
const Max_Header_Height = viewHeader ? 0 : 200;
|
const Max_Header_Height = headerSize == "small" ? 0 : viewHeader ? 0 : 200;
|
||||||
const Min_Header_Height = viewHeader ? 0 : 80;
|
const Min_Header_Height = viewHeader ? 0 : 80;
|
||||||
|
|
||||||
const Scroll_Distance = Max_Header_Height - Min_Header_Height;
|
const Scroll_Distance = Max_Header_Height - Min_Header_Height;
|
||||||
@ -87,13 +111,24 @@ export const DynamicHeaderScrollView = (props) => {
|
|||||||
const [headerVisible, setHeaderVisible] = useState(false);
|
const [headerVisible, setHeaderVisible] = useState(false);
|
||||||
|
|
||||||
const onScroll = (event) => {
|
const onScroll = (event) => {
|
||||||
const scrollY = event.nativeEvent.contentOffset.y;
|
switch (headerSize) {
|
||||||
if (Scroll_Distance < scrollY == headerVisible) return;
|
case "big":
|
||||||
LayoutAnimation.configureNext({
|
setHeaderVisible(false);
|
||||||
duration: 100,
|
return;
|
||||||
update: { type: "easeOut" },
|
case "small":
|
||||||
});
|
setHeaderVisible(true);
|
||||||
setHeaderVisible(Scroll_Distance < scrollY);
|
return;
|
||||||
|
case "default":
|
||||||
|
default:
|
||||||
|
const scrollY = event.nativeEvent.contentOffset.y;
|
||||||
|
if (Scroll_Distance < scrollY == headerVisible) return;
|
||||||
|
LayoutAnimation.configureNext({
|
||||||
|
duration: 100,
|
||||||
|
update: { type: "easeOut" },
|
||||||
|
});
|
||||||
|
setHeaderVisible(Scroll_Distance < scrollY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { View, Text, TouchableOpacity, ScrollView } from "react-native";
|
import { View, Text, TouchableOpacity, ScrollView } from "react-native";
|
||||||
import { ListItem } from "native-base";
|
|
||||||
import Icon from "react-native-vector-icons/Entypo";
|
import Icon from "react-native-vector-icons/Entypo";
|
||||||
import { useFavoriteStation } from "../stateBox/useFavoriteStation";
|
import { useFavoriteStation } from "../stateBox/useFavoriteStation";
|
||||||
import { useCurrentTrain } from "../stateBox/useCurrentTrain";
|
import { useCurrentTrain } from "../stateBox/useCurrentTrain";
|
||||||
import { useNavigation } from "@react-navigation/native";
|
import { useNavigation } from "@react-navigation/native";
|
||||||
|
import { FavoriteListItem } from "./atom/FavoriteListItem";
|
||||||
export default function FavoriteList({ stationData }) {
|
export default function FavoriteList({ stationData }) {
|
||||||
const { favoriteStation } = useFavoriteStation();
|
const { favoriteStation } = useFavoriteStation();
|
||||||
const { webview } = useCurrentTrain();
|
const { webview } = useCurrentTrain();
|
||||||
@ -15,7 +16,7 @@ export default function FavoriteList({ stationData }) {
|
|||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
fontSize: 25,
|
fontSize: 20,
|
||||||
color: "white",
|
color: "white",
|
||||||
fontWeight: "bold",
|
fontWeight: "bold",
|
||||||
paddingVertical: 10,
|
paddingVertical: 10,
|
||||||
@ -28,7 +29,8 @@ export default function FavoriteList({ stationData }) {
|
|||||||
.filter((d) => d[0].StationMap)
|
.filter((d) => d[0].StationMap)
|
||||||
.map((currentStation) => {
|
.map((currentStation) => {
|
||||||
return (
|
return (
|
||||||
<ListItem
|
<FavoriteListItem
|
||||||
|
currentStation={currentStation}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
const getStationLine = (now) => {
|
const getStationLine = (now) => {
|
||||||
const returnData = Object.keys(stationData).filter((d) => {
|
const returnData = Object.keys(stationData).filter((d) => {
|
||||||
@ -42,33 +44,26 @@ export default function FavoriteList({ stationData }) {
|
|||||||
const lineName = getStationLine(currentStation[0]);
|
const lineName = getStationLine(currentStation[0]);
|
||||||
|
|
||||||
webview.current?.injectJavaScript(
|
webview.current?.injectJavaScript(
|
||||||
`MoveDisplayStation('${lineName}_${currentStation[0].MyStation}_${currentStation[0].Station_JP}')`
|
`MoveDisplayStation('${lineName}_${currentStation[0].MyStation}_${currentStation[0].Station_JP}');
|
||||||
|
setStrings();`
|
||||||
);
|
);
|
||||||
navigate("Apps");
|
navigate("Apps");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text style={{ fontSize: 20, flex: 2 }}>
|
|
||||||
{currentStation
|
|
||||||
.map((d) => d.StationNumber)
|
|
||||||
.filter((d) => d !== null)
|
|
||||||
.join("/")}
|
|
||||||
</Text>
|
|
||||||
<Text style={{ fontSize: 20, flex: 3 }}>
|
|
||||||
{currentStation[0].Station_JP}
|
|
||||||
</Text>
|
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
flex: 2,
|
flex: 2,
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignContent: "center",
|
alignContent: "center",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
|
marginVertical: 4,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View style={{ flex: 1 }} />
|
<View style={{ flex: 1 }} />
|
||||||
<Text style={{ fontSize: 20 }}>移動する</Text>
|
<Text style={{ fontSize: 20 }}>移動する</Text>
|
||||||
<Icon name="chevron-right" size={20} />
|
<Icon name="chevron-right" size={20} />
|
||||||
</View>
|
</View>
|
||||||
</ListItem>
|
</FavoriteListItem>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
@ -270,27 +270,7 @@ export const FixedContentBottom = (props) => {
|
|||||||
データベースに存在する全列車のダイヤを探索
|
データベースに存在する全列車のダイヤを探索
|
||||||
</Text>
|
</Text>
|
||||||
</TextBox>
|
</TextBox>
|
||||||
<Text style={{ fontWeight: "bold", fontSize: 20 }}>
|
<Text style={{ fontWeight: "bold", fontSize: 20 }}>その他</Text>
|
||||||
このアプリについて
|
|
||||||
</Text>
|
|
||||||
<Text>
|
|
||||||
このアプリはXprocess(HARUKIN)が製作しているJR四国の完全非公式アシストアプリケーションです。このアプリに関することでのJR四国公式へ問合せすることはお控えください。以下のTwitterよりお願いします。
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<TextBox
|
|
||||||
backgroundColor="#CC0000"
|
|
||||||
flex={1}
|
|
||||||
onPressButton={() =>
|
|
||||||
Linking.openURL("https://twitter.com/Xprocess_main")
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text style={{ color: "white", fontWeight: "bold", fontSize: 20 }}>
|
|
||||||
XprocessのTwitter
|
|
||||||
</Text>
|
|
||||||
<Text style={{ color: "white", fontSize: 18 }}>
|
|
||||||
制作運営のTwitterです。
|
|
||||||
</Text>
|
|
||||||
</TextBox>
|
|
||||||
<TextBox
|
<TextBox
|
||||||
backgroundColor="black"
|
backgroundColor="black"
|
||||||
flex={1}
|
flex={1}
|
||||||
|
134
components/Settings/FavoliteSettings/FavoiliteSettingsItem.js
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import Icon from "react-native-vector-icons/Entypo";
|
||||||
|
import { View, Text, TouchableOpacity, LayoutAnimation } from "react-native";
|
||||||
|
import lineColorList from "../../../assets/originData/lineColorList";
|
||||||
|
import { AS } from "../../../storageControl";
|
||||||
|
|
||||||
|
export const FavoriteSettingsItem = ({
|
||||||
|
currentStation,
|
||||||
|
setFavoriteStation,
|
||||||
|
index,
|
||||||
|
array,
|
||||||
|
}) => {
|
||||||
|
const lineIDs = [];
|
||||||
|
const EachIDs = [];
|
||||||
|
console.log(currentStation);
|
||||||
|
currentStation.forEach((d) => {
|
||||||
|
if (!d.StationNumber) return;
|
||||||
|
const textArray = d.StationNumber.split("");
|
||||||
|
lineIDs.push(textArray.filter((s) => "A" < s && s < "Z").join(""));
|
||||||
|
EachIDs.push(textArray.filter((s) => "0" <= s && s <= "9").join(""));
|
||||||
|
});
|
||||||
|
const [head, setHead] = useState(false);
|
||||||
|
const [tail, setTail] = useState(false);
|
||||||
|
useEffect(() => {
|
||||||
|
switch (true) {
|
||||||
|
case array.length == 1:
|
||||||
|
setHead(true);
|
||||||
|
setTail(true);
|
||||||
|
break;
|
||||||
|
case index == 0:
|
||||||
|
setHead(true);
|
||||||
|
setTail(false);
|
||||||
|
break;
|
||||||
|
case index == array.length - 1:
|
||||||
|
setHead(false);
|
||||||
|
setTail(true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
setHead(false);
|
||||||
|
setTail(false);
|
||||||
|
}
|
||||||
|
}, [array]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{ flexDirection: "row", backgroundColor: "white" }}>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
width: 35,
|
||||||
|
position: "relative",
|
||||||
|
marginHorizontal: 15,
|
||||||
|
flexDirection: "row",
|
||||||
|
height: "101%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{lineIDs.map((lineID, index) => (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
backgroundColor: lineColorList[lineID],
|
||||||
|
flex: 1,
|
||||||
|
}}
|
||||||
|
key={lineID}
|
||||||
|
>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
color: "white",
|
||||||
|
textAlign: "center",
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: "bold",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{lineIDs[index]}
|
||||||
|
{"\n"}
|
||||||
|
{EachIDs[index]}
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
padding: 8,
|
||||||
|
flexDirection: "row",
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: "#f0f0f0",
|
||||||
|
flex: 1,
|
||||||
|
alignContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={{ fontSize: 20 }}>{currentStation[0].Station_JP}</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<TouchableOpacity
|
||||||
|
style={{ marginHorizontal: 10, marginVertical: 4, width: 30 }}
|
||||||
|
onPress={() => {
|
||||||
|
console.log("up");
|
||||||
|
LayoutAnimation.configureNext(
|
||||||
|
LayoutAnimation.Presets.easeInEaseOut
|
||||||
|
);
|
||||||
|
const removedStation = [...array].filter((d, i) => {
|
||||||
|
if (i == index) return false;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
removedStation.splice(index - 1, 0, currentStation);
|
||||||
|
setFavoriteStation(removedStation);
|
||||||
|
|
||||||
|
AS.setItem("favoriteStation", JSON.stringify(removedStation));
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{head ? null : <Icon name="chevron-up" size={26} />}
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={{ marginHorizontal: 10, marginVertical: 4, width: 30 }}
|
||||||
|
onPress={() => {
|
||||||
|
console.log("down");
|
||||||
|
LayoutAnimation.configureNext(
|
||||||
|
LayoutAnimation.Presets.easeInEaseOut
|
||||||
|
);
|
||||||
|
const removedStation = [...array].filter((d, i) => {
|
||||||
|
if (i == index) return false;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
removedStation.splice(index + 1, 0, currentStation);
|
||||||
|
setFavoriteStation(removedStation);
|
||||||
|
AS.setItem("favoriteStation", JSON.stringify(removedStation));
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{tail ? null : <Icon name="chevron-down" size={26} />}
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
90
components/Settings/FavoriteSettings.js
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { View, Text, TouchableOpacity, ScrollView } from "react-native";
|
||||||
|
import { useFavoriteStation } from "../../stateBox/useFavoriteStation";
|
||||||
|
import { CheckBox } from "react-native-elements";
|
||||||
|
import { FavoriteSettingsItem } from "./FavoliteSettings/FavoiliteSettingsItem";
|
||||||
|
|
||||||
|
export const FavoriteSettings = ({ navigate }) => {
|
||||||
|
const { favoriteStation, setFavoriteStation } = useFavoriteStation();
|
||||||
|
return (
|
||||||
|
<View style={{ height: "100%", backgroundColor: "#0099CC" }}>
|
||||||
|
<View style={{ backgroundColor: "#0099CC", flexDirection: "row" }}>
|
||||||
|
<View style={{ flex: 1 }}>
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => navigate("settingTopPage")}
|
||||||
|
style={{
|
||||||
|
flexDirection: "column",
|
||||||
|
flex: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: "bold",
|
||||||
|
textAlign: "left",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
color: "white",
|
||||||
|
padding: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
< 設定
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: "bold",
|
||||||
|
textAlign: "center",
|
||||||
|
color: "white",
|
||||||
|
padding: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
お気に入り設定
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }}></View>
|
||||||
|
</View>
|
||||||
|
<ScrollView style={{ flex: 1, backgroundColor: "white" }}>
|
||||||
|
{favoriteStation.map((currentStation, index, array) => (
|
||||||
|
<FavoriteSettingsItem
|
||||||
|
currentStation={currentStation}
|
||||||
|
setFavoriteStation={setFavoriteStation}
|
||||||
|
index={index}
|
||||||
|
array={array}
|
||||||
|
key={currentStation[0].StationNumber}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ScrollView>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
backgroundColor: "white",
|
||||||
|
borderWidth: 1,
|
||||||
|
borderStyle: "solid",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
お気に入り登録した駅を並び替えることができます。一番上に置いた駅が位置情報の起動時に表示されます。(移動不可能な駅の場合エラーが発生します。任意指定が可能になる機能を開発予定です。)
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SimpleSwitch = ({ bool, setBool, str }) => (
|
||||||
|
<View style={{ flexDirection: "row" }}>
|
||||||
|
<CheckBox
|
||||||
|
checked={bool == "true" ? true : false}
|
||||||
|
checkedColor="red"
|
||||||
|
onPress={() => setBool(bool == "true" ? "false" : "true")}
|
||||||
|
containerStyle={{
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: "#00000000",
|
||||||
|
borderColor: "white",
|
||||||
|
alignContent: "center",
|
||||||
|
}}
|
||||||
|
textStyle={{ fontSize: 20, fontWeight: "normal" }}
|
||||||
|
title={str}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
159
components/Settings/LayoutSettings.js
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { View, Text, TouchableOpacity, ScrollView } from "react-native";
|
||||||
|
import { SwitchArea } from "../atom/SwitchArea";
|
||||||
|
import { CheckBox } from "react-native-elements";
|
||||||
|
import { TripleSwitchArea } from "../atom/TripleSwitchArea";
|
||||||
|
|
||||||
|
export const LayoutSettings = ({
|
||||||
|
navigate,
|
||||||
|
iconSetting,
|
||||||
|
setIconSetting,
|
||||||
|
mapSwitch,
|
||||||
|
setMapSwitch,
|
||||||
|
stationMenu,
|
||||||
|
setStationMenu,
|
||||||
|
usePDFView,
|
||||||
|
setUsePDFView,
|
||||||
|
trainMenu,
|
||||||
|
setTrainMenu,
|
||||||
|
trainPosition,
|
||||||
|
setTrainPosition,
|
||||||
|
headerSize,
|
||||||
|
setHeaderSize,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<View style={{ height: "100%", backgroundColor: "#0099CC" }}>
|
||||||
|
<View style={{ backgroundColor: "#0099CC", flexDirection: "row" }}>
|
||||||
|
<View style={{ flex: 1 }}>
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => navigate("settingTopPage")}
|
||||||
|
style={{
|
||||||
|
flexDirection: "column",
|
||||||
|
flex: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: "bold",
|
||||||
|
textAlign: "left",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
color: "white",
|
||||||
|
padding: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
< 設定
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: "bold",
|
||||||
|
textAlign: "center",
|
||||||
|
color: "white",
|
||||||
|
padding: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
レイアウト設定
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }}></View>
|
||||||
|
</View>
|
||||||
|
<ScrollView style={{ flex: 1, backgroundColor: "white" }}>
|
||||||
|
<View style={{ flex: 1 }}>
|
||||||
|
<SwitchArea
|
||||||
|
str="列車アイコン表示"
|
||||||
|
bool={iconSetting}
|
||||||
|
setBool={setIconSetting}
|
||||||
|
falseImage={require("../../assets/configuration/icon_default.jpg")}
|
||||||
|
trueImage={require("../../assets/configuration/icon_original.jpg")}
|
||||||
|
falseText={"本家\n(文字アイコン)"}
|
||||||
|
trueText={"オリジナル\n(車種アイコン)"}
|
||||||
|
/>
|
||||||
|
<SwitchArea
|
||||||
|
str="トップメニュー表示"
|
||||||
|
bool={mapSwitch}
|
||||||
|
setBool={setMapSwitch}
|
||||||
|
falseImage={require("../../assets/configuration/menu_default.jpg")}
|
||||||
|
trueImage={require("../../assets/configuration/menu_original.jpg")}
|
||||||
|
falseText={"本家\n(文字&路線リスト)"}
|
||||||
|
trueText={"オリジナル\n(マップ&お気に入り)"}
|
||||||
|
/>
|
||||||
|
<SwitchArea
|
||||||
|
str="駅メニュー表示"
|
||||||
|
bool={stationMenu}
|
||||||
|
setBool={setStationMenu}
|
||||||
|
falseText={"本家\n(文字)"}
|
||||||
|
trueText={"オリジナル\n(駅名標)"}
|
||||||
|
falseImage={require("../../assets/configuration/station_default.jpg")}
|
||||||
|
trueImage={require("../../assets/configuration/station_original.jpg")}
|
||||||
|
>
|
||||||
|
<SimpleSwitch
|
||||||
|
bool={usePDFView}
|
||||||
|
setBool={setUsePDFView}
|
||||||
|
color="red"
|
||||||
|
str="時刻表PDFをアプリの外で表示する"
|
||||||
|
/>
|
||||||
|
</SwitchArea>
|
||||||
|
<SwitchArea
|
||||||
|
str="列車メニュー"
|
||||||
|
bool={trainMenu}
|
||||||
|
setBool={setTrainMenu}
|
||||||
|
falseText={"本家"}
|
||||||
|
trueText={"オリジナル"}
|
||||||
|
falseImage={require("../../assets/configuration/train_default.jpg")}
|
||||||
|
trueImage={require("../../assets/configuration/train_original.jpg")}
|
||||||
|
>
|
||||||
|
<TripleSwitchArea
|
||||||
|
str={"ヘッダーサイズ"}
|
||||||
|
bool={headerSize}
|
||||||
|
setBool={setHeaderSize}
|
||||||
|
firstItem={{
|
||||||
|
firstImage: require("../../assets/configuration/train_original_small.jpg"),
|
||||||
|
firstText: "小固定",
|
||||||
|
firstValue: "small",
|
||||||
|
}}
|
||||||
|
secondItem={{
|
||||||
|
secondImage: require("../../assets/configuration/train_original.jpg"),
|
||||||
|
secondText: "既定(可変)",
|
||||||
|
secondValue: "default",
|
||||||
|
}}
|
||||||
|
thirdItem={{
|
||||||
|
thirdImage: require("../../assets/configuration/train_original.jpg"),
|
||||||
|
thirdText: "大固定",
|
||||||
|
thirdValue: "big",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SimpleSwitch
|
||||||
|
bool={trainPosition}
|
||||||
|
setBool={setTrainPosition}
|
||||||
|
color="red"
|
||||||
|
str="列車の現在位置をアイコン表示"
|
||||||
|
/>
|
||||||
|
</SwitchArea>
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SimpleSwitch = ({ bool, setBool, str }) => (
|
||||||
|
<View style={{ flexDirection: "row" }}>
|
||||||
|
<CheckBox
|
||||||
|
checked={bool == "true" ? true : false}
|
||||||
|
checkedColor="red"
|
||||||
|
onPress={() => setBool(bool == "true" ? "false" : "true")}
|
||||||
|
containerStyle={{
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: "#00000000",
|
||||||
|
borderColor: "white",
|
||||||
|
alignContent: "center",
|
||||||
|
}}
|
||||||
|
textStyle={{ fontSize: 20, fontWeight: "normal" }}
|
||||||
|
title={str}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
283
components/Settings/SettingTopPage.js
Normal file
@ -0,0 +1,283 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
TouchableOpacity,
|
||||||
|
ScrollView,
|
||||||
|
Linking,
|
||||||
|
Image,
|
||||||
|
Platform,
|
||||||
|
} from "react-native";
|
||||||
|
import * as Updates from "expo-updates";
|
||||||
|
import { useWindowDimensions } from "react-native";
|
||||||
|
import { ListItem } from "native-base";
|
||||||
|
|
||||||
|
const versionCode = 5.1;
|
||||||
|
|
||||||
|
export const SettingTopPage = ({ navigate, testNFC, updateAndReload }) => {
|
||||||
|
const { width } = useWindowDimensions();
|
||||||
|
return (
|
||||||
|
<View style={{ height: "100%", backgroundColor: "#0099CC" }}>
|
||||||
|
<View style={{ backgroundColor: "#0099CC", flexDirection: "row" }}>
|
||||||
|
<View style={{ flex: 1 }}>
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => navigate("menu")}
|
||||||
|
style={{
|
||||||
|
flexDirection: "column",
|
||||||
|
flex: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: "bold",
|
||||||
|
textAlign: "left",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
color: "white",
|
||||||
|
padding: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
閉じる
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: "bold",
|
||||||
|
textAlign: "center",
|
||||||
|
color: "white",
|
||||||
|
padding: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
アプリの設定画面
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }}></View>
|
||||||
|
</View>
|
||||||
|
<ScrollView style={{ flex: 1, backgroundColor: "#f8f8fc" }}>
|
||||||
|
<View style={{ height: 300, padding: 10 }}>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<Image
|
||||||
|
source={require("../../assets/Header.png")}
|
||||||
|
style={{
|
||||||
|
aspectRatio: 8.08,
|
||||||
|
height: undefined,
|
||||||
|
width: width - 20,
|
||||||
|
borderRadius: 5,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<View style={{ flexDirection: "row", paddingTop: 10 }}>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<Text>内部バージョン: {versionCode}</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
</View>
|
||||||
|
<View style={{ flexDirection: "row", paddingBottom: 10 }}>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<Text>ReleaseChannel: {Updates.channel}</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 14,
|
||||||
|
fontStyle: "italic",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
このアプリは、四国旅客鉄道株式会社の提供する列車走行位置表示システムを利用し、HARUKIN/Xprocessにより一部の機能を拡張したものです。
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 14,
|
||||||
|
fontStyle: "italic",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
このアプリに関するお問い合わせは、HARUKIN/Xprocessにお願いします。くれぐれも四国旅客鉄道株式会社にはお問い合わせしないようにお願いします。
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={{ flex: 1, borderTopWidth: 1, borderColor: "gray" }}>
|
||||||
|
<ListItem
|
||||||
|
style={{ flexDirection: "row" }}
|
||||||
|
onPress={() => navigate("FavoriteSettings")}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
textAlign: "center",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
お気に入り登録の並び替え
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
textAlign: "center",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{">"}
|
||||||
|
</Text>
|
||||||
|
</ListItem>
|
||||||
|
<ListItem
|
||||||
|
style={{ flexDirection: "row" }}
|
||||||
|
onPress={() => navigate("LayoutSettings")}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
textAlign: "center",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
レイアウト設定
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
textAlign: "center",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{">"}
|
||||||
|
</Text>
|
||||||
|
</ListItem>
|
||||||
|
{Platform.OS === "android" ? (
|
||||||
|
<ListItem
|
||||||
|
style={{ flexDirection: "row" }}
|
||||||
|
onPress={() => navigate("WidgetSettings")}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
textAlign: "center",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
ウィジェット設定
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
textAlign: "center",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{">"}
|
||||||
|
</Text>
|
||||||
|
</ListItem>
|
||||||
|
) : null}
|
||||||
|
<ListItem
|
||||||
|
style={{ flexDirection: "row" }}
|
||||||
|
onPress={() =>
|
||||||
|
Linking.openURL(
|
||||||
|
"https://nexcloud.haruk.in/sites/press-harukin/JRShikokuApps/policy"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
textAlign: "center",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
プライバシーポリシー
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
</ListItem>
|
||||||
|
<ListItem
|
||||||
|
style={{ flexDirection: "row" }}
|
||||||
|
onPress={() =>
|
||||||
|
Linking.openURL("https://nexcloud.haruk.in/s/2WFEN5oLPGtrRqT")
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
textAlign: "center",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
開発情報
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
</ListItem>
|
||||||
|
<ListItem
|
||||||
|
style={{ flexDirection: "row" }}
|
||||||
|
onPress={() => Linking.openURL("https://twitter.com/Xprocess_main")}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
textAlign: "center",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
運営Twitter
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
</ListItem>
|
||||||
|
{/* <ListItem style={{ flexDirection: "row" }} onPress={() => testNFC()}>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
textAlign: "center",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
testNFC
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
</ListItem> */}
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={{
|
||||||
|
padding: 10,
|
||||||
|
flexDirection: "row",
|
||||||
|
borderColor: "white",
|
||||||
|
borderWidth: 1,
|
||||||
|
margin: 10,
|
||||||
|
borderRadius: 5,
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
onPress={updateAndReload}
|
||||||
|
>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<Text style={{ fontSize: 25, fontWeight: "bold", color: "white" }}>
|
||||||
|
設定を保存して再読み込み
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
189
components/Settings/WidgetSettings.js
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { View, Text, TouchableOpacity, ScrollView } from "react-native";
|
||||||
|
import { SwitchArea } from "../atom/SwitchArea";
|
||||||
|
import { CheckBox } from "react-native-elements";
|
||||||
|
import { TripleSwitchArea } from "../atom/TripleSwitchArea";
|
||||||
|
import { getWidgetInfo, WidgetPreview } from "react-native-android-widget";
|
||||||
|
import { TraInfoEXWidget } from "../AndroidWidget/TraInfoEXWidget";
|
||||||
|
import {
|
||||||
|
getDelayData,
|
||||||
|
nameToWidget,
|
||||||
|
} from "../AndroidWidget/widget-task-handler";
|
||||||
|
import { ListItem } from "native-base";
|
||||||
|
|
||||||
|
export const WidgetSettings = ({ navigate }) => {
|
||||||
|
const [widgetList, setWidgetList] = useState([]);
|
||||||
|
useEffect(() => {
|
||||||
|
const d = [];
|
||||||
|
Object.keys(nameToWidget).forEach((element) => {
|
||||||
|
const widgetInfo = getWidgetInfo(element);
|
||||||
|
widgetInfo.then((s) => {
|
||||||
|
if (s.length > 0) {
|
||||||
|
s.forEach((elem) => {
|
||||||
|
console.log(elem);
|
||||||
|
d.push(elem);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
setWidgetList(d);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const [time, setTime] = useState(time);
|
||||||
|
const [delayString, setDelayString] = useState(delayString);
|
||||||
|
useEffect(() => {
|
||||||
|
getDelayData().then(({ time, delayString }) => {
|
||||||
|
setTime(time);
|
||||||
|
setDelayString(delayString);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
return (
|
||||||
|
<View style={{ height: "100%", backgroundColor: "#0099CC" }}>
|
||||||
|
<View style={{ backgroundColor: "#0099CC", flexDirection: "row" }}>
|
||||||
|
<View style={{ flex: 1 }}>
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => navigate("settingTopPage")}
|
||||||
|
style={{
|
||||||
|
flexDirection: "column",
|
||||||
|
flex: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: "bold",
|
||||||
|
textAlign: "left",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
color: "white",
|
||||||
|
padding: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
< 設定
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: "bold",
|
||||||
|
textAlign: "center",
|
||||||
|
color: "white",
|
||||||
|
padding: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
ウィジェット設定
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }}></View>
|
||||||
|
</View>
|
||||||
|
<ScrollView style={{ flex: 1, backgroundColor: "white" }}>
|
||||||
|
<View style={{ alignContent: "center", alignItems: "center" }}>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
borderRadius: 15,
|
||||||
|
borderColor: "black",
|
||||||
|
borderWidth: 5,
|
||||||
|
borderStyle: "solid",
|
||||||
|
overflow: "hidden",
|
||||||
|
margin: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{Object.keys(nameToWidget).map((Name) => {
|
||||||
|
const Data = nameToWidget[Name];
|
||||||
|
return (
|
||||||
|
<WidgetPreview
|
||||||
|
renderWidget={() => (
|
||||||
|
<Data time={time} delayString={delayString} />
|
||||||
|
)}
|
||||||
|
width={400}
|
||||||
|
height={250}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<ListItem key={"default"}>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
textAlign: "center",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
marginRight: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
ID
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
textAlign: "center",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
名前
|
||||||
|
</Text>
|
||||||
|
</ListItem>
|
||||||
|
{widgetList.map((widget) => (
|
||||||
|
<ListItem key={widget.widgetId}>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
textAlign: "center",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
marginRight: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{widget.widgetId}
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
textAlign: "center",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{widget.widgetName}
|
||||||
|
</Text>
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</ScrollView>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
backgroundColor: "white",
|
||||||
|
borderWidth: 1,
|
||||||
|
borderStyle: "solid",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
ホーム画面に追加したウィジェットをリストアップします。現状は数を表示するだけですが、ここに各種設定を追加していく予定です。
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SimpleSwitch = ({ bool, setBool, str }) => (
|
||||||
|
<View style={{ flexDirection: "row" }}>
|
||||||
|
<CheckBox
|
||||||
|
checked={bool == "true" ? true : false}
|
||||||
|
checkedColor="red"
|
||||||
|
onPress={() => setBool(bool == "true" ? "false" : "true")}
|
||||||
|
containerStyle={{
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: "#00000000",
|
||||||
|
borderColor: "white",
|
||||||
|
alignContent: "center",
|
||||||
|
}}
|
||||||
|
textStyle={{ fontSize: 20, fontWeight: "normal" }}
|
||||||
|
title={str}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
154
components/Settings/settings.js
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
import React, { useState, useEffect, useLayoutEffect } from "react";
|
||||||
|
import {
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
TouchableOpacity,
|
||||||
|
Linking,
|
||||||
|
ScrollView,
|
||||||
|
Image,
|
||||||
|
useWindowDimensions,
|
||||||
|
ToastAndroid,
|
||||||
|
} from "react-native";
|
||||||
|
import { createStackNavigator } from "@react-navigation/stack";
|
||||||
|
import { TransitionPresets } from "@react-navigation/stack";
|
||||||
|
import * as ExpoFelicaReader from "../../modules/expo-felica-reader/src";
|
||||||
|
import * as Updates from "expo-updates";
|
||||||
|
import StatusbarDetect from "../../StatusbarDetect";
|
||||||
|
import { AS } from "../../storageControl";
|
||||||
|
var Status = StatusbarDetect();
|
||||||
|
import { Switch } from "react-native-elements";
|
||||||
|
import AutoHeightImage from "react-native-auto-height-image";
|
||||||
|
import { SettingTopPage } from "./SettingTopPage";
|
||||||
|
import { LayoutSettings } from "./LayoutSettings";
|
||||||
|
import { FavoriteSettings } from "./FavoriteSettings";
|
||||||
|
import { WidgetSettings } from "./WidgetSettings";
|
||||||
|
|
||||||
|
const Stack = createStackNavigator();
|
||||||
|
export default function Setting(props) {
|
||||||
|
const {
|
||||||
|
navigation: { navigate },
|
||||||
|
} = props;
|
||||||
|
const [iconSetting, setIconSetting] = useState(false);
|
||||||
|
const [mapSwitch, setMapSwitch] = useState(false);
|
||||||
|
const [stationMenu, setStationMenu] = useState(false);
|
||||||
|
const [usePDFView, setUsePDFView] = useState(false);
|
||||||
|
const [trainMenu, setTrainMenu] = useState(false);
|
||||||
|
const [trainPosition, setTrainPosition] = useState(false);
|
||||||
|
const [headerSize, setHeaderSize] = useState("default");
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
AS.getItem("iconSwitch").then(setIconSetting);
|
||||||
|
AS.getItem("mapSwitch").then(setMapSwitch);
|
||||||
|
AS.getItem("stationSwitch").then(setStationMenu);
|
||||||
|
AS.getItem("usePDFView").then(setUsePDFView);
|
||||||
|
AS.getItem("trainSwitch").then(setTrainMenu);
|
||||||
|
AS.getItem("trainPositionSwitch").then(setTrainPosition);
|
||||||
|
AS.getItem("headerSize").then(setHeaderSize);
|
||||||
|
}, []);
|
||||||
|
const testNFC = async () => {
|
||||||
|
const result = await ExpoFelicaReader.scan();
|
||||||
|
alert(result);
|
||||||
|
};
|
||||||
|
const updateAndReload = () => {
|
||||||
|
Promise.all([
|
||||||
|
AS.setItem("iconSwitch", iconSetting.toString()),
|
||||||
|
AS.setItem("mapSwitch", mapSwitch.toString()),
|
||||||
|
AS.setItem("stationSwitch", stationMenu.toString()),
|
||||||
|
AS.setItem("usePDFView", usePDFView.toString()),
|
||||||
|
AS.setItem("trainSwitch", trainMenu.toString()),
|
||||||
|
AS.setItem("trainPositionSwitch", trainPosition.toString()),
|
||||||
|
AS.setItem("headerSize", headerSize),
|
||||||
|
]).then(() => Updates.reloadAsync());
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Stack.Navigator>
|
||||||
|
<Stack.Screen
|
||||||
|
name="settingTopPage"
|
||||||
|
options={{
|
||||||
|
gestureEnabled: false,
|
||||||
|
...TransitionPresets.SlideFromRightIOS,
|
||||||
|
cardOverlayEnabled: true,
|
||||||
|
headerTransparent: true,
|
||||||
|
headerShown: false,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{(props) => (
|
||||||
|
<SettingTopPage
|
||||||
|
{...props}
|
||||||
|
navigate={navigate}
|
||||||
|
iconSetting={iconSetting}
|
||||||
|
setIconSetting={setIconSetting}
|
||||||
|
mapSwitch={mapSwitch}
|
||||||
|
setMapSwitch={setMapSwitch}
|
||||||
|
stationMenu={stationMenu}
|
||||||
|
setStationMenu={setStationMenu}
|
||||||
|
usePDFView={usePDFView}
|
||||||
|
setUsePDFView={setUsePDFView}
|
||||||
|
trainMenu={trainMenu}
|
||||||
|
setTrainMenu={setTrainMenu}
|
||||||
|
trainPosition={trainPosition}
|
||||||
|
setTrainPosition={setTrainPosition}
|
||||||
|
testNFC={testNFC}
|
||||||
|
updateAndReload={updateAndReload}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Stack.Screen>
|
||||||
|
<Stack.Screen
|
||||||
|
name="LayoutSettings"
|
||||||
|
options={{
|
||||||
|
gestureEnabled: true,
|
||||||
|
...TransitionPresets.SlideFromRightIOS,
|
||||||
|
cardOverlayEnabled: true,
|
||||||
|
headerTransparent: true,
|
||||||
|
headerShown: false,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{(props) => (
|
||||||
|
<LayoutSettings
|
||||||
|
{...props}
|
||||||
|
navigate={navigate}
|
||||||
|
iconSetting={iconSetting}
|
||||||
|
setIconSetting={setIconSetting}
|
||||||
|
mapSwitch={mapSwitch}
|
||||||
|
setMapSwitch={setMapSwitch}
|
||||||
|
stationMenu={stationMenu}
|
||||||
|
setStationMenu={setStationMenu}
|
||||||
|
usePDFView={usePDFView}
|
||||||
|
setUsePDFView={setUsePDFView}
|
||||||
|
trainMenu={trainMenu}
|
||||||
|
setTrainMenu={setTrainMenu}
|
||||||
|
trainPosition={trainPosition}
|
||||||
|
setTrainPosition={setTrainPosition}
|
||||||
|
testNFC={testNFC}
|
||||||
|
updateAndReload={updateAndReload}
|
||||||
|
headerSize={headerSize}
|
||||||
|
setHeaderSize={setHeaderSize}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Stack.Screen>
|
||||||
|
<Stack.Screen
|
||||||
|
name="WidgetSettings"
|
||||||
|
options={{
|
||||||
|
gestureEnabled: true,
|
||||||
|
...TransitionPresets.SlideFromRightIOS,
|
||||||
|
cardOverlayEnabled: true,
|
||||||
|
headerTransparent: true,
|
||||||
|
headerShown: false,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{(props) => <WidgetSettings {...props} navigate={navigate} />}
|
||||||
|
</Stack.Screen>
|
||||||
|
<Stack.Screen
|
||||||
|
name="FavoriteSettings"
|
||||||
|
options={{
|
||||||
|
gestureEnabled: true,
|
||||||
|
...TransitionPresets.SlideFromRightIOS,
|
||||||
|
cardOverlayEnabled: true,
|
||||||
|
headerTransparent: true,
|
||||||
|
headerShown: false,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{(props) => <FavoriteSettings {...props} navigate={navigate} />}
|
||||||
|
</Stack.Screen>
|
||||||
|
</Stack.Navigator>
|
||||||
|
);
|
||||||
|
}
|
72
components/atom/FavoriteListItem.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { View, Text, TouchableOpacity } from "react-native";
|
||||||
|
import lineColorList from "../../assets/originData/lineColorList";
|
||||||
|
|
||||||
|
export const FavoriteListItem = ({ currentStation, children, onPress }) => {
|
||||||
|
const lineIDs = [];
|
||||||
|
const EachIDs = [];
|
||||||
|
currentStation.forEach((d) => {
|
||||||
|
if (!d.StationNumber) return;
|
||||||
|
const textArray = d.StationNumber.split("");
|
||||||
|
lineIDs.push(textArray.filter((s) => "A" < s && s < "Z").join(""));
|
||||||
|
EachIDs.push(textArray.filter((s) => "0" <= s && s <= "9").join(""));
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
style={{ flexDirection: "row", backgroundColor: "white" }}
|
||||||
|
onPress={onPress}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
width: 35,
|
||||||
|
position: "relative",
|
||||||
|
marginHorizontal: 15,
|
||||||
|
flexDirection: "row",
|
||||||
|
height: "101%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{lineIDs.map((lineID, index) => (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
backgroundColor: lineColorList[lineID],
|
||||||
|
flex: 1,
|
||||||
|
}}
|
||||||
|
key={lineID}
|
||||||
|
>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
color: "white",
|
||||||
|
textAlign: "center",
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: "bold",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{lineIDs[index]}
|
||||||
|
{"\n"}
|
||||||
|
{EachIDs[index]}
|
||||||
|
</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
padding: 8,
|
||||||
|
flexDirection: "row",
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderBottomColor: "#f0f0f0",
|
||||||
|
flex: 1,
|
||||||
|
alignContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={{ fontSize: 20 }}>{currentStation[0].Station_JP}</Text>
|
||||||
|
<View style={{ flex: 1 }} />
|
||||||
|
{children}
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
};
|
58
components/atom/SimpleSwitch.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import {
|
||||||
|
useWindowDimensions,
|
||||||
|
View,
|
||||||
|
TouchableOpacity,
|
||||||
|
Text,
|
||||||
|
Image,
|
||||||
|
LayoutAnimation,
|
||||||
|
} from "react-native";
|
||||||
|
export const SimpleSwitch = ({
|
||||||
|
bool,
|
||||||
|
setBool,
|
||||||
|
color,
|
||||||
|
value,
|
||||||
|
image = require("../../assets/icons.png"),
|
||||||
|
subText = "",
|
||||||
|
}) => {
|
||||||
|
const { width } = useWindowDimensions();
|
||||||
|
return (
|
||||||
|
<View style={{ flex: 1 }}>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={{
|
||||||
|
backgroundColor: bool == value.toString() ? color : null,
|
||||||
|
padding: 5,
|
||||||
|
borderRadius: 5,
|
||||||
|
margin: 10,
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
flexDirection: "row",
|
||||||
|
flex: 1,
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||||
|
setBool(value.toString());
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
source={image}
|
||||||
|
style={{
|
||||||
|
aspectRatio: 1,
|
||||||
|
height: undefined,
|
||||||
|
width: "100%",
|
||||||
|
borderRadius: 5,
|
||||||
|
}}
|
||||||
|
resizeMethod="scale"
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 14,
|
||||||
|
textAlign: "center",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{subText}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
56
components/atom/SwitchArea.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { View, Text, Image, TouchableOpacity } from "react-native";
|
||||||
|
import { SimpleSwitch } from "./SimpleSwitch";
|
||||||
|
export const SwitchArea = ({
|
||||||
|
str,
|
||||||
|
bool,
|
||||||
|
setBool,
|
||||||
|
falseImage,
|
||||||
|
trueImage,
|
||||||
|
falseText,
|
||||||
|
trueText,
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "column",
|
||||||
|
padding: 10,
|
||||||
|
backgroundColor: "#00000010",
|
||||||
|
borderRadius: 10,
|
||||||
|
margin: 5,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 25,
|
||||||
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
textAlign: "center",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
fontWeight: "bold",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{str}
|
||||||
|
</Text>
|
||||||
|
<View style={{ flexDirection: "row", padding: 10 }}>
|
||||||
|
<SimpleSwitch
|
||||||
|
bool={bool}
|
||||||
|
setBool={setBool}
|
||||||
|
color="red"
|
||||||
|
value={false}
|
||||||
|
image={falseImage}
|
||||||
|
subText={falseText}
|
||||||
|
/>
|
||||||
|
<SimpleSwitch
|
||||||
|
bool={bool}
|
||||||
|
setBool={setBool}
|
||||||
|
color="red"
|
||||||
|
value={true}
|
||||||
|
image={trueImage}
|
||||||
|
subText={trueText}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
{bool == "true" && children}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
52
components/atom/TripleSwitchArea.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { View, Text, Image, TouchableOpacity } from "react-native";
|
||||||
|
import { SimpleSwitch } from "./SimpleSwitch";
|
||||||
|
export const TripleSwitchArea = ({
|
||||||
|
str,
|
||||||
|
bool,
|
||||||
|
setBool,
|
||||||
|
firstItem: { firstImage, firstText, firstValue },
|
||||||
|
secondItem: { secondImage, secondText, secondValue },
|
||||||
|
thirdItem: { thirdImage, thirdText, thirdValue },
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<View style={{ flexDirection: "column", padding: 10 }}>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
alignItems: "center",
|
||||||
|
alignContent: "center",
|
||||||
|
textAlign: "center",
|
||||||
|
textAlignVertical: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{str}
|
||||||
|
</Text>
|
||||||
|
<View style={{ flexDirection: "row", padding: 10 }}>
|
||||||
|
<SimpleSwitch
|
||||||
|
bool={bool}
|
||||||
|
setBool={setBool}
|
||||||
|
color="red"
|
||||||
|
value={firstValue}
|
||||||
|
image={firstImage}
|
||||||
|
subText={firstText}
|
||||||
|
/>
|
||||||
|
<SimpleSwitch
|
||||||
|
bool={bool}
|
||||||
|
setBool={setBool}
|
||||||
|
color="red"
|
||||||
|
value={secondValue}
|
||||||
|
image={secondImage}
|
||||||
|
subText={secondText}
|
||||||
|
/>
|
||||||
|
<SimpleSwitch
|
||||||
|
bool={bool}
|
||||||
|
setBool={setBool}
|
||||||
|
color="red"
|
||||||
|
value={thirdValue}
|
||||||
|
image={thirdImage}
|
||||||
|
subText={thirdText}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
@ -1,245 +0,0 @@
|
|||||||
import React, { useState, useEffect, useLayoutEffect } from "react";
|
|
||||||
import { View, Text, TouchableOpacity, Linking } from "react-native";
|
|
||||||
import * as ExpoFelicaReader from "../modules/expo-felica-reader/src";
|
|
||||||
import * as Updates from "expo-updates";
|
|
||||||
import StatusbarDetect from "../StatusbarDetect";
|
|
||||||
import { AS } from "../storageControl";
|
|
||||||
var Status = StatusbarDetect();
|
|
||||||
import { Switch } from "react-native-elements";
|
|
||||||
|
|
||||||
export default function Setting() {
|
|
||||||
const [iconSetting, setIconSetting] = useState(false);
|
|
||||||
const [mapSwitch, setMapSwitch] = useState(false);
|
|
||||||
const [stationMenu, setStationMenu] = useState(false);
|
|
||||||
const [usePDFView, setUsePDFView] = useState(false);
|
|
||||||
const [trainMenu, setTrainMenu] = useState(false);
|
|
||||||
const [trainPosition, setTrainPosition] = useState(false);
|
|
||||||
useLayoutEffect(() => {
|
|
||||||
AS.getItem("iconSwitch").then(setIconSetting);
|
|
||||||
AS.getItem("mapSwitch").then(setMapSwitch);
|
|
||||||
AS.getItem("stationSwitch").then(setStationMenu);
|
|
||||||
AS.getItem("usePDFView").then(setUsePDFView);
|
|
||||||
AS.getItem("trainSwitch").then(setTrainMenu);
|
|
||||||
AS.getItem("trainPositionSwitch").then(setTrainPosition);
|
|
||||||
}, []);
|
|
||||||
const testNFC = async () => {
|
|
||||||
const resulit = await ExpoFelicaReader.scan();
|
|
||||||
alert(resulit);
|
|
||||||
};
|
|
||||||
const updateAndReload = () => {
|
|
||||||
Promise.all([
|
|
||||||
AS.setItem("iconSwitch", iconSetting.toString()),
|
|
||||||
AS.setItem("mapSwitch", mapSwitch.toString()),
|
|
||||||
AS.setItem("stationSwitch", stationMenu.toString()),
|
|
||||||
AS.setItem("usePDFView", usePDFView.toString()),
|
|
||||||
AS.setItem("trainSwitch", trainMenu.toString()),
|
|
||||||
AS.setItem("trainPositionSwitch", trainPosition.toString()),
|
|
||||||
]).then(() => {
|
|
||||||
Updates.reloadAsync();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<View style={{ height: "100%", backgroundColor: "#0099CC" }}>
|
|
||||||
<View style={{ flex: 1, backgroundColor: "white" }}>
|
|
||||||
<View style={{ backgroundColor: "#0099CC" }}>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 30,
|
|
||||||
fontWeight: "bold",
|
|
||||||
textAlign: "center",
|
|
||||||
color: "white",
|
|
||||||
padding: 10,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
設定画面
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View style={{ flex: 1 }}>
|
|
||||||
<View style={{ flexDirection: "row", padding: 10 }}>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 25,
|
|
||||||
alignItems: "center",
|
|
||||||
alignContent: "center",
|
|
||||||
textAlign: "center",
|
|
||||||
textAlignVertical: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
列車アイコンを表示する
|
|
||||||
</Text>
|
|
||||||
<View style={{ flex: 1 }} />
|
|
||||||
<SimpleSwitch
|
|
||||||
bool={iconSetting}
|
|
||||||
setBool={setIconSetting}
|
|
||||||
color="red"
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
<View style={{ flexDirection: "row", padding: 10 }}>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 25,
|
|
||||||
alignItems: "center",
|
|
||||||
alignContent: "center",
|
|
||||||
textAlign: "center",
|
|
||||||
textAlignVertical: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
マップを表示する(beta)
|
|
||||||
</Text>
|
|
||||||
<View style={{ flex: 1 }} />
|
|
||||||
<SimpleSwitch bool={mapSwitch} setBool={setMapSwitch} color="red" />
|
|
||||||
</View>
|
|
||||||
<View style={{ flexDirection: "row", padding: 10 }}>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 25,
|
|
||||||
alignItems: "center",
|
|
||||||
alignContent: "center",
|
|
||||||
textAlign: "center",
|
|
||||||
textAlignVertical: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
駅メニューを表示
|
|
||||||
</Text>
|
|
||||||
<View style={{ flex: 1 }} />
|
|
||||||
<SimpleSwitch
|
|
||||||
bool={stationMenu}
|
|
||||||
setBool={setStationMenu}
|
|
||||||
color="red"
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
<View style={{ flexDirection: "row", padding: 10 }}>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 25,
|
|
||||||
alignItems: "center",
|
|
||||||
alignContent: "center",
|
|
||||||
textAlign: "center",
|
|
||||||
textAlignVertical: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
時刻表PDFをアプリ外で表示
|
|
||||||
</Text>
|
|
||||||
<View style={{ flex: 1 }} />
|
|
||||||
<SimpleSwitch
|
|
||||||
bool={usePDFView}
|
|
||||||
setBool={setUsePDFView}
|
|
||||||
color="red"
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
<View style={{ flexDirection: "row", padding: 10 }}>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 25,
|
|
||||||
alignItems: "center",
|
|
||||||
alignContent: "center",
|
|
||||||
textAlign: "center",
|
|
||||||
textAlignVertical: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
列車メニュー
|
|
||||||
</Text>
|
|
||||||
<View style={{ flex: 1 }} />
|
|
||||||
<SimpleSwitch bool={trainMenu} setBool={setTrainMenu} color="red" />
|
|
||||||
</View>
|
|
||||||
<View style={{ flexDirection: "row", padding: 10 }}>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 25,
|
|
||||||
alignItems: "center",
|
|
||||||
alignContent: "center",
|
|
||||||
textAlign: "center",
|
|
||||||
textAlignVertical: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
→列車現在位置表示(alpha)
|
|
||||||
</Text>
|
|
||||||
<View style={{ flex: 1 }} />
|
|
||||||
<SimpleSwitch
|
|
||||||
bool={trainPosition}
|
|
||||||
setBool={setTrainPosition}
|
|
||||||
color="red"
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
<View style={{ flexDirection: "row", padding: 10 }}>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 25,
|
|
||||||
alignItems: "center",
|
|
||||||
alignContent: "center",
|
|
||||||
textAlign: "center",
|
|
||||||
textAlignVertical: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
内部バージョン: 5.0.3.2
|
|
||||||
</Text>
|
|
||||||
<View style={{ flex: 1 }} />
|
|
||||||
</View>
|
|
||||||
<TouchableOpacity
|
|
||||||
style={{ flexDirection: "row", padding: 10 }}
|
|
||||||
//onPress={testNFC}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 25,
|
|
||||||
alignItems: "center",
|
|
||||||
alignContent: "center",
|
|
||||||
textAlign: "center",
|
|
||||||
textAlignVertical: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
releaseChannel: {Updates.channel}
|
|
||||||
</Text>
|
|
||||||
<View style={{ flex: 1 }} />
|
|
||||||
</TouchableOpacity>
|
|
||||||
<TouchableOpacity
|
|
||||||
style={{ flexDirection: "row", padding: 10 }}
|
|
||||||
onPress={() =>
|
|
||||||
Linking.openURL(
|
|
||||||
"https://nexcloud.haruk.in/sites/press-harukin/JRShikokuApps/policy"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
fontSize: 25,
|
|
||||||
alignItems: "center",
|
|
||||||
alignContent: "center",
|
|
||||||
textAlign: "center",
|
|
||||||
textAlignVertical: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
プライバシーポリシー
|
|
||||||
</Text>
|
|
||||||
<View style={{ flex: 1 }} />
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
<TouchableOpacity
|
|
||||||
style={{
|
|
||||||
padding: 10,
|
|
||||||
flexDirection: "row",
|
|
||||||
borderColor: "white",
|
|
||||||
borderWidth: 1,
|
|
||||||
margin: 10,
|
|
||||||
borderRadius: 5,
|
|
||||||
alignItems: "center",
|
|
||||||
}}
|
|
||||||
onPress={updateAndReload}
|
|
||||||
>
|
|
||||||
<View style={{ flex: 1 }} />
|
|
||||||
<Text style={{ fontSize: 25, fontWeight: "bold", color: "white" }}>
|
|
||||||
設定を保存して再読み込み
|
|
||||||
</Text>
|
|
||||||
<View style={{ flex: 1 }} />
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const SimpleSwitch = ({ bool, setBool, color }) => (
|
|
||||||
<Switch
|
|
||||||
value={bool == "true" ? true : false}
|
|
||||||
color={bool == "true" ? color : null}
|
|
||||||
onValueChange={(value) => setBool(value.toString())}
|
|
||||||
/>
|
|
||||||
);
|
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useRef } from "react";
|
import React, { useRef, useMemo } from "react";
|
||||||
import { View, Text, TouchableOpacity, Linking } from "react-native";
|
import { View, Text, TouchableOpacity, Linking } from "react-native";
|
||||||
import MapView, { Marker } from "react-native-maps";
|
import MapView, { Marker } from "react-native-maps";
|
||||||
import { MaterialCommunityIcons } from "@expo/vector-icons";
|
import { MaterialCommunityIcons } from "@expo/vector-icons";
|
||||||
@ -8,6 +8,36 @@ export default function TrainMenu({ stationData, style }) {
|
|||||||
const { webview } = useCurrentTrain();
|
const { webview } = useCurrentTrain();
|
||||||
const mapRef = useRef();
|
const mapRef = useRef();
|
||||||
const { navigate } = useNavigation();
|
const { navigate } = useNavigation();
|
||||||
|
const stationPin = useMemo(
|
||||||
|
() =>
|
||||||
|
Object.keys(stationData).map((d, indexBase) =>
|
||||||
|
stationData[d].map((D, index) => {
|
||||||
|
if (!D.StationMap) return null;
|
||||||
|
const latlng = D.StationMap.replace(
|
||||||
|
"https://www.google.co.jp/maps/place/",
|
||||||
|
""
|
||||||
|
).split(",");
|
||||||
|
if (latlng.length == 0) return null;
|
||||||
|
return (
|
||||||
|
<Marker
|
||||||
|
key={index + indexBase}
|
||||||
|
coordinate={{
|
||||||
|
latitude: parseFloat(latlng[0]),
|
||||||
|
longitude: parseFloat(latlng[1]),
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
webview.current?.injectJavaScript(
|
||||||
|
`MoveDisplayStation('${d}_${D.MyStation}_${D.Station_JP}');
|
||||||
|
setStrings();`
|
||||||
|
);
|
||||||
|
if (navigate) navigate("Apps");
|
||||||
|
}}
|
||||||
|
></Marker>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
),
|
||||||
|
[stationData]
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<View style={{ height: "100%", backgroundColor: "#0099CC", ...style }}>
|
<View style={{ height: "100%", backgroundColor: "#0099CC", ...style }}>
|
||||||
<MapView
|
<MapView
|
||||||
@ -26,32 +56,7 @@ export default function TrainMenu({ stationData, style }) {
|
|||||||
longitudeDelta: 1.8,
|
longitudeDelta: 1.8,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{stationData &&
|
{stationPin}
|
||||||
Object.keys(stationData).map((d) =>
|
|
||||||
stationData[d].map((D, index) => {
|
|
||||||
if (!D.StationMap) return null;
|
|
||||||
const latlng = D.StationMap.replace(
|
|
||||||
"https://www.google.co.jp/maps/place/",
|
|
||||||
""
|
|
||||||
).split(",");
|
|
||||||
if (latlng.length == 0) return null;
|
|
||||||
return (
|
|
||||||
<Marker
|
|
||||||
key={index}
|
|
||||||
coordinate={{
|
|
||||||
latitude: parseFloat(latlng[0]),
|
|
||||||
longitude: parseFloat(latlng[1]),
|
|
||||||
}}
|
|
||||||
onPress={() => {
|
|
||||||
webview.current?.injectJavaScript(
|
|
||||||
`MoveDisplayStation('${d}_${D.MyStation}_${D.Station_JP}')`
|
|
||||||
);
|
|
||||||
if (navigate) navigate("Apps");
|
|
||||||
}}
|
|
||||||
></Marker>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
)}
|
|
||||||
</MapView>
|
</MapView>
|
||||||
{navigate && (
|
{navigate && (
|
||||||
<View style={{ flexDirection: "row" }}>
|
<View style={{ flexDirection: "row" }}>
|
||||||
|
@ -28,6 +28,18 @@ export default function Sign(props) {
|
|||||||
});
|
});
|
||||||
setTestButtonStatus(isFavorite.length == 0 ? false : true);
|
setTestButtonStatus(isFavorite.length == 0 ? false : true);
|
||||||
}, [favoriteStation, currentStation]);
|
}, [favoriteStation, currentStation]);
|
||||||
|
useEffect(() => {
|
||||||
|
const isFavorite = favoriteStation.filter((d) => {
|
||||||
|
const compare = JSON.stringify(d);
|
||||||
|
const current = JSON.stringify(currentStation);
|
||||||
|
if (compare === current) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setTestButtonStatus(isFavorite.length == 0 ? false : true);
|
||||||
|
}, [favoriteStation, currentStation]);
|
||||||
|
|
||||||
useInterval(() => {
|
useInterval(() => {
|
||||||
if (currentStation.length == 1) {
|
if (currentStation.length == 1) {
|
||||||
|
@ -1 +1 @@
|
|||||||
export const news = "2024-3-10";
|
export const news = "2024-4-6";
|
||||||
|
@ -22,14 +22,14 @@ export const DeviceOrientationChangeProvider = ({ children }) => {
|
|||||||
//ScreenOrientation.unlockAsync();
|
//ScreenOrientation.unlockAsync();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
if (height / width > 1.5) {
|
// if (height / width > 1.5) {
|
||||||
setIsLandscape(false);
|
// setIsLandscape(false);
|
||||||
}
|
// }
|
||||||
if (height / width < 1.5) {
|
// if (height / width < 1.5) {
|
||||||
//setIsLandscape(true);
|
// setIsLandscape(true);
|
||||||
}
|
// }
|
||||||
}, [height, width]);
|
// }, [height, width]);
|
||||||
return (
|
return (
|
||||||
<DeviceOrientationChange.Provider value={{ isLandscape, setIsLandscape }}>
|
<DeviceOrientationChange.Provider value={{ isLandscape, setIsLandscape }}>
|
||||||
{children}
|
{children}
|
||||||
|