Skip to content

Commit

Permalink
refactor: move distance unit to client
Browse files Browse the repository at this point in the history
  • Loading branch information
TurtIeSocks committed Feb 23, 2024
1 parent ca08a69 commit 40a5c3c
Show file tree
Hide file tree
Showing 13 changed files with 116 additions and 67 deletions.
5 changes: 4 additions & 1 deletion packages/locales/lib/human/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -734,5 +734,8 @@
"gender_filters_all": "Gender Applies to All",
"and_caption": "Linked Together",
"or_caption": "Filters Independently",
"filter_help": "Filter Help"
"filter_help": "Filter Help",
"kilometers": "Kilometers",
"miles": "Miles",
"distance_unit": "Distance Unit"
}
1 change: 0 additions & 1 deletion packages/types/lib/server.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ export interface DbCheckClass {
historical: Rarity
questConditions: { [key: string]: string[] }
rarityPercents: RarityPercents
distanceUnit: 'km' | 'mi'
reactMapDb: null | number
filterContext: {
Route: { maxDistance: number; maxDuration: number }
Expand Down
2 changes: 1 addition & 1 deletion server/src/configs/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@
"permImageDir": "images/perms",
"permArrayImages": false,
"clientTimeoutMinutes": 30,
"distanceUnit": "km",
"distanceUnit": "kilometers",
"enablePokemonPopupCoordsSelector": false,
"enableGymPopupCoordsSelector": false,
"enablePokestopPopupCoordsSelector": false,
Expand Down
8 changes: 1 addition & 7 deletions server/src/models/Pokemon.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable no-unused-vars */
/* eslint-disable no-restricted-syntax */
const { Model, raw, ref } = require('objection')
const i18next = require('i18next')
Expand All @@ -24,7 +23,6 @@ const {
} = require('../services/filters/pokemon/constants')
const PkmnFilter = require('../services/filters/pokemon/Backend')

const distanceUnit = config.getSafe('map.misc.distanceUnit')
const searchResultsLimit = config.getSafe('api.searchResultsLimit')
const queryLimits = config.getSafe('api.queryLimits')
const queryDebug = config.getSafe('devOptions.queryDebug')
Expand Down Expand Up @@ -652,11 +650,7 @@ class Pokemon extends Model {
point([poke.lon, poke.lat]),
point([args.lon, args.lat]),
{
units:
distanceUnit.toLowerCase() === 'km' ||
distanceUnit.toLowerCase() === 'kilometers'
? 'kilometers'
: 'miles',
units: 'meters',
},
).toFixed(2),
}))
Expand Down
9 changes: 3 additions & 6 deletions server/src/services/DbCheck.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,21 +107,18 @@ module.exports = class DbCheck {
)
process.exit(0)
}
this.distanceUnit = config.getSafe('map.misc.distanceUnit')
}

