mirror of
https://github.com/jeffvli/sonixd.git
synced 2026-04-30 11:12:36 -04:00
update contextmenu
- move to root app - styling changes
This commit is contained in:
@@ -23,6 +23,7 @@ import { defaultDark, defaultLight } from './styles/styledTheme';
|
||||
import { useAppSelector } from './redux/hooks';
|
||||
import PageModal from './components/modal/PageModal';
|
||||
import NowPlayingMiniView from './components/player/NowPlayingMiniView';
|
||||
import { GlobalContextMenu } from './components/shared/ContextMenu';
|
||||
|
||||
const keyMap = {
|
||||
FOCUS_SEARCH: 'ctrl+f',
|
||||
@@ -96,6 +97,7 @@ const App = () => {
|
||||
</Layout>
|
||||
<PageModal />
|
||||
<NowPlayingMiniView />
|
||||
<GlobalContextMenu />
|
||||
</Router>
|
||||
</GlobalHotKeys>
|
||||
</ThemeProvider>
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
import React from 'react';
|
||||
import { ContextMenuWindow, StyledContextMenuButton } from './styled';
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { useQuery } from 'react-query';
|
||||
import { useHistory } from 'react-router';
|
||||
import { Popover, Whisper } from 'rsuite';
|
||||
import { getPlaylists, populatePlaylist } from '../../api/api';
|
||||
import { useAppDispatch, useAppSelector } from '../../redux/hooks';
|
||||
import {
|
||||
addProcessingPlaylist,
|
||||
removeProcessingPlaylist,
|
||||
setContextMenu,
|
||||
} from '../../redux/miscSlice';
|
||||
import {
|
||||
ContextMenuTitle,
|
||||
ContextMenuDivider,
|
||||
ContextMenuWindow,
|
||||
StyledContextMenuButton,
|
||||
StyledInputPicker,
|
||||
StyledButton,
|
||||
} from './styled';
|
||||
import { notifyToast } from './toast';
|
||||
|
||||
export const ContextMenuButton = ({ children, ...rest }: any) => {
|
||||
return (
|
||||
@@ -9,7 +27,7 @@ export const ContextMenuButton = ({ children, ...rest }: any) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const NowPlayingContextMenu = ({
|
||||
export const ContextMenu = ({
|
||||
yPos,
|
||||
xPos,
|
||||
width,
|
||||
@@ -31,3 +49,135 @@ export const NowPlayingContextMenu = ({
|
||||
</ContextMenuWindow>
|
||||
);
|
||||
};
|
||||
|
||||
export const GlobalContextMenu = () => {
|
||||
const history = useHistory();
|
||||
const dispatch = useAppDispatch();
|
||||
const misc = useAppSelector((state) => state.misc);
|
||||
const multiSelect = useAppSelector((state) => state.multiSelect);
|
||||
const playlistTriggerRef = useRef<any>();
|
||||
const [selectedPlaylistId, setSelectedPlaylistId] = useState('');
|
||||
|
||||
const { data: playlists }: any = useQuery(['playlists', 'name'], () =>
|
||||
getPlaylists('name')
|
||||
);
|
||||
|
||||
const handleAddToPlaylist = async () => {
|
||||
// If the window is closed, the selectedPlaylistId will be deleted
|
||||
const localSelectedPlaylistId = selectedPlaylistId;
|
||||
dispatch(addProcessingPlaylist(selectedPlaylistId));
|
||||
|
||||
const sortedEntries = [...multiSelect.selected].sort(
|
||||
(a: any, b: any) => a.rowIndex - b.rowIndex
|
||||
);
|
||||
|
||||
try {
|
||||
const res = await populatePlaylist(
|
||||
localSelectedPlaylistId,
|
||||
sortedEntries
|
||||
);
|
||||
|
||||
if (res.status === 'failed') {
|
||||
notifyToast('error', res.error.message);
|
||||
} else {
|
||||
notifyToast(
|
||||
'success',
|
||||
<>
|
||||
<p>
|
||||
Added {sortedEntries.length} song(s) to playlist "
|
||||
{
|
||||
playlists.find(
|
||||
(playlist: any) => playlist.id === localSelectedPlaylistId
|
||||
)?.name
|
||||
}
|
||||
"
|
||||
</p>
|
||||
<StyledButton
|
||||
appearance="link"
|
||||
onClick={() => {
|
||||
history.push(`/playlist/${localSelectedPlaylistId}`);
|
||||
dispatch(setContextMenu({ show: false }));
|
||||
}}
|
||||
>
|
||||
Go to playlist
|
||||
</StyledButton>
|
||||
</>
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
dispatch(removeProcessingPlaylist(localSelectedPlaylistId));
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{misc.contextMenu.show && misc.contextMenu.type === 'nowPlaying' && (
|
||||
<>
|
||||
<ContextMenu
|
||||
xPos={misc.contextMenu.xPos}
|
||||
yPos={misc.contextMenu.yPos}
|
||||
width={140}
|
||||
numOfButtons={5}
|
||||
numOfDividers={3}
|
||||
hasTitle
|
||||
>
|
||||
<ContextMenuTitle>
|
||||
Selected: {multiSelect.selected.length}
|
||||
</ContextMenuTitle>
|
||||
<ContextMenuDivider />
|
||||
<ContextMenuButton>Add to queue</ContextMenuButton>
|
||||
<ContextMenuButton>Remove from current</ContextMenuButton>
|
||||
<ContextMenuDivider />
|
||||
|
||||
<Whisper
|
||||
ref={playlistTriggerRef}
|
||||
enterable
|
||||
placement="autoHorizontal"
|
||||
trigger="none"
|
||||
speaker={
|
||||
<Popover>
|
||||
<StyledInputPicker
|
||||
data={playlists}
|
||||
virtualized
|
||||
style={{ width: '150px' }}
|
||||
labelKey="name"
|
||||
valueKey="id"
|
||||
onChange={(e: any) => setSelectedPlaylistId(e)}
|
||||
/>
|
||||
<StyledButton
|
||||
disabled={
|
||||
!selectedPlaylistId ||
|
||||
misc.isProcessingPlaylist.includes(selectedPlaylistId)
|
||||
}
|
||||
loading={misc.isProcessingPlaylist.includes(
|
||||
selectedPlaylistId
|
||||
)}
|
||||
onClick={handleAddToPlaylist}
|
||||
>
|
||||
Add
|
||||
</StyledButton>
|
||||
</Popover>
|
||||
}
|
||||
>
|
||||
<ContextMenuButton
|
||||
onClick={() =>
|
||||
playlistTriggerRef.current.state.isOverlayShown
|
||||
? playlistTriggerRef.current.close()
|
||||
: playlistTriggerRef.current.open()
|
||||
}
|
||||
>
|
||||
Add to playlist
|
||||
</ContextMenuButton>
|
||||
</Whisper>
|
||||
|
||||
<ContextMenuDivider />
|
||||
<ContextMenuButton>Add to favorites</ContextMenuButton>
|
||||
<ContextMenuButton>Remove from favorites</ContextMenuButton>
|
||||
</ContextMenu>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -170,7 +170,7 @@ export const ContextMenuWindow = styled.div<{
|
||||
left: ${(props) => `${props.xPos}px`};
|
||||
height: ${(props) =>
|
||||
`${
|
||||
props.numOfButtons * 30 +
|
||||
props.numOfButtons * 30.5 +
|
||||
props.numOfDividers * 7 +
|
||||
(props.hasTitle ? 16 : 0)
|
||||
}px`};
|
||||
@@ -180,7 +180,7 @@ export const ContextMenuWindow = styled.div<{
|
||||
overflow: hidden;
|
||||
overflow-x: hidden;
|
||||
font-size: smaller;
|
||||
background: ${(props) => props.theme.primary.background};
|
||||
background: ${(props) => props.theme.primary.sideBar};
|
||||
border: 1px #3c4043 solid;
|
||||
`;
|
||||
|
||||
|
||||
@@ -213,13 +213,11 @@ const ListViewTable = ({
|
||||
(entry: any) => entry.uniqueId === rowData.uniqueId
|
||||
).length > 0
|
||||
) {
|
||||
const xFix = misc.expandSidebar ? 185 : 50;
|
||||
const yFix = nowPlaying ? 150 : 215;
|
||||
dispatch(
|
||||
setContextMenu({
|
||||
show: true,
|
||||
xPos: e.pageX - xFix,
|
||||
yPos: e.pageY - yFix,
|
||||
xPos: e.pageX,
|
||||
yPos: e.pageY,
|
||||
rowId: rowData.uniqueId,
|
||||
type: nowPlaying ? 'nowPlaying' : 'other',
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user