Compare commits

..

29 Commits

Author SHA1 Message Date
harukin-expo-dev-env
499e895165 Merge commit '0aaf171477659e632a23aeb6af39e83d5acf70c2' into develop 2025-02-09 03:19:30 +00:00
harukin-expo-dev-env
0aaf171477 Merge commit 'ec8c0559a08e37fad9b32586f14c2daa3250aa50' into patch/5.0.x 2025-02-09 03:19:13 +00:00
harukin-expo-dev-env
ec8c0559a0 LED対応 2025-02-09 03:18:34 +00:00
harukin-expo-dev-env
a6b676fe9d Merge commit 'a785508b45aa296454cf19f5c95892703cdfaa6c' into develop 2025-02-08 10:46:35 +00:00
harukin-expo-dev-env
a785508b45 新型テキストシステムが一通り完成 2025-02-08 10:44:50 +00:00
harukin-expo-dev-env
aa0ff60e37 新テキストシステムのプロトタイプ作成 2025-02-08 09:47:33 +00:00
harukin-expo-dev-env
5204231ccb インテント整理 2025-02-08 09:00:43 +00:00
harukin-expo-dev-env
ea4fa46fe0 文字列管理を分離 2025-02-08 08:57:18 +00:00
harukin-expo-dev-env
8e0f04c5b2 アイコン設定をfunctionに押し込み 2025-02-08 08:46:46 +00:00
harukin-expo-dev-env
e7cecd38c1 内容の結合 2025-02-08 08:23:12 +00:00
harukin-expo-dev-env
3976552e43 要素結合 2025-02-08 08:06:04 +00:00
harukin-expo-dev-env
79ba9748a6 Merge commit '8967baf12144fcf029cba7d18ad5af8a4d680848' into develop 2025-02-08 07:59:36 +00:00
harukin-expo-dev-env
8967baf121 地図を表示するように変更 2025-02-07 14:22:25 +00:00
harukin-expo-dev-env
0d4dcee4b6 Merge commit 'f4dca5cd87eafa127d639720297c4dcf4f1646b5' into develop 2025-02-05 14:15:58 +00:00
harukin-expo-dev-env
f4dca5cd87 修正 2025-02-05 14:15:52 +00:00
harukin-expo-dev-env
9df1fc1ed2 Merge commit '8818addecd906d2172c3edd0e47a67857d938bd2' into develop 2025-02-05 13:19:06 +00:00
harukin-expo-dev-env
8818addecd 将来的に使うライブラリの追加 2025-02-05 13:18:48 +00:00
harukin-expo-dev-env
1a1e9c417b 調整 2025-02-04 12:49:07 +00:00
harukin-expo-dev-env
e04cfb9a8b add new action 2025-02-04 12:18:54 +00:00
harukin-expo-dev-env
ceffd2da7e Merge commit 'ef16d9ed6b0b53d69ed2e60cc384623c78cc71a6' into develop 2025-02-01 10:36:22 +00:00
harukin-expo-dev-env
ef16d9ed6b iosでフリーズするのでtimeout追加 2025-02-01 10:36:11 +00:00
harukin-expo-dev-env
cbeba9f269 Merge commit '77328bf97acfac463b198d6cea559a14873f6d46' into develop 2025-01-30 13:28:35 +00:00
harukin-expo-dev-env
77328bf97a 修正 2025-01-30 13:27:15 +00:00
harukin-expo-dev-env
a979fee6ec アイコンの設定更新 2025-01-28 13:47:46 +00:00
harukin-expo-dev-env
2176b5511a 6.0でのデフォルト変更 2025-01-22 13:23:32 +00:00
harukin-expo-dev-env
837bd6eb4f バグとレイアウトの崩壊修正 2025-01-22 13:20:45 +00:00
harukin-expo-dev-env
f9e3b1d658 暴走するバグを修正 2025-01-22 13:20:02 +00:00
harukin-expo-dev-env
892d567991 ts化 2025-01-22 12:03:50 +00:00
harukin-expo-dev-env
294b95967f 6.0 update init 2025-01-22 11:34:05 +00:00
93 changed files with 4939 additions and 6596 deletions

35
Apps.js
View File

