Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

経路検索仮実装とバグ修正 #3714

Merged
merged 3 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion android/app/src/main/assets/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -155,5 +155,6 @@
"longPressNotice": "Press and hold the screen to open the menu.",
"autoAnnounceBackgroundTitle":"Enable background voice announcement",
"loadingLocation": "Getting location information...",
"loadingAPI": "Communicating with server..."
"loadingAPI": "Communicating with server...",
"routeSearchTitle": "Find a route"
}
3 changes: 2 additions & 1 deletion android/app/src/main/assets/translations/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -156,5 +156,6 @@
"longPressNotice": "画面を長押しするとメニューが開けます",
"autoAnnounceBackgroundTitle":"バックグラウンド音声を有効にする",
"loadingLocation": "位置情報を取得中です",
"loadingAPI": "サーバーと通信中です"
"loadingAPI": "サーバーと通信中です",
"routeSearchTitle": "経路を検索"
}
3 changes: 2 additions & 1 deletion ios/TrainLCD/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -155,5 +155,6 @@
"longPressNotice": "Press and hold the screen to open the menu.",
"autoAnnounceBackgroundTitle":"Enable background voice announcement",
"loadingLocation": "Getting location information...",
"loadingAPI": "Communicating with server..."
"loadingAPI": "Communicating with server...",
"routeSearchTitle": "Find a route"
}
3 changes: 2 additions & 1 deletion ios/TrainLCD/translations/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -156,5 +156,6 @@
"longPressNotice": "画面を長押しするとメニューが開けます",
"autoAnnounceBackgroundTitle":"バックグラウンド音声を有効にする",
"loadingLocation": "位置情報を取得中です",
"loadingAPI": "サーバーと通信中です"
"loadingAPI": "サーバーと通信中です",
"routeSearchTitle": "経路を検索"
}
2 changes: 1 addition & 1 deletion proto
Submodule proto updated 1 files
+1 −2 stationapi.proto
107 changes: 107 additions & 0 deletions src/components/RouteList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import React, { useCallback, useMemo } from 'react'
import { FlatList, StyleSheet, TouchableOpacity, View } from 'react-native'
import { RFValue } from 'react-native-responsive-fontsize'
import { Route } from '../../gen/proto/stationapi_pb'
import { useCurrentStation } from '../hooks/useCurrentStation'
import { useThemeStore } from '../hooks/useThemeStore'
import { APP_THEME } from '../models/Theme'
import { isJapanese } from '../translation'
import Typography from './Typography'

const styles = StyleSheet.create({
cell: { padding: 12 },
stationNameText: {
fontSize: RFValue(14),
},
descriptionText: {
fontSize: RFValue(11),
marginTop: 8,
},
separator: { height: 1, width: '100%', backgroundColor: '#aaa' },
})

const Separator = () => <View style={styles.separator} />

const ItemCell = ({
item,
onSelect,
}: {
item: Route
onSelect: (item: Route) => void
}) => {
const currentStation = useCurrentStation()

const lineNameTitle = useMemo(() => {
const trainType = item.stops.find(
(stop) => stop.groupId === Number(currentStation?.groupId)
)?.trainType

if (!isJapanese) {
const lineName = item.stops.find(
(s) => s.groupId === currentStation?.groupId
)?.line?.nameRoman
const typeName = trainType?.nameRoman ?? 'Local'

return `${lineName} ${typeName}`
}
const lineName = item.stops.find(
(s) => s.groupId === currentStation?.groupId
)?.line?.nameShort
const typeName = trainType?.name ?? '普通または各駅停車'

return `${lineName} ${typeName}`
}, [currentStation?.groupId, item.stops])

const bottomText = useMemo(() => {
return `${item.stops[0]?.name}から${
item.stops[item.stops.length - 1]?.name
}まで`
}, [item.stops])

return (
<TouchableOpacity style={styles.cell} onPress={() => onSelect(item)}>
<Typography style={styles.stationNameText}>{lineNameTitle}</Typography>
<Typography style={styles.descriptionText} numberOfLines={1}>
{bottomText}
</Typography>
</TouchableOpacity>
)
}

