fix(13-11): a films search found nothing — owned and peer content had no caller
Reported on-device: searching for films in AIUI returns nothing. Init only ever
asked for scope 'own' (content.list-mine — this node's own shared files), so
IndeeHub and everything else purchased, which lives in 'owned'
(content.owned-list), and other nodes' catalogs in 'peers' were never fetched.
Both scopes existed only as type-signature options with no call site anywhere
in the app.
requestArchyAllContent() now loads all three concurrently and merges once.
Merged rather than three setArchyContent calls because that sink REPLACES
films/podcasts — separate pushes would leave only whichever resolved last, the
same class of bug as the shared sequence guard fixed in aac81503. Deduped by
id, since a title can legitimately appear both owned locally and offered by a
peer. Each scope is caught individually so one dead or slow peer costs only its
own results, which is normal rather than exceptional.
requestArchyContent also stops clobbering songs with an empty array, mirroring
what requestArchyLibrary already did for films/podcasts.
vue-tsc clean, 3/3 useArchy tests pass, and the change is verified present in
the built bundle rather than assumed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
1dfd9e720b
commit
11b9cb5012
@@ -140,7 +140,7 @@ export function useArchy() {
|
||||
// functions already resolve to a silent, logged no-op when the user
|
||||
// hasn't granted Media/File access (`permitted: false`), so this never
|
||||
// throws into `init()`.
|
||||
void requestArchyContent('all', 'own')
|
||||
void requestArchyAllContent()
|
||||
void requestArchyLibrary('own')
|
||||
}
|
||||
|
||||
@@ -239,9 +239,10 @@ export function useArchy() {
|
||||
console.warn('[AIUI Archy] content: not permitted — user should enable Media/File access in Archy Settings')
|
||||
return
|
||||
}
|
||||
useContentPanel().setArchyContent({
|
||||
const panel = useContentPanel()
|
||||
panel.setArchyContent({
|
||||
films: res.films as Film[],
|
||||
songs: res.songs as Song[],
|
||||
songs: panel.panelSongs.value,
|
||||
podcasts: res.podcasts as Podcast[],
|
||||
})
|
||||
} catch (err) {
|
||||
@@ -249,6 +250,63 @@ export function useArchy() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load every content scope the node can offer, merged into one grid.
|
||||
*
|
||||
* `own` alone was all init ever asked for, which meant a films search showed
|
||||
* nothing but this node's own shared files: **IndeeHub and anything else
|
||||
* purchased live in `owned` (`content.owned-list`), and other nodes' catalogs
|
||||
* in `peers` — and neither scope had a single caller anywhere in the app.**
|
||||
* They existed only as type-signature options.
|
||||
*
|
||||
* Scopes are fetched concurrently and merged once, rather than each calling
|
||||
* `setArchyContent` itself: that sink REPLACES films/podcasts, so three
|
||||
* separate pushes would leave only whichever resolved last. Deduped by id
|
||||
* because the same title can legitimately appear in more than one scope
|
||||
* (owned locally and offered by a peer).
|
||||
*
|
||||
* A failing scope must not cost the others — a dead or slow peer is normal,
|
||||
* not exceptional — so each is caught individually and contributes nothing.
|
||||
*/
|
||||
async function requestArchyAllContent() {
|
||||
if (!isInitialized.value) return
|
||||
const scopes: Array<'own' | 'owned' | 'peers'> = ['own', 'owned', 'peers']
|
||||
|
||||
const results = await Promise.all(
|
||||
scopes.map((s) =>
|
||||
archyBridge
|
||||
.requestArchyContent('all', s)
|
||||
.then((res) => (res.permitted ? res : null))
|
||||
.catch((err) => {
|
||||
console.warn(`[AIUI Archy] content(${s}) failed:`, (err as Error)?.message ?? err)
|
||||
return null
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
const seen = new Set<string>()
|
||||
const films: Film[] = []
|
||||
const podcasts: Podcast[] = []
|
||||
for (const res of results) {
|
||||
if (!res) continue
|
||||
for (const f of (res.films ?? []) as Film[]) {
|
||||
const key = `film:${f.id}`
|
||||
if (seen.has(key)) continue
|
||||
seen.add(key)
|
||||
films.push(f)
|
||||
}
|
||||
for (const p of (res.podcasts ?? []) as Podcast[]) {
|
||||
const key = `pod:${p.id}`
|
||||
if (seen.has(key)) continue
|
||||
seen.add(key)
|
||||
podcasts.push(p)
|
||||
}
|
||||
}
|
||||
|
||||
const panel = useContentPanel()
|
||||
panel.setArchyContent({ films, songs: panel.panelSongs.value, podcasts })
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the node's real music library (13-11 — the D-13 wave) and hand
|
||||
* it to the same `setArchyContent` sink `requestArchyContent` uses, so
|
||||
@@ -381,6 +439,7 @@ export function useArchy() {
|
||||
readFile,
|
||||
tailLogs,
|
||||
requestArchyContent,
|
||||
requestArchyAllContent,
|
||||
requestArchyLibrary,
|
||||
buildArchyContext,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user