mirror of
https://github.com/owncast/owncast.git
synced 2024-10-10 19:16:02 +00:00
Fill out the follower component
This commit is contained in:
parent
2cfb336411
commit
008f607cf7
@ -1,9 +1,19 @@
|
|||||||
|
import { Avatar, Comment } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
import { Follower } from '../interfaces/follower';
|
import { Follower } from '../interfaces/follower';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
follower: Follower;
|
follower: Follower;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function FollowerCollection(props: Props) {
|
export default function SingleFollower(props: Props) {
|
||||||
return <div>This is a single follower</div>;
|
const { follower } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Comment
|
||||||
|
author={follower.username}
|
||||||
|
avatar={<Avatar src={follower.image} alt="Han Solo" />}
|
||||||
|
content={follower.name}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,24 @@
|
|||||||
|
import { Pagination } from 'antd';
|
||||||
import { Follower } from '../interfaces/follower';
|
import { Follower } from '../interfaces/follower';
|
||||||
|
import SingleFollower from './Follower';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
total: number;
|
||||||
followers: Follower[];
|
followers: Follower[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function FollowerCollection(props: Props) {
|
export default function FollowerCollection(props: Props) {
|
||||||
return <div>List of followers go here</div>;
|
const ITEMS_PER_PAGE = 24;
|
||||||
|
|
||||||
|
const { followers, total } = props;
|
||||||
|
const pages = Math.ceil(total / ITEMS_PER_PAGE);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{followers.map(follower => (
|
||||||
|
<SingleFollower key={follower.link} follower={follower} />
|
||||||
|
))}
|
||||||
|
<Pagination current={1} pageSize={ITEMS_PER_PAGE} total={pages || 1} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { Spin } from 'antd';
|
import { Spin } from 'antd';
|
||||||
import { Virtuoso } from 'react-virtuoso';
|
import { Virtuoso } from 'react-virtuoso';
|
||||||
import { useState, useMemo, useCallback, useEffect, useRef } from 'react';
|
import { useState, useMemo, useCallback, useEffect, useRef } from 'react';
|
||||||
|
import { LoadingOutlined } from '@ant-design/icons';
|
||||||
import { ChatMessage } from '../../interfaces/chat-message.model';
|
import { ChatMessage } from '../../interfaces/chat-message.model';
|
||||||
import { ChatState } from '../../interfaces/application-state';
|
import { ChatState } from '../../interfaces/application-state';
|
||||||
import ChatUserMessage from './ChatUserMessage';
|
import ChatUserMessage from './ChatUserMessage';
|
||||||
import { LoadingOutlined } from '@ant-design/icons';
|
import { MessageType } from '../../interfaces/socket-events';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
messages: ChatMessage[];
|
messages: ChatMessage[];
|
||||||
@ -16,8 +17,19 @@ export default function ChatContainer(props: Props) {
|
|||||||
const loading = state === ChatState.Loading;
|
const loading = state === ChatState.Loading;
|
||||||
|
|
||||||
const chatContainerRef = useRef(null);
|
const chatContainerRef = useRef(null);
|
||||||
const spinIcon = <LoadingOutlined style={{fontSize: '32px'}} spin />
|
const spinIcon = <LoadingOutlined style={{ fontSize: '32px' }} spin />;
|
||||||
|
|
||||||
|
const getViewForMessage = message => {
|
||||||
|
switch (message.type) {
|
||||||
|
case MessageType.CHAT:
|
||||||
|
return <ChatUserMessage message={message} showModeratorMenu={false} />;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(messages);
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1>Chat</h1>
|
<h1>Chat</h1>
|
||||||
@ -26,9 +38,7 @@ export default function ChatContainer(props: Props) {
|
|||||||
ref={chatContainerRef}
|
ref={chatContainerRef}
|
||||||
initialTopMostItemIndex={999}
|
initialTopMostItemIndex={999}
|
||||||
data={messages}
|
data={messages}
|
||||||
itemContent={(index, message) => (
|
itemContent={(index, message) => getViewForMessage(message)}
|
||||||
<ChatUserMessage message={message} showModeratorMenu={false} />
|
|
||||||
)}
|
|
||||||
followOutput="smooth"
|
followOutput="smooth"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,7 +17,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
SocketEvent,
|
SocketEvent,
|
||||||
ConnectedClientInfoEvent,
|
ConnectedClientInfoEvent,
|
||||||
SocketMessageType,
|
MessageType,
|
||||||
ChatEvent,
|
ChatEvent,
|
||||||
} from '../../interfaces/socket-events';
|
} from '../../interfaces/socket-events';
|
||||||
import handleConnectedClientInfoMessage from './eventhandlers/connectedclientinfo';
|
import handleConnectedClientInfoMessage from './eventhandlers/connectedclientinfo';
|
||||||
@ -102,10 +102,10 @@ export function ClientConfigStore() {
|
|||||||
|
|
||||||
const handleMessage = (message: SocketEvent) => {
|
const handleMessage = (message: SocketEvent) => {
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case SocketMessageType.CONNECTED_USER_INFO:
|
case MessageType.CONNECTED_USER_INFO:
|
||||||
handleConnectedClientInfoMessage(message as ConnectedClientInfoEvent);
|
handleConnectedClientInfoMessage(message as ConnectedClientInfoEvent);
|
||||||
break;
|
break;
|
||||||
case SocketMessageType.CHAT:
|
case MessageType.CHAT:
|
||||||
handleChatMessage(message as ChatEvent, chatMessages, setChatMessages);
|
handleChatMessage(message as ChatEvent, chatMessages, setChatMessages);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { Layout, Tabs } from 'antd';
|
import { Layout, Tabs, Layout, Row, Col, Tabs } from 'antd';
|
||||||
import { chatVisibilityAtom, clientConfigStateAtom } from '../../stores/ClientConfigStore';
|
import Grid from 'antd/lib/card/Grid';
|
||||||
|
import {
|
||||||
|
chatVisibilityAtom,
|
||||||
|
clientConfigStateAtom,
|
||||||
|
chatMessagesAtom,
|
||||||
|
chatStateAtom,
|
||||||
|
} from '../../stores/ClientConfigStore';
|
||||||
import { ClientConfig } from '../../../interfaces/client-config.model';
|
import { ClientConfig } from '../../../interfaces/client-config.model';
|
||||||
import CustomPageContent from '../../CustomPageContent';
|
import CustomPageContent from '../../CustomPageContent';
|
||||||
import OwncastPlayer from '../../video/OwncastPlayer';
|
import OwncastPlayer from '../../video/OwncastPlayer';
|
||||||
@ -10,7 +16,6 @@ import Sidebar from '../Sidebar';
|
|||||||
import Footer from '../Footer';
|
import Footer from '../Footer';
|
||||||
import ChatContainer from '../../chat/ChatContainer';
|
import ChatContainer from '../../chat/ChatContainer';
|
||||||
import { ChatMessage } from '../../../interfaces/chat-message.model';
|
import { ChatMessage } from '../../../interfaces/chat-message.model';
|
||||||
import { chatMessagesAtom, chatStateAtom } from '../../stores/ClientConfigStore';
|
|
||||||
import { ChatState, ChatVisibilityState } from '../../../interfaces/application-state';
|
import { ChatState, ChatVisibilityState } from '../../../interfaces/application-state';
|
||||||
import ChatTextField from '../../chat/ChatTextField/ChatTextField';
|
import ChatTextField from '../../chat/ChatTextField/ChatTextField';
|
||||||
|
|
||||||
@ -26,6 +31,10 @@ export default function FooterComponent() {
|
|||||||
|
|
||||||
const { extraPageContent } = clientConfig;
|
const { extraPageContent } = clientConfig;
|
||||||
|
|
||||||
|
const followers: Follower[] = [];
|
||||||
|
|
||||||
|
const total = 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Content className={`${s.root}`} data-columns={chatOpen ? 2 : 1}>
|
<Content className={`${s.root}`} data-columns={chatOpen ? 2 : 1}>
|
||||||
<div className={`${s.leftCol}`}>
|
<div className={`${s.leftCol}`}>
|
||||||
@ -36,7 +45,7 @@ export default function FooterComponent() {
|
|||||||
<CustomPageContent content={extraPageContent} />
|
<CustomPageContent content={extraPageContent} />
|
||||||
</TabPane>
|
</TabPane>
|
||||||
<TabPane tab="Followers" key="2">
|
<TabPane tab="Followers" key="2">
|
||||||
<FollowerCollection />
|
<FollowerCollection total={total} followers={followers} />
|
||||||
</TabPane>
|
</TabPane>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
{chatOpen && (
|
{chatOpen && (
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { User } from './user.model';
|
import { User } from './user.model';
|
||||||
|
|
||||||
export enum SocketMessageType {
|
export enum MessageType {
|
||||||
CHAT = 'CHAT',
|
CHAT = 'CHAT',
|
||||||
PING = 'PING',
|
PING = 'PING',
|
||||||
NAME_CHANGE = 'NAME_CHANGE',
|
NAME_CHANGE = 'NAME_CHANGE',
|
||||||
@ -21,7 +21,7 @@ export enum SocketMessageType {
|
|||||||
export interface SocketEvent {
|
export interface SocketEvent {
|
||||||
id: string;
|
id: string;
|
||||||
timestamp: Date;
|
timestamp: Date;
|
||||||
type: SocketMessageType;
|
type: MessageType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ConnectedClientInfoEvent extends SocketEvent {
|
export interface ConnectedClientInfoEvent extends SocketEvent {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { message } from 'antd';
|
import { message } from 'antd';
|
||||||
import { SocketMessageType } from '../interfaces/socket-events';
|
import { MessageType } from '../interfaces/socket-events';
|
||||||
|
|
||||||
interface SocketMessage {
|
interface SocketMessage {
|
||||||
type: SocketMessageType;
|
type: MessageType;
|
||||||
data: any;
|
data: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ export default class WebsocketService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send PONGs
|
// Send PONGs
|
||||||
if (message.type === SocketMessageType.PING) {
|
if (message.type === MessageType.PING) {
|
||||||
this.sendPong();
|
this.sendPong();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -106,7 +106,7 @@ export default class WebsocketService {
|
|||||||
// Outbound: Other components can pass an object to `send`.
|
// Outbound: Other components can pass an object to `send`.
|
||||||
send(message: any) {
|
send(message: any) {
|
||||||
// Sanity check that what we're sending is a valid type.
|
// Sanity check that what we're sending is a valid type.
|
||||||
if (!message.type || !SocketMessageType[message.type]) {
|
if (!message.type || !MessageType[message.type]) {
|
||||||
console.warn(`Outbound message: Unknown socket message type: "${message.type}" sent.`);
|
console.warn(`Outbound message: Unknown socket message type: "${message.type}" sent.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ export default class WebsocketService {
|
|||||||
|
|
||||||
// Reply to a PING as a keep alive.
|
// Reply to a PING as a keep alive.
|
||||||
sendPong() {
|
sendPong() {
|
||||||
const pong = { type: SocketMessageType.PONG };
|
const pong = { type: MessageType.PONG };
|
||||||
this.send(pong);
|
this.send(pong);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||||
import * as FollowerComponent from '../components/Follower';
|
import SingleFollower from '../components/Follower';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'owncast/Follower',
|
title: 'owncast/Follower',
|
||||||
component: FollowerComponent,
|
component: SingleFollower,
|
||||||
parameters: {},
|
parameters: {},
|
||||||
} as ComponentMeta<typeof FollowerComponent>;
|
} as ComponentMeta<typeof SingleFollower>;
|
||||||
|
|
||||||
const Template: ComponentStory<typeof FollowerComponent> = args => <FollowerComponent {...args} />;
|
const Template: ComponentStory<typeof SingleFollower> = args => <SingleFollower {...args} />;
|
||||||
|
|
||||||
export const Example = Template.bind({});
|
export const Example = Template.bind({});
|
||||||
Example.args = {
|
Example.args = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user