/**
* @param {{ lat: number, lon: number }} args
* @param {boolean} isMad
* @returns {ReturnType<typeof raw>}
*/
getDistance(args, isMad) {
static getDistance(args, isMad) {
const radLat = args.lat * (Math.PI / 180)
const radLon = args.lon * (Math.PI / 180)
return raw(
`ROUND(( ${
this.distanceUnit === 'mi' ? '3959' : '6371'
} * acos( cos( ${radLat} ) * cos( radians( ${
`ROUND(( 6371000 * acos( cos( ${radLat} ) * cos( radians( ${
isMad ? 'latitude' : 'lat'
} ) ) * cos( radians( ${
isMad ? 'longitude' : 'lon'
Expand Down Expand Up @@ -456,7 +453,7 @@ module.exports = class DbCheck {
perms,
args,
source,
this.getDistance(args, source.isMad),
DbCheck.getDistance(args, source.isMad),
bbox,
),
),
Expand Down
17 changes: 16 additions & 1 deletion server/src/services/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,22 @@ const mergeMapConfig = (input = {}) => {

/** @type {import('@rm/types').Config['map']} */
const merged = config.util.extendDeep({}, base, input)

if (
merged.misc.distanceUnit !== 'kilometers' ||
merged.misc.distanceUnit !== 'miles'
) {
log.warn(
HELPERS.config,
`Invalid distanceUnit: ${merged.misc.distanceUnit}, only 'kilometers' OR 'miles' are allowed.`,
)
if (merged.misc.distance === 'km') {
merged.misc.distanceUnit = 'kilometers'
} else if (merged.misc.distance === 'mi') {
merged.misc.distanceUnit = 'miles'
} else {
merged.misc.distanceUnit = 'kilometers'
}
}
merged.general.menuOrder = merged?.general?.menuOrder
? merged.general.menuOrder.filter((x) => allowedMenuItems.includes(x))
: []
Expand Down
4 changes: 4 additions & 0 deletions src/components/Config.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ export default function Config({ children }) {
tileServers: Object.fromEntries(
data.tileServers.map((item) => [item.name, item]),
),
distanceUnit: {
kilometers: { name: 'kilometers' },
miles: { name: 'miles' },
},
}

useScannerSessionStorage.setState((prev) => ({
Expand Down
8 changes: 3 additions & 5 deletions src/components/layout/dialogs/search/renderOption.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Divider, Typography } from '@mui/material'
import Utility from '@services/Utility'
import { RawTimeSince } from '@components/popups/common/Timer'
import { getGruntReward } from '@services/functions/getGruntReward'
import { formatDistance } from '@services/functions/formatDistance'

import { OptionImageMemo } from './OptionImage'

Expand Down Expand Up @@ -92,8 +93,7 @@ const InvasionSubtitle = ({
/** @type {import('@mui/material').AutocompleteProps['renderOption']} */
export const renderOption = (props, option) => {
const { searchTab } = useStorage.getState()
const { distanceUnit, questMessage } = useMemory.getState().config.misc

const { questMessage } = useMemory.getState().config.misc
return (
<ListItem
sx={(theme) => ({
Expand Down Expand Up @@ -146,9 +146,7 @@ export const renderOption = (props, option) => {
sx={{ flexGrow: 1, flexShrink: 1 }}
/>
<ListItemText
primary={`${option.distance} ${
distanceUnit === 'mi' ? t('mi') : t('km')
}`}
primary={formatDistance(option.distance)}
secondary={
searchTab === 'quests' ? (
questMessage || t(`ar_quest_${!!option.with_ar}`).toString()
Expand Down
76 changes: 42 additions & 34 deletions src/components/layout/drawer/Settings.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import InsightsIcon from '@mui/icons-material/Insights'
import NotificationsActiveIcon from '@mui/icons-material/NotificationsActive'
import NotificationsOffIcon from '@mui/icons-material/NotificationsOff'
import LogoDevIcon from '@mui/icons-material/LogoDev'
import SquareFootIcon from '@mui/icons-material/SquareFoot'

import { useTranslation } from 'react-i18next'

Expand Down Expand Up @@ -114,55 +115,62 @@ function UniAssetSelect({ asset }) {
}

const ICON_MAP = {
navigation: NavIcon,
navigationControls: StyleIcon,
tileServers: MapIcon,
navigation: <NavIcon />,
navigationControls: <StyleIcon />,
tileServers: <MapIcon />,
distanceUnit: <SquareFootIcon />,
}
const FALLBACK = <DevicesOtherIcon />

function GeneralSetting({ setting }) {
const { t } = useTranslation()
const staticSettings = useMemory((s) => s.settings)
const value = useStorage((s) => s.settings[setting])
return (
<FCSelect
key={setting}
name={setting}
value={staticSettings[setting][value]?.name || ''}
label={t(Utility.camelToSnake(setting))}
onChange={({ target }) => {
useStorage.setState((prev) => ({
settings: {
...prev.settings,
[target.name]: staticSettings[target.name][target.value].name,
},
}))
}}
icon={ICON_MAP[setting] || FALLBACK}
>
{Object.keys(staticSettings[setting]).map((option) => (
<MenuItem key={option} value={option}>
{t(
`${Utility.camelToSnake(setting)}_${option.toLowerCase()}`,
Utility.getProperName(option),
)}
</MenuItem>
))}
</FCSelect>
)
}

export default function Settings() {
const { t } = useTranslation()

const staticSettings = useMemory((s) => s.settings)
const separateDrawerActions = useMemory(
(s) => s.config.general.separateDrawerActions,
)
const holidayEffects = useMemory((s) => s.config.holidayEffects) || []
const staticSettings = useMemory((s) => s.settings)

const settings = useStorage((s) => s.settings)
const darkMode = useStorage((s) => s.darkMode)

return (
<>
<ListSubheader>{t('general')}</ListSubheader>
{Object.keys(staticSettings).map((setting) => {
const Icon = ICON_MAP[setting] || DevicesOtherIcon
return (
<FCSelect
key={setting}
name={setting}
value={staticSettings[setting][settings[setting]]?.name || ''}
label={t(Utility.camelToSnake(setting))}
onChange={({ target }) => {
useStorage.setState((prev) => ({
settings: {
...prev.settings,
[target.name]: staticSettings[target.name][target.value].name,
},
}))
}}
icon={<Icon />}
>
{Object.keys(staticSettings[setting]).map((option) => (
<MenuItem key={option} value={option}>
{t(
`${Utility.camelToSnake(setting)}_${option.toLowerCase()}`,
Utility.getProperName(option),
)}
</MenuItem>
))}
</FCSelect>
)
})}
{Object.keys(staticSettings).map((setting) => (
<GeneralSetting key={setting} setting={setting} />
))}
<ListItem dense>
<ListItemIcon>
<TranslateIcon />
Expand Down
16 changes: 5 additions & 11 deletions src/components/popups/Route.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import Query from '@services/Query'
import formatInterval from '@services/functions/formatInterval'
import { useMemory } from '@hooks/useMemory'
import { useStorage } from '@hooks/useStorage'
import { useFormatDistance } from '@hooks/useFormatDistance'

import Title from './common/Title'
import TimeSince from './common/Timer'
Expand Down Expand Up @@ -131,8 +132,8 @@ function ExpandableWrapper({ disabled = false, children, expandKey, primary }) {
*/
export default function RoutePopup({ end, ...props }) {
const [route, setRoute] = React.useState({ ...props, tags: [] })
const { i18n } = useTranslation()
const { config } = useMemory.getState()
const formatDistance = useFormatDistance()

const [getRoute, { data, called }] = useLazyQuery(Query.routes('getOne'), {
variables: { id: props.id },
Expand Down Expand Up @@ -165,13 +166,6 @@ export default function RoutePopup({ end, ...props }) {
return sum
}, [!!route.waypoints])

const numFormatter = new Intl.NumberFormat(i18n.language, {
unitDisplay: 'short',
unit: 'meter',
style: 'unit',
maximumFractionDigits: 1,
})

const imagesAreEqual =
route.image === (end ? route.end_image : route.start_image)

Expand Down Expand Up @@ -224,7 +218,7 @@ export default function RoutePopup({ end, ...props }) {
)}
<Grid2 xs={12} component={List}>
<ListItemWrapper primary="distance">
{`${numFormatter.format(route.distance_meters || 0)}`}
{formatDistance(route.distance_meters)}
</ListItemWrapper>
<ListItemWrapper primary="duration">
{`${formatInterval((route.duration_seconds || 0) * 1000).str}`}
Expand All @@ -237,13 +231,13 @@ export default function RoutePopup({ end, ...props }) {
<Box display="flex" alignItems="center">
<ArrowDropUp fontSize="small" />
<Typography variant="caption">
{numFormatter.format(elevation.up)}
{formatDistance(elevation.up)}
</Typography>
</Box>
<Box display="flex" alignItems="center">
<ArrowDropDown fontSize="small" />
<Typography variant="caption">
{numFormatter.format(elevation.down)}
{formatDistance(elevation.down)}
</Typography>
</Box>
</ListItem>
Expand Down
14 changes: 14 additions & 0 deletions src/hooks/useFormatDistance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// @ts-check
import { useTranslation } from 'react-i18next'

import { formatDistance } from '@services/functions/formatDistance'

import { useStorage } from './useStorage'

/** @returns {(meters: number) => string} */
export function useFormatDistance() {
const { i18n } = useTranslation()
const unit = useStorage((s) => s.settings.distanceUnit)

return (meters) => formatDistance(meters, unit, i18n.language)
}
1 change: 1 addition & 0 deletions src/hooks/useStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { persist, createJSONStorage } from 'zustand/middleware'
* navigationControls: 'react' | 'leaflet'
* navigation: string,
* tileServers: string
* distanceUnit: 'kilometers' | 'miles'
* },
* searches: Record<string, string>,
* tabs: Record<string, number>,
Expand Down
22 changes: 22 additions & 0 deletions src/services/functions/formatDistance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// @ts-check
import { useStorage } from '@hooks/useStorage'

const METERS_PER_MILE = 1609.344

/** @param {number} meters */
export function formatDistance(
meters,
unit = useStorage.getState().settings.distanceUnit,
locale = localStorage.getItem('i18nextLng') || 'en',
) {
const distance = unit === 'miles' ? meters / METERS_PER_MILE : meters / 1000

const numFormatter = new Intl.NumberFormat(locale, {
unitDisplay: 'short',
unit: unit.replace(/s$/, ''),
style: 'unit',
maximumFractionDigits: 2,
})

return numFormatter.format(distance)
}

0 comments on commit 40a5c3c

Please sign in to comment.