diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json
index ab9fd13de..b51da305d 100644
--- a/src/i18n/locales/en.json
+++ b/src/i18n/locales/en.json
@@ -796,6 +796,10 @@
"homeConfiguration": "home page configuration",
"homeFeature_description": "controls whether to show the large featured carousel on the home page",
"homeFeature": "home featured carousel",
+ "homeFeatureStyle_description": "controls the style of the home featured carousel",
+ "homeFeatureStyle": "home featured carousel style",
+ "homeFeatureStyle_optionMultiple": "multiple",
+ "homeFeatureStyle_optionSingle": "single",
"hotkey_browserBack": "browser back",
"hotkey_browserForward": "browser forward",
"hotkey_favoriteCurrentSong": "favorite $t(common.currentSong)",
diff --git a/src/renderer/features/home/routes/home-route.tsx b/src/renderer/features/home/routes/home-route.tsx
index d87ac370d..ae51b4763 100644
--- a/src/renderer/features/home/routes/home-route.tsx
+++ b/src/renderer/features/home/routes/home-route.tsx
@@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';
import { useGridCarouselContainerQuery } from '/@/renderer/components/grid-carousel/grid-carousel-v2';
import { NativeScrollArea } from '/@/renderer/components/native-scroll-area/native-scroll-area';
import { AlbumInfiniteCarousel } from '/@/renderer/features/albums/components/album-infinite-carousel';
+import { AlbumInfiniteFeatureCarousel } from '/@/renderer/features/home/components/album-infinite-feature-carousel';
import { AlbumInfiniteSingleFeatureCarousel } from '/@/renderer/features/home/components/album-infinite-single-feature-carousel';
import { FeaturedGenres } from '/@/renderer/features/home/components/featured-genres';
import { AnimatedPage } from '/@/renderer/features/shared/components/animated-page';
@@ -12,9 +13,11 @@ import { LibraryHeaderBar } from '/@/renderer/features/shared/components/library
import { PageErrorBoundary } from '/@/renderer/features/shared/components/page-error-boundary';
import { SongInfiniteCarousel } from '/@/renderer/features/songs/components/song-infinite-carousel';
import {
+ HomeFeatureStyle,
HomeItem,
useCurrentServer,
useHomeFeature,
+ useHomeFeatureStyle,
useHomeItems,
useWindowSettings,
} from '/@/renderer/store';
@@ -35,6 +38,7 @@ const HomeRoute = () => {
const server = useCurrentServer();
const { windowBarStyle } = useWindowSettings();
const homeFeature = useHomeFeature();
+ const homeFeatureStyle = useHomeFeatureStyle();
const homeItems = useHomeItems();
const containerQuery = useGridCarouselContainerQuery();
@@ -116,7 +120,12 @@ const HomeRoute = () => {
px="2rem"
ref={containerQuery.ref}
>
- {homeFeature && }
+ {homeFeature && homeFeatureStyle === HomeFeatureStyle.SINGLE && (
+
+ )}
+ {homeFeature && homeFeatureStyle === HomeFeatureStyle.MULTIPLE && (
+
+ )}
{sortedItems.map((item) => {
if (item.id === HomeItem.GENRES) {
return ;
diff --git a/src/renderer/features/settings/components/general/application-settings.tsx b/src/renderer/features/settings/components/general/application-settings.tsx
index 6b804adea..048773728 100644
--- a/src/renderer/features/settings/components/general/application-settings.tsx
+++ b/src/renderer/features/settings/components/general/application-settings.tsx
@@ -18,6 +18,7 @@ import {
SettingsSection,
} from '/@/renderer/features/settings/components/settings-section';
import {
+ HomeFeatureStyle,
SideQueueType,
useFontSettings,
useGeneralSettings,
@@ -26,6 +27,7 @@ import {
import { type Font, FONT_OPTIONS } from '/@/renderer/types/fonts';
import { FileInput } from '/@/shared/components/file-input/file-input';
import { NumberInput } from '/@/shared/components/number-input/number-input';
+import { SegmentedControl } from '/@/shared/components/segmented-control/segmented-control';
import { Select } from '/@/shared/components/select/select';
import { Slider } from '/@/shared/components/slider/slider';
import { Switch } from '/@/shared/components/switch/switch';
@@ -37,6 +39,23 @@ const ipc = isElectron() ? window.api.ipc : null;
// Electron 32+ removed file.path, use this which is exposed in preload to get real path
const webUtils = isElectron() ? window.electron.webUtils : null;
+const HOME_FEATURE_STYLE_OPTIONS = [
+ {
+ label: t('setting.homeFeatureStyle', {
+ context: 'optionSingle',
+ postProcess: 'sentenceCase',
+ }),
+ value: HomeFeatureStyle.SINGLE,
+ },
+ {
+ label: t('setting.homeFeatureStyle', {
+ context: 'optionMultiple',
+ postProcess: 'sentenceCase',
+ }),
+ value: HomeFeatureStyle.MULTIPLE,
+ },
+];
+
const SIDE_QUEUE_OPTIONS = [
{
label: t('setting.sidePlayQueueStyle', {
@@ -356,6 +375,29 @@ export const ApplicationSettings = memo(() => {
isHidden: false,
title: t('setting.homeFeature', { postProcess: 'sentenceCase' }),
},
+ {
+ control: (
+
+ setSettings({
+ general: {
+ ...settings,
+ homeFeatureStyle: e as HomeFeatureStyle,
+ },
+ })
+ }
+ />
+ ),
+ description: t('setting.homeFeature', {
+ context: 'description',
+ postProcess: 'sentenceCase',
+ }),
+ isHidden: false,
+ title: t('setting.homeFeature', { postProcess: 'sentenceCase' }),
+ },
{
control: (
export const useHomeFeature = () => useSettingsStore((state) => state.general.homeFeature, shallow);
+export const useHomeFeatureStyle = () =>
+ useSettingsStore((state) => state.general.homeFeatureStyle);
+
export const useHomeItems = () => useSettingsStore((state) => state.general.homeItems, shallow);
export const useArtistItems = () => useSettingsStore((state) => state.general.artistItems, shallow);