mirror of
https://github.com/jeffvli/feishin.git
synced 2026-07-24 19:36:30 +02:00
Compare commits
7 Commits
324936e0c8
...
e49e488b4c
| Author | SHA1 | Date | |
|---|---|---|---|
| e49e488b4c | |||
| 5d4547080d | |||
| cc8910cfd6 | |||
| 9fb241dca2 | |||
| e3a0879301 | |||
| 953494e9d0 | |||
| f190626c8c |
@@ -85,7 +85,7 @@
|
|||||||
"hotkey_zoomIn": "拡大",
|
"hotkey_zoomIn": "拡大",
|
||||||
"scrobble_description": "再生した音楽をメディアサーバーから Scrobble します",
|
"scrobble_description": "再生した音楽をメディアサーバーから Scrobble します",
|
||||||
"hotkey_browserForward": "ブラウザ 進む",
|
"hotkey_browserForward": "ブラウザ 進む",
|
||||||
"audioExclusiveMode_description": "排他出力モードを有効にします。このモードでは、システムの他の出力がロックされ、MPV のみがオーディオを出力できるようになります",
|
"audioExclusiveMode_description": "排他出力モードを有効にします。このモードでは、システムの他の出力がロックされ、MPV のみがオーディオを出力できるようになります。このモードが有効になっている間は、ビジュアライザーやシステムオーディオのキャプチャ機能は動作しません",
|
||||||
"discordUpdateInterval": "{{discord}} Rich Presence の更新間隔",
|
"discordUpdateInterval": "{{discord}} Rich Presence の更新間隔",
|
||||||
"themeLight": "テーマ (ライト)",
|
"themeLight": "テーマ (ライト)",
|
||||||
"fontType_optionBuiltIn": "組み込みフォント",
|
"fontType_optionBuiltIn": "組み込みフォント",
|
||||||
@@ -425,7 +425,11 @@
|
|||||||
"sidePlayQueueLayout_optionHorizontal": "水平",
|
"sidePlayQueueLayout_optionHorizontal": "水平",
|
||||||
"sidePlayQueueLayout_optionVertical": "垂直",
|
"sidePlayQueueLayout_optionVertical": "垂直",
|
||||||
"waveformLoadingDelay": "波形読み込みの遅延",
|
"waveformLoadingDelay": "波形読み込みの遅延",
|
||||||
"waveformLoadingDelay_description": "波形を読み込むまでの遅延時間(秒単位)を設定します。Web プレーヤー使用時にカクつきが発生する場合は、この値を増やしてください。"
|
"waveformLoadingDelay_description": "波形を読み込むまでの遅延時間(秒単位)を設定します。Web プレーヤー使用時にカクつきが発生する場合は、この値を増やしてください。",
|
||||||
|
"playerbarWaveformStretch": "波形伸縮",
|
||||||
|
"playerbarWaveformStretch_description": "波形を伸縮させて、利用可能なスペースを埋めます",
|
||||||
|
"preventSuspendOnPlayback_description": "音楽再生中にアプリケーションが停止しないようにします",
|
||||||
|
"preventSuspendOnPlayback": "再生の中断を防止する"
|
||||||
},
|
},
|
||||||
"action": {
|
"action": {
|
||||||
"editPlaylist": "$t(entity.playlist, {\"count\": 1}) を編集",
|
"editPlaylist": "$t(entity.playlist, {\"count\": 1}) を編集",
|
||||||
@@ -808,7 +812,7 @@
|
|||||||
"dynamicBackground": "ダイナミック背景",
|
"dynamicBackground": "ダイナミック背景",
|
||||||
"synchronized": "同期",
|
"synchronized": "同期",
|
||||||
"followCurrentLyric": "歌詞を再生位置に追従",
|
"followCurrentLyric": "歌詞を再生位置に追従",
|
||||||
"opacity": "非透過率",
|
"opacity": "不透明度",
|
||||||
"lyricSize": "歌詞のサイズ",
|
"lyricSize": "歌詞のサイズ",
|
||||||
"showLyricProvider": "歌詞の提供元を表示",
|
"showLyricProvider": "歌詞の提供元を表示",
|
||||||
"unsynchronized": "非同期",
|
"unsynchronized": "非同期",
|
||||||
@@ -817,7 +821,9 @@
|
|||||||
"lyricGap": "歌詞の間隔",
|
"lyricGap": "歌詞の間隔",
|
||||||
"dynamicImageBlur": "画像のぼかしサイズ",
|
"dynamicImageBlur": "画像のぼかしサイズ",
|
||||||
"dynamicIsImage": "背景画像を有効にする",
|
"dynamicIsImage": "背景画像を有効にする",
|
||||||
"lyricOffset": "歌詞のオフセット (ms)"
|
"lyricOffset": "歌詞のオフセット (ms)",
|
||||||
|
"lyricOpacityNonActive": "非アクティブな歌詞の不透明度",
|
||||||
|
"lyricScaleNonActive": "非アクティブな歌詞のスケール"
|
||||||
},
|
},
|
||||||
"upNext": "次へ",
|
"upNext": "次へ",
|
||||||
"lyrics": "歌詞",
|
"lyrics": "歌詞",
|
||||||
@@ -1033,7 +1039,8 @@
|
|||||||
"input_skipDuplicates": "重複をスキップ",
|
"input_skipDuplicates": "重複をスキップ",
|
||||||
"input_playlists": "$t(entity.playlist, {\"count\": 2})",
|
"input_playlists": "$t(entity.playlist, {\"count\": 2})",
|
||||||
"create": "$t(entity.playlist, {\"count\": 1}) {{playlist}} を作成する",
|
"create": "$t(entity.playlist, {\"count\": 1}) {{playlist}} を作成する",
|
||||||
"searchOrCreate": "$t(entity.playlist, {\"count\": 2}) を検索するか、入力して新しいプレイリストを作成してください"
|
"searchOrCreate": "$t(entity.playlist, {\"count\": 2}) を検索するか、入力して新しいプレイリストを作成してください",
|
||||||
|
"noneAdded": "$t(entity.playlist, {\"count\": 1}) {{playlist}} にトラックが追加されませんでした"
|
||||||
},
|
},
|
||||||
"updateServer": {
|
"updateServer": {
|
||||||
"title": "サーバーをアップデート",
|
"title": "サーバーをアップデート",
|
||||||
@@ -1341,6 +1348,7 @@
|
|||||||
"systemAudioConsentDecline": "拒否",
|
"systemAudioConsentDecline": "拒否",
|
||||||
"systemAudioConsentTitle": "システムオーディオへのアクセスを許可しますか?",
|
"systemAudioConsentTitle": "システムオーディオへのアクセスを許可しますか?",
|
||||||
"systemAudioCaptureFailed": "キャプチャを開始できませんでした: {{message}}",
|
"systemAudioCaptureFailed": "キャプチャを開始できませんでした: {{message}}",
|
||||||
"systemAudioNoAudioTrack": "音声トラックが返されませんでした。プロンプトが表示されたら、音声キャプチャが有効になっていることを確認してください。"
|
"systemAudioNoAudioTrack": "音声トラックが返されませんでした。プロンプトが表示されたら、音声キャプチャが有効になっていることを確認してください。",
|
||||||
|
"systemAudioExclusiveModeNotSupported": "オーディオ排他モードが有効になっている間は、ビジュアライザーは利用できません。MPV の設定でオーディオ排他モードを無効にしてから、もう一度お試しください。"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -404,11 +404,12 @@ export const createAuthHeader = (): string => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const jfApiClient = (args: {
|
export const jfApiClient = (args: {
|
||||||
|
forceRemoteUrl?: boolean;
|
||||||
server: null | ServerListItemWithCredential;
|
server: null | ServerListItemWithCredential;
|
||||||
signal?: AbortSignal;
|
signal?: AbortSignal;
|
||||||
url?: string;
|
url?: string;
|
||||||
}) => {
|
}) => {
|
||||||
const { server, signal, url } = args;
|
const { forceRemoteUrl, server, signal, url } = args;
|
||||||
|
|
||||||
return initClient(contract, {
|
return initClient(contract, {
|
||||||
api: async ({ body, headers, method, path }) => {
|
api: async ({ body, headers, method, path }) => {
|
||||||
@@ -418,7 +419,7 @@ export const jfApiClient = (args: {
|
|||||||
const { params, path: api } = parsePath(path);
|
const { params, path: api } = parsePath(path);
|
||||||
|
|
||||||
if (server) {
|
if (server) {
|
||||||
const serverUrl = getServerUrl(server);
|
const serverUrl = getServerUrl(server, forceRemoteUrl);
|
||||||
baseUrl = serverUrl;
|
baseUrl = serverUrl;
|
||||||
token = server?.credential;
|
token = server?.credential;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -395,10 +395,15 @@ export const JellyfinController: InternalControllerEndpoint = {
|
|||||||
userId: apiClientProps.server.userId,
|
userId: apiClientProps.server.userId,
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
|
AlbumIds: query.id,
|
||||||
|
EnableUserData: true,
|
||||||
Fields: JF_FIELDS.SONG,
|
Fields: JF_FIELDS.SONG,
|
||||||
IncludeItemTypes: 'Audio',
|
IncludeItemTypes: 'Audio',
|
||||||
ParentId: query.id,
|
Recursive: true,
|
||||||
SortBy: 'ParentIndexNumber,IndexNumber,SortName',
|
SortBy: 'ParentIndexNumber,IndexNumber,SortName',
|
||||||
|
SortOrder: JFSortOrder.ASC,
|
||||||
|
StartIndex: 0,
|
||||||
|
UserId: apiClientProps.server.userId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -928,6 +933,7 @@ export const JellyfinController: InternalControllerEndpoint = {
|
|||||||
Fields: JF_FIELDS.PLAYLIST_LIST,
|
Fields: JF_FIELDS.PLAYLIST_LIST,
|
||||||
IncludeItemTypes: 'Playlist',
|
IncludeItemTypes: 'Playlist',
|
||||||
Limit: query.limit,
|
Limit: query.limit,
|
||||||
|
MediaTypes: 'Audio',
|
||||||
Recursive: true,
|
Recursive: true,
|
||||||
SearchTerm: query.searchTerm,
|
SearchTerm: query.searchTerm,
|
||||||
SortBy: playlistListSortMap.jellyfin[query.sortBy],
|
SortBy: playlistListSortMap.jellyfin[query.sortBy],
|
||||||
|
|||||||
@@ -479,11 +479,12 @@ axiosClient.interceptors.response.use(
|
|||||||
);
|
);
|
||||||
|
|
||||||
export const ndApiClient = (args: {
|
export const ndApiClient = (args: {
|
||||||
|
forceRemoteUrl?: boolean;
|
||||||
server: null | ServerListItemWithCredential;
|
server: null | ServerListItemWithCredential;
|
||||||
signal?: AbortSignal;
|
signal?: AbortSignal;
|
||||||
url?: string;
|
url?: string;
|
||||||
}) => {
|
}) => {
|
||||||
const { server, signal, url } = args;
|
const { forceRemoteUrl, server, signal, url } = args;
|
||||||
|
|
||||||
return initClient(contract, {
|
return initClient(contract, {
|
||||||
api: async ({ body, headers, method, path }) => {
|
api: async ({ body, headers, method, path }) => {
|
||||||
@@ -493,7 +494,7 @@ export const ndApiClient = (args: {
|
|||||||
const { params, path: api } = parsePath(path);
|
const { params, path: api } = parsePath(path);
|
||||||
|
|
||||||
if (server) {
|
if (server) {
|
||||||
const serverUrl = getServerUrl(server);
|
const serverUrl = getServerUrl(server, forceRemoteUrl);
|
||||||
baseUrl = serverUrl ? `${serverUrl}/api` : undefined;
|
baseUrl = serverUrl ? `${serverUrl}/api` : undefined;
|
||||||
token = server?.ndCredential;
|
token = server?.ndCredential;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -428,12 +428,13 @@ const silentlyTransformResponse = (data: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const ssApiClient = (args: {
|
export const ssApiClient = (args: {
|
||||||
|
forceRemoteUrl?: boolean;
|
||||||
server: null | ServerListItemWithCredential;
|
server: null | ServerListItemWithCredential;
|
||||||
signal?: AbortSignal;
|
signal?: AbortSignal;
|
||||||
silent?: boolean;
|
silent?: boolean;
|
||||||
url?: string;
|
url?: string;
|
||||||
}) => {
|
}) => {
|
||||||
const { server, signal, silent, url } = args;
|
const { forceRemoteUrl, server, signal, silent, url } = args;
|
||||||
|
|
||||||
return initClient(contract, {
|
return initClient(contract, {
|
||||||
api: async ({ body, headers, method, path, rawQuery }) => {
|
api: async ({ body, headers, method, path, rawQuery }) => {
|
||||||
@@ -443,7 +444,7 @@ export const ssApiClient = (args: {
|
|||||||
const { params, path: api } = parsePath(path);
|
const { params, path: api } = parsePath(path);
|
||||||
|
|
||||||
if (server) {
|
if (server) {
|
||||||
const serverUrl = getServerUrl(server);
|
const serverUrl = getServerUrl(server, forceRemoteUrl);
|
||||||
baseUrl = serverUrl ? `${serverUrl}/rest` : undefined;
|
baseUrl = serverUrl ? `${serverUrl}/rest` : undefined;
|
||||||
const token = server.credential;
|
const token = server.credential;
|
||||||
const params = token.split(/&?\w=/gm);
|
const params = token.split(/&?\w=/gm);
|
||||||
|
|||||||
@@ -284,7 +284,10 @@ export const useDiscordRpc = () => {
|
|||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
const info = await api.controller.getAlbumInfo({
|
const info = await api.controller.getAlbumInfo({
|
||||||
apiClientProps: { serverId: song._serverId },
|
apiClientProps: {
|
||||||
|
forceRemoteUrl: true,
|
||||||
|
serverId: song._serverId,
|
||||||
|
},
|
||||||
query: { id: song.albumId },
|
query: { id: song.albumId },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,8 @@ import { Link, NavLink, useNavigate } from 'react-router';
|
|||||||
|
|
||||||
import styles from './collapsed-sidebar.module.css';
|
import styles from './collapsed-sidebar.module.css';
|
||||||
|
|
||||||
import JellyfinLogo from '/@/renderer/features/servers/assets/jellyfin.png';
|
|
||||||
import NavidromeLogo from '/@/renderer/features/servers/assets/navidrome.png';
|
|
||||||
import OpenSubsonicLogo from '/@/renderer/features/servers/assets/opensubsonic.png';
|
|
||||||
import { CollapsedSidebarButton } from '/@/renderer/features/sidebar/components/collapsed-sidebar-button';
|
import { CollapsedSidebarButton } from '/@/renderer/features/sidebar/components/collapsed-sidebar-button';
|
||||||
import { CollapsedSidebarItem } from '/@/renderer/features/sidebar/components/collapsed-sidebar-item';
|
import { CollapsedSidebarItem } from '/@/renderer/features/sidebar/components/collapsed-sidebar-item';
|
||||||
import { ServerSelectorItems } from '/@/renderer/features/sidebar/components/server-selector-items';
|
|
||||||
import { getCollectionTo } from '/@/renderer/features/sidebar/components/sidebar-collection-list';
|
import { getCollectionTo } from '/@/renderer/features/sidebar/components/sidebar-collection-list';
|
||||||
import { SidebarIcon } from '/@/renderer/features/sidebar/components/sidebar-icon';
|
import { SidebarIcon } from '/@/renderer/features/sidebar/components/sidebar-icon';
|
||||||
import { AppMenu } from '/@/renderer/features/titlebar/components/app-menu';
|
import { AppMenu } from '/@/renderer/features/titlebar/components/app-menu';
|
||||||
@@ -19,7 +15,6 @@ import { AppRoute } from '/@/renderer/router/routes';
|
|||||||
import {
|
import {
|
||||||
SidebarItemType,
|
SidebarItemType,
|
||||||
useCollections,
|
useCollections,
|
||||||
useCurrentServer,
|
|
||||||
useSidebarCollapsedNavigation,
|
useSidebarCollapsedNavigation,
|
||||||
useSidebarItems,
|
useSidebarItems,
|
||||||
useWindowSettings,
|
useWindowSettings,
|
||||||
@@ -30,7 +25,7 @@ import { Group } from '/@/shared/components/group/group';
|
|||||||
import { Icon } from '/@/shared/components/icon/icon';
|
import { Icon } from '/@/shared/components/icon/icon';
|
||||||
import { ScrollArea } from '/@/shared/components/scroll-area/scroll-area';
|
import { ScrollArea } from '/@/shared/components/scroll-area/scroll-area';
|
||||||
import { Stack } from '/@/shared/components/stack/stack';
|
import { Stack } from '/@/shared/components/stack/stack';
|
||||||
import { LibraryItem, ServerType } from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain-types';
|
||||||
import { Platform } from '/@/shared/types/types';
|
import { Platform } from '/@/shared/types/types';
|
||||||
|
|
||||||
export const CollapsedSidebar = () => {
|
export const CollapsedSidebar = () => {
|
||||||
@@ -40,8 +35,6 @@ export const CollapsedSidebar = () => {
|
|||||||
const { windowBarStyle } = useWindowSettings();
|
const { windowBarStyle } = useWindowSettings();
|
||||||
const sidebarCollapsedNavigation = useSidebarCollapsedNavigation();
|
const sidebarCollapsedNavigation = useSidebarCollapsedNavigation();
|
||||||
const sidebarItems = useSidebarItems();
|
const sidebarItems = useSidebarItems();
|
||||||
const currentServer = useCurrentServer();
|
|
||||||
|
|
||||||
const translatedSidebarItemMap = useMemo(
|
const translatedSidebarItemMap = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
Albums: t('page.sidebar.albums', { postProcess: 'titleCase' }),
|
Albums: t('page.sidebar.albums', { postProcess: 'titleCase' }),
|
||||||
@@ -174,38 +167,6 @@ export const CollapsedSidebar = () => {
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
)}
|
)}
|
||||||
{currentServer && (
|
|
||||||
<DropdownMenu offset={0} position="right-end" width={240}>
|
|
||||||
<DropdownMenu.Target>
|
|
||||||
<CollapsedSidebarItem
|
|
||||||
activeIcon={null}
|
|
||||||
component={Flex}
|
|
||||||
icon={
|
|
||||||
<img
|
|
||||||
className={styles.serverIcon}
|
|
||||||
src={
|
|
||||||
currentServer.type === ServerType.NAVIDROME
|
|
||||||
? NavidromeLogo
|
|
||||||
: currentServer.type === ServerType.JELLYFIN
|
|
||||||
? JellyfinLogo
|
|
||||||
: OpenSubsonicLogo
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={''}
|
|
||||||
py="md"
|
|
||||||
style={{
|
|
||||||
cursor: 'pointer',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</DropdownMenu.Target>
|
|
||||||
<DropdownMenu.Dropdown>
|
|
||||||
<ScrollArea style={{ maxHeight: '95vh' }}>
|
|
||||||
<ServerSelectorItems />
|
|
||||||
</ScrollArea>
|
|
||||||
</DropdownMenu.Dropdown>
|
|
||||||
</DropdownMenu>
|
|
||||||
)}
|
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ export const NDSongQueryFields = [
|
|||||||
{ label: 'Artist Date Rated', type: 'date', value: 'artistdaterated' },
|
{ label: 'Artist Date Rated', type: 'date', value: 'artistdaterated' },
|
||||||
{ label: 'Artist Is Favorite', type: 'boolean', value: 'artistloved' },
|
{ label: 'Artist Is Favorite', type: 'boolean', value: 'artistloved' },
|
||||||
{ label: 'Artist Play Count', type: 'number', value: 'artistplaycount' },
|
{ label: 'Artist Play Count', type: 'number', value: 'artistplaycount' },
|
||||||
|
{ label: 'Artist Rating', type: 'number', value: 'artistrating' },
|
||||||
{ label: 'Artists', type: 'string', value: 'artists' },
|
{ label: 'Artists', type: 'string', value: 'artists' },
|
||||||
{ label: 'ASIN', type: 'string', value: 'asin' },
|
{ label: 'ASIN', type: 'string', value: 'asin' },
|
||||||
{ label: 'Average Rating', type: 'number', value: 'averagerating' },
|
{ label: 'Average Rating', type: 'number', value: 'averagerating' },
|
||||||
@@ -158,7 +159,7 @@ export const NDSongQueryFields = [
|
|||||||
{ label: 'MusicBrainz Work Id', type: 'string', value: 'musicbrainz_workid' },
|
{ label: 'MusicBrainz Work Id', type: 'string', value: 'musicbrainz_workid' },
|
||||||
{ label: 'Name', type: 'string', value: 'title' },
|
{ label: 'Name', type: 'string', value: 'title' },
|
||||||
{ label: 'Original Date', type: 'date', value: 'originaldate' },
|
{ label: 'Original Date', type: 'date', value: 'originaldate' },
|
||||||
{ label: 'Original Year', type: 'date', value: 'originalyear' },
|
{ label: 'Original Year', type: 'number', value: 'originalyear' },
|
||||||
{ label: 'Performer', type: 'string', value: 'performer' },
|
{ label: 'Performer', type: 'string', value: 'performer' },
|
||||||
{ label: 'Play Count', type: 'number', value: 'playcount' },
|
{ label: 'Play Count', type: 'number', value: 'playcount' },
|
||||||
{ label: 'Playlist', type: 'playlist', value: 'id' },
|
{ label: 'Playlist', type: 'playlist', value: 'id' },
|
||||||
@@ -178,18 +179,18 @@ export const NDSongQueryFields = [
|
|||||||
{ label: 'ReplayGain Track Peak', type: 'number', value: 'replaygain_track_peak' },
|
{ label: 'ReplayGain Track Peak', type: 'number', value: 'replaygain_track_peak' },
|
||||||
{ label: 'Remixer', type: 'string', value: 'remixer' },
|
{ label: 'Remixer', type: 'string', value: 'remixer' },
|
||||||
{ label: 'Script', type: 'string', value: 'script' },
|
{ label: 'Script', type: 'string', value: 'script' },
|
||||||
{ label: 'Sample Rate', type: 'number', value: 'sampleRate' },
|
{ label: 'Sample Rate', type: 'number', value: 'samplerate' },
|
||||||
{ label: 'Size', type: 'number', value: 'size' },
|
{ label: 'Size', type: 'number', value: 'size' },
|
||||||
{ label: 'Sort Album', type: 'string', value: 'albumsort' },
|
{ label: 'Sort Album', type: 'string', value: 'sortalbum' },
|
||||||
{ label: 'Sort Album Artist', type: 'string', value: 'albumartistsort' },
|
{ label: 'Sort Album Artist', type: 'string', value: 'sortalbumartist' },
|
||||||
{ label: 'Sort Album Artists', type: 'string', value: 'albumartistssort' },
|
{ label: 'Sort Album Artists', type: 'string', value: 'albumartistssort' },
|
||||||
{ label: 'Sort Artist', type: 'string', value: 'artistsort' },
|
{ label: 'Sort Artist', type: 'string', value: 'sortartist' },
|
||||||
{ label: 'Sort Artists', type: 'string', value: 'artistssort' },
|
{ label: 'Sort Artists', type: 'string', value: 'artistssort' },
|
||||||
{ label: 'Sort Composer', type: 'string', value: 'composersort' },
|
{ label: 'Sort Composer', type: 'string', value: 'composersort' },
|
||||||
{ label: 'Sort Lyricist', type: 'string', value: 'lyricistsort' },
|
{ label: 'Sort Lyricist', type: 'string', value: 'lyricistsort' },
|
||||||
{ label: 'Sort Name', type: 'string', value: 'titlesort' },
|
{ label: 'Sort Name', type: 'string', value: 'sorttitle' },
|
||||||
{ label: 'Subtitle', type: 'string', value: 'subtitle' },
|
{ label: 'Subtitle', type: 'string', value: 'subtitle' },
|
||||||
{ label: 'Track Number', type: 'number', value: 'track' },
|
{ label: 'Track Number', type: 'number', value: 'tracknumber' },
|
||||||
{ label: 'Track Total', type: 'number', value: 'tracktotal' },
|
{ label: 'Track Total', type: 'number', value: 'tracktotal' },
|
||||||
{ label: 'Website', type: 'string', value: 'website' },
|
{ label: 'Website', type: 'string', value: 'website' },
|
||||||
{ label: 'Work', type: 'string', value: 'work' },
|
{ label: 'Work', type: 'string', value: 'work' },
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ export const sortSongList = (songs: Song[], sortBy: SongListSort, sortOrder: Sor
|
|||||||
case SongListSort.YEAR:
|
case SongListSort.YEAR:
|
||||||
results = orderBy(
|
results = orderBy(
|
||||||
results,
|
results,
|
||||||
['releaseYear', (v) => v.album?.toLowerCase(), 'discNumber', 'track'],
|
['releaseYear', (v) => v.album?.toLowerCase(), 'discNumber', 'trackNumber'],
|
||||||
[order, order, order, order],
|
[order, order, order, order],
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -421,6 +421,7 @@ type ApiContext = {
|
|||||||
|
|
||||||
type BaseEndpointArgs = {
|
type BaseEndpointArgs = {
|
||||||
apiClientProps: {
|
apiClientProps: {
|
||||||
|
forceRemoteUrl?: boolean;
|
||||||
server?: null | ServerListItemWithCredential;
|
server?: null | ServerListItemWithCredential;
|
||||||
serverId: string;
|
serverId: string;
|
||||||
signal?: AbortSignal;
|
signal?: AbortSignal;
|
||||||
|
|||||||
Reference in New Issue
Block a user