mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-07 04:20:12 +02:00
optimize excessive layout re-rendering due to react-router
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useEffect, useMemo, useRef } from 'react';
|
||||
import { useNavigate } from 'react-router';
|
||||
|
||||
import { getTitlePath } from '/@/renderer/components/item-list/helpers/get-title-path';
|
||||
@@ -32,6 +32,11 @@ const itemTypeMapping = {
|
||||
export const useDefaultItemListControls = (args?: UseDefaultItemListControlsArgs) => {
|
||||
const player = usePlayer();
|
||||
const navigate = useNavigate();
|
||||
const navigateRef = useRef(navigate);
|
||||
|
||||
useEffect(() => {
|
||||
navigateRef.current = navigate;
|
||||
}, [navigate]);
|
||||
|
||||
const { onColumnReordered, onColumnResized, overrides } = args || {};
|
||||
|
||||
@@ -202,7 +207,7 @@ export const useDefaultItemListControls = (args?: UseDefaultItemListControlsArgs
|
||||
) {
|
||||
const path = getTitlePath(itemType, item.id);
|
||||
if (path) {
|
||||
navigate(path, { state: { item } });
|
||||
navigateRef.current(path, { state: { item } });
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -330,7 +335,7 @@ export const useDefaultItemListControls = (args?: UseDefaultItemListControlsArgs
|
||||
|
||||
...overrides,
|
||||
};
|
||||
}, [onColumnReordered, onColumnResized, overrides, navigate, player]);
|
||||
}, [onColumnReordered, onColumnResized, overrides, player]);
|
||||
|
||||
return controls;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRef, useState } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { ItemListHandle } from '/@/renderer/components/item-list/types';
|
||||
import { NowPlayingHeader } from '/@/renderer/features/now-playing/components/now-playing-header';
|
||||
@@ -7,11 +7,23 @@ import { PlayQueueListControls } from '/@/renderer/features/now-playing/componen
|
||||
import { AnimatedPage } from '/@/renderer/features/shared/components/animated-page';
|
||||
import { LibraryContainer } from '/@/renderer/features/shared/components/library-container';
|
||||
import { PageErrorBoundary } from '/@/renderer/features/shared/components/page-error-boundary';
|
||||
import { useAppStoreActions } from '/@/renderer/store';
|
||||
import { ItemListKey } from '/@/shared/types/types';
|
||||
|
||||
const NowPlayingRoute = () => {
|
||||
const queueRef = useRef<ItemListHandle | null>(null);
|
||||
const [search, setSearch] = useState<string | undefined>(undefined);
|
||||
const { setSideBar } = useAppStoreActions();
|
||||
|
||||
useEffect(() => {
|
||||
// On page enter, set rightExpanded to false
|
||||
setSideBar({ rightExpanded: false });
|
||||
|
||||
return () => {
|
||||
// On page exit, set rightExpanded to true
|
||||
setSideBar({ rightExpanded: true });
|
||||
};
|
||||
}, [setSideBar]);
|
||||
|
||||
return (
|
||||
<AnimatedPage>
|
||||
|
||||
@@ -14,7 +14,6 @@ import { TextInput } from '/@/shared/components/text-input/text-input';
|
||||
|
||||
export const ActionBar = () => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const { open } = useCommandPalette();
|
||||
|
||||
return (
|
||||
@@ -50,15 +49,25 @@ export const ActionBar = () => {
|
||||
<AppMenu />
|
||||
</DropdownMenu.Dropdown>
|
||||
</DropdownMenu>
|
||||
<Button onClick={() => navigate(-1)} p="0.5rem">
|
||||
<Icon icon="arrowLeftS" size="lg" />
|
||||
</Button>
|
||||
<Button onClick={() => navigate(1)} p="0.5rem">
|
||||
<Icon icon="arrowRightS" size="lg" />
|
||||
</Button>
|
||||
<NavigateButtons />
|
||||
</Group>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const NavigateButtons = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button onClick={() => navigate(-1)} p="0.5rem">
|
||||
<Icon icon="arrowLeftS" size="lg" />
|
||||
</Button>
|
||||
<Button onClick={() => navigate(1)} p="0.5rem">
|
||||
<Icon icon="arrowRightS" size="lg" />
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -19,10 +19,10 @@ export const SidebarItem = ({ children, className, to, ...props }: SidebarItemPr
|
||||
<Button
|
||||
className={clsx(
|
||||
{
|
||||
[styles.active]: isActive,
|
||||
[styles.disabled]: props.disabled,
|
||||
[styles.link]: true,
|
||||
[styles.root]: true,
|
||||
[styles.active]: isActive,
|
||||
},
|
||||
className,
|
||||
)}
|
||||
|
||||
@@ -2,7 +2,6 @@ import clsx from 'clsx';
|
||||
import { AnimatePresence, motion } from 'motion/react';
|
||||
import { CSSProperties, MouseEvent, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLocation } from 'react-router';
|
||||
|
||||
import styles from './sidebar.module.css';
|
||||
|
||||
@@ -39,7 +38,6 @@ import { Platform } from '/@/shared/types/types';
|
||||
|
||||
export const Sidebar = () => {
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
const sidebar = useSidebarStore();
|
||||
const { setSideBar } = useAppStoreActions();
|
||||
const { sidebarPlaylistList } = useGeneralSettings();
|
||||
@@ -60,6 +58,7 @@ export const Sidebar = () => {
|
||||
}),
|
||||
[t],
|
||||
);
|
||||
|
||||
const upsizedImageUrl = currentSong?.imageUrl
|
||||
?.replace(/size=\d+/, 'size=450')
|
||||
.replace(/width=\d+/, 'width=450')
|
||||
|
||||
@@ -1,24 +1,13 @@
|
||||
import clsx from 'clsx';
|
||||
import isElectron from 'is-electron';
|
||||
import { lazy } from 'react';
|
||||
import { useNavigate } from 'react-router';
|
||||
|
||||
import styles from './default-layout.module.css';
|
||||
|
||||
import { ContextMenuController } from '/@/renderer/features/context-menu/context-menu-controller';
|
||||
import { CommandPalette } from '/@/renderer/features/search/components/command-palette';
|
||||
import { MainContent } from '/@/renderer/layouts/default-layout/main-content';
|
||||
import { PlayerBar } from '/@/renderer/layouts/default-layout/player-bar';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { useCommandPalette } from '/@/renderer/store';
|
||||
import {
|
||||
useGeneralSettings,
|
||||
useHotkeySettings,
|
||||
useSettingsStore,
|
||||
useSettingsStoreActions,
|
||||
useWindowSettings,
|
||||
} from '/@/renderer/store/settings.store';
|
||||
import { HotkeyItem, useHotkeys } from '/@/shared/hooks/use-hotkeys';
|
||||
import { useSettingsStore, useWindowSettings } from '/@/renderer/store/settings.store';
|
||||
import { Platform, PlayerType } from '/@/shared/types/types';
|
||||
|
||||
if (!isElectron()) {
|
||||
@@ -42,38 +31,6 @@ interface DefaultLayoutProps {
|
||||
|
||||
export const DefaultLayout = ({ shell }: DefaultLayoutProps) => {
|
||||
const { windowBarStyle } = useWindowSettings();
|
||||
const { opened, ...handlers } = useCommandPalette();
|
||||
const { bindings } = useHotkeySettings();
|
||||
const navigate = useNavigate();
|
||||
const localSettings = isElectron() ? window.api.localSettings : null;
|
||||
const settings = useGeneralSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
|
||||
const updateZoom = (increase: number) => {
|
||||
const newVal = settings.zoomFactor + increase;
|
||||
if (newVal > 300 || newVal < 50 || !isElectron()) return;
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
zoomFactor: newVal,
|
||||
},
|
||||
});
|
||||
localSettings?.setZoomFactor(settings.zoomFactor);
|
||||
};
|
||||
localSettings?.setZoomFactor(settings.zoomFactor);
|
||||
|
||||
const zoomHotkeys: HotkeyItem[] = [
|
||||
[bindings.zoomIn.hotkey, () => updateZoom(5)],
|
||||
[bindings.zoomOut.hotkey, () => updateZoom(-5)],
|
||||
];
|
||||
|
||||
useHotkeys([
|
||||
[bindings.globalSearch.hotkey, () => handlers.open()],
|
||||
[bindings.browserBack.hotkey, () => navigate(-1)],
|
||||
[bindings.browserForward.hotkey, () => navigate(1)],
|
||||
[bindings.navigateHome.hotkey, () => navigate(AppRoute.HOME)],
|
||||
...(isElectron() ? zoomHotkeys : []),
|
||||
]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -88,7 +45,6 @@ export const DefaultLayout = ({ shell }: DefaultLayoutProps) => {
|
||||
<MainContent shell={shell} />
|
||||
<PlayerBar />
|
||||
</div>
|
||||
<CommandPalette modalProps={{ handlers, opened }} />
|
||||
<ContextMenuController.Root />
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import clsx from 'clsx';
|
||||
import { motion } from 'motion/react';
|
||||
import { Suspense, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { Outlet, useLocation } from 'react-router';
|
||||
import { Outlet } from 'react-router';
|
||||
|
||||
import styles from './main-content.module.css';
|
||||
|
||||
import { FullScreenOverlay } from '/@/renderer/layouts/default-layout/full-screen-overlay';
|
||||
import { LeftSidebar } from '/@/renderer/layouts/default-layout/left-sidebar';
|
||||
import { RightSidebar } from '/@/renderer/layouts/default-layout/right-sidebar';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { useAppStoreActions, useSidebarStore } from '/@/renderer/store';
|
||||
import { useGeneralSettings } from '/@/renderer/store/settings.store';
|
||||
import { constrainRightSidebarWidth, constrainSidebarWidth } from '/@/renderer/utils';
|
||||
@@ -17,14 +16,12 @@ import { Spinner } from '/@/shared/components/spinner/spinner';
|
||||
const MINIMUM_SIDEBAR_WIDTH = 260;
|
||||
|
||||
export const MainContent = ({ shell }: { shell?: boolean }) => {
|
||||
const location = useLocation();
|
||||
const { collapsed, leftWidth, rightExpanded, rightWidth } = useSidebarStore();
|
||||
const { setSideBar } = useAppStoreActions();
|
||||
const { sideQueueType } = useGeneralSettings();
|
||||
const [isResizing, setIsResizing] = useState(false);
|
||||
const [isResizingRight, setIsResizingRight] = useState(false);
|
||||
|
||||
const showSideQueue = rightExpanded && location.pathname !== AppRoute.NOW_PLAYING;
|
||||
const rightSidebarRef = useRef<HTMLDivElement | null>(null);
|
||||
const mainContentRef = useRef<HTMLDivElement | null>(null);
|
||||
const initialRightWidthRef = useRef<string>(rightWidth);
|
||||
@@ -128,7 +125,7 @@ export const MainContent = ({ shell }: { shell?: boolean }) => {
|
||||
return (
|
||||
<motion.div
|
||||
className={clsx(styles.mainContentContainer, {
|
||||
[styles.rightExpanded]: showSideQueue && sideQueueType === 'sideQueue',
|
||||
[styles.rightExpanded]: rightExpanded && sideQueueType === 'sideQueue',
|
||||
[styles.shell]: shell,
|
||||
[styles.sidebarCollapsed]: collapsed,
|
||||
[styles.sidebarExpanded]: !collapsed,
|
||||
|
||||
@@ -1,53 +1,48 @@
|
||||
import { AnimatePresence, motion, Variants } from 'motion/react';
|
||||
import { forwardRef, Ref } from 'react';
|
||||
import { useLocation } from 'react-router';
|
||||
|
||||
import styles from './right-sidebar.module.css';
|
||||
|
||||
import { DrawerPlayQueue } from '/@/renderer/features/now-playing/components/drawer-play-queue';
|
||||
import { SidebarPlayQueue } from '/@/renderer/features/now-playing/components/sidebar-play-queue';
|
||||
import { ResizeHandle } from '/@/renderer/features/shared/components/resize-handle';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { useGeneralSettings, useSidebarStore, useWindowSettings } from '/@/renderer/store';
|
||||
import { Platform } from '/@/shared/types/types';
|
||||
import { useGeneralSettings, useSidebarStore } from '/@/renderer/store';
|
||||
|
||||
const queueDrawerVariants: Variants = {
|
||||
closed: (windowBarStyle) => ({
|
||||
height:
|
||||
windowBarStyle === Platform.WINDOWS || Platform.MACOS
|
||||
? 'calc(100vh - 205px)'
|
||||
: 'calc(100vh - 175px)',
|
||||
position: 'absolute',
|
||||
right: 0,
|
||||
top: '75px',
|
||||
transition: {
|
||||
duration: 0.4,
|
||||
ease: 'anticipate',
|
||||
},
|
||||
width: '450px',
|
||||
x: '50vw',
|
||||
}),
|
||||
open: (windowBarStyle) => ({
|
||||
boxShadow: '0px 0px 10px 0px rgba(0, 0, 0, 0.8)',
|
||||
height:
|
||||
windowBarStyle === Platform.WINDOWS || Platform.MACOS
|
||||
? 'calc(100vh - 205px)'
|
||||
: 'calc(100vh - 175px)',
|
||||
position: 'absolute',
|
||||
right: '20px',
|
||||
top: '75px',
|
||||
transition: {
|
||||
damping: 10,
|
||||
delay: 0,
|
||||
duration: 0.4,
|
||||
ease: 'anticipate',
|
||||
mass: 0.5,
|
||||
},
|
||||
width: '450px',
|
||||
x: 0,
|
||||
zIndex: 120,
|
||||
}),
|
||||
};
|
||||
// const queueDrawerVariants: Variants = {
|
||||
// closed: (windowBarStyle) => ({
|
||||
// height:
|
||||
// windowBarStyle === Platform.WINDOWS || Platform.MACOS
|
||||
// ? 'calc(100vh - 205px)'
|
||||
// : 'calc(100vh - 175px)',
|
||||
// position: 'absolute',
|
||||
// right: 0,
|
||||
// top: '75px',
|
||||
// transition: {
|
||||
// duration: 0.4,
|
||||
// ease: 'anticipate',
|
||||
// },
|
||||
// width: '450px',
|
||||
// x: '50vw',
|
||||
// }),
|
||||
// open: (windowBarStyle) => ({
|
||||
// boxShadow: '0px 0px 10px 0px rgba(0, 0, 0, 0.8)',
|
||||
// height:
|
||||
// windowBarStyle === Platform.WINDOWS || Platform.MACOS
|
||||
// ? 'calc(100vh - 205px)'
|
||||
// : 'calc(100vh - 175px)',
|
||||
// position: 'absolute',
|
||||
// right: '20px',
|
||||
// top: '75px',
|
||||
// transition: {
|
||||
// damping: 10,
|
||||
// delay: 0,
|
||||
// duration: 0.4,
|
||||
// ease: 'anticipate',
|
||||
// mass: 0.5,
|
||||
// },
|
||||
// width: '450px',
|
||||
// x: 0,
|
||||
// zIndex: 120,
|
||||
// }),
|
||||
// };
|
||||
|
||||
interface RightSidebarProps {
|
||||
isResizing: boolean;
|
||||
@@ -59,50 +54,28 @@ export const RightSidebar = forwardRef(
|
||||
{ isResizing: isResizingRight, startResizing }: RightSidebarProps,
|
||||
ref: Ref<HTMLDivElement>,
|
||||
) => {
|
||||
const { windowBarStyle } = useWindowSettings();
|
||||
const { rightExpanded } = useSidebarStore();
|
||||
const { sideQueueType } = useGeneralSettings();
|
||||
const location = useLocation();
|
||||
const showSideQueue = rightExpanded && location.pathname !== AppRoute.NOW_PLAYING;
|
||||
|
||||
return (
|
||||
<>
|
||||
{showSideQueue && (
|
||||
<>
|
||||
{sideQueueType === 'sideQueue' ? (
|
||||
<aside
|
||||
className={styles.rightSidebarContainer}
|
||||
id="sidebar-queue"
|
||||
key="queue-sidebar"
|
||||
>
|
||||
<ResizeHandle
|
||||
isResizing={isResizingRight}
|
||||
onMouseDown={(e) => {
|
||||
e.preventDefault();
|
||||
startResizing('right', e.nativeEvent);
|
||||
}}
|
||||
placement="left"
|
||||
ref={ref}
|
||||
/>
|
||||
<SidebarPlayQueue />
|
||||
</aside>
|
||||
) : (
|
||||
<AnimatePresence initial={false} key="queue-drawer" mode="sync">
|
||||
<motion.div
|
||||
animate="open"
|
||||
className={styles.queueDrawer}
|
||||
custom={windowBarStyle}
|
||||
exit="closed"
|
||||
id="drawer-queue"
|
||||
initial="closed"
|
||||
key="queue-drawer"
|
||||
variants={queueDrawerVariants}
|
||||
>
|
||||
<DrawerPlayQueue />
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
)}
|
||||
</>
|
||||
{rightExpanded && sideQueueType === 'sideQueue' && (
|
||||
<aside
|
||||
className={styles.rightSidebarContainer}
|
||||
id="sidebar-queue"
|
||||
key="queue-sidebar"
|
||||
>
|
||||
<ResizeHandle
|
||||
isResizing={isResizingRight}
|
||||
onMouseDown={(e) => {
|
||||
e.preventDefault();
|
||||
startResizing('right', e.nativeEvent);
|
||||
}}
|
||||
placement="left"
|
||||
ref={ref}
|
||||
/>
|
||||
<SidebarPlayQueue />
|
||||
</aside>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import clsx from 'clsx';
|
||||
import { lazy } from 'react';
|
||||
import { Outlet, useNavigate } from 'react-router';
|
||||
import { Outlet } from 'react-router';
|
||||
|
||||
import styles from './mobile-layout.module.css';
|
||||
|
||||
@@ -9,14 +9,11 @@ import { MobileFullscreenPlayer } from '/@/renderer/features/player/components/m
|
||||
import { CommandPalette } from '/@/renderer/features/search/components/command-palette';
|
||||
import { MobileSidebar } from '/@/renderer/features/sidebar/components/mobile-sidebar';
|
||||
import { PlayerBar } from '/@/renderer/layouts/default-layout/player-bar';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { useFullScreenPlayerStore } from '/@/renderer/store';
|
||||
import { useCommandPalette } from '/@/renderer/store';
|
||||
import { useHotkeySettings } from '/@/renderer/store/settings.store';
|
||||
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
||||
import { Drawer } from '/@/shared/components/drawer/drawer';
|
||||
import { useDisclosure } from '/@/shared/hooks/use-disclosure';
|
||||
import { useHotkeys } from '/@/shared/hooks/use-hotkeys';
|
||||
|
||||
const WindowBar = lazy(() =>
|
||||
import('/@/renderer/layouts/window-bar').then((module) => ({
|
||||
@@ -30,18 +27,9 @@ interface MobileLayoutProps {
|
||||
|
||||
export const MobileLayout = ({ shell }: MobileLayoutProps) => {
|
||||
const { opened, ...handlers } = useCommandPalette();
|
||||
const { bindings } = useHotkeySettings();
|
||||
const navigate = useNavigate();
|
||||
const [sidebarOpened, { close: closeSidebar, open: openSidebar }] = useDisclosure(false);
|
||||
const { expanded: isFullScreenPlayerExpanded } = useFullScreenPlayerStore();
|
||||
|
||||
useHotkeys([
|
||||
[bindings.globalSearch.hotkey, () => handlers.open()],
|
||||
[bindings.browserBack.hotkey, () => navigate(-1)],
|
||||
[bindings.browserForward.hotkey, () => navigate(1)],
|
||||
[bindings.navigateHome.hotkey, () => navigate(AppRoute.HOME)],
|
||||
]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={clsx(styles.layout)} id="mobile-layout">
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
import isElectron from 'is-electron';
|
||||
import { useNavigate } from 'react-router';
|
||||
|
||||
import { CommandPalette } from '/@/renderer/features/search/components/command-palette';
|
||||
import { useIsMobile } from '/@/renderer/hooks/use-is-mobile';
|
||||
import { DefaultLayout } from '/@/renderer/layouts/default-layout';
|
||||
import { MobileLayout } from '/@/renderer/layouts/mobile-layout/mobile-layout';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import {
|
||||
useCommandPalette,
|
||||
useGeneralSettings,
|
||||
useHotkeySettings,
|
||||
useSettingsStoreActions,
|
||||
} from '/@/renderer/store';
|
||||
import { HotkeyItem, useHotkeys } from '/@/shared/hooks/use-hotkeys';
|
||||
|
||||
interface ResponsiveLayoutProps {
|
||||
shell?: boolean;
|
||||
}
|
||||
|
||||
export const ResponsiveLayout = ({ shell }: ResponsiveLayoutProps) => {
|
||||
const ResponsiveLayoutBase = ({ shell }: ResponsiveLayoutProps) => {
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
if (isMobile) {
|
||||
@@ -15,3 +27,49 @@ export const ResponsiveLayout = ({ shell }: ResponsiveLayoutProps) => {
|
||||
|
||||
return <DefaultLayout shell={shell} />;
|
||||
};
|
||||
|
||||
export const ResponsiveLayout = ({ shell }: ResponsiveLayoutProps) => {
|
||||
return (
|
||||
<>
|
||||
<ResponsiveLayoutBase shell={shell} />
|
||||
<LayoutHotkeys />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const LayoutHotkeys = () => {
|
||||
const navigate = useNavigate();
|
||||
const localSettings = isElectron() ? window.api.localSettings : null;
|
||||
const settings = useGeneralSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
const { bindings } = useHotkeySettings();
|
||||
const { opened, ...handlers } = useCommandPalette();
|
||||
|
||||
const updateZoom = (increase: number) => {
|
||||
const newVal = settings.zoomFactor + increase;
|
||||
if (newVal > 300 || newVal < 50 || !isElectron()) return;
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
zoomFactor: newVal,
|
||||
},
|
||||
});
|
||||
localSettings?.setZoomFactor(settings.zoomFactor);
|
||||
};
|
||||
localSettings?.setZoomFactor(settings.zoomFactor);
|
||||
|
||||
const zoomHotkeys: HotkeyItem[] = [
|
||||
[bindings.zoomIn.hotkey, () => updateZoom(5)],
|
||||
[bindings.zoomOut.hotkey, () => updateZoom(-5)],
|
||||
];
|
||||
|
||||
useHotkeys([
|
||||
[bindings.globalSearch.hotkey, () => handlers.open()],
|
||||
[bindings.browserBack.hotkey, () => navigate(-1)],
|
||||
[bindings.browserForward.hotkey, () => navigate(1)],
|
||||
[bindings.navigateHome.hotkey, () => navigate(AppRoute.HOME)],
|
||||
...(isElectron() ? zoomHotkeys : []),
|
||||
]);
|
||||
|
||||
return <CommandPalette modalProps={{ handlers, opened }} />;
|
||||
};
|
||||
|
||||
@@ -112,7 +112,15 @@ export const useAuthStore = createWithEqualityFn<AuthSlice>()(
|
||||
),
|
||||
);
|
||||
|
||||
export const useCurrentServerId = () => useAuthStore((state) => state.currentServer)?.id || '';
|
||||
export const useCurrentServerId = () =>
|
||||
useAuthStore((state) => {
|
||||
const currentServer = state.currentServer;
|
||||
if (!currentServer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return currentServer.id || '';
|
||||
}, shallow);
|
||||
|
||||
export const useCurrentServer = () =>
|
||||
useAuthStore((state) => {
|
||||
|
||||
Reference in New Issue
Block a user