export const RouteList = ({
data,
onSelect,
}: {
data: Route[]
onSelect: (item: Route) => void
}) => {
const isLEDTheme = useThemeStore((state) => state === APP_THEME.LED)

const renderItem = useCallback(
({ item }: { item: Route; index: number }) => {
return <ItemCell item={item} onSelect={onSelect} />
},
[onSelect]
)
const keyExtractor = useCallback((item: Route) => item.id.toString(), [])

return (
<FlatList
initialNumToRender={data.length}
style={{
width: '100%',
height: '100%',
maxHeight: '50%',
alignSelf: 'center',
borderColor: isLEDTheme ? '#fff' : '#aaa',
borderWidth: 1,
flex: 1,
}}
data={data}
renderItem={renderItem}
keyExtractor={keyExtractor}
ItemSeparatorComponent={Separator}
ListFooterComponent={Separator}
/>
)
}
112 changes: 112 additions & 0 deletions src/components/RouteListModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import React from 'react'
import { Modal, StyleSheet, View } from 'react-native'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import { Route } from '../../gen/proto/stationapi_pb'
import { LED_THEME_BG_COLOR } from '../constants'
import { useThemeStore } from '../hooks/useThemeStore'
import { APP_THEME } from '../models/Theme'
import { translate } from '../translation'
import isTablet from '../utils/isTablet'
import FAB from './FAB'
import Heading from './Heading'
import { RouteList } from './RouteList'

type Props = {
visible: boolean
routes: Route[]
loading: boolean
error: Error
onClose: () => void
onSelect: (route: Route) => void
}

const styles = StyleSheet.create({
modalContainer: {
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0.5)',
width: '100%',
height: '100%',
},
modalView: {
justifyContent: 'center',
alignItems: 'center',
},
buttons: {
flexDirection: 'row',
justifyContent: 'center',
flexWrap: 'wrap',
alignItems: 'center',
alignSelf: 'center',
marginTop: 12,
},
})

const SAFE_AREA_FALLBACK = 32

