commit
77084c3aff
@ -13,17 +13,19 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@szhsin/react-menu": "^3.0.2",
|
"@szhsin/react-menu": "^3.1.2",
|
||||||
"@types/": "szhsin/react-menu",
|
"@types/": "szhsin/react-menu",
|
||||||
"@types/eventemitter2": "^4.1.0",
|
"@types/eventemitter2": "^4.1.0",
|
||||||
"@types/styled-jsx": "^3.4.4",
|
"@types/styled-jsx": "^3.4.4",
|
||||||
"@types/uuid": "^8.3.4",
|
"@types/uuid": "^8.3.4",
|
||||||
"eventemitter2": "^6.4.7",
|
"eventemitter2": "^6.4.7",
|
||||||
"mancala.js": "^0.0.2-beta.3",
|
"mancala.js": "^0.0.2-beta.3",
|
||||||
|
"notyf": "^3.10.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-router-dom": "6",
|
"react-router-dom": "6",
|
||||||
"styled-jsx": "^5.0.2",
|
"styled-jsx": "^5.0.2",
|
||||||
|
"sweetalert": "^2.1.2",
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@ -12,9 +12,11 @@ import Home from './routes/Home';
|
|||||||
import { initContext } from './context/context';
|
import { initContext } from './context/context';
|
||||||
import { RTMTWS } from './rtmt/rtmt_websocket';
|
import { RTMTWS } from './rtmt/rtmt_websocket';
|
||||||
import { getColorByBrightness } from './util/ColorUtil';
|
import { getColorByBrightness } from './util/ColorUtil';
|
||||||
import { ConnectionState } from './models/ConnectionState';
|
|
||||||
import { Theme } from './theme/Theme';
|
import { Theme } from './theme/Theme';
|
||||||
import LobyPage from './routes/LobyPage';
|
import LobyPage from './routes/LobyPage';
|
||||||
|
import swal from 'sweetalert';
|
||||||
|
import { ConnectionState } from './rtmt/rtmt';
|
||||||
|
|
||||||
const context = initContext();
|
const context = initContext();
|
||||||
|
|
||||||
const MancalaApp: FunctionComponent = () => {
|
const MancalaApp: FunctionComponent = () => {
|
||||||
@ -40,9 +42,15 @@ const MancalaApp: FunctionComponent = () => {
|
|||||||
setTheme(theme)
|
setTheme(theme)
|
||||||
}
|
}
|
||||||
const connectToServer = async () => {
|
const connectToServer = async () => {
|
||||||
|
try {
|
||||||
const userKey = await context.userKeyStore.getUserKey();
|
const userKey = await context.userKeyStore.getUserKey();
|
||||||
setUserKey(userKey);
|
setUserKey(userKey);
|
||||||
(context.rtmt as RTMTWS).initWebSocket(userKey);
|
(context.rtmt as RTMTWS).initWebSocket(userKey);
|
||||||
|
} catch (error) {
|
||||||
|
//TODO: check if it is network error!
|
||||||
|
swal(context.texts.Error + "!", context.texts.ErrorWhenRetrievingInformation, "error");
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
@ -74,7 +82,6 @@ const MancalaApp: FunctionComponent = () => {
|
|||||||
context.themeManager.theme.textColor,
|
context.themeManager.theme.textColor,
|
||||||
context.themeManager.theme.textLightColor
|
context.themeManager.theme.textLightColor
|
||||||
);
|
);
|
||||||
if (!userKey) return <></>;
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
@ -82,7 +89,7 @@ const MancalaApp: FunctionComponent = () => {
|
|||||||
<Route index element={<Home context={context} theme={theme} userKey={userKey} />} />
|
<Route index element={<Home context={context} theme={theme} userKey={userKey} />} />
|
||||||
<Route path="/" >
|
<Route path="/" >
|
||||||
<Route path="game" >
|
<Route path="game" >
|
||||||
<Route path=":gameId" element={<GamePage context={context} theme={theme} userKey={userKey} connectionState={connectionState} />} ></Route>
|
<Route path=":gameId" element={<GamePage context={context} theme={theme} userKey={userKey} />} ></Route>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="loby" element={<LobyPage context={context} theme={theme} userKey={userKey} />}>
|
<Route path="loby" element={<LobyPage context={context} theme={theme} userKey={userKey} />}>
|
||||||
</Route>
|
</Route>
|
||||||
@ -90,7 +97,7 @@ const MancalaApp: FunctionComponent = () => {
|
|||||||
</Routes>
|
</Routes>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
<FloatingPanel context={context} color={floatingPanelColor} visible={showConnectionState}>
|
<FloatingPanel context={context} color={floatingPanelColor} visible={showConnectionState}>
|
||||||
<span style={{ color: textColorOnBoard }}>{connectionStateText()}</span>
|
<span style={{ color: textColorOnBoard, transition: 'color 0.5s' }}>{connectionStateText()}</span>
|
||||||
</FloatingPanel>
|
</FloatingPanel>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import { Context } from "../context/context";
|
|||||||
import BoardViewModelFactory from "../factory/BoardViewModelFactory";
|
import BoardViewModelFactory from "../factory/BoardViewModelFactory";
|
||||||
import { PitViewModelFactory } from "../factory/PitViewModelFactory";
|
import { PitViewModelFactory } from "../factory/PitViewModelFactory";
|
||||||
import { Game } from "../models/Game";
|
import { Game } from "../models/Game";
|
||||||
|
import { Theme } from "../theme/Theme";
|
||||||
import { getColorByBrightness } from "../util/ColorUtil";
|
import { getColorByBrightness } from "../util/ColorUtil";
|
||||||
import BoardViewModel from "../viewmodel/BoardViewModel";
|
import BoardViewModel from "../viewmodel/BoardViewModel";
|
||||||
|
|
||||||
@ -35,6 +36,7 @@ export default class PitAnimator {
|
|||||||
) {
|
) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.onBoardViewModelUpdate = onBoardViewModelUpdate;
|
this.onBoardViewModelUpdate = onBoardViewModelUpdate;
|
||||||
|
this.context.themeManager.on("themechange", this.onThemeChange.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
get mancalaGame(): MancalaGame | undefined {
|
get mancalaGame(): MancalaGame | undefined {
|
||||||
@ -190,6 +192,11 @@ export default class PitAnimator {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onThemeChange(theme: Theme){
|
||||||
|
if(!this.game) return;
|
||||||
|
this.onBoardViewModelUpdate?.(this.getBoardViewModelFromGame(this.game));
|
||||||
|
}
|
||||||
|
|
||||||
public resetAnimationState() {
|
public resetAnimationState() {
|
||||||
this.animationIndex = -1;
|
this.animationIndex = -1;
|
||||||
this.currentHistoryItem = undefined;
|
this.currentHistoryItem = undefined;
|
||||||
@ -204,6 +211,7 @@ export default class PitAnimator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public dispose() {
|
public dispose() {
|
||||||
|
this.context.themeManager.off("themechange", this.onThemeChange.bind(this));
|
||||||
this.resetAnimationState();
|
this.resetAnimationState();
|
||||||
this.clearCurrentInterval();
|
this.clearCurrentInterval();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,7 @@ const Button: FunctionComponent<{
|
|||||||
<button
|
<button
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
style={{
|
style={{
|
||||||
background: color,
|
backgroundColor: color,
|
||||||
color: textColor,
|
color: textColor,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -28,6 +28,9 @@ const Button: FunctionComponent<{
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 30px;
|
border-radius: 30px;
|
||||||
|
transition: color 0.5s;
|
||||||
|
transition: background-color 0.5s;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
`}</style>
|
`}</style>
|
||||||
{text}
|
{text}
|
||||||
|
|||||||
@ -11,6 +11,8 @@ const CircularPanel: FunctionComponent<{
|
|||||||
div {
|
div {
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
border-radius: 30px;
|
border-radius: 30px;
|
||||||
|
transition: background-color 0.5s;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -99,7 +99,7 @@ const InfoPanel: FunctionComponent<{
|
|||||||
if (text) {
|
if (text) {
|
||||||
return (
|
return (
|
||||||
<CircularPanel style={style} color={containerColor}>
|
<CircularPanel style={style} color={containerColor}>
|
||||||
<h4 style={{ margin: "0", color: textColor }}>
|
<h4 style={{ margin: "0", color: textColor, transition: 'color 0.5s' }}>
|
||||||
{text}
|
{text}
|
||||||
</h4>
|
</h4>
|
||||||
</CircularPanel>
|
</CircularPanel>
|
||||||
|
|||||||
@ -14,6 +14,7 @@ const PageContainer: FunctionComponent<{ theme: Theme }> = (props) => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
|
transition: background-color 0.5s;
|
||||||
}
|
}
|
||||||
`}</style>
|
`}</style>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
|||||||
@ -16,17 +16,13 @@ const UserStatus: FunctionComponent<{
|
|||||||
}> = ({ context, user, layoutMode, visible, style }) => {
|
}> = ({ context, user, layoutMode, visible, style }) => {
|
||||||
if (visible === false) return <></>;
|
if (visible === false) return <></>;
|
||||||
const textColorOnBoard = getColorByBrightness(
|
const textColorOnBoard = getColorByBrightness(
|
||||||
context.themeManager.theme.boardColor,
|
context.themeManager.theme.background,
|
||||||
context.themeManager.theme.textColor,
|
context.themeManager.theme.textColor,
|
||||||
context.themeManager.theme.textLightColor
|
context.themeManager.theme.textLightColor
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<div style={style} className={layoutMode === "right" ? "flex-rtl" : "flex-ltr"}>
|
<div style={style} className={layoutMode === "right" ? "flex-rtl" : "flex-ltr"}>
|
||||||
<span style={{color: textColorOnBoard}} className="material-symbols-outlined icon" >
|
<span style={{color: textColorOnBoard, transition: 'color 0.5s'}} className='text'>{user.isAnonymous ? context.texts.Anonymous : user.name}</span>
|
||||||
face_6
|
|
||||||
</span>
|
|
||||||
<Space width='5px' />
|
|
||||||
<span style={{color: textColorOnBoard}} className='text'>{user.isAnonymous ? context.texts.Anonymous : user.name}</span>
|
|
||||||
<Space width='5px' />
|
<Space width='5px' />
|
||||||
<div className={"circle " + (user.isOnline ? "online" : "offline")}></div>
|
<div className={"circle " + (user.isOnline ? "online" : "offline")}></div>
|
||||||
<style jsx>{`
|
<style jsx>{`
|
||||||
@ -43,6 +39,8 @@ const UserStatus: FunctionComponent<{
|
|||||||
min-height: 15px;
|
min-height: 15px;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
border: 2px solid ${context.themeManager.theme.boardColor};
|
border: 2px solid ${context.themeManager.theme.boardColor};
|
||||||
|
transition: background-color 0.5s;
|
||||||
|
transition: color 0.5s;
|
||||||
}
|
}
|
||||||
.flex-rtl {
|
.flex-rtl {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@ -29,7 +29,7 @@ const StoreView: FunctionComponent<{
|
|||||||
gridRow: gridRow
|
gridRow: gridRow
|
||||||
}}>
|
}}>
|
||||||
{stones}
|
{stones}
|
||||||
<span className="store-stone-count-text" style={{ color: textColor }}>
|
<span className="store-stone-count-text" style={{ color: textColor, transition: 'color 0.5s' }}>
|
||||||
{stones.length}
|
{stones.length}
|
||||||
</span>
|
</span>
|
||||||
<style jsx>{`
|
<style jsx>{`
|
||||||
@ -42,6 +42,7 @@ const StoreView: FunctionComponent<{
|
|||||||
align-content: center;
|
align-content: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
transition: background-color 0.5s;
|
||||||
}
|
}
|
||||||
.store-stone-count-text {
|
.store-stone-count-text {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@ -13,6 +13,7 @@ const HeaderBar: FunctionComponent<{ color?: string }> = ({children, color }) =>
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
|
transition: background-color 0.5s;
|
||||||
}
|
}
|
||||||
`}</style>
|
`}</style>
|
||||||
</div>)
|
</div>)
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { Context } from '../../context/context';
|
|||||||
|
|
||||||
const HeaderbarTitle: FunctionComponent<{ title: string, color: string }> = ({ title, color }) => {
|
const HeaderbarTitle: FunctionComponent<{ title: string, color: string }> = ({ title, color }) => {
|
||||||
return (
|
return (
|
||||||
<h1 style={{ color: color }} className="header-bar-title">
|
<h1 style={{ color: color, transition: 'color 0.5s' }} className="header-bar-title">
|
||||||
{title}
|
{title}
|
||||||
<style jsx>{`
|
<style jsx>{`
|
||||||
.header-bar-title {
|
.header-bar-title {
|
||||||
|
|||||||
@ -8,22 +8,27 @@ import "@szhsin/react-menu/dist/transitions/slide.css"
|
|||||||
const ThemeSwitchMenu: FunctionComponent<{ context: Context, textColor: string }> = (props) => {
|
const ThemeSwitchMenu: FunctionComponent<{ context: Context, textColor: string }> = (props) => {
|
||||||
const { context, textColor } = props;
|
const { context, textColor } = props;
|
||||||
const menuButton = <span
|
const menuButton = <span
|
||||||
style={{ color: textColor }}
|
style={{ color: textColor, cursor: 'pointer', userSelect: 'none' }}
|
||||||
className="material-symbols-outlined">
|
className="material-symbols-outlined">
|
||||||
light_mode
|
light_mode
|
||||||
</span>;
|
</span>;
|
||||||
const menuItems = context.themeManager.themes.map((theme, index) => {
|
const menuItems = context.themeManager.themes.map((theme, index) => {
|
||||||
const themeBackground = context.themeManager.theme.background;
|
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={index}
|
key={index}
|
||||||
style={{ color: textColor }}
|
style={{ color: textColor }}
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
onMouseOver={(event) => (event.target.style.background = themeBackground)}
|
onMouseOver={(event) => {
|
||||||
|
const htmlElement: HTMLElement = event.target as HTMLElement;
|
||||||
|
if (htmlElement.localName === "li") htmlElement.style.background = "transparent";
|
||||||
|
}}
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
onMouseOut={(event) => (event.target.style.background = "transparent")}
|
onMouseOut={(event) => {
|
||||||
|
const htmlElement: HTMLElement = event.target as HTMLElement;
|
||||||
|
if (htmlElement.localName === "li") htmlElement.style.background = "transparent";
|
||||||
|
}}
|
||||||
onClick={() => (context.themeManager.theme = theme)}>
|
onClick={() => (context.themeManager.theme = theme)}>
|
||||||
<div style={{ background: theme.boardColor }} className="theme-color-circle" />
|
<div style={{ background: theme.themePreviewColor }} className="theme-color-circle" />
|
||||||
{theme.name}
|
{theme.name}
|
||||||
<style jsx>{`
|
<style jsx>{`
|
||||||
.theme-color-circle {
|
.theme-color-circle {
|
||||||
|
|||||||
@ -6,7 +6,7 @@ export type Texts = {
|
|||||||
YourTurn: string,
|
YourTurn: string,
|
||||||
OpponentTurn: string,
|
OpponentTurn: string,
|
||||||
GameEnded: string,
|
GameEnded: string,
|
||||||
GameCrashed: string,
|
InternalErrorOccurred: string,
|
||||||
YouWon: string,
|
YouWon: string,
|
||||||
Won: string,
|
Won: string,
|
||||||
YouLost: string,
|
YouLost: string,
|
||||||
@ -21,12 +21,20 @@ export type Texts = {
|
|||||||
YouLeftTheGame: string,
|
YouLeftTheGame: string,
|
||||||
UserLeftTheGame: string,
|
UserLeftTheGame: string,
|
||||||
SearchingOpponent: string,
|
SearchingOpponent: string,
|
||||||
PleaseWait : string,
|
PleaseWait: string,
|
||||||
GameDraw : string,
|
GameDraw: string,
|
||||||
Anonymous: string,
|
Anonymous: string,
|
||||||
GameNotFound: string,
|
GameNotFound: string,
|
||||||
Loading: string,
|
Loading: string,
|
||||||
Playing: string,
|
Playing: string,
|
||||||
|
Error: string,
|
||||||
|
ErrorWhenRetrievingInformation: string,
|
||||||
|
UCanOnlyPlayYourOwnPits: string,
|
||||||
|
UMustWaitUntilCurrentMoveComplete: string,
|
||||||
|
UCanNotPlayEmptyPit: string,
|
||||||
|
AreYouSureToLeaveGame: string,
|
||||||
|
Yes: string,
|
||||||
|
Cancel: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const EnUs: Texts = {
|
export const EnUs: Texts = {
|
||||||
@ -36,14 +44,14 @@ export const EnUs: Texts = {
|
|||||||
YourTurn: "Your Turn",
|
YourTurn: "Your Turn",
|
||||||
OpponentTurn: "Opponent Turn",
|
OpponentTurn: "Opponent Turn",
|
||||||
GameEnded: "Game Ended",
|
GameEnded: "Game Ended",
|
||||||
GameCrashed: "Game Crashed",
|
InternalErrorOccurred: "An internal error has occurred",
|
||||||
YouWon: "You Won",
|
YouWon: "You Won",
|
||||||
Won: "Won",
|
Won: "Won",
|
||||||
YouLost: "You Lost",
|
YouLost: "You Lost",
|
||||||
Connecting: "Connecting",
|
Connecting: "Connecting",
|
||||||
Connected: "Connected",
|
Connected: "Connected",
|
||||||
CannotConnect: "Can't Connect",
|
CannotConnect: "Can't Connect",
|
||||||
ConnectionLost: "Connection Lost",
|
ConnectionLost: "Network Connection Lost",
|
||||||
ConnectingAgain: "Connecting Again",
|
ConnectingAgain: "Connecting Again",
|
||||||
ServerError: "Server Error",
|
ServerError: "Server Error",
|
||||||
SearchingOpponet: "Searching Opponet",
|
SearchingOpponet: "Searching Opponet",
|
||||||
@ -51,12 +59,20 @@ export const EnUs: Texts = {
|
|||||||
YouLeftTheGame: "You Left The Game",
|
YouLeftTheGame: "You Left The Game",
|
||||||
UserLeftTheGame: "Left The Game",
|
UserLeftTheGame: "Left The Game",
|
||||||
SearchingOpponent: "Searching Opponent",
|
SearchingOpponent: "Searching Opponent",
|
||||||
PleaseWait : "Please Wait",
|
PleaseWait: "Please Wait",
|
||||||
GameDraw : "Draw",
|
GameDraw: "Draw",
|
||||||
Anonymous: "Anonymous",
|
Anonymous: "Anonymous",
|
||||||
GameNotFound: "Game Not Found",
|
GameNotFound: "Game Not Found",
|
||||||
Loading: "Loading",
|
Loading: "Loading",
|
||||||
Playing: "Playing",
|
Playing: "Playing",
|
||||||
|
Error: "Error",
|
||||||
|
ErrorWhenRetrievingInformation: "An error occured when retrieving information!",
|
||||||
|
UCanOnlyPlayYourOwnPits: "You can only play your own pits",
|
||||||
|
UMustWaitUntilCurrentMoveComplete: "You must wait until the current move is complete",
|
||||||
|
UCanNotPlayEmptyPit: "You can not play empty pit",
|
||||||
|
AreYouSureToLeaveGame: "Are you sure to leave game?",
|
||||||
|
Yes: "Yes",
|
||||||
|
Cancel: "Cancel",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TrTr: Texts = {
|
export const TrTr: Texts = {
|
||||||
@ -66,14 +82,14 @@ export const TrTr: Texts = {
|
|||||||
YourTurn: "Sıra Sende",
|
YourTurn: "Sıra Sende",
|
||||||
OpponentTurn: "Sıra Rakipte",
|
OpponentTurn: "Sıra Rakipte",
|
||||||
GameEnded: "Oyun Bitti",
|
GameEnded: "Oyun Bitti",
|
||||||
GameCrashed: "Oyunda Hata Oluştu",
|
InternalErrorOccurred: "Dahili bir hata oluştu",
|
||||||
YouWon: "Kazandın",
|
YouWon: "Kazandın",
|
||||||
Won: "Kazandı",
|
Won: "Kazandı",
|
||||||
YouLost: "Kaybettin",
|
YouLost: "Kaybettin",
|
||||||
Connecting: "Bağlanılıyor",
|
Connecting: "Bağlanılıyor",
|
||||||
Connected: "Bağlandı",
|
Connected: "Bağlandı",
|
||||||
CannotConnect: "Bağlanılamadı",
|
CannotConnect: "Bağlanılamadı",
|
||||||
ConnectionLost: "Bağlantı Koptu",
|
ConnectionLost: "Ağ Bağlantısı Koptu",
|
||||||
ConnectingAgain: "Tekrar Bağlanılıyor",
|
ConnectingAgain: "Tekrar Bağlanılıyor",
|
||||||
ServerError: "Sunucu Hatası",
|
ServerError: "Sunucu Hatası",
|
||||||
SearchingOpponet: "Rakip Aranıyor",
|
SearchingOpponet: "Rakip Aranıyor",
|
||||||
@ -82,9 +98,17 @@ export const TrTr: Texts = {
|
|||||||
UserLeftTheGame: "Oyundan Ayrıldı",
|
UserLeftTheGame: "Oyundan Ayrıldı",
|
||||||
SearchingOpponent: "Rakip Aranıyor",
|
SearchingOpponent: "Rakip Aranıyor",
|
||||||
PleaseWait: "Lütfen Bekleyin",
|
PleaseWait: "Lütfen Bekleyin",
|
||||||
GameDraw : "Berabere",
|
GameDraw: "Berabere",
|
||||||
Anonymous: "Anonim",
|
Anonymous: "Anonim",
|
||||||
GameNotFound: "Oyun Bulunamadı",
|
GameNotFound: "Oyun Bulunamadı",
|
||||||
Loading: "Yükleniyor",
|
Loading: "Yükleniyor",
|
||||||
Playing: "Oynuyor",
|
Playing: "Oynuyor",
|
||||||
|
Error: "Hata",
|
||||||
|
ErrorWhenRetrievingInformation: "Bilgiler toplanırken bir hata oluştu!",
|
||||||
|
UCanOnlyPlayYourOwnPits: "Sadece sana ait olan kuyular ile oynayabilirsin",
|
||||||
|
UMustWaitUntilCurrentMoveComplete: "Devam eden haraketin bitmesini beklemelisin",
|
||||||
|
UCanNotPlayEmptyPit: "Boş kuyu ile oynayamazsın",
|
||||||
|
AreYouSureToLeaveGame: "Oyundan ayrılmak istediğine emin misin?",
|
||||||
|
Yes: "Evet",
|
||||||
|
Cancel: "İptal"
|
||||||
}
|
}
|
||||||
@ -1 +0,0 @@
|
|||||||
export type ConnectionState = "connecting" | "error" | "connected" | "reconnecting";
|
|
||||||
@ -20,7 +20,6 @@ import UserStatus from '../components/UserStatus';
|
|||||||
import { channel_on_game_update, channel_on_game_crashed, channel_on_game_user_leave, channel_on_user_connection_change, channel_leave_game, channel_game_move, channel_listen_game_events, channel_unlisten_game_events } from '../const/channel_names';
|
import { channel_on_game_update, channel_on_game_crashed, channel_on_game_user_leave, channel_on_user_connection_change, channel_leave_game, channel_game_move, channel_listen_game_events, channel_unlisten_game_events } from '../const/channel_names';
|
||||||
import { Context } from '../context/context';
|
import { Context } from '../context/context';
|
||||||
import useWindowDimensions from '../hooks/useWindowDimensions';
|
import useWindowDimensions from '../hooks/useWindowDimensions';
|
||||||
import { ConnectionState } from '../models/ConnectionState';
|
|
||||||
import { GameMove } from '../models/GameMove';
|
import { GameMove } from '../models/GameMove';
|
||||||
import { LoadingState } from '../models/LoadingState';
|
import { LoadingState } from '../models/LoadingState';
|
||||||
import { Theme } from '../theme/Theme';
|
import { Theme } from '../theme/Theme';
|
||||||
@ -28,13 +27,15 @@ import { getColorByBrightness } from '../util/ColorUtil';
|
|||||||
import BoardViewModel from '../viewmodel/BoardViewModel';
|
import BoardViewModel from '../viewmodel/BoardViewModel';
|
||||||
import Center from '../components/Center';
|
import Center from '../components/Center';
|
||||||
import { Game, GameUsersConnectionInfo } from '../models/Game';
|
import { Game, GameUsersConnectionInfo } from '../models/Game';
|
||||||
|
import notyf from '../util/Notyf';
|
||||||
|
import swal from 'sweetalert';
|
||||||
|
import Util from '../util/Util';
|
||||||
|
|
||||||
const GamePage: FunctionComponent<{
|
const GamePage: FunctionComponent<{
|
||||||
context: Context,
|
context: Context,
|
||||||
userKey?: string,
|
userKey?: string,
|
||||||
theme: Theme,
|
theme: Theme,
|
||||||
connectionState: ConnectionState
|
}> = ({ context, userKey, theme }) => {
|
||||||
}> = ({ context, userKey, theme, connectionState }) => {
|
|
||||||
let params = useParams<{ gameId: string }>();
|
let params = useParams<{ gameId: string }>();
|
||||||
|
|
||||||
const [game, setGame] = useState<Game | undefined>(undefined);
|
const [game, setGame] = useState<Game | undefined>(undefined);
|
||||||
@ -89,6 +90,7 @@ const GamePage: FunctionComponent<{
|
|||||||
}
|
}
|
||||||
const onGameCrashed = (message: any) => {
|
const onGameCrashed = (message: any) => {
|
||||||
const newCrashMessage = message as string;
|
const newCrashMessage = message as string;
|
||||||
|
notyf.error(context.texts.InternalErrorOccurred);
|
||||||
console.error("on_game_crash");
|
console.error("on_game_crash");
|
||||||
console.error(newCrashMessage);
|
console.error(newCrashMessage);
|
||||||
}
|
}
|
||||||
@ -136,10 +138,22 @@ const GamePage: FunctionComponent<{
|
|||||||
const checkHasAnOngoingAction = () => hasOngoingAction;
|
const checkHasAnOngoingAction = () => hasOngoingAction;
|
||||||
|
|
||||||
const onLeaveGameClick = () => {
|
const onLeaveGameClick = () => {
|
||||||
|
if(Util.checkConnectionAndMaybeAlert(context)) return;
|
||||||
|
swal({
|
||||||
|
title: context.texts.AreYouSureToLeaveGame,
|
||||||
|
icon: "warning",
|
||||||
|
buttons: [context.texts.Yes, context.texts.Cancel],
|
||||||
|
dangerMode: true,
|
||||||
|
})
|
||||||
|
.then((cancel) => {
|
||||||
|
if (!cancel) {
|
||||||
context.rtmt.sendMessage(channel_leave_game, {});
|
context.rtmt.sendMessage(channel_leave_game, {});
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onNewGameClick = () => {
|
const onNewGameClick = () => {
|
||||||
|
if(Util.checkConnectionAndMaybeAlert(context)) return;
|
||||||
navigate("/loby")
|
navigate("/loby")
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -147,21 +161,27 @@ const GamePage: FunctionComponent<{
|
|||||||
if (!game || isSpectator || !userKey) {
|
if (!game || isSpectator || !userKey) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (game.mancalaGame.getPlayerIdByIndex(index) !== userKey) {
|
||||||
|
notyf.error(context.texts.UCanOnlyPlayYourOwnPits);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const pitIndexForUser = index % (game.mancalaGame.board.totalPitCount() / 2);
|
const pitIndexForUser = index % (game.mancalaGame.board.totalPitCount() / 2);
|
||||||
if (game.mancalaGame.getPlayerIdByIndex(index) !== userKey ||
|
if (!game.mancalaGame.canPlayerMove(userKey, pitIndexForUser)) {
|
||||||
!game.mancalaGame.canPlayerMove(userKey, pitIndexForUser)) {
|
notyf.error(context.texts.OpponentTurn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (checkHasAnOngoingAction()) {
|
if (checkHasAnOngoingAction()) {
|
||||||
|
notyf.error(context.texts.UMustWaitUntilCurrentMoveComplete);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setHasOngoingAction(true);
|
if(Util.checkConnectionAndMaybeAlert(context)) return;
|
||||||
if (!boardViewModel) return;
|
if (!boardViewModel) return;
|
||||||
//TODO: this check should be in mancala.js
|
//TODO: this check should be in mancala.js
|
||||||
if (pit.stoneCount === 0) {
|
if (pit.stoneCount === 0) {
|
||||||
//TODO : warn user
|
notyf.error(context.texts.UCanNotPlayEmptyPit);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
setHasOngoingAction(true);
|
||||||
boardViewModel.pits[getBoardIndex(pitIndexForUser)].pitColor =
|
boardViewModel.pits[getBoardIndex(pitIndexForUser)].pitColor =
|
||||||
context.themeManager.theme.pitSelectedColor;
|
context.themeManager.theme.pitSelectedColor;
|
||||||
updateBoardViewModel(boardViewModel);
|
updateBoardViewModel(boardViewModel);
|
||||||
@ -210,13 +230,13 @@ const GamePage: FunctionComponent<{
|
|||||||
const bottomLocatedUser = {
|
const bottomLocatedUser = {
|
||||||
id: bottomLocatedUserId,
|
id: bottomLocatedUserId,
|
||||||
name: "Anonymous",
|
name: "Anonymous",
|
||||||
isOnline: isSpectator ? isUserOnline(bottomLocatedUserId) : connectionState === "connected",
|
isOnline: isSpectator ? isUserOnline(bottomLocatedUserId) : context.rtmt.connectionState === "connected",
|
||||||
isAnonymous: true
|
isAnonymous: true
|
||||||
};
|
};
|
||||||
const currentUser = isSpectator ? {
|
const currentUser = isSpectator ? {
|
||||||
id: "2",
|
id: "2",
|
||||||
name: "Anonymous",
|
name: "Anonymous",
|
||||||
isOnline: connectionState === "connected",
|
isOnline: context.rtmt.connectionState === "connected",
|
||||||
isAnonymous: true
|
isAnonymous: true
|
||||||
} : bottomLocatedUser;
|
} : bottomLocatedUser;
|
||||||
const leftPlayer = userKeyWhoLeave ? (userKeyWhoLeave === topLocatedUser.id ? topLocatedUser : bottomLocatedUser) : undefined;
|
const leftPlayer = userKeyWhoLeave ? (userKeyWhoLeave === topLocatedUser.id ? topLocatedUser : bottomLocatedUser) : undefined;
|
||||||
@ -263,7 +283,7 @@ const GamePage: FunctionComponent<{
|
|||||||
|
|
||||||
function renderMobileBoardToolbar() {
|
function renderMobileBoardToolbar() {
|
||||||
return <BoardToolbar style={{ justifyContent: "center" }} visible={showBoardView && isMobile || false}>
|
return <BoardToolbar style={{ justifyContent: "center" }} visible={showBoardView && isMobile || false}>
|
||||||
{buildInfoPanel()}
|
{buildInfoPanel({ visible: isMobile })}
|
||||||
</BoardToolbar>;
|
</BoardToolbar>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +293,7 @@ const GamePage: FunctionComponent<{
|
|||||||
marginBottom: "0.5rem", marginLeft: "6%", maxWidth: isMobile ? "40vw" : "30vw",
|
marginBottom: "0.5rem", marginLeft: "6%", maxWidth: isMobile ? "40vw" : "30vw",
|
||||||
width: isMobile ? "40vw" : "30vw"
|
width: isMobile ? "40vw" : "30vw"
|
||||||
}} context={context} layoutMode="left" user={topLocatedUser} visible={showBoardView || false} />
|
}} context={context} layoutMode="left" user={topLocatedUser} visible={showBoardView || false} />
|
||||||
{buildInfoPanel()}
|
{buildInfoPanel({ visible: !isMobile })}
|
||||||
<UserStatus style={{
|
<UserStatus style={{
|
||||||
marginBottom: "0.5rem", marginRight: "6%", maxWidth: isMobile ? "40vw" : "30vw",
|
marginBottom: "0.5rem", marginRight: "6%", maxWidth: isMobile ? "40vw" : "30vw",
|
||||||
width: isMobile ? "40vw" : "30vw"
|
width: isMobile ? "40vw" : "30vw"
|
||||||
@ -281,7 +301,7 @@ const GamePage: FunctionComponent<{
|
|||||||
</BoardToolbar>;
|
</BoardToolbar>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildInfoPanel() {
|
function buildInfoPanel(params: { visible: boolean }) {
|
||||||
return (
|
return (
|
||||||
<InfoPanel
|
<InfoPanel
|
||||||
style={{ marginTop: "0.5rem", marginBottom: "0.5rem" }}
|
style={{ marginTop: "0.5rem", marginBottom: "0.5rem" }}
|
||||||
@ -291,7 +311,7 @@ const GamePage: FunctionComponent<{
|
|||||||
whitePlayer={topLocatedUser}
|
whitePlayer={topLocatedUser}
|
||||||
blackPlayer={bottomLocatedUser}
|
blackPlayer={bottomLocatedUser}
|
||||||
leftPlayer={leftPlayer}
|
leftPlayer={leftPlayer}
|
||||||
visible={!isMobile}
|
visible={params.visible}
|
||||||
isSpectator={isSpectator} />
|
isSpectator={isSpectator} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import ThemeSwitchMenu from "../components/headerbar/ThemeSwitchMenu";
|
|||||||
import Button from "../components/Button";
|
import Button from "../components/Button";
|
||||||
import { Context } from "../context/context";
|
import { Context } from "../context/context";
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
|
import Util from "../util/Util";
|
||||||
|
|
||||||
const Home: FunctionComponent<{
|
const Home: FunctionComponent<{
|
||||||
context: Context,
|
context: Context,
|
||||||
@ -21,6 +22,7 @@ const Home: FunctionComponent<{
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const onNewGameClick = () => {
|
const onNewGameClick = () => {
|
||||||
|
if(Util.checkConnectionAndMaybeAlert(context)) return;
|
||||||
navigate("/loby")
|
navigate("/loby")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -3,10 +3,12 @@ import EventEmitter2, { Listener } from "eventemitter2"
|
|||||||
export type Bytes = Uint8Array
|
export type Bytes = Uint8Array
|
||||||
export type OnMessage = (message : Object) => any
|
export type OnMessage = (message : Object) => any
|
||||||
|
|
||||||
|
export type ConnectionState = "none" | "connecting" | "error" | "connected" | "closed" | "reconnecting";
|
||||||
|
|
||||||
export type RtmtEventTypes = "open" | "close" | "connected" | "error" | "disconnected" | "message";
|
export type RtmtEventTypes = "open" | "close" | "connected" | "error" | "disconnected" | "message";
|
||||||
|
|
||||||
export interface RTMT extends EventEmitter2 {
|
export interface RTMT extends EventEmitter2 {
|
||||||
|
get connectionState() : ConnectionState;
|
||||||
sendMessage: (channel: string, message: Object) => void;
|
sendMessage: (channel: string, message: Object) => void;
|
||||||
addMessageListener(channel: string, callback: (message: any) => void);
|
addMessageListener(channel: string, callback: (message: any) => void);
|
||||||
removeMessageListener(channel: string, callback: (message: any) => void);
|
removeMessageListener(channel: string, callback: (message: any) => void);
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { decode, encode } from "./encode_decode_message";
|
|||||||
import { channel_ping, channel_pong } from "../const/channel_names";
|
import { channel_ping, channel_pong } from "../const/channel_names";
|
||||||
import { server } from "../const/config";
|
import { server } from "../const/config";
|
||||||
import EventEmitter2, { Listener } from "eventemitter2";
|
import EventEmitter2, { Listener } from "eventemitter2";
|
||||||
import { Bytes, RTMT, RtmtEventTypes } from "./rtmt";
|
import { Bytes, ConnectionState, RTMT, RtmtEventTypes } from "./rtmt";
|
||||||
|
|
||||||
const PING_INTERVAL = 15000, PING_INTERVAL_BUFFER_TIME = 1000;
|
const PING_INTERVAL = 15000, PING_INTERVAL_BUFFER_TIME = 1000;
|
||||||
const MESSAGE_CHANNEL_PREFIX = "message_channel";
|
const MESSAGE_CHANNEL_PREFIX = "message_channel";
|
||||||
@ -10,24 +10,32 @@ const MESSAGE_CHANNEL_PREFIX = "message_channel";
|
|||||||
export class RTMTWS extends EventEmitter2 implements RTMT {
|
export class RTMTWS extends EventEmitter2 implements RTMT {
|
||||||
private webSocket: WebSocket;
|
private webSocket: WebSocket;
|
||||||
private pingTimeout?: number = undefined;
|
private pingTimeout?: number = undefined;
|
||||||
|
private _connectionState: ConnectionState = "none";
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get connectionState(): ConnectionState {
|
||||||
|
return this._connectionState;
|
||||||
|
}
|
||||||
|
|
||||||
public initWebSocket(userKey: string) {
|
public initWebSocket(userKey: string) {
|
||||||
|
this._connectionState = this._connectionState !== "none" ? "reconnecting" : "connecting";
|
||||||
const url = server.wsServerAdress + "?userKey=" + userKey;
|
const url = server.wsServerAdress + "?userKey=" + userKey;
|
||||||
const webSocket = new WebSocket(url);
|
const webSocket = new WebSocket(url);
|
||||||
webSocket.onopen = () => {
|
webSocket.onopen = () => {
|
||||||
console.info("(RTMT) WebSocket has opened");
|
console.info("(RTMT) WebSocket has opened");
|
||||||
this.webSocket = webSocket;
|
this.webSocket = webSocket;
|
||||||
this.heartbeat();
|
this.heartbeat();
|
||||||
|
this._connectionState = "connected";
|
||||||
this.emit("open");
|
this.emit("open");
|
||||||
};
|
};
|
||||||
webSocket.onclose = () => {
|
webSocket.onclose = () => {
|
||||||
console.info("(RTMT) WebSocket has closed");
|
console.info("(RTMT) WebSocket has closed");
|
||||||
//this.WebSocket = undefined
|
//this.WebSocket = undefined
|
||||||
clearTimeout(this.pingTimeout);
|
clearTimeout(this.pingTimeout);
|
||||||
|
this._connectionState = "closed";
|
||||||
this.emit("close");
|
this.emit("close");
|
||||||
};
|
};
|
||||||
webSocket.onmessage = (event: MessageEvent) => {
|
webSocket.onmessage = (event: MessageEvent) => {
|
||||||
@ -36,6 +44,7 @@ export class RTMTWS extends EventEmitter2 implements RTMT {
|
|||||||
};
|
};
|
||||||
webSocket.onerror = (error) => {
|
webSocket.onerror = (error) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
this._connectionState = "error";
|
||||||
this.emit("error", error);
|
this.emit("error", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ const colorSpecial = "#337a44";
|
|||||||
const darkTheme: Theme = {
|
const darkTheme: Theme = {
|
||||||
id: "2",
|
id: "2",
|
||||||
name: "Dark Theme",
|
name: "Dark Theme",
|
||||||
|
themePreviewColor: colors.primary,
|
||||||
background: colors.primary,
|
background: colors.primary,
|
||||||
appBarBgColor: colors.secondary,
|
appBarBgColor: colors.secondary,
|
||||||
textColor: colors.primary,
|
textColor: colors.primary,
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { Theme } from "./Theme";
|
|||||||
const greyTheme: Theme = {
|
const greyTheme: Theme = {
|
||||||
id: "1",
|
id: "1",
|
||||||
name: "Grey Theme",
|
name: "Grey Theme",
|
||||||
|
themePreviewColor: "#4D606E",
|
||||||
background: "#EEEEEE",
|
background: "#EEEEEE",
|
||||||
appBarBgColor: "#e4e4e4",
|
appBarBgColor: "#e4e4e4",
|
||||||
textColor: "#4D606E",
|
textColor: "#4D606E",
|
||||||
|
|||||||
@ -5,6 +5,7 @@ const colorSpecial = "#8B8B8B";
|
|||||||
const lightTheme: Theme = {
|
const lightTheme: Theme = {
|
||||||
id: "1",
|
id: "1",
|
||||||
name: "Light Theme",
|
name: "Light Theme",
|
||||||
|
themePreviewColor: "#9B9B9B",
|
||||||
background: "#BBBBBB",
|
background: "#BBBBBB",
|
||||||
appBarBgColor: "#7B7B7B",
|
appBarBgColor: "#7B7B7B",
|
||||||
textColor: "#5B5B5B",
|
textColor: "#5B5B5B",
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
export type Theme = {
|
export type Theme = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
themePreviewColor: string; // for theme switch menu
|
||||||
textColor: string;
|
textColor: string;
|
||||||
textLightColor: string;
|
textLightColor: string;
|
||||||
background: string;
|
background: string;
|
||||||
|
|||||||
4
src/util/Notyf.ts
Normal file
4
src/util/Notyf.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { Notyf } from 'notyf';
|
||||||
|
import 'notyf/notyf.min.css';
|
||||||
|
const notyf = new Notyf();
|
||||||
|
export default notyf;
|
||||||
@ -1,10 +1,20 @@
|
|||||||
|
import { Context } from "../context/context";
|
||||||
|
import notyf from "./Notyf";
|
||||||
|
|
||||||
export default class Util {
|
export default class Util {
|
||||||
public static range(size: number) {
|
public static range(size: number) {
|
||||||
var ans : number[] = [];
|
var ans: number[] = [];
|
||||||
for (let i = 0; i < size; i++) {
|
for (let i = 0; i < size; i++) {
|
||||||
ans.push(i);
|
ans.push(i);
|
||||||
}
|
}
|
||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static checkConnectionAndMaybeAlert(context: Context): boolean {
|
||||||
|
if (context.rtmt.connectionState !== "connected") {
|
||||||
|
notyf.error(context.texts.ConnectionLost);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
31
yarn.lock
31
yarn.lock
@ -1067,10 +1067,10 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib "^2.4.0"
|
tslib "^2.4.0"
|
||||||
|
|
||||||
"@szhsin/react-menu@^3.0.2":
|
"@szhsin/react-menu@^3.1.2":
|
||||||
version "3.0.2"
|
version "3.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/@szhsin/react-menu/-/react-menu-3.0.2.tgz#d22971c53d56e6d404c9d3c98f533907cd8f03dc"
|
resolved "https://registry.yarnpkg.com/@szhsin/react-menu/-/react-menu-3.1.2.tgz#3a791e7e6c672d113c298985bec5185e9c7aa8a7"
|
||||||
integrity sha512-m9Ly+cT+CxQx3xhq90CVaOLQWU7f7UKeMxfDt1gPYV23tDwEe8Zo6PO547qPlAEGEwwb9MdA38U8OyueXKJc2g==
|
integrity sha512-NUnU429a3jXtRD4xxk8EsR4yRSuhZPWAkI+4P4K63LQPUZGVE7adVKtEmlyOpd8CRQ7aoUz1ZLr1VmR1nZi6GQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
prop-types "^15.7.2"
|
prop-types "^15.7.2"
|
||||||
react-transition-state "^1.1.4"
|
react-transition-state "^1.1.4"
|
||||||
@ -1418,6 +1418,11 @@ error-ex@^1.3.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-arrayish "^0.2.1"
|
is-arrayish "^0.2.1"
|
||||||
|
|
||||||
|
es6-object-assign@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c"
|
||||||
|
integrity sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==
|
||||||
|
|
||||||
escalade@^3.1.1:
|
escalade@^3.1.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz"
|
resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz"
|
||||||
@ -1630,6 +1635,11 @@ node-releases@^2.0.6:
|
|||||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503"
|
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503"
|
||||||
integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==
|
integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==
|
||||||
|
|
||||||
|
notyf@^3.10.0:
|
||||||
|
version "3.10.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/notyf/-/notyf-3.10.0.tgz#67a64443c69ea0e6495c56ea0f91198860163d06"
|
||||||
|
integrity sha512-Mtnp+0qiZxgrH+TzVlzhWyZceHdAZ/UWK0/ju9U0HQeDpap1mZ8cC7H5wSI5mwgni6yeAjaxsTw0sbMK+aSuHw==
|
||||||
|
|
||||||
nth-check@^2.0.1:
|
nth-check@^2.0.1:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
|
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
|
||||||
@ -1738,6 +1748,11 @@ process@^0.11.10:
|
|||||||
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||||
integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
|
integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
|
||||||
|
|
||||||
|
promise-polyfill@^6.0.2:
|
||||||
|
version "6.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-6.1.0.tgz#dfa96943ea9c121fca4de9b5868cb39d3472e057"
|
||||||
|
integrity sha512-g0LWaH0gFsxovsU7R5LrrhHhWAWiHRnh1GPrhXnPgYsDkIqjRYUYSZEsej/wtleDrz5xVSIDbeKfidztp2XHFQ==
|
||||||
|
|
||||||
prop-types@^15.7.2:
|
prop-types@^15.7.2:
|
||||||
version "15.8.1"
|
version "15.8.1"
|
||||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
|
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
|
||||||
@ -1884,6 +1899,14 @@ svgo@^2.4.0, svgo@^2.5.0:
|
|||||||
picocolors "^1.0.0"
|
picocolors "^1.0.0"
|
||||||
stable "^0.1.8"
|
stable "^0.1.8"
|
||||||
|
|
||||||
|
sweetalert@^2.1.2:
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/sweetalert/-/sweetalert-2.1.2.tgz#010baaa80d0dbdc86f96bfcaa96b490728594b79"
|
||||||
|
integrity sha512-iWx7X4anRBNDa/a+AdTmvAzQtkN1+s4j/JJRWlHpYE8Qimkohs8/XnFcWeYHH2lMA8LRCa5tj2d244If3S/hzA==
|
||||||
|
dependencies:
|
||||||
|
es6-object-assign "^1.1.0"
|
||||||
|
promise-polyfill "^6.0.2"
|
||||||
|
|
||||||
term-size@^2.2.1:
|
term-size@^2.2.1:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54"
|
resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user