Chat popup (#3098)

* add pop out chat button

* add button to close chat popup

* chat is hidden on main interface when a popup chat is open

* NameChangeEvent renames clients with the given id

if you have two or more owncast windows (or pop-out chats) open, changing your
name in 1 client is reflected in all clients.

* replace isChatVisible booleans with chatState enum

* update stories to use ChatState

* fix build tests

---------

Co-authored-by: janWilejan <>
This commit is contained in:
janWilejan
2023-06-26 16:00:27 +00:00
committed by GitHub
parent fca85a4a42
commit c563742856
6 changed files with 101 additions and 33 deletions

View File

@@ -18,6 +18,7 @@ import {
ConnectedClientInfoEvent,
MessageType,
ChatEvent,
NameChangeEvent,
MessageVisibilityEvent,
SocketEvent,
FediverseEvent,
@@ -88,11 +89,6 @@ export const isMobileAtom = atom<boolean | undefined>({
default: undefined,
});
export const chatVisibleToggleAtom = atom<boolean>({
key: 'chatVisibilityToggleAtom',
default: true,
});
export const isVideoPlayingAtom = atom<boolean>({
key: 'isVideoPlayingAtom',
default: false,
@@ -122,15 +118,23 @@ export const isChatAvailableSelector = selector({
},
});
// Chat is visible if the user wishes it to be visible AND the required
// chat state is set.
export const isChatVisibleSelector = selector({
key: 'isChatVisibleSelector',
get: ({ get }) => {
const state: AppStateOptions = get(appStateAtom);
const userVisibleToggle: boolean = get(chatVisibleToggleAtom);
return state.chatAvailable && userVisibleToggle && !hasWebsocketDisconnected;
},
// The requested state of chat in the UI
export enum ChatState {
VISIBLE, // Chat is open (the default state when the stream is online)
HIDDEN, // Chat is hidden
POPPED_OUT, // Chat is playing in a popout window
EMBEDDED, // This window is opened at /embed/chat/readwrite/
}
export const chatStateAtom = atom<ChatState>({
key: 'chatState',
default: (() => {
// XXX Somehow, `window` is undefined here, even though this runs in client
const window = globalThis;
return window?.location?.pathname === '/embed/chat/readwrite/'
? ChatState.EMBEDDED
: ChatState.VISIBLE;
})(),
});
// We display in an "online/live" state as long as video is actively playing.
@@ -315,7 +319,7 @@ export const ClientConfigStore: FC = () => {
setChatMessages(currentState => [...currentState, message as ChatEvent]);
break;
case MessageType.NAME_CHANGE:
handleNameChangeEvent(message as ChatEvent, setChatMessages);
handleNameChangeEvent(message as NameChangeEvent, setChatMessages, setCurrentUser);
break;
case MessageType.USER_JOINED:
setChatMessages(currentState => [...currentState, message as ChatEvent]);