mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-15 21:16:17 +02:00
fix the loading state on listquery add to queue
This commit is contained in:
@@ -358,7 +358,6 @@
|
||||
},
|
||||
"moveToNext": "přesunout na další",
|
||||
"downloadStarted": "spuštěno stahování {{count}} položek",
|
||||
"largeFetch": "tato akce se pokusí načíst {{count}} položek z vašeho serveru",
|
||||
"moveItems": "přesunout položky",
|
||||
"shuffle": "náhodně",
|
||||
"shuffleAll": "vše náhodně",
|
||||
@@ -913,7 +912,7 @@
|
||||
},
|
||||
"largeFetchConfirmation": {
|
||||
"title": "přidat položky do fronty",
|
||||
"description": "Tento požadavek se pokusí načíst {{count}} položek ze serveru"
|
||||
"description": "Tato akce přidá všechny položky v aktuálně filtrovaném zobrazení"
|
||||
},
|
||||
"shuffleAll": {
|
||||
"title": "přehrát náhodně",
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
},
|
||||
"moveToNext": "Als nächstes",
|
||||
"downloadStarted": "Download von {{count}} Elementen gestartet",
|
||||
"largeFetch": "Diese Aktion wird versuchen {{count}} Elemente von Deinem Server zu laden",
|
||||
"moveItems": "Elemente verschieben",
|
||||
"shuffle": "Zufällig wiedergeben",
|
||||
"shuffleAll": "Alle zufällig wiedergeben",
|
||||
@@ -294,7 +293,7 @@
|
||||
},
|
||||
"largeFetchConfirmation": {
|
||||
"title": "Elemente der Warteschlange hinzufügen",
|
||||
"description": "Diese Anfrage wird versuchen {{count}} Elemente vom Server abzurufen"
|
||||
"description": "Diese Aktion fügt alle Elemente in der aktuell gefilterten Ansicht hinzu"
|
||||
},
|
||||
"shuffleAll": {
|
||||
"title": "Zufallswiedergabe",
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
"downloadStarted": "started download of {{count}} items",
|
||||
"editPlaylist": "edit $t(entity.playlist_one)",
|
||||
"goToPage": "go to page",
|
||||
"largeFetch": "this action will attempt to fetch {{count}} items from your server",
|
||||
"moveToNext": "move to next",
|
||||
"moveToBottom": "move to bottom",
|
||||
"moveToTop": "move to top",
|
||||
@@ -297,7 +296,7 @@
|
||||
},
|
||||
"largeFetchConfirmation": {
|
||||
"title": "add items to the queue",
|
||||
"description": "This request will attempt to fetch {{count}} items from the server"
|
||||
"description": "This action will add all items in the current filtered view"
|
||||
},
|
||||
"addToPlaylist": {
|
||||
"create": "create $t(entity.playlist_one) {{playlist}}",
|
||||
|
||||
@@ -358,7 +358,6 @@
|
||||
},
|
||||
"moveToNext": "pasar al siguiente",
|
||||
"downloadStarted": "Iniciada descarga de {{count}} elementos",
|
||||
"largeFetch": "Esta acción intentará obtener {{count}} elementos de tu servidor",
|
||||
"moveItems": "Mover elementos",
|
||||
"shuffle": "Mezclar",
|
||||
"shuffleAll": "Mezclar todo",
|
||||
@@ -813,7 +812,7 @@
|
||||
},
|
||||
"largeFetchConfirmation": {
|
||||
"title": "Añadir elementos a la cola",
|
||||
"description": "Esta petición intentará obtener {{count}} elementos del servidor"
|
||||
"description": "Esta acción agregará todos los elementos en la vista filtrada actual"
|
||||
},
|
||||
"shuffleAll": {
|
||||
"title": "Reproducir aleatorio",
|
||||
|
||||
@@ -61,7 +61,6 @@
|
||||
},
|
||||
"moveToNext": "passer au suivant",
|
||||
"downloadStarted": "téléchargement de {{count}} éléments en cours",
|
||||
"largeFetch": "cette action tentera de récupérer {{count}} éléments depuis votre serveur.",
|
||||
"moveItems": "déplacer les entrées",
|
||||
"shuffle": "mélanger",
|
||||
"shuffleAll": "mélanger tout",
|
||||
@@ -807,7 +806,7 @@
|
||||
},
|
||||
"largeFetchConfirmation": {
|
||||
"title": "ajouter des entrées à la file d'attente",
|
||||
"description": "cette requête tentera de récupérer {{count}} éléments depuis le serveur"
|
||||
"description": "Cette action ajoutera tous les éléments dans la vue filtrée actuelle"
|
||||
},
|
||||
"shuffleAll": {
|
||||
"title": "jouer aléatoirement",
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
"addToPlaylist": "hozzáadás lejátszási listához: $t(entity.playlist_one)",
|
||||
"refresh": "$t(common.refresh)",
|
||||
"downloadStarted": "megkezdődött {{count}} elem letöltése",
|
||||
"largeFetch": "ez a művelet {{count}} hálózati kérést fog küldeni a szerverednek",
|
||||
"moveItems": "elemek mozgatása",
|
||||
"shuffle": "keverés",
|
||||
"shuffleAll": "összes keverése",
|
||||
@@ -325,7 +324,7 @@
|
||||
},
|
||||
"largeFetchConfirmation": {
|
||||
"title": "műsorlistához ad",
|
||||
"description": "Ez a kérés megpróbál letölteni {{count}} elemet a szerverről"
|
||||
"description": "Ez a művelet hozzáadja az összes elemet az aktuális szűrt nézetben"
|
||||
},
|
||||
"shuffleAll": {
|
||||
"title": "véletlenszerű lejátszás",
|
||||
|
||||
@@ -324,7 +324,6 @@
|
||||
},
|
||||
"moveToNext": "次",
|
||||
"downloadStarted": "{{count}} 曲のダウンロードを開始しました",
|
||||
"largeFetch": "この操作により、サーバーに対して {{count}} 回のネットワークリクエストが送信されます",
|
||||
"moveItems": "曲を移動",
|
||||
"shuffle": "シャッフル",
|
||||
"shuffleAll": "すべてシャッフル",
|
||||
@@ -807,7 +806,7 @@
|
||||
},
|
||||
"largeFetchConfirmation": {
|
||||
"title": "キューにアイテムを追加する",
|
||||
"description": "このリクエストはサーバーから {{count}} 個のアイテムを取得しようと試みます"
|
||||
"description": "このアクションは、現在のフィルターされたビュー内のすべてのアイテムを追加します"
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
},
|
||||
"moveToNext": "ga naar volgende",
|
||||
"downloadStarted": "begonnen met downloaden van {{count}} items",
|
||||
"largeFetch": "deze actie zal {{count}} netwerkverzoeken naar je server sturen",
|
||||
"moveItems": "verplaats items",
|
||||
"shuffle": "shuffle",
|
||||
"shuffleAll": "shuffle alles",
|
||||
@@ -557,7 +556,7 @@
|
||||
},
|
||||
"largeFetchConfirmation": {
|
||||
"title": "items toevoegen aan de wachtrij",
|
||||
"description": "Dit verzoek zal proberen {{count}} items van de server op te halen"
|
||||
"description": "Deze actie voegt alle items in de huidige gefilterde weergave toe"
|
||||
},
|
||||
"shuffleAll": {
|
||||
"title": "willekeurig afspelen",
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
},
|
||||
"moveToNext": "przesuń na następne",
|
||||
"downloadStarted": "rozpoczęto pobieranie {{count}} elementów",
|
||||
"largeFetch": "ta akcja wykona {{count}} żądań sieciowych do twojego serwera",
|
||||
"moveItems": "przenieś elementy",
|
||||
"shuffle": "odtwarzaj losowo",
|
||||
"shuffleAll": "odtwarzaj wszystkie losowo",
|
||||
@@ -346,7 +345,7 @@
|
||||
},
|
||||
"largeFetchConfirmation": {
|
||||
"title": "dodaj elementy do kolejki",
|
||||
"description": "To żądanie spróbuje pobrać {{count}} elementów z serwera"
|
||||
"description": "Ta akcja doda wszystkie elementy w aktualnie przefiltrowanym widoku"
|
||||
},
|
||||
"shuffleAll": {
|
||||
"title": "odtwarzaj losowo",
|
||||
|
||||
@@ -778,7 +778,6 @@
|
||||
"musicbrainz": "在MusicBrainz開啟"
|
||||
},
|
||||
"downloadStarted": "已開始下載 {{count}} 項內容",
|
||||
"largeFetch": "這項操作將會嘗試從您的伺服器擷取 {{count}} 個項目",
|
||||
"moveItems": "移動項目",
|
||||
"shuffle": "隨機播放",
|
||||
"shuffleAll": "全部隨機播放",
|
||||
@@ -925,7 +924,7 @@
|
||||
},
|
||||
"largeFetchConfirmation": {
|
||||
"title": "將項目加入佇列",
|
||||
"description": "這個請求將嘗試從伺服器擷取 {{count}} 個項目"
|
||||
"description": "此操作將新增目前篩選檢視中的所有項目"
|
||||
},
|
||||
"shuffleAll": {
|
||||
"title": "隨機播放",
|
||||
|
||||
@@ -266,7 +266,11 @@ export const queryKeys: Record<
|
||||
list: (serverId: string) => [serverId, 'musicFolders', 'list'] as const,
|
||||
},
|
||||
player: {
|
||||
fetch: () => {
|
||||
fetch: (meta?: any) => {
|
||||
if (meta) {
|
||||
return ['player', 'fetch', meta] as const;
|
||||
}
|
||||
|
||||
return ['player', 'fetch'] as const;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -151,62 +151,57 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
const queryClient = useQueryClient();
|
||||
const storeActions = usePlayerActions();
|
||||
const timeoutIds = useRef<null | Record<string, ReturnType<typeof setTimeout>>>({});
|
||||
const queueFetchConfirmThreshold = 100;
|
||||
|
||||
const [doNotShowAgain, setDoNotShowAgain] = useLocalStorage({
|
||||
defaultValue: false,
|
||||
key: 'large_fetch_confirmation',
|
||||
});
|
||||
|
||||
const confirmLargeFetch = useCallback(
|
||||
(itemCount: number): Promise<boolean> => {
|
||||
if (doNotShowAgain) {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
const confirmLargeFetch = useCallback((): Promise<boolean> => {
|
||||
if (doNotShowAgain) {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
openModal({
|
||||
children: (
|
||||
<ConfirmModal
|
||||
labels={{
|
||||
cancel: t('common.cancel', { postProcess: 'titleCase' }),
|
||||
confirm: t('common.confirm', { postProcess: 'titleCase' }),
|
||||
}}
|
||||
onCancel={() => {
|
||||
resolve(false);
|
||||
closeAllModals();
|
||||
}}
|
||||
onConfirm={() => {
|
||||
resolve(true);
|
||||
closeAllModals();
|
||||
}}
|
||||
>
|
||||
<Stack>
|
||||
<Text>
|
||||
{t('action.largeFetch', {
|
||||
count: itemCount,
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
</Text>
|
||||
<Checkbox
|
||||
label={t('common.doNotShowAgain', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
onChange={(event) => {
|
||||
setDoNotShowAgain(event.currentTarget.checked);
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
</ConfirmModal>
|
||||
),
|
||||
title: t('common.areYouSure', {
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
});
|
||||
return new Promise((resolve) => {
|
||||
openModal({
|
||||
children: (
|
||||
<ConfirmModal
|
||||
labels={{
|
||||
cancel: t('common.cancel', { postProcess: 'titleCase' }),
|
||||
confirm: t('common.confirm', { postProcess: 'titleCase' }),
|
||||
}}
|
||||
onCancel={() => {
|
||||
resolve(false);
|
||||
closeAllModals();
|
||||
}}
|
||||
onConfirm={() => {
|
||||
resolve(true);
|
||||
closeAllModals();
|
||||
}}
|
||||
>
|
||||
<Stack>
|
||||
<Text>
|
||||
{t('form.largeFetchConfirmation.description', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
</Text>
|
||||
<Checkbox
|
||||
label={t('common.doNotShowAgain', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
onChange={(event) => {
|
||||
setDoNotShowAgain(event.currentTarget.checked);
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
</ConfirmModal>
|
||||
),
|
||||
title: t('form.largeFetchConfirmation.title', {
|
||||
postProcess: 'sentenceCase',
|
||||
}),
|
||||
});
|
||||
},
|
||||
[doNotShowAgain, setDoNotShowAgain, t],
|
||||
);
|
||||
});
|
||||
}, [doNotShowAgain, setDoNotShowAgain, t]);
|
||||
|
||||
const addToQueueByData = useCallback(
|
||||
(data: Song[], type: AddToQueueType, playSongId?: string) => {
|
||||
@@ -248,8 +243,8 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
type: AddToQueueType,
|
||||
skipConfirmation?: boolean,
|
||||
) => {
|
||||
if (!skipConfirmation && id.length > queueFetchConfirmThreshold) {
|
||||
const confirmed = await confirmLargeFetch(id.length);
|
||||
if (!skipConfirmation) {
|
||||
const confirmed = await confirmLargeFetch();
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
@@ -271,6 +266,11 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
exact: false,
|
||||
queryKey: getRootQueryKey(itemType, serverId),
|
||||
});
|
||||
|
||||
queryClient.cancelQueries({
|
||||
exact: false,
|
||||
queryKey: queryKeys.player.fetch(),
|
||||
});
|
||||
},
|
||||
title: t('player.playbackFetchInProgress', {
|
||||
postProcess: 'sentenceCase',
|
||||
@@ -331,7 +331,7 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
});
|
||||
}
|
||||
},
|
||||
[confirmLargeFetch, queueFetchConfirmThreshold, queryClient, storeActions, t],
|
||||
[confirmLargeFetch, queryClient, storeActions, t],
|
||||
);
|
||||
|
||||
const addToQueueByListQuery = useCallback(
|
||||
@@ -388,6 +388,7 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
serverId,
|
||||
}),
|
||||
gcTime: 0,
|
||||
queryKey: queryKeys.player.fetch(),
|
||||
staleTime: 0,
|
||||
})) as number;
|
||||
totalCount = countResult || 0;
|
||||
@@ -395,21 +396,9 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
const allResults: Song[] | string[] = [];
|
||||
const pageSize = 500;
|
||||
|
||||
// Calculate the number of fetches needed
|
||||
let numberOfFetches = 0;
|
||||
if (itemType === LibraryItem.SONG) {
|
||||
// For songs, the number of fetches is based on pagination
|
||||
numberOfFetches = Math.ceil(totalCount / pageSize);
|
||||
} else {
|
||||
const paginationFetches = Math.ceil(totalCount / pageSize);
|
||||
numberOfFetches = paginationFetches + totalCount;
|
||||
}
|
||||
|
||||
if (numberOfFetches > queueFetchConfirmThreshold) {
|
||||
const confirmed = await confirmLargeFetch(numberOfFetches);
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
const confirmed = await confirmLargeFetch();
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Start timeout only after confirmation (if needed)
|
||||
@@ -433,6 +422,11 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
exact: false,
|
||||
queryKey: getRootQueryKey(itemType, serverId),
|
||||
});
|
||||
|
||||
queryClient.cancelQueries({
|
||||
exact: false,
|
||||
queryKey: queryKeys.player.fetch(),
|
||||
});
|
||||
},
|
||||
title: t('player.playbackFetchInProgress', {
|
||||
postProcess: 'sentenceCase',
|
||||
@@ -455,6 +449,7 @@ export const PlayerProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
serverId,
|
||||
}),
|
||||
gcTime: 0,
|
||||
queryKey: queryKeys.player.fetch({ startIndex }),
|
||||
staleTime: 0,
|
||||
})) as { items: any[] };
|
||||
|
||||
@@ -1006,6 +1001,7 @@ export async function fetchSongsByItemType(
|
||||
}
|
||||
|
||||
export const useIsPlayerFetching = () => {
|
||||
const fetcherCount = useIsFetching({ queryKey: queryKeys.player.fetch() });
|
||||
return fetcherCount > 0;
|
||||
const playerFetchCount = useIsFetching({ queryKey: queryKeys.player.fetch() });
|
||||
|
||||
return playerFetchCount > 0;
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import { CSSProperties, memo, ReactNode, useCallback } from 'react';
|
||||
|
||||
import styles from './library-header-bar.module.css';
|
||||
|
||||
import { usePlayer } from '/@/renderer/features/player/context/player-context';
|
||||
import { useIsPlayerFetching, usePlayer } from '/@/renderer/features/player/context/player-context';
|
||||
import { DefaultPlayButton } from '/@/renderer/features/shared/components/play-button';
|
||||
import { PlayButtonGroup } from '/@/renderer/features/shared/components/play-button-group';
|
||||
import { useCurrentServerId } from '/@/renderer/store';
|
||||
@@ -86,10 +86,13 @@ const HeaderPlayButton = ({
|
||||
});
|
||||
}, [serverId, handlePlay]);
|
||||
|
||||
const isPlayerFetching = useIsPlayerFetching();
|
||||
|
||||
return (
|
||||
<div className={styles.playButtonContainer}>
|
||||
<DefaultPlayButton
|
||||
className={className}
|
||||
loading={isPlayerFetching}
|
||||
onClick={openPlayTypeModal}
|
||||
variant={variant}
|
||||
{...props}
|
||||
|
||||
Reference in New Issue
Block a user