react-use#useOrientation JavaScript Examples
The following examples show how to use
react-use#useOrientation.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: App.js From FSE-Planner with MIT License | 4 votes |
function App() {
const [filtersBar, setFiltersBar] = React.useState(false)
const [filters, setFilters] = React.useState({
type: 'Trip-Only',
cargo: ['passengers'],
fromIcao: null,
toIcao: null,
minPax: '',
minKg: '',
maxPax: '',
maxKg: '',
minDist: '',
maxDist: '',
minJobPay: '',
minLegPay: '',
percentPay: '',
direction: ''
});
const [table, setTable] = React.useState(false);
const [updatePopup, setUpdatePopup] = React.useState(false);
const [settingsPopup, setSettingsPopup] = React.useState(false);
const [creditsPopup, setCreditsPopup] = React.useState(false);
const [jobs, setJobs] = React.useState(() => {
return transformJobs(storage.get('jobs', {}, true));
});
const [planes, setPlanes] = React.useState(() => {
return transformPlanes(storage.get('planes', {}));
});
const [flight, setFlight] = React.useState(() => {
return transformJobs(storage.get('flight', {}));
});
const [settings, setSettings] = React.useState(() => {
const obj = {};
// Cannot use _defaultsDeep, because it messes up with array
[defaultSettings, storage.get('settings', {})].forEach(item => {
_mergeWith(obj, item, (objectValue, sourceValue) => {
return _isArray(sourceValue) ? sourceValue : undefined;
});
});
return obj;
});
const [search, setSearch] = React.useState(null);
const [searchDest, setSearchDest] = React.useState(null);
const [searchInput, setSearchInput] = React.useState('');
const [searchHistory, setSearchHistory] = React.useState(storage.get('searchHistory', []));
const [icaodata, setIcaodata] = React.useState(icaodataSrc);
const [isTourOpen, setIsTourOpen] = React.useState(storage.get('tutorial') === null);
const [routeFinder, setRouteFinder] = React.useState(false);
const [route, setRoute] = React.useState(null);
const [searchOptions, setSearchOptions] = React.useState([]);
const mapRef = React.useRef();
const searchDestRef = React.useRef(null);
const orientation = useOrientation();
const windowSize = useWindowSize();
const options = React.useMemo(() => ({
jobs: jobs,
planes: planes,
flight: flight,
settings: settings,
icaodata: icaodata,
...filters
}), [jobs, planes, flight, settings, icaodata, filters]);
React.useEffect(() => {
const obj = _clone(icaodataSrc);
icaos.forEach((icao) => {
const nb = wrap(obj[icao].lon, settings.display.map.center);
obj[icao].lon += nb;
});
setIcaodata(obj);
}, [settings.display.map.center]);
React.useEffect(() => {
// Display changelog if new version
const last = storage.get('tutorial');
if (last && last !== process.env.REACT_APP_VERSION) {
setCreditsPopup(true);
storage.set('tutorial', process.env.REACT_APP_VERSION);
}
// Set search if query string in URL
const urlParams = new URLSearchParams(window.location.search);
const icao = urlParams.get('icao');
if (icao) {
setSearch(icao);
}
// Register error logging
window.onerror = (message, file, line, column, errorObject) => {
// We do not use ErrorBoundary component for logging, because it does
// not detect errors in event handlers, and we need to log these errors too
log.error(message, {
file: file,
line: line,
column: column,
obj: errorObject,
});
}
}, []);
// Create goTo function, to allow panning to given ICAO
// Cannot just use setSearch, because need to pan even if the ICAO was already in search var
const goToRef = React.useRef(null);
const goTo = React.useCallback((icao, from = null) => {
if (icao) {
if (from) {
searchDestRef.current = {...icaodataSrc[icao], from: from};
setSearchDest(icao);
setSearch(from);
setSearchOptions([searchDestRef.current]);
setSearchHistory(prevList => {
const list = [...(new Set([icao, from, ...prevList]))].slice(0, 5);
storage.set('searchHistory', list);
return list;
});
window.history.replaceState({icao:from}, '', '?icao='+from);
}
else {
setSearch(prevIcao => prevIcao === icao ? null : icao);
setSearchDest(null);
setSearchOptions([icaodataSrc[icao]]);
goToRef.current = icao;
setSearchHistory(prevList => {
const list = [...(new Set([icao, ...prevList]))].slice(0, 5);
storage.set('searchHistory', list);
return list;
});
window.history.replaceState({icao:icao}, '', '?icao='+icao);
}
}
else {
setSearch(null);
window.history.replaceState(null, '', '?');
}
}, []);
React.useEffect(() => {
if (goToRef.current) {
const icao = goToRef.current;
goToRef.current = null;
setSearch(icao);
}
}, [search]);
// Invalidate map size when routing toogled
React.useEffect(() => {
if (!mapRef.current) { return; }
if (window.scrollY !== 0) {
window.scrollTo(0, 0);
}
mapRef.current.invalidateSize({pan:false});
}, [routeFinder, filters, orientation, table, windowSize.width, windowSize.height]);
// Actions
const actions = React.useRef(null);
const setActions = () => {
actions.current = {
goTo: goTo,
fromIcao: (icao) => setFilters(prev => {
const f = {...prev};
f.fromIcao = icao;
return f;
}),
isFromIcao: (icao) => filters.fromIcao === icao,
isToIcao: (icao) => filters.toIcao === icao,
toIcao: (icao) => setFilters(prev => {
const f = {...prev};
f.toIcao = icao;
return f;
}),
contextMenu: (actions.current && actions.current.contextMenu) ? actions.current.contextMenu : undefined,
measureDistance: () => null,
openTable: () => { setRouteFinder(false); setTable(true); },
getCustomLayers: (icao) => [],
addToCustomLayer: () => null,
removeFromCustomLayer: () => null
};
}
if (!actions.current) { setActions(); }
React.useEffect(setActions, [goTo, filters.fromIcao, filters.toIcao]);
React.useEffect(() => {
const inputs = searchInput.split(/\s*[><]+\s*/g);
// Should not be more than 2 ICAOS long
if (inputs.length > 2) { return setSearchOptions([]); }
// If typing a second ICAO, the first one should be valid
if (inputs.length > 1 && !icaodataSrc.hasOwnProperty(inputs[0])) { return setSearchOptions([]); }
const input = inputs[inputs.length-1];
let filtered = [];
// If input is empty and search history is not, display search history
if (!input && searchHistory.length > 0) {
filtered = searchHistory.map(icao => icaodataSrc[icao]);
}
else {
// Search for ICAO
filtered = filter(icaodataSrcArr, { inputValue: input, getOptionLabel: (a) => a.icao });
// If not enough results, search for city name
if (filtered.length < 5) {
const add = filter(icaodataSrcArr, { inputValue: input, getOptionLabel: (a) => a.name });
filtered = filtered.concat(add.slice(0, 5-filtered.length));
}
}
if (inputs.length === 2) {
filtered = filtered.map(elm => { return {...elm, from: inputs[0]} });
}
if (search) {
if (searchDest) {
const exist = filtered.reduce((acc, elm) => acc || (elm.icao === searchDest && elm.from === search), false);
if (!exist) { filtered.push({...icaodataSrc[searchDest], from: search}) }
}
else {
const exist = filtered.reduce((acc, elm) => acc || (elm.icao === search && !elm.from), false);
if (!exist) { filtered.push(icaodataSrc[search]) }
}
}
setSearchOptions(filtered);
}, [searchInput, searchHistory, search, searchDest]);
return (
<Box
sx={{
display: "flex",
flexFlow: "column",
height: "100%"
}}
>
<AppBar position="static">
<Toolbar>
<Box
sx={{
display: 'flex',
alignItems: 'flex-end',
flexWrap: 'wrap'
}}
>
<Typography variant="h6" sx={{ lineHeight: 1, py: 0.4 }}>
FSE Planner
</Typography>
<Tooltip title="Changelog & credits">
<Button
sx={{
marginLeft: 1,
paddingLeft: '2px',
paddingRight: '2px',
px: 0.5,
py: 0,
fontWeight: 'normal',
color: '#fff',
letterSpacing: 'normal',
textTransform: 'none',
minWidth: 'auto'
}}
onClick={() => setCreditsPopup(true)}
data-tour="Step10"
size="small"
>
v{process.env.REACT_APP_VERSION}
</Button>
</Tooltip>
</Box>
<Box
sx={{
display: "flex",
flexWrap: "wrap",
ml: 1,
flexGrow: 2
}}
>
<Button
sx={styles.menuBtn}
onClick={() => setUpdatePopup(true)}
data-tour="Step2"
startIcon={<UpdateIcon />}
>
Load data
</Button>
<Button
sx={styles.menuBtn}
onClick={() => {
if (!table) {
setRouteFinder(false);
}
setTable(!table);
}}
startIcon={table ? <MapIcon /> : <TableViewIcon />}
>
{table ? "Map" : "Table" }
</Button>
<Button
sx={{
...styles.menuBtn,
...(filtersBar && {
backgroundColor: 'rgba(255, 255, 255, 0.3)',
'&:hover': {
backgroundColor: 'rgba(255, 255, 255, 0.3)',
}
})
}}
onClick={() => setFiltersBar(!filtersBar)}
data-tour="Step7"
startIcon={<FilterAltIcon />}
>
Filters
</Button>
<Button
sx={{
...styles.menuBtn,
...(routeFinder && {
backgroundColor: 'rgba(255, 255, 255, 0.3)',
'&:hover': {
backgroundColor: 'rgba(255, 255, 255, 0.3)',
}
})
}}
onClick={() => {
if (table) {
setTable(false);
setRouteFinder(true);
}
else {
setRouteFinder(!routeFinder)
}
}}
data-tour="Step9"
startIcon={<DirectionsIcon />}
>
Route finder
</Button>
<Button
sx={styles.menuBtn}
onClick={() => setSettingsPopup(true)}
startIcon={<TuneIcon />}
>
Settings
</Button>
</Box>
<Box
sx={{
display: 'flex',
ml: 2
}}
>
<Autocomplete
options={searchOptions}
getOptionLabel={(a) => a.icao ? (a.from ? a.from + ' > ' + a.icao : a.icao) : ''}
renderOption={(props, a) =>
<li {...props}>
<Box
component="span"
sx={{
display: 'flex',
alignItems: 'center',
overflow: 'hidden'
}}
>
{a.from &&
<React.Fragment>
<Box
component="b"
sx={{
minWidth: '40px',
textAlign: 'center'
}}
>
{a.from}
</Box>
<Box
component="span"
sx={{ px: 1}}
>
>
</Box>
</React.Fragment>
}
<Box
component="b"
sx={{
minWidth: '40px',
textAlign: 'center'
}}
>
{a.icao}
</Box>
<Box
component="span"
sx={{
display: 'flex',
flexDirection: 'column',
marginLeft: 2,
overflow: 'hidden',
}}
>
<Box
component="span"
sx={{
textOverflow: 'ellipsis',
overflow: 'hidden',
whiteSpace: 'nowrap'
}}
>
{a.name}
</Box>
<Typography
variant="caption"
sx={{
textOverflow: 'ellipsis',
overflow: 'hidden',
whiteSpace: 'nowrap',
color: '#aaa'
}}
>
{a.city}, {a.state ? a.state+', ' : ''}{a.country}
</Typography>
</Box>
</Box>
</li>
}
filterOptions={x => x}
renderInput={(params) =>
<InputBase
placeholder="Search..."
sx={styles.inputSearch}
ref={params.InputProps.ref}
inputProps={params.inputProps}
endAdornment={params.inputProps.value ?
<IconButton
size="small"
onClick={() => {
setSearchDest(null);
setSearch(null);
setSearchInput('');
window.history.replaceState(null, '', '?');
}}
>
<CloseIcon />
</IconButton>
:
null
}
/>
}
isOptionEqualToValue={(option, value) => option.icao === value.icao && option.from === value.from}
PopperComponent={PopperMy}
onChange={(evt, value) => value && goTo(value.icao, value.from)}
value={search ? (searchDest ? searchDestRef.current : icaodataSrc[search]) : null}
inputValue={searchInput}
onInputChange={(evt, value) => setSearchInput(value)}
autoHighlight={true}
selectOnFocus={false}
/>
</Box>
</Toolbar>
{filtersBar &&
<Filters
filters={filters}
setFilters={setFilters}
icaodata={icaodata}
actions={actions}
setSettingsPopup={setSettingsPopup}
/>
}
</AppBar>
<Box
sx={{
display: 'flex',
flexWrap: 'nowrap',
flexGrow: '1',
overflow: 'hidden'
}}
>
<Routing
options={options}
setRoute={setRoute}
hidden={!routeFinder}
mapRef={mapRef}
close={() => setRouteFinder(false)}
actions={actions}
/>
<FSEMap
options={options}
search={search}
searchDest={searchDest}
icaos={icaos}
route={route}
mapRef={mapRef}
actions={actions}
hidden={table}
/>
<Table
options={options}
hidden={!table}
actions={actions}
search={search}
searchDest={searchDest}
/>
</Box>
<UpdatePopup
open={updatePopup}
setUpdatePopup={setUpdatePopup}
setJobs={(jobs) => setJobs(transformJobs(jobs))}
setPlanes={(planes) => setPlanes(transformPlanes(planes))}
setFlight={(flight) => setFlight(transformJobs(flight))}
icaodata={icaodata}
icaos={icaos}
settings={settings}
/>
<SettingsPopup
open={settingsPopup}
handleClose={() => setSettingsPopup(false)}
settings={settings}
setSettings={setSettings}
defaultSettings={defaultSettings}
/>
<CreditsPopup
open={creditsPopup}
handleClose={() => setCreditsPopup(false)}
openTutorial={() => setIsTourOpen(true)}
/>
<Tour
isTourOpen={isTourOpen}
setIsTourOpen={setIsTourOpen}
updatePopup={updatePopup}
setUpdatePopup={setUpdatePopup}
/>
</Box>
);
}