aeharding / aeharding/wingover

map: keep MapKit usable offline (tiles are already cached; reauth is the lock)

Đang mở
#165 1 bình luận 0 reaction 0 người được giao Xem trên GitHub
offline
Ngôn ngữ chính
TypeScript
Star
0
Fork
0
Merge trung bình
4 giờ 2 phút
Pull request đã merge (30 ngày)
6

Mô tả

Follow-on to #164. #164 guarantees the track always draws. This issue is about keeping the **basemap** too, so an in-flight restart out of coverage still shows the ground you were just flying over.

## The key finding: the tiles are already on the device

MapKit serves tiles with `cache-control: public, max-age=604800` (7 days), and WebKit's cache persists across launches. So a flight flown with service has already downloaded the tiles for that exact area. Nothing is missing offline. MapKit simply refuses to start, so the data is locked, not absent.

**Proven:** capture every MapKit response online, then load the app in a fresh browser with a hard network block, serving only the captured bytes. MapKit initialises completely and paints a full Apple basemap (terrain, labels, coastlines, attribution) with zero network. 75/75 replayed, no console errors.

Note `no-store` on the bootstrap does not prevent this. It binds the browser's HTTP cache, not storage we control.

## What actually blocks an offline relaunch

Only two responses. Everything else is already cached and long-lived.

| endpoint | cache-control | offline? |
|---|---|---|
| `/mk/6.0.x/libs/mapkit.core.*.js` | `max-age=31322996` (~362d) | cached, fine |
| `/md/v1/vtile`, `/ttile`, `/icon` | `max-age=604800` (7d), `s-maxage=2` | cached, fine |
| `/mk/6/mapkit.core.js` (version pointer) | `max-age=23..275` | **expires, blocks** |
| `/ma/bootstrap` (auth) | `max-age=0, no-cache, no-store` | **never cached, blocks** |

So a shim serving just those two from local storage could let WebKit's own cache supply the rest.

## Open question: does reauth cap it?

`/ma/bootstrap` returns an `accessKey` with `expiresInSeconds: 1800`, and the key embeds an issue timestamp. Forcing `expiresInSeconds: 0` in a replay produced an initialised map that painted **no tiles** (empty grid) - but that test *tells* MapKit the key is dead, which a verbatim replay does not. A stored bootstrap still says `1800`, so MapKit may compute the deadline from receipt and never learn otherwise, with no server present to disagree.

An experiment is running: capture untouched, wait out the full 30 minutes, replay verbatim. Result decides scope:

- **Tiles paint:** no practical ceiling; the shim is worth building.
- **Empty grid:** reauth caps continuity at ~30 min from last bootstrap, and only owned tiles give multi-hour coverage.

## Mechanism (PWA and native are different problems)

- **PWA** (`https://wingover.app`): service workers work. `src/sw.ts` (workbox) already exists. Note no `registerSW` call was found in `src/` or `index.html`, so the worker may not be registering at all today - worth checking separately.
- **Native** (`tauri://localhost`): a custom scheme, where WebKit does **not** run service workers. The PWA worker does nothing for the app. `NSURLProtocol` does not see WKWebView traffic and `setURLSchemeHandler` only handles custom schemes, so neither helps. The candidate is `WKWebsiteDataStore.proxyConfigurations` (public API, iOS 17+), routing webview traffic through a proxy we run. Untested.

## Before building

Apple's MapKit JS terms need a real read. Their own `max-age=604800` sanctions a browser cache; a custom store that replays their responses is a different question, and this ships on the App Store.

Hướng dẫn đóng góp

Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.