Add a Pools browser backed by e621's /pools endpoint
- /pools: search by name, category/active filters, sort options and pagination per the OpenAPI spec, with covers taken from each pool's first post in one batched post call; blacklisted covers fall back to a placeholder and deleted pools get an archive marker. - /pools/<id>: DText description, post grid kept in the pool's own order with chunked loading, in-library badges, a blacklist reveal toggle and a Follow pool button wired into the follows API. - e621 client gains fetchPools/fetchPool; Pools nav entry added.
This commit is contained in:
@@ -316,6 +316,68 @@ export async function fetchPostsByMd5(
|
||||
return data.posts;
|
||||
}
|
||||
|
||||
export interface E621Pool {
|
||||
id: number;
|
||||
name: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
creator_id: number;
|
||||
creator_name: string;
|
||||
description: string;
|
||||
is_active: boolean;
|
||||
category: "collection" | "series";
|
||||
post_ids: number[];
|
||||
post_count: number;
|
||||
}
|
||||
|
||||
export type E621PoolOrder =
|
||||
| "id_desc"
|
||||
| "id_asc"
|
||||
| "name"
|
||||
| "created_at"
|
||||
| "post_count";
|
||||
|
||||
export async function fetchPools(
|
||||
credentials: E621Credentials,
|
||||
options: {
|
||||
name?: string;
|
||||
category?: string;
|
||||
isActive?: string;
|
||||
order?: E621PoolOrder;
|
||||
page?: number;
|
||||
limit?: number;
|
||||
signal?: AbortSignal;
|
||||
} = {},
|
||||
): Promise<E621Pool[]> {
|
||||
const data = await e621Request<unknown>(credentials, "/pools.json", {
|
||||
params: {
|
||||
limit: options.limit ?? 48,
|
||||
page: options.page,
|
||||
"search[order]": options.order ?? "id_desc",
|
||||
"search[name_matches]": options.name || undefined,
|
||||
"search[category]": options.category || undefined,
|
||||
"search[is_active]": options.isActive || undefined,
|
||||
},
|
||||
signal: options.signal,
|
||||
});
|
||||
// The spec says a bare array; tolerate a wrapped payload too.
|
||||
if (Array.isArray(data)) return data as E621Pool[];
|
||||
const wrapped = (data as { pools?: E621Pool[] })?.pools;
|
||||
return Array.isArray(wrapped) ? wrapped : [];
|
||||
}
|
||||
|
||||
export async function fetchPool(
|
||||
credentials: E621Credentials,
|
||||
poolId: number,
|
||||
signal?: AbortSignal,
|
||||
): Promise<E621Pool> {
|
||||
const data = await e621Request<unknown>(credentials, `/pools/${poolId}.json`, {
|
||||
signal,
|
||||
});
|
||||
const wrapped = (data as { pool?: E621Pool })?.pool;
|
||||
return (wrapped ?? (data as E621Pool)) as E621Pool;
|
||||
}
|
||||
|
||||
export interface E621IqdbResult {
|
||||
post_id: number | null;
|
||||
score: number | null;
|
||||
|
||||
Reference in New Issue
Block a user