Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: website style #412

Merged
merged 1 commit into from
Oct 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions components/rooms/GameWindow.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
type GameWindowProps = {
className?: string;
gameUrl: string;
};

export default function GameWindow({ gameUrl }: GameWindowProps) {
export default function GameWindow({ className, gameUrl }: GameWindowProps) {
return (
<div>
<iframe
className="absolute inset-0 m-auto w-[95%] h-[95vh] border"
src={gameUrl}
>
<iframe className={className} src={gameUrl}>
<p>Your browser does not support iframes.</p>
</iframe>
</div>
Expand Down
4 changes: 3 additions & 1 deletion components/shared/Chat/v2/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export type ChatProps = {
friendList: FriendType[];
roomMessages: MessageType[];
className?: string;
defaultTarget?: ChatTab["id"];
onSubmit: (message: Pick<MessageType, "content" | "target">) => void;
};

Expand All @@ -25,11 +26,12 @@ export default function Chat({
friendList,
roomMessages,
className,
defaultTarget,
onSubmit,
}: Readonly<ChatProps>) {
const [messages, setMessages] = useState(lobbyMessages);
const [target, setTarget] = useState<[ChatTab["id"], string | null]>([
"lobby",
defaultTarget || "lobby",
null,
]);
const [activeTab, friendRoom] = target;
Expand Down
27 changes: 20 additions & 7 deletions containers/layout/AppLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,51 @@
import { PropsWithChildren } from "react";
import { PropsWithChildren, useEffect } from "react";
import { useRouter } from "next/router";
import Header from "@/components/shared/Header";
import Sidebar from "@/components/shared/Sidebar";
import Chat from "@/components/shared/Chat/v2/Chat";
import useChat from "@/hooks/useChat";

export default function Layout({ children }: PropsWithChildren) {
const router = useRouter();
const {
roomId,
messageList,
isChatVisible,
openChat,
toggleChatVisibility,
handleSubmitText,
} = useChat();
const roomPathname = "/rooms/[roomId]";

useEffect(() => {
if (router.pathname === roomPathname) {
openChat();
}
}, [router.pathname, openChat]);

return (
<>
<Header
className="sticky top-0 z-40"
className="fixed top-0 inset-x-0 z-40"
onClickChatButton={toggleChatVisibility}
/>
<div className="ml-2 mr-4 my-6 flex grow">
<div className="shrink-0">
<Sidebar className="sticky top-20 z-30 h-main-height" />
<div className="pl-2 pt-20 flex grow">
<div className="shrink-0 w-18">
<Sidebar className="fixed top-20 bottom-6 z-30" />
</div>
<main className="grow overflow-x-hidden">{children}</main>
{isChatVisible && (
<div className="shrink-0">
<div className="shrink-0 w-80 mr-4">
<Chat
className="sticky top-20 z-30 h-main-height"
className="fixed top-20 bottom-6 z-30"
userId=""
roomId={roomId}
friendList={[]}
lobbyMessages={[]}
roomMessages={messageList}
defaultTarget={
router.pathname === roomPathname ? "room" : "lobby"
}
onSubmit={handleSubmitText}
/>
</div>
Expand Down
7 changes: 6 additions & 1 deletion hooks/useChat.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import type { MessageType } from "@/components/shared/Chat/v2/ChatMessages";
import useChatroom from "./context/useChatroom";
import useSocketCore from "./context/useSocketCore";
Expand All @@ -17,6 +17,10 @@ export default function useChat() {
setIsChatVisible((prev) => !prev);
};

const openChat = useCallback(() => {
setIsChatVisible(true);
}, []);

// join chatroom by roomId
useEffect(() => {
if (!roomId) return;
Expand Down Expand Up @@ -48,6 +52,7 @@ export default function useChat() {
roomId,
messageList,
isChatVisible,
openChat,
sendChatMessage,
toggleChatVisibility,
handleSubmitText,
Expand Down
17 changes: 10 additions & 7 deletions hooks/useUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,16 @@ const useUser = () => {
return roomIdOperator.get();
};

const updateRoomId = (roomId?: string) => {
if (roomId) {
roomIdOperator.set(roomId);
} else {
roomIdOperator.remove();
}
};
const updateRoomId = useCallback(
(roomId?: string) => {
if (roomId) {
roomIdOperator.set(roomId);
} else {
roomIdOperator.remove();
}
},
[roomIdOperator]
);

return {
getLoginEndpoint,
Expand Down
2 changes: 1 addition & 1 deletion pages/_document.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default function Document() {
<meta name="og:title" content={siteTitle} />
<meta name="twitter:card" content="summary_large_image" />
</Head>
<body className="body-bg text-primary-200">
<body className="body-bg min-h-screen text-primary-200">
<Main />
<NextScript />
</body>
Expand Down
2 changes: 1 addition & 1 deletion pages/auth/token/[token].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const Token: NextPageWithProps = () => {
}
}, [token, login, push]);

return <h1>{token}</h1>;
return <></>;
};

Token.getLayout = (page: ReactElement) => page;
Expand Down
8 changes: 4 additions & 4 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ function CarouselCard({
draggable={false}
priority
fill
objectFit="cover"
className="object-cover"
onError={onImageError}
/>
<div className="m-4 flex gap-4">
Expand Down Expand Up @@ -106,7 +106,7 @@ function CarouselCard({
draggable={false}
priority
fill
objectFit="cover"
className="object-cover"
onError={onImageError}
/>
)}
Expand Down Expand Up @@ -181,12 +181,12 @@ const TabPaneContent = ({
>
<picture className="relative aspect-game-cover overflow-hidden">
<Image
src={game.img}
src={game.img || gameDefaultCoverImg.src}
alt={game.name}
draggable={false}
priority
fill
objectFit="cover"
className="object-cover"
onError={onImageError}
/>
</picture>
Expand Down
107 changes: 71 additions & 36 deletions pages/rooms/[roomId]/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import { ReactEventHandler, useEffect, useState } from "react";
import { GetStaticProps, GetStaticPaths } from "next";
import { useRouter } from "next/router";
import Image from "next/image";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import RoomUserCardList from "@/components/rooms/RoomUserCardList";
import RoomButtonGroup from "@/components/rooms/RoomButtonGroup";
Expand All @@ -22,10 +23,18 @@ import {
playerCancelReady,
startGame,
} from "@/requests/rooms";
import { GameType, getAllGamesEndpoint } from "@/requests/games";
import useUser from "@/hooks/useUser";
import gameDefaultCoverImg from "@/public/images/game-default-cover.png";

type User = Omit<RoomInfo.User, "isReady">;

const onImageError: ReactEventHandler<HTMLImageElement> = (e) => {
if (e.target instanceof HTMLImageElement) {
e.target.src = gameDefaultCoverImg.src;
}
};

export default function Room() {
const {
roomInfo,
Expand All @@ -44,16 +53,27 @@ export default function Room() {
const { fetch } = useRequest();
const { query, replace } = useRouter();
const [gameUrl, setGameUrl] = useState("");
const [gameList, setGameList] = useState<GameType[]>([]);
const roomId = query.roomId as string;
const player = roomInfo.players.find(
(player) => player.id === currentUser?.id
);
const isHost = roomInfo.host.id === currentUser?.id;
const gameInfo = gameList.find((game) => game.id === roomInfo.game.id);

useEffect(() => {
fetch(getAllGamesEndpoint()).then(setGameList);
}, [fetch]);

useEffect(() => {
async function getRoomInfo() {
const roomInfo = await fetch(getRoomInfoEndpoint(roomId));
initializeRoom(roomInfo);
try {
const roomInfo = await fetch(getRoomInfoEndpoint(roomId));
initializeRoom(roomInfo);
} catch (err) {
updateRoomId();
replace("/rooms");
}
}

getRoomInfo();
Expand Down Expand Up @@ -119,6 +139,7 @@ export default function Room() {
socket,
currentUser?.id,
roomId,
updateRoomId,
addPlayer,
removePlayer,
updateUserReadyStatus,
Expand Down Expand Up @@ -211,40 +232,54 @@ export default function Room() {
};

return (
<section className="px-6">
<div className="relative w-full h-[280px] overflow-hidden">
<img
className="absolute inset-0 w-full h-full object-cover"
src="https://images.unsplash.com/photo-1601987177651-8edfe6c20009?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80"
alt="cover"
<section className="px-4">
{gameUrl ? (
<GameWindow
className="h-[calc(100dvh-104px)] w-full"
gameUrl={gameUrl}
/>
<div className="absolute top-0 left-0 right-0 bottom-0 bg-gradient-to-t from-[#0f0919] to-50% to-[#170D2500]"></div>
<div className="m-2 py-1 px-2 w-fit bg-gray-950/50 backdrop-blur-sm rounded-lg text-sm">
<RoomBreadcrumb roomInfo={roomInfo} />
</div>
<div className="m-2 py-1 px-2 w-fit bg-gray-950/50 backdrop-blur-sm rounded-lg text-sm">
{roomInfo.isLocked ? "非公開" : "公開"}
</div>
<div className="m-2 py-1 px-2 w-fit bg-gray-950/50 backdrop-blur-sm rounded-lg text-sm">
{roomInfo.currentPlayers} / {roomInfo.maxPlayers} 人
</div>
<div className="absolute bottom-0 right-0 flex items-center">
<RoomButtonGroup
onToggleReady={handleToggleReady}
onClickClose={handleClickClose}
onClickLeave={handleLeave}
onClickStart={handleStart}
isHost={isHost}
isReady={isHost || !!player?.isReady}
) : (
<>
<div className="relative w-full h-[280px] overflow-hidden">
{roomInfo.currentPlayers && (
<Image
src={gameInfo?.img || gameDefaultCoverImg.src}
alt={gameInfo?.name || "default game cover"}
draggable={false}
priority
fill
className="object-cover"
onError={onImageError}
/>
)}
<div className="absolute top-0 left-0 right-0 bottom-0 bg-gradient-to-t from-[#0f0919] to-50% to-[#170D2500]"></div>
<div className="m-2 py-1 px-2 w-fit bg-gray-950/50 backdrop-blur-sm rounded-lg text-sm">
<RoomBreadcrumb roomInfo={roomInfo} />
</div>
<div className="m-2 py-1 px-2 w-fit bg-gray-950/50 backdrop-blur-sm rounded-lg text-sm">
{roomInfo.isLocked ? "非公開" : "公開"}
</div>
<div className="m-2 py-1 px-2 w-fit bg-gray-950/50 backdrop-blur-sm rounded-lg text-sm">
{roomInfo.currentPlayers} / {roomInfo.maxPlayers} 人
</div>
<div className="absolute bottom-0 right-0 flex items-center">
<RoomButtonGroup
onToggleReady={handleToggleReady}
onClickClose={handleClickClose}
onClickLeave={handleLeave}
onClickStart={handleStart}
isHost={isHost}
isReady={isHost || !!player?.isReady}
/>
</div>
</div>
<RoomUserCardList
roomInfo={roomInfo}
currentUserId={currentUser?.id}
onKickUser={handleClickKick}
/>
</div>
</div>
<RoomUserCardList
roomInfo={roomInfo}
currentUserId={currentUser?.id}
onKickUser={handleClickKick}
/>
{gameUrl && <GameWindow gameUrl={gameUrl} />}
</>
)}
<Popup />
</section>
);
Expand Down
4 changes: 4 additions & 0 deletions styles/global.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

html {
color-scheme: dark;
}
Loading