7 Commits

Author SHA1 Message Date
9ce29807fd 1.8.1 2026-01-26 13:31:13 +07:00
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
da64ae1572 1.7.0 2026-01-24 21:07:40 +07:00
36 changed files with 301 additions and 14 deletions

View File

@@ -16,6 +16,7 @@ We are building **Marco**, a decentralized maps application using **Ember.js** (
- Detects clicks on visual vector tiles. - Detects clicks on visual vector tiles.
- Falls back to fetching authoritative data from an **Overpass API** service. - 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). - 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. - **Optimization:** Added **10px hit tolerance** for easier tapping on mobile devices.
- **Visuals:** Increased bookmark marker size (Radius 9px) and added a subtle drop shadow. - **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). - **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:** 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. - **Optimization:** Correctly handles deletion/updates by clearing stale data for reloaded geohash sectors.
- `osm.js`: Fetches nearby POIs from Overpass API. - `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. - **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:** - **UI Components:**
- `places-sidebar.gjs`: Displays a list of nearby POIs. - `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. - **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. - **Layout:** Polished UI with distinct sections for Actions and Meta info.
- `app-header.gjs`: Transparent header with "Menu" button (Settings) and User Avatar (Login). - `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. - `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. - **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:** - **Geo Utils:**
- `app/utils/geo.js`: Haversine distance calculations. - `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. - `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. 5. User clicks "Save Bookmark" -> Stores JSON in RemoteStorage.
6. RemoteStorage change event -> Debounced reload updates the map reactive-ly. 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. 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 ## Files Currently in Focus
- `app/styles/app.css`: Responsive sidebar styles and mobile optimizations. - `app/templates/application.gjs`: Core layout and "Outside Click" logic.
- `app/components/place-details.gjs`: Place display and editing logic. - `app/components/settings-pane.gjs`: Settings UI.
- `app/services/storage.js`: Data sync and update logic. - `app/services/settings.js`: Settings persistence.
## Next Steps & Pending Tasks ## 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 vite build --mode development` (development)
- `pnpm build` (production) - `pnpm build` (production)
### App Icon
- `pnpm build:icons` generates PNGs of all sizes from `public/icons/icon.svg`
### Deploying ### 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 ## Further Reading / Useful Links

View File

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

View File

@@ -6,7 +6,27 @@
<meta name="description" content=""> <meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1"> <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> </head>
<body> <body>
<script type="module"> <script type="module">

View File

@@ -1,6 +1,6 @@
{ {
"name": "marco", "name": "marco",
"version": "1.6.1", "version": "1.8.1",
"private": true, "private": true,
"description": "Small description for marco goes here", "description": "Small description for marco goes here",
"repository": "", "repository": "",
@@ -18,6 +18,7 @@
}, },
"scripts": { "scripts": {
"build": "vite build --outDir release/", "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", "format": "prettier . --cache --write",
"lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\" --prefixColors auto", "lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\" --prefixColors auto",
"lint:css": "stylelint \"**/*.css\"", "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

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.3 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.2 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 896 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: 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
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,9 +5,29 @@
<title>Marco</title> <title>Marco</title>
<meta name="description" content=""> <meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<script type="module" crossorigin src="/assets/main-CSdnGzLO.js"></script> <!-- App identity -->
<link rel="stylesheet" crossorigin href="/assets/main-CrGC4Dlj.css"> <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> </head>
<body> <body>
</body> </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"
}
]
}