tsx化
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { NavigationContainer } from "@react-navigation/native";
|
||||
import { NavigationContainer, NavigationContainerRef } from "@react-navigation/native";
|
||||
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
|
||||
import { Platform } from "react-native";
|
||||
import { useFonts } from "expo-font";
|
||||
@@ -10,17 +10,40 @@ import { MenuPage } from "./MenuPage";
|
||||
import { useAreaInfo } from "./stateBox/useAreaInfo";
|
||||
import "./components/ActionSheetComponents/sheets";
|
||||
|
||||
type RootTabParamList = {
|
||||
positions: undefined;
|
||||
topMenu: undefined;
|
||||
information: undefined;
|
||||
};
|
||||
|
||||
type TabProps = {
|
||||
name: string;
|
||||
label: string;
|
||||
icon: string;
|
||||
iconFamily: string;
|
||||
tabBarBadge?: string;
|
||||
isInfo?: boolean;
|
||||
};
|
||||
|
||||
export function AppContainer() {
|
||||
const Tab = createBottomTabNavigator();
|
||||
const Tab = createBottomTabNavigator<RootTabParamList>();
|
||||
const { areaInfo, areaIconBadgeText, isInfo } = useAreaInfo();
|
||||
const navigationRef = React.useRef();
|
||||
const getTabProps = (name, label, icon, iconFamily, tabBarBadge, isInfo) => ({
|
||||
const navigationRef = React.useRef<NavigationContainerRef<RootTabParamList>>(null);
|
||||
|
||||
const getTabProps = (
|
||||
name: keyof RootTabParamList,
|
||||
label: string,
|
||||
icon: string,
|
||||
iconFamily: "Ionicons" | "AntDesign",
|
||||
tabBarBadge?: string,
|
||||
isInfo?: boolean
|
||||
) => ({
|
||||
name,
|
||||
options: {
|
||||
tabBarLabel: label,
|
||||
headerShown: false,
|
||||
gestureEnabled: true,
|
||||
tabBarIcon: initIcon(icon, iconFamily,tabBarBadge,isInfo),
|
||||
tabBarIcon: initIcon(icon as any, iconFamily, tabBarBadge, isInfo),
|
||||
|
||||
},
|
||||
});
|
||||
@@ -32,15 +55,13 @@ export function AppContainer() {
|
||||
});
|
||||
return (
|
||||
<NavigationContainer ref={navigationRef}>
|
||||
{/* @ts-expect-error - Tab.Navigator type definition issue */}
|
||||
<Tab.Navigator
|
||||
initialRouteName="topMenu"
|
||||
screenOptions={{
|
||||
lazy: false,
|
||||
animation: "shift",
|
||||
tabBarHideOnKeyboard: Platform.OS === "android",
|
||||
}}
|
||||
detachInactiveScreens={false}
|
||||
lazy={false}
|
||||
>
|
||||
<Tab.Screen
|
||||
{...getTabProps("positions", "走行位置", "barchart", "AntDesign")}
|
||||
@@ -28,7 +28,7 @@ export function MenuPage() {
|
||||
const { favoriteStation, setFavoriteStation } = useFavoriteStation();
|
||||
const { height, width } = useWindowDimensions();
|
||||
const tabBarHeight = useBottomTabBarHeight();
|
||||
const navigation = useNavigation();
|
||||
const navigation = useNavigation<any>();
|
||||
const { addListener } = navigation;
|
||||
useEffect(() => {
|
||||
AS.getItem(STORAGE_KEYS.START_PAGE)
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
import React, { useRef } from "react";
|
||||
import { Platform } from "react-native";
|
||||
import ActionSheet from "react-native-actions-sheet";
|
||||
import ActionSheet, { useScrollHandlers } from "react-native-actions-sheet";
|
||||
import { EachTrainInfoCore } from "./EachTrainInfoCore";
|
||||
export const EachTrainInfo = ({ payload }) => {
|
||||
if (!payload) return <></>;
|
||||
const actionSheetRef = useRef(null);
|
||||
const scrollHandlers = useScrollHandlers();
|
||||
return (
|
||||
<ActionSheet
|
||||
gestureEnabled={true}
|
||||
CustomHeaderComponent={<></>}
|
||||
ref={actionSheetRef}
|
||||
drawUnderStatusBar={false}
|
||||
isModal={Platform.OS == "ios"}
|
||||
|
||||
//useBottomSafeAreaPadding={Platform.OS == "android"}
|
||||
>
|
||||
<EachTrainInfoCore {...{ actionSheetRef, ...payload }} />
|
||||
<EachTrainInfoCore {...{ scrollHandlers, ...payload }} />
|
||||
</ActionSheet>
|
||||
);
|
||||
};
|
||||
@@ -33,10 +33,12 @@ type currentTrainDataType = {
|
||||
Type: string;
|
||||
Line: string;
|
||||
};
|
||||
type StationInfo = { StationName: string; StationNumber: string | null };
|
||||
|
||||
type props = {
|
||||
i: string;
|
||||
index: number;
|
||||
stationList: { StationName: string; StationNumber: string }[][];
|
||||
stationList: StationInfo[][];
|
||||
points: boolean;
|
||||
currentTrainData?: currentTrainDataType;
|
||||
openStationACFromEachTrainInfo?: (station: string) => void;
|
||||
@@ -84,18 +86,17 @@ export const EachStopList: FC<props> = ({
|
||||
.reduce((newArray, e) => newArray.concat(e), []);
|
||||
/*Array [
|
||||
Object {
|
||||
"StationName": "佐古",
|
||||
"Station_JP": "佐古",
|
||||
"StationNumber": "T01",
|
||||
},
|
||||
Object {
|
||||
"StationName": "佐古",
|
||||
"Station_JP": "佐古",
|
||||
"StationNumber": "B01",
|
||||
},
|
||||
] */
|
||||
const StationNumbers =
|
||||
Stations &&
|
||||
Stations.filter((d) => d.StationNumber).map((d) => d.StationNumber);
|
||||
|
||||
const StationNumbers = Stations
|
||||
.filter((d) => d.StationNumber != null)
|
||||
.map((d) => d.StationNumber as string);
|
||||
// SE文字列を表示用に変換
|
||||
const [seString, seType] = parseSeString(se);
|
||||
|
||||
|
||||
@@ -194,9 +194,9 @@ export const TrainDataView:FC<props> = ({
|
||||
<View style={{ flex: 1, flexDirection: "row" }}>
|
||||
<StateBox
|
||||
mode={mode}
|
||||
title={isNaN(currentTrainData?.delay) ? "状態" : "遅延時分"}
|
||||
title={typeof currentTrainData?.delay === "number" && !isNaN(currentTrainData?.delay) ? "遅延時分" : "状態"}
|
||||
text={`${currentTrainData?.delay}${
|
||||
isNaN(currentTrainData?.delay) ? "" : "分"
|
||||
typeof currentTrainData?.delay === "number" && !isNaN(currentTrainData?.delay) ? "分" : ""
|
||||
}`}
|
||||
/>
|
||||
</View>
|
||||
|
||||
@@ -8,8 +8,7 @@ import {
|
||||
BackHandler,
|
||||
Linking,
|
||||
} from "react-native";
|
||||
import { SheetManager } from "react-native-actions-sheet";
|
||||
import { useScrollHandlers } from "react-native-actions-sheet";
|
||||
import { SheetManager, useScrollHandlers } from "react-native-actions-sheet";
|
||||
import { getTrainType } from "../../lib/getTrainType";
|
||||
import { customTrainDataDetector } from "../custom-train-data";
|
||||
import { useDeviceOrientationChange } from "../../stateBox/useDeviceOrientationChange";
|
||||
@@ -35,32 +34,31 @@ import { useAutoScroll } from "./EachTrainInfoCore/hooks/useAutoScroll";
|
||||
import { useExtendedStations } from "./EachTrainInfoCore/hooks/useExtendedStations";
|
||||
|
||||
export const EachTrainInfoCore = ({
|
||||
actionSheetRef,
|
||||
data,
|
||||
openStationACFromEachTrainInfo,
|
||||
from,
|
||||
navigate,
|
||||
scrollHandlers,
|
||||
}) => {
|
||||
const { stationList } = useStationList();
|
||||
const { allCustomTrainData } = useAllTrainDiagram();
|
||||
const { setTrainInfo } = useTrainMenu();
|
||||
const { height } = useWindowDimensions();
|
||||
const { isLandscape } = useDeviceOrientationChange();
|
||||
|
||||
const scrollHandlers = actionSheetRef
|
||||
? useScrollHandlers("scrollview-1", actionSheetRef)
|
||||
: null;
|
||||
|
||||
// Custom hooks for data management
|
||||
const { trainData, setTrainData, trueTrainID } = useTrainDiagramData(data.trainNum);
|
||||
const { trainDataWithThrough, haveThrough } = useThroughStations(trainData);
|
||||
const { headStation, tailStation, nearTrainIDList } = useNearbyTrains(data.trainNum, trainData);
|
||||
const stopStationIDList = useStopStationIDs(trainDataWithThrough);
|
||||
const { currentTrainData, currentPosition, points, pointsDisplay } = useTrainPosition(
|
||||
data.trainNum,
|
||||
stopStationIDList
|
||||
const { trainData, setTrainData, trueTrainID } = useTrainDiagramData(
|
||||
data.trainNum
|
||||
);
|
||||
|
||||
const { trainDataWithThrough, haveThrough } = useThroughStations(trainData);
|
||||
const { headStation, tailStation, nearTrainIDList } = useNearbyTrains(
|
||||
data.trainNum,
|
||||
trainData
|
||||
);
|
||||
const stopStationIDList = useStopStationIDs(trainDataWithThrough);
|
||||
const { currentTrainData, currentPosition, points, pointsDisplay } =
|
||||
useTrainPosition(data.trainNum, stopStationIDList);
|
||||
|
||||
const {
|
||||
showHeadStation,
|
||||
showTailStation,
|
||||
@@ -73,7 +71,14 @@ export const EachTrainInfoCore = ({
|
||||
const [isJumped, setIsJumped] = useState(false);
|
||||
|
||||
// Auto scroll to current position
|
||||
useAutoScroll(points, trainDataWithThrough, scrollHandlers, isJumped, setIsJumped, setShowThrew);
|
||||
useAutoScroll(
|
||||
points,
|
||||
trainDataWithThrough,
|
||||
scrollHandlers,
|
||||
isJumped,
|
||||
setIsJumped,
|
||||
setShowThrew
|
||||
);
|
||||
|
||||
// Back button handler
|
||||
useEffect(() => {
|
||||
@@ -81,7 +86,10 @@ export const EachTrainInfoCore = ({
|
||||
SheetManager.hide("EachTrainInfo");
|
||||
return true;
|
||||
};
|
||||
const backHandler = BackHandler.addEventListener("hardwareBackPress", backAction);
|
||||
const backHandler = BackHandler.addEventListener(
|
||||
"hardwareBackPress",
|
||||
backAction
|
||||
);
|
||||
return () => backHandler.remove();
|
||||
}, []);
|
||||
|
||||
@@ -91,13 +99,13 @@ export const EachTrainInfoCore = ({
|
||||
|
||||
const openTrainInfo = (trainNum) => {
|
||||
const train = customTrainDataDetector(trainNum, allCustomTrainData);
|
||||
|
||||
|
||||
let trainNumber = "";
|
||||
if (train.train_num_distance && !isNaN(train.train_num_distance)) {
|
||||
if (train.train_num_distance && !isNaN(Number(train.train_num_distance))) {
|
||||
const numericPart = parseInt(trainNum.replace("M", "").replace("D", ""));
|
||||
trainNumber = `${numericPart - train.train_num_distance}号`;
|
||||
trainNumber = `${numericPart - Number(train.train_num_distance)}号`;
|
||||
}
|
||||
|
||||
|
||||
const limitedData = getTrainType({ type: train.type });
|
||||
const payload = {
|
||||
data: {
|
||||
@@ -107,12 +115,15 @@ export const EachTrainInfoCore = ({
|
||||
navigate,
|
||||
from: from === "LED" ? "LED2" : "NearTrainDiagramView",
|
||||
};
|
||||
|
||||
|
||||
if (isLandscape) {
|
||||
setTrainInfo(payload.data);
|
||||
} else {
|
||||
SheetManager.hide("EachTrainInfo").then(() => {
|
||||
setTimeout(() => SheetManager.show("EachTrainInfo", { payload }), 200);
|
||||
setTimeout(() => {
|
||||
// @ts-expect-error - SheetManager payload type is too restrictive
|
||||
SheetManager.show("EachTrainInfo", { payload });
|
||||
}, 200);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -121,25 +132,24 @@ export const EachTrainInfoCore = ({
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: "#0099CC",
|
||||
borderTopRadius: 5,
|
||||
borderTopLeftRadius: 5,
|
||||
borderTopRightRadius: 5,
|
||||
borderColor: "dark",
|
||||
borderWidth: 1,
|
||||
}}
|
||||
>
|
||||
{isLandscape || (
|
||||
<View style={{ height: 26, width: "100%" }}>
|
||||
<View
|
||||
style={{
|
||||
height: 6,
|
||||
width: 45,
|
||||
borderRadius: 100,
|
||||
backgroundColor: "#f0f0f0",
|
||||
marginVertical: 10,
|
||||
alignSelf: "center",
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
<View style={{ height: 26, width: "100%" }}>
|
||||
<View
|
||||
style={{
|
||||
height: 6,
|
||||
width: 45,
|
||||
borderRadius: 100,
|
||||
backgroundColor: "#f0f0f0",
|
||||
marginVertical: 10,
|
||||
alignSelf: "center",
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
<HeaderText
|
||||
data={data}
|
||||
trainData={trainData}
|
||||
@@ -149,12 +159,13 @@ export const EachTrainInfoCore = ({
|
||||
tailStation={tailStation}
|
||||
navigate={navigate}
|
||||
from={from}
|
||||
fontLoaded={true}
|
||||
scrollHandlers={scrollHandlers}
|
||||
/>
|
||||
|
||||
<DynamicHeaderScrollView
|
||||
from={from}
|
||||
styles={styles}
|
||||
styles={styles as any}
|
||||
scrollHandlers={scrollHandlers}
|
||||
containerProps={{
|
||||
style: {
|
||||
@@ -197,18 +208,21 @@ export const EachTrainInfoCore = ({
|
||||
</Text>
|
||||
)}
|
||||
{headStation.length > 0 &&
|
||||
headStation.map((item, index) =>
|
||||
!showHeadStation.includes(index) && (
|
||||
<TouchableOpacity
|
||||
onPress={() => extendToHeadStation(item.station, item.dia, index)}
|
||||
style={styles.extendStationButton}
|
||||
key={`${item.station}-head${index}`}
|
||||
>
|
||||
<Text style={styles.extendStationText}>
|
||||
「本当の始発駅」を表示
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
headStation.map(
|
||||
(item, index) =>
|
||||
!showHeadStation.includes(index) && (
|
||||
<TouchableOpacity
|
||||
onPress={() =>
|
||||
extendToHeadStation(item.station, item.dia, index)
|
||||
}
|
||||
style={styles.extendStationButton}
|
||||
key={`${item.station}-head${index}`}
|
||||
>
|
||||
<Text style={styles.extendStationText}>
|
||||
「本当の始発駅」を表示
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
)}
|
||||
<ShowSpecialTrain
|
||||
isTrainDataNothing={trainData.length === 0}
|
||||
@@ -222,9 +236,7 @@ export const EachTrainInfoCore = ({
|
||||
}
|
||||
style={styles.twitterSearchButton}
|
||||
>
|
||||
<Text style={styles.extendStationText}>
|
||||
Twitterで検索
|
||||
</Text>
|
||||
<Text style={styles.extendStationText}>Twitterで検索</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{trainDataWithThrough.map((item, index, array) =>
|
||||
@@ -234,9 +246,9 @@ export const EachTrainInfoCore = ({
|
||||
<EachStopList
|
||||
i={item}
|
||||
index={index}
|
||||
stationList={stationList}
|
||||
stationList={stationList as any}
|
||||
points={pointsDisplay?.[index] || false}
|
||||
currentTrainData={currentTrainData}
|
||||
currentTrainData={currentTrainData as any}
|
||||
openStationACFromEachTrainInfo={openStationACFromEachTrainInfo}
|
||||
showThrew={showThrew}
|
||||
array={array}
|
||||
@@ -248,18 +260,19 @@ export const EachTrainInfoCore = ({
|
||||
時刻が斜体,青色になっている時刻はコミュニティで追加されている独自データです。
|
||||
</Text>
|
||||
{tailStation.length > 0 &&
|
||||
tailStation.map(({ station, dia }, index) =>
|
||||
!showTailStation.includes(index) && (
|
||||
<TouchableOpacity
|
||||
onPress={() => extendToTailStation(station, dia, index)}
|
||||
style={styles.extendStationButton}
|
||||
key={`${station}-tail${index}`}
|
||||
>
|
||||
<Text style={styles.extendStationText}>
|
||||
「本当の終着駅」を表示
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
tailStation.map(
|
||||
({ station, dia }, index) =>
|
||||
!showTailStation.includes(index) && (
|
||||
<TouchableOpacity
|
||||
onPress={() => extendToTailStation(station, dia, index)}
|
||||
style={styles.extendStationButton}
|
||||
key={`${station}-tail${index}`}
|
||||
>
|
||||
<Text style={styles.extendStationText}>
|
||||
「本当の終着駅」を表示
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
)}
|
||||
|
||||
<View style={styles.bottomSpacer} />
|
||||
@@ -1,9 +1,17 @@
|
||||
import { useEffect } from 'react';
|
||||
import { LayoutAnimation } from 'react-native';
|
||||
import React,{ useEffect, MutableRefObject } from 'react';
|
||||
import { LayoutAnimation, ScrollView } from 'react-native';
|
||||
|
||||
export const useAutoScroll = (points, trainDataWithThrough, scrollHandlers, isJumped, setIsJumped, setShowThrew) => {
|
||||
|
||||
export const useAutoScroll = (
|
||||
points: boolean[] | undefined,
|
||||
trainDataWithThrough: string[],
|
||||
scrollHandlers: any,
|
||||
isJumped: boolean,
|
||||
setIsJumped: (value: boolean) => void,
|
||||
setShowThrew: (value: boolean) => void
|
||||
) => {
|
||||
useEffect(() => {
|
||||
if (isJumped || !points?.length) return;
|
||||
if (isJumped || !points?.length || !scrollHandlers) return;
|
||||
|
||||
const currentPositionIndex = points.findIndex((d) => d === true);
|
||||
if (currentPositionIndex === -1) return;
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useStationList } from '@/stateBox/useStationList';
|
||||
|
||||
export const useStopStationIDs = (trainDataWithThrough) => {
|
||||
export const useStopStationIDs = (trainDataWithThrough: string[]) => {
|
||||
const { stationList } = useStationList();
|
||||
const [stopStationIDList, setStopStationIDList] = useState([]);
|
||||
const [stopStationIDList, setStopStationIDList] = useState<string[][]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const stationIDs = trainDataWithThrough.map((item) => {
|
||||
@@ -5,11 +5,21 @@ import { logger } from '@/utils/logger';
|
||||
import { useCurrentTrain } from '@/stateBox/useCurrentTrain';
|
||||
import { findReversalPoints } from '@/lib/eachTrainInfoCoreLib/findReversalPoints';
|
||||
|
||||
export const useTrainPosition = (trainNum, stopStationIDList) => {
|
||||
type TrainData = {
|
||||
trainNum: string;
|
||||
position?: string[];
|
||||
delay?: number | "入線";
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
export const useTrainPosition = (
|
||||
trainNum: string,
|
||||
stopStationIDList: string[][]
|
||||
) => {
|
||||
const { currentTrain, getCurrentStationData, getPosition } = useCurrentTrain();
|
||||
const [currentTrainData, setCurrentTrainData] = useState();
|
||||
const [currentPosition, setCurrentPosition] = useState([]);
|
||||
const [trainPositionSwitch, setTrainPositionSwitch] = useState('false');
|
||||
const [currentTrainData, setCurrentTrainData] = useState<TrainData | undefined>();
|
||||
const [currentPosition, setCurrentPosition] = useState<string[]>([]);
|
||||
const [trainPositionSwitch, setTrainPositionSwitch] = useState<string>('false');
|
||||
|
||||
useEffect(() => {
|
||||
const trainPosData = getCurrentStationData(trainNum);
|
||||
@@ -1,11 +1,5 @@
|
||||
import React from "react";
|
||||
import {
|
||||
View,
|
||||
Platform,
|
||||
useWindowDimensions,
|
||||
LayoutAnimation,
|
||||
Text,
|
||||
} from "react-native";
|
||||
import { View, Platform, useWindowDimensions } from "react-native";
|
||||
import Constants from "expo-constants";
|
||||
import * as Updates from "expo-updates";
|
||||
|
||||
@@ -13,16 +7,12 @@ import { lineList } from "../lib/getStationList";
|
||||
import { useCurrentTrain } from "../stateBox/useCurrentTrain";
|
||||
import { useDeviceOrientationChange } from "../stateBox/useDeviceOrientationChange";
|
||||
import { SheetManager } from "react-native-actions-sheet";
|
||||
import TrainMenu from "../components/trainMenu";
|
||||
import { EachTrainInfoCore } from "../components/ActionSheetComponents/EachTrainInfoCore";
|
||||
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
import { useTrainMenu } from "../stateBox/useTrainMenu";
|
||||
import { AppsWebView } from "./Apps/WebView";
|
||||
import { NewMenu } from "./Apps/NewMenu";
|
||||
import { MapsButton } from "./Apps/MapsButton";
|
||||
import { ReloadButton } from "./Apps/ReloadButton";
|
||||
import { LandscapeBackButton } from "./Apps/LandscapeBackButton";
|
||||
import { useStationList } from "../stateBox/useStationList";
|
||||
import { FixedPositionBox } from "./Apps/FixedPositionBox";
|
||||
/*
|
||||
@@ -58,10 +48,16 @@ export default function Apps() {
|
||||
currentStation: returnDataBase,
|
||||
navigate,
|
||||
goTo: "Apps",
|
||||
useShow: () => SheetManager.show("StationDetailView", { payload }),
|
||||
useShow: () => {
|
||||
// @ts-expect-error - SheetManager payload type is too restrictive
|
||||
SheetManager.show("StationDetailView", { payload });
|
||||
},
|
||||
onExit: () => SheetManager.hide("StationDetailView"),
|
||||
};
|
||||
setTimeout(() => SheetManager.show("StationDetailView", { payload }), 50);
|
||||
setTimeout(() => {
|
||||
// @ts-expect-error - SheetManager payload type is too restrictive
|
||||
SheetManager.show("StationDetailView", { payload });
|
||||
}, 50);
|
||||
} else {
|
||||
SheetManager.hide("StationDetailView");
|
||||
}
|
||||
@@ -75,61 +71,14 @@ export default function Apps() {
|
||||
}}
|
||||
onLayout={handleLayout}
|
||||
>
|
||||
{!trainInfo.trainNum && isLandscape ? (
|
||||
<TrainMenu
|
||||
style={{
|
||||
width: (width / 100) * 40,
|
||||
height: "100%",
|
||||
flexDirection: "column-reverse",
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
{/* {Status} */}
|
||||
<AppsWebView
|
||||
{...{
|
||||
openStationACFromEachTrainInfo,
|
||||
}}
|
||||
/>
|
||||
{isLandscape && trainInfo.trainNum && (
|
||||
<View
|
||||
style={{
|
||||
width: (width / 100) * 40,
|
||||
height: height,
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
<EachTrainInfoCore
|
||||
{...{
|
||||
data: trainInfo.trainNum ? trainInfo : undefined,
|
||||
openStationACFromEachTrainInfo,
|
||||
from: "Train",
|
||||
navigate,
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
{isLandscape || (
|
||||
<MapsButton
|
||||
onPress={() => {
|
||||
navigate("trainMenu", { webview });
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{isLandscape && trainInfo.trainNum && (
|
||||
<LandscapeBackButton
|
||||
onPress={() => {
|
||||
LayoutAnimation.easeInEaseOut();
|
||||
setTrainInfo({
|
||||
trainNum: undefined,
|
||||
limited: undefined,
|
||||
trainData: undefined,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{fixedPosition.type && (
|
||||
<FixedPositionBox />
|
||||
)}
|
||||
|
||||
{fixedPosition.type && <FixedPositionBox />}
|
||||
|
||||
{mapSwitch == "true" ? (
|
||||
<ReloadButton
|
||||
@@ -1,10 +1,23 @@
|
||||
import { ScrollView, View, Animated, LayoutAnimation } from "react-native";
|
||||
import React, { useEffect, useMemo, useState, useLayoutEffect } from "react";
|
||||
import { ScrollView, View, Animated, LayoutAnimation, ViewStyle, Platform } from "react-native";
|
||||
import React, { useEffect, useMemo, useState, useLayoutEffect, ReactNode, useRef } from "react";
|
||||
import { NativeViewGestureHandler } from "react-native-gesture-handler";
|
||||
import { AS } from "../storageControl";
|
||||
import { STORAGE_KEYS } from "@/constants";
|
||||
|
||||
export const DynamicHeaderScrollView = (props) => {
|
||||
type HeaderSize = "small" | "big" | "default";
|
||||
|
||||
type DynamicHeaderScrollViewProps = {
|
||||
children: ReactNode;
|
||||
containerProps?: Record<string, unknown>;
|
||||
shortHeader?: ReactNode;
|
||||
longHeader?: ReactNode;
|
||||
topStickyContent?: ReactNode;
|
||||
styles?: { header: ViewStyle };
|
||||
from?: string;
|
||||
scrollHandlers?: any;
|
||||
};
|
||||
|
||||
export const DynamicHeaderScrollView: React.FC<DynamicHeaderScrollViewProps> = (props) => {
|
||||
const {
|
||||
children,
|
||||
containerProps = {},
|
||||
@@ -88,7 +101,7 @@ export const DynamicHeaderScrollView = (props) => {
|
||||
opacity: 0,
|
||||
},
|
||||
};
|
||||
const StickyStyle = {
|
||||
const StickyStyle: Record<string, ViewStyle> = {
|
||||
on: {
|
||||
position: "absolute",
|
||||
width: "100%",
|
||||
@@ -106,9 +119,10 @@ export const DynamicHeaderScrollView = (props) => {
|
||||
};
|
||||
|
||||
const [headerVisible, setHeaderVisible] = useState(false);
|
||||
const fallbackScrollRef = useRef<ScrollView>(null);
|
||||
|
||||
const onScroll = (event) => {
|
||||
scrollHandlers.onScroll(event);
|
||||
scrollHandlers?.onScroll(event);
|
||||
switch (headerSize) {
|
||||
case "big":
|
||||
setHeaderVisible(false);
|
||||
@@ -152,14 +166,37 @@ export const DynamicHeaderScrollView = (props) => {
|
||||
{topStickyContent}
|
||||
</Animated.View>
|
||||
</View>
|
||||
<NativeViewGestureHandler
|
||||
simultaneousHandlers={scrollHandlers.simultaneousHandlers}
|
||||
>
|
||||
{Platform.OS === 'ios' ? (
|
||||
<NativeViewGestureHandler
|
||||
simultaneousHandlers={scrollHandlers?.simultaneousHandlers}
|
||||
>
|
||||
<ScrollView
|
||||
nestedScrollEnabled
|
||||
ref={scrollHandlers?.ref || fallbackScrollRef}
|
||||
onLayout={scrollHandlers?.onLayout}
|
||||
scrollEventThrottle={scrollHandlers?.scrollEventThrottle || 16}
|
||||
style={{ zIndex: 0 }}
|
||||
stickyHeaderIndices={[1]}
|
||||
onScroll={onScroll}
|
||||
>
|
||||
<View style={{ height: Scroll_Distance, flexDirection: "column" }} />
|
||||
{topStickyContent && (
|
||||
<View
|
||||
style={{
|
||||
paddingTop: Min_Header_Height + 40,
|
||||
flexDirection: "column",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{children}
|
||||
</ScrollView>
|
||||
</NativeViewGestureHandler>
|
||||
) : (
|
||||
<ScrollView
|
||||
nestedScrollEnabled
|
||||
ref={scrollHandlers.ref}
|
||||
onLayout={scrollHandlers.onLayout}
|
||||
scrollEventThrottle={scrollHandlers.scrollEventThrottle}
|
||||
ref={scrollHandlers?.ref || fallbackScrollRef}
|
||||
onLayout={scrollHandlers?.onLayout}
|
||||
scrollEventThrottle={scrollHandlers?.scrollEventThrottle || 16}
|
||||
style={{ zIndex: 0 }}
|
||||
stickyHeaderIndices={[1]}
|
||||
onScroll={onScroll}
|
||||
@@ -171,12 +208,11 @@ export const DynamicHeaderScrollView = (props) => {
|
||||
paddingTop: Min_Header_Height + 40,
|
||||
flexDirection: "column",
|
||||
}}
|
||||
index={1}
|
||||
/>
|
||||
)}
|
||||
{children}
|
||||
</ScrollView>
|
||||
</NativeViewGestureHandler>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
@@ -8,7 +8,7 @@ type Props = {
|
||||
index: number;
|
||||
indexBase: number;
|
||||
latlng: string[];
|
||||
D: StationProps[][];
|
||||
D: StationProps;
|
||||
d: string;
|
||||
navigate: (screen: string) => void;
|
||||
webview: React.RefObject<any>;
|
||||
|
||||
@@ -69,9 +69,8 @@ export const EachData: FC<Props> = (props) => {
|
||||
openStationACFromEachTrainInfo,
|
||||
from: "LED",
|
||||
};
|
||||
SheetManager.show("EachTrainInfo", {
|
||||
payload,
|
||||
});
|
||||
// @ts-expect-error - SheetManager payload type is too restrictive
|
||||
SheetManager.show("EachTrainInfo", { payload });
|
||||
};
|
||||
|
||||
const [train, setTrain] = useState<CustomTrainData>(
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
import React from "react";
|
||||
import { View } from "react-native";
|
||||
import { View, StyleSheet } from "react-native";
|
||||
import { WebView } from "react-native-webview";
|
||||
import { BigButton } from "./components/atom/BigButton";
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
export default ({ navigation: { navigate }, route }) => {
|
||||
|
||||
type RouteParams = {
|
||||
info: string;
|
||||
goTo?: string;
|
||||
useShow?: () => void;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
navigation: { navigate: (screen: string) => void };
|
||||
route: { params?: RouteParams };
|
||||
};
|
||||
|
||||
export default ({ navigation: { navigate }, route }: Props) => {
|
||||
if (!route.params) {
|
||||
return null
|
||||
}
|
||||
@@ -17,7 +29,7 @@ export default ({ navigation: { navigate }, route }) => {
|
||||
goBack();
|
||||
};
|
||||
return (
|
||||
<View style={styles}>
|
||||
<View style={styles.container}>
|
||||
<WebView
|
||||
useWebKit
|
||||
source={{ uri: info.replace("http://", "https://") }}
|
||||
@@ -26,4 +38,10 @@ export default ({ navigation: { navigate }, route }) => {
|
||||
</View>
|
||||
);
|
||||
};
|
||||
const styles = { height: "100%", backgroundColor: "#0099CC" };
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
height: "100%" as const,
|
||||
backgroundColor: "#0099CC",
|
||||
},
|
||||
});
|
||||
14
index.ts
Normal file
14
index.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
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";
|
||||
|
||||
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
|
||||
// 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);
|
||||
if (Platform.OS === "android") {
|
||||
registerWidgetTaskHandler(widgetTaskHandler);
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
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";
|
||||
type IconName = string;
|
||||
type IconType = "Ionicons" | "AntDesign";
|
||||
export const initIcon = (
|
||||
name: name,
|
||||
type: type,
|
||||
tabBarBadge: string,
|
||||
isInfo: boolean
|
||||
name: IconName,
|
||||
type: IconType,
|
||||
tabBarBadge?: string,
|
||||
isInfo?: boolean
|
||||
) => {
|
||||
const IconComponent = type == "Ionicons" ? Ionicons : AntDesign;
|
||||
return ({ focused, color, size }) => (
|
||||
|
||||
Reference in New Issue
Block a user