soulseek: fix browse crashing on the wrapped share-tree response
GET /users/{u}/browse returns { directories, directoryCount, lockedDirectories,
lockedDirectoryCount }, not the bare Directory[] that 0.26.0's source suggests,
so spreading it threw "E is not iterable" and every browse failed. Read
.directories, tolerating both shapes since the two disagree.
Also note in the type that browsed files carry only a basename, unlike search
results which carry the full remote path slskd needs to enqueue.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@ import { useSoulseekFavorites } from './useSoulseekFavorites';
|
|||||||
import {
|
import {
|
||||||
SOULSEEK_USER_CHANNEL,
|
SOULSEEK_USER_CHANNEL,
|
||||||
type SlskdBrowseDirectory,
|
type SlskdBrowseDirectory,
|
||||||
|
type SlskdBrowseResponse,
|
||||||
type SlskdUserInfo,
|
type SlskdUserInfo,
|
||||||
type SlskdUserStatus,
|
type SlskdUserStatus,
|
||||||
type SoulseekUserRequest,
|
type SoulseekUserRequest,
|
||||||
@@ -51,9 +52,11 @@ export const SoulseekUsers = () => {
|
|||||||
const browse = async (username: string) => {
|
const browse = async (username: string) => {
|
||||||
setBrowsing(true);
|
setBrowsing(true);
|
||||||
try {
|
try {
|
||||||
const tree = await client.get<SlskdBrowseDirectory[]>(
|
const res = await client.get<SlskdBrowseResponse | SlskdBrowseDirectory[]>(
|
||||||
`/slskd/api/v0/users/${encodeURIComponent(username)}/browse`,
|
`/slskd/api/v0/users/${encodeURIComponent(username)}/browse`,
|
||||||
);
|
);
|
||||||
|
// Tolerate both shapes: 0.26.0's source returns a bare array, the running build wraps it.
|
||||||
|
const tree = Array.isArray(res) ? res : (res?.directories ?? []);
|
||||||
setDirs([...tree].sort((a, b) => a.name.localeCompare(b.name)));
|
setDirs([...tree].sort((a, b) => a.name.localeCompare(b.name)));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
toast.error(`Browse failed: ${err instanceof Error ? err.message : String(err)}`);
|
toast.error(`Browse failed: ${err instanceof Error ? err.message : String(err)}`);
|
||||||
|
|||||||
@@ -174,6 +174,16 @@ export type SlskdUserStatus = {
|
|||||||
presence?: string; // 'Offline' | 'Away' | 'Online'
|
presence?: string; // 'Offline' | 'Away' | 'Online'
|
||||||
};
|
};
|
||||||
export type SlskdBrowseDirectory = { name: string; fileCount: number; files?: SlskdFile[] };
|
export type SlskdBrowseDirectory = { name: string; fileCount: number; files?: SlskdFile[] };
|
||||||
|
// GET /users/{u}/browse wraps the share tree rather than returning a bare array, and inlines every
|
||||||
|
// file of every folder in one shot (real peers hit 18k folders / tens of MB). Note that a browsed
|
||||||
|
// file's `filename` is only the basename — unlike search results, where it's the full remote path —
|
||||||
|
// so enqueuing one means rejoining it to its directory name with a backslash.
|
||||||
|
export type SlskdBrowseResponse = {
|
||||||
|
directories: SlskdBrowseDirectory[];
|
||||||
|
directoryCount: number;
|
||||||
|
lockedDirectories: SlskdBrowseDirectory[];
|
||||||
|
lockedDirectoryCount: number;
|
||||||
|
};
|
||||||
|
|
||||||
// Server connection state (GET /server, and the server block of GET /application).
|
// Server connection state (GET /server, and the server block of GET /application).
|
||||||
export type SlskdServerState = { address?: string; state?: string; isConnected?: boolean; username?: string };
|
export type SlskdServerState = { address?: string; state?: string; isConnected?: boolean; username?: string };
|
||||||
|
|||||||
Reference in New Issue
Block a user