Browse Source

add initial context menu

fix default click
- remove preventDefault() from root container
master
jeffvli 3 years ago
parent
commit
63012f4035
  1. 4
      src/__tests__/App.test.tsx
  2. 36
      src/components/layout/Layout.tsx
  3. 2
      src/components/layout/Sidebar.tsx
  4. 1
      src/components/layout/styled.tsx
  5. 33
      src/components/shared/ContextMenu.tsx
  6. 42
      src/components/shared/styled.ts
  7. 36
      src/components/viewtypes/ListViewTable.tsx
  8. 40
      src/components/viewtypes/ListViewType.tsx
  9. 28
      src/redux/miscSlice.ts
  10. 4
      src/styles/custom-theme.less

4
src/__tests__/App.test.tsx

@ -66,6 +66,10 @@ const playerState: Player = {
const miscState: General = {
theme: 'defaultDark',
font: 'Poppins',
contextMenu: {
show: false,
},
expandSidebar: false,
modal: {
currentPageIndex: undefined,
show: false,

36
src/components/layout/Layout.tsx

@ -1,16 +1,19 @@
import React, { useState } from 'react';
import React from 'react';
import { useHistory } from 'react-router-dom';
import { Content } from 'rsuite';
import Sidebar from './Sidebar';
import Titlebar from './Titlebar';
import { RootContainer, RootFooter, MainContainer } from './styled';
import { setContextMenu, setExpandSidebar } from '../../redux/miscSlice';
import { useAppDispatch, useAppSelector } from '../../redux/hooks';
const Layout = ({ footer, children, disableSidebar, font }: any) => {
const [expandSidebar, setExpandSidebar] = useState(false);
const history = useHistory();
const dispatch = useAppDispatch();
const misc = useAppSelector((state) => state.misc);
const handleToggle = () => {
setExpandSidebar(!expandSidebar);
dispatch(setExpandSidebar(!misc.expandSidebar));
};
const handleSidebarSelect = (e: string) => {
@ -56,14 +59,35 @@ const Layout = ({ footer, children, disableSidebar, font }: any) => {
<>
<Titlebar font={font} />
<Sidebar
expand={expandSidebar}
expand={misc.expandSidebar}
handleToggle={handleToggle}
handleSidebarSelect={handleSidebarSelect}
disableSidebar={disableSidebar}
font={font}
onClick={() => {
if (misc.contextMenu.show === true) {
dispatch(
setContextMenu({
show: false,
})
);
}
}}
/>
<RootContainer id="container-root" font={font}>
<MainContainer id="container-main" expanded={expandSidebar}>
<RootContainer
id="container-root"
font={font}
onClick={() => {
if (misc.contextMenu.show === true) {
dispatch(
setContextMenu({
show: false,
})
);
}
}}
>
<MainContainer id="container-main" expanded={misc.expandSidebar}>
<Content id="container-content">{children}</Content>
</MainContainer>
<RootFooter id="container-footer">{footer}</RootFooter>

2
src/components/layout/Sidebar.tsx

@ -8,6 +8,7 @@ const Sidebar = ({
handleSidebarSelect,
disableSidebar,
font,
...rest
}: any) => {
return (
<FixedSidebar
@ -15,6 +16,7 @@ const Sidebar = ({
width={expand ? 193 : 56}
collapsible
font={font}
onClick={rest.onClick}
>
<Sidenav
style={{

1
src/components/layout/styled.tsx

@ -100,6 +100,7 @@ export const WindowControlButton = styled.div<{
// GenericPage.tsx
export const PageContainer = styled(Container)`
height: 100%;
overflow-x: hidden;
`;
export const PageHeader = styled(Header)<{ padding?: string }>`

33
src/components/shared/ContextMenu.tsx

@ -0,0 +1,33 @@
import React from 'react';
import { ContextMenuWindow, StyledContextMenuButton } from './styled';
export const ContextMenuButton = ({ children, ...rest }: any) => {
return (
<StyledContextMenuButton {...rest} appearance="subtle" size="xs" block>
{children}
</StyledContextMenuButton>
);
};
export const NowPlayingContextMenu = ({
yPos,
xPos,
width,
numOfButtons,
numOfDividers,
hasTitle,
children,
}: any) => {
return (
<ContextMenuWindow
yPos={yPos}
xPos={xPos}
width={width}
numOfButtons={numOfButtons}
numOfDividers={numOfDividers}
hasTitle={hasTitle}
>
{children}
</ContextMenuWindow>
);
};

42
src/components/shared/styled.ts

@ -156,3 +156,45 @@ export const StyledInputPicker = styled(InputPicker)<{ width?: number }>`
export const StyledIcon = styled(Icon)`
color: ${(props) => `${props.theme.primary.main} !important`};
`;
export const ContextMenuWindow = styled.div<{
yPos: number;
xPos: number;
numOfButtons: number;
numOfDividers: number;
width: number;
hasTitle: boolean;
}>`
position: absolute;
top: ${(props) => `${props.yPos}px`};
left: ${(props) => `${props.xPos}px`};
height: ${(props) =>
`${
props.numOfButtons * 30 +
props.numOfDividers * 7 +
(props.hasTitle ? 16 : 0)
}px`};
width: ${(props) => `${props.width}px`};
margin: 0px;
white-space: normal;
overflow: hidden;
overflow-x: hidden;
font-size: smaller;
background: ${(props) => props.theme.primary.background};
border: 1px #3c4043 solid;
`;
export const StyledContextMenuButton = styled(Button)`
text-align: left;
`;
export const ContextMenuDivider = styled.hr`
margin: 5px 0 5px 0;
`;
export const ContextMenuTitle = styled.div`
color: ${(props) => props.theme.primary.text};
margin-left: 5px;
margin-top: 5px;
user-select: none;
`;

36
src/components/viewtypes/ListViewTable.tsx

@ -24,7 +24,7 @@ import {
} from '../../shared/utils';
import cacheImage from '../shared/cacheImage';
import { setRating, star, unstar } from '../../api/api';
import { useAppDispatch } from '../../redux/hooks';
import { useAppDispatch, useAppSelector } from '../../redux/hooks';
import {
fixPlayer2Index,
setSort,
@ -32,7 +32,7 @@ import {
sortPlayQueue,
} from '../../redux/playQueueSlice';
import { StyledIconToggle, StyledRate } from '../shared/styled';
import { addModalPage } from '../../redux/miscSlice';
import { addModalPage, setContextMenu } from '../../redux/miscSlice';
import {
setCurrentMouseOverId,
setIsDragging,
@ -62,6 +62,7 @@ const ListViewTable = ({
}: any) => {
const history = useHistory();
const dispatch = useAppDispatch();
const misc = useAppSelector((state) => state.misc);
const queryClient = useQueryClient();
const [cachePath] = useState(path.join(getImageCachePath(), '/'));
const [sortColumn, setSortColumn] = useState<any>();
@ -203,6 +204,34 @@ const ListViewTable = ({
sortColumn={nowPlaying ? playQueue.sortColumn : sortColumn}
sortType={nowPlaying ? playQueue.sortType : sortType}
onSortColumn={handleSortColumn}
onRowContextMenu={(rowData: any, e: any) => {
e.preventDefault();
if (
(misc.contextMenu.show === false ||
misc.contextMenu.rowId !== rowData.uniqueId) &&
multiSelect.selected.filter(
(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,
rowId: rowData.uniqueId,
type: nowPlaying ? 'nowPlaying' : 'other',
})
);
} else {
dispatch(
setContextMenu({
show: false,
})
);
}
}}
// onScroll={onScroll}
>
{columns.map((column: any) => (
@ -233,7 +262,6 @@ const ListViewTable = ({
{(rowData: any, rowIndex: any) => {
return (
<TableCellWrapper
onContextMenu={() => console.log('fuck')}
playing={
(rowData.uniqueId === playQueue?.currentSongUniqueId &&
nowPlaying) ||
@ -698,7 +726,7 @@ const ListViewTable = ({
/>
) : column.dataKey === 'userRating' ? (
<StyledRate
size="xs"
size="sm"
readOnly={false}
defaultValue={
rowData?.userRating ? rowData.userRating : 0

40
src/components/viewtypes/ListViewType.tsx

@ -8,11 +8,16 @@ import React, {
forwardRef,
useImperativeHandle,
} from 'react';
import { DOMHelper } from 'rsuite';
import { DOMHelper, Rate } from 'rsuite';
import { useAppSelector } from '../../redux/hooks';
import PageLoader from '../loader/PageLoader';
import SelectionBar from '../selectionbar/SelectionBar';
import ListViewTable from './ListViewTable';
import {
NowPlayingContextMenu,
ContextMenuButton,
} from '../shared/ContextMenu';
import { ContextMenuDivider, ContextMenuTitle } from '../shared/styled';
declare global {
interface Window {
@ -40,6 +45,7 @@ const ListViewType = (
}: any,
ref: any
) => {
const misc = useAppSelector((state) => state.misc);
const [isDragging, setIsDragging] = useState(false);
const [dragDirection, setDragDirection] = useState('');
const [dragSpeed, setDragSpeed] = useState('');
@ -346,6 +352,38 @@ const ListViewType = (
/>
)}
</div>
{misc.contextMenu.show && misc.contextMenu.type === 'nowPlaying' && (
<NowPlayingContextMenu
xPos={misc.contextMenu.xPos}
yPos={misc.contextMenu.yPos}
width={130}
numOfButtons={6}
numOfDividers={5}
hasTitle
>
<ContextMenuTitle>
Selected: {multiSelect.selected.length}
</ContextMenuTitle>
<ContextMenuDivider />
<ContextMenuButton>Remove from queue</ContextMenuButton>
<ContextMenuDivider />
<ContextMenuButton>Add to playlist</ContextMenuButton>
<ContextMenuDivider />
<ContextMenuButton>Add favorite</ContextMenuButton>
<ContextMenuButton>Remove favorite</ContextMenuButton>
<ContextMenuDivider />
<ContextMenuButton>View details</ContextMenuButton>
<ContextMenuDivider />
<Rate
readOnly={false}
size="xs"
style={{ textAlign: 'center', marginLeft: '10px' }}
/>
</NowPlayingContextMenu>
)}
</>
);
};

28
src/redux/miscSlice.ts

@ -12,12 +12,22 @@ export interface Modal {
show: boolean;
currentPageIndex: number | undefined;
}
export interface ContextMenu {
show: boolean;
xPos?: number;
yPos?: number;
rowId?: string;
type?: string;
}
export interface General {
theme: string;
font: string;
modal: Modal;
modalPages: ModalPage[];
expandSidebar: boolean;
isProcessingPlaylist: string[];
contextMenu: ContextMenu;
}
const initialState: General = {
@ -28,13 +38,29 @@ const initialState: General = {
currentPageIndex: undefined,
},
modalPages: [],
expandSidebar: false,
isProcessingPlaylist: [],
contextMenu: {
show: false,
},
};
const miscSlice = createSlice({
name: 'misc',
initialState,
reducers: {
setExpandSidebar: (state, action: PayloadAction<boolean>) => {
state.expandSidebar = action.payload;
},
setContextMenu: (state, action: PayloadAction<ContextMenu>) => {
state.contextMenu.show = action.payload.show;
state.contextMenu.xPos = action.payload.xPos;
state.contextMenu.yPos = action.payload.yPos;
state.contextMenu.rowId = action.payload.rowId;
state.contextMenu.type = action.payload.type;
},
addProcessingPlaylist: (state, action: PayloadAction<string>) => {
state.isProcessingPlaylist.push(action.payload);
},
@ -111,5 +137,7 @@ export const {
decrementModalPage,
addProcessingPlaylist,
removeProcessingPlaylist,
setContextMenu,
setExpandSidebar,
} = miscSlice.actions;
export default miscSlice.reducer;

4
src/styles/custom-theme.less

@ -1,6 +1,10 @@
// Main
@body-bg: undefined;
// Rate
@rate-xs-font-size: 14px;
@rate-sm-font-size: 17px;
// Input
@input-bg: undefined;
@input-color: undefined;

Loading…
Cancel
Save