add scan listener and query invalidation on tag editor save

This commit is contained in:
jeffvli
2026-07-19 21:03:13 -07:00
parent e62242824d
commit 173efa9bfd
17 changed files with 326 additions and 5 deletions
@@ -3,6 +3,7 @@ import { useNavigate } from 'react-router';
import styles from './action-bar.module.css';
import { useScanStatus } from '/@/renderer/features/shared/hooks/use-scan-status';
import { AppMenu } from '/@/renderer/features/titlebar/components/app-menu';
import { useCommandPalette } from '/@/renderer/store';
import { Button } from '/@/shared/components/button/button';
@@ -15,6 +16,7 @@ import { TextInput } from '/@/shared/components/text-input/text-input';
export const ActionBar = () => {
const { t } = useTranslation();
const { open } = useCommandPalette();
const { isScanning } = useScanStatus();
return (
<div className={styles.container}>
@@ -49,7 +51,11 @@ export const ActionBar = () => {
<DropdownMenu position="bottom-start">
<DropdownMenu.Target>
<Button p="0">
<Icon icon="menu" size="lg" />
<Icon
animate={isScanning ? 'spin' : undefined}
icon={isScanning ? 'spinner' : 'menu'}
size="lg"
/>
</Button>
</DropdownMenu.Target>
<DropdownMenu.Dropdown>
@@ -6,6 +6,7 @@ import { Link, NavLink, useNavigate } from 'react-router';
import styles from './collapsed-sidebar.module.css';
import { useScanStatus } from '/@/renderer/features/shared/hooks/use-scan-status';
import { CollapsedSidebarButton } from '/@/renderer/features/sidebar/components/collapsed-sidebar-button';
import { CollapsedSidebarItem } from '/@/renderer/features/sidebar/components/collapsed-sidebar-item';
import { getCollectionTo } from '/@/renderer/features/sidebar/components/sidebar-collection-list';
@@ -35,6 +36,8 @@ export const CollapsedSidebar = () => {
const { windowBarStyle } = useWindowSettings();
const sidebarCollapsedNavigation = useSidebarCollapsedNavigation();
const sidebarItems = useSidebarItems();
const { isScanning } = useScanStatus();
const translatedSidebarItemMap = useMemo(
() => ({
Albums: t('page.sidebar.albums'),
@@ -94,7 +97,14 @@ export const CollapsedSidebar = () => {
<CollapsedSidebarItem
activeIcon={null}
component={Flex}
icon={<Icon fill="muted" icon="menu" size="3xl" />}
icon={
<Icon
animate={isScanning ? 'spin' : undefined}
fill="muted"
icon={isScanning ? 'spinner' : 'menu'}
size="3xl"
/>
}
label={t('common.menu')}
style={{
cursor: 'pointer',
@@ -7,6 +7,7 @@ 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 { sharedQueries } from '/@/renderer/features/shared/api/shared-api';
import { useScanStatus } from '/@/renderer/features/shared/hooks/use-scan-status';
import { ServerSelectorItems } from '/@/renderer/features/sidebar/components/server-selector-items';
import { useCurrentServer } from '/@/renderer/store';
import { hasFeature } from '/@/shared/api/utils';
@@ -23,6 +24,7 @@ import { ServerFeature } from '/@/shared/types/features-types';
export const ServerSelector = () => {
const { t } = useTranslation();
const currentServer = useCurrentServer();
const { data: scanStatus, isScanning, isWatching } = useScanStatus();
const { data: musicFolders } = useQuery(
currentServer
@@ -54,6 +56,19 @@ export const ServerSelector = () => {
return selectedMusicFolders[0].name;
})();
const scanProgressParts: string[] = [];
if (scanStatus?.count && scanStatus.count > 0) {
scanProgressParts.push(t('common.scanItemCount', { count: scanStatus.count }));
}
if (scanStatus?.folderCount && scanStatus.folderCount > 0) {
scanProgressParts.push(t('common.scanFolderCount', { count: scanStatus.folderCount }));
}
const scanStatusText =
isWatching && isScanning
? [t('common.scanningLibrary'), ...scanProgressParts].filter(Boolean).join(' · ')
: null;
const logo =
currentServer.type === ServerType.NAVIDROME
? NavidromeLogo
@@ -75,6 +90,11 @@ export const ServerSelector = () => {
<Text isMuted size="xs" truncate>
{musicFolderDisplayText}
</Text>
{scanStatusText && (
<Text isMuted size="xs" truncate>
{scanStatusText}
</Text>
)}
</Stack>
<Icon icon="ellipsisVertical" size="sm" />
</Group>