Compare commits

...

5 Commits

Author SHA1 Message Date
c659dcc2d4
Deployment instructions 2026-01-26 13:30:38 +07:00
4bdd25c9c3
Add npm script for building icon versions from SVG source
`pnpm build:icons`
2026-01-26 13:30:02 +07:00
0f3359f725
1.8.0 2026-01-26 13:17:02 +07:00
25081f9cfc
Add app icon, web app manifest 2026-01-26 13:16:24 +07:00
2efb15041e
Update status doc 2026-01-24 21:15:58 +07:00
34 changed files with 298 additions and 11 deletions

View File

@ -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

View File

@ -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

View File

@ -95,7 +95,7 @@ export default class ApplicationComponent extends Component {
}
<template>
{{pageTitle "M/\RCO"}}
{{pageTitle "Marco"}}
<AppHeader @onToggleMenu={{this.toggleSettings}} />

View File

@ -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">

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
public/icons/icon-144.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
public/icons/icon-152.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
public/icons/icon-167.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
public/icons/icon-180.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
public/icons/icon-192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
public/icons/icon-32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 896 B

BIN
public/icons/icon-48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
public/icons/icon-512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View 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
View 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

View 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"
}
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
release/icons/icon-1024.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
release/icons/icon-144.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
release/icons/icon-152.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
release/icons/icon-167.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
release/icons/icon-180.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
release/icons/icon-192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
release/icons/icon-32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 727 B

BIN
release/icons/icon-48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
release/icons/icon-512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View 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
View 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

View File

@ -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>

View 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"
}
]
}