Skip to content

Commit

Permalink
feat: add support for custom offline maps (#318)
Browse files Browse the repository at this point in the history
  • Loading branch information
achou11 authored May 14, 2024
1 parent 09b8d11 commit f8219a2
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 9 deletions.
4 changes: 3 additions & 1 deletion scripts/build-backend.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ const KEEP_THESE = [
// Static folders referenced by @mapeo/core code
'node_modules/@mapeo/core/drizzle',
// zip file that is the default config
'node_modules/@mapeo/default-config/dist/mapeo-default-config.mapeoconfig'
'node_modules/@mapeo/default-config/dist/mapeo-default-config.mapeoconfig',
// Offline fallback map
'node_modules/mapeo-offline-map',
];

for (const name of KEEP_THESE) {
Expand Down
5 changes: 5 additions & 0 deletions src/backend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ const MIGRATIONS_FOLDER_PATH = new URL(
'./node_modules/@mapeo/core/drizzle',
import.meta.url,
).pathname
const FALLBACK_MAP_PATH = new URL(
'./node_modules/mapeo-offline-map',
import.meta.url,
).pathname

const DEFAULT_CONFIG_PATH = new URL(
'./node_modules/@mapeo/default-config/dist/mapeo-default-config.mapeoconfig',
Expand Down Expand Up @@ -41,6 +45,7 @@ try {
migrationsFolderPath: MIGRATIONS_FOLDER_PATH,
sharedStoragePath: values.sharedStoragePath,
defaultConfigPath: DEFAULT_CONFIG_PATH,
fallbackMapPath: FALLBACK_MAP_PATH,
}).catch((err) => {
console.error('Server startup error:', err)
})
Expand Down
13 changes: 12 additions & 1 deletion src/backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion src/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"@mapeo/core": "9.0.0-alpha.9",
"@mapeo/default-config": "^4.0.0-alpha.2",
"@mapeo/ipc": "0.5.0",
"debug": "^4.3.4"
"debug": "^4.3.4",
"mapeo-offline-map": "^2.0.0"
},
"devDependencies": {
"@digidem/types": "~2.1.0",
Expand Down
31 changes: 30 additions & 1 deletion src/backend/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ import { createRequire } from 'module'
const require = createRequire(import.meta.url)
/** @type {import('../types/rn-bridge.js')} */
const rnBridge = require('rn-bridge')
import { MapeoManager, FastifyController } from '@mapeo/core'
import {
MapeoManager,
FastifyController,
MapeoMapsFastifyPlugin,
MapeoStaticMapsFastifyPlugin,
MapeoOfflineFallbackMapFastifyPlugin,
} from '@mapeo/core'
import { createMapeoServer } from '@mapeo/ipc'
import Fastify from 'fastify'

Expand All @@ -16,6 +22,10 @@ import { ServerStatus } from './status.js'
const DB_DIR_NAME = 'sqlite-dbs'
const CORE_STORAGE_DIR_NAME = 'core-storage'

const MAPBOX_ACCESS_TOKEN =
'pk.eyJ1IjoiZGlnaWRlbSIsImEiOiJjbHRyaGh3cm0wN3l4Mmpsam95NDI3c2xiIn0.daq2iZFZXQ08BD0VZWAGUw'
const DEFAULT_ONLINE_MAP_STYLE_URL = `https://api.mapbox.com/styles/v1/mapbox/outdoors-v11?access_token=${MAPBOX_ACCESS_TOKEN}`

const log = debug('mapeo:app')

// Set these up as soon as possible (e.g. before the init function)
Expand Down Expand Up @@ -48,6 +58,7 @@ process.on('exit', (code) => {
* @param {string} options.migrationsFolderPath
* @param {string} options.sharedStoragePath Path to app-specific external file storage folder
* @param {string} options.defaultConfigPath
* @param {string} options.fallbackMapPath Path to app-specific external file storage folder
*
*/
export async function init({
Expand All @@ -56,20 +67,38 @@ export async function init({
migrationsFolderPath,
sharedStoragePath,
defaultConfigPath,
fallbackMapPath,
}) {
log('Starting app...')
log(`Device version is ${version}`)

const privateStorageDir = rnBridge.app.datadir()
const dbDir = join(privateStorageDir, DB_DIR_NAME)
const indexDir = join(privateStorageDir, CORE_STORAGE_DIR_NAME)
const staticStylesDir = join(sharedStoragePath, 'styles')

mkdirSync(dbDir, { recursive: true })
mkdirSync(indexDir, { recursive: true })
mkdirSync(staticStylesDir, { recursive: true })

const fastify = Fastify()
const fastifyController = new FastifyController({ fastify })

// Register maps plugins
fastify.register(MapeoStaticMapsFastifyPlugin, {
prefix: 'static',
staticRootDir: staticStylesDir,
})
fastify.register(MapeoOfflineFallbackMapFastifyPlugin, {
prefix: 'fallback',
styleJsonPath: join(fallbackMapPath, 'style.json'),
sourcesDir: join(fallbackMapPath, 'dist'),
})
fastify.register(MapeoMapsFastifyPlugin, {
prefix: 'maps',
defaultOnlineStyleUrl: DEFAULT_ONLINE_MAP_STYLE_URL,
})

const manager = new MapeoManager({
rootKey,
dbFolder: dbDir,
Expand Down
16 changes: 16 additions & 0 deletions src/frontend/hooks/server/mapStyleUrl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {useQuery} from '@tanstack/react-query';

import {useApi} from '../../contexts/ApiContext';

export const MAP_STYLE_URL_KEY = 'map_style_url';

export function useMapStyleUrl() {
const api = useApi();

return useQuery({
queryKey: [MAP_STYLE_URL_KEY],
queryFn: () => {
return api.getMapStyleJsonUrl();
},
});
}
8 changes: 5 additions & 3 deletions src/frontend/screens/MapScreen/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import Mapbox from '@rnmapbox/maps';

import config from '../../../config.json';
import {IconButton} from '../../sharedComponents/IconButton';
import {
Expand All @@ -21,6 +22,7 @@ import {GPSPermissionsModal} from './GPSPermissions/GPSPermissionsModal';
import {TrackPathLayer} from './track/TrackPathLayer';
import {UserLocation} from './UserLocation';
import {useSharedLocationContext} from '../../contexts/SharedLocationContext';
import {useMapStyleUrl} from '../../hooks/server/mapStyleUrl';

// This is the default zoom used when the map first loads, and also the zoom
// that the map will zoom to if the user clicks the "Locate" button and the
Expand All @@ -30,8 +32,6 @@ const DEFAULT_ZOOM = 12;
Mapbox.setAccessToken(config.mapboxAccessToken);
const MIN_DISPLACEMENT = 3;

export const MAP_STYLE = Mapbox.StyleURL.Outdoors;

export const MapScreen = () => {
const [zoom, setZoom] = React.useState(DEFAULT_ZOOM);
const [isFinishedLoading, setIsFinishedLoading] = React.useState(false);
Expand All @@ -45,6 +45,8 @@ export const MapScreen = () => {
const locationServicesEnabled =
!!locationProviderStatus?.locationServicesEnabled;

const styleUrlQuery = useMapStyleUrl();

const handleAddPress = () => {
newDraft();
navigate('PresetChooser');
Expand Down Expand Up @@ -75,7 +77,7 @@ export const MapScreen = () => {
attributionPosition={{right: 8, bottom: 8}}
compassEnabled={false}
scaleBarEnabled={false}
styleURL={MAP_STYLE}
styleURL={styleUrlQuery.data}
onDidFinishLoadingStyle={handleDidFinishLoadingStyle}
onMoveShouldSetResponder={() => {
if (following) setFollowing(false);
Expand Down
6 changes: 4 additions & 2 deletions src/frontend/screens/Observation/InsetMapView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {View, Text, StyleSheet, Dimensions, Image} from 'react-native';
import {BLACK, WHITE} from '../../lib/styles';
import {usePersistedSettings} from '../../hooks/persistedState/usePersistedSettings';
import {FormattedCoords} from '../../sharedComponents/FormattedData';
import {MAP_STYLE} from '../MapScreen';
import {useMapStyleUrl} from '../../hooks/server/mapStyleUrl';

const MAP_HEIGHT = 175;
const ICON_OFFSET = {x: 22, y: 21};
Expand All @@ -16,6 +16,8 @@ type MapProps = {

export const InsetMapView = React.memo<MapProps>(({lon, lat}: MapProps) => {
const format = usePersistedSettings(store => store.coordinateFormat);
const styleUrlQuery = useMapStyleUrl();

return (
<View>
<Image
Expand All @@ -37,7 +39,7 @@ export const InsetMapView = React.memo<MapProps>(({lon, lat}: MapProps) => {
rotateEnabled={false}
compassEnabled={false}
scaleBarEnabled={false}
styleURL={MAP_STYLE}>
styleURL={styleUrlQuery.data}>
<MapboxGL.Camera
centerCoordinate={[lon, lat]}
zoomLevel={12}
Expand Down

0 comments on commit f8219a2

Please sign in to comment.