Compare commits
5 Commits
da64ae1572
...
c659dcc2d4
| Author | SHA1 | Date | |
|---|---|---|---|
| c659dcc2d4 | |||
| 4bdd25c9c3 | |||
| 0f3359f725 | |||
| 25081f9cfc | |||
| 2efb15041e |
@ -16,6 +16,7 @@ We are building **Marco**, a decentralized maps application using **Ember.js** (
|
||||
- Detects clicks on visual vector tiles.
|
||||
- Falls back to fetching authoritative data from an **Overpass API** service.
|
||||
- Uses a **heuristic** (distance + type matching) to link visual clicks to API results (handling data desynchronization).
|
||||
- **Logic Upgrade:** Map intelligently detects if _any_ sidebar/pane is open and handles outside clicks to close them instead of initiating new searches.
|
||||
- **Optimization:** Added **10px hit tolerance** for easier tapping on mobile devices.
|
||||
- **Visuals:** Increased bookmark marker size (Radius 9px) and added a subtle drop shadow.
|
||||
- **Feedback:** Implemented a "pulse" animation (via OpenLayers Overlay) at the click location to visualize the search radius (30m/50m).
|
||||
@ -50,7 +51,9 @@ We are building **Marco**, a decentralized maps application using **Ember.js** (
|
||||
- **Optimization:** Implemented **Debounced Reload** (200ms) for bookmark updates to handle rapid change events efficiently.
|
||||
- **Optimization:** Correctly handles deletion/updates by clearing stale data for reloaded geohash sectors.
|
||||
- `osm.js`: Fetches nearby POIs from Overpass API.
|
||||
- **Configurable:** Now supports dynamic API endpoints via `SettingsService`.
|
||||
- **Reliability:** Implemented `fetchWithRetry` to handle HTTP 504/502/503 timeouts and 429 rate limits, in addition to network errors.
|
||||
- `settings.js`: Manages user preferences (currently Overpass API provider) persisted to `localStorage`.
|
||||
- **UI Components:**
|
||||
- `places-sidebar.gjs`: Displays a list of nearby POIs.
|
||||
- **Layout:** Responsive design that transforms into a **Bottom Sheet** (50% height) on mobile screens (`<=768px`) with rounded corners and upward shadow.
|
||||
@ -59,7 +62,9 @@ We are building **Marco**, a decentralized maps application using **Ember.js** (
|
||||
- **Layout:** Polished UI with distinct sections for Actions and Meta info.
|
||||
- `app-header.gjs`: Transparent header with "Menu" button (Settings) and User Avatar (Login).
|
||||
- `settings-pane.gjs`: Sidebar component for app info ("About" section) and settings.
|
||||
- **Features:** Dropdown to select Overpass API provider (bke.ro, overpass-api.de, private.coffee).
|
||||
- **Mobile:** Renders as a 2/3 height bottom sheet on mobile.
|
||||
- **Z-Index:** Configured to overlay the Places sidebar correctly (`z-index: 3200`).
|
||||
- **Geo Utils:**
|
||||
- `app/utils/geo.js`: Haversine distance calculations.
|
||||
- `app/utils/geohash-coverage.js`: Logic to calculate required 4-char geohash prefixes for a given bounding box.
|
||||
@ -82,12 +87,13 @@ We are building **Marco**, a decentralized maps application using **Ember.js** (
|
||||
5. User clicks "Save Bookmark" -> Stores JSON in RemoteStorage.
|
||||
6. RemoteStorage change event -> Debounced reload updates the map reactive-ly.
|
||||
7. **Editing:** User can edit the Title and Description of saved bookmarks via an "Edit" button in the details view.
|
||||
8. **Settings:** User can change the Overpass API provider via the new Settings menu.
|
||||
|
||||
## Files Currently in Focus
|
||||
|
||||
- `app/styles/app.css`: Responsive sidebar styles and mobile optimizations.
|
||||
- `app/components/place-details.gjs`: Place display and editing logic.
|
||||
- `app/services/storage.js`: Data sync and update logic.
|
||||
- `app/templates/application.gjs`: Core layout and "Outside Click" logic.
|
||||
- `app/components/settings-pane.gjs`: Settings UI.
|
||||
- `app/services/settings.js`: Settings persistence.
|
||||
|
||||
## Next Steps & Pending Tasks
|
||||
|
||||
|
||||
@ -42,9 +42,15 @@ Make use of the many generators for code, try `pnpm ember help generate` for mor
|
||||
- `pnpm vite build --mode development` (development)
|
||||
- `pnpm build` (production)
|
||||
|
||||
### App Icon
|
||||
|
||||
- `pnpm build:icons` generates PNGs of all sizes from `public/icons/icon.svg`
|
||||
|
||||
### Deploying
|
||||
|
||||
Specify what it takes to deploy your app.
|
||||
- `git push 5apps master` (needs collaborator permission on 5apps)
|
||||
- Or deploy `release/` to any static file host (ideally routing all 404s to
|
||||
`index.html` for launching with client-side routes to work)
|
||||
|
||||
## Further Reading / Useful Links
|
||||
|
||||
|
||||
@ -95,7 +95,7 @@ export default class ApplicationComponent extends Component {
|
||||
}
|
||||
|
||||
<template>
|
||||
{{pageTitle "M/\RCO"}}
|
||||
{{pageTitle "Marco"}}
|
||||
|
||||
<AppHeader @onToggleMenu={{this.toggleSettings}} />
|
||||
|
||||
|
||||
22
index.html
@ -6,7 +6,27 @@
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link rel="stylesheet" href="/app/styles/app.css">
|
||||
<!-- App identity -->
|
||||
<meta name="application-name" content="Marco">
|
||||
<meta name="apple-mobile-web-app-title" content="Marco">
|
||||
<meta name="theme-color" content="#F6E9A6">
|
||||
|
||||
<!-- PWA Manifest -->
|
||||
<link rel="manifest" href="/manifest.webmanifest">
|
||||
|
||||
<!-- Icons -->
|
||||
<link rel="icon" href="/icons/icon.svg" type="image/svg+xml">
|
||||
|
||||
<!-- iOS -->
|
||||
<link rel="apple-touch-icon" href="/icons/icon-180.png">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||
|
||||
<!-- Windows -->
|
||||
<meta name="msapplication-TileColor" content="#F6E9A6">
|
||||
<meta name="msapplication-TileImage" content="/icons/icon-144.png">
|
||||
|
||||
<link rel="stylesheet" href="/app/styles/app.css">
|
||||
</head>
|
||||
<body>
|
||||
<script type="module">
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "marco",
|
||||
"version": "1.7.0",
|
||||
"version": "1.8.0",
|
||||
"private": true,
|
||||
"description": "Small description for marco goes here",
|
||||
"repository": "",
|
||||
@ -18,6 +18,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"build": "vite build --outDir release/",
|
||||
"build:icons": "for size in 32 48 144 180 192 512; do if [ \"$size\" -le 64 ]; then magick public/icons/icon.svg -define svg:remove-groups=map-grid -resize ${size}x${size} public/icons/icon-${size}.png; else rsvg-convert -w $size -h $size public/icons/icon.svg -o public/icons/icon-${size}.png; fi; done && rsvg-convert -w 512 -h 512 public/icons/icon.svg -o public/icons/icon-maskable.png",
|
||||
"format": "prettier . --cache --write",
|
||||
"lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\" --prefixColors auto",
|
||||
"lint:css": "stylelint \"**/*.css\"",
|
||||
|
||||
BIN
public/icons/icon-1024.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
public/icons/icon-144.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/icons/icon-152.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
public/icons/icon-167.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
public/icons/icon-180.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
public/icons/icon-192.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
public/icons/icon-32.png
Normal file
|
After Width: | Height: | Size: 896 B |
BIN
public/icons/icon-48.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
public/icons/icon-512.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
public/icons/icon-maskable.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
45
public/icons/icon-rounded.svg
Normal file
@ -0,0 +1,45 @@
|
||||
<svg
|
||||
width="1024"
|
||||
height="1024"
|
||||
viewBox="0 0 1024 1024"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<!-- Background -->
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="1024"
|
||||
height="1024"
|
||||
rx="220"
|
||||
fill="#F6E9A6"
|
||||
/>
|
||||
|
||||
<!-- Subtle map grid (kept well outside safe zone) -->
|
||||
<g stroke="#E6D88A" stroke-width="10" opacity="0.6">
|
||||
<line x1="256" y1="0" x2="256" y2="1024" />
|
||||
<line x1="512" y1="0" x2="512" y2="1024" />
|
||||
<line x1="768" y1="0" x2="768" y2="1024" />
|
||||
|
||||
<line x1="0" y1="256" x2="1024" y2="256" />
|
||||
<line x1="0" y1="512" x2="1024" y2="512" />
|
||||
<line x1="0" y1="768" x2="1024" y2="768" />
|
||||
</g>
|
||||
|
||||
<!-- Location pin (exact app shape, larger, centered, safe-zone compliant) -->
|
||||
<!-- Safe zone target: ~680px diameter -->
|
||||
<g
|
||||
transform="
|
||||
translate(512 512)
|
||||
scale(22)
|
||||
translate(-12 -12)
|
||||
"
|
||||
fill="#ea4335"
|
||||
stroke="#b31412"
|
||||
stroke-width="1"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" />
|
||||
<circle cx="12" cy="10" r="3" fill="#b31412" stroke="none" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
44
public/icons/icon.svg
Normal file
@ -0,0 +1,44 @@
|
||||
<svg
|
||||
width="1024"
|
||||
height="1024"
|
||||
viewBox="0 0 1024 1024"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<!-- Background -->
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="1024"
|
||||
height="1024"
|
||||
fill="#F6E9A6"
|
||||
/>
|
||||
|
||||
<!-- Subtle map grid (kept well outside safe zone) -->
|
||||
<g stroke="#E6D88A" stroke-width="10" opacity="0.6">
|
||||
<line x1="256" y1="0" x2="256" y2="1024" />
|
||||
<line x1="512" y1="0" x2="512" y2="1024" />
|
||||
<line x1="768" y1="0" x2="768" y2="1024" />
|
||||
|
||||
<line x1="0" y1="256" x2="1024" y2="256" />
|
||||
<line x1="0" y1="512" x2="1024" y2="512" />
|
||||
<line x1="0" y1="768" x2="1024" y2="768" />
|
||||
</g>
|
||||
|
||||
<!-- Location pin (exact app shape, larger, centered, safe-zone compliant) -->
|
||||
<!-- Safe zone target: ~680px diameter -->
|
||||
<g
|
||||
transform="
|
||||
translate(512 512)
|
||||
scale(22)
|
||||
translate(-12 -12)
|
||||
"
|
||||
fill="#ea4335"
|
||||
stroke="#b31412"
|
||||
stroke-width="1"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" />
|
||||
<circle cx="12" cy="10" r="3" fill="#b31412" stroke="none" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
28
public/manifest.webmanifest
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "Marco",
|
||||
"short_name": "Marco",
|
||||
"description": "Marco (as in Marco Polo) is an unhosted maps application that respects your privacy and choices",
|
||||
"start_url": "/",
|
||||
"scope": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#F6E9A6",
|
||||
"theme_color": "#F6E9A6",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/icons/icon-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/icons/icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/icons/icon-maskable.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
release/icons/icon-1024.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
release/icons/icon-144.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
release/icons/icon-152.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
release/icons/icon-167.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
release/icons/icon-180.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
release/icons/icon-192.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
release/icons/icon-32.png
Normal file
|
After Width: | Height: | Size: 727 B |
BIN
release/icons/icon-48.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
release/icons/icon-512.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
release/icons/icon-maskable.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
45
release/icons/icon-rounded.svg
Normal file
@ -0,0 +1,45 @@
|
||||
<svg
|
||||
width="1024"
|
||||
height="1024"
|
||||
viewBox="0 0 1024 1024"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<!-- Background -->
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="1024"
|
||||
height="1024"
|
||||
rx="220"
|
||||
fill="#F6E9A6"
|
||||
/>
|
||||
|
||||
<!-- Subtle map grid (kept well outside safe zone) -->
|
||||
<g stroke="#E6D88A" stroke-width="10" opacity="0.6">
|
||||
<line x1="256" y1="0" x2="256" y2="1024" />
|
||||
<line x1="512" y1="0" x2="512" y2="1024" />
|
||||
<line x1="768" y1="0" x2="768" y2="1024" />
|
||||
|
||||
<line x1="0" y1="256" x2="1024" y2="256" />
|
||||
<line x1="0" y1="512" x2="1024" y2="512" />
|
||||
<line x1="0" y1="768" x2="1024" y2="768" />
|
||||
</g>
|
||||
|
||||
<!-- Location pin (exact app shape, larger, centered, safe-zone compliant) -->
|
||||
<!-- Safe zone target: ~680px diameter -->
|
||||
<g
|
||||
transform="
|
||||
translate(512 512)
|
||||
scale(22)
|
||||
translate(-12 -12)
|
||||
"
|
||||
fill="#ea4335"
|
||||
stroke="#b31412"
|
||||
stroke-width="1"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" />
|
||||
<circle cx="12" cy="10" r="3" fill="#b31412" stroke="none" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
44
release/icons/icon.svg
Normal file
@ -0,0 +1,44 @@
|
||||
<svg
|
||||
width="1024"
|
||||
height="1024"
|
||||
viewBox="0 0 1024 1024"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<!-- Background -->
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="1024"
|
||||
height="1024"
|
||||
fill="#F6E9A6"
|
||||
/>
|
||||
|
||||
<!-- Subtle map grid (kept well outside safe zone) -->
|
||||
<g stroke="#E6D88A" stroke-width="10" opacity="0.6">
|
||||
<line x1="256" y1="0" x2="256" y2="1024" />
|
||||
<line x1="512" y1="0" x2="512" y2="1024" />
|
||||
<line x1="768" y1="0" x2="768" y2="1024" />
|
||||
|
||||
<line x1="0" y1="256" x2="1024" y2="256" />
|
||||
<line x1="0" y1="512" x2="1024" y2="512" />
|
||||
<line x1="0" y1="768" x2="1024" y2="768" />
|
||||
</g>
|
||||
|
||||
<!-- Location pin (exact app shape, larger, centered, safe-zone compliant) -->
|
||||
<!-- Safe zone target: ~680px diameter -->
|
||||
<g
|
||||
transform="
|
||||
translate(512 512)
|
||||
scale(22)
|
||||
translate(-12 -12)
|
||||
"
|
||||
fill="#ea4335"
|
||||
stroke="#b31412"
|
||||
stroke-width="1"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" />
|
||||
<circle cx="12" cy="10" r="3" fill="#b31412" stroke="none" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@ -5,8 +5,28 @@
|
||||
<title>Marco</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<script type="module" crossorigin src="/assets/main-Dpm1fpXl.js"></script>
|
||||
|
||||
<!-- App identity -->
|
||||
<meta name="application-name" content="Marco">
|
||||
<meta name="apple-mobile-web-app-title" content="Marco">
|
||||
<meta name="theme-color" content="#F6E9A6">
|
||||
|
||||
<!-- PWA Manifest -->
|
||||
<link rel="manifest" href="/manifest.webmanifest">
|
||||
|
||||
<!-- Icons -->
|
||||
<link rel="icon" href="/icons/icon.svg" type="image/svg+xml">
|
||||
|
||||
<!-- iOS -->
|
||||
<link rel="apple-touch-icon" href="/icons/icon-180.png">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||
|
||||
<!-- Windows -->
|
||||
<meta name="msapplication-TileColor" content="#F6E9A6">
|
||||
<meta name="msapplication-TileImage" content="/icons/icon-144.png">
|
||||
|
||||
<script type="module" crossorigin src="/assets/main-CYQJLBu1.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/main-B9HZHSjP.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
28
release/manifest.webmanifest
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "Marco",
|
||||
"short_name": "Marco",
|
||||
"description": "Marco (as in Marco Polo) is an unhosted maps application that respects your privacy and choices",
|
||||
"start_url": "/",
|
||||
"scope": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#F6E9A6",
|
||||
"theme_color": "#F6E9A6",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/icons/icon-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/icons/icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/icons/icon-maskable.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
]
|
||||
}
|
||||