mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-07 04:20:12 +02:00
optimize settings store
This commit is contained in:
@@ -14,7 +14,7 @@ import { WebAudioContext } from '/@/renderer/features/player/context/webaudio-co
|
||||
import { useSyncSettingsToMain } from '/@/renderer/hooks/use-sync-settings-to-main';
|
||||
import { ReleaseNotesModal } from './release-notes-modal';
|
||||
import { AppRouter } from '/@/renderer/router/app-router';
|
||||
import { useCssSettings, useHotkeySettings, useSettingsStore } from '/@/renderer/store';
|
||||
import { useCssSettings, useHotkeySettings, useLanguage } from '/@/renderer/store';
|
||||
import { useAppTheme } from '/@/renderer/themes/use-app-theme';
|
||||
import { sanitizeCss } from '/@/renderer/utils/sanitize';
|
||||
import { WebAudio } from '/@/shared/types/types';
|
||||
@@ -26,7 +26,7 @@ const ipc = isElectron() ? window.api.ipc : null;
|
||||
|
||||
export const App = () => {
|
||||
const { mode, theme } = useAppTheme();
|
||||
const language = useSettingsStore((store) => store.general.language);
|
||||
const language = useLanguage();
|
||||
|
||||
const { content, enabled } = useCssSettings();
|
||||
const { bindings } = useHotkeySettings();
|
||||
|
||||
@@ -19,7 +19,7 @@ import { ItemControls } from '/@/renderer/components/item-list/types';
|
||||
import { JoinedArtists } from '/@/renderer/features/albums/components/joined-artists';
|
||||
import { useDragDrop } from '/@/renderer/hooks/use-drag-drop';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { useGeneralSettings } from '/@/renderer/store';
|
||||
import { useShowRatings } from '/@/renderer/store';
|
||||
import {
|
||||
formatDateAbsolute,
|
||||
formatDateAbsoluteUTC,
|
||||
@@ -77,7 +77,7 @@ export const ItemCard = ({
|
||||
type = 'poster',
|
||||
withControls,
|
||||
}: ItemCardProps) => {
|
||||
const { showRatings } = useGeneralSettings();
|
||||
const showRatings = useShowRatings();
|
||||
const imageUrl = getImageUrl(data);
|
||||
const rows = providedRows || [];
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
getServerById,
|
||||
useAuthStore,
|
||||
useCurrentServerId,
|
||||
useImageRes,
|
||||
useSettingsStore,
|
||||
} from '/@/renderer/store';
|
||||
import { BaseImage, ImageProps } from '/@/shared/components/image/image';
|
||||
@@ -73,7 +74,7 @@ export const useItemImageUrl = (args: UseItemImageUrlProps) => {
|
||||
const { id, imageUrl, itemType, size, type, useRemoteUrl } = args;
|
||||
const serverId = useCurrentServerId();
|
||||
|
||||
const imageRes = useSettingsStore((store) => store.general.imageRes);
|
||||
const imageRes = useImageRes();
|
||||
const sizeByType: number | undefined = type ? imageRes[type] : undefined;
|
||||
|
||||
return useMemo(() => {
|
||||
|
||||
@@ -21,7 +21,7 @@ import { searchLibraryItems } from '/@/renderer/features/shared/utils';
|
||||
import { useContainerQuery } from '/@/renderer/hooks';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { useCurrentServer, usePlayerSong } from '/@/renderer/store';
|
||||
import { useGeneralSettings, useSettingsStore } from '/@/renderer/store/settings.store';
|
||||
import { useExternalLinks, useSettingsStore } from '/@/renderer/store/settings.store';
|
||||
import { sentenceCase, titleCase } from '/@/renderer/utils';
|
||||
import { replaceURLWithHTMLLinks } from '/@/renderer/utils/linkify';
|
||||
import { normalizeReleaseTypes } from '/@/renderer/utils/normalize-release-types';
|
||||
@@ -312,7 +312,7 @@ export const AlbumDetailContent = () => {
|
||||
);
|
||||
|
||||
const { ref, ...cq } = useContainerQuery();
|
||||
const { externalLinks, lastFM, musicBrainz } = useGeneralSettings();
|
||||
const { externalLinks, lastFM, musicBrainz } = useExternalLinks();
|
||||
|
||||
const genreCarousels = useMemo(() => {
|
||||
const genreLimit = 2;
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
LibraryHeaderMenu,
|
||||
} from '/@/renderer/features/shared/components/library-header';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { useCurrentServer, useGeneralSettings } from '/@/renderer/store';
|
||||
import { useCurrentServer, useShowRatings } from '/@/renderer/store';
|
||||
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
||||
import { formatDateAbsoluteUTC, formatDurationString } from '/@/renderer/utils';
|
||||
import { normalizeReleaseTypes } from '/@/renderer/utils/normalize-release-types';
|
||||
@@ -29,7 +29,7 @@ export const AlbumDetailHeader = forwardRef<HTMLDivElement>((_props, ref) => {
|
||||
const { albumId } = useParams() as { albumId: string };
|
||||
const { t } = useTranslation();
|
||||
const server = useCurrentServer();
|
||||
const { showRatings } = useGeneralSettings();
|
||||
const showRatings = useShowRatings();
|
||||
const detailQuery = useQuery(
|
||||
albumQueries.detail({ query: { id: albumId }, serverId: server?.id }),
|
||||
);
|
||||
|
||||
@@ -16,13 +16,13 @@ import { LibraryContainer } from '/@/renderer/features/shared/components/library
|
||||
import { LibraryHeaderBar } from '/@/renderer/features/shared/components/library-header-bar';
|
||||
import { PageErrorBoundary } from '/@/renderer/features/shared/components/page-error-boundary';
|
||||
import { useFastAverageColor, useWaitForColorCalculation } from '/@/renderer/hooks';
|
||||
import { useCurrentServer, useGeneralSettings } from '/@/renderer/store';
|
||||
import { useAlbumBackground, useCurrentServer } from '/@/renderer/store';
|
||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
||||
|
||||
const AlbumDetailRoute = () => {
|
||||
const scrollAreaRef = useRef<HTMLDivElement>(null);
|
||||
const headerRef = useRef<HTMLDivElement>(null);
|
||||
const { albumBackground, albumBackgroundBlur } = useGeneralSettings();
|
||||
const { albumBackground, albumBackgroundBlur } = useAlbumBackground();
|
||||
|
||||
const { albumId } = useParams() as { albumId: string };
|
||||
const server = useCurrentServer();
|
||||
|
||||
@@ -49,7 +49,13 @@ import {
|
||||
useCurrentServerId,
|
||||
usePlayerSong,
|
||||
} from '/@/renderer/store';
|
||||
import { useGeneralSettings, useSettingsStore } from '/@/renderer/store/settings.store';
|
||||
import {
|
||||
useArtistItems,
|
||||
useArtistRadioCount,
|
||||
useArtistReleaseTypeItems,
|
||||
useExternalLinks,
|
||||
useSettingsStore,
|
||||
} from '/@/renderer/store/settings.store';
|
||||
import { titleCase } from '/@/renderer/utils';
|
||||
import { sanitize } from '/@/renderer/utils/sanitize';
|
||||
import { sortAlbumList } from '/@/shared/api/utils';
|
||||
@@ -589,8 +595,9 @@ export const AlbumArtistDetailContent = ({
|
||||
albumsQuery,
|
||||
detailQuery,
|
||||
}: AlbumArtistDetailContentProps) => {
|
||||
const { artistItems, artistRadioCount, externalLinks, lastFM, musicBrainz } =
|
||||
useGeneralSettings();
|
||||
const artistItems = useArtistItems();
|
||||
const artistRadioCount = useArtistRadioCount();
|
||||
const { externalLinks, lastFM, musicBrainz } = useExternalLinks();
|
||||
const { albumArtistId, artistId } = useParams() as {
|
||||
albumArtistId?: string;
|
||||
artistId?: string;
|
||||
@@ -1064,7 +1071,7 @@ interface ArtistAlbumsProps {
|
||||
|
||||
const ArtistAlbums = ({ albumsQuery }: ArtistAlbumsProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { artistReleaseTypeItems } = useGeneralSettings();
|
||||
const artistReleaseTypeItems = useArtistReleaseTypeItems();
|
||||
const [searchTerm, setSearchTerm] = useState('');
|
||||
const [debouncedSearchTerm] = useDebouncedValue(searchTerm, 300);
|
||||
const albumArtistDetailSort = useAppStore((state) => state.albumArtistDetailSort);
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
LibraryHeaderMenu,
|
||||
} from '/@/renderer/features/shared/components/library-header';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { useCurrentServer, useGeneralSettings } from '/@/renderer/store';
|
||||
import { useCurrentServer, useShowRatings } from '/@/renderer/store';
|
||||
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
||||
import { formatDurationString } from '/@/renderer/utils';
|
||||
import { Group } from '/@/shared/components/group/group';
|
||||
@@ -30,7 +30,7 @@ export const AlbumArtistDetailHeader = forwardRef((_props, ref: Ref<HTMLDivEleme
|
||||
};
|
||||
const routeId = (artistId || albumArtistId) as string;
|
||||
const server = useCurrentServer();
|
||||
const { showRatings } = useGeneralSettings();
|
||||
const showRatings = useShowRatings();
|
||||
const { t } = useTranslation();
|
||||
const detailQuery = useSuspenseQuery(
|
||||
artistsQueries.albumArtistDetail({
|
||||
|
||||
@@ -17,7 +17,7 @@ import { LibraryContainer } from '/@/renderer/features/shared/components/library
|
||||
import { LibraryHeaderBar } from '/@/renderer/features/shared/components/library-header-bar';
|
||||
import { PageErrorBoundary } from '/@/renderer/features/shared/components/page-error-boundary';
|
||||
import { useFastAverageColor, useWaitForColorCalculation } from '/@/renderer/hooks';
|
||||
import { useCurrentServer, useCurrentServerId, useGeneralSettings } from '/@/renderer/store';
|
||||
import { useArtistBackground, useCurrentServer, useCurrentServerId } from '/@/renderer/store';
|
||||
import { Spinner } from '/@/shared/components/spinner/spinner';
|
||||
import { AlbumListSort, LibraryItem, SortOrder } from '/@/shared/types/domain-types';
|
||||
|
||||
@@ -26,7 +26,7 @@ const AlbumArtistDetailRouteContent = () => {
|
||||
const headerRef = useRef<HTMLDivElement>(null);
|
||||
const server = useCurrentServer();
|
||||
const serverId = useCurrentServerId();
|
||||
const { artistBackground, artistBackgroundBlur } = useGeneralSettings();
|
||||
const { artistBackground, artistBackgroundBlur } = useArtistBackground();
|
||||
|
||||
const { albumArtistId, artistId } = useParams() as {
|
||||
albumArtistId?: string;
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||
import { usePlayer } from '/@/renderer/features/player/context/player-context';
|
||||
import { songsQueries } from '/@/renderer/features/songs/api/songs-api';
|
||||
import { useCurrentServerId, useGeneralSettings, usePlayButtonBehavior } from '/@/renderer/store';
|
||||
import { useArtistRadioCount, useCurrentServerId, usePlayButtonBehavior } from '/@/renderer/store';
|
||||
import { ContextMenu } from '/@/shared/components/context-menu/context-menu';
|
||||
import { AlbumArtist, Artist } from '/@/shared/types/domain-types';
|
||||
import { Play } from '/@/shared/types/types';
|
||||
@@ -16,7 +16,7 @@ interface PlayArtistRadioActionProps {
|
||||
}
|
||||
|
||||
export const PlayArtistRadioAction = ({ artist, disabled }: PlayArtistRadioActionProps) => {
|
||||
const { artistRadioCount } = useGeneralSettings();
|
||||
const artistRadioCount = useArtistRadioCount();
|
||||
const { t } = useTranslation();
|
||||
const player = usePlayer();
|
||||
const serverId = useCurrentServerId();
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { useSetRating } from '/@/renderer/features/shared/mutations/set-rating-mutation';
|
||||
import { useCurrentServer, useCurrentServerId, useGeneralSettings } from '/@/renderer/store';
|
||||
import { useCurrentServer, useCurrentServerId, useShowRatings } from '/@/renderer/store';
|
||||
import { ContextMenu } from '/@/shared/components/context-menu/context-menu';
|
||||
import { Rating } from '/@/shared/components/rating/rating';
|
||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
||||
@@ -17,7 +17,7 @@ export const SetRatingAction = ({ ids, itemType }: SetRatingActionProps) => {
|
||||
const { t } = useTranslation();
|
||||
const server = useCurrentServer();
|
||||
const serverId = useCurrentServerId();
|
||||
const { showRatings } = useGeneralSettings();
|
||||
const showRatings = useShowRatings();
|
||||
|
||||
const setRatingMutation = useSetRating({});
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
DiscordLinkType,
|
||||
useAppStore,
|
||||
useDiscordSettings,
|
||||
useGeneralSettings,
|
||||
useLastfmApiKey,
|
||||
usePlayerSong,
|
||||
usePlayerStore,
|
||||
useTimestampStoreBase,
|
||||
@@ -31,7 +31,7 @@ const truncate = (field: string) =>
|
||||
|
||||
export const useDiscordRpc = () => {
|
||||
const discordSettings = useDiscordSettings();
|
||||
const generalSettings = useGeneralSettings();
|
||||
const lastfmApiKey = useLastfmApiKey();
|
||||
const privateMode = useAppStore((state) => state.privateMode);
|
||||
const [lastUniqueId, setlastUniqueId] = useState('');
|
||||
|
||||
@@ -220,12 +220,12 @@ export const useDiscordRpc = () => {
|
||||
|
||||
if (
|
||||
activity.largeImageKey === undefined &&
|
||||
generalSettings.lastfmApiKey &&
|
||||
lastfmApiKey &&
|
||||
song?.album &&
|
||||
song?.albumArtists.length
|
||||
) {
|
||||
const albumInfo = await fetch(
|
||||
`https://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=${generalSettings.lastfmApiKey}&artist=${encodeURIComponent(song.albumArtists[0].name)}&album=${encodeURIComponent(song.album)}&format=json`,
|
||||
`https://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=${lastfmApiKey}&artist=${encodeURIComponent(song.albumArtists[0].name)}&album=${encodeURIComponent(song.album)}&format=json`,
|
||||
);
|
||||
|
||||
const albumInfoJson = await albumInfo.json();
|
||||
@@ -292,7 +292,7 @@ export const useDiscordRpc = () => {
|
||||
discordSettings.showAsListening,
|
||||
discordSettings.showServerImage,
|
||||
discordSettings.showPaused,
|
||||
generalSettings.lastfmApiKey,
|
||||
lastfmApiKey,
|
||||
discordSettings.clientId,
|
||||
discordSettings.displayType,
|
||||
discordSettings.linkType,
|
||||
|
||||
@@ -13,7 +13,8 @@ import { SongInfiniteCarousel } from '/@/renderer/features/songs/components/song
|
||||
import {
|
||||
HomeItem,
|
||||
useCurrentServer,
|
||||
useGeneralSettings,
|
||||
useHomeFeature,
|
||||
useHomeItems,
|
||||
useWindowSettings,
|
||||
} from '/@/renderer/store';
|
||||
import { Spinner } from '/@/shared/components/spinner/spinner';
|
||||
@@ -32,7 +33,8 @@ const HomeRoute = () => {
|
||||
const scrollAreaRef = useRef<HTMLDivElement>(null);
|
||||
const server = useCurrentServer();
|
||||
const { windowBarStyle } = useWindowSettings();
|
||||
const { homeFeature, homeItems } = useGeneralSettings();
|
||||
const homeFeature = useHomeFeature();
|
||||
const homeItems = useHomeItems();
|
||||
|
||||
const isJellyfin = server?.type === ServerType.JELLYFIN;
|
||||
|
||||
|
||||
@@ -20,12 +20,12 @@ import {
|
||||
mapShuffledToQueueIndex,
|
||||
subscribeCurrentTrack,
|
||||
subscribePlayerQueue,
|
||||
useFollowCurrentSong,
|
||||
useListSettings,
|
||||
usePlayerActions,
|
||||
usePlayerQueueType,
|
||||
usePlayerSong,
|
||||
usePlayerStore,
|
||||
useSettingsStore,
|
||||
} from '/@/renderer/store';
|
||||
import { Flex } from '/@/shared/components/flex/flex';
|
||||
import { LoadingOverlay } from '/@/shared/components/loading-overlay/loading-overlay';
|
||||
@@ -51,7 +51,7 @@ export const PlayQueue = forwardRef<ItemListHandle, QueueProps>(({ listKey, sear
|
||||
const mergedRef = useMergedRef(ref, tableRef);
|
||||
const { getQueue } = usePlayerActions();
|
||||
const queueType = usePlayerQueueType();
|
||||
const followCurrentSong = useSettingsStore((state) => state.general.followCurrentSong);
|
||||
const followCurrentSong = useFollowCurrentSong();
|
||||
|
||||
const [debouncedSearchTerm] = useDebouncedValue(searchTerm, 200);
|
||||
|
||||
|
||||
@@ -12,12 +12,15 @@ import { Lyrics } from '/@/renderer/features/lyrics/lyrics';
|
||||
import { PlayQueue } from '/@/renderer/features/now-playing/components/play-queue';
|
||||
import { PlayQueueListControls } from '/@/renderer/features/now-playing/components/play-queue-list-controls';
|
||||
import {
|
||||
useCombinedLyricsAndVisualizer,
|
||||
useFullScreenPlayerStore,
|
||||
useGeneralSettings,
|
||||
usePlaybackSettings,
|
||||
usePlayerSong,
|
||||
useSettingsStore,
|
||||
useSettingsStoreActions,
|
||||
useShowLyricsInSidebar,
|
||||
useShowVisualizerInSidebar,
|
||||
useSidebarPanelOrder,
|
||||
} from '/@/renderer/store';
|
||||
import { ActionIcon, ActionIconGroup } from '/@/shared/components/action-icon/action-icon';
|
||||
import { Flex } from '/@/shared/components/flex/flex';
|
||||
@@ -43,12 +46,10 @@ export const SidebarPlayQueue = () => {
|
||||
const [search, setSearch] = useState<string | undefined>(undefined);
|
||||
const { expanded: isFullScreenPlayerExpanded } = useFullScreenPlayerStore();
|
||||
const [shouldRender, setShouldRender] = useState(!isFullScreenPlayerExpanded);
|
||||
const {
|
||||
combinedLyricsAndVisualizer,
|
||||
showLyricsInSidebar,
|
||||
showVisualizerInSidebar,
|
||||
sidebarPanelOrder,
|
||||
} = useGeneralSettings();
|
||||
const combinedLyricsAndVisualizer = useCombinedLyricsAndVisualizer();
|
||||
const showLyricsInSidebar = useShowLyricsInSidebar();
|
||||
const showVisualizerInSidebar = useShowVisualizerInSidebar();
|
||||
const sidebarPanelOrder = useSidebarPanelOrder();
|
||||
const { type, webAudio } = usePlaybackSettings();
|
||||
const showVisualizer = showVisualizerInSidebar && type === PlayerType.WEB && webAudio;
|
||||
const showPanel = showLyricsInSidebar || showVisualizer;
|
||||
@@ -217,9 +218,9 @@ export const SidebarPlayQueue = () => {
|
||||
|
||||
const PanelReorderControls = ({ panelType }: { panelType: 'lyrics' | 'visualizer' }) => {
|
||||
const { t } = useTranslation();
|
||||
const generalSettings = useGeneralSettings();
|
||||
const { combinedLyricsAndVisualizer, sidebarPanelOrder } = generalSettings;
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
const sidebarPanelOrder = useSidebarPanelOrder();
|
||||
const combinedLyricsAndVisualizer = useCombinedLyricsAndVisualizer();
|
||||
|
||||
const currentIndex = sidebarPanelOrder.indexOf(panelType);
|
||||
const canMoveUp = currentIndex > 0;
|
||||
@@ -238,11 +239,10 @@ const PanelReorderControls = ({ panelType }: { panelType: 'lyrics' | 'visualizer
|
||||
|
||||
setSettings({
|
||||
general: {
|
||||
...generalSettings,
|
||||
sidebarPanelOrder: newOrder,
|
||||
},
|
||||
});
|
||||
}, [canMoveUp, currentIndex, generalSettings, sidebarPanelOrder, setSettings]);
|
||||
}, [canMoveUp, currentIndex, sidebarPanelOrder, setSettings]);
|
||||
|
||||
const handleMoveDown = useCallback(() => {
|
||||
if (!canMoveDown) return;
|
||||
@@ -255,17 +255,15 @@ const PanelReorderControls = ({ panelType }: { panelType: 'lyrics' | 'visualizer
|
||||
|
||||
setSettings({
|
||||
general: {
|
||||
...generalSettings,
|
||||
sidebarPanelOrder: newOrder,
|
||||
},
|
||||
});
|
||||
}, [canMoveDown, currentIndex, generalSettings, sidebarPanelOrder, setSettings]);
|
||||
}, [canMoveDown, currentIndex, sidebarPanelOrder, setSettings]);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
if (combinedLyricsAndVisualizer && panelType === 'lyrics') {
|
||||
setSettings({
|
||||
general: {
|
||||
...generalSettings,
|
||||
showLyricsInSidebar: false,
|
||||
showVisualizerInSidebar: false,
|
||||
},
|
||||
@@ -273,19 +271,17 @@ const PanelReorderControls = ({ panelType }: { panelType: 'lyrics' | 'visualizer
|
||||
} else if (panelType === 'lyrics') {
|
||||
setSettings({
|
||||
general: {
|
||||
...generalSettings,
|
||||
showLyricsInSidebar: false,
|
||||
},
|
||||
});
|
||||
} else if (panelType === 'visualizer') {
|
||||
setSettings({
|
||||
general: {
|
||||
...generalSettings,
|
||||
showVisualizerInSidebar: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
}, [combinedLyricsAndVisualizer, generalSettings, panelType, setSettings]);
|
||||
}, [combinedLyricsAndVisualizer, panelType, setSettings]);
|
||||
|
||||
return (
|
||||
<div className={styles.panelReorderControls}>
|
||||
|
||||
@@ -13,17 +13,18 @@ import {
|
||||
useRadioPlayer,
|
||||
} from '/@/renderer/features/radio/hooks/use-radio-player';
|
||||
import {
|
||||
useButtonSize,
|
||||
usePlayerRepeat,
|
||||
usePlayerShuffle,
|
||||
usePlayerSong,
|
||||
usePlayerStatus,
|
||||
useSettingsStore,
|
||||
useSkipButtons,
|
||||
} from '/@/renderer/store';
|
||||
import { Icon } from '/@/shared/components/icon/icon';
|
||||
import { PlayerRepeat, PlayerShuffle, PlayerStatus } from '/@/shared/types/types';
|
||||
|
||||
export const CenterControls = () => {
|
||||
const skip = useSettingsStore((state) => state.general.skipButtons);
|
||||
const skip = useSkipButtons();
|
||||
|
||||
const isRadioActive = useIsRadioActive();
|
||||
|
||||
@@ -85,7 +86,7 @@ const RadioCenterPlayButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
|
||||
const RadioStopButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const buttonSize = useSettingsStore((state) => state.general.buttonSize);
|
||||
const buttonSize = useButtonSize();
|
||||
const { stop } = useRadioControls();
|
||||
|
||||
return (
|
||||
@@ -104,7 +105,7 @@ const RadioStopButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
|
||||
const StopButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const buttonSize = useSettingsStore((state) => state.general.buttonSize);
|
||||
const buttonSize = useButtonSize();
|
||||
const { mediaStop } = usePlayer();
|
||||
|
||||
return (
|
||||
@@ -123,7 +124,7 @@ const StopButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
|
||||
const ShuffleButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const buttonSize = useSettingsStore((state) => state.general.buttonSize);
|
||||
const buttonSize = useButtonSize();
|
||||
const shuffle = usePlayerShuffle();
|
||||
const { toggleShuffle } = usePlayer();
|
||||
|
||||
@@ -156,7 +157,7 @@ const ShuffleButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
|
||||
const PreviousButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const buttonSize = useSettingsStore((state) => state.general.buttonSize);
|
||||
const buttonSize = useButtonSize();
|
||||
const { mediaPrevious } = usePlayer();
|
||||
|
||||
return (
|
||||
@@ -175,7 +176,7 @@ const PreviousButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
|
||||
const SkipBackwardButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const buttonSize = useSettingsStore((state) => state.general.buttonSize);
|
||||
const buttonSize = useButtonSize();
|
||||
const { mediaSkipBackward } = usePlayer();
|
||||
|
||||
return (
|
||||
@@ -211,7 +212,7 @@ const CenterPlayButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
|
||||
const SkipForwardButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const buttonSize = useSettingsStore((state) => state.general.buttonSize);
|
||||
const buttonSize = useButtonSize();
|
||||
const { mediaSkipForward } = usePlayer();
|
||||
|
||||
return (
|
||||
@@ -233,7 +234,7 @@ const SkipForwardButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
|
||||
const NextButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const buttonSize = useSettingsStore((state) => state.general.buttonSize);
|
||||
const buttonSize = useButtonSize();
|
||||
const { mediaNext } = usePlayer();
|
||||
|
||||
return (
|
||||
@@ -252,7 +253,7 @@ const NextButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
|
||||
const RepeatButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const buttonSize = useSettingsStore((state) => state.general.buttonSize);
|
||||
const buttonSize = useButtonSize();
|
||||
const repeat = usePlayerRepeat();
|
||||
const { toggleRepeat } = usePlayer();
|
||||
|
||||
@@ -298,7 +299,7 @@ const RepeatButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
|
||||
const ShuffleAllButton = ({ disabled }: { disabled?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const buttonSize = useSettingsStore((state) => state.general.buttonSize);
|
||||
const buttonSize = useButtonSize();
|
||||
|
||||
return (
|
||||
<PlayerButton
|
||||
|
||||
@@ -7,8 +7,7 @@ import styles from './full-screen-player-image.module.css';
|
||||
|
||||
import { useItemImageUrl } from '/@/renderer/components/item-image/item-image';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { usePlayerData, usePlayerSong } from '/@/renderer/store';
|
||||
import { useSettingsStore } from '/@/renderer/store/settings.store';
|
||||
import { useNativeAspectRatio, usePlayerData, usePlayerSong } from '/@/renderer/store';
|
||||
import { Badge } from '/@/shared/components/badge/badge';
|
||||
import { Center } from '/@/shared/components/center/center';
|
||||
import { Flex } from '/@/shared/components/flex/flex';
|
||||
@@ -48,7 +47,7 @@ const ImageWithPlaceholder = ({
|
||||
className,
|
||||
...props
|
||||
}: HTMLMotionProps<'img'> & { placeholder?: string }) => {
|
||||
const nativeAspectRatio = useSettingsStore((store) => store.general.nativeAspectRatio);
|
||||
const nativeAspectRatio = useNativeAspectRatio();
|
||||
|
||||
if (!props.src) {
|
||||
return (
|
||||
|
||||
@@ -7,9 +7,9 @@ import styles from './mobile-fullscreen-player.module.css';
|
||||
import { useItemImageUrl } from '/@/renderer/components/item-image/item-image';
|
||||
import {
|
||||
useFullScreenPlayerStore,
|
||||
useImageRes,
|
||||
usePlayerData,
|
||||
usePlayerSong,
|
||||
useSettingsStore,
|
||||
} from '/@/renderer/store';
|
||||
import { Center } from '/@/shared/components/center/center';
|
||||
import { Icon } from '/@/shared/components/icon/icon';
|
||||
@@ -78,7 +78,7 @@ export const MobileFullscreenPlayerAlbumArt = () => {
|
||||
const mainImageRef = useRef<HTMLImageElement | null>(null);
|
||||
const [mainImageDimensions, setMainImageDimensions] = useState({ idealSize: 1000 });
|
||||
|
||||
const albumArtRes = useSettingsStore((store) => store.general.imageRes.fullScreenPlayer);
|
||||
const { fullScreenPlayer: albumArtRes } = useImageRes();
|
||||
const { useImageAspectRatio } = useFullScreenPlayerStore();
|
||||
const currentSong = usePlayerSong();
|
||||
const { nextSong } = usePlayerData();
|
||||
|
||||
@@ -12,10 +12,12 @@ import {
|
||||
usePlayerStatus,
|
||||
} from '/@/renderer/store';
|
||||
import {
|
||||
useGeneralSettings,
|
||||
useCombinedLyricsAndVisualizer,
|
||||
usePlaybackSettings,
|
||||
useSettingsStore,
|
||||
useSettingsStoreActions,
|
||||
useShowLyricsInSidebar,
|
||||
useShowVisualizerInSidebar,
|
||||
} from '/@/renderer/store/settings.store';
|
||||
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
||||
import { Popover } from '/@/shared/components/popover/popover';
|
||||
@@ -49,7 +51,9 @@ export const PlayerConfig = () => {
|
||||
const { setCrossfadeDuration, setCrossfadeStyle, setQueueType, setSpeed, setTransitionType } =
|
||||
usePlayerActions();
|
||||
const preservePitch = useSettingsStore((state) => state.playback.preservePitch);
|
||||
const generalSettings = useGeneralSettings();
|
||||
const showLyricsInSidebar = useShowLyricsInSidebar();
|
||||
const showVisualizerInSidebar = useShowVisualizerInSidebar();
|
||||
const combinedLyricsAndVisualizer = useCombinedLyricsAndVisualizer();
|
||||
|
||||
const playbackSettings = usePlaybackSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
@@ -325,11 +329,10 @@ export const PlayerConfig = () => {
|
||||
{
|
||||
component: (
|
||||
<Switch
|
||||
defaultChecked={generalSettings.showLyricsInSidebar}
|
||||
defaultChecked={showLyricsInSidebar}
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...generalSettings,
|
||||
showLyricsInSidebar: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -342,11 +345,10 @@ export const PlayerConfig = () => {
|
||||
{
|
||||
component: (
|
||||
<Switch
|
||||
defaultChecked={generalSettings.showVisualizerInSidebar}
|
||||
defaultChecked={showVisualizerInSidebar}
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...generalSettings,
|
||||
showVisualizerInSidebar: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -359,11 +361,10 @@ export const PlayerConfig = () => {
|
||||
{
|
||||
component: (
|
||||
<Switch
|
||||
defaultChecked={generalSettings.combinedLyricsAndVisualizer}
|
||||
defaultChecked={combinedLyricsAndVisualizer}
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...generalSettings,
|
||||
combinedLyricsAndVisualizer: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -395,7 +396,9 @@ export const PlayerConfig = () => {
|
||||
setTransitionType,
|
||||
setCrossfadeStyle,
|
||||
setPreservePitch,
|
||||
generalSettings,
|
||||
showLyricsInSidebar,
|
||||
showVisualizerInSidebar,
|
||||
combinedLyricsAndVisualizer,
|
||||
]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -10,8 +10,8 @@ import { useSongUrl } from '/@/renderer/features/player/audio-player/hooks/use-s
|
||||
import { usePlayer } from '/@/renderer/features/player/context/player-context';
|
||||
import {
|
||||
BarAlign,
|
||||
useGeneralSettings,
|
||||
usePlaybackSettings,
|
||||
usePlayerbarSlider,
|
||||
usePlayerSong,
|
||||
usePlayerTimestamp,
|
||||
} from '/@/renderer/store';
|
||||
@@ -22,7 +22,7 @@ import { Text } from '/@/shared/components/text/text';
|
||||
export const PlayerbarWaveform = () => {
|
||||
const currentSong = usePlayerSong();
|
||||
const { transcode } = usePlaybackSettings();
|
||||
const { playerbarSlider } = useGeneralSettings();
|
||||
const playerbarSlider = usePlayerbarSlider();
|
||||
const currentTime = usePlayerTimestamp();
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const { mediaSeekToTimestamp } = usePlayer();
|
||||
|
||||
@@ -9,11 +9,11 @@ import { MobilePlayerbar } from '/@/renderer/features/player/components/mobile-p
|
||||
import { RightControls } from '/@/renderer/features/player/components/right-controls';
|
||||
import { useIsMobile } from '/@/renderer/hooks/use-is-mobile';
|
||||
import { useFullScreenPlayerStore, useSetFullScreenPlayerStore } from '/@/renderer/store';
|
||||
import { useGeneralSettings } from '/@/renderer/store/settings.store';
|
||||
import { usePlayerbarOpenDrawer } from '/@/renderer/store';
|
||||
import { PlaybackSelectors } from '/@/shared/constants/playback-selectors';
|
||||
|
||||
export const Playerbar = () => {
|
||||
const { playerbarOpenDrawer } = useGeneralSettings();
|
||||
const playerbarOpenDrawer = usePlayerbarOpenDrawer();
|
||||
const { expanded: isFullScreenPlayerExpanded } = useFullScreenPlayerStore();
|
||||
const setFullScreenPlayerStore = useSetFullScreenPlayerStore();
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
@@ -14,16 +14,17 @@ import {
|
||||
useAutoDJSettings,
|
||||
useCurrentServer,
|
||||
useFullScreenPlayerStore,
|
||||
useGeneralSettings,
|
||||
useHotkeySettings,
|
||||
usePlayerData,
|
||||
usePlayerMuted,
|
||||
usePlayerSong,
|
||||
usePlayerVolume,
|
||||
useSetFullScreenPlayerStore,
|
||||
useSettingsStore,
|
||||
useSettingsStoreActions,
|
||||
useSidebarRightExpanded,
|
||||
useSideQueueType,
|
||||
useVolumeWheelStep,
|
||||
useVolumeWidth,
|
||||
} from '/@/renderer/store';
|
||||
import { useFullScreenPlayerStoreActions } from '/@/renderer/store/full-screen-player.store';
|
||||
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
||||
@@ -114,7 +115,7 @@ const QueueButton = () => {
|
||||
const { t } = useTranslation();
|
||||
const isSidebarRightExpanded = useSidebarRightExpanded();
|
||||
const { setSideBar } = useAppStoreActions();
|
||||
const { sideQueueType } = useGeneralSettings();
|
||||
const sideQueueType = useSideQueueType();
|
||||
|
||||
const { bindings } = useHotkeySettings();
|
||||
|
||||
@@ -355,8 +356,8 @@ const VolumeButton = () => {
|
||||
const { bindings } = useHotkeySettings();
|
||||
const volume = usePlayerVolume();
|
||||
const muted = usePlayerMuted();
|
||||
const { volumeWheelStep } = useGeneralSettings();
|
||||
const volumeWidth = useSettingsStore((state) => state.general.volumeWidth);
|
||||
const volumeWheelStep = useVolumeWheelStep();
|
||||
const volumeWidth = useVolumeWidth();
|
||||
const { mediaToggleMute, setVolume } = usePlayer();
|
||||
const isMinWidth = useMediaQuery('(max-width: 480px)');
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
usePlaybackSettings,
|
||||
usePlayerStore,
|
||||
useSettingsStore,
|
||||
useSkipButtons,
|
||||
useTimestampStoreBase,
|
||||
} from '/@/renderer/store';
|
||||
import { LibraryItem, QueueSong } from '/@/shared/types/domain-types';
|
||||
@@ -18,7 +19,7 @@ const mediaSession = navigator.mediaSession;
|
||||
export const useMediaSession = () => {
|
||||
const { mediaSession: mediaSessionEnabled } = usePlaybackSettings();
|
||||
const player = usePlayer();
|
||||
const skip = useSettingsStore((state) => state.general.skipButtons);
|
||||
const skip = useSkipButtons();
|
||||
const playbackType = useSettingsStore((state) => state.playback.type);
|
||||
|
||||
const isMediaSessionEnabled = useMemo(() => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { memo } from 'react';
|
||||
import { Fragment } from 'react/jsx-runtime';
|
||||
|
||||
import { AnalyticsSettings } from '/@/renderer/features/settings/components/advanced/analytics-settings';
|
||||
@@ -16,7 +17,7 @@ const sections = [
|
||||
{ component: CacheSettings, key: 'cache' },
|
||||
];
|
||||
|
||||
export const AdvancedTab = () => {
|
||||
export const AdvancedTab = memo(() => {
|
||||
return (
|
||||
<Stack gap="md">
|
||||
{sections.map(({ component: Section, key }, index) => (
|
||||
@@ -27,4 +28,4 @@ export const AdvancedTab = () => {
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
@@ -6,7 +7,7 @@ import {
|
||||
} from '/@/renderer/features/settings/components/settings-section';
|
||||
import { Switch } from '/@/shared/components/switch/switch';
|
||||
|
||||
export const AnalyticsSettings = () => {
|
||||
export const AnalyticsSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleToggleAnalytics = (disable: boolean) => {
|
||||
@@ -36,4 +37,4 @@ export const AnalyticsSettings = () => {
|
||||
title={t('page.setting.analytics', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { openModal } from '@mantine/modals';
|
||||
import { t } from 'i18next';
|
||||
import { useCallback } from 'react';
|
||||
import { memo, useCallback } from 'react';
|
||||
|
||||
import { ExportImportSettingsModal } from '/@/renderer/components/export-import-settings-modal/export-import-settings-modal';
|
||||
import {
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
import { useSettingsForExport } from '/@/renderer/store';
|
||||
import { Button } from '/@/shared/components/button/button';
|
||||
|
||||
export const ExportImportSettings = () => {
|
||||
export const ExportImportSettings = memo(() => {
|
||||
const settingForExport = useSettingsForExport();
|
||||
|
||||
const onExportSettings = useCallback(() => {
|
||||
@@ -68,4 +68,4 @@ export const ExportImportSettings = () => {
|
||||
title={t('page.setting.exportImport', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
@@ -9,7 +10,7 @@ import { Select } from '/@/shared/components/select/select';
|
||||
|
||||
const DEFAULT_LOG_LEVEL: LogLevel = process.env.NODE_ENV === 'production' ? 'info' : 'debug';
|
||||
|
||||
export const LoggerSettings = () => {
|
||||
export const LoggerSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const getCurrentLogLevel = (): LogLevel => {
|
||||
@@ -84,4 +85,4 @@ export const LoggerSettings = () => {
|
||||
title={t('page.setting.logger', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { memo, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { SettingsOptions } from '/@/renderer/features/settings/components/settings-option';
|
||||
@@ -10,7 +10,7 @@ import { Switch } from '/@/shared/components/switch/switch';
|
||||
import { Text } from '/@/shared/components/text/text';
|
||||
import { Textarea } from '/@/shared/components/textarea/textarea';
|
||||
|
||||
export const StylesSettings = () => {
|
||||
export const StylesSettings = memo(() => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -108,4 +108,4 @@ export const StylesSettings = () => {
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { IpcRendererEvent } from 'electron';
|
||||
|
||||
import { t } from 'i18next';
|
||||
import isElectron from 'is-electron';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { memo, useCallback, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import i18n, { languages } from '/@/i18n/i18n';
|
||||
@@ -78,7 +78,7 @@ if (isElectron()) {
|
||||
});
|
||||
}
|
||||
|
||||
export const ApplicationSettings = () => {
|
||||
export const ApplicationSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const settings = useGeneralSettings();
|
||||
const fontSettings = useFontSettings();
|
||||
@@ -618,4 +618,4 @@ export const ApplicationSettings = () => {
|
||||
title={t('page.setting.application', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import { memo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import i18n from '/@/i18n/i18n';
|
||||
@@ -34,7 +34,7 @@ const options = [
|
||||
},
|
||||
];
|
||||
|
||||
export const ImageResolutionSettings = () => {
|
||||
export const ImageResolutionSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
const settings = useGeneralSettings();
|
||||
@@ -108,4 +108,4 @@ export const ImageResolutionSettings = () => {
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { memo } from 'react';
|
||||
|
||||
import { DraggableItems } from '/@/renderer/features/settings/components/general/draggable-items';
|
||||
import {
|
||||
ArtistItem,
|
||||
@@ -14,7 +16,7 @@ const ARTIST_ITEMS: Array<[ArtistItem, string]> = [
|
||||
[ArtistItem.SIMILAR_ARTISTS, 'page.albumArtistDetail.relatedArtists'],
|
||||
];
|
||||
|
||||
export const ArtistSettings = () => {
|
||||
export const ArtistSettings = memo(() => {
|
||||
const { artistItems } = useGeneralSettings();
|
||||
const { setArtistItems } = useSettingsStoreActions();
|
||||
|
||||
@@ -27,7 +29,7 @@ export const ArtistSettings = () => {
|
||||
title="setting.artistConfiguration"
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
const ARTIST_RELEASE_TYPE_ITEMS: Array<[ArtistReleaseTypeItem, string]> = [
|
||||
[ArtistReleaseTypeItem.APPEARS_ON, 'page.albumArtistDetail.appearsOn'],
|
||||
@@ -50,7 +52,7 @@ const ARTIST_RELEASE_TYPE_ITEMS: Array<[ArtistReleaseTypeItem, string]> = [
|
||||
[ArtistReleaseTypeItem.RELEASE_TYPE_SPOKENWORD, 'releaseType.secondary.spokenWord'],
|
||||
];
|
||||
|
||||
export const ArtistReleaseTypeSettings = () => {
|
||||
export const ArtistReleaseTypeSettings = memo(() => {
|
||||
const { artistReleaseTypeItems } = useGeneralSettings();
|
||||
const { setArtistReleaseTypeItems } = useSettingsStoreActions();
|
||||
|
||||
@@ -63,4 +65,4 @@ export const ArtistReleaseTypeSettings = () => {
|
||||
title="setting.artistReleaseTypeConfiguration"
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
@@ -21,7 +22,7 @@ import { Text } from '/@/shared/components/text/text';
|
||||
import { Tooltip } from '/@/shared/components/tooltip/tooltip';
|
||||
import { Play } from '/@/shared/types/types';
|
||||
|
||||
export const ControlSettings = () => {
|
||||
export const ControlSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const settings = useGeneralSettings();
|
||||
const playerbarSlider = usePlayerbarSlider();
|
||||
@@ -486,4 +487,4 @@ export const ControlSettings = () => {
|
||||
title={t('page.setting.controls', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useMemo } from 'react';
|
||||
import { memo, useMemo } from 'react';
|
||||
import { Fragment } from 'react/jsx-runtime';
|
||||
|
||||
import { ApplicationSettings } from '/@/renderer/features/settings/components/general/application-settings';
|
||||
@@ -14,7 +14,7 @@ import { Divider } from '/@/shared/components/divider/divider';
|
||||
import { Stack } from '/@/shared/components/stack/stack';
|
||||
import { ServerFeature } from '/@/shared/types/features-types';
|
||||
|
||||
export const GeneralTab = () => {
|
||||
export const GeneralTab = memo(() => {
|
||||
const server = useCurrentServer();
|
||||
const supportsSmartPlaylists = hasFeature(server, ServerFeature.PLAYLISTS_SMART);
|
||||
|
||||
@@ -45,4 +45,4 @@ export const GeneralTab = () => {
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { memo } from 'react';
|
||||
|
||||
import { DraggableItems } from '/@/renderer/features/settings/components/general/draggable-items';
|
||||
import {
|
||||
HomeItem,
|
||||
@@ -15,7 +17,7 @@ const HOME_ITEMS: Array<[string, string]> = [
|
||||
[HomeItem.MOST_PLAYED, 'page.home.mostPlayed'],
|
||||
];
|
||||
|
||||
export const HomeSettings = () => {
|
||||
export const HomeSettings = memo(() => {
|
||||
const { homeItems } = useGeneralSettings();
|
||||
const { setHomeItems } = useSettingsStoreActions();
|
||||
|
||||
@@ -28,4 +30,4 @@ export const HomeSettings = () => {
|
||||
title="setting.homeConfiguration"
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import isElectron from 'is-electron';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { languages } from '/@/i18n/i18n';
|
||||
@@ -16,7 +17,7 @@ import { LyricSource } from '/@/shared/types/domain-types';
|
||||
|
||||
const localSettings = isElectron() ? window.api.localSettings : null;
|
||||
|
||||
export const LyricSettings = () => {
|
||||
export const LyricSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const settings = useLyricsSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
@@ -210,4 +211,4 @@ export const LyricSettings = () => {
|
||||
title={t('page.setting.lyrics', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,22 +1,19 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { memo, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { songsQueries } from '/@/renderer/features/songs/api/songs-api';
|
||||
import {
|
||||
useCurrentServerId,
|
||||
useGeneralSettings,
|
||||
useSettingsStore,
|
||||
useSettingsStoreActions,
|
||||
} from '/@/renderer/store';
|
||||
import { useCurrentServerId, useGeneralSettings, useSettingsStoreActions } from '/@/renderer/store';
|
||||
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
||||
import { Code } from '/@/shared/components/code/code';
|
||||
import { Group } from '/@/shared/components/group/group';
|
||||
import { Stack } from '/@/shared/components/stack/stack';
|
||||
import { TextInput } from '/@/shared/components/text-input/text-input';
|
||||
import { Text } from '/@/shared/components/text/text';
|
||||
import { useDebouncedCallback } from '/@/shared/hooks/use-debounced-callback';
|
||||
import { Played } from '/@/shared/types/domain-types';
|
||||
|
||||
export const PathSettings = () => {
|
||||
export const PathSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const serverId = useCurrentServerId();
|
||||
const randomSong = useQuery({
|
||||
@@ -31,6 +28,37 @@ export const PathSettings = () => {
|
||||
const { pathReplace, pathReplaceWith } = useGeneralSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
|
||||
const [localPathReplace, setLocalPathReplace] = useState(pathReplace);
|
||||
const [localPathReplaceWith, setLocalPathReplaceWith] = useState(pathReplaceWith);
|
||||
|
||||
useEffect(() => {
|
||||
setLocalPathReplace(pathReplace);
|
||||
}, [pathReplace]);
|
||||
|
||||
useEffect(() => {
|
||||
setLocalPathReplaceWith(pathReplaceWith);
|
||||
}, [pathReplaceWith]);
|
||||
|
||||
const debouncedSetPathReplace = useDebouncedCallback((value: string) => {
|
||||
setSettings({
|
||||
general: {
|
||||
pathReplace: value,
|
||||
},
|
||||
});
|
||||
|
||||
randomSong.refetch();
|
||||
}, 500);
|
||||
|
||||
const debouncedSetPathReplaceWith = useDebouncedCallback((value: string) => {
|
||||
setSettings({
|
||||
general: {
|
||||
pathReplaceWith: value,
|
||||
},
|
||||
});
|
||||
|
||||
randomSong.refetch();
|
||||
}, 500);
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<Group>
|
||||
@@ -50,34 +78,28 @@ export const PathSettings = () => {
|
||||
</Code>
|
||||
<Group grow>
|
||||
<TextInput
|
||||
onChange={(e) =>
|
||||
setSettings({
|
||||
general: {
|
||||
...useSettingsStore.getState().general,
|
||||
pathReplace: e.currentTarget.value,
|
||||
},
|
||||
})
|
||||
}
|
||||
onChange={(e) => {
|
||||
const value = e.currentTarget.value;
|
||||
setLocalPathReplace(value);
|
||||
debouncedSetPathReplace(value);
|
||||
}}
|
||||
placeholder={t('setting.pathReplace_optionRemovePrefix', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
value={pathReplace}
|
||||
value={localPathReplace}
|
||||
/>
|
||||
<TextInput
|
||||
onChange={(e) =>
|
||||
setSettings({
|
||||
general: {
|
||||
...useSettingsStore.getState().general,
|
||||
pathReplaceWith: e.currentTarget.value,
|
||||
},
|
||||
})
|
||||
}
|
||||
onChange={(e) => {
|
||||
const value = e.currentTarget.value;
|
||||
setLocalPathReplaceWith(value);
|
||||
debouncedSetPathReplaceWith(value);
|
||||
}}
|
||||
placeholder={t('setting.pathReplace_optionAddPrefix', {
|
||||
postProcess: 'sentenceCase',
|
||||
})}
|
||||
value={pathReplaceWith}
|
||||
value={localPathReplaceWith}
|
||||
/>
|
||||
</Group>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
@@ -21,7 +22,7 @@ const QUERY_VALUE_INPUT_TYPES = [
|
||||
{ label: 'String', value: 'string' },
|
||||
] as const;
|
||||
|
||||
export const QueryBuilderSettings = () => {
|
||||
export const QueryBuilderSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const queryBuilder = useQueryBuilderSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
@@ -148,4 +149,4 @@ export const QueryBuilderSettings = () => {
|
||||
})}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
@@ -10,7 +11,7 @@ import { Slider } from '/@/shared/components/slider/slider';
|
||||
import { Switch } from '/@/shared/components/switch/switch';
|
||||
import { toast } from '/@/shared/components/toast/toast';
|
||||
|
||||
export const ScrobbleSettings = () => {
|
||||
export const ScrobbleSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const settings = usePlaybackSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
@@ -24,9 +25,7 @@ export const ScrobbleSettings = () => {
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
playback: {
|
||||
...settings,
|
||||
scrobble: {
|
||||
...settings.scrobble,
|
||||
enabled: e.currentTarget.checked,
|
||||
},
|
||||
},
|
||||
@@ -51,9 +50,7 @@ export const ScrobbleSettings = () => {
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
playback: {
|
||||
...settings,
|
||||
scrobble: {
|
||||
...settings.scrobble,
|
||||
scrobbleAtPercentage: e,
|
||||
},
|
||||
},
|
||||
@@ -79,9 +76,7 @@ export const ScrobbleSettings = () => {
|
||||
if (e === '') return;
|
||||
setSettings({
|
||||
playback: {
|
||||
...settings,
|
||||
scrobble: {
|
||||
...settings.scrobble,
|
||||
scrobbleAtDuration: Number(e),
|
||||
},
|
||||
},
|
||||
@@ -125,9 +120,7 @@ export const ScrobbleSettings = () => {
|
||||
|
||||
setSettings({
|
||||
playback: {
|
||||
...settings,
|
||||
scrobble: {
|
||||
...settings.scrobble,
|
||||
notify: e.currentTarget.checked,
|
||||
},
|
||||
},
|
||||
@@ -150,4 +143,4 @@ export const ScrobbleSettings = () => {
|
||||
title={t('page.setting.scrobble', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChangeEvent } from 'react';
|
||||
import { ChangeEvent, memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { SidebarReorder } from '/@/renderer/features/settings/components/general/sidebar-reorder';
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
import { useGeneralSettings, useSettingsStoreActions } from '/@/renderer/store';
|
||||
import { Switch } from '/@/shared/components/switch/switch';
|
||||
|
||||
export const SidebarSettings = () => {
|
||||
export const SidebarSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const settings = useGeneralSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
@@ -17,7 +17,6 @@ export const SidebarSettings = () => {
|
||||
const handleSetSidebarPlaylistList = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
sidebarPlaylistList: e.target.checked,
|
||||
},
|
||||
});
|
||||
@@ -26,7 +25,6 @@ export const SidebarSettings = () => {
|
||||
const handleSetSidebarCollapsedNavigation = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
sidebarCollapsedNavigation: e.target.checked,
|
||||
},
|
||||
});
|
||||
@@ -67,7 +65,6 @@ export const SidebarSettings = () => {
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
showLyricsInSidebar: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -88,7 +85,6 @@ export const SidebarSettings = () => {
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
showVisualizerInSidebar: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -109,7 +105,6 @@ export const SidebarSettings = () => {
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
combinedLyricsAndVisualizer: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -131,4 +126,4 @@ export const SidebarSettings = () => {
|
||||
title={t('page.setting.sidebar', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import isElectron from 'is-electron';
|
||||
import { useMemo } from 'react';
|
||||
import { memo, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import i18n from '/@/i18n/i18n';
|
||||
@@ -85,7 +85,7 @@ const renderThemeOption = ({ option }: { option: { label: string; value: string
|
||||
);
|
||||
};
|
||||
|
||||
export const ThemeSettings = () => {
|
||||
export const ThemeSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const settings = useGeneralSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
@@ -101,7 +101,6 @@ export const ThemeSettings = () => {
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
followSystemTheme: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -135,7 +134,6 @@ export const ThemeSettings = () => {
|
||||
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
theme,
|
||||
},
|
||||
});
|
||||
@@ -167,7 +165,6 @@ export const ThemeSettings = () => {
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
themeDark: e as AppTheme,
|
||||
},
|
||||
});
|
||||
@@ -191,7 +188,6 @@ export const ThemeSettings = () => {
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
themeLight: e as AppTheme,
|
||||
},
|
||||
});
|
||||
@@ -214,7 +210,6 @@ export const ThemeSettings = () => {
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
useThemeAccentColor: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -238,7 +233,6 @@ export const ThemeSettings = () => {
|
||||
onChangeEnd={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
accent: e,
|
||||
},
|
||||
});
|
||||
@@ -270,4 +264,4 @@ export const ThemeSettings = () => {
|
||||
title={t('page.setting.theme', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import isElectron from 'is-electron';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { ChangeEvent, KeyboardEvent, useCallback, useMemo, useState } from 'react';
|
||||
import { ChangeEvent, KeyboardEvent, memo, useCallback, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import styles from './hotkeys-manager-settings.module.css';
|
||||
@@ -120,9 +120,9 @@ const BINDINGS_MAP: Record<BindingActions, string> = {
|
||||
zoomOut: i18n.t('setting.hotkey', { context: 'zoomOut', postProcess: 'sentenceCase' }),
|
||||
};
|
||||
|
||||
export const HotkeyManagerSettings = () => {
|
||||
export const HotkeyManagerSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const { bindings, globalMediaHotkeys } = useHotkeySettings();
|
||||
const { bindings } = useHotkeySettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
const [selected, setSelected] = useState<BindingActions | null>(null);
|
||||
const keyword = useSettingSearchContext();
|
||||
@@ -162,7 +162,6 @@ export const HotkeyManagerSettings = () => {
|
||||
setSettings({
|
||||
hotkeys: {
|
||||
bindings: updatedBindings,
|
||||
globalMediaHotkeys,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -188,13 +187,12 @@ export const HotkeyManagerSettings = () => {
|
||||
setSettings({
|
||||
hotkeys: {
|
||||
bindings: updatedBindings,
|
||||
globalMediaHotkeys,
|
||||
},
|
||||
});
|
||||
|
||||
ipc?.send('set-global-shortcuts', updatedBindings);
|
||||
},
|
||||
[bindings, globalMediaHotkeys, setSettings],
|
||||
[bindings, setSettings],
|
||||
);
|
||||
|
||||
const handleClearHotkey = useCallback(
|
||||
@@ -207,13 +205,12 @@ export const HotkeyManagerSettings = () => {
|
||||
setSettings({
|
||||
hotkeys: {
|
||||
bindings: updatedBindings,
|
||||
globalMediaHotkeys,
|
||||
},
|
||||
});
|
||||
|
||||
ipc?.send('set-global-shortcuts', updatedBindings);
|
||||
},
|
||||
[bindings, globalMediaHotkeys, setSettings],
|
||||
[bindings, setSettings],
|
||||
);
|
||||
|
||||
const duplicateHotkeyMap = useMemo(() => {
|
||||
@@ -367,4 +364,4 @@ export const HotkeyManagerSettings = () => {
|
||||
options={options}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import isElectron from 'is-electron';
|
||||
import { memo } from 'react';
|
||||
import { Fragment } from 'react/jsx-runtime';
|
||||
|
||||
import { HotkeyManagerSettings } from '/@/renderer/features/settings/components/hotkeys/hotkey-manager-settings';
|
||||
@@ -13,7 +14,7 @@ const sections = [
|
||||
{ component: HotkeyManagerSettings, key: 'hotkey-manager' },
|
||||
];
|
||||
|
||||
export const HotkeysTab = () => {
|
||||
export const HotkeysTab = memo(() => {
|
||||
return (
|
||||
<Stack gap="md">
|
||||
{sections.map(({ component: Section, hidden, key }, index) => (
|
||||
@@ -24,4 +25,4 @@ export const HotkeysTab = () => {
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import isElectron from 'is-electron';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
@@ -6,11 +7,7 @@ import {
|
||||
SettingsSection,
|
||||
} from '/@/renderer/features/settings/components/settings-section';
|
||||
import { openRestartRequiredToast } from '/@/renderer/features/settings/restart-toast';
|
||||
import {
|
||||
useHotkeySettings,
|
||||
usePlaybackSettings,
|
||||
useSettingsStoreActions,
|
||||
} from '/@/renderer/store/settings.store';
|
||||
import { usePlaybackSettings, useSettingsStoreActions } from '/@/renderer/store/settings.store';
|
||||
import { Switch } from '/@/shared/components/switch/switch';
|
||||
import { PlayerType } from '/@/shared/types/types';
|
||||
|
||||
@@ -18,11 +15,9 @@ const isLinux = isElectron() ? window.api.utils.isLinux() : false;
|
||||
const isDesktop = isElectron();
|
||||
const localSettings = isElectron() ? window.api.localSettings : null;
|
||||
|
||||
export const MediaSessionSettings = () => {
|
||||
export const MediaSessionSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const { mediaSession, type: playbackType } = usePlaybackSettings();
|
||||
const playbackSettings = usePlaybackSettings();
|
||||
const hotkeySettings = useHotkeySettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
|
||||
function handleMediaSessionChange(e: boolean) {
|
||||
@@ -31,7 +26,6 @@ export const MediaSessionSettings = () => {
|
||||
localSettings!.set('global_media_hotkeys', false);
|
||||
setSettings({
|
||||
hotkeys: {
|
||||
...hotkeySettings,
|
||||
globalMediaHotkeys: false,
|
||||
},
|
||||
});
|
||||
@@ -40,7 +34,6 @@ export const MediaSessionSettings = () => {
|
||||
localSettings!.set('mediaSession', e);
|
||||
setSettings({
|
||||
playback: {
|
||||
...playbackSettings,
|
||||
mediaSession: e,
|
||||
},
|
||||
});
|
||||
@@ -70,4 +63,4 @@ export const MediaSessionSettings = () => {
|
||||
];
|
||||
|
||||
return <SettingsSection options={mediaSessionOptions} />;
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import isElectron from 'is-electron';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
@@ -11,10 +12,9 @@ import { Switch } from '/@/shared/components/switch/switch';
|
||||
|
||||
const localSettings = isElectron() ? window.api.localSettings : null;
|
||||
|
||||
export const WindowHotkeySettings = () => {
|
||||
export const WindowHotkeySettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const settings = useHotkeySettings();
|
||||
const playbackSettings = usePlaybackSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
const { mediaSession } = usePlaybackSettings();
|
||||
|
||||
@@ -28,7 +28,6 @@ export const WindowHotkeySettings = () => {
|
||||
localSettings!.set('global_media_hotkeys', e.currentTarget.checked);
|
||||
setSettings({
|
||||
hotkeys: {
|
||||
...settings,
|
||||
globalMediaHotkeys: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -45,7 +44,6 @@ export const WindowHotkeySettings = () => {
|
||||
localSettings!.set('mediaSession', false);
|
||||
setSettings({
|
||||
playback: {
|
||||
...playbackSettings,
|
||||
mediaSession: false,
|
||||
},
|
||||
});
|
||||
@@ -64,4 +62,4 @@ export const WindowHotkeySettings = () => {
|
||||
];
|
||||
|
||||
return <SettingsSection options={options} />;
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import isElectron from 'is-electron';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { memo, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
@@ -20,7 +20,7 @@ const getAudioDevice = async () => {
|
||||
return (devices || []).filter((dev: MediaDeviceInfo) => dev.kind === 'audiooutput');
|
||||
};
|
||||
|
||||
export const AudioSettings = () => {
|
||||
export const AudioSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const settings = usePlaybackSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
@@ -61,7 +61,7 @@ export const AudioSettings = () => {
|
||||
defaultValue={settings.type}
|
||||
disabled={status === PlayerStatus.PLAYING}
|
||||
onChange={(e) => {
|
||||
setSettings({ playback: { ...settings, type: e as PlayerType } });
|
||||
setSettings({ playback: { type: e as PlayerType } });
|
||||
ipc?.send('settings-set', { property: 'playbackType', value: e });
|
||||
}}
|
||||
/>
|
||||
@@ -84,7 +84,7 @@ export const AudioSettings = () => {
|
||||
data={audioDevices}
|
||||
defaultValue={settings.audioDeviceId}
|
||||
disabled={settings.type !== PlayerType.WEB}
|
||||
onChange={(e) => setSettings({ playback: { ...settings, audioDeviceId: e } })}
|
||||
onChange={(e) => setSettings({ playback: { audioDeviceId: e } })}
|
||||
/>
|
||||
),
|
||||
description: t('setting.audioDevice', {
|
||||
@@ -100,7 +100,7 @@ export const AudioSettings = () => {
|
||||
defaultChecked={settings.webAudio}
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
playback: { ...settings, webAudio: e.currentTarget.checked },
|
||||
playback: { webAudio: e.currentTarget.checked },
|
||||
});
|
||||
}}
|
||||
/>
|
||||
@@ -121,7 +121,7 @@ export const AudioSettings = () => {
|
||||
defaultChecked={settings.preservePitch}
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
playback: { ...settings, preservePitch: e.currentTarget.checked },
|
||||
playback: { preservePitch: e.currentTarget.checked },
|
||||
});
|
||||
}}
|
||||
/>
|
||||
@@ -142,7 +142,6 @@ export const AudioSettings = () => {
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
playback: {
|
||||
...settings,
|
||||
audioFadeOnStatusChange: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -165,4 +164,4 @@ export const AudioSettings = () => {
|
||||
title={t('page.setting.audio', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
@@ -7,7 +8,7 @@ import {
|
||||
import { useAutoDJSettings, useSettingsStoreActions } from '/@/renderer/store/settings.store';
|
||||
import { NumberInput } from '/@/shared/components/number-input/number-input';
|
||||
|
||||
export const AutoDJSettings = () => {
|
||||
export const AutoDJSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const settings = useAutoDJSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
@@ -23,7 +24,6 @@ export const AutoDJSettings = () => {
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
autoDJ: {
|
||||
...settings,
|
||||
itemCount: Number(e),
|
||||
},
|
||||
});
|
||||
@@ -47,7 +47,6 @@ export const AutoDJSettings = () => {
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
autoDJ: {
|
||||
...settings,
|
||||
timing: Number(e),
|
||||
},
|
||||
});
|
||||
@@ -69,4 +68,4 @@ export const AutoDJSettings = () => {
|
||||
title={t('setting.autoDJ', { postProcess: 'titleCase' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import isElectron from 'is-electron';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { memo, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
@@ -68,7 +68,7 @@ export const getMpvProperties = (settings: SettingsState['playback']['mpvPropert
|
||||
return properties;
|
||||
};
|
||||
|
||||
export const MpvSettings = () => {
|
||||
export const MpvSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const settings = usePlaybackSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
@@ -114,9 +114,7 @@ export const MpvSettings = () => {
|
||||
) => {
|
||||
setSettings({
|
||||
playback: {
|
||||
...settings,
|
||||
mpvProperties: {
|
||||
...settings.mpvProperties,
|
||||
[setting]: value,
|
||||
},
|
||||
},
|
||||
@@ -146,7 +144,6 @@ export const MpvSettings = () => {
|
||||
const handleSetExtraParameters = (data: string[]) => {
|
||||
setSettings({
|
||||
playback: {
|
||||
...settings,
|
||||
mpvExtraParameters: data,
|
||||
},
|
||||
});
|
||||
@@ -421,4 +418,4 @@ export const MpvSettings = () => {
|
||||
<SettingsSection options={replayGainOptions} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import isElectron from 'is-electron';
|
||||
import { lazy, Suspense, useMemo } from 'react';
|
||||
import { lazy, memo, Suspense, useMemo } from 'react';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
|
||||
import { AudioSettings } from '/@/renderer/features/settings/components/playback/audio-settings';
|
||||
import { AutoDJSettings } from '/@/renderer/features/settings/components/playback/auto-dj-settings';
|
||||
@@ -16,9 +17,14 @@ const MpvSettings = lazy(() =>
|
||||
}),
|
||||
);
|
||||
|
||||
export const PlaybackTab = () => {
|
||||
const audioType = useSettingsStore((state) => state.playback.type);
|
||||
const useWebAudio = useSettingsStore((state) => state.playback.webAudio);
|
||||
export const PlaybackTab = memo(() => {
|
||||
const { audioType, useWebAudio } = useSettingsStore(
|
||||
(state) => ({
|
||||
audioType: state.playback.type,
|
||||
useWebAudio: state.playback.webAudio,
|
||||
}),
|
||||
shallow,
|
||||
);
|
||||
|
||||
const hasFancyAudio = useMemo(() => {
|
||||
return (
|
||||
@@ -39,4 +45,4 @@ export const PlaybackTab = () => {
|
||||
<AutoDJSettings />
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { nanoid } from 'nanoid/non-secure';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
@@ -262,7 +262,7 @@ const FilterValueInput = ({
|
||||
}
|
||||
};
|
||||
|
||||
export const PlayerFilterSettings = () => {
|
||||
export const PlayerFilterSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const filters = useSettingsStore((state) => state.playback.filters);
|
||||
const { setPlaybackFilters } = useSettingsStoreActions();
|
||||
@@ -432,4 +432,4 @@ export const PlayerFilterSettings = () => {
|
||||
title={t('page.setting.playerFilters', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
@@ -9,7 +10,7 @@ import { NumberInput } from '/@/shared/components/number-input/number-input';
|
||||
import { Switch } from '/@/shared/components/switch/switch';
|
||||
import { TextInput } from '/@/shared/components/text-input/text-input';
|
||||
|
||||
export const TranscodeSettings = () => {
|
||||
export const TranscodeSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const { transcode } = usePlaybackSettings();
|
||||
const { setTranscodingConfig } = useSettingsStoreActions();
|
||||
@@ -92,4 +93,4 @@ export const TranscodeSettings = () => {
|
||||
title={t('page.setting.transcoding', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { memo } from 'react';
|
||||
|
||||
import { Group } from '/@/shared/components/group/group';
|
||||
import { Icon } from '/@/shared/components/icon/icon';
|
||||
@@ -13,38 +13,40 @@ interface SettingsOptionProps {
|
||||
title: React.ReactNode | string;
|
||||
}
|
||||
|
||||
export const SettingsOptions = ({ control, description, note, title }: SettingsOptionProps) => {
|
||||
return (
|
||||
<>
|
||||
<Group justify="space-between" style={{ alignItems: 'center' }} wrap="nowrap">
|
||||
<Stack
|
||||
gap="xs"
|
||||
style={{
|
||||
alignSelf: 'flex-start',
|
||||
display: 'flex',
|
||||
maxWidth: '50%',
|
||||
}}
|
||||
>
|
||||
<Group>
|
||||
<Text isNoSelect size="md">
|
||||
{title}
|
||||
</Text>
|
||||
{note && (
|
||||
<Tooltip label={note} openDelay={0}>
|
||||
<Icon icon="info" />
|
||||
</Tooltip>
|
||||
export const SettingsOptions = memo(
|
||||
({ control, description, note, title }: SettingsOptionProps) => {
|
||||
return (
|
||||
<>
|
||||
<Group justify="space-between" style={{ alignItems: 'center' }} wrap="nowrap">
|
||||
<Stack
|
||||
gap="xs"
|
||||
style={{
|
||||
alignSelf: 'flex-start',
|
||||
display: 'flex',
|
||||
maxWidth: '50%',
|
||||
}}
|
||||
>
|
||||
<Group>
|
||||
<Text isNoSelect size="md">
|
||||
{title}
|
||||
</Text>
|
||||
{note && (
|
||||
<Tooltip label={note} openDelay={0}>
|
||||
<Icon icon="info" />
|
||||
</Tooltip>
|
||||
)}
|
||||
</Group>
|
||||
{React.isValidElement(description) ? (
|
||||
description
|
||||
) : (
|
||||
<Text isMuted isNoSelect size="sm">
|
||||
{description}
|
||||
</Text>
|
||||
)}
|
||||
</Group>
|
||||
{React.isValidElement(description) ? (
|
||||
description
|
||||
) : (
|
||||
<Text isMuted isNoSelect size="sm">
|
||||
{description}
|
||||
</Text>
|
||||
)}
|
||||
</Stack>
|
||||
<Group justify="flex-end">{control}</Group>
|
||||
</Group>
|
||||
</>
|
||||
);
|
||||
};
|
||||
</Stack>
|
||||
<Group justify="flex-end">{control}</Group>
|
||||
</Group>
|
||||
</>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { closeAllModals, openModal } from '@mantine/modals';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import isElectron from 'is-electron';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { memo, useCallback, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
@@ -14,7 +14,7 @@ import { toast } from '/@/shared/components/toast/toast';
|
||||
|
||||
const browser = isElectron() ? window.api.browser : null;
|
||||
|
||||
export const CacheSettings = () => {
|
||||
export const CacheSettings = memo(() => {
|
||||
const [isClearing, setIsClearing] = useState(false);
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
@@ -115,4 +115,4 @@ export const CacheSettings = () => {
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import isElectron from 'is-electron';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
@@ -16,7 +17,7 @@ import { Select } from '/@/shared/components/select/select';
|
||||
import { Switch } from '/@/shared/components/switch/switch';
|
||||
import { TextInput } from '/@/shared/components/text-input/text-input';
|
||||
|
||||
export const DiscordSettings = () => {
|
||||
export const DiscordSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const settings = useDiscordSettings();
|
||||
const generalSettings = useGeneralSettings();
|
||||
@@ -30,7 +31,6 @@ export const DiscordSettings = () => {
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
discord: {
|
||||
...settings,
|
||||
enabled: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -58,7 +58,6 @@ export const DiscordSettings = () => {
|
||||
onBlur={(e) => {
|
||||
setSettings({
|
||||
discord: {
|
||||
...settings,
|
||||
clientId: e.currentTarget.value,
|
||||
},
|
||||
});
|
||||
@@ -84,7 +83,6 @@ export const DiscordSettings = () => {
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
discord: {
|
||||
...settings,
|
||||
showPaused: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -107,7 +105,6 @@ export const DiscordSettings = () => {
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
discord: {
|
||||
...settings,
|
||||
showAsListening: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -150,7 +147,6 @@ export const DiscordSettings = () => {
|
||||
if (!e) return;
|
||||
setSettings({
|
||||
discord: {
|
||||
...settings,
|
||||
displayType: e as DiscordDisplayType,
|
||||
},
|
||||
});
|
||||
@@ -195,7 +191,6 @@ export const DiscordSettings = () => {
|
||||
if (!e) return;
|
||||
setSettings({
|
||||
discord: {
|
||||
...settings,
|
||||
linkType: e as DiscordLinkType,
|
||||
},
|
||||
});
|
||||
@@ -222,7 +217,6 @@ export const DiscordSettings = () => {
|
||||
onChange={(e) => {
|
||||
setSettings({
|
||||
discord: {
|
||||
...settings,
|
||||
showServerImage: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -248,7 +242,6 @@ export const DiscordSettings = () => {
|
||||
onBlur={(e) => {
|
||||
setSettings({
|
||||
general: {
|
||||
...generalSettings,
|
||||
lastfmApiKey: e.currentTarget.value,
|
||||
},
|
||||
});
|
||||
@@ -274,4 +267,4 @@ export const DiscordSettings = () => {
|
||||
title={t('page.setting.discord', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import isElectron from 'is-electron';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
@@ -17,7 +18,7 @@ const PASSWORD_SETTINGS: { label: string; value: string }[] = [
|
||||
{ label: 'KDE 6 (kwallet6)', value: 'kwallet6' },
|
||||
];
|
||||
|
||||
export const PasswordSettings = () => {
|
||||
export const PasswordSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const settings = useGeneralSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
@@ -53,4 +54,4 @@ export const PasswordSettings = () => {
|
||||
];
|
||||
|
||||
return <SettingsSection divider={false} options={updateOptions} />;
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import isElectron from 'is-electron';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { SettingsSection } from '/@/renderer/features/settings/components/settings-section';
|
||||
@@ -12,7 +13,7 @@ import { toast } from '/@/shared/components/toast/toast';
|
||||
|
||||
const remote = isElectron() ? window.api.remote : null;
|
||||
|
||||
export const RemoteSettings = () => {
|
||||
export const RemoteSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const settings = useRemoteSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
@@ -25,7 +26,6 @@ export const RemoteSettings = () => {
|
||||
if (errorMsg === null) {
|
||||
setSettings({
|
||||
remote: {
|
||||
...settings,
|
||||
enabled,
|
||||
},
|
||||
});
|
||||
@@ -44,7 +44,6 @@ export const RemoteSettings = () => {
|
||||
if (!errorMsg) {
|
||||
setSettings({
|
||||
remote: {
|
||||
...settings,
|
||||
port,
|
||||
},
|
||||
});
|
||||
@@ -115,7 +114,6 @@ export const RemoteSettings = () => {
|
||||
remote!.updateUsername(username);
|
||||
setSettings({
|
||||
remote: {
|
||||
...settings,
|
||||
username,
|
||||
},
|
||||
});
|
||||
@@ -139,7 +137,6 @@ export const RemoteSettings = () => {
|
||||
remote!.updatePassword(password);
|
||||
setSettings({
|
||||
remote: {
|
||||
...settings,
|
||||
password,
|
||||
},
|
||||
});
|
||||
@@ -161,4 +158,4 @@ export const RemoteSettings = () => {
|
||||
title={t('page.setting.remote', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import isElectron from 'is-electron';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
@@ -13,10 +14,10 @@ const localSettings = isElectron() ? window.api.localSettings : null;
|
||||
const utils = isElectron() ? window.api.utils : null;
|
||||
|
||||
function disableAutoUpdates(): boolean {
|
||||
return !isElectron() || utils?.disableAutoUpdates();
|
||||
return Boolean(!isElectron() || utils?.disableAutoUpdates());
|
||||
}
|
||||
|
||||
export const UpdateSettings = () => {
|
||||
export const UpdateSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const settings = useWindowSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
@@ -49,7 +50,6 @@ export const UpdateSettings = () => {
|
||||
localSettings?.set('release_channel', value);
|
||||
setSettings({
|
||||
window: {
|
||||
...settings,
|
||||
releaseChannel: value as 'beta' | 'latest',
|
||||
},
|
||||
});
|
||||
@@ -74,7 +74,6 @@ export const UpdateSettings = () => {
|
||||
localSettings?.set('disable_auto_updates', e.currentTarget.checked);
|
||||
setSettings({
|
||||
window: {
|
||||
...settings,
|
||||
disableAutoUpdate: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -96,4 +95,4 @@ export const UpdateSettings = () => {
|
||||
title={t('page.setting.updates', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import isElectron from 'is-electron';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
@@ -20,7 +21,7 @@ const WINDOW_BAR_OPTIONS = [
|
||||
|
||||
const localSettings = isElectron() ? window.api.localSettings : null;
|
||||
|
||||
export const WindowSettings = () => {
|
||||
export const WindowSettings = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const settings = useWindowSettings();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
@@ -50,7 +51,6 @@ export const WindowSettings = () => {
|
||||
localSettings?.set('window_window_bar_style', e as Platform);
|
||||
setSettings({
|
||||
window: {
|
||||
...settings,
|
||||
windowBarStyle: e as Platform,
|
||||
},
|
||||
});
|
||||
@@ -77,7 +77,6 @@ export const WindowSettings = () => {
|
||||
if (e.currentTarget.checked) {
|
||||
setSettings({
|
||||
window: {
|
||||
...settings,
|
||||
tray: true,
|
||||
},
|
||||
});
|
||||
@@ -88,7 +87,6 @@ export const WindowSettings = () => {
|
||||
|
||||
setSettings({
|
||||
window: {
|
||||
...settings,
|
||||
exitToTray: false,
|
||||
minimizeToTray: false,
|
||||
startMinimized: false,
|
||||
@@ -120,7 +118,6 @@ export const WindowSettings = () => {
|
||||
localSettings?.set('window_minimize_to_tray', e.currentTarget.checked);
|
||||
setSettings({
|
||||
window: {
|
||||
...settings,
|
||||
minimizeToTray: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -145,7 +142,6 @@ export const WindowSettings = () => {
|
||||
localSettings?.set('window_exit_to_tray', e.currentTarget.checked);
|
||||
setSettings({
|
||||
window: {
|
||||
...settings,
|
||||
exitToTray: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -170,7 +166,6 @@ export const WindowSettings = () => {
|
||||
localSettings?.set('window_start_minimized', e.currentTarget.checked);
|
||||
setSettings({
|
||||
window: {
|
||||
...settings,
|
||||
startMinimized: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -198,7 +193,6 @@ export const WindowSettings = () => {
|
||||
);
|
||||
setSettings({
|
||||
window: {
|
||||
...settings,
|
||||
preventSleepOnPlayback: e.currentTarget.checked,
|
||||
},
|
||||
});
|
||||
@@ -220,4 +214,4 @@ export const WindowSettings = () => {
|
||||
title={t('page.setting.application', { postProcess: 'sentenceCase' })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import isElectron from 'is-electron';
|
||||
import { memo } from 'react';
|
||||
import { Fragment } from 'react/jsx-runtime';
|
||||
|
||||
import { DiscordSettings } from '/@/renderer/features/settings/components/window/discord-settings';
|
||||
@@ -17,7 +18,7 @@ const sections = [
|
||||
{ component: PasswordSettings, hidden: !utils?.isLinux(), key: 'password' },
|
||||
];
|
||||
|
||||
export const WindowTab = () => {
|
||||
export const WindowTab = memo(() => {
|
||||
return (
|
||||
<Stack gap="md">
|
||||
{sections.map(({ component: Section, hidden, key }, index) => (
|
||||
@@ -28,4 +29,4 @@ export const WindowTab = () => {
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -17,7 +17,8 @@ import { AppMenu } from '/@/renderer/features/titlebar/components/app-menu';
|
||||
import {
|
||||
SidebarItemType,
|
||||
useCurrentServer,
|
||||
useGeneralSettings,
|
||||
useSidebarCollapsedNavigation,
|
||||
useSidebarItems,
|
||||
useWindowSettings,
|
||||
} from '/@/renderer/store';
|
||||
import { DropdownMenu } from '/@/shared/components/dropdown-menu/dropdown-menu';
|
||||
@@ -32,7 +33,8 @@ export const CollapsedSidebar = () => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const { windowBarStyle } = useWindowSettings();
|
||||
const { sidebarCollapsedNavigation, sidebarItems } = useGeneralSettings();
|
||||
const sidebarCollapsedNavigation = useSidebarCollapsedNavigation();
|
||||
const sidebarItems = useSidebarItems();
|
||||
const currentServer = useCurrentServer();
|
||||
|
||||
const translatedSidebarItemMap = useMemo(
|
||||
|
||||
@@ -11,7 +11,11 @@ import {
|
||||
SidebarPlaylistList,
|
||||
SidebarSharedPlaylistList,
|
||||
} from '/@/renderer/features/sidebar/components/sidebar-playlist-list';
|
||||
import { SidebarItemType, useGeneralSettings } from '/@/renderer/store/settings.store';
|
||||
import {
|
||||
SidebarItemType,
|
||||
useSidebarItems,
|
||||
useSidebarPlaylistList,
|
||||
} from '/@/renderer/store/settings.store';
|
||||
import { Accordion } from '/@/shared/components/accordion/accordion';
|
||||
import { Group } from '/@/shared/components/group/group';
|
||||
import { ScrollArea } from '/@/shared/components/scroll-area/scroll-area';
|
||||
@@ -19,7 +23,7 @@ import { Text } from '/@/shared/components/text/text';
|
||||
|
||||
export const MobileSidebar = () => {
|
||||
const { t } = useTranslation();
|
||||
const { sidebarPlaylistList } = useGeneralSettings();
|
||||
const sidebarPlaylistList = useSidebarPlaylistList();
|
||||
|
||||
const translatedSidebarItemMap = useMemo(
|
||||
() => ({
|
||||
@@ -38,7 +42,7 @@ export const MobileSidebar = () => {
|
||||
[t],
|
||||
);
|
||||
|
||||
const { sidebarItems } = useGeneralSettings();
|
||||
const sidebarItems = useSidebarItems();
|
||||
|
||||
const sidebarItemsWithRoute: SidebarItemType[] = useMemo(() => {
|
||||
if (!sidebarItems) return [];
|
||||
|
||||
@@ -25,7 +25,8 @@ import {
|
||||
} from '/@/renderer/store';
|
||||
import {
|
||||
SidebarItemType,
|
||||
useGeneralSettings,
|
||||
useSidebarItems,
|
||||
useSidebarPlaylistList,
|
||||
useWindowSettings,
|
||||
} from '/@/renderer/store/settings.store';
|
||||
import { Accordion } from '/@/shared/components/accordion/accordion';
|
||||
@@ -41,7 +42,7 @@ import { Platform } from '/@/shared/types/types';
|
||||
export const Sidebar = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { sidebarPlaylistList } = useGeneralSettings();
|
||||
const sidebarPlaylistList = useSidebarPlaylistList();
|
||||
|
||||
const translatedSidebarItemMap = useMemo(
|
||||
() => ({
|
||||
@@ -62,7 +63,7 @@ export const Sidebar = () => {
|
||||
[t],
|
||||
);
|
||||
|
||||
const { sidebarItems } = useGeneralSettings();
|
||||
const sidebarItems = useSidebarItems();
|
||||
const { windowBarStyle } = useWindowSettings();
|
||||
const sidebarImageEnabled = useAppStore((state) => state.sidebar.image);
|
||||
const isRadioPlaying = useRadioStore((state) => state.isPlaying);
|
||||
|
||||
-15
@@ -127,9 +127,7 @@ const useUpdateAudioMotionAnalyzer = () => {
|
||||
) => {
|
||||
setSettings({
|
||||
visualizer: {
|
||||
...visualizer,
|
||||
audiomotionanalyzer: {
|
||||
...visualizer.audiomotionanalyzer,
|
||||
[property]: value,
|
||||
},
|
||||
},
|
||||
@@ -149,9 +147,7 @@ const useUpdateButterchurn = () => {
|
||||
) => {
|
||||
setSettings({
|
||||
visualizer: {
|
||||
...visualizer,
|
||||
butterchurn: {
|
||||
...visualizer.butterchurn,
|
||||
[property]: value,
|
||||
},
|
||||
},
|
||||
@@ -177,7 +173,6 @@ export const VisualizerSettingsForm = () => {
|
||||
const handleTypeChange = (value: string) => {
|
||||
setSettings({
|
||||
visualizer: {
|
||||
...visualizer,
|
||||
type: value as 'audiomotionanalyzer' | 'butterchurn',
|
||||
},
|
||||
});
|
||||
@@ -464,9 +459,7 @@ const PresetSettings = () => {
|
||||
|
||||
setSettings({
|
||||
visualizer: {
|
||||
...visualizer,
|
||||
audiomotionanalyzer: {
|
||||
...visualizer.audiomotionanalyzer,
|
||||
...presetValue,
|
||||
},
|
||||
},
|
||||
@@ -501,9 +494,7 @@ const PresetSettings = () => {
|
||||
|
||||
setSettings({
|
||||
visualizer: {
|
||||
...visualizer,
|
||||
audiomotionanalyzer: {
|
||||
...visualizer.audiomotionanalyzer,
|
||||
presets: updatedPresets,
|
||||
},
|
||||
},
|
||||
@@ -517,9 +508,7 @@ const PresetSettings = () => {
|
||||
|
||||
setSettings({
|
||||
visualizer: {
|
||||
...visualizer,
|
||||
audiomotionanalyzer: {
|
||||
...visualizer.audiomotionanalyzer,
|
||||
presets: [...visualizer.audiomotionanalyzer.presets, newPreset],
|
||||
},
|
||||
},
|
||||
@@ -644,9 +633,7 @@ const PresetSettings = () => {
|
||||
|
||||
setSettings({
|
||||
visualizer: {
|
||||
...visualizer,
|
||||
audiomotionanalyzer: {
|
||||
...visualizer.audiomotionanalyzer,
|
||||
presets: updatedPresets,
|
||||
},
|
||||
},
|
||||
@@ -776,9 +763,7 @@ const PresetSettings = () => {
|
||||
|
||||
setSettings({
|
||||
visualizer: {
|
||||
...visualizer,
|
||||
audiomotionanalyzer: {
|
||||
...visualizer.audiomotionanalyzer,
|
||||
...configValue,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -6,13 +6,13 @@ import styles from './visualizer.module.css';
|
||||
import { useWebAudio } from '/@/renderer/features/player/hooks/use-webaudio';
|
||||
import { openVisualizerSettingsModal } from '/@/renderer/features/player/utils/open-visualizer-settings-modal';
|
||||
import { ComponentErrorBoundary } from '/@/renderer/features/shared/components/component-error-boundary';
|
||||
import { useSettingsStore } from '/@/renderer/store';
|
||||
import { useAccent, useSettingsStore } from '/@/renderer/store';
|
||||
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
||||
|
||||
const VisualizerInner = () => {
|
||||
const { webAudio } = useWebAudio();
|
||||
const canvasRef = createRef<HTMLDivElement>();
|
||||
const accent = useSettingsStore((store) => store.general.accent);
|
||||
const accent = useAccent();
|
||||
const visualizer = useSettingsStore((store) => store.visualizer);
|
||||
const opacity = useSettingsStore((store) => store.visualizer.audiomotionanalyzer.opacity);
|
||||
const [motion, setMotion] = useState<AudioMotionAnalyzer>();
|
||||
|
||||
@@ -277,12 +277,9 @@ const VisualizerInner = () => {
|
||||
visualizer.loadPreset(nextPreset, currentSettings.blendTime || 0.0);
|
||||
|
||||
// Update currentPreset in settings
|
||||
const currentVisualizer = useSettingsStore.getState().visualizer;
|
||||
setSettings({
|
||||
visualizer: {
|
||||
...currentVisualizer,
|
||||
butterchurn: {
|
||||
...currentVisualizer.butterchurn,
|
||||
currentPreset: nextPresetName,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -2,14 +2,14 @@ import isElectron from 'is-electron';
|
||||
import { useLocation } from 'react-router';
|
||||
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { useGeneralSettings, useSidebarRightExpanded, useWindowSettings } from '/@/renderer/store';
|
||||
import { useSidebarRightExpanded, useSideQueueType, useWindowSettings } from '/@/renderer/store';
|
||||
import { Platform } from '/@/shared/types/types';
|
||||
|
||||
export const useShouldPadTitlebar = () => {
|
||||
const location = useLocation();
|
||||
const isSidebarExpanded = useSidebarRightExpanded();
|
||||
const isQueuePage = location.pathname === AppRoute.NOW_PLAYING;
|
||||
const { sideQueueType } = useGeneralSettings();
|
||||
const sideQueueType = useSideQueueType();
|
||||
const { windowBarStyle } = useWindowSettings();
|
||||
|
||||
const conditions = [
|
||||
|
||||
@@ -13,7 +13,6 @@ import { Platform, PlayerType } from '/@/shared/types/types';
|
||||
if (!isElectron()) {
|
||||
useSettingsStore.getState().actions.setSettings({
|
||||
playback: {
|
||||
...useSettingsStore.getState().playback,
|
||||
type: PlayerType.WEB,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -9,8 +9,7 @@ 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 { useAppStore, useAppStoreActions } from '/@/renderer/store';
|
||||
import { useGeneralSettings } from '/@/renderer/store/settings.store';
|
||||
import { useAppStore, useAppStoreActions, useSideQueueType } from '/@/renderer/store';
|
||||
import { constrainRightSidebarWidth, constrainSidebarWidth } from '/@/renderer/utils';
|
||||
import { Spinner } from '/@/shared/components/spinner/spinner';
|
||||
|
||||
@@ -27,7 +26,7 @@ export const MainContent = ({ shell }: { shell?: boolean }) => {
|
||||
shallow,
|
||||
);
|
||||
const { setSideBar } = useAppStoreActions();
|
||||
const { sideQueueType } = useGeneralSettings();
|
||||
const sideQueueType = useSideQueueType();
|
||||
const [isResizing, setIsResizing] = useState(false);
|
||||
const [isResizingRight, setIsResizingRight] = useState(false);
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@ import clsx from 'clsx';
|
||||
import styles from './player-bar.module.css';
|
||||
|
||||
import { Playerbar } from '/@/renderer/features/player/components/playerbar';
|
||||
import { useGeneralSettings } from '/@/renderer/store/settings.store';
|
||||
import { usePlayerbarOpenDrawer } from '/@/renderer/store';
|
||||
|
||||
export const PlayerBar = () => {
|
||||
const { playerbarOpenDrawer } = useGeneralSettings();
|
||||
const playerbarOpenDrawer = usePlayerbarOpenDrawer();
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -4,7 +4,7 @@ import styles from './right-sidebar.module.css';
|
||||
|
||||
import { SidebarPlayQueue } from '/@/renderer/features/now-playing/components/sidebar-play-queue';
|
||||
import { ResizeHandle } from '/@/renderer/features/shared/components/resize-handle';
|
||||
import { useAppStore, useGeneralSettings } from '/@/renderer/store';
|
||||
import { useAppStore, useSideQueueType } from '/@/renderer/store';
|
||||
|
||||
// const queueDrawerVariants: Variants = {
|
||||
// closed: (windowBarStyle) => ({
|
||||
@@ -55,7 +55,7 @@ export const RightSidebar = forwardRef(
|
||||
ref: Ref<HTMLDivElement>,
|
||||
) => {
|
||||
const rightExpanded = useAppStore((state) => state.sidebar.rightExpanded);
|
||||
const { sideQueueType } = useGeneralSettings();
|
||||
const sideQueueType = useSideQueueType();
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -10,9 +10,9 @@ import { MobileLayout } from '/@/renderer/layouts/mobile-layout/mobile-layout';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import {
|
||||
useCommandPalette,
|
||||
useGeneralSettings,
|
||||
useHotkeySettings,
|
||||
useSettingsStoreActions,
|
||||
useZoomFactor,
|
||||
} from '/@/renderer/store';
|
||||
import { HotkeyItem, useHotkeys } from '/@/shared/hooks/use-hotkeys';
|
||||
|
||||
@@ -45,23 +45,22 @@ export const ResponsiveLayout = ({ shell }: ResponsiveLayoutProps) => {
|
||||
const LayoutHotkeys = () => {
|
||||
const navigate = useNavigate();
|
||||
const localSettings = isElectron() ? window.api.localSettings : null;
|
||||
const settings = useGeneralSettings();
|
||||
const zoomFactor = useZoomFactor();
|
||||
const { setSettings } = useSettingsStoreActions();
|
||||
const { bindings } = useHotkeySettings();
|
||||
const { opened, ...handlers } = useCommandPalette();
|
||||
|
||||
const updateZoom = (increase: number) => {
|
||||
const newVal = settings.zoomFactor + increase;
|
||||
const newVal = zoomFactor + increase;
|
||||
if (newVal > 300 || newVal < 50 || !isElectron()) return;
|
||||
setSettings({
|
||||
general: {
|
||||
...settings,
|
||||
zoomFactor: newVal,
|
||||
},
|
||||
});
|
||||
localSettings?.setZoomFactor(settings.zoomFactor);
|
||||
localSettings?.setZoomFactor(zoomFactor);
|
||||
};
|
||||
localSettings?.setZoomFactor(settings.zoomFactor);
|
||||
localSettings?.setZoomFactor(zoomFactor);
|
||||
|
||||
const zoomHotkeys: HotkeyItem[] = [
|
||||
[bindings.zoomIn.hotkey, () => updateZoom(5)],
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import isElectron from 'is-electron';
|
||||
import merge from 'lodash/merge';
|
||||
import { generatePath } from 'react-router';
|
||||
import { z } from 'zod';
|
||||
import { devtools, persist } from 'zustand/middleware';
|
||||
@@ -42,6 +43,17 @@ type DeepPartial<T> = {
|
||||
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
|
||||
};
|
||||
|
||||
const deepMergeIntoState = <T extends Record<string, any>>(
|
||||
state: T,
|
||||
updates: DeepPartial<T>,
|
||||
): void => {
|
||||
// Skip 'actions' property
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { actions, ...updatesWithoutActions } = updates as any;
|
||||
|
||||
merge(state, updatesWithoutActions);
|
||||
};
|
||||
|
||||
const HomeItemSchema = z.enum([
|
||||
'genres',
|
||||
'mostPlayed',
|
||||
@@ -767,7 +779,7 @@ export interface SettingsSlice extends z.infer<typeof SettingsStateSchema> {
|
||||
setHomeItems: (item: SortableItem<HomeItem>[]) => void;
|
||||
setList: (type: ItemListKey, data: DeepPartial<ItemListSettings>) => void;
|
||||
setPlaybackFilters: (filters: PlayerFilter[]) => void;
|
||||
setSettings: (data: Partial<SettingsState>) => void;
|
||||
setSettings: (data: DeepPartial<SettingsState>) => void;
|
||||
setSidebarItems: (items: SidebarItemType[]) => void;
|
||||
setTable: (type: ItemListKey, data: DataTableProps) => void;
|
||||
setTranscodingConfig: (config: TranscodingConfig) => void;
|
||||
@@ -1642,7 +1654,7 @@ const getInitialState = (): SettingsState => {
|
||||
export const useSettingsStore = createWithEqualityFn<SettingsSlice>()(
|
||||
persist(
|
||||
devtools(
|
||||
immer((set, get) => ({
|
||||
immer((set) => ({
|
||||
actions: {
|
||||
reset: () => {
|
||||
const freshState = getInitialState();
|
||||
@@ -1723,7 +1735,9 @@ export const useSettingsStore = createWithEqualityFn<SettingsSlice>()(
|
||||
});
|
||||
},
|
||||
setSettings: (data) => {
|
||||
set({ ...get(), ...data });
|
||||
set((state) => {
|
||||
deepMergeIntoState(state, data);
|
||||
});
|
||||
},
|
||||
setSidebarItems: (items: SidebarItemType[]) => {
|
||||
set((state) => {
|
||||
@@ -1980,11 +1994,128 @@ export const useListSettings = (type: ItemListKey) =>
|
||||
shallow,
|
||||
) as ItemListSettings;
|
||||
|
||||
export const usePrimaryColor = () => useSettingsStore((store) => store.general.accent);
|
||||
export const usePrimaryColor = () => useSettingsStore((store) => store.general.accent, shallow);
|
||||
|
||||
export const usePlayerbarSlider = () => useSettingsStore((store) => store.general.playerbarSlider);
|
||||
export const usePlayerbarSlider = () =>
|
||||
useSettingsStore((store) => store.general.playerbarSlider, shallow);
|
||||
|
||||
export const useGenreTarget = () => useSettingsStore((store) => store.general.genreTarget);
|
||||
export const useGenreTarget = () => useSettingsStore((store) => store.general.genreTarget, shallow);
|
||||
|
||||
export const useLanguage = () => useSettingsStore((state) => state.general.language, shallow);
|
||||
|
||||
export const useAccent = () => useSettingsStore((state) => state.general.accent, shallow);
|
||||
|
||||
export const useNativeAspectRatio = () =>
|
||||
useSettingsStore((state) => state.general.nativeAspectRatio, shallow);
|
||||
|
||||
export const useButtonSize = () => useSettingsStore((state) => state.general.buttonSize, shallow);
|
||||
|
||||
export const useSkipButtons = () => useSettingsStore((state) => state.general.skipButtons, shallow);
|
||||
|
||||
export const useImageRes = () => useSettingsStore((state) => state.general.imageRes, shallow);
|
||||
|
||||
export const useVolumeWidth = () => useSettingsStore((state) => state.general.volumeWidth, shallow);
|
||||
|
||||
export const useFollowCurrentSong = () =>
|
||||
useSettingsStore((state) => state.general.followCurrentSong, shallow);
|
||||
|
||||
export const useThemeSettings = () =>
|
||||
useSettingsStore(
|
||||
(state) => ({
|
||||
followSystemTheme: state.general.followSystemTheme,
|
||||
theme: state.general.theme,
|
||||
themeDark: state.general.themeDark,
|
||||
themeLight: state.general.themeLight,
|
||||
useThemeAccentColor: state.general.useThemeAccentColor,
|
||||
}),
|
||||
shallow,
|
||||
);
|
||||
|
||||
export const useSideQueueType = () =>
|
||||
useSettingsStore((state) => state.general.sideQueueType, shallow);
|
||||
|
||||
export const useVolumeWheelStep = () =>
|
||||
useSettingsStore((state) => state.general.volumeWheelStep, shallow);
|
||||
|
||||
export const useSidebarPlaylistList = () =>
|
||||
useSettingsStore((state) => state.general.sidebarPlaylistList, shallow);
|
||||
|
||||
export const useSidebarItems = () =>
|
||||
useSettingsStore((state) => state.general.sidebarItems, shallow);
|
||||
|
||||
export const useSidebarCollapsedNavigation = () =>
|
||||
useSettingsStore((state) => state.general.sidebarCollapsedNavigation, shallow);
|
||||
|
||||
export const usePlayerbarOpenDrawer = () =>
|
||||
useSettingsStore((state) => state.general.playerbarOpenDrawer, shallow);
|
||||
|
||||
export const useShowRatings = () => useSettingsStore((state) => state.general.showRatings, shallow);
|
||||
|
||||
export const useArtistRadioCount = () =>
|
||||
useSettingsStore((state) => state.general.artistRadioCount, shallow);
|
||||
|
||||
export const useArtistBackground = () =>
|
||||
useSettingsStore(
|
||||
(state) => ({
|
||||
artistBackground: state.general.artistBackground,
|
||||
artistBackgroundBlur: state.general.artistBackgroundBlur,
|
||||
}),
|
||||
shallow,
|
||||
);
|
||||
|
||||
export const useAlbumBackground = () =>
|
||||
useSettingsStore(
|
||||
(state) => ({
|
||||
albumBackground: state.general.albumBackground,
|
||||
albumBackgroundBlur: state.general.albumBackgroundBlur,
|
||||
}),
|
||||
shallow,
|
||||
);
|
||||
|
||||
export const useExternalLinks = () =>
|
||||
useSettingsStore(
|
||||
(state) => ({
|
||||
externalLinks: state.general.externalLinks,
|
||||
lastFM: state.general.lastFM,
|
||||
musicBrainz: state.general.musicBrainz,
|
||||
}),
|
||||
shallow,
|
||||
);
|
||||
|
||||
export const useHomeFeature = () => useSettingsStore((state) => state.general.homeFeature, shallow);
|
||||
|
||||
export const useHomeItems = () => useSettingsStore((state) => state.general.homeItems, shallow);
|
||||
|
||||
export const useArtistItems = () => useSettingsStore((state) => state.general.artistItems, shallow);
|
||||
|
||||
export const useArtistReleaseTypeItems = () =>
|
||||
useSettingsStore((state) => state.general.artistReleaseTypeItems, shallow);
|
||||
|
||||
export const useZoomFactor = () => useSettingsStore((state) => state.general.zoomFactor, shallow);
|
||||
|
||||
export const usePathReplace = () =>
|
||||
useSettingsStore(
|
||||
(state) => ({
|
||||
pathReplace: state.general.pathReplace,
|
||||
pathReplaceWith: state.general.pathReplaceWith,
|
||||
}),
|
||||
shallow,
|
||||
);
|
||||
|
||||
export const useLastfmApiKey = () =>
|
||||
useSettingsStore((state) => state.general.lastfmApiKey, shallow);
|
||||
|
||||
export const useSidebarPanelOrder = () =>
|
||||
useSettingsStore((state) => state.general.sidebarPanelOrder, shallow);
|
||||
|
||||
export const useCombinedLyricsAndVisualizer = () =>
|
||||
useSettingsStore((state) => state.general.combinedLyricsAndVisualizer, shallow);
|
||||
|
||||
export const useShowLyricsInSidebar = () =>
|
||||
useSettingsStore((state) => state.general.showLyricsInSidebar, shallow);
|
||||
|
||||
export const useShowVisualizerInSidebar = () =>
|
||||
useSettingsStore((state) => state.general.showVisualizerInSidebar, shallow);
|
||||
|
||||
export const useAutoDJSettings = () => useSettingsStore((store) => store.autoDJ, shallow);
|
||||
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import { useMantineColorScheme } from '@mantine/core';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import { useSettingsStore } from '/@/renderer/store/settings.store';
|
||||
import {
|
||||
useAccent,
|
||||
useFontSettings,
|
||||
useNativeAspectRatio,
|
||||
useThemeSettings,
|
||||
} from '/@/renderer/store/settings.store';
|
||||
import { createMantineTheme } from '/@/renderer/themes/mantine-theme';
|
||||
import { getAppTheme } from '/@/shared/themes/app-theme';
|
||||
import { AppTheme, AppThemeConfiguration } from '/@/shared/themes/app-theme-types';
|
||||
@@ -36,15 +41,15 @@ export const THEME_DATA = [
|
||||
];
|
||||
|
||||
export const useAppTheme = (overrideTheme?: AppTheme) => {
|
||||
const accent = useSettingsStore((store) => store.general.accent);
|
||||
const nativeImageAspect = useSettingsStore((store) => store.general.nativeAspectRatio);
|
||||
const { builtIn, custom, system, type } = useSettingsStore((state) => state.font);
|
||||
const accent = useAccent();
|
||||
const nativeImageAspect = useNativeAspectRatio();
|
||||
const { builtIn, custom, system, type } = useFontSettings();
|
||||
const textStyleRef = useRef<HTMLStyleElement | null>(null);
|
||||
const loadedStylesheetsRef = useRef<Set<string>>(new Set());
|
||||
const getCurrentTheme = () => window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
const [isDarkTheme, setIsDarkTheme] = useState(getCurrentTheme());
|
||||
const { followSystemTheme, theme, themeDark, themeLight, useThemeAccentColor } =
|
||||
useSettingsStore((state) => state.general);
|
||||
useThemeSettings();
|
||||
|
||||
const mqListener = (e: any) => {
|
||||
setIsDarkTheme(e.matches);
|
||||
@@ -263,11 +268,11 @@ export const useColorScheme = () => {
|
||||
};
|
||||
|
||||
export const useAppThemeColors = () => {
|
||||
const accent = useSettingsStore((store) => store.general.accent);
|
||||
const accent = useAccent();
|
||||
const getCurrentTheme = () => window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
const [isDarkTheme] = useState(getCurrentTheme());
|
||||
const { followSystemTheme, theme, themeDark, themeLight, useThemeAccentColor } =
|
||||
useSettingsStore((state) => state.general);
|
||||
useThemeSettings();
|
||||
|
||||
const getSelectedTheme = () => {
|
||||
if (followSystemTheme) {
|
||||
|
||||
Reference in New Issue
Block a user