u._id === authenticatedUserId)
- ? 'star-filled'
- : 'star'
- }`}
+ ? 'star-filled'
+ : 'star'
+ }`}
onClick={() => handleStarMessage(message)}
/>
setEmojiOpen(false)}
closeOnEscape
- position="left center"
+ contentStyle={popupStyle}
>
{
@@ -123,7 +129,10 @@ export const MessageToolbox = ({
handlePinMessage(message)}
/>
)}
@@ -155,10 +164,10 @@ export const MessageToolbox = ({
{showDeleteModal && (
-
+
- Delete this message?
+ Delete this message?
diff --git a/packages/react/src/components/MessageList/MessageList.js b/packages/react/src/components/MessageList/MessageList.js
index 78954faba..60cdecd12 100644
--- a/packages/react/src/components/MessageList/MessageList.js
+++ b/packages/react/src/components/MessageList/MessageList.js
@@ -13,10 +13,11 @@ import MessageReportWindow from '../ReportMessage/MessageReportWindow';
import isMessageSequential from '../../lib/isMessageSequential';
import SearchMessage from '../SearchMessage/SearchMessage';
import Roominfo from '../RoomInformation/RoomInformation';
+import AllThreads from '../AllThreads/AllThreads';
import { Message } from '../Message';
-import { Button } from '../Button';
-import { Box } from '../Box';
+import { ActionButton } from '../ActionButton';
import { Icon } from '../Icon';
+import useThreadsMessageStore from '../../store/threadsMessageStore';
const MessageList = ({ messages, handleGoBack }) => {
const showSearch = useSearchMessageStore((state) => state.showSearch);
@@ -27,6 +28,7 @@ const MessageList = ({ messages, handleGoBack }) => {
const showReportMessage = useMessageStore((state) => state.showReportMessage);
const messageToReport = useMessageStore((state) => state.messageToReport);
const showAvatar = useUserStore((state) => state.showAvatar);
+ const showAllThreads = useThreadsMessageStore((state) => state.showAllThreads);
const isMessageNewDay = (current, previous) =>
!previous || !isSameDay(new Date(current.ts), new Date(previous.ts));
@@ -52,22 +54,15 @@ const MessageList = ({ messages, handleGoBack }) => {
);
})}
{filtered && (
-
-
-
+
+
+
)}
{showMembers && }
{showReportMessage && }
{showSearch && }
{showChannelinfo && }
+ {showAllThreads && }
>
);
};
diff --git a/packages/react/src/components/Modal/Modal.js b/packages/react/src/components/Modal/Modal.js
index 6b7d0a359..260b9e016 100644
--- a/packages/react/src/components/Modal/Modal.js
+++ b/packages/react/src/components/Modal/Modal.js
@@ -1,12 +1,13 @@
import { css, useTheme } from '@emotion/react';
-import React, { forwardRef } from 'react';
+import React, { forwardRef, useRef, useCallback, useEffect } from 'react';
import useComponentOverrides from '../../theme/useComponentOverrides';
import { Box } from '../Box';
import { ModalBackdrop } from './ModalBackdrop';
export const Modal = forwardRef(
- ({ className = '', style = {}, open = true, children, ...props }, ref) => {
+ ({ className = '', style = {}, open = true, children, onClose = () => { }, ...props }, ref) => {
const { classNames, styleOverrides } = useComponentOverrides('Modal');
+ const backDropRef = useRef(null);
const theme = useTheme();
const ModalCss = css`
background: none;
@@ -25,8 +26,32 @@ export const Modal = forwardRef(
if (!open) {
return null;
}
+
+ const handleClick = useCallback(
+ (e) => {
+ if (e.target === backDropRef.current) {
+ onClose();
+ }
+ },
+ [onClose]
+ );
+
+ const handleEscKey = useCallback((e) => {
+ if (e.key === 'Escape') {
+ onClose();
+ }
+ }, [onClose]);
+
+ useEffect(() => {
+ window.addEventListener('keydown', handleEscKey);
+
+ return () => {
+ window.removeEventListener('keydown', handleEscKey);
+ };
+ }, [handleEscKey]);
+
return (
-
+
(
-
- {children}
-
-);
+export const ModalBackdrop = forwardRef(({ children, onClick = () => { } }, ref) => {
+ return (
+
+ {children}
+
+ )
+});
diff --git a/packages/react/src/components/ReportMessage/MessageReportWindow.js b/packages/react/src/components/ReportMessage/MessageReportWindow.js
index 2a7989859..5ada6ac4d 100644
--- a/packages/react/src/components/ReportMessage/MessageReportWindow.js
+++ b/packages/react/src/components/ReportMessage/MessageReportWindow.js
@@ -27,6 +27,7 @@ const MessageReportWindow = ({ messageId }) => {
display: 'flex',
justifyContent: 'center',
marginBottom: '0.125rem',
+ padding:'0.6rem 0'
}}
>
{
};
return (
-
+
- Report this message?
+
+ Report this message?
diff --git a/packages/react/src/components/SearchMessage/SearchMessage.js b/packages/react/src/components/SearchMessage/SearchMessage.js
index 0eb5c7cba..f5cc41c72 100644
--- a/packages/react/src/components/SearchMessage/SearchMessage.js
+++ b/packages/react/src/components/SearchMessage/SearchMessage.js
@@ -49,7 +49,7 @@ const Search = () => {
flexDirection: 'row',
alignItems: 'center',
gap: '0.5rem',
- marginBottom: '0.25rem',
+ marginBottom: '1rem',
}}
>
@@ -64,25 +64,14 @@ const Search = () => {
className={classes.container}
style={{ border: '2px solid #ddd', position: 'relative' }}
>
-
setText(e.target.value)}
onKeyDown={handleKeyPress}
className={classes.textInput}
/>
-
+
+
{messageList &&
messageList.map((msg, index, arr) => {
diff --git a/packages/react/src/components/SearchMessage/SearchMessage.module.css b/packages/react/src/components/SearchMessage/SearchMessage.module.css
index 06fdb357d..8369e2381 100644
--- a/packages/react/src/components/SearchMessage/SearchMessage.module.css
+++ b/packages/react/src/components/SearchMessage/SearchMessage.module.css
@@ -16,10 +16,11 @@
align-items: center;
justify-content: center;
background-color: #fff;
+ margin-bottom: 1rem;
}
.textInput {
- width: 65%;
+ width: 75%;
height: 2.5rem;
border: none;
outline: none;
diff --git a/packages/react/src/components/ThreadHeader/ThreadHeader.js b/packages/react/src/components/ThreadHeader/ThreadHeader.js
deleted file mode 100644
index 900d1bec3..000000000
--- a/packages/react/src/components/ThreadHeader/ThreadHeader.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import styles from './ThreadHeader.module.css';
-import { Icon } from '../Icon';
-import { Box } from '../Box';
-import { ActionButton } from '../ActionButton';
-
-const ThreadHeader = ({ title, handleClose }) => (
-
-
-
-
-
- {title}
-
-
-);
-
-export default ThreadHeader;
-
-ThreadHeader.propTypes = {
- handleClose: PropTypes.func,
- title: PropTypes.string,
-};
diff --git a/packages/react/src/components/ThreadHeader/index.js b/packages/react/src/components/ThreadHeader/index.js
deleted file mode 100644
index cf213e591..000000000
--- a/packages/react/src/components/ThreadHeader/index.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default as ThreadHeader } from './ThreadHeader';
diff --git a/packages/react/src/components/Throbber/Throbber.js b/packages/react/src/components/Throbber/Throbber.js
index 24d9e9203..323ac8fc6 100644
--- a/packages/react/src/components/Throbber/Throbber.js
+++ b/packages/react/src/components/Throbber/Throbber.js
@@ -57,7 +57,7 @@ const Throbber = forwardRef(
) => {
const ThrobberCss = css`
display: flex;
- justify-content: center;
+ width: fit-content
margin-block: -0.125rem;
`;
return (
diff --git a/packages/react/src/components/ToastBar/ToastContainer.js b/packages/react/src/components/ToastBar/ToastContainer.js
index 078a30eca..34cf4db14 100644
--- a/packages/react/src/components/ToastBar/ToastContainer.js
+++ b/packages/react/src/components/ToastBar/ToastContainer.js
@@ -1,14 +1,32 @@
import React, { useContext, useMemo, useCallback } from 'react';
-import { css, useTheme } from '@emotion/react';
+import { css, useTheme, keyframes} from '@emotion/react';
import ToastContext from '../../context/ToastContext';
import { Box } from '../Box';
import ToastBar from './ToastBar';
const ToastContainer = () => {
const theme = useTheme();
+
+ const animation = keyframes`
+ 0% {
+ opacity: 0;
+ }
+ 20% {
+ opacity: 1;
+ }
+ 80% {
+ opacity: 1;
+ }
+ 100% {
+ opacity: 0;
+ }
+ `;
const ToastContainerCss = css`
position: fixed;
z-index: ${theme.zIndex.toastbar};
+ border-radius: 0.25em;
+ background-color:white;
+ animation: ${animation} ${2000}ms ease-in-out forwards;
`;
const { position, toasts, setToasts } = useContext(ToastContext);
diff --git a/packages/react/src/components/auth/LoginForm.js b/packages/react/src/components/auth/LoginForm.js
index 7292b43b0..ce1f3bedf 100644
--- a/packages/react/src/components/auth/LoginForm.js
+++ b/packages/react/src/components/auth/LoginForm.js
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React, { useEffect, useState } from 'react';
import { css } from '@emotion/react';
import { GenericModal } from '../GenericModal';
import { loginModalStore } from '../../store';
@@ -10,16 +10,34 @@ import EyeOpen from './icons/EyeOpen';
import EyeClose from './icons/EyeClose';
export default function LoginForm() {
- const [userOrEmail, setuserOrEmail] = useState(null);
- const [password, setpassword] = useState(null);
+ const [userOrEmail, setUserOrEmail] = useState(null);
+ const [password, setPassword] = useState(null);
const [showPassword, setShowPassword] = useState(false);
+ const [usernameError, setUsernameError] = useState(false);
+ const [passwordError, setPasswordError] = useState(false);
const isLoginModalOpen = loginModalStore((state) => state.isLoginModalOpen);
const setIsLoginModalOpen = loginModalStore(
(state) => state.setIsLoginModalOpen
);
const { handleLogin } = useRCAuth();
+ useEffect(()=>{
+ if(userOrEmail !== null && userOrEmail.trim() === ''){
+ setUsernameError(true);
+ }else{
+ setUsernameError(false);
+ }
+
+ if(password !== null && password.trim() === ''){
+ setPasswordError(true);
+ }else{
+ setPasswordError(false);
+ }
+ },[userOrEmail,password])
+
const handleSubmit = () => {
+ if(!userOrEmail) setUserOrEmail('');
+ if(!password) setPassword('');
handleLogin(userOrEmail, password);
};
const handleClose = () => {
@@ -27,10 +45,10 @@ export default function LoginForm() {
};
const handleEdituserOrEmail = (e) => {
- setuserOrEmail(e.target.value);
+ setUserOrEmail(e.target.value);
};
const handleEditPassword = (e) => {
- setpassword(e.target.value);
+ setPassword(e.target.value);
};
const handleTogglePassword = () => {
setShowPassword(!showPassword);
@@ -98,8 +116,10 @@ export default function LoginForm() {
onChange={handleEdituserOrEmail}
placeholder="example@example.com"
onKeyPress={handleKeyPress}
+ style={{ borderColor: usernameError ? 'red' : '' }}
/>
+ {usernameError && This field is required}
@@ -109,6 +129,7 @@ export default function LoginForm() {
type={showPassword ? 'text' : 'password'}
onChange={handleEditPassword}
onKeyPress={handleKeyPress}
+ style={{ borderColor: passwordError ? 'red' : '' }}
/>
: }
+ {passwordError && This field is required}
{
primary={block.style === 'primary'}
danger={block.style === 'danger'}
minWidth="4ch"
- small
+ size='medium'
value={block.value}
onClick={action}
>
diff --git a/packages/react/src/hooks/useDropBox.js b/packages/react/src/hooks/useDropBox.js
new file mode 100644
index 000000000..31a5acde6
--- /dev/null
+++ b/packages/react/src/hooks/useDropBox.js
@@ -0,0 +1,44 @@
+import { useState } from 'react';
+import useAttachmentWindowStore from '../store/attachmentwindow';
+
+
+const useDropBox = () => {
+
+ const data = useAttachmentWindowStore((state) => state.data);
+ const setData = useAttachmentWindowStore((state) => state.setData);
+ const toggle = useAttachmentWindowStore((state) => state.toggle);
+
+ const [onDrag, setOnDrag] = useState(false);
+ const [leaveCount, setLeaveCount] = useState(0);
+
+ const handleDrag = (e) => {
+ e.preventDefault();
+ };
+
+ const handleDragEnter = () => {
+ setOnDrag(true);
+ };
+
+ const handleDragLeave = () => {
+ if ((leaveCount % 2) === 1) {
+ setOnDrag(false);
+ setLeaveCount(leaveCount + 1);
+ } else {
+ setLeaveCount(leaveCount + 1);
+ }
+ };
+
+ const handleDragDrop = (e) => {
+ e.preventDefault();
+ setOnDrag(false);
+ setLeaveCount(0);
+
+ toggle();
+ setData(e.dataTransfer.files[0]);
+ };
+
+
+ return { onDrag, data, handleDrag, handleDragEnter, handleDragLeave, handleDragDrop }
+};
+
+export default useDropBox;
diff --git a/packages/react/src/hooks/useMediaRecorder.js b/packages/react/src/hooks/useMediaRecorder.js
index 4dfccc833..05046a59d 100644
--- a/packages/react/src/hooks/useMediaRecorder.js
+++ b/packages/react/src/hooks/useMediaRecorder.js
@@ -1,6 +1,6 @@
import { useState, useRef } from 'react';
-function useUserMedia(constraints) {
+function useUserMedia(constraints, videoRef) {
const [stream, setStream] = useState();
async function getStream(refresh = false) {
if (stream && !refresh) {
@@ -8,14 +8,20 @@ function useUserMedia(constraints) {
}
const _stream = await navigator.mediaDevices.getUserMedia(constraints);
setStream(_stream);
+
+ // Optionally, set the stream as the srcObject of the video element
+ if (videoRef.current) {
+ videoRef.current.srcObject = _stream;
+ }
+
return _stream;
}
return { stream, getStream };
}
-export function useMediaRecorder({ constraints, onStop }) {
+export function useMediaRecorder({ constraints, onStop, videoRef }) {
const [recorder, setRecorder] = useState();
- const { getStream } = useUserMedia(constraints);
+ const { getStream } = useUserMedia(constraints, videoRef);
const chunks = useRef([]);
async function start() {
diff --git a/packages/react/src/hooks/useRCAuth.js b/packages/react/src/hooks/useRCAuth.js
index 2b4eec957..2a68da1ad 100644
--- a/packages/react/src/hooks/useRCAuth.js
+++ b/packages/react/src/hooks/useRCAuth.js
@@ -29,7 +29,7 @@ export const useRCAuth = () => {
const handleLogin = async (userOrEmail, password, code) => {
try {
const res = await RCInstance.login(userOrEmail, password, code);
- if (res.error === 'Unauthorized') {
+ if (res.error === 'Unauthorized' || res.error === 403) {
dispatchToastMessage({
type: 'error',
message:
diff --git a/packages/react/src/store/channelStore.js b/packages/react/src/store/channelStore.js
index 6a500edac..fddc512e6 100644
--- a/packages/react/src/store/channelStore.js
+++ b/packages/react/src/store/channelStore.js
@@ -2,9 +2,11 @@ import { create } from 'zustand';
const useChannelStore = create((set) => ({
showChannelinfo: false,
+ isChannelPrivate: false,
setShowChannelinfo: (showChannelinfo) => set(() => ({ showChannelinfo })),
channelInfo: {},
setChannelInfo: (channelInfo) => set(() => ({ channelInfo })),
+ setIsChannelPrivate: (isChannelPrivate) => set(() => ({ isChannelPrivate }))
}));
export default useChannelStore;
diff --git a/packages/react/src/store/index.js b/packages/react/src/store/index.js
index 3961a1baa..1d734fbbe 100644
--- a/packages/react/src/store/index.js
+++ b/packages/react/src/store/index.js
@@ -6,3 +6,4 @@ export { default as totpModalStore } from './totpmodalStore';
export { default as useSearchMessageStore } from './searchMessageStore';
export { default as loginModalStore } from './loginmodalStore';
export { default as useChannelStore } from './channelStore';
+export { default as useThreadsMessageStore } from './threadsMessageStore';
diff --git a/packages/react/src/store/messageStore.js b/packages/react/src/store/messageStore.js
index a251aafd3..9fdbcc2ef 100644
--- a/packages/react/src/store/messageStore.js
+++ b/packages/react/src/store/messageStore.js
@@ -12,6 +12,7 @@ const useMessageStore = create((set, get) => ({
isRecordingMessage: false,
isThreadOpen: false,
threadMainMessage: null,
+ headerTitle:null,
setFilter: (filter) => set(() => ({ filtered: filter })),
setMessages: (messages) => set(() => ({ messages })),
upsertMessage: (message, enableThreads = false) => {
@@ -89,6 +90,7 @@ const useMessageStore = create((set, get) => ({
}));
},
setThreadMessages: (messages) => set(() => ({ threadMessages: messages })),
+ setHeaderTitle: (title) => set(()=>({headerTitle:title}))
}));
export default useMessageStore;
diff --git a/packages/react/src/store/threadsMessageStore.js b/packages/react/src/store/threadsMessageStore.js
new file mode 100644
index 000000000..f455a04f6
--- /dev/null
+++ b/packages/react/src/store/threadsMessageStore.js
@@ -0,0 +1,8 @@
+import { create } from 'zustand';
+
+const useThreadsMessageStore = create((set) => ({
+ showAllThreads: false,
+ setShowAllThreads: (showAllThreads) => set(() => ({ showAllThreads })),
+}));
+
+export default useThreadsMessageStore;
diff --git a/packages/react/src/theme/DefaultTheme.js b/packages/react/src/theme/DefaultTheme.js
index 32f742291..0f124f7aa 100644
--- a/packages/react/src/theme/DefaultTheme.js
+++ b/packages/react/src/theme/DefaultTheme.js
@@ -138,8 +138,8 @@ const DefaultTheme = {
header: 1100,
popup: 1200,
modal: 1300,
- toastbar: 1400,
tooltip: 1500,
+ toastbar: 10001,
},
};