From 5516daab6ea11c22b6e7e3e10cf2d97ea059fd43 Mon Sep 17 00:00:00 2001 From: Kendall Garner <17521368+kgarner7@users.noreply.github.com> Date: Mon, 15 Jan 2024 20:46:06 -0800 Subject: [PATCH] enable comments, safer note --- .../api/jellyfin/jellyfin-normalize.ts | 1 + .../api/navidrome/navidrome-normalize.ts | 1 + src/renderer/api/navidrome/navidrome-types.ts | 1 + .../api/subsonic/subsonic-normalize.ts | 1 + src/renderer/api/types.ts | 1 + .../virtual-table/cells/note-cell.tsx | 17 ++------- .../components/album-detail-content.tsx | 16 +++++++- src/renderer/utils/linkify.tsx | 38 +++++++++++++++++++ 8 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 src/renderer/utils/linkify.tsx diff --git a/src/renderer/api/jellyfin/jellyfin-normalize.ts b/src/renderer/api/jellyfin/jellyfin-normalize.ts index 4d844174..ffef489a 100644 --- a/src/renderer/api/jellyfin/jellyfin-normalize.ts +++ b/src/renderer/api/jellyfin/jellyfin-normalize.ts @@ -214,6 +214,7 @@ const normalizeAlbum = ( name: entry.Name, })), backdropImageUrl: null, + comment: null, createdAt: item.DateCreated, duration: item.RunTimeTicks / 10000, genres: item.GenreItems?.map((entry) => ({ diff --git a/src/renderer/api/navidrome/navidrome-normalize.ts b/src/renderer/api/navidrome/navidrome-normalize.ts index 4aafb14e..717ba2ca 100644 --- a/src/renderer/api/navidrome/navidrome-normalize.ts +++ b/src/renderer/api/navidrome/navidrome-normalize.ts @@ -154,6 +154,7 @@ const normalizeAlbum = ( albumArtists: [{ id: item.albumArtistId, imageUrl: null, name: item.albumArtist }], artists: [{ id: item.artistId, imageUrl: null, name: item.artist }], backdropImageUrl: imageBackdropUrl, + comment: item.comment || null, createdAt: item.createdAt.split('T')[0], duration: item.duration * 1000 || null, genres: item.genres?.map((genre) => ({ diff --git a/src/renderer/api/navidrome/navidrome-types.ts b/src/renderer/api/navidrome/navidrome-types.ts index d01174f6..b63b5442 100644 --- a/src/renderer/api/navidrome/navidrome-types.ts +++ b/src/renderer/api/navidrome/navidrome-types.ts @@ -111,6 +111,7 @@ const album = z.object({ allArtistIds: z.string(), artist: z.string(), artistId: z.string(), + comment: z.string().optional(), compilation: z.boolean(), coverArtId: z.string().optional(), // Removed after v0.48.0 coverArtPath: z.string().optional(), // Removed after v0.48.0 diff --git a/src/renderer/api/subsonic/subsonic-normalize.ts b/src/renderer/api/subsonic/subsonic-normalize.ts index 881e7fef..31c2f6c8 100644 --- a/src/renderer/api/subsonic/subsonic-normalize.ts +++ b/src/renderer/api/subsonic/subsonic-normalize.ts @@ -155,6 +155,7 @@ const normalizeAlbum = ( : [], artists: item.artistId ? [{ id: item.artistId, imageUrl: null, name: item.artist }] : [], backdropImageUrl: null, + comment: null, createdAt: item.created, duration: item.duration, genres: item.genre diff --git a/src/renderer/api/types.ts b/src/renderer/api/types.ts index 5165c7fb..3abf9f64 100644 --- a/src/renderer/api/types.ts +++ b/src/renderer/api/types.ts @@ -147,6 +147,7 @@ export type Album = { albumArtists: RelatedArtist[]; artists: RelatedArtist[]; backdropImageUrl: string | null; + comment: string | null; createdAt: string; duration: number | null; genres: Genre[]; diff --git a/src/renderer/components/virtual-table/cells/note-cell.tsx b/src/renderer/components/virtual-table/cells/note-cell.tsx index 1191d597..eaa1b5f7 100644 --- a/src/renderer/components/virtual-table/cells/note-cell.tsx +++ b/src/renderer/components/virtual-table/cells/note-cell.tsx @@ -3,17 +3,7 @@ import { Skeleton } from '/@/renderer/components/skeleton'; import { CellContainer } from '/@/renderer/components/virtual-table/cells/generic-cell'; import { useMemo } from 'react'; import { Text } from '/@/renderer/components/text'; - -const URL_REGEX = - /((?:https?:\/\/)?(?:[\w-]{1,32}(?:\.[\w-]{1,32})+)(?:\/[\w\-./?%&=][^.|^\s]*)?)/g; - -const replaceURLWithHTMLLinks = (text: string) => { - const urlRegex = new RegExp(URL_REGEX, 'g'); - return text.replaceAll( - urlRegex, - (url) => `${url}`, - ); -}; +import { replaceURLWithHTMLLinks } from '/@/renderer/utils/linkify'; export const NoteCell = ({ value }: ICellRendererParams) => { const formattedValue = useMemo(() => { @@ -39,9 +29,10 @@ export const NoteCell = ({ value }: ICellRendererParams) => { + > + {formattedValue} + ); }; diff --git a/src/renderer/features/albums/components/album-detail-content.tsx b/src/renderer/features/albums/components/album-detail-content.tsx index d158d908..97addc46 100644 --- a/src/renderer/features/albums/components/album-detail-content.tsx +++ b/src/renderer/features/albums/components/album-detail-content.tsx @@ -1,7 +1,7 @@ import { MutableRefObject, useCallback, useMemo } from 'react'; import { RowDoubleClickedEvent, RowHeightParams, RowNode } from '@ag-grid-community/core'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; -import { Box, Group, Stack } from '@mantine/core'; +import { Box, Group, Spoiler, Stack } from '@mantine/core'; import { useSetState } from '@mantine/hooks'; import { useTranslation } from 'react-i18next'; import { RiHeartFill, RiHeartLine, RiMoreFill, RiSettings2Fill } from 'react-icons/ri'; @@ -41,6 +41,7 @@ import { useTableSettings, } from '/@/renderer/store/settings.store'; import { Play } from '/@/renderer/types'; +import { replaceURLWithHTMLLinks } from '/@/renderer/utils/linkify'; const isFullWidthRow = (node: RowNode) => { return node.id?.startsWith('disc-'); @@ -279,6 +280,7 @@ export const AlbumDetailContent = ({ tableRef, background }: AlbumDetailContentP }; const showGenres = detailQuery?.data?.genres ? detailQuery?.data?.genres.length !== 0 : false; + const comment = detailQuery?.data?.comment; const handleGeneralContextMenu = useHandleGeneralContextMenu( LibraryItem.ALBUM, @@ -395,6 +397,18 @@ export const AlbumDetailContent = ({ tableRef, background }: AlbumDetailContentP )} + {comment && ( + + + {replaceURLWithHTMLLinks(comment)} + + + )} { + const urlRegex = new RegExp(URL_REGEX, 'g'); + const matches = text.matchAll(urlRegex); + const elements = []; + let lastIndex = 0; + + for (const match of matches) { + const position = match.index!; + + if (position > lastIndex) { + elements.push(text.substring(lastIndex, position)); + } + + const link = match[0]; + elements.push( + + {link} + , + ); + + lastIndex = position + link.length; + } + + if (text.length > lastIndex) { + elements.push(text.substring(lastIndex)); + } + + return elements; +};