Add routing, cast API conversion, and filters

Introduce client-side routing and cast API support. Key changes:

- Add react-router-dom dependency and wire BrowserRouter in App.
- Convert App to route-based structure (/, /media/:id, /cast, /cast/:id, /add, /import) with MediaDetailRoute and CastDetailRoute helpers.
- Extend API types for cast items and add convertApiCastToStaff; fetchAllCast now returns Staff[] (mapped via converter).
- Update components to use react-router hooks (useNavigate, useParams, useLocation, Link/NavLink): Header links, DetailView, CastDetailView, AddMediaView, ImporterView and others now navigate via routes.
- Enhance CastView: fetch cast list, loading state, persistent search/sort/filter controls, filtering by occupations/media types and enabled categories, improved pagination and UI controls.
- Update stashapp importer: add configurable blacklist check to skip scenes, increase per_page for queries.

These changes consolidate navigation, improve cast data handling from the API, and add richer filtering and importer controls.
This commit is contained in:
Lars Behrends
2026-04-10 13:46:52 +02:00
parent a610ce304e
commit f5c3e96823
12 changed files with 830 additions and 196 deletions
+23 -1
View File
@@ -1,6 +1,7 @@
export interface StashAPPConfig {
url: string;
apiKey?: string;
blacklist?: ['/AI/', 'temp', 'backup'];
}
export interface ImportProgress {
@@ -127,6 +128,13 @@ export interface StashAPPPerformersResponse {
export type LogCallback = (message: string) => void;
export type ProgressCallback = (progress: Partial<ImportProgress>) => void;
function isPathBlacklisted(filePath: string, blacklist: string[]): boolean {
if (!blacklist || blacklist.length === 0) {
return false;
}
return blacklist.some(pattern => filePath.includes(pattern));
}
export async function updateActorsFromStashAPP(
config: StashAPPConfig,
logCallback: LogCallback,
@@ -457,7 +465,7 @@ export async function importFromStashAPP(
`,
variables: {
filter: {
per_page: 100,
per_page: 20000,
sort: "date",
direction: "DESC"
}
@@ -616,6 +624,20 @@ export async function importFromStashAPP(
for (let i = 0; i < scenes.length; i++) {
const scene = scenes[i];
// Check if scene is blacklisted
if (config.blacklist && config.blacklist.length > 0) {
const isBlacklisted = scene.files && scene.files.some(file =>
isPathBlacklisted(file.path, config.blacklist!)
);
if (isBlacklisted) {
logCallback(`⊘ Skipped blacklisted scene: ${scene.title}`);
progressCallback({
current: uniquePerformers.length + i + 1
});
continue;
}
}
// Check for duplicate
if (existingTitles.has(scene.title)) {
logCallback(`⊘ Skipped duplicate: ${scene.title}`);