mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-11 03:24:16 +00:00
added SyncRoomCard
component
This commit is contained in:
parent
9e4c8a8607
commit
53200388d6
200
packages/app/src/components/SyncRoomCard/index.jsx
Normal file
200
packages/app/src/components/SyncRoomCard/index.jsx
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
import React from "react"
|
||||||
|
import { Button, Tooltip, Badge } from "antd"
|
||||||
|
import { Icons } from "components/Icons"
|
||||||
|
import LiveChat from "components/LiveChat"
|
||||||
|
import classnames from "classnames"
|
||||||
|
|
||||||
|
import "./index.less"
|
||||||
|
|
||||||
|
export default class SyncRoomCard extends React.Component {
|
||||||
|
state = {
|
||||||
|
roomData: {},
|
||||||
|
socketLatency: null,
|
||||||
|
owner: false,
|
||||||
|
chatVisible: false,
|
||||||
|
notReadedMessages: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
latencyInterval = null
|
||||||
|
|
||||||
|
roomEvents = {
|
||||||
|
"room:joined": (data) => {
|
||||||
|
this.setState({
|
||||||
|
roomData: data,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
"room:current-data": (data) => {
|
||||||
|
console.log(data)
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
roomData: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chatEvents = {
|
||||||
|
"room:recive:message": (data) => {
|
||||||
|
if (!this.state.chatVisible) {
|
||||||
|
this.setState({
|
||||||
|
notReadedMessages: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkLatency = () => {
|
||||||
|
const instance = app.cores.api.instance().wsInstances.music
|
||||||
|
|
||||||
|
if (instance) {
|
||||||
|
this.setState({
|
||||||
|
socketLatency: instance.latency
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount = () => {
|
||||||
|
Object.keys(this.roomEvents).forEach((event) => {
|
||||||
|
app.cores.sync.music.eventBus.on(event, this.roomEvents[event])
|
||||||
|
})
|
||||||
|
|
||||||
|
// chat instance
|
||||||
|
const chatInstance = app.cores.api.instance().wsInstances.chat
|
||||||
|
|
||||||
|
if (chatInstance) {
|
||||||
|
Object.keys(this.chatEvents).forEach((event) => {
|
||||||
|
chatInstance.on(event, this.chatEvents[event])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.checkLatency()
|
||||||
|
|
||||||
|
this.latencyInterval = setInterval(() => {
|
||||||
|
this.checkLatency()
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount = () => {
|
||||||
|
Object.keys(this.roomEvents).forEach((event) => {
|
||||||
|
app.cores.sync.music.eventBus.off(event, this.roomEvents[event])
|
||||||
|
})
|
||||||
|
|
||||||
|
if (this.latencyInterval) {
|
||||||
|
clearInterval(this.latencyInterval)
|
||||||
|
}
|
||||||
|
|
||||||
|
// chat instance
|
||||||
|
const chatInstance = app.cores.api.instance().wsInstances.chat
|
||||||
|
|
||||||
|
if (chatInstance) {
|
||||||
|
Object.keys(this.chatEvents).forEach((event) => {
|
||||||
|
chatInstance.off(event, this.chatEvents[event])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
leaveRoom = () => {
|
||||||
|
app.cores.sync.music.leaveRoom()
|
||||||
|
}
|
||||||
|
|
||||||
|
toogleChatVisibility = (to) => {
|
||||||
|
if (typeof to !== "boolean") {
|
||||||
|
to = !this.state.chatVisible
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
chatVisible: to
|
||||||
|
})
|
||||||
|
|
||||||
|
if (this.state.notReadedMessages && to) {
|
||||||
|
this.setState({
|
||||||
|
notReadedMessages: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <>
|
||||||
|
<div className="sync-room_subcard top">
|
||||||
|
<div className="sync-room_name">
|
||||||
|
<span>
|
||||||
|
<Icons.MdSync /> {this.state.roomData?.options?.title ?? "Untitled room"}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="sync-room_share_btns">
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
icon={<Icons.MdShare />}
|
||||||
|
onClick={app.cores.sync.music.createInviteUserModal}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Badge
|
||||||
|
dot={this.state.notReadedMessages}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
icon={<Icons.MdChat />}
|
||||||
|
onClick={this.toogleChatVisibility}
|
||||||
|
/>
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="sync-room_card">
|
||||||
|
<div className="sync-room_users">
|
||||||
|
{
|
||||||
|
Array.isArray(this.state.roomData?.connectedUsers) && this.state.roomData?.connectedUsers.map((user, index) => {
|
||||||
|
return <Tooltip
|
||||||
|
title={user.username}
|
||||||
|
key={index}
|
||||||
|
>
|
||||||
|
<div className="sync-room_user" key={index}>
|
||||||
|
{
|
||||||
|
user.user_id === this.state.roomData.ownerUserId && <div className="ownerIcon">
|
||||||
|
<Icons.Crown />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div className="sync-room_user_avatar">
|
||||||
|
<img src={user.avatar} alt={user.username} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="sync-room_actions">
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={this.leaveRoom}
|
||||||
|
size="small"
|
||||||
|
icon={<Icons.MdLogout />}
|
||||||
|
danger
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="latency_display">
|
||||||
|
<span>
|
||||||
|
{
|
||||||
|
app.cores.api.instance().wsInstances.music.latency ?? "..."
|
||||||
|
}ms
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className={classnames(
|
||||||
|
"sync-room_subcard bottom",
|
||||||
|
{
|
||||||
|
"hidden": !this.state.chatVisible
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<LiveChat
|
||||||
|
room={this.state.roomData?.roomId}
|
||||||
|
compact
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
}
|
191
packages/app/src/components/SyncRoomCard/index.less
Normal file
191
packages/app/src/components/SyncRoomCard/index.less
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
.sync-room_card {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
z-index: 300;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
padding: 20px;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
min-width: 270px;
|
||||||
|
|
||||||
|
background-color: var(--background-color-accent);
|
||||||
|
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.2);
|
||||||
|
|
||||||
|
overflow-x: overlay;
|
||||||
|
|
||||||
|
.sync-room_actions {
|
||||||
|
position: sticky;
|
||||||
|
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sync-room_users {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
// width: 100%;
|
||||||
|
// height: 100%;
|
||||||
|
|
||||||
|
// overflow-y: visible;
|
||||||
|
// overflow-x: overlay;
|
||||||
|
|
||||||
|
.sync-room_user {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
gap: 5px;
|
||||||
|
|
||||||
|
animation: user-join 500ms ease-out forwards;
|
||||||
|
|
||||||
|
.sync-room_user_avatar {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
object-fit: cover;
|
||||||
|
object-position: center;
|
||||||
|
|
||||||
|
border-radius: 12px;
|
||||||
|
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ownerIcon {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
transform: translate(0, -100%);
|
||||||
|
|
||||||
|
// make gold color
|
||||||
|
color: #FFD700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.latency_display {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
gap: 5px;
|
||||||
|
|
||||||
|
padding: 5px 10px;
|
||||||
|
|
||||||
|
border-radius: 0 8px 0 8px;
|
||||||
|
|
||||||
|
font-size: 8px;
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
color: var(--text-color-accent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sync-room_subcard {
|
||||||
|
position: relative;
|
||||||
|
z-index: 295;
|
||||||
|
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
max-height: 350px;
|
||||||
|
|
||||||
|
overflow-y: overlay;
|
||||||
|
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
background-color: var(--background-color-accent);
|
||||||
|
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
|
||||||
|
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.2);
|
||||||
|
|
||||||
|
transition: all 250ms ease-in-out;
|
||||||
|
|
||||||
|
&.top {
|
||||||
|
transform: translateY(10px);
|
||||||
|
padding-bottom: 20px;
|
||||||
|
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.bottom {
|
||||||
|
transform: translateY(-10px);
|
||||||
|
padding-top: 20px;
|
||||||
|
|
||||||
|
border-radius: 0 0 8px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
opacity: 0;
|
||||||
|
max-height: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sync-room_share_btns {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// animate a bounce in
|
||||||
|
@keyframes user-join {
|
||||||
|
0% {
|
||||||
|
transform: translateY(10px);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
transform: translateY(-10px);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateY(0px);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user