diff --git a/src/apps/dashboard/features/plugins/api/configurationPage.ts b/src/apps/dashboard/features/plugins/api/configurationPage.ts new file mode 100644 index 0000000000..c0ff05eb3c --- /dev/null +++ b/src/apps/dashboard/features/plugins/api/configurationPage.ts @@ -0,0 +1,21 @@ +import type { ConfigurationPageInfo } from '@jellyfin/sdk/lib/generated-client/models/configuration-page-info'; + +export const findBestConfigurationPage = ( + configurationPages: ConfigurationPageInfo[], + pluginId: string +) => { + // Find candidates matching the plugin id + const candidates = configurationPages.filter(c => c.PluginId === pluginId); + + // If none are found, return undefined + if (candidates.length === 0) return; + // If only one is found, return it + if (candidates.length === 1) return candidates[0]; + + // Prefer the first candidate with the EnableInMainMenu flag for consistency + const menuCandidate = candidates.find(c => !!c.EnableInMainMenu); + if (menuCandidate) return menuCandidate; + + // Fallback to the first match + return candidates[0]; +}; diff --git a/src/apps/dashboard/features/plugins/types/PluginDetails.ts b/src/apps/dashboard/features/plugins/types/PluginDetails.ts index 1985348a8b..88a96080c1 100644 --- a/src/apps/dashboard/features/plugins/types/PluginDetails.ts +++ b/src/apps/dashboard/features/plugins/types/PluginDetails.ts @@ -1,14 +1,14 @@ -import type { PluginStatus, VersionInfo } from '@jellyfin/sdk/lib/generated-client'; +import type { ConfigurationPageInfo, PluginStatus, VersionInfo } from '@jellyfin/sdk/lib/generated-client'; export interface PluginDetails { canUninstall: boolean description?: string - hasConfiguration: boolean id: string imageUrl?: string isEnabled: boolean name?: string owner?: string + configurationPage?: ConfigurationPageInfo status?: PluginStatus version?: VersionInfo versions: VersionInfo[] diff --git a/src/apps/dashboard/routes/plugins/plugin.tsx b/src/apps/dashboard/routes/plugins/plugin.tsx index 5319937bf0..d16b308c7a 100644 --- a/src/apps/dashboard/routes/plugins/plugin.tsx +++ b/src/apps/dashboard/routes/plugins/plugin.tsx @@ -16,6 +16,7 @@ import Settings from '@mui/icons-material/Settings'; import React, { type FC, useEffect, useState, useCallback, useMemo } from 'react'; import { useSearchParams, Link as RouterLink, useParams } from 'react-router-dom'; +import { findBestConfigurationPage } from 'apps/dashboard/features/plugins/api/configurationPage'; import { findBestPluginInfo } from 'apps/dashboard/features/plugins/api/pluginInfo'; import { useConfigurationPages } from 'apps/dashboard/features/plugins/api/useConfigurationPages'; import { useDisablePlugin } from 'apps/dashboard/features/plugins/api/useDisablePlugin'; @@ -261,7 +262,6 @@ const PluginPage: FC = () => { setPluginDetails({ canUninstall: !!pluginInfo?.CanUninstall, description: pluginInfo?.Description || packageInfo?.description || packageInfo?.overview, - hasConfiguration: !!configurationPages?.some(page => page.PluginId === pluginId), id: pluginId, imageUrl: imageUrl || packageInfo?.imageUrl || undefined, isEnabled: (isEnabledOverride && pluginInfo?.Status === PluginStatus.Restart) @@ -269,6 +269,7 @@ const PluginPage: FC = () => { name: pluginName || pluginInfo?.Name || packageInfo?.name, owner: packageInfo?.owner, status: pluginInfo?.Status, + configurationPage: findBestConfigurationPage(configurationPages || [], pluginId), version, versions: packageInfo?.versions || [] }); @@ -360,10 +361,10 @@ const PluginPage: FC = () => { )} - {!isLoading && pluginDetails?.hasConfiguration && ( + {!isLoading && pluginDetails?.configurationPage?.Name && (