mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-06-10 00:04:48 -07:00
upgrade packages + improve typing
This commit is contained in:
parent
fd55f4fb7f
commit
19f5eefdd2
138 changed files with 4504 additions and 11015 deletions
|
|
@ -1,24 +1,16 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Navigate } from 'react-router-dom';
|
||||
|
||||
import { ServerSelectors } from 'store';
|
||||
import { RouteEnum } from 'types';
|
||||
|
||||
import { useAppSelector } from 'store/store';
|
||||
import { AuthenticationService } from 'api';
|
||||
|
||||
const AuthGuard = ({ state }: AuthGuardProps) => {
|
||||
const AuthGuard = () => {
|
||||
const state = useAppSelector(s => ServerSelectors.getState(s));
|
||||
return !AuthenticationService.isConnected(state)
|
||||
? <Navigate to={RouteEnum.LOGIN} />
|
||||
: <div></div>;
|
||||
};
|
||||
|
||||
interface AuthGuardProps {
|
||||
state: number;
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
state: ServerSelectors.getState(state),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(AuthGuard);
|
||||
export default AuthGuard;
|
||||
|
|
|
|||
|
|
@ -1,27 +1,16 @@
|
|||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import React from 'react';
|
||||
import { Navigate } from 'react-router-dom';
|
||||
|
||||
import { ServerSelectors } from 'store';
|
||||
import { User } from 'types';
|
||||
|
||||
import { AuthenticationService } from 'api';
|
||||
import { RouteEnum } from 'types';
|
||||
import { useAppSelector } from 'store/store';
|
||||
|
||||
class ModGuard extends Component<ModGuardProps> {
|
||||
render() {
|
||||
return !AuthenticationService.isModerator(this.props.user)
|
||||
? <Navigate to={RouteEnum.SERVER} />
|
||||
: '';
|
||||
}
|
||||
const ModGuard = () => {
|
||||
const user = useAppSelector(state => ServerSelectors.getUser(state));
|
||||
return !AuthenticationService.isModerator(user)
|
||||
? <Navigate to={RouteEnum.SERVER} />
|
||||
: <></>;
|
||||
};
|
||||
|
||||
interface ModGuardProps {
|
||||
user: User;
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
user: ServerSelectors.getUser(state),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(ModGuard);
|
||||
export default ModGuard;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { InputField } from 'components';
|
|||
|
||||
import './InputAction.css';
|
||||
|
||||
const InputAction = ({ action, label, name, validate, disabled }) => (
|
||||
const InputAction = ({ action, label, name, validate = () => false, disabled = false }) => (
|
||||
<div className="input-action">
|
||||
<div className="input-action__item">
|
||||
<Field label={label} name={name} component={InputField} validate={validate} />
|
||||
|
|
@ -19,9 +19,4 @@ const InputAction = ({ action, label, name, validate, disabled }) => (
|
|||
</div>
|
||||
);
|
||||
|
||||
InputAction.defaultProps = {
|
||||
disabled: false,
|
||||
validate: () => false,
|
||||
}
|
||||
|
||||
export default InputAction;
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ const KnownHosts = (props) => {
|
|||
}, [loadKnownHosts]);
|
||||
|
||||
useEffect(() => {
|
||||
const { hosts, selectedHost } = hostsState;
|
||||
const { selectedHost } = hostsState;
|
||||
|
||||
if (selectedHost?.id) {
|
||||
updateLastSelectedHost(selectedHost.id).then(() => {
|
||||
|
|
@ -255,7 +255,7 @@ const KnownHosts = (props) => {
|
|||
</div>
|
||||
|
||||
{ host.editable && (
|
||||
<IconButton className='KnownHosts-item__edit' size='small' color='primary' onClick={(e) => {
|
||||
<IconButton className='KnownHosts-item__edit' size='small' color='primary' onClick={() => {
|
||||
openEditKnownHostDialog(hostsState.hosts[index]);
|
||||
}}>
|
||||
<EditRoundedIcon fontSize='small' />
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
// eslint-disable-next-line
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Select, MenuItem } from '@mui/material';
|
||||
import FormControl from '@mui/material/FormControl';
|
||||
import InputLabel from '@mui/material/InputLabel';
|
||||
|
||||
import { Images } from 'images/Images';
|
||||
import { Language, LanguageCountry, LanguageNative } from 'types';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// eslint-disable-next-line
|
||||
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import Popover from '@mui/material/Popover';
|
||||
|
|
@ -17,7 +17,7 @@ const classes = {
|
|||
popoverContent: `${PREFIX}-popoverContent`
|
||||
};
|
||||
|
||||
const Root = styled('span')(({ theme }) => ({
|
||||
const Root = styled('span')(() => ({
|
||||
[`& .${classes.popover}`]: {
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import {
|
|||
import CardCallout from './CardCallout';
|
||||
import './Message.css';
|
||||
|
||||
const Message = ({ message: { message, messageType, timeOf, timeReceived } }) => (
|
||||
const Message = ({ message: { message } }) => (
|
||||
<div className='message'>
|
||||
<div className='message__detail'>
|
||||
<ParsedMessage message={message} />
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
import { Component, CElement } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Hidden from '@mui/material/Hidden';
|
||||
|
||||
import './ThreePaneLayout.css';
|
||||
|
||||
|
|
@ -12,25 +10,23 @@ class ThreePaneLayout extends Component<ThreePaneLayoutProps> {
|
|||
return (
|
||||
<div className="three-pane-layout">
|
||||
<Grid container rowSpacing={0} columnSpacing={2} className="grid">
|
||||
<Grid item xs={12} md={9} lg={10} className="grid-main">
|
||||
<Grid item className={
|
||||
<Grid size={{ xs: 12, md: 9, lg: 10 }} className="grid-main">
|
||||
<Grid className={
|
||||
'grid-main__top'
|
||||
+ (this.props.fixedHeight ? ' fixedHeight' : '')
|
||||
}>
|
||||
{this.props.top}
|
||||
</Grid>
|
||||
<Grid item className={
|
||||
<Grid className={
|
||||
'grid-main__bottom'
|
||||
+ (this.props.fixedHeight ? ' fixedHeight' : '')
|
||||
}>
|
||||
{this.props.bottom}
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Hidden mdDown>
|
||||
<Grid item md={3} lg={2} className="grid-side">
|
||||
{this.props.side}
|
||||
</Grid>
|
||||
</Hidden>
|
||||
<Grid size={{ md: 3, lg: 2 }} sx={{ display: { xs: 'none', md: 'block' } }} className="grid-side">
|
||||
{this.props.side}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -44,6 +40,4 @@ interface ThreePaneLayoutProps {
|
|||
fixedHeight?: boolean,
|
||||
}
|
||||
|
||||
const mapStateToProps = state => ({});
|
||||
|
||||
export default connect(mapStateToProps)(ThreePaneLayout);
|
||||
export default ThreePaneLayout;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import * as React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
import Alert, { AlertProps } from '@mui/material/Alert';
|
||||
import Alert from '@mui/material/Alert';
|
||||
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
||||
import Slide, { SlideProps } from '@mui/material/Slide';
|
||||
import Slide from '@mui/material/Slide';
|
||||
import Snackbar from '@mui/material/Snackbar';
|
||||
|
||||
const iconMapping = {
|
||||
|
|
@ -11,7 +11,7 @@ const iconMapping = {
|
|||
}
|
||||
|
||||
function Toast(props) {
|
||||
const { open, onClose, severity, autoHideDuration, children } = props
|
||||
const { open, onClose, severity = 'success', autoHideDuration = 10000, children } = props
|
||||
|
||||
const rootElemRef = React.useRef(document.createElement('div'));
|
||||
|
||||
|
|
@ -37,9 +37,9 @@ function Toast(props) {
|
|||
TransitionComponent={TransitionLeft}
|
||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
||||
>
|
||||
<Alert onClose={handleClose} severity={severity} iconMapping={iconMapping}>
|
||||
{children}
|
||||
</Alert>
|
||||
<Alert onClose={handleClose} severity={severity} iconMapping={iconMapping}
|
||||
slotProps={{ message: { children } }}
|
||||
/>
|
||||
</Snackbar>
|
||||
)
|
||||
if (!rootElemRef.current) {
|
||||
|
|
@ -52,12 +52,6 @@ function Toast(props) {
|
|||
);
|
||||
}
|
||||
|
||||
Toast.defaultProps = {
|
||||
severity: 'success',
|
||||
// 10s wait before automatically dismissing the Toast.
|
||||
autoHideDuration: 10000,
|
||||
}
|
||||
|
||||
function TransitionLeft(props) {
|
||||
return <Slide {...props} direction="left" />;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { createContext, FC, PropsWithChildren, ReactChild, ReactNode, useContext, useEffect, useReducer, ContextType, Context } from 'react'
|
||||
import { createContext, FC, PropsWithChildren, ReactChild, ReactNode, useContext, useEffect, useReducer, Context } from 'react'
|
||||
|
||||
import { ACTIONS, initialState, reducer } from './reducer';
|
||||
import Toast from './Toast'
|
||||
|
|
@ -18,10 +18,10 @@ interface ToastState {
|
|||
|
||||
const ToastContext: Context<any> = createContext<ToastState>({
|
||||
toasts: new Map<string, ToastEntry>(),
|
||||
addToast: (key, children) => {},
|
||||
openToast: (key) => {},
|
||||
closeToast: (key) => {},
|
||||
removeToast: (key) => {},
|
||||
addToast: (_key, _children) => {},
|
||||
openToast: (_key) => {},
|
||||
closeToast: (_key) => {},
|
||||
removeToast: (_key) => {},
|
||||
});
|
||||
|
||||
export const ToastProvider: FC<PropsWithChildren> = (props) => {
|
||||
|
|
@ -56,7 +56,7 @@ export interface ToastHookOptions {
|
|||
children: ReactNode
|
||||
}
|
||||
|
||||
export function useToast<ToastHookOptions>({ key, children }) {
|
||||
export function useToast({ key, children }) {
|
||||
const { addToast, openToast, closeToast, removeToast } = useContext(ToastContext)
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
// eslint-disable-next-line
|
||||
import React, { Component } from "react";
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { NavLink, generatePath } from 'react-router-dom';
|
||||
|
||||
import Menu from '@mui/material/Menu';
|
||||
|
|
@ -10,141 +9,85 @@ import { Images } from 'images/Images';
|
|||
import { SessionService } from 'api';
|
||||
import { ServerSelectors } from 'store';
|
||||
import { RouteEnum, User } from 'types';
|
||||
import { useAppSelector } from 'store/store';
|
||||
|
||||
import './UserDisplay.css';
|
||||
|
||||
|
||||
class UserDisplay extends Component<UserDisplayProps, UserDisplayState> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const UserDisplay = ({ user }: UserDisplayProps) => {
|
||||
const buddyList = useAppSelector(state => ServerSelectors.getBuddyList(state));
|
||||
const ignoreList = useAppSelector(state => ServerSelectors.getIgnoreList(state));
|
||||
const [position, setPosition] = useState<{ x: number; y: number } | null>(null);
|
||||
|
||||
this.handleClick = this.handleClick.bind(this);
|
||||
this.handleClose = this.handleClose.bind(this);
|
||||
this.navigateToUserProfile = this.navigateToUserProfile.bind(this);
|
||||
this.addToBuddyList = this.addToBuddyList.bind(this);
|
||||
this.removeFromBuddyList = this.removeFromBuddyList.bind(this);
|
||||
this.addToIgnoreList = this.addToIgnoreList.bind(this);
|
||||
this.removeFromIgnoreList = this.removeFromIgnoreList.bind(this);
|
||||
const { name, country } = user;
|
||||
|
||||
this.isABuddy = this.isABuddy.bind(this);
|
||||
this.isIgnored = this.isIgnored.bind(this);
|
||||
|
||||
this.state = {
|
||||
position: null
|
||||
};
|
||||
}
|
||||
|
||||
handleClick(event) {
|
||||
const handleClick = (event) => {
|
||||
event.preventDefault();
|
||||
setPosition({ x: event.clientX + 2, y: event.clientY + 4 });
|
||||
};
|
||||
|
||||
this.setState({
|
||||
position: {
|
||||
x: event.clientX + 2,
|
||||
y: event.clientY + 4,
|
||||
}
|
||||
});
|
||||
}
|
||||
const handleClose = () => setPosition(null);
|
||||
|
||||
handleClose() {
|
||||
this.setState({
|
||||
position: null
|
||||
});
|
||||
}
|
||||
const isABuddy = buddyList.filter(u => u.name === user.name).length;
|
||||
const isIgnored = ignoreList.filter(u => u.name === user.name).length;
|
||||
|
||||
navigateToUserProfile() {
|
||||
this.handleClose();
|
||||
}
|
||||
const onAddBuddy = () => {
|
||||
SessionService.addToBuddyList(user.name);
|
||||
handleClose();
|
||||
};
|
||||
const onRemoveBuddy = () => {
|
||||
SessionService.removeFromBuddyList(user.name);
|
||||
handleClose();
|
||||
};
|
||||
const onAddIgnore = () => {
|
||||
SessionService.addToIgnoreList(user.name);
|
||||
handleClose();
|
||||
};
|
||||
const onRemoveIgnore = () => {
|
||||
SessionService.removeFromIgnoreList(user.name);
|
||||
handleClose();
|
||||
};
|
||||
|
||||
addToBuddyList() {
|
||||
SessionService.addToBuddyList(this.props.user.name);
|
||||
this.handleClose();
|
||||
}
|
||||
|
||||
removeFromBuddyList() {
|
||||
SessionService.removeFromBuddyList(this.props.user.name);
|
||||
this.handleClose();
|
||||
}
|
||||
|
||||
addToIgnoreList() {
|
||||
SessionService.addToIgnoreList(this.props.user.name);
|
||||
this.handleClose();
|
||||
}
|
||||
|
||||
removeFromIgnoreList() {
|
||||
SessionService.removeFromIgnoreList(this.props.user.name);
|
||||
this.handleClose();
|
||||
}
|
||||
|
||||
isABuddy() {
|
||||
return this.props.buddyList.filter(user => user.name === this.props.user.name).length;
|
||||
}
|
||||
|
||||
isIgnored() {
|
||||
return this.props.ignoreList.filter(user => user.name === this.props.user.name).length;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { user } = this.props;
|
||||
const { position } = this.state;
|
||||
const { name, country } = user;
|
||||
|
||||
const isABuddy = this.isABuddy();
|
||||
const isIgnored = this.isIgnored();
|
||||
|
||||
// console.log('user', name, !!isABuddy, !!isIgnored);
|
||||
|
||||
return (
|
||||
<div className="user-display">
|
||||
<NavLink to={generatePath(RouteEnum.PLAYER, { name })} className="plain-link">
|
||||
<div className="user-display__details" onContextMenu={this.handleClick}>
|
||||
<img className="user-display__country" src={Images.Countries[country]} alt={country}></img>
|
||||
<div className="user-display__name single-line-ellipsis">{name}</div>
|
||||
</div>
|
||||
</NavLink>
|
||||
<div className="user-display__menu">
|
||||
<Menu
|
||||
open={Boolean(position)}
|
||||
onClose={this.handleClose}
|
||||
anchorReference='anchorPosition'
|
||||
anchorPosition={
|
||||
position !== null
|
||||
? { top: position.y, left: position.x }
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<NavLink to={generatePath(RouteEnum.PLAYER, { name })} className="user-display__link plain-link">
|
||||
<MenuItem dense>Chat</MenuItem>
|
||||
</NavLink>
|
||||
{
|
||||
!isABuddy
|
||||
? (<MenuItem dense onClick={this.addToBuddyList}>Add to Buddy List</MenuItem>)
|
||||
: (<MenuItem dense onClick={this.removeFromBuddyList}>Remove From Buddy List</MenuItem>)
|
||||
}
|
||||
{
|
||||
!isIgnored
|
||||
? (<MenuItem dense onClick={this.addToIgnoreList}>Add to Ignore List</MenuItem>)
|
||||
: (<MenuItem dense onClick={this.removeFromIgnoreList}>Remove From Ignore List</MenuItem>)
|
||||
}
|
||||
</Menu>
|
||||
return (
|
||||
<div className="user-display">
|
||||
<NavLink to={generatePath(RouteEnum.PLAYER, { name })} className="plain-link">
|
||||
<div className="user-display__details" onContextMenu={handleClick}>
|
||||
<img className="user-display__country" src={Images.Countries[country]} alt={country}></img>
|
||||
<div className="user-display__name single-line-ellipsis">{name}</div>
|
||||
</div>
|
||||
</NavLink>
|
||||
<div className="user-display__menu">
|
||||
<Menu
|
||||
open={Boolean(position)}
|
||||
onClose={handleClose}
|
||||
anchorReference='anchorPosition'
|
||||
anchorPosition={
|
||||
position !== null
|
||||
? { top: position.y, left: position.x }
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<NavLink to={generatePath(RouteEnum.PLAYER, { name })} className="user-display__link plain-link">
|
||||
<MenuItem dense>Chat</MenuItem>
|
||||
</NavLink>
|
||||
{
|
||||
!isABuddy
|
||||
? (<MenuItem dense onClick={onAddBuddy}>Add to Buddy List</MenuItem>)
|
||||
: (<MenuItem dense onClick={onRemoveBuddy}>Remove From Buddy List</MenuItem>)
|
||||
}
|
||||
{
|
||||
!isIgnored
|
||||
? (<MenuItem dense onClick={onAddIgnore}>Add to Ignore List</MenuItem>)
|
||||
: (<MenuItem dense onClick={onRemoveIgnore}>Remove From Ignore List</MenuItem>)
|
||||
}
|
||||
</Menu>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
interface UserDisplayProps {
|
||||
user: User;
|
||||
buddyList: User[];
|
||||
ignoreList: User[];
|
||||
}
|
||||
|
||||
interface UserDisplayState {
|
||||
position: any;
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
buddyList: ServerSelectors.getBuddyList(state),
|
||||
ignoreList: ServerSelectors.getIgnoreList(state)
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(UserDisplay);
|
||||
export default UserDisplay;
|
||||
|
|
|
|||
|
|
@ -1,34 +1,29 @@
|
|||
// eslint-disable-next-line
|
||||
import React from "react";
|
||||
|
||||
import { FixedSizeList as List } from 'react-window';
|
||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||
import { List, RowComponentProps } from 'react-window';
|
||||
|
||||
import './VirtualList.css';
|
||||
|
||||
const VirtualList = ({ items, itemKey, className = {}, size = 30 }) => (
|
||||
<div className="virtual-list">
|
||||
<AutoSizer>
|
||||
{({ height, width }) => (
|
||||
<List
|
||||
className={`virtual-list__list ${className}`}
|
||||
height={height}
|
||||
width={width}
|
||||
itemData={items}
|
||||
itemCount={items.length}
|
||||
itemSize={size}
|
||||
itemKey={itemKey}
|
||||
>
|
||||
{Row}
|
||||
</List>
|
||||
)}
|
||||
</AutoSizer>
|
||||
interface RowData {
|
||||
items: any[];
|
||||
}
|
||||
|
||||
const Row = ({ index, style, items }: RowComponentProps<RowData>) => (
|
||||
<div style={style}>
|
||||
{items[index]}
|
||||
</div>
|
||||
);
|
||||
|
||||
const Row = ({ data, index, style }) => (
|
||||
<div style={style}>
|
||||
{data[index]}
|
||||
const VirtualList = ({ items, className = {}, size = 30 }) => (
|
||||
<div className="virtual-list">
|
||||
<List<RowData>
|
||||
className={`virtual-list__list ${className}`}
|
||||
rowCount={items.length}
|
||||
rowHeight={size}
|
||||
rowComponent={Row}
|
||||
rowProps={{ items }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue