diff --git a/apps/docs/docs/widgets/audio-stats/index.mdx b/apps/docs/docs/widgets/audio-stats/index.mdx index f37a4eb83..50f32f5ec 100644 --- a/apps/docs/docs/widgets/audio-stats/index.mdx +++ b/apps/docs/docs/widgets/audio-stats/index.mdx @@ -1,43 +1,45 @@ --- -title: 'Audio Stats' -description: 'Displays library statistics from Navidrome or Audiobookshelf, adapting its display based on the linked integration.' +title: "Audio Stats" +description: "Displays library statistics from Navidrome or Audiobookshelf, adapting its display based on the linked integration." hide_title: true --- -import { WidgetHeader } from '@site/src/components/widgets/header'; -import { AddingWidget } from '@site/src/components/widgets/adding'; -import { WidgetConfig } from '@site/src/components/widgets/configuration'; -import { WidgetIntegrations } from '@site/src/components/widgets/integrations'; -import { audioStatsWidget } from '.'; -import { navidromeIntegration } from '@site/docs/integrations/navidrome'; -import { audiobookshelfIntegration } from '@site/docs/integrations/audiobookshelf'; +import { WidgetHeader } from "@site/src/components/widgets/header"; +import { AddingWidget } from "@site/src/components/widgets/adding"; +import { WidgetConfig } from "@site/src/components/widgets/configuration"; +import { WidgetIntegrations } from "@site/src/components/widgets/integrations"; +import { audioStatsWidget } from "."; +import { navidromeIntegration } from "@site/docs/integrations/navidrome"; +import { audiobookshelfIntegration } from "@site/docs/integrations/audiobookshelf"; - - + This widget adapts its display based on the linked integration: -- **Navidrome**: Shows artist, album, and song counts, plus a now playing section with active streams +- **Navidrome**: Shows artist, album, and song counts - **Audiobookshelf**: Shows library count, audiobook/podcast totals, listening time, and active sessions Only options relevant to your linked integration are shown in the configuration panel. ### Supported Integrations - + ### Adding the widget ### Configuration + diff --git a/apps/docs/docs/widgets/audio-stats/index.ts b/apps/docs/docs/widgets/audio-stats/index.ts index ab9bd7f2f..21ef8714d 100644 --- a/apps/docs/docs/widgets/audio-stats/index.ts +++ b/apps/docs/docs/widgets/audio-stats/index.ts @@ -27,24 +27,6 @@ export const audioStatsWidget: WidgetDefinition = { values: { type: "boolean" }, defaultValue: "yes", }, - { - name: "Show now playing", - description: "Displays currently playing tracks (Navidrome only)", - values: { type: "boolean" }, - defaultValue: "yes", - }, - { - name: "Show now playing list", - description: "Displays a detailed list of now playing tracks (Navidrome only)", - values: { type: "boolean" }, - defaultValue: "yes", - }, - { - name: "Max now playing items", - description: "Maximum number of now playing tracks to display (Navidrome only)", - values: "Number (1-5)", - defaultValue: "3", - }, { name: "Show library count", description: "Displays the number of libraries (Audiobookshelf only)", diff --git a/packages/integrations/src/navidrome/navidrome-integration.ts b/packages/integrations/src/navidrome/navidrome-integration.ts index 6f1e7b1b7..ebbff6611 100644 --- a/packages/integrations/src/navidrome/navidrome-integration.ts +++ b/packages/integrations/src/navidrome/navidrome-integration.ts @@ -55,17 +55,15 @@ export class NavidromeIntegration extends Integration implements IMediaServerInt } public async getDashboardDataAsync(): Promise { - const [artistCount, libraryCounts, nowPlaying] = await Promise.all([ + const [artistCount, libraryCounts] = await Promise.all([ this.getArtistCountAsync(), this.getAlbumAndSongCountsAsync(), - this.getNowPlayingAsync(), ]); return { artistCount, albumCount: libraryCounts.albumCount, songCount: libraryCounts.songCount, - nowPlaying, }; } diff --git a/packages/integrations/src/navidrome/navidrome-types.ts b/packages/integrations/src/navidrome/navidrome-types.ts index a9e5067f2..53f930d93 100644 --- a/packages/integrations/src/navidrome/navidrome-types.ts +++ b/packages/integrations/src/navidrome/navidrome-types.ts @@ -67,5 +67,4 @@ export interface NavidromeDashboardData { artistCount: number; albumCount: number; songCount: number; - nowPlaying: NavidromeNowPlayingEntry[]; } diff --git a/packages/integrations/src/navidrome/test/navidrome-integration.spec.ts b/packages/integrations/src/navidrome/test/navidrome-integration.spec.ts index 3300f7003..33912b395 100644 --- a/packages/integrations/src/navidrome/test/navidrome-integration.spec.ts +++ b/packages/integrations/src/navidrome/test/navidrome-integration.spec.ts @@ -84,12 +84,6 @@ describe("NavidromeIntegration.getDashboardDataAsync", () => { >; } - if (urlStr.includes("getNowPlaying")) { - return Promise.resolve(new Response(subsonicOk({ nowPlaying: {} }), { status: 200 })) as unknown as ReturnType< - typeof fetchWithTrustedCertificatesAsync - >; - } - return Promise.resolve(new Response(subsonicOk({}), { status: 200 })) as unknown as ReturnType< typeof fetchWithTrustedCertificatesAsync >; @@ -101,7 +95,6 @@ describe("NavidromeIntegration.getDashboardDataAsync", () => { expect(result.albumCount).toBe(700); expect(result.songCount).toBe(500 * 10 + 200 * 5); expect(result.artistCount).toBe(1); - expect(result.nowPlaying).toEqual([]); }); test("handles empty library gracefully", async () => { @@ -120,12 +113,6 @@ describe("NavidromeIntegration.getDashboardDataAsync", () => { ) as unknown as ReturnType; } - if (urlStr.includes("getNowPlaying")) { - return Promise.resolve( - new Response(subsonicFailed("Library not found or empty"), { status: 200 }), - ) as unknown as ReturnType; - } - return Promise.resolve(new Response(subsonicOk({}), { status: 200 })) as unknown as ReturnType< typeof fetchWithTrustedCertificatesAsync >; @@ -137,7 +124,6 @@ describe("NavidromeIntegration.getDashboardDataAsync", () => { expect(result.artistCount).toBe(0); expect(result.albumCount).toBe(0); expect(result.songCount).toBe(0); - expect(result.nowPlaying).toEqual([]); }); test("throws on non-empty-library subsonic error", async () => { @@ -151,53 +137,6 @@ describe("NavidromeIntegration.getDashboardDataAsync", () => { const integration = createIntegration(); await expect(integration.getDashboardDataAsync()).rejects.toThrow(); }); - - test("now playing maps entries correctly", async () => { - mockFetch.mockImplementation((url) => { - const urlStr = toUrlString(url); - - if (urlStr.includes("getNowPlaying")) { - return Promise.resolve( - new Response( - subsonicOk({ - nowPlaying: { - entry: { title: "Song", artist: "Band", album: "LP", username: "user1", playerName: "Chrome" }, - }, - }), - { status: 200 }, - ), - ) as unknown as ReturnType; - } - - if (urlStr.includes("getArtists")) { - return Promise.resolve(new Response(subsonicOk({ artists: {} }), { status: 200 })) as unknown as ReturnType< - typeof fetchWithTrustedCertificatesAsync - >; - } - - if (urlStr.includes("getAlbumList2")) { - return Promise.resolve(new Response(subsonicOk({ albumList2: {} }), { status: 200 })) as unknown as ReturnType< - typeof fetchWithTrustedCertificatesAsync - >; - } - - return Promise.resolve(new Response(subsonicOk({}), { status: 200 })) as unknown as ReturnType< - typeof fetchWithTrustedCertificatesAsync - >; - }); - - const integration = createIntegration(); - const result = await integration.getDashboardDataAsync(); - - expect(result.nowPlaying).toHaveLength(1); - expect(result.nowPlaying[0]).toEqual({ - title: "Song", - artist: "Band", - album: "LP", - username: "user1", - playerName: "Chrome", - }); - }); }); describe("NavidromeIntegration.getCurrentSessionsAsync", () => { @@ -331,8 +270,9 @@ describe("NavidromeIntegration.getCurrentSessionsAsync", () => { const integration = createIntegration(); - await expect(integration.getCurrentSessionsAsync({ showOnlyPlaying: true })).rejects.toThrow( - "Wrong username or password", - ); + await expect(integration.getCurrentSessionsAsync({ showOnlyPlaying: true })).rejects.toMatchObject({ + message: "An unknown error occured while executing Integration method", + cause: { message: "Wrong username or password" }, + }); }); }); diff --git a/packages/translation/src/lang/en.json b/packages/translation/src/lang/en.json index 388dc4186..de211bf66 100644 --- a/packages/translation/src/lang/en.json +++ b/packages/translation/src/lang/en.json @@ -3768,18 +3768,6 @@ "label": "Show songs", "description": "Show the total number of songs in your music library (Navidrome)" }, - "showNowPlaying": { - "label": "Show now playing", - "description": "Show tracks currently being played (Navidrome)" - }, - "showNowPlayingList": { - "label": "Show now playing list", - "description": "Show individual tracks instead of only the active stream count (Navidrome)" - }, - "maxNowPlayingItems": { - "label": "Max now playing items", - "description": "Maximum number of tracks to show in the now playing list (Navidrome)" - }, "showLibraryCount": { "label": "Show library count", "description": "Show the number of libraries on your instance (Audiobookshelf)" @@ -3813,8 +3801,6 @@ "podcasts": "Podcasts", "listeningTime": "Listening Time", "activeSessions": "Active Sessions", - "nowPlaying": "Now Playing", - "nowPlayingCount": "{count, plural, one {# stream} other {# streams}}", "error": { "internalServerError": "Failed to fetch audio stats data" } diff --git a/packages/widgets/src/audio-stats/audio-stats-shared.spec.ts b/packages/widgets/src/audio-stats/audio-stats-shared.spec.ts index 3aab75060..406562f66 100644 --- a/packages/widgets/src/audio-stats/audio-stats-shared.spec.ts +++ b/packages/widgets/src/audio-stats/audio-stats-shared.spec.ts @@ -42,7 +42,6 @@ describe("getVisibleStats", () => { artistCount: 100, albumCount: 200, songCount: 3000, - nowPlaying: [], }; const audiobookshelfStats: AudiobookshelfDashboardData = { diff --git a/packages/widgets/src/audio-stats/component.module.css b/packages/widgets/src/audio-stats/component.module.css index f665c8028..84b3a447c 100644 --- a/packages/widgets/src/audio-stats/component.module.css +++ b/packages/widgets/src/audio-stats/component.module.css @@ -87,92 +87,6 @@ font-size: clamp(11px, 4cqi, 16px); } -.nowPlaying { - display: flex; - flex-direction: column; - gap: clamp(3px, 1.2cqi, 5px); - flex: 1; - min-height: 0; - overflow: hidden; -} - -.nowPlayingHeader { - display: flex; - align-items: center; - gap: clamp(4px, 1.5cqi, 6px); - font-size: clamp(10px, 2.8cqi, 12px); - font-weight: 600; - flex-shrink: 0; - min-width: 0; -} - -.nowPlayingTitle { - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.nowPlayingCount { - flex-shrink: 0; - margin-inline-start: auto; -} - -.nowPlayingList { - display: flex; - flex-direction: column; - gap: clamp(2px, 0.8cqi, 4px); - flex: 1; - min-height: 0; - overflow: hidden; -} - -.nowPlayingItem { - display: flex; - align-items: center; - justify-content: space-between; - gap: clamp(4px, 1.5cqi, 6px); - padding: clamp(3px, 1.2cqi, 6px) clamp(4px, 1.5cqi, 8px); - border-radius: var(--mantine-radius-sm); - background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-6)); - min-width: 0; - flex-shrink: 0; -} - -.trackInfo { - display: flex; - flex-direction: column; - gap: 1px; - min-width: 0; - flex: 1; -} - -.trackTitle { - font-size: clamp(9px, 2.6cqi, 12px); - font-weight: 500; - line-height: 1.2; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.trackArtist { - font-size: clamp(8px, 2.2cqi, 10px); - color: var(--mantine-color-dimmed); - line-height: 1.2; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.trackUser { - flex-shrink: 0; - max-width: clamp(40px, 22cqi, 88px); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - .emptyState { display: flex; flex: 1;