export const RouteListModal: React.FC<Props> = ({
visible,
routes,
loading,
Dismissed Show dismissed Hide dismissed
onClose,
onSelect,
}: Props) => {
const isLEDTheme = useThemeStore((state) => state === APP_THEME.LED)
const { left: leftSafeArea, right: rightSafeArea } = useSafeAreaInsets()

return (
<Modal
animationType="slide"
transparent
visible={visible}
onRequestClose={onClose}
supportedOrientations={['landscape']}
>
<View style={styles.modalContainer}>
<View
style={[
styles.modalView,
{
backgroundColor: isLEDTheme ? LED_THEME_BG_COLOR : '#fff',
},
isTablet
? {
width: '80%',
maxHeight: '90%',
shadowOpacity: 0.25,
shadowColor: '#000',
borderRadius: 16,
}
: {
width: '100%',
height: '100%',
paddingLeft: leftSafeArea || SAFE_AREA_FALLBACK,
paddingRight: rightSafeArea || SAFE_AREA_FALLBACK,
},
]}
>
<View
style={{
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
}}
>
<View
style={{
marginBottom: 12,
}}
>
<Heading>{translate('routeSearchTitle')}</Heading>
</View>
{routes.length ? (
<RouteList data={routes} onSelect={onSelect} />
) : null}
</View>
</View>
<FAB onPress={onClose} icon="close" />
</View>
</Modal>
)
}
11 changes: 7 additions & 4 deletions src/components/TrainTypeInfoModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export const TrainTypeInfoModal: React.FC<Props> = ({
visible,
trainType,
stations,
loading,
onClose,
onConfirmed,
}: Props) => {
Expand Down Expand Up @@ -136,7 +137,7 @@ export const TrainTypeInfoModal: React.FC<Props> = ({
marginTop: 8,
}}
>
停車駅:
{translate('allStops')}:
</Typography>
<Typography
style={{
Expand All @@ -147,7 +148,8 @@ export const TrainTypeInfoModal: React.FC<Props> = ({
>
{stopStations.length
? stopStations.map((s) => s.name).join('、')
: `${translate('loadingAPI')}...`}
: ''}
{loading ? `${translate('loadingAPI')}...` : ''}
</Typography>
<Typography
style={{
Expand All @@ -156,6 +158,7 @@ export const TrainTypeInfoModal: React.FC<Props> = ({
marginTop: 16,
}}
>
{/* FIXME: translate */}
各線の種別:
</Typography>
</View>
Expand Down Expand Up @@ -222,10 +225,10 @@ export const TrainTypeInfoModal: React.FC<Props> = ({
onPress={() => onConfirmed(trainType)}
disabled={!stopStations.length}
>
確定
確定{/* FIXME: translate */}
</Button>
<Button color={isLEDTheme ? undefined : '#333'} onPress={onClose}>
キャンセル
{translate('cancel')}
</Button>
</View>
</View>
Expand Down
4 changes: 1 addition & 3 deletions src/components/TrainTypeList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,7 @@ const ItemCell = ({
return (
<TouchableOpacity style={styles.cell} onPress={() => onSelect(item)}>
<Typography style={styles.stationNameText}>
{isJapanese
? item.name
: `${currentLine?.nameRoman} ${item.nameRoman}`}
{isJapanese ? item.name : item.nameRoman}
</Typography>
<Typography style={styles.descriptionText}>
{isJapanese ? '種別変更なし' : ''}{' '}
Expand Down
45 changes: 24 additions & 21 deletions src/hooks/useResetMainState.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useEffect } from 'react'
import { useFocusEffect } from '@react-navigation/native'
import { useCallback } from 'react'
import { useSetRecoilState } from 'recoil'
import navigationState from '../store/atoms/navigation'
import stationState from '../store/atoms/station'
Expand All @@ -8,24 +9,26 @@
const setNavigationState = useSetRecoilState(navigationState)
const setStationState = useSetRecoilState(stationState)

useEffect(() => {
return () => {
setNavigationState((prev) => ({
...prev,
headerState: isJapanese ? 'CURRENT' : 'CURRENT_EN',
bottomState: 'LINE',
leftStations: [],
stationForHeader: null,
}))
setStationState((prev) => ({
...prev,
selectedDirection: null,
selectedBound: null,
arrived: true,
approaching: false,
averageDistance: null,
}))
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
useFocusEffect(
useCallback(() => {
return () => {
setNavigationState((prev) => ({
...prev,
headerState: isJapanese ? 'CURRENT' : 'CURRENT_EN',
bottomState: 'LINE',
leftStations: [],
stationForHeader: null,
}))
setStationState((prev) => ({
...prev,
selectedDirection: null,
selectedBound: null,
arrived: true,
approaching: false,
averageDistance: null,
}))
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
Dismissed Show dismissed Hide dismissed
)
}
7 changes: 6 additions & 1 deletion src/hooks/useTransitionHeaderState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type HeaderState = 'CURRENT' | 'NEXT' | 'ARRIVING'
type HeaderLangState = 'JA' | 'KANA' | 'EN' | 'ZH' | 'KO'

const useTransitionHeaderState = (): void => {
const { arrived, approaching } = useRecoilValue(stationState)
const { arrived, approaching, selectedBound } = useRecoilValue(stationState)
const isLEDTheme = useThemeStore((state) => state === APP_THEME.LED)
const [
{
Expand Down Expand Up @@ -93,6 +93,10 @@ const useTransitionHeaderState = (): void => {

useIntervalEffect(
useCallback(() => {
if (!selectedBound) {
return
}

const currentHeaderState = headerStateRef.current.split(
'_'
)[0] as HeaderState
Expand Down Expand Up @@ -235,6 +239,7 @@ const useTransitionHeaderState = (): void => {
isExtraLangAvailable,
isPassing,
nextStation,
selectedBound,
setNavigation,
showNextExpression,
]),
Expand Down
Loading
Loading