fix(SearchAssembly64): update fetch headers to include User-Agent for server compatibility

This commit is contained in:
Jaime Idolpx 2026-06-14 05:17:42 -04:00
parent 07cd6a81cf
commit 3b94d3d956
2 changed files with 15 additions and 9 deletions

View File

@ -52,9 +52,9 @@ src/
# AQL search with pagination; category filter chips; ContentItem result rows;
# item tap → /search/entries → file list with Download + Mount actions;
# Download saves to /sd/downloads/ via putFileContents;
# Client-Id: Ultimate header (identifies the 1541 Ultimate
# cartridge; the server returns HTTP 464 for unknown client ids);
# module-level _store
# Client-Id: Ultimate + User-Agent: Assembly Query headers (identifies
# the 1541 Ultimate cartridge; server returns 464 for unknown Client-Id
# and 463 for missing/foreign User-Agent); module-level _store
WiFiScanOverlay.tsx # WiFi scan results; Connect sends "connect <ssid> [<pass>]" via WS
MediaManager.tsx # WebDAV file browser: file icons by type, kebab actions,
# Configure Folder (.config editor), base_url mount logic,
@ -209,7 +209,7 @@ Header search icon opens SearchPane at tab 0 (Local). "Assembly64" AppCard opens
58. **MediaManager: Duplicate action**`duplicateEntry()` generates unique `"name copy.ext"` / `"name copy 2.ext"` etc. via sequential `fileExists` checks, then calls `copyPath`; button appears in the file Actions Dialog between Download and Rename; reloads current directory on success
59. **`.vms` Virtual Media Stack format** — `.vms` files are like `.lst` but each line is `path,name` (comma-separated); name after comma becomes the `MediaSetEntry.name` display label; `PLAYLIST_EXTS = new Set(['lst', 'vms'])` exported from `MediaEntry.tsx` with `Layers` icon (indigo); `MediaManager` and `DeviceDetailOverlay` both parse `.vms` into `MediaSetEntry[]`; `mediaSetEntryUrl()` used for `fileExists` checks and `dev.url`
60. **MarqueeText component**`ui/marquee-text.tsx`: extracted from inline MediaManager code; module-level `_seq` counter generates unique animation IDs; per-instance `@keyframes` rule injected into `<head>` and cleaned up on unmount; `ResizeObserver` re-measures on resize; ping-pong (alternate) scroll with `ease-in-out` and 0.8 s delay; used by MediaManager, SearchLocal, SearchAssembly64
61. **SearchLocal + SearchAssembly64 + SearchPane**`SearchOverlay.tsx` split into three components: `SearchPane.tsx` (swipeable shell: `fixed inset-0 bg-white/80 backdrop-blur-md`, spring slide-up via `motion/react`, tab bar with underline indicator + X button, horizontal `snap-x snap-mandatory` scroll container, `onScroll` updates active tab); `SearchLocal.tsx` (local file search panel: TOSEC/No-Intro tag parsing for system/video/language facet chips, wildcard search via `toSqlLike()` in `locate-db.ts` converting `*`→`%` and `?`→`_`, `MediaEntry` rows with badges + path, module-level `_store` persists results/scroll/filters across unmounts, actions dialog with MarqueeText + "Mount on virtual drive" + "Open containing folder", mounted-path highlight via `base_url + url` resolution); `SearchAssembly64.tsx` (Assembly64 Leet API: AQL search via `GET /search/aql/{offset}/{limit}`, categories + presets on mount, category filter chips, paginated ContentItem results, item tap fetches file entries, Download saves to `/sd/downloads/` via `putFileContents`, Mount opens device picker dialog, `Client-Id: Ultimate` header (identifies the 1541 Ultimate cartridge; the server returns HTTP 464 for unknown client ids), module-level `_store`); header search icon → tab 0, Apps "Assembly64" card → tab 1
61. **SearchLocal + SearchAssembly64 + SearchPane**`SearchOverlay.tsx` split into three components: `SearchPane.tsx` (swipeable shell: `fixed inset-0 bg-white/80 backdrop-blur-md`, spring slide-up via `motion/react`, tab bar with underline indicator + X button, horizontal `snap-x snap-mandatory` scroll container, `onScroll` updates active tab); `SearchLocal.tsx` (local file search panel: TOSEC/No-Intro tag parsing for system/video/language facet chips, wildcard search via `toSqlLike()` in `locate-db.ts` converting `*`→`%` and `?`→`_`, `MediaEntry` rows with badges + path, module-level `_store` persists results/scroll/filters across unmounts, actions dialog with MarqueeText + "Mount on virtual drive" + "Open containing folder", mounted-path highlight via `base_url + url` resolution); `SearchAssembly64.tsx` (Assembly64 Leet API: AQL search via `GET /search/aql/{offset}/{limit}`, categories + presets on mount, category filter chips, paginated ContentItem results, item tap fetches file entries, Download saves to `/sd/downloads/` via `putFileContents`, Mount opens device picker dialog, `Client-Id: Ultimate` + `User-Agent: Assembly Query` headers (identifies the 1541 Ultimate cartridge; server returns 464 for wrong Client-Id and 463 for missing/foreign User-Agent), module-level `_store`); header search icon → tab 0, Apps "Assembly64" card → tab 1
## Known Issues / Open Work

View File

@ -14,11 +14,17 @@ const DOWNLOAD_DIR = '/sd/downloads';
function leetFetch(path: string, query?: Record<string, string>) {
const url = new URL(LEET_BASE + path);
if (query) Object.entries(query).forEach(([k, v]) => url.searchParams.set(k, v));
// The server whitelists "Client-Id: Ultimate" (the 1541 Ultimate
// cartridge) and rejects unknown client ids with HTTP 464. The server
// also advertises "client-id" in Access-Control-Allow-Headers, so the
// preflight that this custom header triggers is allowed.
return fetch(url.toString(), { headers: { 'Client-Id': 'Ultimate' } });
// The server whitelists "Client-Id: Ultimate" and the "Assembly Query"
// User-Agent (matching the native Assembly64 client). Requests with the
// wrong identifiers get rejected: HTTP 464 for unknown Client-Id, HTTP
// 463 for a missing/foreign User-Agent. The server's CORS preflight
// allows both headers, so the browser accepts this request.
return fetch(url.toString(), {
headers: {
'Client-Id': 'Ultimate',
'User-Agent': 'Assembly Query',
},
});
}
async function leetJson<T>(path: string, query?: Record<string, string>): Promise<T> {