Commit 6d3d6113 authored by Chunchi Che's avatar Chunchi Che

update styles

parent 8cd7aa95
Pipeline #23645 passed with stages
in 14 minutes and 57 seconds
.container {
display: flex;
flex-direction: column;
font: var(--theme-font);
font-size: 1rem;
.search {
margin-bottom: 1rem;
.input {
border: 1px solid #afbdd2;
background: transparent;
}
}
.item {
display: flex;
padding: 1rem 0;
.avatar {
flex: 1;
margin-left: 1rem;
}
.title {
flex: 2;
}
.mode {
flex: 1;
display: flex;
justify-content: center;
color: #5f6b7c;
}
}
.item:hover {
border: 2px solid #1059c6;
border-radius: 0.5rem;
cursor: pointer;
}
.item-selected {
border: 2px solid #1059c6;
border-radius: 0.5rem;
box-shadow: 0 0 0 2px #0087e6 inset;
}
.divider {
margin: 0;
}
}
import { App, Avatar, List } from "antd"; import { SearchOutlined } from "@ant-design/icons";
import { App, Avatar, Button, Divider, Empty, Input } from "antd";
import classNames from "classnames";
import React, { useState } from "react"; import React, { useState } from "react";
import useWebSocket, { ReadyState } from "react-use-websocket"; import useWebSocket, { ReadyState } from "react-use-websocket";
import { proxy, useSnapshot } from "valtio";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { ScrollableArea } from "../Shared";
import styles from "./WatchContent.module.scss";
const { athleticWatchUrl, avatarApi } = useConfig(); const { athleticWatchUrl, avatarApi } = useConfig();
interface Info { interface Info {
...@@ -33,11 +39,14 @@ interface Options { ...@@ -33,11 +39,14 @@ interface Options {
auto_death: boolean; auto_death: boolean;
} }
export const WatchContent: React.FC<{ export const watchStore = proxy<{ watchID: string | undefined }>({
setWatchID: React.Dispatch<React.SetStateAction<string | undefined>>; watchID: undefined,
}> = ({ setWatchID }) => { });
export const WatchContent: React.FC = () => {
const [rooms, setRooms] = useState<Room[]>([]); const [rooms, setRooms] = useState<Room[]>([]);
const { message } = App.useApp(); const { message } = App.useApp();
const { watchID } = useSnapshot(watchStore);
// 暂时只支持竞技匹配的观战,TODO:后面需要加上娱乐匹配的支持 // 暂时只支持竞技匹配的观战,TODO:后面需要加上娱乐匹配的支持
const url = new URL(athleticWatchUrl); const url = new URL(athleticWatchUrl);
url.searchParams.set("filter", "started"); url.searchParams.set("filter", "started");
...@@ -90,33 +99,52 @@ export const WatchContent: React.FC<{ ...@@ -90,33 +99,52 @@ export const WatchContent: React.FC<{
}); });
return ( return (
<List <div className={styles.container}>
itemLayout="vertical" <div className={styles.search}>
loading={readyState === ReadyState.CONNECTING} <Input
size="small" className={styles.input}
pagination={{ placeholder="搜索房间"
position: "bottom", bordered={false}
align: "center", suffix={<Button type="text" icon={<SearchOutlined />} />}
pageSize: 5, />
simple: true, </div>
}} <ScrollableArea maxHeight="50vh">
dataSource={rooms} {readyState === ReadyState.CONNECTING || rooms.length === 0 ? (
renderItem={(room) => ( <Empty />
<List.Item key={room.id} onClick={() => setWatchID(room.id)}> ) : (
<List.Item.Meta rooms.map((room) => (
avatar={ <div key={room.id}>
<Avatar <div
src={avatarApi.replace( className={classNames(styles.item, {
"{username}", [styles["item-selected"]]: watchID && watchID === room.id,
room.users?.at(0)?.username ?? "?", })}
)} onClick={() => (watchStore.watchID = room.id)}
/> >
} <div className={styles.avatar}>
title={`${room.users?.at(0)?.username} 与 ${room.users?.at(1) <Avatar
?.username} 的决斗`} src={avatarApi.replace(
/> "{username}",
</List.Item> room.users?.at(0)?.username ?? "?",
)} )}
/> />
<Avatar
src={avatarApi.replace(
"{username}",
room.users?.at(1)?.username ?? "?",
)}
/>
</div>
<div className={styles.title}>
{`${room.users?.at(0)?.username} 与 ${room.users?.at(1)
?.username} 的决斗`}
</div>
<div className={styles.mode}>竞技匹配</div>
</div>
<Divider className={styles.divider} />
</div>
))
)}
</ScrollableArea>
</div>
); );
}; };
...@@ -18,7 +18,7 @@ import styles from "./index.module.scss"; ...@@ -18,7 +18,7 @@ import styles from "./index.module.scss";
import { MatchModal, matchStore } from "./MatchModal"; import { MatchModal, matchStore } from "./MatchModal";
import { ReplayModal, replayOpen } from "./ReplayModal"; import { ReplayModal, replayOpen } from "./ReplayModal";
import { connectSrvpro, getEncryptedPasswd } from "./util"; import { connectSrvpro, getEncryptedPasswd } from "./util";
import { WatchContent } from "./WatchContent"; import { WatchContent, watchStore } from "./WatchContent";
const { servers: serverList } = useConfig(); const { servers: serverList } = useConfig();
...@@ -38,9 +38,11 @@ export const Component: React.FC = () => { ...@@ -38,9 +38,11 @@ export const Component: React.FC = () => {
const [singleLoading, setSingleLoading] = useState(false); // 单人模式的loading状态 const [singleLoading, setSingleLoading] = useState(false); // 单人模式的loading状态
const [matchLoading, setMatchLoading] = useState(false); // 匹配模式的loading状态 const [matchLoading, setMatchLoading] = useState(false); // 匹配模式的loading状态
const [watchLoading, setWatchLoading] = useState(false); // 观战模式的loading状态 const [watchLoading, setWatchLoading] = useState(false); // 观战模式的loading状态
const [watchID, setWatchID] = useState<string | undefined>(undefined);
const navigate = useNavigate(); const navigate = useNavigate();
// FIXME: 这里有bug,第一次选择房间的时候获取不到watchID
const { watchID } = useSnapshot(watchStore);
// 竞技匹配 // 竞技匹配
const onCompetitiveMatch = () => message.error("暂未开放,敬请期待"); const onCompetitiveMatch = () => message.error("暂未开放,敬请期待");
...@@ -71,6 +73,7 @@ export const Component: React.FC = () => { ...@@ -71,6 +73,7 @@ export const Component: React.FC = () => {
} else { } else {
modal.info({ modal.info({
icon: null, icon: null,
width: "40vw",
okText: "进入观战", okText: "进入观战",
onOk: async () => { onOk: async () => {
if (watchID) { if (watchID) {
...@@ -98,7 +101,7 @@ export const Component: React.FC = () => { ...@@ -98,7 +101,7 @@ export const Component: React.FC = () => {
}, },
centered: true, centered: true,
maskClosable: true, maskClosable: true,
content: <WatchContent setWatchID={setWatchID} />, content: <WatchContent />,
}); });
} }
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment