123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- import React from "react";
- import styled from "styled-components";
- import { useTranslation } from "react-i18next";
- import { useHistory, useRouteMatch } from "react-router-dom";
- import { confirmAlert } from "react-confirm-alert";
- import { useWire, useBoardConfig } from "react-sync-board";
- import UserList from "../../users/UserList";
- import Touch from "../../ui/Touch";
- import WebConferenceButton from "../../webconf/WebConferenceButton";
- import { getBestTranslationFromConfig } from "../../utils/api";
- import useLocalStorage from "../../hooks/useLocalStorage";
- import InfoModal from "./InfoModal";
- import LoadGameModal from "./LoadGameModal";
- import LoadSessionModal from "./LoadSessionModal";
- import ChangeGameModal from "./ChangeGameModal";
- import ExportModal from "./ExportModal";
- import SaveExportModal from "./SaveExportModal";
- import WelcomeModal from "./WelcomeModal";
- import useSession from "../../hooks/useSession";
- const StyledNavBar = styled.div.attrs(() => ({ className: "nav" }))`
- position: fixed;
- top: 0;
- width: 100%;
- z-index: 205;
- background-color: #19202ce0;
- box-shadow: 0px 3px 6px #00000029;
- color: var(--font-color);
- & .nav-center {
- display: relative;
- & h3 {
- position: absolute;
- top: 0;
- margin: 0;
- padding: 0 2em;
- background-color: ${({ edit }) =>
- edit ? "var(--color-primary)" : "var(--color-blueGrey)"};
- box-shadow: 0px 3px 6px #00000029;
- line-height: 80px;
- letter-spacing: 0px;
- font-size: 24px;
- text-transform: uppercase;
- transform: perspective(280px) rotateX(-20deg);
- }
- }
- & .nav-right,
- & .nav-center,
- & .nav-left {
- align-items: center;
- }
- & .nav-left {
- & > div {
- padding-right: 1em;
- }
- padding-left: 40px;
- justify-content: flex-start;
- }
- & .nav-right {
- justify-content: flex-end;
- padding-right: 1em;
- gap: 1em;
- }
- & .spacer {
- flex: 1;
- max-width: 1em;
- }
- @media screen and (max-width: 640px) {
- & .nav-left {
- flex: 1;
- padding-left: 5px;
- & > div {
- padding-right: 2px;
- }
- }
- & .nav-center h3 {
- position: relative;
- padding: 0;
- background-color: transparent;
- box-shadow: none;
- line-height: 1.2em;
- font-size: 1.2em;
- transform: none;
- }
- & .nav-right {
- display: none;
- }
- & .spacer {
- flex: 0;
- }
- & {
- flex-direction: row;
- }
- & .save {
- display: none;
- }
- & .info {
- margin: 0;
- padding: 0;
- width: 24px;
- height: 24px;
- }
- & .help {
- margin: 0;
- padding: 0;
- width: 24px;
- height: 24px;
- }
- & h3 {
- font-size: 1.2em;
- }
- }
- `;
- const NavBar = ({ editMode, title }) => {
- const { t, i18n } = useTranslation();
- const { sessionId: room } = useSession();
- const [boardConfig] = useBoardConfig();
- const { isMaster } = useWire("board");
- const history = useHistory();
- const match = useRouteMatch();
- const [showLoadGameModal, setShowLoadGameModal] = React.useState(false);
- const [showSaveGameModal, setShowSaveGameModal] = React.useState(false);
- const [showChangeGameModal, setShowChangeGameModal] = React.useState(false);
- const [showInfoModal, setShowInfoModal] = React.useState(false);
- const [showLink, setShowLink] = React.useState(false);
- const translation = React.useMemo(
- () => getBestTranslationFromConfig(boardConfig, i18n.languages),
- [boardConfig, i18n.languages]
- );
- const handleBack = React.useCallback(() => {
- // If inside session
- if (match.path === "/session/:sessionId" && history.length > 2) {
- // Go to previous if exists
- // Previous can be home or studio
- // Yes history should be greater than 2 for any reason...
- history.goBack();
- return;
- }
- // If inside room, go back to that room
- if (match.path === "/room/:roomId/session/:sessionId") {
- history.push(`/room/${match.params.roomId}`);
- return;
- }
- // Otherwise, go back to home
- history.push("/games");
- }, [history, match.params.roomId, match.path]);
- const handleBackWithConfirm = React.useCallback(() => {
- confirmAlert({
- title: t("Confirmation"),
- message: t("Do you really want to quit game edition?"),
- buttons: [
- {
- label: t("Yes"),
- onClick: async () => {
- history.push("/studio");
- },
- },
- {
- label: t("No"),
- onClick: () => {},
- },
- ],
- });
- }, [history, t]);
- return (
- <>
- <StyledNavBar edit={editMode}>
- <div className="nav-left">
- {!editMode && (
- <>
- <Touch
- onClick={handleBack}
- alt={t("Go back")}
- title={t("Go back")}
- icon={"chevron-left"}
- style={{ display: "inline" }}
- />
- {isMaster && (
- <>
- <Touch
- onClick={() => setShowChangeGameModal((prev) => !prev)}
- alt={t("Change game")}
- title={t("Change game")}
- icon="https://icongr.am/material/cards-playing-outline.svg?size=24&color=f9fbfa"
- />
- <ChangeGameModal
- show={showChangeGameModal}
- setShow={setShowChangeGameModal}
- />
- </>
- )}
- </>
- )}
- {editMode && (
- <Touch
- onClick={handleBackWithConfirm}
- alt={t("Go back to studio")}
- title={t("Go back to studio")}
- icon={"chevron-left"}
- style={{ display: "inline" }}
- />
- )}
- </div>
- <div className="nav-center">
- <h3>
- {translation.name ? translation.name : title || "Air Board Game"}
- </h3>
- </div>
- <div className="nav-right">
- {!editMode && (
- <>
- <UserList />
- <Touch
- onClick={() => {
- setShowLink(true);
- }}
- icon="add-user"
- title={t("Invite more player")}
- />
- <WebConferenceButton room={room} />
- </>
- )}
- <div className="spacer" />
- {(isMaster || editMode) && (
- <Touch
- onClick={() => setShowLoadGameModal((prev) => !prev)}
- alt={editMode ? t("Load game") : t("Load session")}
- title={editMode ? t("Load game") : t("Load session")}
- icon={"upload-to-cloud"}
- />
- )}
- <Touch
- onClick={() => setShowSaveGameModal((prev) => !prev)}
- alt={t("Save")}
- title={editMode ? t("Save game") : t("Save session")}
- icon={editMode ? "save" : "download"}
- />
- <div className="spacer" />
- <Touch
- onClick={() => setShowInfoModal((prev) => !prev)}
- alt={t("Help & info")}
- title={t("Help & info")}
- icon={"info"}
- />
- </div>
- </StyledNavBar>
- <InfoModal show={showInfoModal} setShow={setShowInfoModal} />
- {!editMode && (
- <WelcomeModal show={showLink} setShow={setShowLink} welcome={false} />
- )}
- {!editMode && (
- <LoadSessionModal
- show={showLoadGameModal}
- setShow={setShowLoadGameModal}
- edit={editMode}
- />
- )}
- {editMode && (
- <LoadGameModal
- show={showLoadGameModal}
- setShow={setShowLoadGameModal}
- edit={editMode}
- />
- )}
- {!editMode && (
- <ExportModal show={showSaveGameModal} setShow={setShowSaveGameModal} />
- )}
- {editMode && (
- <SaveExportModal
- show={showSaveGameModal}
- setShow={setShowSaveGameModal}
- />
- )}
- </>
- );
- };
- export default NavBar;
|