Compare commits

...

58 Commits

Author SHA1 Message Date
harukin-expo-dev-env
2fb7d97d33 Merge commit '31618aab496a7979a39e534d023cb69103b06721' 2025-03-10 15:51:25 +00:00
harukin-expo-dev-env
31618aab49 Merge commit '343bf25139b53b872429d25b181d4ae8d757f8f3' into patch/6.x 2025-03-10 15:51:14 +00:00
harukin-expo-dev-env
343bf25139 Merge commit 'e58e24ba71ad5d66348d19b0e650dbb45aa0d723' into develop 2025-03-10 15:47:37 +00:00
harukin-expo-dev-env
e58e24ba71 デザインの調整 2025-03-10 15:47:29 +00:00
harukin-expo-dev-env
c0478bf9ae iOSでアイコンを変更すると即時再起動するように 2025-03-10 15:34:29 +00:00
harukin-expo-dev-env
0838414540 アイコン更新画面を作成 2025-03-10 15:24:11 +00:00
harukin-expo-dev-env
a9488b98bc Merge commit '26cf84705abd4c9a69ac56fcade483a373089bf8' into develop 2025-03-10 13:56:01 +00:00
harukin-expo-dev-env
76ebf8055b Merge commit '26cf84705abd4c9a69ac56fcade483a373089bf8' 2025-03-06 03:52:42 +00:00
harukin-expo-dev-env
26cf84705a クソ審査のせいでまた無駄なコミットが増えた 2025-03-06 03:52:19 +00:00
harukin-expo-dev-env
55f4a79eef ストアたちが文句しか言ってこないのでしゃーなしにexpo-av削除してやった。クソめ 2025-03-06 03:50:41 +00:00
harukin-expo-dev-env
7b572cd657 Merge commit 'fa882223d49fec390177131371b99a3101976759' 2025-03-05 11:51:51 +00:00
harukin-expo-dev-env
046a8dbfb2 Merge commit 'fa882223d49fec390177131371b99a3101976759' into develop 2025-03-05 11:51:46 +00:00
harukin-expo-dev-env
fa882223d4 Androidリリース再提出 2025-03-05 11:47:20 +00:00
harukin-expo-dev-env
bb7b474006 Merge commit 'ede2884c4a7b8a508cfd9f4f7cc87da4efe3db08' into develop 2025-03-04 16:17:57 +00:00
harukin-expo-dev-env
61fa0f8484 Merge commit 'ede2884c4a7b8a508cfd9f4f7cc87da4efe3db08' 2025-03-04 16:17:50 +00:00
harukin-expo-dev-env
ede2884c4a app.json自動更新 2025-03-04 16:17:41 +00:00
harukin-expo-dev-env
935aaf2610 Merge commit '098cae50533368eec9cfdb933900c503ae46e850' 2025-03-04 15:01:08 +00:00
harukin-expo-dev-env
098cae5053 news番号更新 2025-03-04 15:00:41 +00:00
harukin-expo-dev-env
7cddc657fd update 6.0 release code 2025-03-04 14:51:05 +00:00
harukin-expo-dev-env
adee63b549 Merge commit '5dd60027a08f0223d17bfc024079acf914ef541a' into patch/5.0.x 2025-03-04 14:40:02 +00:00
harukin-expo-dev-env
5dd60027a0 beta6.0新規ビルド 2025-03-04 11:37:37 +00:00
harukin-expo-dev-env
558d37c3c6 Merge commit '74ff188d842c1d6e3b9c3b96487278a4840a789b' into develop 2025-03-04 10:38:21 +00:00
harukin-expo-dev-env
74ff188d84 部分的web対応 2025-03-04 10:38:04 +00:00
harukin-expo-dev-env
974b12667f Merge commit '9a157d711b4c4e9ab8b9d99a7c55daf93e47b1fb' into develop 2025-02-22 05:29:08 +00:00
harukin-expo-dev-env
9a157d711b 配置を逆転させていたミスを修正 2025-02-22 05:29:00 +00:00
harukin-expo-dev-env
6ff4aba050 Merge commit 'a4eda11b2de606aea6dec1d23fd359d35e2c7802' into develop 2025-02-22 05:24:20 +00:00
harukin-expo-dev-env
a4eda11b2d 伊予若宮信号場関係でバグが発生していたのを修正 2025-02-22 05:24:07 +00:00
harukin-expo-dev-env
45e14274cb 絶対パスのtsconfigを追加 2025-02-13 10:05:55 +00:00
harukin-expo-dev-env
499e895165 Merge commit '0aaf171477659e632a23aeb6af39e83d5acf70c2' into develop 2025-02-09 03:19:30 +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
harukin-expo-dev-env
a5efb13506 Merge commit '4a01c529b47cd85420a4c1feeac87164730dee94' into develop 2025-01-15 12:42:35 +00:00
harukin-expo-dev-env
00b17bfbc1 Merge commit '2776f17681ac2bf76a70c268c4db8921c5888a4f' into develop 2025-01-14 07:44:41 +00:00
harukin-expo-dev-env
72c4bd10aa Merge commit '58d3eae1d7797a74febc752f4185337a6eb95dad' into develop 2025-01-09 09:56:03 +00:00
99 changed files with 5545 additions and 6588 deletions

4
.gitignore vendored
View File

@ -5,4 +5,6 @@ npm-debug.*
*.p12
*.key
*.mobileprovision
dist/
dist/
# Local Netlify folder
.netlify

41
Apps.js
View File

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

View File