@ -14,50 +14,51 @@ export function AppContainer() {
const Tab = createBottomTabNavigator(); const Tab = createBottomTabNavigator();
const { areaInfo, areaIconBadgeText, isInfo } = useAreaInfo(); const { areaInfo, areaIconBadgeText, isInfo } = useAreaInfo();
const navigationRef = React.useRef(); const navigationRef = React.useRef();
const getTabProps = (name, label, icon, iconFamily, tabBarBadge, style) => ({ const getTabProps = (name, label, icon, iconFamily, tabBarBadge, isInfo) => ({
name, name,
options: { options: {
tabBarLabel: label, tabBarLabel: label,
headerTransparent: true, headerShown: false,
gestureEnabled: true, gestureEnabled: true,
tabBarIcon: initIcon(icon, iconFamily), tabBarIcon: initIcon(icon, iconFamily,tabBarBadge,isInfo),
tabBarBadge,
tabBarBadgeStyle: style,
}, },
}); });
const [fontLoaded, error] = useFonts({ const [fontLoaded, error] = useFonts({
"JR-Nishi": require("./assets/fonts/jr-nishi.otf"), "JR-Nishi": require("./assets/fonts/jr-nishi.otf"),
"Zou": require("./assets/fonts/DelaGothicOne-Regular.ttf"), Zou: require("./assets/fonts/DelaGothicOne-Regular.ttf"),
}); });
return ( return (
<NavigationContainer name="Root" style={{ flex: 1 }} ref={navigationRef}> <NavigationContainer ref={navigationRef}>
<Tab.Navigator <Tab.Navigator
tabBarOptions={{ keyboardHidesTabBar: Platform.OS === "android" }} tabBarOptions={{ keyboardHidesTabBar: Platform.OS === "android" }}
initialRouteName="menuPage" initialRouteName="topMenu"
screenOptions={{
lazy: false,
animation: "shift",
}}
detachInactiveScreens={false}
lazy={false} lazy={false}
> >
<Tab.Screen <Tab.Screen
{...getTabProps("login", "位置情報", "barchart", "AntDesign")} {...getTabProps("positions", "走行位置", "barchart", "AntDesign")}
children={(props) => <Top {...props} navigationRef={navigationRef} />} component={Top}
/> />
<Tab.Screen <Tab.Screen
{...getTabProps("menuPage", "リンク", "radio", "Ionicons")} {...getTabProps("topMenu", "トップメニュー", "radio", "Ionicons")}
component={MenuPage} component={MenuPage}
/> />
<Tab.Screen <Tab.Screen
{...getTabProps( {...getTabProps(
"home", "information",
"運行情報", "運行情報",
"train", "train",
"Ionicons", "Ionicons",
areaInfo ? areaIconBadgeText : undefined, areaInfo ? areaIconBadgeText : undefined,
isInfo && { isInfo
backgroundColor: "#00b8ff",
color: "white",
}
)} )}
children={(props) => <TNDView {...props} />} children={TNDView}
/> />
</Tab.Navigator> </Tab.Navigator>
</NavigationContainer> </NavigationContainer>

View File

@ -1,12 +1,11 @@
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { import { createStackNavigator } from "@react-navigation/stack";
createStackNavigator, import { CommonActions } from "@react-navigation/native";
TransitionPresets,
} from "@react-navigation/stack";
import { AS } from "./storageControl"; import { AS } from "./storageControl";
import TrainBase from "./components/trainbaseview"; import TrainBase from "./components/trainbaseview";
import HowTo from "./howto"; import HowTo from "./howto";
import Menu from "./menu"; import Menu from "./menu";
import News from "./components/news";
import Setting from "./components/Settings/settings"; 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";
@ -14,6 +13,7 @@ import CurrentTrainListView from "./components/CurrentTrainListView";
import AllTrainDiagramView from "./components/AllTrainDiagramView"; import AllTrainDiagramView from "./components/AllTrainDiagramView";
import { useCurrentTrain } from "./stateBox/useCurrentTrain"; import { useCurrentTrain } from "./stateBox/useCurrentTrain";
import { useNavigation } from "@react-navigation/native"; import { useNavigation } from "@react-navigation/native";
import { news } from "./config/newsUpdate";
const Stack = createStackNavigator(); const Stack = createStackNavigator();
export function MenuPage() { export function MenuPage() {
@ -24,12 +24,19 @@ export function MenuPage() {
useEffect(() => { useEffect(() => {
AS.getItem("startPage") AS.getItem("startPage")
.then((res) => { .then((res) => {
if (res == "true") navigation.navigate("login"); if (res == "true") navigation.navigate("positions");
}) })
.catch((e) => { .catch((e) => {
//6.0以降false //6.0以降false
AS.setItem("startPage", "true"); AS.setItem("startPage", "false");
}); });
//ニュース表示
AS.getItem("status")
.then((d) => {
if (d != news) navigation.navigate("topMenu", { screen: "news" });
})
.catch(() => navigation.navigate("topMenu", { screen: "news" }));
}, []); }, []);
useEffect(() => { useEffect(() => {
const unsubscribe = addListener("tabPress", (e) => { const unsubscribe = addListener("tabPress", (e) => {
@ -56,6 +63,7 @@ export function MenuPage() {
}} }}
children={() => <Menu getCurrentTrain={getCurrentTrain} />} children={() => <Menu getCurrentTrain={getCurrentTrain} />}
/> />
<Stack.Screen name="news" options={optionData} component={News} />
<Stack.Screen <Stack.Screen
name="setting" name="setting"
options={{ options={{
@ -67,13 +75,8 @@ export function MenuPage() {
/> />
<Stack.Screen <Stack.Screen
name="trainbase" name="trainbase"
options={{ ...optionData, gestureResponseDistance: { vertical: 300 } }} options={{ ...optionData }}
children={(props) => <TrainBase {...props} />} component={TrainBase}
/>
<Stack.Screen
name="currentTrainIDList"
options={{ ...optionData, gestureResponseDistance: { vertical: 300 } }}
component={CurrentTrainListView}
/> />
<Stack.Screen <Stack.Screen
name="AllTrainIDList" name="AllTrainIDList"

64
Top.js
View File

@ -1,8 +1,6 @@
import React, { useEffect, useRef, useState } from "react"; import React, { useEffect } from "react";
import { import { createStackNavigator } from "@react-navigation/stack";
createStackNavigator, import { useNavigation } from "@react-navigation/native";
TransitionPresets,
} from "@react-navigation/stack";
import Apps from "./components/Apps"; import Apps from "./components/Apps";
import TrainBase from "./components/trainbaseview"; import TrainBase from "./components/trainbaseview";
import HowTo from "./howto"; import HowTo from "./howto";
@ -10,91 +8,67 @@ import News from "./components/news";
import TrainMenu from "./components/trainMenu"; import TrainMenu from "./components/trainMenu";
import FavoriteList from "./components/FavoriteList"; import FavoriteList from "./components/FavoriteList";
import { optionData } from "./lib/stackOption"; import { optionData } from "./lib/stackOption";
import { useNavigation } from "@react-navigation/native";
import { useCurrentTrain } from "./stateBox/useCurrentTrain"; import { useCurrentTrain } from "./stateBox/useCurrentTrain";
import { useTrainMenu } from "./stateBox/useTrainMenu"; import { useTrainMenu } from "./stateBox/useTrainMenu";
import { AS } from "./storageControl"; import { AS } from "./storageControl";
import { news } from "./config/newsUpdate"; import { news } from "./config/newsUpdate";
const Stack = createStackNavigator(); const Stack = createStackNavigator();
export const Top = ({ navigationRef }) => { export const Top = () => {
const { webview } = useCurrentTrain(); const { webview } = useCurrentTrain();
const { navigate, addListener } = useNavigation(); const { navigate, addListener, isFocused } = useNavigation();
useEffect(() => {
//ニュース表示
AS.getItem("status")
.then((d) => {
if (d != news) navigate("news");
})
.catch(() => navigate("news"));
}, []);
//地図用 //地図用
const { injectJavaScript, setInjectJavaScript, mapSwitch } = useTrainMenu(); const { injectJavaScript, mapSwitch } = useTrainMenu();
const goToFavoriteList = () => navigate("favoriteList"); const goToFavoriteList = () =>
navigate("positions", { screen: "favoriteList" });
useEffect(() => { useEffect(() => {
const unsubscribe = addListener("tabLongPress", goToFavoriteList); const unsubscribe = addListener("tabLongPress", goToFavoriteList);
return unsubscribe; return unsubscribe;
}, [{ navigate, addListener }]); }, []);
const goToTrainMenu = () => { const goToTrainMenu = () => {
if (navigationRef.current?.getCurrentRoute().name == "Apps") { if (!isFocused()) {
navigate("positions", { screen: "Apps" });
}
if (mapSwitch == "true") { if (mapSwitch == "true") {
navigate("trainMenu"); navigate("positions", { screen: "trainMenu" });
setInjectJavaScript("");
} else { } else {
webview.current?.injectJavaScript(`AccordionClassEvent()`); webview.current?.injectJavaScript(`AccordionClassEvent()`);
} }
} else { return;
if (mapSwitch == "true") {
if (injectJavaScript) {
webview.current?.injectJavaScript(injectJavaScript);
setInjectJavaScript("");
}
}
navigate("Apps");
}
}; };
useEffect(() => { useEffect(() => {
const unsubscribe = addListener("tabPress", goToTrainMenu); const unsubscribe = addListener("tabPress", goToTrainMenu);
return unsubscribe; return unsubscribe;
}, [{ navigate, addListener }, mapSwitch, injectJavaScript]); }, [addListener, mapSwitch, injectJavaScript]);
return ( return (
<Stack.Navigator> <Stack.Navigator detachInactiveScreens={false}>
<Stack.Screen <Stack.Screen
name="Apps" name="Apps"
options={{ options={{
headerShown: false, headerShown: false,
gestureEnabled: true, gestureEnabled: true,
headerTransparent: true, headerTransparent: true,
detachPreviousScreen: false,
}} }}
component={Apps} component={Apps}
/> />
<Stack.Screen <Stack.Screen
name="trainbase" name="trainbase"
options={{ options={{ ...optionData }}
title: "トレインビジョン",
gestureEnabled: true,
...TransitionPresets.SlideFromRightIOS,
}}
component={TrainBase} component={TrainBase}
/> />
<Stack.Screen name="howto" options={optionData} component={HowTo} /> <Stack.Screen name="howto" options={optionData} component={HowTo} />
<Stack.Screen name="news" options={optionData} component={News} /> <Stack.Screen name="news" options={optionData} component={News} />
<Stack.Screen <Stack.Screen
name="trainMenu" name="trainMenu"
options={optionData} options={optionData}
component={TrainMenu} component={TrainMenu}
/> />
<Stack.Screen <Stack.Screen
name="favoriteList" name="favoriteList"
options={{ ...optionData, gestureEnabled: false }} options={{ ...optionData, gestureEnabled: false }}

View File

@ -1,4 +1,4 @@
import { ToastAndroid } from "react-native"; import { Platform, ToastAndroid } from "react-native";
import * as Updates from "expo-updates"; import * as Updates from "expo-updates";
export const UpdateAsync = () => { export const UpdateAsync = () => {

448
app.json
View File

@ -1,47 +1,13 @@
{ {
"expo": { "expo": {
"name": "JR四国運行状況", "name": "JR四国非公式",
"slug": "jrshikoku", "slug": "jrshikoku",
"privacy": "public",
"platforms": ["ios", "android"], "platforms": ["ios", "android"],
"plugins": [ "version": "6.0",
[
"react-native-android-widget",
{
"widgets": [
{
"name": "JR_shikoku_train_info",
"label": "JR四国列車遅延速報EX",
"minWidth": "70dp",
"minHeight": "50dp",
"description": "JR四国列車遅延速報EXのウィジェットです。30分ごとに自動更新します。タッチすると強制更新します。",
"previewImage": "./assets/icon.png",
"updatePeriodMillis": 1800000,
"resizeMode": "horizontal|vertical"
}
]
}
],
"expo-font",
[
"expo-screen-orientation",
{
"initialOrientation": "DEFAULT"
}
],
[
"expo-location",
{
"locationWhenInUsePermission": "この位置情報は、リンク画面で現在地側近の駅情報を取得するのに使用されます。"
}
]
],
"version": "5.0",
"orientation": "default", "orientation": "default",
"icon": "./assets/icon.png", "icon": "./assets/icons/s8600.png",
"splash": { "splash": {
"image": "./assets/splash.png", "image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#00b8ff" "backgroundColor": "#00b8ff"
}, },
"updates": { "updates": {
@ -50,7 +16,7 @@
}, },
"assetBundlePatterns": ["**/*"], "assetBundlePatterns": ["**/*"],
"ios": { "ios": {
"buildNumber": "39", "buildNumber": "42",
"supportsTablet": false, "supportsTablet": false,
"bundleIdentifier": "jrshikokuinfo.xprocess.hrkn", "bundleIdentifier": "jrshikokuinfo.xprocess.hrkn",
"config": { "config": {
@ -64,13 +30,18 @@
] ]
}, },
"entitlements": { "entitlements": {
"com.apple.developer.nfc.readersession.formats": ["TAG"] "com.apple.developer.nfc.readersession.formats": [
"TAG"
]
} }
}, },
"android": { "android": {
"package": "jrshikokuinfo.xprocess.hrkn", "package": "jrshikokuinfo.xprocess.hrkn",
"versionCode": 22, "versionCode": 23,
"permissions": ["ACCESS_FINE_LOCATION", "NFC"], "permissions": [
"ACCESS_FINE_LOCATION",
"NFC"
],
"googleServicesFile": "./google-services.json", "googleServicesFile": "./google-services.json",
"config": { "config": {
"googleMaps": { "googleMaps": {
@ -85,6 +56,401 @@
}, },
"runtimeVersion": { "runtimeVersion": {
"policy": "sdkVersion" "policy": "sdkVersion"
},
"plugins": [
"expo-font",
"expo-localization",
[
"expo-video",
{
"supportsBackgroundPlayback": true,
"supportsPictureInPicture": true
}
],
[
"expo-screen-orientation",
{
"initialOrientation": "DEFAULT"
}
],
[
"expo-location",
{
"locationWhenInUsePermission": "この位置情報は、リンク画面で現在地側近の駅情報を取得するのに使用されます。"
}
],
[
"react-native-android-widget",
{
"widgets": [
{
"name": "JR_shikoku_train_info",
"label": "列車遅延速報EX",
"minWidth": "70dp",
"minHeight": "50dp",
"description": "JR四国列車遅延速報EXのウィジェットです。30分ごとに自動更新します。タッチすると強制更新します。",
"previewImage": "./assets/icon.png",
"updatePeriodMillis": 1800000,
"resizeMode": "horizontal|vertical"
},
{
"name": "JR_shikoku_train_strange",
"label": "怪レい列車",
"minWidth": "70dp",
"minHeight": "50dp",
"description": "JR四国怪レい列車BOTのウィジェットです。30分ごとに自動更新します。タッチすると強制更新します。",
"previewImage": "./assets/icon.png",
"updatePeriodMillis": 1800000,
"resizeMode": "horizontal|vertical"
},
{
"name": "JR_shikoku_info",
"label": "運行情報",
"minWidth": "70dp",
"minHeight": "50dp",
"description": "JR四国運行情報のウィジェットです。30分ごとに自動更新します。タッチすると強制更新します。",
"previewImage": "./assets/icon.png",
"updatePeriodMillis": 1800000,
"resizeMode": "horizontal|vertical"
},
{
"name": "JR_shikoku_apps_shortcut",
"label": "クイックアクセス",
"minWidth": "70dp",
"minHeight": "50dp",
"description": "JR四国非公式アプリの各種リンクを表示するウィジェットです。",
"previewImage": "./assets/icon.png",
"updatePeriodMillis": 1800000,
"resizeMode": "horizontal|vertical"
}
]
}
],
[
"expo-alternate-app-icons",
[
{
"name": "32",
"ios": "./assets/icons/32.png",
"android": {
"foregroundImage": "./assets/icons/32.png",
"backgroundColor": "#001413"
}
},
{
"name": "32kpuuy",
"ios": "./assets/icons/32kpuuy.png",
"android": {
"foregroundImage": "./assets/icons/32kpuuy.png",
"backgroundColor": "#001413"
}
},
{
"name": "32tht",
"ios": "./assets/icons/32tht.png",
"android": {
"foregroundImage": "./assets/icons/32tht.png",
"backgroundColor": "#001413"
}
},
{
"name": "32at",
"ios": "./assets/icons/32at.png",
"android": {
"foregroundImage": "./assets/icons/32at.png",
"backgroundColor": "#001413"
}
},
{
"name": "54",
"ios": "./assets/icons/54.png",
"android": {
"foregroundImage": "./assets/icons/54.png",
"backgroundColor": "#001413"
}
},
{
"name": "54st",
"ios": "./assets/icons/54st.png",
"android": {
"foregroundImage": "./assets/icons/54st.png",
"backgroundColor": "#001413"
}
},
{
"name": "40",
"ios": "./assets/icons/40.png",
"android": {
"foregroundImage": "./assets/icons/40.png",
"backgroundColor": "#001413"
}
},
{
"name": "185mrt",
"ios": "./assets/icons/s185_mrt.png",
"android": {
"foregroundImage": "./assets/icons/s185_mrt.png",
"backgroundColor": "#001413"
}
},
{
"name": "185tu",
"ios": "./assets/icons/s185tu.png",
"android": {
"foregroundImage": "./assets/icons/s185tu.png",
"backgroundColor": "#001413"
}
},
{
"name": "185iyor",
"ios": "./assets/icons/s185iyor.png",
"android": {
"foregroundImage": "./assets/icons/s185iyor.png",
"backgroundColor": "#001413"
}
},
{
"name": "185iyoy",
"ios": "./assets/icons/s185iyoy.png",
"android": {
"foregroundImage": "./assets/icons/s185iyoy.png",
"backgroundColor": "#001413"
}
},
{
"name": "185toai",
"ios": "./assets/icons/s185to_ai.png",
"android": {
"foregroundImage": "./assets/icons/s185to_ai.png",
"backgroundColor": "#001413"
}
},
{
"name": "185mm1",
"ios": "./assets/icons/s185mm1.png",
"android": {
"foregroundImage": "./assets/icons/s185mm1.png",
"backgroundColor": "#001413"
}
},
{
"name": "185ym1",
"ios": "./assets/icons/s185ym1.png",
"android": {
"foregroundImage": "./assets/icons/s185ym1.png",
"backgroundColor": "#001413"
}
},
{
"name": "1000",
"ios": "./assets/icons/s1000.png",
"android": {
"foregroundImage": "./assets/icons/s1000.png",
"backgroundColor": "#001413"
}
},
{
"name": "1200n",
"ios": "./assets/icons/s1200n.png",
"android": {
"foregroundImage": "./assets/icons/s1200n.png",
"backgroundColor": "#001413"
}
},
{
"name": "1500",
"ios": "./assets/icons/s1500.png",
"android": {
"foregroundImage": "./assets/icons/s1500.png",
"backgroundColor": "#001413"
}
},
{
"name": "5001",
"ios": "./assets/icons/s5001.png",
"android": {
"foregroundImage": "./assets/icons/s5001.png",
"backgroundColor": "#001413"
}
},
{
"name": "5001k",
"ios": "./assets/icons/s5001k.png",
"android": {
"foregroundImage": "./assets/icons/s5001k.png",
"backgroundColor": "#001413"
}
},
{
"name": "6000p",
"ios": "./assets/icons/s6000p.png",
"android": {
"foregroundImage": "./assets/icons/s6000p.png",
"backgroundColor": "#001413"
}
},
{
"name": "7000",
"ios": "./assets/icons/s7000.png",
"android": {
"foregroundImage": "./assets/icons/s7000.png",
"backgroundColor": "#001413"
}
},
{
"name": "s7200",
"ios": "./assets/icons/s7200.png",
"android": {
"foregroundImage": "./assets/icons/s7200.png",
"backgroundColor": "#001413"
}
},
{
"name": "2000asi",
"ios": "./assets/icons/s2000_asi.png",
"android": {
"foregroundImage": "./assets/icons/s2000_asi.png",
"backgroundColor": "#001413"
}
},
{
"name": "N2000",
"ios": "./assets/icons/s2000n.png",
"android": {
"foregroundImage": "./assets/icons/s2000n.png",
"backgroundColor": "#001413"
}
},
{
"name": "2002a",
"ios": "./assets/icons/s2002a.png",
"android": {
"foregroundImage": "./assets/icons/s2002a.png",
"backgroundColor": "#001413"
}
},
{
"name": "2600",
"ios": "./assets/icons/s2600.png",
"android": {
"foregroundImage": "./assets/icons/s2600.png",
"backgroundColor": "#001413"
}
},
{
"name": "2700",
"ios": "./assets/icons/s2700.png",
"android": {
"foregroundImage": "./assets/icons/s2700.png",
"backgroundColor": "#001413"
}
},
{
"name": "2700apy",
"ios": "./assets/icons/s2700apy.png",
"android": {
"foregroundImage": "./assets/icons/s2700apy.png",
"backgroundColor": "#001413"
}
},
{
"name": "2700apr",
"ios": "./assets/icons/s2700apr.png",
"android": {
"foregroundImage": "./assets/icons/s2700apr.png",
"backgroundColor": "#001413"
}
},
{
"name": "8000no",
"ios": "./assets/icons/s8000no.png",
"android": {
"foregroundImage": "./assets/icons/s8000no.png",
"backgroundColor": "#001413"
}
},
{
"name": "8000nr",
"ios": "./assets/icons/s8000nr.png",
"android": {
"foregroundImage": "./assets/icons/s8000nr.png",
"backgroundColor": "#001413"
}
},
{
"name": "8000ap",
"ios": "./assets/icons/s8000ap.png",
"android": {
"foregroundImage": "./assets/icons/s8000ap.png",
"backgroundColor": "#001413"
}
},
{
"name": "8000nn",
"ios": "./assets/icons/s8000nn.png",
"android": {
"foregroundImage": "./assets/icons/s8000nn.png",
"backgroundColor": "#001413"
}
},
{
"name": "8600",
"ios": "./assets/icons/s8600.png",
"android": {
"foregroundImage": "./assets/icons/s8600.png",
"backgroundColor": "#001413"
}
},
{
"name": "9640",
"ios": "./assets/icons/tosa9640.png",
"android": {
"foregroundImage": "./assets/icons/tosa9640.png",
"backgroundColor": "#001413"
}
},
{
"name": "9640jgr",
"ios": "./assets/icons/tosa9640jgr.png",
"android": {
"foregroundImage": "./assets/icons/tosa9640jgr.png",
"backgroundColor": "#001413"
}
},
{
"name": "285",
"ios": "./assets/icons/w285.png",
"android": {
"foregroundImage": "./assets/icons/w285.png",
"backgroundColor": "#001413"
}
},
{
"name": "213w",
"ios": "./assets/icons/w213w.png",
"android": {
"foregroundImage": "./assets/icons/w213w.png",
"backgroundColor": "#001413"
}
},
{
"name": "EF65",
"ios": "./assets/icons/ef65.png",
"android": {
"foregroundImage": "./assets/icons/ef65.png",
"backgroundColor": "#001413"
}
},
{
"name": "EF210",
"ios": "./assets/icons/ef210.png",
"android": {
"foregroundImage": "./assets/icons/ef210.png",
"backgroundColor": "#001413"
} }
} }
]
]
]
}
} }

BIN
assets/icons/32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
assets/icons/32at.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
assets/icons/32kpuuy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
assets/icons/32tht.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
assets/icons/40.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
assets/icons/54.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
assets/icons/54st.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
assets/icons/ef210.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
assets/icons/ef65.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

45
assets/icons/icons.ts Normal file
View File

@ -0,0 +1,45 @@
export default () =>{
return [
{ "id": "32", "name": "キハ32形", "icon": require("./32.png") },
{ "id": "32kpuuy", "name": "キハ32形かっぱうようよ号", "icon": require("./32kpuuy.png") },
{ "id": "32tht", "name": "キハ32形新幹線ホビートレイン", "icon": require("./32tht.png") },
{ "id": "32at", "name": "キクハ32形アンパンマントロッコ", "icon": require("./32at.png") },
{ "id": "54", "name": "キハ54形", "icon": require("./54.png") },
{ "id": "54st", "name": "キハ54形しまんトロッコ", "icon": require("./54st.png") },
{ "id": "40", "name": "キハ40", "icon": require("./40.png") },
{ "id": "185mrt", "name": "キハ185系四国色", "icon": require("./s185_mrt.png") },
{ "id": "185tu", "name": "キハ185系剣山色", "icon": require("./s185tu.png") },
{ "id": "185iyor", "name": "キハ185系伊予灘ものがたり(赤)", "icon": require("./s185iyor.png") },
{ "id": "185iyoy", "name": "キハ185系伊予灘ものがたり(黄)", "icon": require("./s185iyoy.png") },
{ "id": "185toai", "name": "キハ185系藍よしのがわトロッコ", "icon": require("./s185to_ai.png") },
{ "id": "185mm1", "name": "キハ185系四国まんなか千年ものがたり(緑)", "icon": require("./s185mm1.png") },
{ "id": "185ym1", "name": "キハ185系時代の夜明けのものがたり(茶)", "icon": require("./s185ym1.png") },
{ "id": "1000", "name": "1000形", "icon": require("./s1000.png") },
{ "id": "1200n", "name": "1200形", "icon": require("./s1200n.png") },
{ "id": "1500", "name": "1500形", "icon": require("./s1500.png") },
{ "id": "5001", "name": "5000系(二階建て)", "icon": require("./s5001.png") },
{ "id": "5001k", "name": "5000系(平屋側)", "icon": require("./s5001k.png") },
{ "id": "6000p", "name": "6000系", "icon": require("./s6000p.png") },
{ "id": "7000", "name": "7000系", "icon": require("./s7000.png") },
{ "id": "7200", "name": "7200系", "icon": require("./s7200.png") },
{ "id": "2000asi", "name": "2000系", "icon": require("./s2000_asi.png") },
{ "id": "N2000", "name": "N2000系", "icon": require("./s2000n.png") },
{ "id": "2002a", "name": "2000系アンパンマン", "icon": require("./s2002a.png") },
{ "id": "2600", "name": "2600系" , "icon": require("./s2600.png")},
{ "id": "2700", "name": "2700系", "icon": require("./s2700.png") },
{ "id": "2700apy", "name": "2700系アンパンマン(黄)", "icon": require("./s2700apy.png") },
{ "id": "2700apr", "name": "2700系アンパンマン(赤)", "icon": require("./s2700apr.png") },
{ "id": "8000no", "name": "8000系(オレンジ)", "icon": require("./s8000no.png") },
{ "id": "8000nr", "name": "8000系(赤)", "icon": require("./s8000nr.png") },
{ "id": "8000ap", "name": "8000系アンパンマン", "icon": require("./s8000ap.png") },
{ "id": "8000nn", "name": "8000系リニューアル改", "icon": require("./s8000nn.png") },
{ "id": "8600", "name": "8600系", "icon": require("./s8600.png") },
{ "id": "9640", "name": "9640形(白)", "icon": require("./tosa9640.png") },
{ "id": "9640jgr", "name": "9640形オープンデッキ(緑)", "icon": require("./tosa9640jgr.png") },
{ "id": "285", "name": "285系サンライズ瀬戸", "icon": require("./w285.png") },
{ "id": "213w", "name": "ラ・マル・ド・ボァ", "icon": require("./w213w.png") },
{ "id": "EF65", "name": "EF65", "icon": require("./ef65.png") },
{ "id": "EF210", "name": "EF210", "icon": require("./ef210.png") },
]
}

BIN
assets/icons/s1000.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
assets/icons/s1200n.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
assets/icons/s1500.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
assets/icons/s185_mrt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
assets/icons/s185iyor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
assets/icons/s185iyoy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
assets/icons/s185mm1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

BIN
assets/icons/s185to_ai.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
assets/icons/s185tu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
assets/icons/s185ym1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
assets/icons/s2000_asi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
assets/icons/s2000n.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
assets/icons/s2002a.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
assets/icons/s2600.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
assets/icons/s2700.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
assets/icons/s2700apr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
assets/icons/s2700apy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
assets/icons/s5001.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
assets/icons/s5001k.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
assets/icons/s6000p.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
assets/icons/s7000.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
assets/icons/s7200.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
assets/icons/s8000ap.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
assets/icons/s8000nn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
assets/icons/s8000no.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
assets/icons/s8000nr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
assets/icons/s8600.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

BIN
assets/icons/tosa9640.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
assets/icons/w213w.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

BIN
assets/icons/w285.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@ -8,7 +8,6 @@ export const EachTrainInfo = ({ payload }) => {
return ( return (
<ActionSheet <ActionSheet
gestureEnabled={true} gestureEnabled={true}
//gestureEnabled={!actionSheetHorizonalScroll}
CustomHeaderComponent={<></>} CustomHeaderComponent={<></>}
ref={actionSheetRef} ref={actionSheetRef}
drawUnderStatusBar={false} drawUnderStatusBar={false}

View File

@ -9,9 +9,6 @@ import { trainPosition } from "../../../lib/trainPositionTextArray";
import { TrainPositionDataPush } from "../../発車時刻表/LED_inside_Component/TrainPositionDataPush"; import { TrainPositionDataPush } from "../../発車時刻表/LED_inside_Component/TrainPositionDataPush";
import { getStationID } from "../../../lib/eachTrainInfoCoreLib/getStationData"; import { getStationID } from "../../../lib/eachTrainInfoCoreLib/getStationData";
import { useStationList } from "../../../stateBox/useStationList"; import { useStationList } from "../../../stateBox/useStationList";
import { lineList } from "../../../lib/getStationList";
export const TrainDataView = ({ export const TrainDataView = ({
currentTrainData, currentTrainData,
@ -21,7 +18,6 @@ export const TrainDataView = ({
mode = 0, mode = 0,
navigate, navigate,
}) => { }) => {
const { stationList } = useStationList(); const { stationList } = useStationList();
const { width, height } = useWindowDimensions(); const { width, height } = useWindowDimensions();
@ -62,7 +58,8 @@ export const TrainDataView = ({
const [descInput, setDescInput] = useState(""); const [descInput, setDescInput] = useState("");
const [stationInput, setStationInput] = useState(""); const [stationInput, setStationInput] = useState("");
const [stationNumberInput, setStationNumberInput] = useState(""); const [stationNumberInput, setStationNumberInput] = useState("");
return (<> return (
<>
<TrainPositionDataPush <TrainPositionDataPush
dialog={dialog} dialog={dialog}
setDialog={setDialog} setDialog={setDialog}
@ -73,7 +70,11 @@ export const TrainDataView = ({
descInput={descInput} descInput={descInput}
setPosInput={setPosInput} setPosInput={setPosInput}
setDescInput={setDescInput} setDescInput={setDescInput}
station={{Station_JP:trainPositionText(currentTrainData),StationNumber:currentPosition[0]}} /> station={{
Station_JP: trainPositionText(currentTrainData),
StationNumber: currentPosition[0],
}}
/>
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
@ -89,7 +90,10 @@ export const TrainDataView = ({
onLongPress={() => { onLongPress={() => {
const { isBetween, Pos } = trainPosition(currentTrainData); const { isBetween, Pos } = trainPosition(currentTrainData);
if (isBetween === true) { if (isBetween === true) {
if (platformNumber == undefined && platformDescription == undefined) if (
platformNumber == undefined &&
platformDescription == undefined
)
return; return;
setStationInput(`${Pos.from}${Pos.to}`); setStationInput(`${Pos.from}${Pos.to}`);
setStationNumberInput( setStationNumberInput(
@ -123,7 +127,7 @@ export const TrainDataView = ({
} }
}); });
if (!test.length) return; if (!test.length) return;
navigate("Apps"); navigate("positions", { screen: "Apps" });
inject( inject(
`MoveDisplayStation('${test[0].line}_${test[0].station.MyStation}_${test[0].station.Station_JP}');document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");` `MoveDisplayStation('${test[0].line}_${test[0].station.MyStation}_${test[0].station.Station_JP}');document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");`
); );

View File

@ -10,6 +10,7 @@ import {
LayoutAnimation, LayoutAnimation,
} from "react-native"; } from "react-native";
import { SheetManager } from "react-native-actions-sheet"; import { SheetManager } from "react-native-actions-sheet";
import { useScrollHandlers } from "react-native-actions-sheet";
import { AS } from "../../storageControl"; import { AS } from "../../storageControl";
import trainList from "../../assets/originData/trainList"; import trainList from "../../assets/originData/trainList";
import { lineListPair } from "../../lib/getStationList"; import { lineListPair } from "../../lib/getStationList";
@ -188,7 +189,7 @@ export const EachTrainInfoCore = ({
const count = position * 44 - 50; const count = position * 44 - 50;
// 0.5秒待機してからスクロール // 0.5秒待機してからスクロール
setTimeout( setTimeout(
() => ScrollViewRef.current?.scrollTo({ y: count, animated: true }), () => scrollHandlers.ref.current?.scrollTo({ y: count, animated: true }),
400 400
); );
} }
@ -219,8 +220,9 @@ export const EachTrainInfoCore = ({
const { height } = useWindowDimensions(); const { height } = useWindowDimensions();
const { isLandscape } = useDeviceOrientationChange(); const { isLandscape } = useDeviceOrientationChange();
const ScrollViewRef = useRef(); const scrollHandlers = actionSheetRef
? useScrollHandlers("scrollview-1", actionSheetRef)
: null;
const [trueTrainID, setTrueTrainID] = useState(); const [trueTrainID, setTrueTrainID] = useState();
useEffect(() => { useEffect(() => {
if (!data.trainNum) return; if (!data.trainNum) return;
@ -335,8 +337,7 @@ export const EachTrainInfoCore = ({
.then((d) => { .then((d) => {
if (d) setTrainPositionSwitch(d); if (d) setTrainPositionSwitch(d);
}) })
//6.0で変更 .catch(() => AS.setItem("trainPositionSwitch", "true"));
.catch(() => AS.setItem("trainPositionSwitch", "false"));
}, []); }, []);
const openTrainInfo = (d) => { const openTrainInfo = (d) => {
@ -362,7 +363,7 @@ export const EachTrainInfoCore = ({
} else { } else {
SheetManager.hide("EachTrainInfo").then(() => { SheetManager.hide("EachTrainInfo").then(() => {
//0.1秒待機してから開く //0.1秒待機してから開く
setTimeout(() => SheetManager.show("EachTrainInfo", { payload }), 2); setTimeout(() => SheetManager.show("EachTrainInfo", { payload }), 200);
}); });
} }
}; };
@ -412,7 +413,7 @@ export const EachTrainInfoCore = ({
from={from} from={from}
styles={styles} styles={styles}
actionSheetRef={actionSheetRef} actionSheetRef={actionSheetRef}
ScrollViewRef={ScrollViewRef} scrollHandlers={scrollHandlers}
containerProps={{ containerProps={{
style: { style: {
maxHeight: isLandscape ? height - 94 : (height / 100) * 70, maxHeight: isLandscape ? height - 94 : (height / 100) * 70,

View File

@ -13,7 +13,7 @@ export const TrainViewIcon: FC<Props> = ({ data, navigate, from }) => {
const [isTrainView, setIsTrainView] = useState(false); const [isTrainView, setIsTrainView] = useState(false);
//トレインビュー表示対象(特急、マリン)かを判定 //トレインビュー表示対象(特急、マリン)かを判定
useEffect(() => { useEffect(() => {
if (!data.limited) return; if (!data.limited) return () => {};
setIsTrainView( setIsTrainView(
getType(data.limited.split(":")[0]) && getType(data.limited.split(":")[0]) &&
!data.limited.split(":")[1].match("サンポート") !data.limited.split(":")[1].match("サンポート")

View File

@ -9,6 +9,7 @@ import {
import ActionSheet, { SheetManager } from "react-native-actions-sheet"; import ActionSheet, { SheetManager } from "react-native-actions-sheet";
import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useSafeAreaInsets } from "react-native-safe-area-context";
import { useTrainMenu } from "../../stateBox/useTrainMenu"; import { useTrainMenu } from "../../stateBox/useTrainMenu";
import { useCurrentTrain } from "../../stateBox/useCurrentTrain";
import lineColorList from "../../assets/originData/lineColorList"; import lineColorList from "../../assets/originData/lineColorList";
import { stationIDPair } from "../../lib/getStationList2"; import { stationIDPair } from "../../lib/getStationList2";
import { lineListPair } from "../../lib/getStationList"; import { lineListPair } from "../../lib/getStationList";
@ -19,6 +20,7 @@ export const TrainMenuLineSelector = () => {
setSelectedLine, setSelectedLine,
mapsStationData: stationData, mapsStationData: stationData,
} = useTrainMenu(); } = useTrainMenu();
const { webview } = useCurrentTrain();
const actionSheetRef = useRef(null); const actionSheetRef = useRef(null);
const insets = useSafeAreaInsets(); const insets = useSafeAreaInsets();
const platformIs = Platform.OS == "android"; const platformIs = Platform.OS == "android";
@ -52,7 +54,25 @@ export const TrainMenuLineSelector = () => {
}} }}
onPress={() => { onPress={() => {
SheetManager.hide("TrainMenuLineSelector"); SheetManager.hide("TrainMenuLineSelector");
setSelectedLine(selectedLine == d ? undefined : d); const s = selectedLine == d ? undefined : d;
if(!s) return;
setSelectedLine(s);
Object.keys(stationData).forEach((data, indexBase) => {
stationData[data].forEach((D, index) => {
if (!D.StationMap) return null;
if (s && s != data) return;
const latlng = D.StationMap.replace(
"https://www.google.co.jp/maps/place/",
""
).split(",");
if (latlng.length == 0) return null;
if (index == 0 ) {
webview.current
?.injectJavaScript(`MoveDisplayStation('${data}_${D.MyStation}_${D.Station_JP}');
document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");`);
}
});
});
}} }}
> >
<View <View

View File

@ -20,7 +20,7 @@ import { useNavigation } from "@react-navigation/native";
import { BigButton } from "./atom/BigButton"; import { BigButton } from "./atom/BigButton";
import { Switch } from "react-native-elements"; import { Switch } from "react-native-elements";
export default function AllTrainDiagramView() { export default function AllTrainDiagramView() {
const { navigate } = useNavigation(); const { goBack, navigate } = useNavigation();
const { keyList, allTrainDiagram } = useAllTrainDiagram(); const { keyList, allTrainDiagram } = useAllTrainDiagram();
const [input, setInput] = useState(""); // 文字入力 const [input, setInput] = useState(""); // 文字入力
const [keyBoardVisible, setKeyBoardVisible] = useState(false); const [keyBoardVisible, setKeyBoardVisible] = useState(false);
@ -206,7 +206,7 @@ export default function AllTrainDiagramView() {
</View> </View>
</KeyboardAvoidingView> </KeyboardAvoidingView>
<BigButton <BigButton
onPress={() => navigate("menu")} onPress={goBack}
string="閉じる" string="閉じる"
style={{ style={{
display: display:

View File

@ -20,7 +20,7 @@ export const getInfoString = async () => {
} }
return null; return null;
}); });
ToastAndroid.show(`${text}`, ToastAndroid.SHORT); //ToastAndroid.show(`${text}`, ToastAndroid.SHORT);
return { time, text }; return { time, text };
}; };

View File

@ -20,7 +20,7 @@ export const getDelayData = async () => {
} }
return null; return null;
}); });
ToastAndroid.show(`${delayString}`, ToastAndroid.SHORT); //ToastAndroid.show(`${delayString}`, ToastAndroid.SHORT);
return { time, delayString }; return { time, delayString };
}; };
export function TraInfoEXWidget({ time, delayString }) { export function TraInfoEXWidget({ time, delayString }) {

View File

@ -20,11 +20,11 @@ export async function widgetTaskHandler(props) {
const WidgetName = await AS.getItem( const WidgetName = await AS.getItem(
`widgetType/${widgetInfo.widgetId}` `widgetType/${widgetInfo.widgetId}`
).catch((e) => "JR_shikoku_train_info"); ).catch((e) => "JR_shikoku_train_info");
ToastAndroid.show( // ToastAndroid.show(
`Widget Action: ${JSON.stringify(widgetInfo.widgetId)}`, // `Widget Action: ${JSON.stringify(widgetInfo.widgetId)}`,
ToastAndroid.SHORT // ToastAndroid.SHORT
); // );
ToastAndroid.show(`Widget Name: ${WidgetName}`, ToastAndroid.SHORT); //ToastAndroid.show(`Widget Name: ${WidgetName}`, ToastAndroid.SHORT);
switch (widgetAction) { switch (widgetAction) {
case "WIDGET_ADDED": case "WIDGET_ADDED":
case "WIDGET_UPDATE": case "WIDGET_UPDATE":

View File

@ -60,7 +60,7 @@ export default function Apps() {
useShow: () => SheetManager.show("StationDetailView", { payload }), useShow: () => SheetManager.show("StationDetailView", { payload }),
onExit: () => SheetManager.hide("StationDetailView"), onExit: () => SheetManager.hide("StationDetailView"),
}; };
SheetManager.show("StationDetailView", { payload }); setTimeout(()=>SheetManager.show("StationDetailView", { payload }),50);
} else { } else {
SheetManager.hide("StationDetailView"); SheetManager.hide("StationDetailView");
} }

View File

@ -4,12 +4,12 @@ import { useCurrentTrain } from "../stateBox/useCurrentTrain";
import { useNavigation } from "@react-navigation/native"; import { useNavigation } from "@react-navigation/native";
import { BigButton } from "./atom/BigButton"; import { BigButton } from "./atom/BigButton";
export default function CurrentTrainListView() { export default function CurrentTrainListView() {
const { navigate } = useNavigation(); const { goBack } = useNavigation();
const { currentTrain } = useCurrentTrain(); const { currentTrain } = useCurrentTrain();
return ( return (
<View style={{ height: "100%", backgroundColor: "#0099CC" }}> <View style={{ height: "100%", backgroundColor: "#0099CC" }}>
{currentTrain && currentTrain.map((d) => <Text>{d.num}</Text>)} {currentTrain && currentTrain.map((d) => <Text>{d.num}</Text>)}
<BigButton onPress={() => navigate("menu")} string="閉じる" /> <BigButton onPress={goBack} string="閉じる" />
</View> </View>
); );
} }

View File

@ -1,6 +1,6 @@
import { ScrollView, View, Animated, LayoutAnimation } from "react-native"; import { ScrollView, View, Animated, LayoutAnimation } from "react-native";
import React, { useEffect, useMemo, useState, useLayoutEffect } from "react"; import React, { useEffect, useMemo, useState, useLayoutEffect } from "react";
import { useScrollHandlers } from "react-native-actions-sheet"; import { NativeViewGestureHandler } from "react-native-gesture-handler";
import { AS } from "../storageControl"; import { AS } from "../storageControl";
export const DynamicHeaderScrollView = (props) => { export const DynamicHeaderScrollView = (props) => {
@ -13,7 +13,7 @@ export const DynamicHeaderScrollView = (props) => {
topStickyContent, topStickyContent,
styles, styles,
from, from,
ScrollViewRef, scrollHandlers,
} = props; } = props;
const [headerSize, setHeaderSize] = useState("default"); const [headerSize, setHeaderSize] = useState("default");
useLayoutEffect(() => { useLayoutEffect(() => {
@ -53,9 +53,7 @@ export const DynamicHeaderScrollView = (props) => {
const Scroll_Distance = Max_Header_Height - Min_Header_Height; const Scroll_Distance = Max_Header_Height - Min_Header_Height;
const scrollHandlers = actionSheetRef
? useScrollHandlers("scrollview-1", actionSheetRef)
: null;
const shotHeaderStyle = { const shotHeaderStyle = {
on: { on: {
@ -110,6 +108,7 @@ export const DynamicHeaderScrollView = (props) => {
const [headerVisible, setHeaderVisible] = useState(false); const [headerVisible, setHeaderVisible] = useState(false);
const onScroll = (event) => { const onScroll = (event) => {
scrollHandlers.onScroll(event);
switch (headerSize) { switch (headerSize) {
case "big": case "big":
setHeaderVisible(false); setHeaderVisible(false);
@ -153,13 +152,17 @@ export const DynamicHeaderScrollView = (props) => {
{topStickyContent} {topStickyContent}
</Animated.View> </Animated.View>
</View> </View>
<NativeViewGestureHandler
simultaneousHandlers={scrollHandlers.simultaneousHandlers}
>
<ScrollView <ScrollView
{...scrollHandlers} nestedScrollEnabled
ref={scrollHandlers.ref}
onLayout={scrollHandlers.onLayout}
scrollEventThrottle={scrollHandlers.scrollEventThrottle}
style={{ backgroundColor: "white", zIndex: 0 }} style={{ backgroundColor: "white", zIndex: 0 }}
stickyHeaderIndices={[1]} stickyHeaderIndices={[1]}
scrollEventThrottle={16}
onScroll={onScroll} onScroll={onScroll}
ref={ScrollViewRef}
> >
<View style={{ height: Scroll_Distance, flexDirection: "column" }} /> <View style={{ height: Scroll_Distance, flexDirection: "column" }} />
{topStickyContent && ( {topStickyContent && (
@ -173,6 +176,7 @@ export const DynamicHeaderScrollView = (props) => {
)} )}
{children} {children}
</ScrollView> </ScrollView>
</NativeViewGestureHandler>
</View> </View>
); );
}; };

View File

@ -1,5 +1,5 @@
import React from "react"; import React, { useEffect } from "react";
import { View, Text, TouchableOpacity, ScrollView } from "react-native"; import { View, Text, ScrollView } from "react-native";
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";
@ -11,9 +11,18 @@ import { BigButton } from "./atom/BigButton";
export default function FavoriteList() { export default function FavoriteList() {
const { favoriteStation } = useFavoriteStation(); const { favoriteStation } = useFavoriteStation();
const { webview } = useCurrentTrain(); const { webview } = useCurrentTrain();
const { navigate, goBack } = useNavigation(); const { navigate, addListener, goBack, canGoBack } = useNavigation();
const { mapsStationData: stationData } = useTrainMenu(); const { mapsStationData: stationData } = useTrainMenu();
useEffect(() => {
const unsubscribe = addListener("tabPress", goToTrainMenu);
return unsubscribe;
}, [{ navigate, addListener }]);
const goToTrainMenu = (e) => {
e.preventDefault();
goBack();
};
return ( return (
<View style={{ height: "100%", backgroundColor: "#0099CC" }}> <View style={{ height: "100%", backgroundColor: "#0099CC" }}>
<Text <Text
@ -50,7 +59,8 @@ export default function FavoriteList() {
`MoveDisplayStation('${lineName}_${currentStation[0].MyStation}_${currentStation[0].Station_JP}'); `MoveDisplayStation('${lineName}_${currentStation[0].MyStation}_${currentStation[0].Station_JP}');
document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");` document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");`
); );
navigate("Apps"); goBack();
if (canGoBack()) goBack();
}} }}
> >
<View <View

View File

@ -5,10 +5,11 @@ import {
Ionicons, Ionicons,
MaterialCommunityIcons, MaterialCommunityIcons,
} from "@expo/vector-icons"; } from "@expo/vector-icons";
import { ListItem } from "@rneui/themed";
import TouchableScale from 'react-native-touchable-scale';
import Icon from "react-native-vector-icons/Entypo"; import Icon from "react-native-vector-icons/Entypo";
import { TextBox } from "../atom/TextBox"; import { TextBox } from "../atom/TextBox";
import { TicketBox } from "../atom/TicketBox"; import { TicketBox } from "../atom/TicketBox";
import { ListItem } from "native-base";
export const FixedContentBottom = (props) => { export const FixedContentBottom = (props) => {
return ( return (
@ -249,10 +250,16 @@ export const FixedContentBottom = (props) => {
name: "しこくたぬきのぽんちゃん 【四国家サポーターズクラブ】", name: "しこくたぬきのぽんちゃん 【四国家サポーターズクラブ】",
}, },
].map((d) => ( ].map((d) => (
<ListItem onPress={() => Linking.openURL(d.url)}> <ListItem bottomDivider onPress={() => Linking.openURL(d.url)}
<Text>{d.name}</Text> key={d.url}friction={90} //
<View style={{ flex: 1 }} /> tension={100} // These props are passed to the parent component (here TouchableScale)
<Icon name="chevron-right" size={20} /> activeScale={0.95} //
Component={TouchableScale}
>
<ListItem.Content>
<ListItem.Title>{d.name}</ListItem.Title>
</ListItem.Content>
<ListItem.Chevron />
</ListItem> </ListItem>
))} ))}
</View> </View>

View File

@ -0,0 +1,27 @@
import React, { FC } from "react";
import { Ionicons } from "@expo/vector-icons";
import { TouchableOpacity } from "react-native";
type SimpleDotProps = {
active: boolean;
onPress: () => void;
};
export const SimpleDot: FC<SimpleDotProps> = (props) => {
const { active, onPress } = props;
return (
<TouchableOpacity
style={{
width: 20,
marginHorizontal: 2,
alignItems: "center",
justifyContent: "center",
}}
onPress={onPress}
>
<Ionicons
name="ellipse"
size={active ? 20 : 14}
color={active ? "#00b8ff" : "#00b8ff55"}
/>
</TouchableOpacity>
);
};

View File

@ -1,6 +1,5 @@
import React, { FC, useState } from "react"; import React, { FC, useState } from "react";
import { View, Text, TouchableOpacity } from "react-native"; import { View, Text, TouchableOpacity } from "react-native";
import { Pagination } from "react-native-snap-carousel";
import { useInterval } from "../../lib/useInterval"; import { useInterval } from "../../lib/useInterval";
import lineColorList from "../../assets/originData/lineColorList"; import lineColorList from "../../assets/originData/lineColorList";
@ -18,78 +17,6 @@ type StationProps = {
lat: number; lat: number;
lng: number; lng: number;
}; };
type StationPaginationProps = {
entries: StationProps[][];
activeSlide: number;
carouselRef: any;
setSelectedCurrentStation: React.Dispatch<React.SetStateAction<number>>;
dotButton: boolean;
};
export const Paginations: FC<StationPaginationProps> = (props) => {
const {
entries,
activeSlide,
carouselRef,
setSelectedCurrentStation,
dotButton,
} = props;
return (
<Pagination
dotsLength={entries.length}
activeDotIndex={activeSlide}
carouselRef={carouselRef}
containerStyle={{ paddingVertical: 0 }}
dotStyle={{
width: 12,
height: 12,
borderRadius: 6,
backgroundColor: "#0099CC",
}}
inactiveDotStyle={
{
// Define styles for inactive dots here
}
}
tappableDots={true}
inactiveDotOpacity={0.4}
inactiveDotScale={0.8}
inactiveDotElement={
dotButton && (
<StationNumberMaker
currentStations={entries}
setSelectedCurrentStation={setSelectedCurrentStation}
/>
)
}
dotElement={
dotButton && (
<StationNumberMaker
currentStations={entries}
setSelectedCurrentStation={setSelectedCurrentStation}
/>
)
}
/>
);
};
type StationNumberMakerProps = {
currentStations: StationProps[][];
setSelectedCurrentStation: React.Dispatch<React.SetStateAction<number>>;
active?: boolean;
index?: number;
};
export const StationNumberMaker: FC<StationNumberMakerProps> = (props) => {
const { currentStations, active, index, setSelectedCurrentStation } = props;
return (
<StationNumber
currentStation={currentStations[index]}
active={active}
onPress={() => setSelectedCurrentStation(index)}
key={currentStations[index][0].StationNumber}
/>
);
};
type StationNumberProps = { type StationNumberProps = {
currentStation: StationProps[]; currentStation: StationProps[];
active: boolean; active: boolean;
@ -107,41 +34,42 @@ export const StationNumber: FC<StationNumberProps> = (props) => {
const lineID = data[animation].StationNumber.slice(0, 1); const lineID = data[animation].StationNumber.slice(0, 1);
const lineName = data[animation].StationNumber.slice(1); const lineName = data[animation].StationNumber.slice(1);
const size = active ? 24 : 18; const size = active ? 24 : 18;
const margin = active ? 3 : 6;
const border = active ? 2 : 1;
return ( return (
<> <TouchableOpacity
onPress={onPress} style={{
width: 28,
height:24,
alignContent:"center",
alignItems:"center",
justifyContent:"center",
position:"relative",
}}>
{active && ( {active && (
<View style={{ position: "relative", width: 0, height: 0 }}>
<View <View
style={{ style={{
flex: 1, flex: 1,
position: "absolute", position: "absolute",
width: 28, width: 28,
height: 28, height: 28,
marginLeft: 1, marginHorizontal:1,
marginRight: 1,
borderRadius: 22, borderRadius: 22,
borderColor: "black", borderColor: "black",
borderWidth: 2, borderWidth: 2,
left: 0, left: -1,
top: -14, top: -2,
zIndex:10
}} }}
/> />
</View>
)} )}
<TouchableOpacity <View
onPress={onPress}
style={{ style={{
alignContent: "center", alignContent: "center",
alignItems: "center", alignItems: "center",
width: size, width: size,
height: size, height: size,
marginLeft: margin,
marginRight: margin,
borderColor: lineColorList[lineID], borderColor: lineColorList[lineID],
backgroundColor: "white", backgroundColor: "white",
borderWidth: border, borderWidth: active ? 2 : 1,
borderRadius: 22, borderRadius: 22,
}} }}
key={currentStation[0].StationNumber + lineID} key={currentStation[0].StationNumber + lineID}
@ -161,7 +89,7 @@ export const StationNumber: FC<StationNumberProps> = (props) => {
{lineID + "\n" + lineName} {lineID + "\n" + lineName}
</Text> </Text>
<View style={{ flex: 1 }} /> <View style={{ flex: 1 }} />
</View>
</TouchableOpacity> </TouchableOpacity>
</>
); );
}; };

View File

@ -1,17 +1,19 @@
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 { useNavigation } from "@react-navigation/native";
import { useFavoriteStation } from "../../stateBox/useFavoriteStation"; import { useFavoriteStation } from "../../stateBox/useFavoriteStation";
import { CheckBox } from "react-native-elements"; import { CheckBox } from "react-native-elements";
import { FavoriteSettingsItem } from "./FavoliteSettings/FavoiliteSettingsItem"; import { FavoriteSettingsItem } from "./FavoliteSettings/FavoiliteSettingsItem";
export const FavoriteSettings = ({ navigate }) => { export const FavoriteSettings = () => {
const { favoriteStation, setFavoriteStation } = useFavoriteStation(); const { favoriteStation, setFavoriteStation } = useFavoriteStation();
const { goBack } = useNavigation();
return ( return (
<View style={{ height: "100%", backgroundColor: "#0099CC" }}> <View style={{ height: "100%", backgroundColor: "#0099CC" }}>
<View style={{ backgroundColor: "#0099CC", flexDirection: "row" }}> <View style={{ backgroundColor: "#0099CC", flexDirection: "row" }}>
<View style={{ flex: 1 }}> <View style={{ flex: 1 }}>
<TouchableOpacity <TouchableOpacity
onPress={() => navigate("settingTopPage")} onPress={goBack}
style={{ style={{
flexDirection: "column", flexDirection: "column",
flex: 1, flex: 1,

View File

@ -0,0 +1,147 @@
import React, { useEffect, useState } from "react";
import { View, Text, TouchableOpacity, ScrollView, Image } from "react-native";
import { useNavigation } from "@react-navigation/native";
import { CheckBox } from "react-native-elements";
import { AS } from "../../storageControl";
import icons from "../../assets/icons/icons";
import app from "../../app.json";
import { ListItem } from "native-base";
import {
setAlternateAppIcon,
resetAppIcon,
getAppIconName,
supportsAlternateIcons,
} from "expo-alternate-app-icons";
import { widthPercentageToDP } from "react-native-responsive-screen";
export const LauncherIconSettings = ({ navigate }) => {
const { goBack } = useNavigation();
const [iconList, ] = useState(icons());
const [currentIcon, ] = useState(getAppIconName());
return (
<View style={{ height: "100%", backgroundColor: "#0099CC" }}>
<View style={{ backgroundColor: "#0099CC", flexDirection: "row" }}>
<View style={{ flex: 1 }}>
<TouchableOpacity
onPress={goBack}
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" }}>
{currentIcon ? (
<>
<Text
style={{
backgroundColor: "#DDDDDD",
}}
>
現在のアイコン:
{iconList.filter(({ id }) => id == currentIcon)[0].id}
</Text>
<View
style={{
flexDirection: "cokumn",
alignItems: "center",
justifyContent: "center",
backgroundColor: "#DDDDDD",
padding: 10,
}}
>
<Image
source={
iconList.filter(({ id }) => id == currentIcon)[0].icon
}
style={{
width: 50,
height: 50,
padding: 30,
borderWidth: 1,
borderRadius: 10,
borderColor: "white",
margin: 10,
backgroundColor: "white",
}}
/>
<Text>JR四国非公式アプリ</Text>
</View>
</>
) : (
<></>
)}
<View
style={{
flexDirection: "row",
flexWrap: "wrap",
alignContent: "center",
justifyContent: "center",
}}
>
{iconList.map(({ name, icon, id }) => {
return (
<TouchableOpacity
key={id}
style={{
margin: 10,
alignItems: "center",
justifyContent: "center",
width: widthPercentageToDP("30%"),
maxWidth: 60,
height: 100,
borderColor: "#999999",
borderWidth: id == currentIcon ? 2 : 0,
borderRadius: 10,
}}
onPress={() => {
setAlternateAppIcon(id)
.then((res) => {
alert(res);
})
.catch((err) => {
alert(err);
});
}}
>
<Image source={icon} style={{ width: 50, height: 50 }} />
<Text>{id}</Text>
</TouchableOpacity>
);
})}
</View>
</ScrollView>
</View>
);
};

View File

@ -1,5 +1,6 @@
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 { useNavigation } from "@react-navigation/native";
import { SwitchArea } from "../atom/SwitchArea"; import { SwitchArea } from "../atom/SwitchArea";
import { CheckBox } from "react-native-elements"; import { CheckBox } from "react-native-elements";
import { TripleSwitchArea } from "../atom/TripleSwitchArea"; import { TripleSwitchArea } from "../atom/TripleSwitchArea";
@ -21,12 +22,13 @@ export const LayoutSettings = ({
headerSize, headerSize,
setHeaderSize, setHeaderSize,
}) => { }) => {
const { goBack } = useNavigation();
return ( return (
<View style={{ height: "100%", backgroundColor: "#0099CC" }}> <View style={{ height: "100%", backgroundColor: "#0099CC" }}>
<View style={{ backgroundColor: "#0099CC", flexDirection: "row" }}> <View style={{ backgroundColor: "#0099CC", flexDirection: "row" }}>
<View style={{ flex: 1 }}> <View style={{ flex: 1 }}>
<TouchableOpacity <TouchableOpacity
onPress={() => navigate("settingTopPage")} onPress={goBack}
style={{ style={{
flexDirection: "column", flexDirection: "column",
flex: 1, flex: 1,

View File

@ -1,12 +1,15 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { View, Text, TouchableOpacity, ScrollView,Clipboard } from "react-native"; import { View, Text, TouchableOpacity, ScrollView } from "react-native";
import * as Clipboard from 'expo-clipboard';
import { CheckBox } from "react-native-elements"; import { CheckBox } from "react-native-elements";
import { AS } from "../../storageControl"; import { AS } from "../../storageControl";
import { useNotification } from "../../stateBox/useNotifications"; import { useNotification } from "../../stateBox/useNotifications";
import { useNavigation } from "@react-navigation/native";
export const NotificationSettings = ({ navigate }) => { export const NotificationSettings = () => {
const { expoPushToken } = useNotification(); const { expoPushToken } = useNotification();
const { goBack } = useNavigation();
const [traInfoEX, setTraInfoEX] = useState(false); const [traInfoEX, setTraInfoEX] = useState(false);
const [informations, setInformations] = useState(false); const [informations, setInformations] = useState(false);
const [strangeTrain, setStrangeTrain] = useState(false); const [strangeTrain, setStrangeTrain] = useState(false);
@ -21,9 +24,7 @@ export const NotificationSettings = ({ navigate }) => {
<View style={{ backgroundColor: "#0099CC", flexDirection: "row" }}> <View style={{ backgroundColor: "#0099CC", flexDirection: "row" }}>
<View style={{ flex: 1 }}> <View style={{ flex: 1 }}>
<TouchableOpacity <TouchableOpacity
onPress={() => { onPress={goBack}
navigate("settingTopPage");
}}
style={{ style={{
flexDirection: "column", flexDirection: "column",
flex: 1, flex: 1,
@ -40,7 +41,7 @@ export const NotificationSettings = ({ navigate }) => {
padding: 10, padding: 10,
}} }}
> >
設定/送信 設定
</Text> </Text>
<View style={{ flex: 1 }} /> <View style={{ flex: 1 }} />
</TouchableOpacity> </TouchableOpacity>
@ -120,9 +121,10 @@ export const NotificationSettings = ({ navigate }) => {
setBool={setStrangeTrain} setBool={setStrangeTrain}
str="怪レい列車" str="怪レい列車"
/> />
<Text style={{fontWeight: "bold", padding: 10 }} onPress={()=>{ <Text
Clipboard.setString(expoPushToken); style={{ fontWeight: "bold", padding: 10 }}
}}> onPress={() => Clipboard.setStringAsync(expoPushToken)}
>
通知を受け取りたい項目を選択してくださいチェックボックスを選び右上の登録実行を押すと設定が反映され通知が届くようになります 通知を受け取りたい項目を選択してくださいチェックボックスを選び右上の登録実行を押すと設定が反映され通知が届くようになります
</Text> </Text>
</ScrollView> </ScrollView>

View File

@ -10,14 +10,15 @@ import {
} from "react-native"; } from "react-native";
import * as Updates from "expo-updates"; import * as Updates from "expo-updates";
import { useWindowDimensions } from "react-native"; import { useWindowDimensions } from "react-native";
import { ListItem } from "native-base"; import { useNavigation } from "@react-navigation/native";
import { ListItem } from "@rneui/themed";
import TouchableScale from "react-native-touchable-scale";
import { SwitchArea } from "../atom/SwitchArea"; import { SwitchArea } from "../atom/SwitchArea";
import { useNotification } from "../../stateBox/useNotifications"; import { useNotification } from "../../stateBox/useNotifications";
const versionCode = "5.6.0.2"; const versionCode = "6.0";
export const SettingTopPage = ({ export const SettingTopPage = ({
navigate,
testNFC, testNFC,
startPage, startPage,
setStartPage, setStartPage,
@ -25,12 +26,13 @@ export const SettingTopPage = ({
}) => { }) => {
const { width } = useWindowDimensions(); const { width } = useWindowDimensions();
const { expoPushToken } = useNotification(); const { expoPushToken } = useNotification();
const navigation = useNavigation();
return ( return (
<View style={{ height: "100%", backgroundColor: "#0099CC" }}> <View style={{ height: "100%", backgroundColor: "#0099CC" }}>
<View style={{ backgroundColor: "#0099CC", flexDirection: "row" }}> <View style={{ backgroundColor: "#0099CC", flexDirection: "row" }}>
<View style={{ flex: 1 }}> <View style={{ flex: 1 }}>
<TouchableOpacity <TouchableOpacity
onPress={() => navigate("menu")} onPress={() => navigation.goBack()}
style={{ style={{
flexDirection: "column", flexDirection: "column",
flex: 1, flex: 1,
@ -118,179 +120,63 @@ export const SettingTopPage = ({
falseText={"リンクメニュー"} falseText={"リンクメニュー"}
trueText={"列車位置情報"} trueText={"列車位置情報"}
/> />
<ListItem <SettingList
style={{ flexDirection: "row" }} string="お気に入り登録の並び替え"
onPress={() => navigate("FavoriteSettings")} onPress={() =>
> navigation.navigate("setting", { screen: "FavoriteSettings" })
<Text }
style={{ />
fontSize: 20, <SettingList
alignItems: "center", string={`通知設定${
alignContent: "center", expoPushToken == "" ? "(通知設定をオンにしてください)" : "(β)"
textAlign: "center", }`}
textAlignVertical: "center", onPress={() =>
}} navigation.navigate("setting", { screen: "NotificationSettings" })
> }
お気に入り登録の並び替え
</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("NotificationSettings")}
disabled={expoPushToken == ""} disabled={expoPushToken == ""}
> />
<Text
style={{ <SettingList
fontSize: 20, string="レイアウト設定"
alignItems: "center", onPress={() =>
alignContent: "center", navigation.navigate("setting", { screen: "LayoutSettings" })
textAlign: "center", }
textAlignVertical: "center", />
}}
>
通知設定{expoPushToken == "" ? "(通知設定をオンにしてください)" : "(β)"}
</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" ? ( {Platform.OS === "android" ? (
<ListItem <SettingList
style={{ flexDirection: "row" }} string="ウィジェット設定"
onPress={() => navigate("WidgetSettings")} onPress={() =>
> navigation.navigate("setting", { screen: "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} ) : null}
<ListItem <SettingList
style={{ flexDirection: "row" }} string="アイコン設定"
onPress={() =>
navigation.navigate("setting", { screen: "LauncherIconSettings" })
}
/>
<SettingList
string="プライバシーポリシー"
onPress={() => onPress={() =>
Linking.openURL( Linking.openURL(
"https://nexcloud.haruk.in/sites/press-harukin/JRShikokuApps/policy" "https://nexcloud.haruk.in/sites/press-harukin/JRShikokuApps/policy"
) )
} }
> />
<Text
style={{ <SettingList
fontSize: 20, string="開発情報"
alignItems: "center",
alignContent: "center",
textAlign: "center",
textAlignVertical: "center",
}}
>
プライバシーポリシー
</Text>
<View style={{ flex: 1 }} />
</ListItem>
<ListItem
style={{ flexDirection: "row" }}
onPress={() => onPress={() =>
Linking.openURL("https://nexcloud.haruk.in/s/2WFEN5oLPGtrRqT") 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 }} /> <SettingList
</ListItem> string="運営Twitter"
<ListItem
style={{ flexDirection: "row" }}
onPress={() => Linking.openURL("https://twitter.com/Xprocess_main")} 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()}> {/* <ListItem style={{ flexDirection: "row" }} onPress={() => testNFC()}>
<Text <Text
style={{ style={{
@ -328,3 +214,20 @@ export const SettingTopPage = ({
</View> </View>
); );
}; };
const SettingList = ({ string, onPress, disabled }) => {
return (
<ListItem
activeScale={0.95}
Component={TouchableScale}
bottomDivider
onPress={onPress}
disabled={disabled}
>
<ListItem.Content>
<ListItem.Title>{string}</ListItem.Title>
</ListItem.Content>
<ListItem.Chevron />
</ListItem>
);
};

View File

@ -1,8 +1,7 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { View, Text, TouchableOpacity, ScrollView } from "react-native"; import { View, Text, TouchableOpacity, ScrollView } from "react-native";
import { SwitchArea } from "../atom/SwitchArea"; import { useNavigation } from "@react-navigation/native";
import { CheckBox } from "react-native-elements"; import { CheckBox } from "react-native-elements";
import { TripleSwitchArea } from "../atom/TripleSwitchArea";
import { getWidgetInfo, WidgetPreview } from "react-native-android-widget"; import { getWidgetInfo, WidgetPreview } from "react-native-android-widget";
import { getDelayData } from "../AndroidWidget/TraInfoEXWidget"; import { getDelayData } from "../AndroidWidget/TraInfoEXWidget";
import { getInfoString } from "../AndroidWidget/InfoWidget"; import { getInfoString } from "../AndroidWidget/InfoWidget";
@ -12,6 +11,7 @@ import { ListItem } from "native-base";
export const WidgetSettings = ({ navigate }) => { export const WidgetSettings = ({ navigate }) => {
const { JR_shikoku_train_info, Info_Widget } = nameToWidget; const { JR_shikoku_train_info, Info_Widget } = nameToWidget;
const { goBack } = useNavigation();
const [time, setTime] = useState(); const [time, setTime] = useState();
const [delayString, setDelayString] = useState(); const [delayString, setDelayString] = useState();
const [trainInfo, setTrainInfo] = useState(); const [trainInfo, setTrainInfo] = useState();
@ -25,7 +25,9 @@ export const WidgetSettings = ({ navigate }) => {
setWidgetList(d); setWidgetList(d);
}; };
useEffect(reload, []); useEffect(() => {
reload();
}, []);
useEffect(() => { useEffect(() => {
getDelayData().then(({ time, delayString }) => { getDelayData().then(({ time, delayString }) => {
@ -42,7 +44,7 @@ export const WidgetSettings = ({ navigate }) => {
<View style={{ backgroundColor: "#0099CC", flexDirection: "row" }}> <View style={{ backgroundColor: "#0099CC", flexDirection: "row" }}>
<View style={{ flex: 1 }}> <View style={{ flex: 1 }}>
<TouchableOpacity <TouchableOpacity
onPress={() => navigate("settingTopPage")} onPress={goBack}
style={{ style={{
flexDirection: "column", flexDirection: "column",
flex: 1, flex: 1,

View File

@ -23,6 +23,7 @@ import { LayoutSettings } from "./LayoutSettings";
import { FavoriteSettings } from "./FavoriteSettings"; import { FavoriteSettings } from "./FavoriteSettings";
import { WidgetSettings } from "./WidgetSettings"; import { WidgetSettings } from "./WidgetSettings";
import { NotificationSettings } from "./NotificationSettings"; import { NotificationSettings } from "./NotificationSettings";
import { LauncherIconSettings } from "./LauncherIconSettings";
const Stack = createStackNavigator(); const Stack = createStackNavigator();
export default function Setting(props) { export default function Setting(props) {
@ -148,6 +149,18 @@ export default function Setting(props) {
> >
{(props) => <WidgetSettings {...props} navigate={navigate} />} {(props) => <WidgetSettings {...props} navigate={navigate} />}
</Stack.Screen> </Stack.Screen>
<Stack.Screen
name="LauncherIconSettings"
options={{
gestureEnabled: true,
...TransitionPresets.SlideFromRightIOS,
cardOverlayEnabled: true,
headerTransparent: true,
headerShown: false,
}}
>
{(props) => <LauncherIconSettings {...props} navigate={navigate} />}
</Stack.Screen>
<Stack.Screen <Stack.Screen
name="FavoriteSettings" name="FavoriteSettings"
options={{ options={{

View File

@ -1,5 +1,6 @@
import React, { FC } from "react"; import React, { FC } from "react";
import { Marker } from "react-native-maps"; import { Marker } from "react-native-maps";
import { useNavigation } from "@react-navigation/native";
type Props = { type Props = {
index: number; index: number;
indexBase: number; indexBase: number;
@ -12,6 +13,7 @@ type Props = {
export const MapPin: FC<Props> = (props) => { export const MapPin: FC<Props> = (props) => {
const { index, indexBase, latlng, D, d, navigate, webview } = props; const { index, indexBase, latlng, D, d, navigate, webview } = props;
const {goBack} = useNavigation();
return ( return (
<Marker <Marker
key={index + indexBase} key={index + indexBase}
@ -24,7 +26,7 @@ export const MapPin: FC<Props> = (props) => {
`MoveDisplayStation('${d}_${D.MyStation}_${D.Station_JP}'); `MoveDisplayStation('${d}_${D.MyStation}_${D.Station_JP}');
document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");` document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");`
); );
if (navigate) navigate("Apps"); if (navigate) goBack();
}} }}
image={require("../../assets/reccha-small.png")} image={require("../../assets/reccha-small.png")}
></Marker> ></Marker>

View File

@ -6,7 +6,7 @@ import { news } from "../config/newsUpdate";
import { useNavigation } from "@react-navigation/native"; import { useNavigation } from "@react-navigation/native";
import { BigButton } from "./atom/BigButton"; import { BigButton } from "./atom/BigButton";
const News: FC = () => { const News: FC = () => {
const { navigate } = useNavigation(); const { goBack } = useNavigation();
return ( return (
<View style={{ height: "100%", backgroundColor: "#0099CC" }}> <View style={{ height: "100%", backgroundColor: "#0099CC" }}>
<WebView <WebView
@ -20,7 +20,7 @@ const News: FC = () => {
<BigButton <BigButton
onPress={() => { onPress={() => {
AS.setItem("status", news); AS.setItem("status", news);
navigate("Apps"); goBack();
}} }}
string="更新情報を閉じる" string="更新情報を閉じる"
/> />

View File

@ -1,7 +1,6 @@
import React, { useRef, useState, useEffect, useLayoutEffect } from "react"; import React, { useRef, useState, useEffect, useLayoutEffect } 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 from "react-native-maps";
import { MaterialCommunityIcons, Ionicons } from "@expo/vector-icons";
import { useCurrentTrain } from "../stateBox/useCurrentTrain"; import { useCurrentTrain } from "../stateBox/useCurrentTrain";
import { useNavigation } from "@react-navigation/native"; import { useNavigation } from "@react-navigation/native";
import lineColorList from "../assets/originData/lineColorList"; import lineColorList from "../assets/originData/lineColorList";
@ -15,7 +14,7 @@ import { MapsButton } from "./TrainMenu/MapsButton";
export default function TrainMenu({ style }) { export default function TrainMenu({ style }) {
const { webview } = useCurrentTrain(); const { webview } = useCurrentTrain();
const mapRef = useRef(); const mapRef = useRef();
const { navigate } = useNavigation(); const { navigate, goBack } = useNavigation();
const [stationPin, setStationPin] = useState([]); const [stationPin, setStationPin] = useState([]);
const { const {
selectedLine, selectedLine,
@ -35,12 +34,6 @@ export default function TrainMenu({ style }) {
"" ""
).split(","); ).split(",");
if (latlng.length == 0) return null; if (latlng.length == 0) return null;
if (index == 0 && stationPin.length > 0) {
setInjectJavaScript(
`MoveDisplayStation('${d}_${D.MyStation}_${D.Station_JP}');
document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");`
);
}
stationPinData.push({ D, d, latlng, indexBase: 0, index }); stationPinData.push({ D, d, latlng, indexBase: 0, index });
}); });
}); });
@ -152,7 +145,27 @@ export default function TrainMenu({ style }) {
opacity: selectedLine == d ? 1 : !selectedLine ? 1 : 0.5, opacity: selectedLine == d ? 1 : !selectedLine ? 1 : 0.5,
zIndex: 10, zIndex: 10,
}} }}
onPress={() => setSelectedLine(selectedLine == d ? undefined : d)} onPress={() => {
const s = selectedLine == d ? undefined : d;
if(!s) return;
setSelectedLine(s);
Object.keys(stationData).forEach((data, indexBase) => {
stationData[data].forEach((D, index) => {
if (!D.StationMap) return null;
if (s && s != data) return;
const latlng = D.StationMap.replace(
"https://www.google.co.jp/maps/place/",
""
).split(",");
if (latlng.length == 0) return null;
if (index == 0 && stationPin.length > 0) {
webview.current
?.injectJavaScript(`MoveDisplayStation('${data}_${D.MyStation}_${D.Station_JP}');
document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");`);
}
});
});
}}
> >
<Text <Text
style={{ color: "white", fontWeight: "bold", fontSize: 20 }} style={{ color: "white", fontWeight: "bold", fontSize: 20 }}
@ -201,7 +214,7 @@ export default function TrainMenu({ style }) {
)} )}
<MapsButton <MapsButton
onPress={() => { onPress={() => {
navigate("Apps"); goBack();
webview.current?.injectJavaScript(injectJavaScript); webview.current?.injectJavaScript(injectJavaScript);
}} }}
top={0} top={0}

View File

@ -1,4 +1,4 @@
import React, { useRef } from "react"; import React from "react";
import { StatusBar, Platform, View } from "react-native"; import { StatusBar, Platform, View } from "react-native";
import { WebView } from "react-native-webview"; import { WebView } from "react-native-webview";
import { MaterialCommunityIcons } from "@expo/vector-icons"; import { MaterialCommunityIcons } from "@expo/vector-icons";
@ -6,44 +6,40 @@ import { useNavigation } from "@react-navigation/native";
import { BigButton } from "./atom/BigButton"; import { BigButton } from "./atom/BigButton";
export default function TrainBase({ route }) { export default function TrainBase({ route }) {
const { info, from } = route.params; const { info } = route.params;
const { navigate } = useNavigation(); const { goBack } = useNavigation();
const webview = useRef(); const jss = `
const jss = `document.getElementById('Footer').style.display = 'none'; document.getElementById('Footer').style.display = 'none';
${ ${
Platform.OS == "ios" && Platform.OS == "ios"
`document.getElementsByTagName("html")[0].style['font-size'] = '11px';` ? `document.getElementsByTagName("html")[0].style['font-size'] = '11px';`
}`; : ""
//const jss = `alert("ほげ")`; }
true;`;
return ( return (
<View style={{ height: "100%" }}> <View style={{ height: "100%" }}>
{Platform.OS == "ios" && <StatusBar barStyle="dark-content" />} {Platform.OS == "ios" && <StatusBar barStyle="dark-content" />}
<WebView <WebView
//useWebKit={true} useWebKit
ref={webview}
source={{ uri: "https://train.jr-shikoku.co.jp/" + info }} source={{ uri: "https://train.jr-shikoku.co.jp/" + info }}
originWhitelist={[ originWhitelist={[
"https://train.jr-shikoku.co.jp", "https://train.jr-shikoku.co.jp",
"https://train.jr-shikoku.co.jp/sp.html", "https://train.jr-shikoku.co.jp/sp.html",
]} ]}
mixedContentMode={"compatibility"}
javaScriptEnabled={true}
injectedJavaScript={jss}
setSupportMultipleWindows={false}
onMessage={(event) => {}} onMessage={(event) => {}}
mixedContentMode={"compatibility"}
javaScriptEnabled
injectedJavaScript={jss}
setSupportMultipleWindows
/> />
{(from == "LED" || from == "LED2" || from == "AllTrainIDList") && (
<BigButton <BigButton
style={{ borderColor: "black" }} style={{ borderColor: "black" }}
tS={{ color: "black" }} tS={{ color: "black" }}
string="閉じる" string="閉じる"
onPress={() => onPress={goBack}
navigate(from == "AllTrainIDList" ? "AllTrainIDList" : "menu")
}
> >
<MaterialCommunityIcons name="close" color="black" size={30} /> <MaterialCommunityIcons name="close" color="black" size={30} />
</BigButton> </BigButton>
)}
</View> </View>
); );
} }

View File

@ -116,7 +116,7 @@ export default function LED_vision(props) {
if (data.split(",")[0] === station.Station_JP) { if (data.split(",")[0] === station.Station_JP) {
if (data.match(",発,")) { if (data.match(",発,")) {
trainData.time = data.split(",発,")[1]; trainData.time = data.split(",発,")[1];
} else { } else if(data.match(",着,")){
trainData.time = data.split(",着,")[1]; trainData.time = data.split(",着,")[1];
trainData.lastStation = "当駅止"; trainData.lastStation = "当駅止";
} }
@ -127,7 +127,7 @@ export default function LED_vision(props) {
time: trainData.time, time: trainData.time,
lastStation: trainData.lastStation, 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]):
@ -138,6 +138,8 @@ export default function LED_vision(props) {
return -1; return -1;
case parseInt(a.time.split(":")[1]) > parseInt(b.time.split(":")[1]): case parseInt(a.time.split(":")[1]) > parseInt(b.time.split(":")[1]):
return 1; return 1;
default:
return 0;
} }
}); });
}; };

View File

@ -35,6 +35,12 @@
}, },
"production5.0": { "production5.0": {
"channel": "dmm" "channel": "dmm"
},
"beta6.0": {
"channel": "ebookjapan"
},
"production6.0": {
"channel": "ebay"
} }
}, },
"submit": { "submit": {

View File

@ -8,11 +8,10 @@ export default ({ navigation: { navigate }, route }) => {
const { goBack } = useNavigation(); const { goBack } = useNavigation();
const onExit = () => { const onExit = () => {
if (goTo != "NearTrainDiagramView") { if (goTo != "NearTrainDiagramView") {
navigate(goTo || "Apps"); //navigate(goTo || "Apps");
useShow && useShow(); useShow && useShow();
} else {
goBack();
} }
goBack();
}; };
return ( return (
<View style={styles}> <View style={styles}>

View File

@ -1,5 +1,5 @@
// 種別判定 // 種別判定
export const getType = (string) => { export const getType = (string:string) => {
switch (string) { switch (string) {
case "express": case "express":
return "特急"; return "特急";

View File

@ -1,6 +1,6 @@
// Description: 電車名の変換を行う。 // Description: 電車名の変換を行う。
// マリンライナーやマリン表記をマリンライナーに変換する。 // マリンライナーやマリン表記をマリンライナーに変換する。
export const migrateTrainName = (string) => { export const migrateTrainName = (string:string) => {
return string return string
.replace("マリン", "マリンライナー") .replace("マリン", "マリンライナー")
.replace("ライナーライナー", "ライナー"); .replace("ライナーライナー", "ライナー");

View File

@ -1,7 +1,7 @@
// S列番の列車からDやMの列車を検索する // S列番の列車からDやMの列車を検索する
export const searchSpecialTrain = (trainNum, trainList) => { export const searchSpecialTrain = (trainNum: string, trainList: any[]) => {
const searchBase = trainNum.replace("S", "").replace("X", ""); const searchBase = trainNum.replace("S", "").replace("X", "");
const search = (text) => { const search = (text: string) => {
const TD = trainList[searchBase + text]; const TD = trainList[searchBase + text];
if (TD) { if (TD) {
return true; return true;

View File

@ -1,6 +1,6 @@
import { Platform } from "react-native"; import { Platform } from "react-native";
export const getPDFViewURL = (url) => { export const getPDFViewURL = (url:string) => {
if (Platform.OS == "ios") return url; if (Platform.OS == "ios") return url;
else else
return `https://mozilla.github.io/pdf.js/web/viewer.html?file=${encodeURI(url)}`; return `https://mozilla.github.io/pdf.js/web/viewer.html?file=${encodeURI(url)}`;

View File

@ -41,7 +41,7 @@ export const lineListPair = {
M: "瀬戸大橋線(児島-宇多津間)[M]", M: "瀬戸大橋線(児島-宇多津間)[M]",
}; };
export const getStationList = async (props) => { export const getStationList = async () => {
if (status) return status; if (status) return status;
//駅リストイニシャライズ //駅リストイニシャライズ
return await Promise.all([ return await Promise.all([
@ -68,8 +68,8 @@ export const getStationList = async (props) => {
stationList["徳島線(徳島-阿波池田間)[B]"], stationList["徳島線(徳島-阿波池田間)[B]"],
stationList["鳴門線(池谷-鳴門間)[N]"], stationList["鳴門線(池谷-鳴門間)[N]"],
stationList["瀬戸大橋線(児島-宇多津間)[M]"], stationList["瀬戸大橋線(児島-宇多津間)[M]"],
stationList., stationList["駅間リスト"],
stationList., stationList["日英対応表"],
] = values; ] = values;
const concatBetweenStations = (eachRouteData) => { const concatBetweenStations = (eachRouteData) => {
let additional = []; let additional = [];
@ -82,7 +82,7 @@ export const getStationList = async (props) => {
eachRouteData[routeIndex + 1].StationNumber.replace(/[A-Z]/g, "") eachRouteData[routeIndex + 1].StationNumber.replace(/[A-Z]/g, "")
); );
if (nextStationID - currentStationID != 1) { if (nextStationID - currentStationID != 1) {
stationList..forEach((betweenList) => { stationList["駅間リスト"].forEach((betweenList) => {
if ( if (
betweenList.BetweenStation == betweenList.BetweenStation ==
routeData.Station_JP + routeData.Station_JP +
@ -125,12 +125,12 @@ export const getStationList = async (props) => {
stationList["予讃線(高松-松山間)[Y]"] = addStationPosition( stationList["予讃線(高松-松山間)[Y]"] = addStationPosition(
concatBetweenStations(stationList["予讃線(高松-松山間)[Y]"]), concatBetweenStations(stationList["予讃線(高松-松山間)[Y]"]),
, ,
stationList. stationList["日英対応表"]
); );
stationList["予讃線(松山-宇和島間)[U]"] = addStationPosition( stationList["予讃線(松山-宇和島間)[U]"] = addStationPosition(
concatBetweenStations(stationList["予讃線(松山-宇和島間)[U]"]), concatBetweenStations(stationList["予讃線(松山-宇和島間)[U]"]),
, ,
stationList. stationList["日英対応表"]
); );
stationList["予讃線/愛ある伊予灘線(向井原-伊予大洲間)[S]"] = stationList["予讃線/愛ある伊予灘線(向井原-伊予大洲間)[S]"] =
addStationPosition( addStationPosition(
@ -138,32 +138,32 @@ export const getStationList = async (props) => {
stationList["予讃線/愛ある伊予灘線(向井原-伊予大洲間)[S]"] stationList["予讃線/愛ある伊予灘線(向井原-伊予大洲間)[S]"]
), ),
, ,
stationList. stationList["日英対応表"]
); );
stationList["土讃線(多度津-高知間)[D]"] = addStationPosition( stationList["土讃線(多度津-高知間)[D]"] = addStationPosition(
concatBetweenStations(stationList["土讃線(多度津-高知間)[D]"]), concatBetweenStations(stationList["土讃線(多度津-高知間)[D]"]),
, ,
stationList. stationList["日英対応表"]
); );
stationList["土讃線(高知-窪川間)[K]"] = addStationPosition( stationList["土讃線(高知-窪川間)[K]"] = addStationPosition(
concatBetweenStations(stationList["土讃線(高知-窪川間)[K]"]), concatBetweenStations(stationList["土讃線(高知-窪川間)[K]"]),
, ,
stationList. stationList["日英対応表"]
); );
stationList["高徳線(高松-徳島間)[T]"] = addStationPosition( stationList["高徳線(高松-徳島間)[T]"] = addStationPosition(
concatBetweenStations(stationList["高徳線(高松-徳島間)[T]"]), concatBetweenStations(stationList["高徳線(高松-徳島間)[T]"]),
, ,
stationList. stationList["日英対応表"]
); );
stationList["鳴門線(池谷-鳴門間)[N]"] = addStationPosition( stationList["鳴門線(池谷-鳴門間)[N]"] = addStationPosition(
concatBetweenStations(stationList["鳴門線(池谷-鳴門間)[N]"]), concatBetweenStations(stationList["鳴門線(池谷-鳴門間)[N]"]),
, ,
stationList. stationList["日英対応表"]
); );
const tokushimaCurrent = addStationPosition( const tokushimaCurrent = addStationPosition(
concatBetweenStations(stationList["徳島線(徳島-阿波池田間)[B]"]), concatBetweenStations(stationList["徳島線(徳島-阿波池田間)[B]"]),
, ,
stationList. stationList["日英対応表"]
); );
stationList["徳島線(徳島-阿波池田間)[B]"] = [ stationList["徳島線(徳島-阿波池田間)[B]"] = [
tokushimaCurrent[tokushimaCurrent.length - 1], tokushimaCurrent[tokushimaCurrent.length - 1],

View File

@ -5,7 +5,7 @@ type nameString =
| "SPCL" | "SPCL"
| "Normal" | "Normal"
| string; | string;
type colorString = "aqua" | "red" | "blue" | "white"; type colorString = "aqua" | "red" | "#297bff" | "white";
type trainTypeString = type trainTypeString =
| "快速" | "快速"
| "特急" | "特急"
@ -29,7 +29,7 @@ export const getTrainType: getTrainType = (nameString) => {
case "NightLTDEXP": case "NightLTDEXP":
return { color: "red", name: "寝台特急", data: "express" }; return { color: "red", name: "寝台特急", data: "express" };
case "SPCL": case "SPCL":
return { color: "blue", name: "臨時", data: "normal" }; return { color: "#297bff", name: "臨時", data: "normal" };
case "OneMan": case "OneMan":
return { color: "white", name: "普通列車(ワンマン)", data: "normal" }; return { color: "white", name: "普通列車(ワンマン)", data: "normal" };
case "Normal": case "Normal":

View File

@ -1,20 +1,72 @@
import React from "react"; import React, { FC } from "react";
import { Ionicons, AntDesign } from "@expo/vector-icons"; import { Ionicons, AntDesign } from "@expo/vector-icons";
import { Text, View } from "react-native";
type name = keyof typeof Ionicons.glyphMap & keyof typeof AntDesign.glyphMap; type name = keyof typeof Ionicons.glyphMap & keyof typeof AntDesign.glyphMap;
type type = "Ionicons" | "AntDesign"; type type = "Ionicons" | "AntDesign";
export const initIcon = (name: name, type:type) => { export const initIcon = (
name: name,
type: type,
tabBarBadge: string,
isInfo: boolean
) => {
switch (type) { switch (type) {
case "Ionicons": case "Ionicons":
return ({ focused, color, size }) => ( return ({ focused, color, size }) => (
<Ionicons name={name} size={32} color={focused ? "#0099CC" : "black"} /> <>
{!!tabBarBadge && <Badge tabBarBadge={tabBarBadge} isInfo={isInfo} />}
<Ionicons
name={name}
size={30}
color={focused ? "#0099CC" : "black"}
/>
</>
); );
case "AntDesign": case "AntDesign":
return ({ focused, color, size }) => ( return ({ focused, color, size }) => (
<>
{!!tabBarBadge && <Badge tabBarBadge={tabBarBadge} isInfo={isInfo} />}
<AntDesign <AntDesign
name={name} name={name}
size={32} size={30}
color={focused ? "#0099CC" : "black"} color={focused ? "#0099CC" : "black"}
/> />
</>
); );
} }
}; };
type BadgeProps = { tabBarBadge: string; isInfo: boolean };
export const Badge: FC<BadgeProps> = ({ tabBarBadge, isInfo }) => {
return (
<View
style={{
position: "relative",
top: -5,
right: 0,
zIndex: 100,
padding: 1,
width: 0,
}}
>
<View
style={{
position: "absolute",
top: 0,
left: 0,
backgroundColor: isInfo ? "#00b8ff" : "red",
borderRadius: 10,
padding: 2,
shadowColor: "#000",
shadowOffset: { width: 0, height: 0 },
shadowOpacity: 0.5,
shadowRadius: 4,
elevation: 2
}}
>
<Text style={{ color: "white", paddingHorizontal: 4 }}>
{tabBarBadge}
</Text>
</View>
</View>
);
};

View File

@ -1,4 +1,5 @@
export const buildProvidersTree = (providers) => { import React, { FC } from "react";
export const buildProvidersTree:FC<any> = (providers) => {
// 基本ケースContextProviderが1つしか残っていない場合、それを返して終了する // 基本ケースContextProviderが1つしか残っていない場合、それを返して終了する
if (providers.length === 1) { if (providers.length === 1) {
return providers[0]; return providers[0];

View File

@ -26,21 +26,19 @@ export const injectJavascriptData: InjectJavascriptData = (
document.querySelector('#headerStr').style.display = 'none'; document.querySelector('#headerStr').style.display = 'none';
`; `;
// 何これ // 上部ヘッダーの取り扱い、自動再読み込み、setStringsの実行
const bootData = ` const bootData = `
const setReload = () =>{ const setReload = () =>{
try{ try{
document.getElementById('refreshIcon').click(); document.getElementById('refreshIcon').click();
setStrings(); setStrings();
}catch{ }catch(error){}
}
setTimeout(setReload, 10000); setTimeout(setReload, 10000);
} }
setReload(); setReload();
`; `;
// 左か右かを判定してアイコンを設置する // 左か右かを判定してアイコンを設置する
const trainIconMaker = ` const trainIcon = `
const setStationIcon = (setIconElem,img) =>{ const setStationIcon = (setIconElem,img) =>{
if(setIconElem.getAttribute("style").includes("left")){ if(setIconElem.getAttribute("style").includes("left")){
setIconElem.insertAdjacentHTML('beforebegin', "<img src="+img+" style='float:left;height:20px;'>"); setIconElem.insertAdjacentHTML('beforebegin', "<img src="+img+" style='float:left;height:20px;'>");
@ -50,11 +48,7 @@ export const injectJavascriptData: InjectJavascriptData = (
} }
setIconElem.remove(); setIconElem.remove();
} }
`; const setTrainIcon = (,e) =>{
const trainIcon =
iconSetting == "true"
? `
switch(){ switch(){
//しおかぜメイン //しおかぜメイン
//8000 ノーマル //8000 ノーマル
@ -76,14 +70,14 @@ export const injectJavascriptData: InjectJavascriptData = (
case "25M": case "25M":
case "27M": case "27M":
case "29M": case "29M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s8000nr.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s8000nr.png');
break; break;
//8000 アンパン //8000 アンパン
case "10M": case "10M":
case "22M": case "22M":
case "9M": case "9M":
case "21M": case "21M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s8000ap.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s8000ap.png');
break; break;
@ -96,7 +90,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "11M": case "11M":
case "19M": case "19M":
case "23M": case "23M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s8600.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s8600.png');
break; break;
//いしづちメイン //いしづちメイン
@ -119,7 +113,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "1025M": case "1025M":
case "1027M": case "1027M":
case "1029M": case "1029M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s8000no.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s8000no.png');
break; break;
//8000 アンパン //8000 アンパン
@ -127,7 +121,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "1022M": case "1022M":
case "1009M": case "1009M":
case "1021M": case "1021M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s8000ap.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s8000ap.png');
break; break;
//8600 //8600
@ -139,29 +133,29 @@ export const injectJavascriptData: InjectJavascriptData = (
case "1011M": case "1011M":
case "1019M": case "1019M":
case "1023M": case "1023M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s8600_isz.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s8600_isz.png');
break; break;
//MEXP //MEXP
//8000 //8000
case "1092M": case "1092M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s8000nr.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s8000nr.png');
break; break;
//8600 //8600
case "1091M": case "1091M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s8600_isz.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s8600_isz.png');
break; break;
//三桁いしづち //三桁いしづち
//8000 アンパン //8000 アンパン
case "1041M": case "1041M":
case "1044M": case "1044M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s8000ap.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s8000ap.png');
break; break;
//8600 //8600
case "1043M": case "1043M":
case "1042M": case "1042M":
case "1046M": case "1046M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s8600_isz.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s8600_isz.png');
break; break;
@ -184,7 +178,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "51D": case "51D":
case "53D": case "53D":
case "55D": case "55D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s2700.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s2700.png');
break; break;
//2700アンパン //2700アンパン
case "32D": case "32D":
@ -197,7 +191,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "45D": case "45D":
case "49D": case "49D":
case "57D": case "57D":
setStationIcon(element.querySelector("img"),'https://n8n.haruk.in/webhook/dosan-anpanman-pictures.png?trainNum='+); setStationIcon(e.querySelector("img"),'https://n8n.haruk.in/webhook/dosan-anpanman-pictures.png?trainNum='+);
break; break;
@ -217,7 +211,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "3007D": case "3007D":
case "3025D": case "3025D":
case "3031D": case "3031D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s2700_uzu.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s2700_uzu.png');
break; break;
//2700 二両編成 //2700 二両編成
@ -230,7 +224,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "3017D": case "3017D":
case "3019D": case "3019D":
case "3023D": case "3023D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s2700_uzu.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s2700_uzu.png');
break; break;
//2600 //2600
@ -244,13 +238,13 @@ export const injectJavascriptData: InjectJavascriptData = (
case "3021D": case "3021D":
case "3027D": case "3027D":
case "3033D": case "3033D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s2600.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s2600.png');
break; break;
//キハ185 //キハ185
case "3001D": case "3001D":
case "3008D": case "3008D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s185tu_uzu.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s185tu_uzu.png');
break; break;
//マリンライナー //マリンライナー
@ -322,14 +316,14 @@ export const injectJavascriptData: InjectJavascriptData = (
case "3167M": case "3167M":
case "3169M": case "3169M":
case "3175M": case "3175M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s5001.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s5001.png');
break; break;
case "3102M": case "3102M":
case "3101M": case "3101M":
case "3103M": case "3103M":
case "3171M": case "3171M":
case "3173M": case "3173M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s5001k.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s5001k.png');
break; break;
//サンライズ瀬戸 //サンライズ瀬戸
@ -337,7 +331,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "5031M": case "5031M":
case "8041M": //琴平延長高松迄 case "8041M": //琴平延長高松迄
case "8031M": //琴平延長高松以降 case "8031M": //琴平延長高松以降
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/w285.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/w285.png');
break; break;
//宇和海 //宇和海
@ -366,7 +360,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "1075D": case "1075D":
case "1077D": case "1077D":
case "1079D": case "1079D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s2000_uwa.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s2000_uwa.png');
break; break;
//2000 アンパン込み //2000 アンパン込み
case "1054D": case "1054D":
@ -377,7 +371,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "1061D": case "1061D":
case "1067D": case "1067D":
case "1081D": case "1081D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s2002a.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s2002a.png');
break; break;
//しまんと //しまんと
case "2002D": case "2002D":
@ -388,7 +382,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "2003D": case "2003D":
case "2005D": case "2005D":
case "2007D": case "2007D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s2700_smn.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s2700_smn.png');
break; break;
//あしずり 2000 //あしずり 2000
@ -400,7 +394,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "2073D": case "2073D":
case "2079D": case "2079D":
case "2081D": case "2081D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s2000_asi.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s2000_asi.png');
break; break;
//あしずり 2700 //あしずり 2700
@ -411,7 +405,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "2077D": case "2077D":
case "2072D": case "2072D":
case "2083D": case "2083D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s2700_asi.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s2700_asi.png');
break; break;
//剣山 //剣山
case "4002D": case "4002D":
@ -425,19 +419,19 @@ export const injectJavascriptData: InjectJavascriptData = (
case "4007D": case "4007D":
case "4009D": case "4009D":
case "4011D": case "4011D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s185tu.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s185tu.png');
break; break;
//むろと //むろと
case "8051D": case "8051D":
case "8052D": case "8052D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s185_mrt.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s185_mrt.png');
break; break;
//よしのがわトロッコ //よしのがわトロッコ
case "8452D": case "8452D":
case "8451D": case "8451D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s185to_ai.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s185to_ai.png');
break; break;
//岡山高松アントロ //岡山高松アントロ
@ -446,14 +440,14 @@ export const injectJavascriptData: InjectJavascriptData = (
//岡山琴平アントロ //岡山琴平アントロ
case "8277D": case "8277D":
case "8278D": case "8278D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s32to4.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s32to4.png');
break; break;
//千年ものがたり //千年ものがたり
case "8021D": case "8021D":
case "8022D": case "8022D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s185mm1.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s185mm1.png');
break; break;
//夜明けものがたり //夜明けものがたり
@ -461,18 +455,18 @@ export const injectJavascriptData: InjectJavascriptData = (
case "8083D": case "8083D":
case "8073D": case "8073D":
case "8074D": case "8074D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s185ym1.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s185ym1.png');
break; break;
//ラマルドボア //ラマルドボア
case "9253M": case "9253M":
case "9256M": case "9256M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/w213w.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/w213w.png');
break; break;
// 貨物 // 貨物
case "74": case "74":
case "75": case "75":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/ef65_rp0.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/ef65_rp0.png');
break; break;
case "70": case "70":
case "71": case "71":
@ -490,7 +484,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "8071": case "8071":
case "8072": case "8072":
case "8077": case "8077":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/ef210a.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/ef210a.png');
break; break;
// 普通列車系統、6000系運用 // 普通列車系統、6000系運用
@ -506,7 +500,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "147M": case "147M":
//962運用 //962運用
case "114M": case "114M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s6000p.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s6000p.png');
break; break;
@ -514,31 +508,31 @@ export const injectJavascriptData: InjectJavascriptData = (
// ごな線 // ごな線
case "5851D": //219D併結 [ToDo: 219Dとの分割対策] case "5851D": //219D併結 [ToDo: 219Dとの分割対策]
case "5854D": case "5854D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/tosa9640jgr.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/tosa9640jgr.png');
break; break;
//JR車両乗り入れ運用 //JR車両乗り入れ運用
case "5858D": case "5858D":
case "5869D": case "5869D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s1000.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s1000.png');
break; break;
//併結運用の併結される側 [ToDo: 分割対策] //併結運用の併結される側 [ToDo: 分割対策]
case "5845D": case "5845D":
case "5851D": case "5851D":
case "5818D": case "5818D":
case "5820D": case "5820D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/tosa9640.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/tosa9640.png');
break; break;
// 土讃線単体列車のキハ32運用 // 土讃線単体列車のキハ32運用
case "715D": case "715D":
case "718D": case "718D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s32ns.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s32ns.png');
break; break;
// サンライズに伴う気動車代走 // サンライズに伴う気動車代走
case "6219D": case "6219D":
case "6222D": case "6222D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s1000.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s1000.png');
break; break;
// それ以外の土讃線ごな線直通列車 // それ以外の土讃線ごな線直通列車
case "5811D": case "5811D":
@ -567,7 +561,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "5876D": case "5876D":
case "5880D": case "5880D":
case "5882D": case "5882D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/tosa9640.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/tosa9640.png');
break; break;
// それ以外の土讃線普通列車(1000) // それ以外の土讃線普通列車(1000)
case "4210D": case "4210D":
@ -688,7 +682,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "757D": case "757D":
case "761D": case "761D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s1000.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s1000.png');
break; break;
// 予讃線/土讃線普通列車運用(7000,7200) // 予讃線/土讃線普通列車運用(7000,7200)
// 下り列車(伊予西条-松山は全て7000系) // 下り列車(伊予西条-松山は全て7000系)
@ -742,7 +736,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "155M": case "155M":
case "1263M": case "1263M":
case "157M": case "157M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s7200.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s7200.png');
break; break;
// 下り7000系 // 下り7000系
case "101M": case "101M":
@ -754,7 +748,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "555M": case "555M":
case "4565M": case "4565M":
case "159M": case "159M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s7000.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s7000.png');
break; break;
// 上り列車 7200系 // 上り列車 7200系
case "5102M": case "5102M":
@ -808,7 +802,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "1606M": case "1606M":
case "5160M": case "5160M":
case "5256M": case "5256M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s7200.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s7200.png');
break; break;
// 上り7000系 // 上り7000系
case "114M": case "114M":
@ -819,7 +813,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "4542M": case "4542M":
case "162M": case "162M":
case "4166M": case "4166M":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s7000.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s7000.png');
break; break;
// 松山界隈気動車運用 // 松山界隈気動車運用
// 上り下りの概念アリ // 上り下りの概念アリ
@ -842,28 +836,28 @@ export const injectJavascriptData: InjectJavascriptData = (
case "4824D": case "4824D":
case "4813D": case "4813D":
case "4664D": case "4664D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s32s.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s32s.png');
break; break;
// 河童うようよ号偶数 // 河童うようよ号偶数
case "4816D": case "4816D":
case "4830D": case "4830D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s32kpuy2.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s32kpuy2.png');
break; break;
// 河童うようよ号奇数 // 河童うようよ号奇数
case "4827D": case "4827D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s32kpuy1.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s32kpuy1.png');
break; break;
// 新幹線偶数 // 新幹線偶数
case "4810D": case "4810D":
case "4822D": case "4822D":
case "4826D": case "4826D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s32tht.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s32tht.png');
break; break;
// 新幹線奇数 // 新幹線奇数
case "4817D": case "4817D":
case "4823D": case "4823D":
case "4829D": case "4829D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s32thtk.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s32thtk.png');
break; break;
// キハ54 通常運用 // キハ54 通常運用
case "4632D": case "4632D":
@ -906,29 +900,29 @@ export const injectJavascriptData: InjectJavascriptData = (
case "4922D": case "4922D":
case "4923D": case "4923D":
case "4663D": case "4663D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s54s.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s54s.png');
break; break;
// 54しまんとろっこ // 54しまんとろっこ
case "4623D": case "4623D":
case "8814D": case "8814D":
case "8819D": case "8819D":
case "4662D": case "4662D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s54to0ys.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s54to0ys.png');
break; break;
// キハ185 通常運用 // キハ185 通常運用
case "911D": case "911D":
case "628D": case "628D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s185cm.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s185cm.png');
break; break;
// 伊予灘ものがたり 赤 // 伊予灘ものがたり 赤
case "8091D": case "8091D":
case "8093D": case "8093D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s185iyor.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s185iyor.png');
break; break;
// 伊予灘ものがたり 黄 // 伊予灘ものがたり 黄
case "8092D": case "8092D":
case "8094D": case "8094D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s185iyoy.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s185iyoy.png');
break; break;
// 高徳線、徳島線、牟岐線、鳴門線普通列車系統 // 高徳線、徳島線、牟岐線、鳴門線普通列車系統
// キハ40・47 // キハ40・47
@ -955,7 +949,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "976D": case "976D":
case "980D": case "980D":
case "982D": case "982D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s40.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s40.png');
break; break;
// 1000形 // 1000形
case "4309D": case "4309D":
@ -968,7 +962,7 @@ export const injectJavascriptData: InjectJavascriptData = (
case "473D": case "473D":
case "450D": case "450D":
case "480D": case "480D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s1000.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s1000.png');
break; break;
// 1200形 // 1200形
case "4301D": case "4301D":
@ -1016,117 +1010,154 @@ export const injectJavascriptData: InjectJavascriptData = (
case "4962D": case "4962D":
case "4966D": case "4966D":
case "4978D": case "4978D":
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s1200n.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s1200n.png');
break; break;
default: //指定車両でなく、Regexでの指定に移動 default: //指定車両でなく、Regexでの指定に移動
// 琴平直通系普通電車 // 琴平直通系普通電車
if(new RegExp(/^(1|4|5)2\\d\\dM$/).test()){ if(new RegExp(/^(1|4|5)2\\d\\dM$/).test()){
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s7200.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s7200.png');
break; break;
} }
else if(new RegExp(/^(1|4|5)(1|5|6)\\d\\dM$/).test()){ else if(new RegExp(/^(1|4|5)(1|5|6)\\d\\dM$/).test()){
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s7000.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s7000.png');
break; break;
} }
else if(new RegExp(/^(1|5|6)\\d\\dM$/).test()){ else if(new RegExp(/^(1|5|6)\\d\\dM$/).test()){
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s7000.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s7000.png');
break; break;
}// 高徳線 普通列車系統 }// 高徳線 普通列車系統
else if(new RegExp(/^(4|5)3\\d\\dD$/).test()){ else if(new RegExp(/^(4|5)3\\d\\dD$/).test()){
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s1500.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s1500.png');
break; break;
} }
else if(new RegExp(/^3\\d\\dD$/).test()){ else if(new RegExp(/^3\\d\\dD$/).test()){
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s1500.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s1500.png');
break; break;
}// 徳島線 普通列車系統 }// 徳島線 普通列車系統
else if(new RegExp(/^(4|5)4\\d\\dD$/).test()){ else if(new RegExp(/^(4|5)4\\d\\dD$/).test()){
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s1500.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s1500.png');
break; break;
} }
else if(new RegExp(/^4\\d\\dD$/).test()){ else if(new RegExp(/^4\\d\\dD$/).test()){
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s1500.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s1500.png');
break; break;
}// 鳴門線普通列車系統 }// 鳴門線普通列車系統
else if(new RegExp(/^(4|5)9(5|6|7|8)\\dD$/).test()){ else if(new RegExp(/^(4|5)9(5|6|7|8)\\dD$/).test()){
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s1500.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s1500.png');
break; break;
} }
else if(new RegExp(/^9(5|6|7|8)\\dD$/).test()){ else if(new RegExp(/^9(5|6|7|8)\\dD$/).test()){
setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s1500.png'); setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s1500.png');
break; break;
} }
// 牟岐線普通列車系統 一旦閉鎖 // 牟岐線普通列車系統 一旦閉鎖
// else if(new RegExp(/^(4|5)5\\d\\dD$/).test(列番データ)){ // else if(new RegExp(/^(4|5)5\\d\\dD$/).test(列番データ)){
// setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s7200.png'); // setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s7200.png');
// break; // break;
// } // }
// else if(new RegExp(/^5\\d\\dD$/).test(列番データ)){ // else if(new RegExp(/^5\\d\\dD$/).test(列番データ)){
// setStationIcon(element.querySelector("img"),'https://storage.haruk.in/s7000.png'); // setStationIcon(e.querySelector("img"),'https://storage.haruk.in/s7000.png');
// break; // break;
// } // }
break; break;
} }
` }
: ``; `;
const normal_train_name = ` const normal_train_name = `
const nameReplace = (,,) =>{
let isWanman = false;
let trainName = "";
let viaData = "";
let ToData = "";
let TrainNumber = ;
try{
const diagram = trainTimeInfo[];
if(diagram){
const diagramData = diagram.split("#");
ToData = diagramData[diagramData.length - 2].split(",")[0];
}
}catch(e){}
if(.split(":")[1]){
const textBase = .split(":")[1].replace("\\r","");
trainName = textBase;
}
if(.match("サンポート")){ if(.match("サンポート")){
const textBase = .split(":")[1]; const textBase = .split(":")[1].replace("\\r","");
.innerText = textBase+.innerText; .innerText = textBase+.innerText;
trainName = textBase;
} }
if(new RegExp(/^4[1-9]\\d\\d[DM]$/).test() || new RegExp(/^5[1-7]\\d\\d[DM]$/).test() || ==="3621D"){ if(new RegExp(/^4[1-9]\\d\\d[DM]$/).test() || new RegExp(/^5[1-7]\\d\\d[DM]$/).test() || ==="3621D"){
.innerText = "ワンマン\\n"+.innerText; .innerText = "ワンマン\\n"+.innerText;
flag=true; flag=true;
isWanman = true;
} }
if(new RegExp(/^49[0-4]\\dD$/).test() || new RegExp(/^9[0-4]\\dD$/).test()){ if(new RegExp(/^49[0-4]\\dD$/).test() || new RegExp(/^9[0-4]\\dD$/).test()){
.innerText = "(海経由)"+(flag ? "" : "\\n")+.innerText; .innerText = "(海経由)"+(flag ? "" : "\\n")+.innerText;
viaData = "(海経由)";
} }
if(new RegExp(/^46\\d\\dD$/).test() || new RegExp(/^6\\d\\dD$/).test()){ if(new RegExp(/^46\\d\\dD$/).test() || new RegExp(/^6\\d\\dD$/).test()){
.innerText = "(内子経由)"+(flag ? "" : "\\n")+.innerText; .innerText = "(内子経由)"+(flag ? "" : "\\n")+.innerText;
viaData = "(内子経由)";
} }
if(.indexOf("H") != -1){ if(.indexOf("H") != -1){
.innerText = .innerText+"試運転\\n"; .innerText = .innerText+"試運転\\n";
trainName = "試運転";
} }
else if(.indexOf("R") != -1){ else if(.indexOf("R") != -1){
.innerText = .innerText+"回送\\n"; .innerText = .innerText+"回送\\n";
trainName = "回送";
} }
else if(.indexOf("S") != -1){ else if(.indexOf("S") != -1){
.innerText = .innerText+"臨時列車\\n"; .innerText = .innerText+"臨時列車\\n";
trainName = "臨時列車";
} }
`;
const JRF_name = `
let JRF = false; let JRF = false;
const getJRF = num =>{ const getJRF = num =>{
switch(num){ switch(num){
case "71": case "71":
trainName = "東京(タ)→高松(タ)";
return "東京(タ)→高松(タ)"+"\\n"; return "東京(タ)→高松(タ)"+"\\n";
case "73": case "73":
case "75": case "75":
trainName = "大阪(タ)→高松(タ)";
return "大阪(タ)→高松(タ)"+"\\n"; return "大阪(タ)→高松(タ)"+"\\n";
case "3079": case "3079":
trainName = "高松(タ)→伊予三島";
return "高松(タ)→伊予三島"+"\\n"; return "高松(タ)→伊予三島"+"\\n";
case "3071": case "3071":
case "3077": case "3077":
trainName = "高松(タ)→新居浜";
return "高松(タ)→新居浜"+"\\n"; return "高松(タ)→新居浜"+"\\n";
case "3073": case "3073":
trainName = "高松(タ)→松山貨物";
return "高松(タ)→松山貨物"+"\\n"; return "高松(タ)→松山貨物"+"\\n";
case "70": case "70":
trainName = "高松(タ)→東京(タ)";
return "高松(タ)→東京(タ)"+"\\n"; return "高松(タ)→東京(タ)"+"\\n";
case "74": case "74":
case "76": case "76":
trainName = "高松(タ)→大阪(タ)";
return "高松(タ)→大阪(タ)"+"\\n"; return "高松(タ)→大阪(タ)"+"\\n";
case "3078": case "3078":
trainName = "伊予三島→高松(タ)";
return "伊予三島→高松(タ)"+"\\n"; return "伊予三島→高松(タ)"+"\\n";
case "3070": case "3070":
trainName = "新居浜→高松(タ)";
return "新居浜→高松(タ)"+"\\n"; return "新居浜→高松(タ)"+"\\n";
case "3076": case "3076":
trainName = "新居浜→高松(タ)";
return "新居浜→高松(タ)"+"\\n"; return "新居浜→高松(タ)"+"\\n";
case "3072": case "3072":
trainName = "松山貨物→高松(タ)";
return "松山貨物→高松(タ)"+"\\n"; return "松山貨物→高松(タ)"+"\\n";
case "9070": case "9070":
trainName = "臨時貨物";
return "臨時貨物"+"\\n"; return "臨時貨物"+"\\n";
default: default:
JRF = true; JRF = true;
@ -1136,9 +1167,6 @@ const getJRF = num =>{
const data = getJRF(); const data = getJRF();
.innerText = data != null ? data+行き先情報.innerText : 行き先情報.innerText; .innerText = data != null ? data+行き先情報.innerText : 行き先情報.innerText;
`;
const Other_Name = `
const getThrew = num =>{ const getThrew = num =>{
switch(num){ switch(num){
@ -1146,56 +1174,92 @@ const data = getJRF(列番データ);
case "351D": case "351D":
case "468D": case "468D":
case "484D": case "484D":
viaData = "牟岐線直通";
ToData = "牟岐";
return "牟岐線直通\\n牟岐行"; return "牟岐線直通\\n牟岐行";
case "951D": case "951D":
viaData = "牟岐線直通";
ToData = "桑野";
return "牟岐線直通\\n桑野行"; return "牟岐線直通\\n桑野行";
case "4430D": case "4430D":
case "4472D": case "4472D":
viaData = "牟岐線直通";
isWanman = true;
ToData = "牟岐";
return "牟岐線直通\\nワンマン 牟岐行"; return "牟岐線直通\\nワンマン 牟岐行";
case "434D": case "434D":
case "474D": case "474D":
case "478D": case "478D":
case "480D": case "480D":
viaData = "牟岐線直通";
ToData = "阿南";
return "牟岐線直通\\n阿南行"; return "牟岐線直通\\n阿南行";
case "5444D": case "5444D":
case "4452D": case "4452D":
case "4458D": case "4458D":
case "4460D": case "4460D":
case "4466D": case "4466D":
viaData = "牟岐線直通";
isWanman = true;
ToData = "阿南";
return "牟岐線直通\\nワンマン 阿南行"; return "牟岐線直通\\nワンマン 阿南行";
case "4464D": case "4464D":
viaData = "牟岐線直通";
isWanman = true;
ToData = "阿波海南"
return "牟岐線直通\\nワンマン 阿波海南行"; return "牟岐線直通\\nワンマン 阿波海南行";
//安芸行と併結列車を個別に表示、それ以外をdefaultで下りなら既定の行き先を、上りなら奈半利行を設定 //安芸行と併結列車を個別に表示、それ以外をdefaultで下りなら既定の行き先を、上りなら奈半利行を設定
case "5814D": case "5814D":
case "5816D": case "5816D":
viaData = "ごめん・なはり線[快速]";
ToData = "奈半利";
return "ごめん・なはり線直通\\n快速 奈半利行"; return "ごめん・なはり線直通\\n快速 奈半利行";
case "5812D": case "5812D":
viaData = "ごめん・なはり線[快速]";
ToData = "安芸";
return "ごめん・なはり線直通\\n快速 安芸行"; return "ごめん・なはり線直通\\n快速 安芸行";
case "5874D": case "5874D":
case "5882D": case "5882D":
case "5878D": case "5878D":
viaData = "ごめん・なはり線[各停]";
ToData = "安芸";
return "ごめん・なはり線直通\\n各停 安芸行"; return "ごめん・なはり線直通\\n各停 安芸行";
case "246D": case "246D":
case "750D": case "750D":
viaData = "ごめん・なはり線[快速]";
ToData = "(後免にて解結)土佐山田/奈半利";
return "土佐山田/奈半利行\\n(後免にて解結)\\nごめん・なはり線快速"; return "土佐山田/奈半利行\\n(後免にて解結)\\nごめん・なはり線快速";
default: default:
if(new RegExp(/^58[1-3][1,3,5,7,9][DM]$/).test()){ if(new RegExp(/^58[1-3][1,3,5,7,9][DM]$/).test()){
viaData = "ごめん・なはり線[快速]";
return "ごめん・なはり線直通\\n快速 "+.innerText; return "ごめん・なはり線直通\\n快速 "+.innerText;
} }
else if(new RegExp(/^58[4-9][1,3,5,7,9][DM]$/).test()){ else if(new RegExp(/^58[4-9][1,3,5,7,9][DM]$/).test()){
viaData = "ごめん・なはり線[各停]";
return "ごめん・なはり線直通\\n各停 "+.innerText; return "ごめん・なはり線直通\\n各停 "+.innerText;
} }
else if(new RegExp(/^58[3-4][0,2,4,6,8][DM]$/).test()){ else if(new RegExp(/^58[3-4][0,2,4,6,8][DM]$/).test()){
viaData = "ごめん・なはり線[快速]";
ToData = "奈半利";
return "ごめん・なはり線直通\\n快速 奈半利行"; return "ごめん・なはり線直通\\n快速 奈半利行";
} }
else if(new RegExp(/^58[5-9][0,2,4,6,8][DM]$/).test()){ else if(new RegExp(/^58[5-9][0,2,4,6,8][DM]$/).test()){
viaData = "ごめん・なはり線[各停]";
ToData = "奈半利";
return "ごめん・なはり線直通\\n各停 奈半利行"; return "ごめん・なはり線直通\\n各停 奈半利行";
} }
} }
} }
.innerText = getThrew() || .innerText; .innerText = getThrew() || .innerText;
//列番付与
.innerText = .innerText++(JRF ? "":"レ");
const returnText1 = (isWanman ? "ワンマン " : "") + trainName + viaData;
const returnText2 = (ToData ? ToData+"行 " : ToData)+ TrainNumber;
.innerText = "";
.insertAdjacentHTML('beforebegin', "<p style='font-size:10px;font-weight:bold;padding:0;'>" + returnText1 + "</p>");
.insertAdjacentHTML('beforebegin', "<div style='display:inline-flex;flex-direction:row;'><p style='font-size:10px;font-weight: bold;padding:0;'>" + (ToData ? ToData + "行 " : ToData) + "</p><p style='font-size:10px;padding:0;'>" + TrainNumber + (JRF ? "":"レ") + "</p></div>");
}
`; `;
const textInsert = const textInsert =
@ -1205,24 +1269,18 @@ const setStrings = () =>{
try { try {
const elements = document.querySelectorAll('#disp > div > div > div[onclick]'); const elements = document.querySelectorAll('#disp > div > div > div[onclick]');
for (let element of elements) { for (let element of elements) {
if(!element.getAttribute('offclick')){ if(element.getAttribute('offclick')){ continue; }
element.setAttribute('offclick',element.getAttribute('onclick')) element.setAttribute('offclick',element.getAttribute('onclick'))
}
var = element.getElementsByTagName("p")[0]; var = element.getElementsByTagName("p")[0];
var = element.getAttribute('offclick').split('"')[1]; var = element.getAttribute('offclick').split('"')[1];
var = element.getAttribute('offclick').split('"')[3]; var = element.getAttribute('offclick').split('"')[3];
var flag=false; var flag=false;
var TrainType = undefined; var TrainType = undefined;
setTrainMenuDialog(element) setTrainMenuDialog(element)
if(.innerText.includes())continue; //回避
` + ${iconSetting == "true" ? "setTrainIcon(列番データ,element);" : ""}
trainIcon + nameReplace(,,);
normal_train_name +
JRF_name +
Other_Name +
`
//列番付与
.innerText = .innerText++(JRF ? "":"レ");
} }
try{ try{
for(let d of document.getElementById('disp').childNodes){ for(let d of document.getElementById('disp').childNodes){
@ -1319,16 +1377,14 @@ textInsert.observe(document.getElementById('disp'), {
}); });
`; `;
// 列車メニュー表示の起動用スクリプト
const makeTrainView = ` const makeTrainView = `
const makeTrainView = new MutationObserver( (mutations) => { const makeTrainView = new MutationObserver( (mutations) => {
for(let d of modal_content.getElementsByTagName("button") ){ for(let d of modal_content.getElementsByTagName("button") ){
const data = d.onclick.toString().split("\\"")[1]; const data = d.onclick.toString().split("\\"")[1];
d.onclick = () => window.ReactNativeWebView.postMessage(data) d.onclick = () => window.ReactNativeWebView.postMessage(data)
} }
}); });
// 監視を開始 // 監視を開始
makeTrainView.observe(document.getElementById('modal_content'), { makeTrainView.observe(document.getElementById('modal_content'), {
//attributes: true, // 属性変化の監視 //attributes: true, // 属性変化の監視
@ -1415,8 +1471,9 @@ setStationMenuDialog.observe(document.querySelector('#disp'), {
return ( return (
bootData + bootData +
topMenu + topMenu +
trainIcon +
normal_train_name +
makeTrainView + makeTrainView +
trainIconMaker +
makeTrainMenu + makeTrainMenu +
textInsert + textInsert +
makeStationMenu makeStationMenu

107
menu.js
View File

@ -1,5 +1,5 @@
import React, { useRef, useState, useEffect } from "react"; import React, { useRef, useState, useEffect } from "react";
import Carousel, { Pagination } from "react-native-snap-carousel"; import Carousel from "react-native-reanimated-carousel";
import { import {
Platform, Platform,
View, View,
@ -8,6 +8,7 @@ import {
Text, Text,
TouchableOpacity, 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 * as Location from "expo-location";
@ -32,9 +33,10 @@ import { SheetManager } from "react-native-actions-sheet";
import { useTrainDelayData } from "./stateBox/useTrainDelayData"; 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 { Paginations } from "./components/Menu/StationPagination"; import { StationNumber } from "./components/Menu/StationPagination";
import lineColorList from "./assets/originData/lineColorList"; import lineColorList from "./assets/originData/lineColorList";
import { AS } from "./storageControl"; import { AS } from "./storageControl";
import { SimpleDot } from "./components/Menu/SimpleDot";
export default function Menu({ getCurrentTrain }) { export default function Menu({ getCurrentTrain }) {
const { navigate } = useNavigation(); const { navigate } = useNavigation();
@ -118,32 +120,20 @@ export default function Menu({ getCurrentTrain }) {
const count = selectedCurrentStation - 1; const count = selectedCurrentStation - 1;
setSelectedCurrentStation(count); setSelectedCurrentStation(count);
} }
}, [selectedCurrentStation, currentStation, favoriteStation]); }, [selectedCurrentStation, currentStation, allStationData]);
useEffect(() => { useEffect(() => {
if (!carouselRef.current) return; if (!carouselRef.current) return;
if (carouselRef.current?._itemToSnapTo != selectedCurrentStation) { carouselRef?.current.scrollTo({
carouselRef.current.snapToItem(0); count: selectedCurrentStation - carouselRef.current.getCurrentIndex(),
carouselRef.current.snapToItem(selectedCurrentStation); animated: true,
} });
}, [selectedCurrentStation]); }, [selectedCurrentStation]);
//全列車ダイヤリストを作成するuseEffect //全列車ダイヤリストを作成するuseEffect
const [trainDiagram, setTrainDiagram] = useState(null); // 全列車のダイヤを列番ベースで整理 const [trainDiagram, setTrainDiagram] = useState(null); // 全列車のダイヤを列番ベースで整理
useEffect(() => { useEffect(() => {
//全列車リストを生成する副作用[無条件初回実行] //全列車リストを生成する副作用[無条件初回実行]
fetch(
"https://train.jr-shikoku.co.jp/g?arg1=station&arg2=traintimeinfo&arg3=dia",
HeaderConfig
)
.then((response) => response.text())
.then((d) => {
if (d.indexOf("<title>404 Not Found</title>") != -1) throw Error;
setTrainDiagram(parseAllTrainDiagram(d));
})
.catch(() => {
console.log("fallback");
setTrainDiagram(trainList); setTrainDiagram(trainList);
});
}, []); }, []);
const oPSign = () => { const oPSign = () => {
@ -177,7 +167,8 @@ export default function Menu({ getCurrentTrain }) {
!dotButton ? "true" : "false" !dotButton ? "true" : "false"
); );
setDotButton(!dotButton); setDotButton(!dotButton);
} };
const width = Dimensions.get("window").width;
return ( return (
<View <View
style={{ style={{
@ -191,41 +182,80 @@ export default function Menu({ getCurrentTrain }) {
<ScrollView> <ScrollView>
<TopMenuButton /> <TopMenuButton />
{originalStationList.length != 0 && allStationData.length != 0 && ( {originalStationList.length != 0 && allStationData.length != 0 && (
<> <View style={{ flex: 1, paddingTop: 10 }}>
<Carousel <Carousel
ref={carouselRef} ref={carouselRef}
layout={"default"}
data={originalStationList && allStationData} data={originalStationList && allStationData}
sliderWidth={wp("100%")} height={(wp("80%") / 20) * 9 + 10}
itemWidth={wp("80%")} pagingEnabled={true}
enableMomentum snapEnabled={true}
callbackOffsetMargin={1000} loop={false}
activeAnimationOptions={0.3} width={width}
style={{ width: width, alignContent: "center" }}
mode="parallax"
modeConfig={{
parallaxScrollingScale: 1,
parallaxScrollingOffset: 100,
parallaxAdjacentItemScale: 0.8,
}}
onSnapToItem={setSelectedCurrentStation} onSnapToItem={setSelectedCurrentStation}
renderItem={({ item }) => { renderItem={({ item, index }) => {
return ( return (
<View <View
style={{ marginVertical: 10 }} style={{
backgroundColor: "#0000",
width: width,
flexDirection: "row",
marginLeft: 0,
marginRight: 0,
}}
key={item[0].StationNumber} key={item[0].StationNumber}
> >
<View style={{ flex: 1 }} />
<Sign <Sign
currentStation={item} currentStation={item}
isCurrentStation={item == currentStation} isCurrentStation={item == currentStation}
oP={oPSign} oP={oPSign}
oLP={oLPSign} oLP={oLPSign}
/> />
<View style={{ flex: 1 }} />
</View> </View>
); );
}} }}
/> />
<Paginations <View
entries={allStationData} style={{
activeSlide={selectedCurrentStation} flexDirection: "row",
carouselRef={carouselRef} justifyContent: "center",
setSelectedCurrentStation={setSelectedCurrentStation} alignContent: "center",
dotButton={dotButton} alignItems: "center",
}}
>
{originalStationList &&
allStationData.map((d, index) => {
const active = index == selectedCurrentStation;
const numberIndex = d[0].StationNumber;
if (dotButton) {
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 && {allStationData.length != 0 &&
originalStationList.length != 0 && originalStationList.length != 0 &&
@ -365,7 +395,10 @@ const JRSTraInfoBox = () => {
delayData.map((d, index, array) => { delayData.map((d, index, array) => {
let data = d.split(" "); let data = d.split(" ");
return ( return (
<View style={{ flexDirection: "row" }} key={data[1] + "key"+index}> <View
style={{ flexDirection: "row" }}
key={data[1] + "key" + index}
>
<Text style={{ flex: 15, fontSize: 18 }}> <Text style={{ flex: 15, fontSize: 18 }}>
{data[0].replace("\n", "")} {data[0].replace("\n", "")}
</Text> </Text>

View File

@ -1,63 +0,0 @@
import React, { useRef, useState } from "react";
import { View, Platform, TouchableOpacity } from "react-native";
import { WebView } from "react-native-webview";
import Constants from "expo-constants";
import { Ionicons } from "@expo/vector-icons";
export default function tndView() {
const webview = useRef();
const jsa = `
document.querySelector('.sitettl').style.display = 'none';
document.querySelector('.attention').style.display = 'none';
`;
return (
<View
style={{
backgroundColor: "#309AC3",
height: "100%",
paddingTop: Platform.OS == "ios" ? Constants.statusBarHeight : 0,
}}
>
<WebView
useWebKit={true}
ref={webview}
source={{ uri: "https://www.jr-shikoku.co.jp/info/" }}
originWhitelist={["https://www.jr-shikoku.co.jp"]}
mixedContentMode={"compatibility"}
javaScriptEnabled={true}
injectedJavaScript={jsa}
pullToRefreshEnabled
onError={() => this.webView?.reload()}
/>
<ReloadButton
onPress={() => webview.current?.reload()}
top={Platform.OS == "ios" ? Constants.statusBarHeight : 0}
/>
</View>
);
}
const ReloadButton = ({ onPress, top, mapSwitch, LoadError = false }) => {
const styles = {
position: "absolute",
top,
right: 10,
width: 50,
height: 50,
backgroundColor: LoadError ? "red" : "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
borderRadius: 50,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
display: mapSwitch,
};
return (
<TouchableOpacity onPress={onPress} style={styles}>
<View style={{ flex: 1 }} />
<Ionicons name="reload" color="white" size={30} />
<View style={{ flex: 1 }} />
</TouchableOpacity>
);
};

137
ndView.tsx Normal file
View File

@ -0,0 +1,137 @@
import React, { Ref, useRef, useState } from "react";
import { View, Platform, TouchableOpacity, StyleProp, ViewStyle } from "react-native";
import { WebView } from "react-native-webview";
import Constants from "expo-constants";
import { Ionicons } from "@expo/vector-icons";
export default function tndView() {
const webview = useRef<WebView>(null);
const jsa = `
document.querySelector('.sitettl').style.display = 'none';
document.querySelector('.attention').style.display = 'none';
document.querySelector('.mapheader').style.display = 'none';
document.querySelector('.map').style.width = '100vw';
document.querySelector('.map').style.display = 'block';
document.querySelector('.map').style.marginLeft = '-5px';
document.querySelector('.map').style.marginTop = '0px';
document.querySelector('.mapbase > img').style.width = '100vw';
document.querySelector('.ml_station > img').style.width = '100vw';
document.querySelector('.ml_seto >img').removeAttribute('width');
document.querySelector('.ml_seto >img').removeAttribute('height');
document.querySelector('.ml_seto >img').style.width = '14.5vw';
document.querySelector('.ml_seto').style.top = '0.2vw';
document.querySelector('.ml_seto').style.right = '25.8vw';
document.querySelector('.ml_yosan1 >img').removeAttribute('width');
document.querySelector('.ml_yosan1 >img').removeAttribute('height');
document.querySelector('.ml_yosan1 >img').style.width = '42.6vw';
document.querySelector('.ml_yosan1').style.top = '5.1vw';
document.querySelector('.ml_yosan1').style.left = '18.7vw';
document.querySelector('.ml_yosan2 >img').removeAttribute('width');
document.querySelector('.ml_yosan2 >img').removeAttribute('height');
document.querySelector('.ml_yosan2 >img').style.width = '12.2vw';
document.querySelector('.ml_yosan2').style.top = '8.6vw';
document.querySelector('.ml_yosan2').style.left = '8.0vw';
document.querySelector('.ml_dosan1 >img').removeAttribute('width');
document.querySelector('.ml_dosan1 >img').removeAttribute('height');
document.querySelector('.ml_dosan1 >img').style.width = '13.5vw';
document.querySelector('.ml_dosan1').style.top = '6.6vw';
document.querySelector('.ml_dosan1').style.left = '47.8vw';
document.querySelector('.ml_dosan2 >img').removeAttribute('width');
document.querySelector('.ml_dosan2 >img').removeAttribute('height');
document.querySelector('.ml_dosan2 >img').style.width = '22.5vw';
document.querySelector('.ml_dosan2').style.top = '32vw';
document.querySelector('.ml_dosan2').style.left = '26.5vw';
document.querySelector('.ml_kotoku >img').removeAttribute('width');
document.querySelector('.ml_kotoku >img').removeAttribute('height');
document.querySelector('.ml_kotoku >img').style.width = '17vw';
document.querySelector('.ml_kotoku').style.top = '6.5vw';
document.querySelector('.ml_kotoku').style.left = '72.9vw';
document.querySelector('.ml_mugi >img').removeAttribute('width');
document.querySelector('.ml_mugi >img').removeAttribute('height');
document.querySelector('.ml_mugi >img').style.width = '11.6vw';
document.querySelector('.ml_mugi').style.top = '23.6vw';
document.querySelector('.ml_mugi').style.left = '78.3vw';
document.querySelector('.ml_tokushima >img').removeAttribute('width');
document.querySelector('.ml_tokushima >img').removeAttribute('height');
document.querySelector('.ml_tokushima >img').style.width = '27.8vw';
document.querySelector('.ml_tokushima').style.top = '17vw';
document.querySelector('.ml_tokushima').style.left = '61.3vw';
document.querySelector('.ml_naruto >img').removeAttribute('width');
document.querySelector('.ml_naruto >img').removeAttribute('height');
document.querySelector('.ml_naruto >img').style.width = '5.5vw';
document.querySelector('.ml_naruto').style.top = '17.1vw';
document.querySelector('.ml_naruto').style.left = '88.5vw';
document.querySelector('.ml_yodo >img').removeAttribute('width');
document.querySelector('.ml_yodo >img').removeAttribute('height');
document.querySelector('.ml_yodo >img').style.width = '18.3vw';
document.querySelector('.ml_yodo').style.top = '30.2vw';
document.querySelector('.ml_yodo').style.left = '9.6vw';
setInterval(() => {
document.querySelectorAll('.ml_seto, .ml_yosan1, .ml_yosan2, .ml_dosan1, .ml_dosan2, .ml_kotoku, .ml_mugi, .ml_tokushima, .ml_naruto, .ml_yodo').forEach(el => {
el.style.visibility = el.style.visibility === 'hidden' ? 'visible' : 'hidden';
});
}, 1000);
`;
return (
<View
style={{
backgroundColor: "#309AC3",
height: "100%",
paddingTop: Platform.OS == "ios" ? Constants.statusBarHeight : 0,
}}
>
<WebView
ref={webview}
source={{ uri: "https://www.jr-shikoku.co.jp/info/" }}
originWhitelist={["https://www.jr-shikoku.co.jp"]}
mixedContentMode={"compatibility"}
javaScriptEnabled={true}
injectedJavaScript={jsa}
pullToRefreshEnabled
onError={() => this.webView?.reload()}
onMessage={()=>{}}
/>
<ReloadButton
onPress={() => webview.current.reload()}
top={Platform.OS == "ios" ? Constants.statusBarHeight : 0}
/>
</View>
);
}
const ReloadButton = ({ onPress, top, LoadError = false }) => {
const styles:StyleProp<ViewStyle> = {
position: "absolute",
top,
right: 10,
width: 50,
height: 50,
backgroundColor: LoadError ? "red" : "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
borderRadius: 50,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
};
return (
<TouchableOpacity onPress={onPress} style={styles}>
<View style={{ flex: 1 }} />
<Ionicons name="reload" color="white" size={30} />
<View style={{ flex: 1 }} />
</TouchableOpacity>
);
};

View File

@ -8,54 +8,69 @@
}, },
"dependencies": { "dependencies": {
"@expo/ngrok": "^4.1.0", "@expo/ngrok": "^4.1.0",
"@expo/vector-icons": "^14.0.0", "@expo/vector-icons": "^14.0.2",
"@react-native-async-storage/async-storage": "1.21.0", "@gorhom/bottom-sheet": "^5",
"@react-native-community/masked-view": "0.1.10", "@react-native-async-storage/async-storage": "1.23.1",
"@react-navigation/bottom-tabs": "^5.11.11", "@react-native-masked-view/masked-view": "0.3.2",
"@react-navigation/native": "^5.9.4", "@react-navigation/bottom-tabs": "^7.2.0",
"@react-navigation/stack": "^5.14.5", "@react-navigation/native": "^7.0.14",
"@react-navigation/stack": "^7.1.1",
"@rneui/base": "^0.0.0-edge.2",
"@rneui/themed": "^0.0.0-edge.2",
"dayjs": "^1.11.9", "dayjs": "^1.11.9",
"eas-cli": "^5.9.1", "expo": "^52.0.0",
"expo": "^50.0.11", "expo-alternate-app-icons": "^1.3.0",
"expo-dev-client": "~3.3.9", "expo-clipboard": "~7.0.1",
"expo-device": "~5.9.3", "expo-constants": "~17.0.4",
"expo-font": "~11.10.3", "expo-dev-client": "~5.0.9",
"expo-location": "~16.5.5", "expo-device": "~7.0.2",
"expo-notifications": "~0.27.6", "expo-font": "~13.0.3",
"expo-screen-orientation": "~6.4.1", "expo-haptics": "~14.0.1",
"expo-sharing": "~11.10.0", "expo-intent-launcher": "~12.0.2",
"expo-updates": "~0.24.11", "expo-linear-gradient": "~14.0.2",
"expo-web-browser": "~12.8.2", "expo-linking": "~7.0.4",
"expo-localization": "~16.0.1",
"expo-location": "~18.0.5",
"expo-notifications": "~0.29.12",
"expo-screen-orientation": "~8.0.4",
"expo-sharing": "~13.0.1",
"expo-status-bar": "~2.0.1",
"expo-updates": "~0.26.12",
"expo-video": "~2.0.5",
"expo-web-browser": "~14.0.2",
"firebase": "8.2.3", "firebase": "8.2.3",
"lottie-react-native": "6.5.1", "lottie-react-native": "7.1.0",
"native-base": "^2.15.2", "native-base": "^2.15.2",
"npm": "^7.18.1",
"pushy-react-native": "^1.0.18", "pushy-react-native": "^1.0.18",
"react": "18.2.0", "react": "18.3.1",
"react-native": "0.73.4", "react-native": "0.76.6",
"react-native-actions-sheet": "0.8.21", "react-native-actions-sheet": "0.8.21",
"react-native-android-widget": "^0.11.2", "react-native-android-widget": "^0.15.1",
"react-native-auto-height-image": "^3.2.4", "react-native-auto-height-image": "^3.2.4",
"react-native-elements": "^3.4.2", "react-native-elements": "^3.4.2",
"react-native-gesture-handler": "~2.14.0", "react-native-gesture-handler": "~2.20.2",
"react-native-maps": "1.10.0", "react-native-maps": "1.18.0",
"react-native-reanimated": "~3.6.2", "react-native-reanimated": "~3.16.1",
"react-native-reanimated-carousel": "^3.5.1",
"react-native-remote-svg": "^2.0.6", "react-native-remote-svg": "^2.0.6",
"react-native-responsive-screen": "^1.4.2", "react-native-responsive-screen": "^1.4.2",
"react-native-router-flux": "^4.3.1", "react-native-router-flux": "^4.3.1",
"react-native-safe-area-context": "4.8.2", "react-native-safe-area-context": "4.12.0",
"react-native-screens": "~3.29.0", "react-native-screens": "~4.4.0",
"react-native-snap-carousel": "^3.9.1", "react-native-snap-carousel": "^3.9.1",
"react-native-sortables": "^1.1.0",
"react-native-storage": "^1.0.1", "react-native-storage": "^1.0.1",
"react-native-svg": "14.1.0", "react-native-svg": "15.8.0",
"react-native-svg-uri": "^1.2.3", "react-native-svg-uri": "^1.2.3",
"react-native-vector-icons": "^8.1.0", "react-native-touchable-scale": "^2.2.0",
"react-native-view-shot": "3.8.0", "react-native-vector-icons": "^10.2.0",
"react-native-webview": "13.6.4", "react-native-view-shot": "~4.0.3",
"react-native-walkthrough-tooltip": "^1.6.0",
"react-native-webview": "13.12.5",
"typescript": "^5.3.0" "typescript": "^5.3.0"
}, },
"devDependencies": { "devDependencies": {
"babel-preset-expo": "^10.0.0" "babel-preset-expo": "~12.0.0"
}, },
"private": true "private": true
} }

View File

@ -4,6 +4,7 @@ import React, {
useState, useState,
useEffect, useEffect,
useLayoutEffect, useLayoutEffect,
FC,
} from "react"; } from "react";
import { AS } from "../storageControl"; import { AS } from "../storageControl";
import { useStationList } from "./useStationList"; import { useStationList } from "./useStationList";
@ -13,13 +14,20 @@ const initialState = {
lodAddMigration: () => {}, lodAddMigration: () => {},
}; };
const FavoriteStationContext = createContext(initialState); type initialStateType = {
favoriteStation: any[];
setFavoriteStation: (d:any)=>void;
lodAddMigration: ()=>void;
};
const FavoriteStationContext = createContext<initialStateType>(initialState);
export const useFavoriteStation = () => { export const useFavoriteStation = () => {
return useContext(FavoriteStationContext); return useContext(FavoriteStationContext);
}; };
type Props = {
export const FavoriteStationProvider = ({ children }) => { children: React.ReactNode;
};
export const FavoriteStationProvider:FC<Props> = ({ children }) => {
const [favoriteStation, setFavoriteStation] = useState([]); const [favoriteStation, setFavoriteStation] = useState([]);
const { getStationData } = useStationList(); const { getStationData } = useStationList();
const lodAddMigration = () => { const lodAddMigration = () => {

View File

@ -6,9 +6,7 @@ import React, {
FC, FC,
useRef, useRef,
} from "react"; } from "react";
// 6.0でライブラリ変更 import { Platform } from "react-native";
import { Platform, Clipboard } from "react-native";
// 6.0でライブラリ更新、tsの型定義が変わった
import * as Notifications from "expo-notifications"; import * as Notifications from "expo-notifications";
import * as Device from "expo-device"; import * as Device from "expo-device";
import Constants from "expo-constants"; import Constants from "expo-constants";

View File

@ -42,7 +42,9 @@ export const TrainMenuProvider = ({ children }) => {
const [mapsStationData, setMapsStationData] = useState(undefined); const [mapsStationData, setMapsStationData] = useState(undefined);
const [injectJavaScript, setInjectJavaScript] = useState(); const [injectJavaScript, setInjectJavaScript] = useState();
useEffect(() => getStationList2().then(setMapsStationData), []); useEffect(() => {
getStationList2().then(setMapsStationData);
}, []);
//画面表示関連 //画面表示関連
const [iconSetting, setIconSetting] = useState(undefined); const [iconSetting, setIconSetting] = useState(undefined);
@ -72,7 +74,6 @@ export const TrainMenuProvider = ({ children }) => {
//列車アイコンスイッチ //列車アイコンスイッチ
ASCore({ k: "iconSwitch", s: setIconSetting, d: "true", u: true }); ASCore({ k: "iconSwitch", s: setIconSetting, d: "true", u: true });
//地図スイッチ //地図スイッチ
//6.0.0以降true
ASCore({ k: "mapSwitch", s: setMapSwitch, d: "false", u: true }); ASCore({ k: "mapSwitch", s: setMapSwitch, d: "false", u: true });
//駅メニュースイッチ //駅メニュースイッチ
ASCore({ k: "stationSwitch", s: setStationMenu, d: "true", u: true }); ASCore({ k: "stationSwitch", s: setStationMenu, d: "true", u: true });

7088
yarn.lock

File diff suppressed because it is too large Load Diff