diff --git a/src/apps/experimental/components/library/NewCollectionButton.tsx b/src/apps/experimental/components/library/NewCollectionButton.tsx
new file mode 100644
index 00000000000..e337de7ddd2
--- /dev/null
+++ b/src/apps/experimental/components/library/NewCollectionButton.tsx
@@ -0,0 +1,34 @@
+import React, { FC, useCallback } from 'react';
+import { IconButton } from '@mui/material';
+import AddIcon from '@mui/icons-material/Add';
+import globalize from 'scripts/globalize';
+
+const NewCollectionButton: FC = () => {
+ const showCollectionEditor = useCallback(() => {
+ import('components/collectionEditor/collectionEditor').then(
+ ({ default: CollectionEditor }) => {
+ const serverId = window.ApiClient.serverId();
+ const collectionEditor = new CollectionEditor();
+ collectionEditor.show({
+ items: [],
+ serverId: serverId
+ }).catch(() => {
+ // closed collection editor
+ });
+ }).catch(err => {
+ console.error('[NewCollection] failed to load collection editor', err);
+ });
+ }, []);
+
+ return (
+
+
+
+ );
+};
+
+export default NewCollectionButton;
diff --git a/src/apps/experimental/components/library/PlayAllButton.tsx b/src/apps/experimental/components/library/PlayAllButton.tsx
new file mode 100644
index 00000000000..d7fb0903807
--- /dev/null
+++ b/src/apps/experimental/components/library/PlayAllButton.tsx
@@ -0,0 +1,57 @@
+import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client';
+import React, { FC, useCallback } from 'react';
+import { IconButton } from '@mui/material';
+import PlayArrowIcon from '@mui/icons-material/PlayArrow';
+
+import { playbackManager } from 'components/playback/playbackmanager';
+import globalize from 'scripts/globalize';
+import { getFiltersQuery } from 'utils/items';
+import { LibraryViewSettings } from 'types/library';
+import { LibraryTab } from 'types/libraryTab';
+
+interface PlayAllButtonProps {
+ item: BaseItemDto | undefined;
+ items: BaseItemDto[];
+ viewType: LibraryTab;
+ hasFilters: boolean;
+ libraryViewSettings: LibraryViewSettings
+}
+
+const PlayAllButton: FC = ({ item, items, viewType, hasFilters, libraryViewSettings }) => {
+ const play = useCallback(() => {
+ if (item && !hasFilters) {
+ playbackManager.play({
+ items: [item],
+ autoplay: true,
+ queryOptions: {
+ SortBy: [libraryViewSettings.SortBy],
+ SortOrder: [libraryViewSettings.SortOrder]
+ }
+ });
+ } else {
+ playbackManager.play({
+ items: items,
+ autoplay: true,
+ queryOptions: {
+ ParentId: item?.Id ?? undefined,
+ ...getFiltersQuery(viewType, libraryViewSettings),
+ SortBy: [libraryViewSettings.SortBy],
+ SortOrder: [libraryViewSettings.SortOrder]
+ }
+
+ });
+ }
+ }, [hasFilters, item, items, libraryViewSettings, viewType]);
+
+ return (
+
+
+
+ );
+};
+
+export default PlayAllButton;
diff --git a/src/apps/experimental/components/library/QueueButton.tsx b/src/apps/experimental/components/library/QueueButton.tsx
new file mode 100644
index 00000000000..fdc6a7666b2
--- /dev/null
+++ b/src/apps/experimental/components/library/QueueButton.tsx
@@ -0,0 +1,39 @@
+import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client';
+import React, { FC, useCallback } from 'react';
+import { IconButton } from '@mui/material';
+import QueueIcon from '@mui/icons-material/Queue';
+
+import { playbackManager } from 'components/playback/playbackmanager';
+import globalize from 'scripts/globalize';
+
+interface QueueButtonProps {
+ item: BaseItemDto | undefined
+ items: BaseItemDto[];
+ hasFilters: boolean;
+}
+
+const QueueButton: FC = ({ item, items, hasFilters }) => {
+ const queue = useCallback(() => {
+ if (item && !hasFilters) {
+ playbackManager.queue({
+ items: [item]
+ });
+ } else {
+ playbackManager.queue({
+ items: items
+ });
+ }
+ }, [hasFilters, item, items]);
+
+ return (
+
+
+
+ );
+};
+
+export default QueueButton;
diff --git a/src/apps/experimental/components/library/ShuffleButton.tsx b/src/apps/experimental/components/library/ShuffleButton.tsx
new file mode 100644
index 00000000000..c81ee4c4bac
--- /dev/null
+++ b/src/apps/experimental/components/library/ShuffleButton.tsx
@@ -0,0 +1,49 @@
+import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client';
+import { ItemSortBy } from '@jellyfin/sdk/lib/models/api/item-sort-by';
+import React, { FC, useCallback } from 'react';
+import { IconButton } from '@mui/material';
+import ShuffleIcon from '@mui/icons-material/Shuffle';
+
+import { playbackManager } from 'components/playback/playbackmanager';
+import globalize from 'scripts/globalize';
+import { getFiltersQuery } from 'utils/items';
+import { LibraryViewSettings } from 'types/library';
+import { LibraryTab } from 'types/libraryTab';
+
+interface ShuffleButtonProps {
+ item: BaseItemDto | undefined;
+ items: BaseItemDto[];
+ viewType: LibraryTab
+ hasFilters: boolean;
+ libraryViewSettings: LibraryViewSettings
+}
+
+const ShuffleButton: FC = ({ item, items, viewType, hasFilters, libraryViewSettings }) => {
+ const shuffle = useCallback(() => {
+ if (item && !hasFilters) {
+ playbackManager.shuffle(item);
+ } else {
+ playbackManager.play({
+ items: items,
+ autoplay: true,
+ queryOptions: {
+ ParentId: item?.Id ?? undefined,
+ ...getFiltersQuery(viewType, libraryViewSettings),
+ SortBy: [ItemSortBy.Random]
+ }
+ });
+ }
+ }, [hasFilters, item, items, libraryViewSettings, viewType]);
+
+ return (
+
+
+
+ );
+};
+
+export default ShuffleButton;
diff --git a/src/apps/experimental/components/library/SortButton.tsx b/src/apps/experimental/components/library/SortButton.tsx
index 7deeae349b0..2c7425f0dea 100644
--- a/src/apps/experimental/components/library/SortButton.tsx
+++ b/src/apps/experimental/components/library/SortButton.tsx
@@ -98,7 +98,7 @@ const SortButton: FC = ({
title={globalize.translate('Sort')}
sx={{ ml: 2 }}
aria-describedby={id}
- className='paper-icon-button-light btnShuffle autoSize'
+ className='paper-icon-button-light btnSort autoSize'
onClick={handleClick}
>
diff --git a/src/apps/experimental/components/library/ViewSettingsButton.tsx b/src/apps/experimental/components/library/ViewSettingsButton.tsx
index cec5090accb..b1ca1679e00 100644
--- a/src/apps/experimental/components/library/ViewSettingsButton.tsx
+++ b/src/apps/experimental/components/library/ViewSettingsButton.tsx
@@ -100,7 +100,7 @@ const ViewSettingsButton: FC = ({
title={globalize.translate('ButtonSelectView')}
sx={{ ml: 2 }}
aria-describedby={id}
- className='paper-icon-button-light btnShuffle autoSize'
+ className='paper-icon-button-light btnSelectView autoSize'
onClick={handleClick}
>