@ -1,19 +1,18 @@
import React, { useEffect } from "react";
import {
createStackNavigator,
TransitionPresets,
} from "@react-navigation/stack";
import { createStackNavigator } from "@react-navigation/stack";
import { SheetManager } from "react-native-actions-sheet";
import { AS } from "./storageControl";
import TrainBase from "./components/trainbaseview";
import HowTo from "./howto";
import Menu from "./menu";
import News from "./components/news";
import Setting from "./components/Settings/settings";
import { useFavoriteStation } from "./stateBox/useFavoriteStation";
import { optionData } from "./lib/stackOption";
import CurrentTrainListView from "./components/CurrentTrainListView";
import AllTrainDiagramView from "./components/AllTrainDiagramView";
import { useCurrentTrain } from "./stateBox/useCurrentTrain";
import { useNavigation } from "@react-navigation/native";
import { news } from "./config/newsUpdate";
const Stack = createStackNavigator();
export function MenuPage() {
@ -24,12 +23,24 @@ export function MenuPage() {
useEffect(() => {
AS.getItem("startPage")
.then((res) => {
if (res == "true") navigation.navigate("login");
if (res == "true") navigation.navigate("positions");
})
.catch((e) => {
//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" }));
AS.getItem("isSetIcon")
.then((isSetIcon) => {
if (isSetIcon == "true") SheetManager.show("TrainIconUpdate");
})
.catch((error) => console.error("Error fetching icon setting:", error));
}, []);
useEffect(() => {
const unsubscribe = addListener("tabPress", (e) => {
@ -56,6 +67,7 @@ export function MenuPage() {
}}
children={() => <Menu getCurrentTrain={getCurrentTrain} />}
/>
<Stack.Screen name="news" options={optionData} component={News} />
<Stack.Screen
name="setting"
options={{
@ -67,13 +79,8 @@ export function MenuPage() {
/>
<Stack.Screen
name="trainbase"
options={{ ...optionData, gestureResponseDistance: { vertical: 300 } }}
children={(props) => <TrainBase {...props} />}
/>
<Stack.Screen
name="currentTrainIDList"
options={{ ...optionData, gestureResponseDistance: { vertical: 300 } }}
component={CurrentTrainListView}
options={{ ...optionData }}
component={TrainBase}
/>
<Stack.Screen
name="AllTrainIDList"

79
Top.js
View File

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

View File

@ -1,11 +1,11 @@
import { ToastAndroid } from "react-native";
import { Platform, ToastAndroid } from "react-native";
import * as Updates from "expo-updates";
export const UpdateAsync = () => {
Updates.checkForUpdateAsync()
.then((update) => {
if (!update.isAvailable) return;
if (Platform.OS == "ios") {
if (Platform.OS !== "android") {
alert("アプリのデータを更新しています。");
} else {
ToastAndroid.showWithGravityAndOffset(
@ -20,7 +20,7 @@ export const UpdateAsync = () => {
return;
})
.catch((e) => {
Platform.OS == "ios"
Platform.OS != "android"
? alert(e.toString())
: ToastAndroid.showWithGravityAndOffset(
e.toString(),

456
app.json
View File

@ -1,56 +1,28 @@
{
"expo": {
"name": "JR四国運行状況",
"name": "JR四国非公式",
"slug": "jrshikoku",
"privacy": "public",
"platforms": ["ios", "android"],
"plugins": [
[
"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": "この位置情報は、リンク画面で現在地側近の駅情報を取得するのに使用されます。"
}
]
"platforms": [
"ios",
"android",
"web"
],
"version": "5.0",
"version": "6.0",
"orientation": "default",
"icon": "./assets/icon.png",
"icon": "./assets/icons/s8600.png",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#00b8ff"
},
"updates": {
"fallbackToCacheTimeout": 0,
"url": "https://u.expo.dev/398abf60-57a7-11e9-970c-8f04356d08bf"
},
"assetBundlePatterns": ["**/*"],
"assetBundlePatterns": [
"**/*"
],
"ios": {
"buildNumber": "39",
"buildNumber": "46",
"supportsTablet": false,
"bundleIdentifier": "jrshikokuinfo.xprocess.hrkn",
"config": {
@ -61,16 +33,24 @@
"com.apple.developer.nfc.readersession.felica.systemcodes": [
"0003",
"FE00"
]
],
"ITSAppUsesNonExemptEncryption": false
},
"entitlements": {
"com.apple.developer.nfc.readersession.formats": ["TAG"]
"com.apple.developer.nfc.readersession.formats": [
"TAG"
]
}
},
"android": {
"package": "jrshikokuinfo.xprocess.hrkn",
"versionCode": 22,
"permissions": ["ACCESS_FINE_LOCATION", "NFC"],
"versionCode": 27,
"permissions": [
"ACCESS_FINE_LOCATION",
"NFC",
"android.permission.ACCESS_COARSE_LOCATION",
"android.permission.ACCESS_FINE_LOCATION"
],
"googleServicesFile": "./google-services.json",
"config": {
"googleMaps": {
@ -85,6 +65,394 @@
},
"runtimeVersion": {
"policy": "sdkVersion"
}
},
"plugins": [
"expo-font",
"expo-localization",
[
"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 (
<ActionSheet
gestureEnabled={true}
//gestureEnabled={!actionSheetHorizonalScroll}
CustomHeaderComponent={<></>}
ref={actionSheetRef}
drawUnderStatusBar={false}

View File

@ -9,9 +9,6 @@ import { trainPosition } from "../../../lib/trainPositionTextArray";
import { TrainPositionDataPush } from "../../発車時刻表/LED_inside_Component/TrainPositionDataPush";
import { getStationID } from "../../../lib/eachTrainInfoCoreLib/getStationData";
import { useStationList } from "../../../stateBox/useStationList";
import { lineList } from "../../../lib/getStationList";
export const TrainDataView = ({
currentTrainData,
@ -21,7 +18,6 @@ export const TrainDataView = ({
mode = 0,
navigate,
}) => {
const { stationList } = useStationList();
const { width, height } = useWindowDimensions();
@ -57,13 +53,14 @@ export const TrainDataView = ({
return `${Pos}${platformNumber ? ` ${platformNumber}番線` : ""}`;
};
const [dialog, setDialog] = useState(false);
const [deleteDialog, setDeleteDialog] = useState(false);
const [deleteDialog, setDeleteDialog] = useState(false);
const [posInput, setPosInput] = useState("");
const [descInput, setDescInput] = useState("");
const [stationInput, setStationInput] = useState("");
const [stationNumberInput, setStationNumberInput] = useState("");
return (<>
<TrainPositionDataPush
return (
<>
<TrainPositionDataPush
dialog={dialog}
setDialog={setDialog}
currentTrainData={currentTrainData}
@ -73,111 +70,118 @@ export const TrainDataView = ({
descInput={descInput}
setPosInput={setPosInput}
setDescInput={setDescInput}
station={{Station_JP:trainPositionText(currentTrainData),StationNumber:currentPosition[0]}} />
<View
style={{
flexDirection: "row",
//minHeight: 200,
//height: heightPercentageToDP("20%"),
width: isLandscape ? (width / 100) * 40 : width,
flex: 1,
}}
>
<TouchableOpacity
style={{ flex: 1, flexDirection: "row" }}
//disabled={!onLine}
onLongPress={() => {
const { isBetween, Pos } = trainPosition(currentTrainData);
if (isBetween === true) {
if (platformNumber == undefined && platformDescription == undefined)
return;
setStationInput(`${Pos.from}${Pos.to}`);
setStationNumberInput(
getStationID(currentTrainData?.Pos, stationList)
);
setPosInput(platformNumber?.toString() || "");
setDeleteDialog(true);
} else {
setStationInput(Pos.Pos);
setStationNumberInput(
getStationID(currentTrainData?.Pos, stationList)
);
setDescInput(platformDescription || "");
setPosInput(platformNumber?.toString() || "");
setDialog(true);
}
station={{
Station_JP: trainPositionText(currentTrainData),
StationNumber: currentPosition[0],
}}
onPress={() => {
if(!onLine) return;
const test = [];
Object.keys(mapsStationData).forEach((d) => {
mapsStationData[d].forEach((x) => {
if (x.StationNumber == currentPosition[0])
test.push({ line: d, station: x });
});
if (currentPosition[0] == "M12") {
test.push({
line: "seto",
station: { Station_JP: "児島", MyStation: "0" },
});
}
});
if (!test.length) return;
navigate("Apps");
inject(
`MoveDisplayStation('${test[0].line}_${test[0].station.MyStation}_${test[0].station.Station_JP}');document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");`
);
SheetManager.hide("EachTrainInfo");
/>
<View
style={{
flexDirection: "row",
//minHeight: 200,
//height: heightPercentageToDP("20%"),
width: isLandscape ? (width / 100) * 40 : width,
flex: 1,
}}
>
<StateBox
mode={mode}
title={`現在地 ${currentPosition?.toString()}${onLine ? "▶️" : ""}`}
text={trainPositionText(currentTrainData)}
endText={platformDescription ? `${platformDescription}` : ""}
style={
onLine
? { borderWidth: 1, borderColor: "red", borderStyle: "solid" }
: {}
}
/>
</TouchableOpacity>
<View style={{ flex: 1, flexDirection: mode == 2 ? "row" : "column" }}>
<View style={{ flex: 1, flexDirection: "row" }}>
<StateBox
mode={mode}
title={isNaN(currentTrainData?.delay) ? "状態" : "遅延時分"}
text={`${currentTrainData?.delay}${
isNaN(currentTrainData?.delay) ? "" : "分"
}`}
/>
</View>
<TouchableOpacity
style={{ flex: 1, flexDirection: "row" }}
disabled={nearTrainIDList.length == 0}
//disabled={!onLine}
onLongPress={() => {
const { isBetween, Pos } = trainPosition(currentTrainData);
if (isBetween === true) {
if (
platformNumber == undefined &&
platformDescription == undefined
)
return;
setStationInput(`${Pos.from}${Pos.to}`);
setStationNumberInput(
getStationID(currentTrainData?.Pos, stationList)
);
setPosInput(platformNumber?.toString() || "");
setDeleteDialog(true);
} else {
setStationInput(Pos.Pos);
setStationNumberInput(
getStationID(currentTrainData?.Pos, stationList)
);
setDescInput(platformDescription || "");
setPosInput(platformNumber?.toString() || "");
setDialog(true);
}
}}
onPress={() => {
if (nearTrainIDList.length == 0) return;
openTrainInfo(nearTrainIDList[0]);
if (!onLine) return;
const test = [];
Object.keys(mapsStationData).forEach((d) => {
mapsStationData[d].forEach((x) => {
if (x.StationNumber == currentPosition[0])
test.push({ line: d, station: x });
});
if (currentPosition[0] == "M12") {
test.push({
line: "seto",
station: { Station_JP: "児島", MyStation: "0" },
});
}
});
if (!test.length) return;
navigate("positions", { screen: "Apps" });
inject(
`MoveDisplayStation('${test[0].line}_${test[0].station.MyStation}_${test[0].station.Station_JP}');document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");`
);
SheetManager.hide("EachTrainInfo");
}}
>
{nearTrainIDList.length == 0 ? (
<StateBox mode={mode} title="列番" text={currentTrainData?.num} />
) : (
<StateBox
mode={mode}
title={`現在地 ${currentPosition?.toString()}${onLine ? "▶️" : ""}`}
text={trainPositionText(currentTrainData)}
endText={platformDescription ? `${platformDescription}` : ""}
style={
onLine
? { borderWidth: 1, borderColor: "red", borderStyle: "solid" }
: {}
}
/>
</TouchableOpacity>
<View style={{ flex: 1, flexDirection: mode == 2 ? "row" : "column" }}>
<View style={{ flex: 1, flexDirection: "row" }}>
<StateBox
mode={mode}
title="増解結相手を表示▶️"
text={`${nearTrainIDList}`}
style={{
borderWidth: 1,
borderColor: "red",
borderStyle: "solid",
}}
title={isNaN(currentTrainData?.delay) ? "状態" : "遅延時分"}
text={`${currentTrainData?.delay}${
isNaN(currentTrainData?.delay) ? "" : "分"
}`}
/>
)}
</TouchableOpacity>
</View>
<TouchableOpacity
style={{ flex: 1, flexDirection: "row" }}
disabled={nearTrainIDList.length == 0}
onPress={() => {
if (nearTrainIDList.length == 0) return;
openTrainInfo(nearTrainIDList[0]);
}}
>
{nearTrainIDList.length == 0 ? (
<StateBox mode={mode} title="列番" text={currentTrainData?.num} />
) : (
<StateBox
mode={mode}
title="増解結相手を表示▶️"
text={`${nearTrainIDList}`}
style={{
borderWidth: 1,
borderColor: "red",
borderStyle: "solid",
}}
/>
)}
</TouchableOpacity>
</View>
</View>
</View>
</>
</>
);
};

View File

@ -10,6 +10,7 @@ import {
LayoutAnimation,
} from "react-native";
import { SheetManager } from "react-native-actions-sheet";
import { useScrollHandlers } from "react-native-actions-sheet";
import { AS } from "../../storageControl";
import trainList from "../../assets/originData/trainList";
import { lineListPair } from "../../lib/getStationList";
@ -188,7 +189,7 @@ export const EachTrainInfoCore = ({
const count = position * 44 - 50;
// 0.5秒待機してからスクロール
setTimeout(
() => ScrollViewRef.current?.scrollTo({ y: count, animated: true }),
() => scrollHandlers.ref.current?.scrollTo({ y: count, animated: true }),
400
);
}
@ -219,8 +220,9 @@ export const EachTrainInfoCore = ({
const { height } = useWindowDimensions();
const { isLandscape } = useDeviceOrientationChange();
const ScrollViewRef = useRef();
const scrollHandlers = actionSheetRef
? useScrollHandlers("scrollview-1", actionSheetRef)
: null;
const [trueTrainID, setTrueTrainID] = useState();
useEffect(() => {
if (!data.trainNum) return;
@ -289,6 +291,18 @@ export const EachTrainInfoCore = ({
} else if (pos[1] == "児島" && pos[0] == "宇多津") {
setCurrentPosition(["Y09", "M12"]);
return;
}else if (pos[0] == "伊予若宮" && pos[1] == "伊予白滝") {
setCurrentPosition(["S18", "S14"]);
return;
} else if (pos[0] == "伊予白滝" && pos[1] == "伊予若宮") {
setCurrentPosition(["S14", "S18"]);
return;
} else if (pos[0] == "伊予大洲" && pos[1] == "伊予若宮") {
setCurrentPosition(["U14", "U14"]);
return;
} else if (pos[0] == "伊予若宮" && pos[1] == "伊予大洲") {
setCurrentPosition(["U14", "U14"]);
return;
}
const currentPosID = Object.keys(originalStationList).map((key) => {
let firstStation = false;
@ -335,8 +349,7 @@ export const EachTrainInfoCore = ({
.then((d) => {
if (d) setTrainPositionSwitch(d);
})
//6.0で変更
.catch(() => AS.setItem("trainPositionSwitch", "false"));
.catch(() => AS.setItem("trainPositionSwitch", "true"));
}, []);
const openTrainInfo = (d) => {
@ -362,7 +375,7 @@ export const EachTrainInfoCore = ({
} else {
SheetManager.hide("EachTrainInfo").then(() => {
//0.1秒待機してから開く
setTimeout(() => SheetManager.show("EachTrainInfo", { payload }), 2);
setTimeout(() => SheetManager.show("EachTrainInfo", { payload }), 200);
});
}
};
@ -412,7 +425,7 @@ export const EachTrainInfoCore = ({
from={from}
styles={styles}
actionSheetRef={actionSheetRef}
ScrollViewRef={ScrollViewRef}
scrollHandlers={scrollHandlers}
containerProps={{
style: {
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);
//トレインビュー表示対象(特急、マリン)かを判定
useEffect(() => {
if (!data.limited) return;
if (!data.limited) return () => {};
setIsTrainView(
getType(data.limited.split(":")[0]) &&
!data.limited.split(":")[1].match("サンポート")

View File

@ -0,0 +1,179 @@
import React, { useEffect, useRef, useState } from "react";
import {
View,
Text,
TouchableOpacity,
Platform,
Image,
BackHandler,
} from "react-native";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import ActionSheet, { SheetManager } from "react-native-actions-sheet";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import ViewShot from "react-native-view-shot";
import * as Sharing from "expo-sharing";
import icons from "../../assets/icons/icons";
import { getAppIconName } from "expo-alternate-app-icons";
import { AS } from "@/storageControl";
export const TrainIconUpdate = () => {
const [iconList] = useState(icons());
const [currentIcon] = useState(getAppIconName());
const actionSheetRef = useRef(null);
const insets = useSafeAreaInsets();
const viewShot = useRef(null);
const onCapture = async () => {
const url = await viewShot.current.capture();
const ok = await Sharing.isAvailableAsync();
if (ok) {
await Sharing.shareAsync(
"file://" + url,
(options = { mimeType: "image/jpeg", dialogTitle: "Share this image" })
);
}
};
return (
<ActionSheet
gestureEnabled
CustomHeaderComponent={<></>}
onClose={() => {
AS.setItem("isSetIcon", "false");
}}
ref={actionSheetRef}
isModal={Platform.OS == "ios"}
containerStyle={
Platform.OS == "android"
? {
paddingBottom: insets.bottom,
}
: {}
}
useBottomSafeAreaPadding={Platform.OS == "android"}
>
<Handler />
<View
style={{
backgroundColor: "#0099CC",
borderTopRadius: 5,
borderColor: "dark",
borderWidth: 1,
}}
>
<View style={{ height: 26, width: "100%", backgroundColor: "#0099CC" }}>
<View
style={{
height: 6,
width: 45,
borderRadius: 100,
backgroundColor: "#f0f0f0",
marginVertical: 10,
alignSelf: "center",
}}
/>
</View>
<ViewShot ref={viewShot} options={{ format: "jpg" }}>
<View
style={{
padding: 10,
flexDirection: "row",
alignItems: "center",
backgroundColor: "#0099CC",
}}
>
<Text style={{ fontSize: 30, fontWeight: "bold", color: "white" }}>
</Text>
<View style={{ flex: 1 }} />
</View>
{currentIcon ? (
<View
style={{
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
backgroundColor: "#FFFFFFEE",
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={{
padding: 10,
flexDirection: "row",
alignItems: "center",
backgroundColor: "#0099CC",
}}
>
<Text style={{ fontSize: 15, fontWeight: "bold", color: "white" }}>
JR四国非公式アプリを更新して好きなアイコンに変更してみよう
</Text>
</View>
</ViewShot>
<View
style={{
padding: 10,
backgroundColor: "#0099CC",
flexDirection: "row",
justifyContent: "space-between",
}}
>
<TouchableOpacity
style={{
padding: 10,
flexDirection: "row",
borderColor: "white",
borderWidth: 1,
margin: 10,
borderRadius: 5,
alignItems: "center",
backgroundColor: "#0099CC",
flex: 1,
}}
onPress={onCapture}
>
<MaterialCommunityIcons name="share" color="white" size={30} />
<View style={{ flex: 1 }} />
<Text style={{ fontSize: 25, fontWeight: "bold", color: "white" }}>
</Text>
<View style={{ flex: 1 }} />
</TouchableOpacity>
</View>
</View>
</ActionSheet>
);
};
const Handler = () => {
useEffect(() => {
const backAction = () => {
SheetManager.hide("JRSTraInfo");
return true;
};
const backHandler = BackHandler.addEventListener(
"hardwareBackPress",
backAction
);
return () => backHandler.remove();
}, []);
return <></>;
};

View File

@ -9,6 +9,7 @@ import {
import ActionSheet, { SheetManager } from "react-native-actions-sheet";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { useTrainMenu } from "../../stateBox/useTrainMenu";
import { useCurrentTrain } from "../../stateBox/useCurrentTrain";
import lineColorList from "../../assets/originData/lineColorList";
import { stationIDPair } from "../../lib/getStationList2";
import { lineListPair } from "../../lib/getStationList";
@ -19,6 +20,7 @@ export const TrainMenuLineSelector = () => {
setSelectedLine,
mapsStationData: stationData,
} = useTrainMenu();
const { webview } = useCurrentTrain();
const actionSheetRef = useRef(null);
const insets = useSafeAreaInsets();
const platformIs = Platform.OS == "android";
@ -52,7 +54,25 @@ export const TrainMenuLineSelector = () => {
}}
onPress={() => {
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 File

@ -3,10 +3,12 @@ import { EachTrainInfo } from "./EachTrainInfo";
import { JRSTraInfo } from "./JRSTraInfo";
import { StationDeteilView } from "./StationDeteilView";
import { TrainMenuLineSelector } from "./TrainMenuLineSelector";
import { TrainIconUpdate } from "./TrainIconUpdate";
registerSheet("EachTrainInfo", EachTrainInfo);
registerSheet("JRSTraInfo", JRSTraInfo);
registerSheet("StationDetailView", StationDeteilView);
registerSheet("TrainMenuLineSelector", TrainMenuLineSelector);
registerSheet("TrainIconUpdate", TrainIconUpdate);
export {};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,10 +5,11 @@ import {
Ionicons,
MaterialCommunityIcons,
} 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 { TextBox } from "../atom/TextBox";
import { TicketBox } from "../atom/TicketBox";
import { ListItem } from "native-base";
export const FixedContentBottom = (props) => {
return (
@ -249,10 +250,16 @@ export const FixedContentBottom = (props) => {
name: "しこくたぬきのぽんちゃん 【四国家サポーターズクラブ】",
},
].map((d) => (
<ListItem onPress={() => Linking.openURL(d.url)}>
<Text>{d.name}</Text>
<View style={{ flex: 1 }} />
<Icon name="chevron-right" size={20} />
<ListItem bottomDivider onPress={() => Linking.openURL(d.url)}
key={d.url}friction={90} //
tension={100} // These props are passed to the parent component (here TouchableScale)
activeScale={0.95} //
Component={TouchableScale}
>
<ListItem.Content>
<ListItem.Title>{d.name}</ListItem.Title>
</ListItem.Content>
<ListItem.Chevron />
</ListItem>
))}
</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 { View, Text, TouchableOpacity } from "react-native";
import { Pagination } from "react-native-snap-carousel";
import { useInterval } from "../../lib/useInterval";
import lineColorList from "../../assets/originData/lineColorList";
@ -18,78 +17,6 @@ type StationProps = {
lat: 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 = {
currentStation: StationProps[];
active: boolean;
@ -107,41 +34,42 @@ export const StationNumber: FC<StationNumberProps> = (props) => {
const lineID = data[animation].StationNumber.slice(0, 1);
const lineName = data[animation].StationNumber.slice(1);
const size = active ? 24 : 18;
const margin = active ? 3 : 6;
const border = active ? 2 : 1;
return (
<>
<TouchableOpacity
onPress={onPress} style={{
width: 28,
height:24,
alignContent:"center",
alignItems:"center",
justifyContent:"center",
position:"relative",
}}>
{active && (
<View style={{ position: "relative", width: 0, height: 0 }}>
<View
style={{
flex: 1,
position: "absolute",
width: 28,
height: 28,
marginLeft: 1,
marginRight: 1,
marginHorizontal:1,
borderRadius: 22,
borderColor: "black",
borderWidth: 2,
left: 0,
top: -14,
left: -1,
top: -2,
zIndex:10
}}
/>
</View>
)}
<TouchableOpacity
onPress={onPress}
<View
style={{
alignContent: "center",
alignItems: "center",
width: size,
height: size,
marginLeft: margin,
marginRight: margin,
borderColor: lineColorList[lineID],
backgroundColor: "white",
borderWidth: border,
borderWidth: active ? 2 : 1,
borderRadius: 22,
}}
key={currentStation[0].StationNumber + lineID}
@ -161,7 +89,7 @@ export const StationNumber: FC<StationNumberProps> = (props) => {
{lineID + "\n" + lineName}
</Text>
<View style={{ flex: 1 }} />
</TouchableOpacity>
</>
</View>
</TouchableOpacity>
);
};

View File

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

View File

@ -0,0 +1,154 @@
import React, { useState } from "react";
import {
View,
Text,
TouchableOpacity,
ScrollView,
Image,
ToastAndroid,
Platform,
} from "react-native";
import { useNavigation } from "@react-navigation/native";
import * as Updates from "expo-updates";
import { AS } from "../../storageControl";
import icons from "../../assets/icons/icons";
import { setAlternateAppIcon, getAppIconName } 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) => {
AS.setItem("isSetIcon", "true");
if (Platform.OS === "android") {
ToastAndroid.show(
"アイコンを変更しました。アプリを再起動します。",
ToastAndroid.SHORT
);
} else if (Platform.OS === "ios") {
Updates.reloadAsync();
}
})
.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 { View, Text, TouchableOpacity, ScrollView } from "react-native";
import { useNavigation } from "@react-navigation/native";
import { SwitchArea } from "../atom/SwitchArea";
import { CheckBox } from "react-native-elements";
import { TripleSwitchArea } from "../atom/TripleSwitchArea";
@ -21,12 +22,13 @@ export const LayoutSettings = ({
headerSize,
setHeaderSize,
}) => {
const { goBack } = useNavigation();
return (
<View style={{ height: "100%", backgroundColor: "#0099CC" }}>
<View style={{ backgroundColor: "#0099CC", flexDirection: "row" }}>
<View style={{ flex: 1 }}>
<TouchableOpacity
onPress={() => navigate("settingTopPage")}
onPress={goBack}
style={{
flexDirection: "column",
flex: 1,

View File

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

View File

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

View File

@ -8,10 +8,11 @@ import {
Image,
useWindowDimensions,
ToastAndroid,
Platform
} from "react-native";
import { createStackNavigator } from "@react-navigation/stack";
import { TransitionPresets } from "@react-navigation/stack";
import * as ExpoFelicaReader from "../../modules/expo-felica-reader/src";
//import * as ExpoFelicaReader from "../../modules/expo-felica-reader/src";
import * as Updates from "expo-updates";
import StatusbarDetect from "../../StatusbarDetect";
import { AS } from "../../storageControl";
@ -23,6 +24,7 @@ import { LayoutSettings } from "./LayoutSettings";
import { FavoriteSettings } from "./FavoriteSettings";
import { WidgetSettings } from "./WidgetSettings";
import { NotificationSettings } from "./NotificationSettings";
import { LauncherIconSettings } from "./LauncherIconSettings";
const Stack = createStackNavigator();
export default function Setting(props) {
@ -48,8 +50,8 @@ export default function Setting(props) {
AS.getItem("startPage").then(setStartPage);
}, []);
const testNFC = async () => {
const result = await ExpoFelicaReader.scan();
alert(result);
//const result = await ExpoFelicaReader.scan();
//alert(result);
};
const updateAndReload = () => {
Promise.all([
@ -136,7 +138,7 @@ export default function Setting(props) {
/>
)}
</Stack.Screen>
<Stack.Screen
{Platform.OS === 'android' && <Stack.Screen
name="WidgetSettings"
options={{
gestureEnabled: true,
@ -147,6 +149,18 @@ export default function Setting(props) {
}}
>
{(props) => <WidgetSettings {...props} navigate={navigate} />}
</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
name="FavoriteSettings"

View File

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

View File

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

View File

@ -1,7 +1,6 @@
import React, { useRef, useState, useEffect, useLayoutEffect } from "react";
import { View, Text, TouchableOpacity, Linking } from "react-native";
import MapView, { Marker } from "react-native-maps";
import { MaterialCommunityIcons, Ionicons } from "@expo/vector-icons";
import MapView from "react-native-maps";
import { useCurrentTrain } from "../stateBox/useCurrentTrain";
import { useNavigation } from "@react-navigation/native";
import lineColorList from "../assets/originData/lineColorList";
@ -15,7 +14,7 @@ import { MapsButton } from "./TrainMenu/MapsButton";
export default function TrainMenu({ style }) {
const { webview } = useCurrentTrain();
const mapRef = useRef();
const { navigate } = useNavigation();
const { navigate, goBack } = useNavigation();
const [stationPin, setStationPin] = useState([]);
const {
selectedLine,
@ -35,12 +34,6 @@ export default function TrainMenu({ style }) {
""
).split(",");
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 });
});
});
@ -82,7 +75,7 @@ export default function TrainMenu({ style }) {
d={d}
navigate={navigate}
webview={webview}
key={D.StationNumber+d}
key={D.StationNumber + d}
/>
))}
</MapView>
@ -152,7 +145,27 @@ export default function TrainMenu({ style }) {
opacity: selectedLine == d ? 1 : !selectedLine ? 1 : 0.5,
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
style={{ color: "white", fontWeight: "bold", fontSize: 20 }}
@ -201,7 +214,7 @@ export default function TrainMenu({ style }) {
)}
<MapsButton
onPress={() => {
navigate("Apps");
goBack();
webview.current?.injectJavaScript(injectJavaScript);
}}
top={0}
@ -209,4 +222,4 @@ export default function TrainMenu({ style }) {
/>
</View>
);
}
}

226
components/trainMenu.web.js Normal file
View File

@ -0,0 +1,226 @@
import React, { useRef, useState, useEffect, useLayoutEffect } from "react";
import { View, Text, TouchableOpacity, Linking } from "react-native";
//import MapView from "react-native-maps";
import { useCurrentTrain } from "../stateBox/useCurrentTrain";
import { useNavigation } from "@react-navigation/native";
import lineColorList from "../assets/originData/lineColorList";
import { stationIDPair } from "../lib/getStationList2";
import { lineListPair } from "../lib/getStationList";
import { SheetManager } from "react-native-actions-sheet";
import { useTrainMenu } from "../stateBox/useTrainMenu";
//import { MapPin } from "./TrainMenu/MapPin";
import { UsefulBox } from "./TrainMenu/UsefulBox";
import { MapsButton } from "./TrainMenu/MapsButton";
export default function TrainMenu({ style }) {
return null;
const { webview } = useCurrentTrain();
const mapRef = useRef();
const { navigate, goBack } = useNavigation();
const [stationPin, setStationPin] = useState([]);
const {
selectedLine,
setSelectedLine,
injectJavaScript,
setInjectJavaScript,
mapsStationData: stationData,
} = useTrainMenu();
useEffect(() => {
const stationPinData = [];
Object.keys(stationData).forEach((d, indexBase) => {
stationData[d].forEach((D, index) => {
if (!D.StationMap) return null;
if (selectedLine && selectedLine != d) return;
const latlng = D.StationMap.replace(
"https://www.google.co.jp/maps/place/",
""
).split(",");
if (latlng.length == 0) return null;
stationPinData.push({ D, d, latlng, indexBase: 0, index });
});
});
setStationPin(stationPinData);
}, [stationData, selectedLine]);
useLayoutEffect(() => {
mapRef.current.fitToCoordinates(
stationPin.map(({ latlng }) => ({
latitude: parseFloat(latlng[0]),
longitude: parseFloat(latlng[1]),
})),
{ edgePadding: { top: 80, bottom: 120, left: 50, right: 50 } } // Add margin values here
);
}, [stationPin]);
return (
<View style={{ height: "100%", backgroundColor: "#0099CC", ...style }}>
<MapView
style={{ flex: 1, width: "100%", height: "100%" }}
showsUserLocation={true}
loadingEnabled={true}
showsMyLocationButton={false}
moveOnMarkerPress={false}
showsCompass={false}
ref={mapRef}
//provider={PROVIDER_GOOGLE}
initialRegion={{
latitude: 33.774519,
longitude: 133.533306,
latitudeDelta: 1.8, //小さくなるほどズーム
longitudeDelta: 1.8,
}}
>
{stationPin.map(({ D, d, latlng, indexBase, index }) => (
<MapPin
index={index}
indexBase={indexBase}
latlng={latlng}
D={D}
d={d}
navigate={navigate}
webview={webview}
key={D.StationNumber + d}
/>
))}
</MapView>
<View style={{ position: "relative" }}>
<View
style={{
flexDirection: "row",
position: "absolute",
width: "100vw",
bottom: 0,
flex: 1,
}}
>
<TouchableOpacity
style={{
backgroundColor: selectedLine
? lineColorList[stationIDPair[selectedLine]]
: "#0099CC",
padding: 10,
zIndex: 1,
alignItems: "center",
position: "absolute",
bottom: 0,
width: "100%",
paddingBottom: 50,
}}
onPress={() => SheetManager.show("TrainMenuLineSelector")}
>
<Text
style={{
color: "white",
fontWeight: "bold",
fontSize: 10,
textAlign: "center",
}}
>
  ここを押して路線をフィルタリングできます  
</Text>
<Text
style={{
color: "white",
fontWeight: "bold",
fontSize: 20,
textAlign: "center",
}}
>
{selectedLine
? lineListPair[stationIDPair[selectedLine]]
: "JR四国 対象全駅"}
</Text>
</TouchableOpacity>
<Text style={{ position: "absolute", bottom: 40 }}>
路線記号からフィルタリング
</Text>
{Object.keys(stationData).map((d) => (
<TouchableOpacity
style={{
flex: 1,
backgroundColor: lineColorList[stationIDPair[d]],
padding: 5,
margin: 2,
borderRadius: 10,
borderColor: "white",
borderWidth: 1,
borderStyle: "solid",
alignItems: "center",
opacity: selectedLine == d ? 1 : !selectedLine ? 1 : 0.5,
zIndex: 10,
}}
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
style={{ color: "white", fontWeight: "bold", fontSize: 20 }}
>
{stationIDPair[d]}
</Text>
</TouchableOpacity>
))}
</View>
</View>
{navigate && (
<View style={{ flexDirection: "row" }}>
<UsefulBox
backgroundColor={"#F89038"}
icon="train-car"
flex={1}
onPressButton={() =>
navigate("howto", {
info: "https://train.jr-shikoku.co.jp/usage.htm",
})
}
>
使い方
</UsefulBox>
<UsefulBox
backgroundColor={"#EA4752"}
icon="star"
flex={1}
onPressButton={() => navigate("favoriteList")}
>
お気に入り
</UsefulBox>
<UsefulBox
backgroundColor={"#91C31F"}
icon="clipboard-list-outline"
flex={1}
onPressButton={() =>
Linking.openURL(
"https://nexcloud.haruk.in/apps/forms/ZRHjWFF7znr5Xjr2"
)
}
>
フィードバック
</UsefulBox>
</View>
)}
<MapsButton
onPress={() => {
goBack();
webview.current?.injectJavaScript(injectJavaScript);
}}
top={0}
mapSwitch={"flex"}
/>
</View>
);
}

View File

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

View File

@ -1 +1 @@
export const news = "2025-01-09";
export const news = "2025-03-06";

View File

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

View File

@ -4,15 +4,17 @@ import { WebView } from "react-native-webview";
import { BigButton } from "./components/atom/BigButton";
import { useNavigation } from "@react-navigation/native";
export default ({ navigation: { navigate }, route }) => {
if (!route.params) {
return null
}
const { info, goTo, useShow } = route.params;
const { goBack } = useNavigation();
const onExit = () => {
if(goTo != "NearTrainDiagramView") {
navigate(goTo || "Apps");
if (goTo != "NearTrainDiagramView") {
//navigate(goTo || "Apps");
useShow && useShow();
} else {
goBack();
}
goBack();
};
return (
<View style={styles}>

View File

@ -1,5 +1,7 @@
import 'babel-polyfill';
import { registerRootComponent } from "expo";
import { registerWidgetTaskHandler } from "react-native-android-widget";
import { Platform } from "react-native";
import App from "./App";
import { widgetTaskHandler } from "./components/AndroidWidget/widget-task-handler";
@ -8,4 +10,6 @@ import { widgetTaskHandler } from "./components/AndroidWidget/widget-task-handle
// It also ensures that whether you load the app in Expo Go or in a native build,
// the environment is set up appropriately
registerRootComponent(App);
registerWidgetTaskHandler(widgetTaskHandler);
if (Platform.OS === "android") {
registerWidgetTaskHandler(widgetTaskHandler);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,20 +1,72 @@
import React from "react";
import React, { FC } from "react";
import { Ionicons, AntDesign } from "@expo/vector-icons";
import { Text, View } from "react-native";
type name = keyof typeof Ionicons.glyphMap & keyof typeof AntDesign.glyphMap;
type type = "Ionicons" | "AntDesign";
export const initIcon = (name: name, type:type) => {
export const initIcon = (
name: name,
type: type,
tabBarBadge: string,
isInfo: boolean
) => {
switch (type) {
case "Ionicons":
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":
return ({ focused, color, size }) => (
<AntDesign
name={name}
size={32}
color={focused ? "#0099CC" : "black"}
/>
<>
{!!tabBarBadge && <Badge tabBarBadge={tabBarBadge} isInfo={isInfo} />}
<AntDesign
name={name}
size={30}
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つしか残っていない場合、それを返して終了する
if (providers.length === 1) {
return providers[0];

File diff suppressed because it is too large Load Diff

102
menu.js
View File

@ -1,5 +1,5 @@
import React, { useRef, useState, useEffect } from "react";
import Carousel, { Pagination } from "react-native-snap-carousel";
import Carousel from "react-native-reanimated-carousel";
import {
Platform,
View,
@ -8,6 +8,7 @@ import {
Text,
TouchableOpacity,
LayoutAnimation,
Dimensions,
} from "react-native";
import Constants from "expo-constants";
import * as Location from "expo-location";
@ -32,9 +33,10 @@ import { SheetManager } from "react-native-actions-sheet";
import { useTrainDelayData } from "./stateBox/useTrainDelayData";
import { useNavigation } from "@react-navigation/native";
import { useStationList } from "./stateBox/useStationList";
import { Paginations } from "./components/Menu/StationPagination";
import { StationNumber } from "./components/Menu/StationPagination";
import lineColorList from "./assets/originData/lineColorList";
import { AS } from "./storageControl";
import { SimpleDot } from "./components/Menu/SimpleDot";
export default function Menu({ getCurrentTrain }) {
const { navigate } = useNavigation();
@ -44,6 +46,7 @@ export default function Menu({ getCurrentTrain }) {
//位置情報
const [locationStatus, setLocationStatus] = useState(null);
useEffect(() => {
if (Platform.OS == "web") return;
Location.requestForegroundPermissionsAsync().then((data) => {
setLocationStatus(
Platform.OS == "ios"
@ -118,13 +121,13 @@ export default function Menu({ getCurrentTrain }) {
const count = selectedCurrentStation - 1;
setSelectedCurrentStation(count);
}
}, [selectedCurrentStation, currentStation, favoriteStation]);
}, [selectedCurrentStation, currentStation, allStationData]);
useEffect(() => {
if (!carouselRef.current) return;
if (carouselRef.current?._itemToSnapTo != selectedCurrentStation) {
carouselRef.current.snapToItem(0);
carouselRef.current.snapToItem(selectedCurrentStation);
}
carouselRef?.current.scrollTo({
count: selectedCurrentStation - carouselRef.current.getCurrentIndex(),
animated: true,
});
}, [selectedCurrentStation]);
//全列車ダイヤリストを作成するuseEffect
@ -162,10 +165,11 @@ export default function Menu({ getCurrentTrain }) {
});
AS.setItem(
"CarouselSettings/activeDotSettings",
!dotButton ? "true": "false"
!dotButton ? "true" : "false"
);
setDotButton(!dotButton);
}
};
const width = Dimensions.get("window").width;
return (
<View
style={{
@ -179,41 +183,80 @@ export default function Menu({ getCurrentTrain }) {
<ScrollView>
<TopMenuButton />
{originalStationList.length != 0 && allStationData.length != 0 && (
<>
<View style={{ flex: 1, paddingTop: 10 }}>
<Carousel
ref={carouselRef}
layout={"default"}
data={originalStationList && allStationData}
sliderWidth={wp("100%")}
itemWidth={wp("80%")}
enableMomentum
callbackOffsetMargin={1000}
activeAnimationOptions={0.3}
height={(wp("80%") / 20) * 9 + 10}
pagingEnabled={true}
snapEnabled={true}
loop={false}
width={width}
style={{ width: width, alignContent: "center" }}
mode="parallax"
modeConfig={{
parallaxScrollingScale: 1,
parallaxScrollingOffset: 100,
parallaxAdjacentItemScale: 0.8,
}}
onSnapToItem={setSelectedCurrentStation}
renderItem={({ item }) => {
renderItem={({ item, index }) => {
return (
<View
style={{ marginVertical: 10 }}
style={{
backgroundColor: "#0000",
width: width,
flexDirection: "row",
marginLeft: 0,
marginRight: 0,
}}
key={item[0].StationNumber}
>
<View style={{ flex: 1 }} />
<Sign
currentStation={item}
isCurrentStation={item == currentStation}
oP={oPSign}
oLP={oLPSign}
/>
<View style={{ flex: 1 }} />
</View>
);
}}
/>
<Paginations
entries={allStationData}
activeSlide={selectedCurrentStation}
carouselRef={carouselRef}
setSelectedCurrentStation={setSelectedCurrentStation}
dotButton={dotButton}
/>
</>
<View
style={{
flexDirection: "row",
justifyContent: "center",
alignContent: "center",
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 &&
originalStationList.length != 0 &&
@ -350,10 +393,13 @@ const JRSTraInfoBox = () => {
/>
</View>
) : delayData ? (
delayData.map((d,index,array) => {
delayData.map((d, index, array) => {
let data = d.split(" ");
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 }}>
{data[0].replace("\n", "")}
</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>
);
};

156
ndView.tsx Normal file
View File

@ -0,0 +1,156 @@
import React, { Ref, useRef, useState,useEffect } from "react";
import { View, Platform, TouchableOpacity, StyleProp, ViewStyle,Linking } from "react-native";
import { WebView } from "react-native-webview";
import Constants from "expo-constants";
import { Ionicons } from "@expo/vector-icons";
import { useNavigation } from "@react-navigation/native";
export default function tndView() {
const webview = useRef<WebView>(null);
const { navigate, addListener, isFocused } = useNavigation();
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);
`;
const goToTrainMenu = () =>{
if (Platform.OS === "web") {
Linking.openURL("https://www.jr-shikoku.co.jp/info/");
setTimeout(() => {
// @ts-ignore
navigate("topMenu", { screen: "menu" });
}, 100);
return;
}
}
useEffect(() => {
// @ts-ignore
const unsubscribe = addListener("tabPress", goToTrainMenu);
return unsubscribe;
}, [addListener]);
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

@ -7,55 +7,74 @@
"eject": "expo eject"
},
"dependencies": {
"@expo/metro-runtime": "~4.0.1",
"@expo/ngrok": "^4.1.0",
"@expo/vector-icons": "^14.0.0",
"@react-native-async-storage/async-storage": "1.21.0",
"@react-native-community/masked-view": "0.1.10",
"@react-navigation/bottom-tabs": "^5.11.11",
"@react-navigation/native": "^5.9.4",
"@react-navigation/stack": "^5.14.5",
"@expo/vector-icons": "^14.0.2",
"@gorhom/bottom-sheet": "^5",
"@lottiefiles/dotlottie-react": "^0.13.0",
"@react-native-async-storage/async-storage": "1.23.1",
"@react-native-masked-view/masked-view": "0.3.2",
"@react-navigation/bottom-tabs": "^7.2.0",
"@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",
"eas-cli": "^5.9.1",
"expo": "^50.0.11",
"expo-dev-client": "~3.3.9",
"expo-device": "~5.9.3",
"expo-font": "~11.10.3",
"expo-location": "~16.5.5",
"expo-notifications": "~0.27.6",
"expo-screen-orientation": "~6.4.1",
"expo-sharing": "~11.10.0",
"expo-updates": "~0.24.11",
"expo-web-browser": "~12.8.2",
"expo": "^52.0.0",
"expo-alternate-app-icons": "^1.3.0",
"expo-clipboard": "~7.0.1",
"expo-constants": "~17.0.4",
"expo-dev-client": "~5.0.9",
"expo-device": "~7.0.2",
"expo-font": "~13.0.3",
"expo-haptics": "~14.0.1",
"expo-intent-launcher": "~12.0.2",
"expo-linear-gradient": "~14.0.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",
"lottie-react-native": "6.5.1",
"lottie-react-native": "7.1.0",
"native-base": "^2.15.2",
"npm": "^7.18.1",
"pushy-react-native": "^1.0.18",
"react": "18.2.0",
"react-native": "0.73.4",
"react-native-actions-sheet": "0.8.21",
"react-native-android-widget": "^0.11.2",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-native": "0.76.6",
"react-native-actions-sheet": "^0.9.7",
"react-native-android-widget": "^0.15.1",
"react-native-auto-height-image": "^3.2.4",
"react-native-elements": "^3.4.2",
"react-native-gesture-handler": "~2.14.0",
"react-native-maps": "1.10.0",
"react-native-reanimated": "~3.6.2",
"react-native-gesture-handler": "~2.20.2",
"react-native-maps": "1.18.0",
"react-native-reanimated": "~3.16.1",
"react-native-reanimated-carousel": "^3.5.1",
"react-native-remote-svg": "^2.0.6",
"react-native-responsive-screen": "^1.4.2",
"react-native-router-flux": "^4.3.1",
"react-native-safe-area-context": "4.8.2",
"react-native-screens": "~3.29.0",
"react-native-safe-area-context": "4.12.0",
"react-native-screens": "~4.4.0",
"react-native-snap-carousel": "^3.9.1",
"react-native-sortables": "^1.1.0",
"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-vector-icons": "^8.1.0",
"react-native-view-shot": "3.8.0",
"react-native-webview": "13.6.4",
"react-native-touchable-scale": "^2.2.0",
"react-native-vector-icons": "^10.2.0",
"react-native-view-shot": "~4.0.3",
"react-native-walkthrough-tooltip": "^1.6.0",
"react-native-web": "~0.19.13",
"react-native-webview": "13.12.5",
"typescript": "^5.3.0"
},
"devDependencies": {
"babel-preset-expo": "^10.0.0"
"babel-preset-expo": "~12.0.0"
},
"private": true
}

1
public/_redirects Normal file
View File

@ -0,0 +1 @@
/* /index.html 200

View File

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

View File

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

View File

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

View File

@ -1,4 +1,13 @@
{
"compilerOptions": {},
"compilerOptions": {
"plugins": [
{
"@/*": ["./*"] //
}
],
"paths": {
"@/*": ["./*"] //
}
},
"extends": "expo/tsconfig.base"
}

7194
yarn.lock

File diff suppressed because it is too large Load Diff