mirror of
https://github.com/owncast/owncast.git
synced 2024-11-22 04:40:37 +03:00
Add Fediverse event chat views. Closes #2679
This commit is contained in:
parent
922c68bcf7
commit
313a81359a
7 changed files with 586 additions and 15 deletions
File diff suppressed because one or more lines are too long
|
@ -3,6 +3,7 @@ import { useState, useMemo, useRef, CSSProperties, FC, useEffect } from 'react';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import {
|
import {
|
||||||
ConnectedClientInfoEvent,
|
ConnectedClientInfoEvent,
|
||||||
|
FediverseEvent,
|
||||||
MessageType,
|
MessageType,
|
||||||
NameChangeEvent,
|
NameChangeEvent,
|
||||||
} from '../../../interfaces/socket-events';
|
} from '../../../interfaces/socket-events';
|
||||||
|
@ -16,6 +17,7 @@ import { ChatSystemMessage } from '../ChatSystemMessage/ChatSystemMessage';
|
||||||
import { ChatJoinMessage } from '../ChatJoinMessage/ChatJoinMessage';
|
import { ChatJoinMessage } from '../ChatJoinMessage/ChatJoinMessage';
|
||||||
import { ScrollToBotBtn } from './ScrollToBotBtn';
|
import { ScrollToBotBtn } from './ScrollToBotBtn';
|
||||||
import { ChatActionMessage } from '../ChatActionMessage/ChatActionMessage';
|
import { ChatActionMessage } from '../ChatActionMessage/ChatActionMessage';
|
||||||
|
import { ChatSocialMessage } from '../ChatSocialMessage/ChatSocialMessage';
|
||||||
|
|
||||||
// Lazy loaded components
|
// Lazy loaded components
|
||||||
|
|
||||||
|
@ -105,6 +107,8 @@ export const ChatContainer: FC<ChatContainerProps> = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getFediverseMessage = (message: FediverseEvent) => <ChatSocialMessage message={message} />;
|
||||||
|
|
||||||
const getUserJoinedMessage = (message: ChatMessage) => {
|
const getUserJoinedMessage = (message: ChatMessage) => {
|
||||||
const {
|
const {
|
||||||
user: { displayName, displayColor },
|
user: { displayName, displayColor },
|
||||||
|
@ -138,7 +142,7 @@ export const ChatContainer: FC<ChatContainerProps> = ({
|
||||||
|
|
||||||
const getViewForMessage = (
|
const getViewForMessage = (
|
||||||
index: number,
|
index: number,
|
||||||
message: ChatMessage | NameChangeEvent | ConnectedClientInfoEvent,
|
message: ChatMessage | NameChangeEvent | ConnectedClientInfoEvent | FediverseEvent,
|
||||||
) => {
|
) => {
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case MessageType.CHAT:
|
case MessageType.CHAT:
|
||||||
|
@ -147,18 +151,18 @@ export const ChatContainer: FC<ChatContainerProps> = ({
|
||||||
message={message as ChatMessage}
|
message={message as ChatMessage}
|
||||||
showModeratorMenu={isModerator} // Moderators have access to an additional menu
|
showModeratorMenu={isModerator} // Moderators have access to an additional menu
|
||||||
highlightString={usernameToHighlight} // What to highlight in the message
|
highlightString={usernameToHighlight} // What to highlight in the message
|
||||||
sentBySelf={message.user?.id === chatUserId} // The local user sent this message
|
sentBySelf={(message as ChatMessage).user?.id === chatUserId} // The local user sent this message
|
||||||
sameUserAsLast={shouldCollapseMessages(messages, index)}
|
sameUserAsLast={shouldCollapseMessages(messages, index)}
|
||||||
isAuthorModerator={(message as ChatMessage).user.scopes?.includes('MODERATOR')}
|
isAuthorModerator={(message as ChatMessage).user.scopes?.includes('MODERATOR')}
|
||||||
isAuthorBot={(message as ChatMessage).user.scopes?.includes('BOT')}
|
isAuthorBot={(message as ChatMessage).user.scopes?.includes('BOT')}
|
||||||
isAuthorAuthenticated={message.user?.authenticated}
|
isAuthorAuthenticated={(message as ChatMessage).user?.authenticated}
|
||||||
key={message.id}
|
key={message.id}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case MessageType.NAME_CHANGE:
|
case MessageType.NAME_CHANGE:
|
||||||
return getNameChangeViewForMessage(message as NameChangeEvent);
|
return getNameChangeViewForMessage(message as NameChangeEvent);
|
||||||
case MessageType.CONNECTED_USER_INFO:
|
case MessageType.CONNECTED_USER_INFO:
|
||||||
return getConnectedInfoMessage(message);
|
return getConnectedInfoMessage(message as ConnectedClientInfoEvent);
|
||||||
case MessageType.USER_JOINED:
|
case MessageType.USER_JOINED:
|
||||||
return getUserJoinedMessage(message as ChatMessage);
|
return getUserJoinedMessage(message as ChatMessage);
|
||||||
case MessageType.CHAT_ACTION:
|
case MessageType.CHAT_ACTION:
|
||||||
|
@ -171,6 +175,12 @@ export const ChatContainer: FC<ChatContainerProps> = ({
|
||||||
key={message.id}
|
key={message.id}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
case MessageType.FEDIVERSE_ENGAGEMENT_FOLLOW:
|
||||||
|
return getFediverseMessage(message as FediverseEvent);
|
||||||
|
case MessageType.FEDIVERSE_ENGAGEMENT_LIKE:
|
||||||
|
return getFediverseMessage(message as FediverseEvent);
|
||||||
|
case MessageType.FEDIVERSE_ENGAGEMENT_REPOST:
|
||||||
|
return getFediverseMessage(message as FediverseEvent);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
height: 85px;
|
height: 85px;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
background-color: var(--theme-color-background-main);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: var(--theme-text-link);
|
border-color: var(--theme-text-link);
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
.body {
|
.body {
|
||||||
color: var(--theme-color-components-text-on-light);
|
color: var(--theme-color-components-text-on-light);
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
line-height: 1.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.account {
|
.account {
|
||||||
|
@ -37,8 +39,8 @@
|
||||||
height: 25px;
|
height: 25px;
|
||||||
top: -20px;
|
top: -20px;
|
||||||
left: 40px;
|
left: 40px;
|
||||||
border-color: white;
|
border-color: var(--theme-color-background-main);
|
||||||
border-width: 1px;
|
border-width: 2px;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
|
|
|
@ -13,7 +13,7 @@ const Template: ComponentStory<typeof ChatSocialMessage> = args => <ChatSocialMe
|
||||||
export const Follow = Template.bind({});
|
export const Follow = Template.bind({});
|
||||||
Follow.args = {
|
Follow.args = {
|
||||||
message: {
|
message: {
|
||||||
type: 'follow',
|
type: 'FEDIVERSE_ENGAGEMENT_FOLLOW',
|
||||||
body: 'james followed this live stream.',
|
body: 'james followed this live stream.',
|
||||||
title: 'james@mastodon.social',
|
title: 'james@mastodon.social',
|
||||||
image: 'https://mastodon.social/avatars/original/missing.png',
|
image: 'https://mastodon.social/avatars/original/missing.png',
|
||||||
|
@ -24,7 +24,7 @@ Follow.args = {
|
||||||
export const Like = Template.bind({});
|
export const Like = Template.bind({});
|
||||||
Like.args = {
|
Like.args = {
|
||||||
message: {
|
message: {
|
||||||
type: 'like',
|
type: 'FEDIVERSE_ENGAGEMENT_LIKE',
|
||||||
body: 'james liked that this stream went live.',
|
body: 'james liked that this stream went live.',
|
||||||
title: 'james@mastodon.social',
|
title: 'james@mastodon.social',
|
||||||
image: 'https://mastodon.social/avatars/original/missing.png',
|
image: 'https://mastodon.social/avatars/original/missing.png',
|
||||||
|
@ -35,7 +35,7 @@ Like.args = {
|
||||||
export const Repost = Template.bind({});
|
export const Repost = Template.bind({});
|
||||||
Repost.args = {
|
Repost.args = {
|
||||||
message: {
|
message: {
|
||||||
type: 'repost',
|
type: 'FEDIVERSE_ENGAGEMENT_REPOST',
|
||||||
body: 'james shared this stream with their followers.',
|
body: 'james shared this stream with their followers.',
|
||||||
title: 'james@mastodon.social',
|
title: 'james@mastodon.social',
|
||||||
image: 'https://mastodon.social/avatars/original/missing.png',
|
image: 'https://mastodon.social/avatars/original/missing.png',
|
||||||
|
|
|
@ -25,13 +25,13 @@ export const ChatSocialMessage: FC<ChatSocialMessageProps> = ({ message }) => {
|
||||||
let Icon;
|
let Icon;
|
||||||
|
|
||||||
switch (type.toString()) {
|
switch (type.toString()) {
|
||||||
case 'follow':
|
case 'FEDIVERSE_ENGAGEMENT_FOLLOW':
|
||||||
Icon = FollowIcon;
|
Icon = FollowIcon;
|
||||||
break;
|
break;
|
||||||
case 'like':
|
case 'FEDIVERSE_ENGAGEMENT_LIKE':
|
||||||
Icon = LikeIcon;
|
Icon = LikeIcon;
|
||||||
break;
|
break;
|
||||||
case 'repost':
|
case 'FEDIVERSE_ENGAGEMENT_REPOST':
|
||||||
Icon = RepostIcon;
|
Icon = RepostIcon;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -20,6 +20,7 @@ import {
|
||||||
ChatEvent,
|
ChatEvent,
|
||||||
MessageVisibilityEvent,
|
MessageVisibilityEvent,
|
||||||
SocketEvent,
|
SocketEvent,
|
||||||
|
FediverseEvent,
|
||||||
} from '../../interfaces/socket-events';
|
} from '../../interfaces/socket-events';
|
||||||
import { mergeMeta } from '../../utils/helpers';
|
import { mergeMeta } from '../../utils/helpers';
|
||||||
import handleConnectedClientInfoMessage from './eventhandlers/connected-client-info-handler';
|
import handleConnectedClientInfoMessage from './eventhandlers/connected-client-info-handler';
|
||||||
|
@ -160,7 +161,7 @@ export const ClientConfigStore: FC = () => {
|
||||||
const [clientConfig, setClientConfig] = useRecoilState<ClientConfig>(clientConfigStateAtom);
|
const [clientConfig, setClientConfig] = useRecoilState<ClientConfig>(clientConfigStateAtom);
|
||||||
const [, setServerStatus] = useRecoilState<ServerStatus>(serverStatusState);
|
const [, setServerStatus] = useRecoilState<ServerStatus>(serverStatusState);
|
||||||
const setClockSkew = useSetRecoilState<Number>(clockSkewAtom);
|
const setClockSkew = useSetRecoilState<Number>(clockSkewAtom);
|
||||||
const [chatMessages, setChatMessages] = useRecoilState<ChatMessage[]>(chatMessagesAtom);
|
const [chatMessages, setChatMessages] = useRecoilState<SocketEvent[]>(chatMessagesAtom);
|
||||||
const [accessToken, setAccessToken] = useRecoilState<string>(accessTokenAtom);
|
const [accessToken, setAccessToken] = useRecoilState<string>(accessTokenAtom);
|
||||||
const setAppState = useSetRecoilState<AppStateOptions>(appStateAtom);
|
const setAppState = useSetRecoilState<AppStateOptions>(appStateAtom);
|
||||||
const setGlobalFatalErrorMessage = useSetRecoilState<DisplayableError>(fatalErrorStateAtom);
|
const setGlobalFatalErrorMessage = useSetRecoilState<DisplayableError>(fatalErrorStateAtom);
|
||||||
|
@ -307,6 +308,15 @@ export const ClientConfigStore: FC = () => {
|
||||||
case MessageType.CHAT_ACTION:
|
case MessageType.CHAT_ACTION:
|
||||||
setChatMessages(currentState => [...currentState, message as ChatEvent]);
|
setChatMessages(currentState => [...currentState, message as ChatEvent]);
|
||||||
break;
|
break;
|
||||||
|
case MessageType.FEDIVERSE_ENGAGEMENT_FOLLOW:
|
||||||
|
setChatMessages(currentState => [...currentState, message as FediverseEvent]);
|
||||||
|
break;
|
||||||
|
case MessageType.FEDIVERSE_ENGAGEMENT_LIKE:
|
||||||
|
setChatMessages(currentState => [...currentState, message as FediverseEvent]);
|
||||||
|
break;
|
||||||
|
case MessageType.FEDIVERSE_ENGAGEMENT_REPOST:
|
||||||
|
setChatMessages(currentState => [...currentState, message as FediverseEvent]);
|
||||||
|
break;
|
||||||
case MessageType.VISIBILITY_UPDATE:
|
case MessageType.VISIBILITY_UPDATE:
|
||||||
handleMessageVisibilityChange(message as MessageVisibilityEvent);
|
handleMessageVisibilityChange(message as MessageVisibilityEvent);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -42,3 +42,10 @@ export interface MessageVisibilityEvent extends SocketEvent {
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
ids: string[];
|
ids: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FediverseEvent extends SocketEvent {
|
||||||
|
title: string;
|
||||||
|
image: string;
|
||||||
|
link: string;
|
||||||
|
body: string;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue