diff --git a/package.json b/package.json index 773f9fc..20dfbee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "quickblox-react-ui-kit", - "version": "0.3.0-beta.4", + "version": "0.3.0", "main": "dist/index-ui.js", "license": "MIT", "dependencies": { @@ -86,7 +86,7 @@ "lint": "eslint ./src", "eject": "react-scripts eject", "storybook": "storybook dev -p 6006", - "build-storybook": "storybook build" + "build:storybook": "storybook build" }, "lint-staged": { "src/**/*.{ts,tsx}": "eslint" diff --git a/src/App.tsx b/src/App.tsx index 77137a3..01653f1 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -27,8 +27,8 @@ function App() { const { connectionRepository } = useQBConnection(); const initLoginData: LoginData = { - login: 'artik', // vit1 380990579507 - password: 'quickblox', + login: '', + password: '', }; const [currentUser, setCurrentUser] = React.useState(initLoginData); diff --git a/src/Data/DefaultConfigurations.ts b/src/Data/DefaultConfigurations.ts index 1cb335d..6c54ff4 100644 --- a/src/Data/DefaultConfigurations.ts +++ b/src/Data/DefaultConfigurations.ts @@ -133,10 +133,10 @@ export class DefaultConfigurations { static getDefaultQBConfig(): QBConfig { return { credentials: { - appId: 75949, - accountKey: 'uK_8uinNyz8-npTNB6tx', - authKey: 'DdS7zxMEm5Q7DaS', - authSecret: 'g88RhdOjnDOqFkv', + appId: -1, + accountKey: '', + authKey: '', + authSecret: '', sessionToken: '', }, configAIApi: { diff --git a/src/Presentation/layouts/Desktop/QuickBloxUIKitDesktopLayout.tsx b/src/Presentation/layouts/Desktop/QuickBloxUIKitDesktopLayout.tsx index ff2f961..0a05c41 100644 --- a/src/Presentation/layouts/Desktop/QuickBloxUIKitDesktopLayout.tsx +++ b/src/Presentation/layouts/Desktop/QuickBloxUIKitDesktopLayout.tsx @@ -41,8 +41,6 @@ import { useMobileLayout } from '../../components/containers/SectionList/hooks'; import { MessageDTOMapper } from '../../../Data/source/remote/Mapper/MessageDTOMapper'; import MembersList from '../../Views/DialogInfo/MembersList/MembersList'; import useUsersListViewModel from '../../Views/DialogInfo/UsersList/useUsersListViewModel'; -import { GetUserNameFct } from '../../Views/Dialog/Message/IncomingMessage/IncomingMessage'; -import { UserEntity } from '../../../Domain/entity/UserEntity'; import Header from '../../ui-components/Header/Header'; import Avatar from '../../ui-components/Avatar/Avatar'; import { @@ -81,83 +79,36 @@ const QuickBloxUIKitDesktopLayout: React.FC< // eslint-disable-next-line @typescript-eslint/no-unused-vars,react/function-component-definition > = ({ theme = undefined, - // eslint-disable-next-line @typescript-eslint/no-unused-vars AITranslate = undefined, - // eslint-disable-next-line @typescript-eslint/no-unused-vars AIRephrase = undefined, AIAssist = undefined, - // eslint-disable-next-line @typescript-eslint/no-unused-vars uikitHeightOffset = '0px', }: QuickBloxUIKitDesktopLayoutProps) => { - console.log('create QuickBloxUIKitDesktopLayout'); - const [forwardMessage, setForwardMessage] = useState(); - const forwardMessageModal = useModal(); - const [selectedDialog, setSelectedDialog] = React.useState(); + const mimeType = 'audio/webm;codecs=opus'; // audio/ogg audio/mpeg audio/webm audio/x-wav audio/mp4 + const messagePerPage = 47; const currentContext = useQbInitializedDataContext(); const QBConfig = currentContext.InitParams.qbConfig || DefaultConfigurations.getDefaultQBConfig(); - // const eventMessaging = useEventMessagesRepository(); - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore const userName = currentContext.storage.REMOTE_DATA_SOURCE.authInformation?.userName; const currentUserId = currentContext.storage.REMOTE_DATA_SOURCE.authInformation?.userId; const sessionToken = currentContext.storage.REMOTE_DATA_SOURCE.authInformation?.sessionToken; + const { enableForwarding } = QBConfig.appConfig; + const { enableReplying } = QBConfig.appConfig; + const { maxFileSize } = currentContext.InitParams; - const dialogsViewModel: DialogListViewModel = - useDialogListViewModel(currentContext); - - // must re-create as result dialog changing - const messagesViewModel: DialogViewModel = useDialogViewModel( - dialogsViewModel.entity?.type, - dialogsViewModel.entity, - ); - - const { browserOnline, connectionStatus, connectionRepository } = - useQBConnection(); - - const [isOnline, setIsOnline] = useState( - browserOnline && connectionStatus, - ); - - connectionRepository.subscribe((status) => { - console.log(`Connection status: ${status ? 'CONNECTED' : 'DISCONNECTED'}`); - if (status) setIsOnline(true); - else setIsOnline(false); - }); - - const [needRefresh, setNeedRefresh] = useState(false); - const toastConnectionErrorId = React.useRef(null); - - useEffect(() => { - if (browserOnline) { - setIsOnline(true); - // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/ban-ts-comment - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - toast.dismiss(toastConnectionErrorId.current); - } else { - setIsOnline(false); - // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/ban-ts-comment - // @ts-ignore - toastConnectionErrorId.current = toast('Connection ...', { - autoClose: false, - isLoading: true, - }); - } - }, [browserOnline && connectionStatus]); + const maxTokensForAIRephrase = + currentContext.InitParams.qbConfig.configAIApi.AIRephraseWidgetConfig + .maxTokens; - useEffect(() => { - if (!isOnline) { - setNeedRefresh(true); - } - }, [isOnline]); + const rephraseTones: Tone[] = + currentContext.InitParams.qbConfig.configAIApi.AIRephraseWidgetConfig.Tones; - let defaultAIRephraseWidget = AIRephrase?.AIWidget; // useDefaultTextInputWidget(); + let defaultAIRephraseWidget = AIRephrase?.AIWidget; let defaultAITranslateWidget = AITranslate?.AIWidget; let defaultAIAssistWidget = AIAssist?.AIWidget; @@ -270,34 +221,101 @@ const QuickBloxUIKitDesktopLayout: React.FC< getAITranslate(); getAIRephrase(); getAIAssistAnswer(); + const dialogsViewModel: DialogListViewModel = + useDialogListViewModel(currentContext); - const { enableForwarding } = QBConfig.appConfig; - const { enableReplying } = QBConfig.appConfig; + const messagesViewModel: DialogViewModel = useDialogViewModel( + dialogsViewModel.entity?.type, + dialogsViewModel.entity, + ); - const selectDialogActions = (item: BaseViewModel): void => { - if (isOnline) { - if (!dialogsViewModel.loading) { - setSelectedDialog(item.entity); - // dialogsViewModel.entity = item.entity; - } - } - }; + const [forwardMessage, setForwardMessage] = useState(); + const forwardMessageModal = useModal(); + const [selectedDialog, setSelectedDialog] = React.useState(); + const userViewModel = useUsersListViewModel(selectedDialog); + const [dialogAvatarUrl, setDialogAvatarUrl] = React.useState(''); + + const { browserOnline, connectionStatus, connectionRepository } = + useQBConnection(); + + const [isOnline, setIsOnline] = useState( + browserOnline && connectionStatus, + ); + + connectionRepository.subscribe((status) => { + console.log(`Connection status: ${status ? 'CONNECTED' : 'DISCONNECTED'}`); + if (status) setIsOnline(true); + else setIsOnline(false); + }); + + const [needRefresh, setNeedRefresh] = useState(false); + const toastConnectionErrorId = React.useRef(null); + + // + const [waitAIWidget, setWaitAIWidget] = useState(false); + const [messageText, setMessageText] = useState(''); const [showReplyMessage, setShowReplyMessage] = useState(false); const [messagesToReply, setMessagesToReply] = useState([]); + // eslint-disable-next-line @typescript-eslint/no-unused-vars const [isMobile, width, height, breakpoint] = useMobileLayout(); const [clientHeight, setClientHeight] = useState(0); // eslint-disable-next-line @typescript-eslint/no-unused-vars const [scrollUpToDown, setScrollUpToDown] = React.useState(false); + const [needDialogInformation, setNeedDialogInformation] = useState(false); + const informationCloseHandler = (): void => { + setNeedDialogInformation(false); + }; + const informationOpenHandler = (): void => { + setNeedDialogInformation(true); + }; + // + const maxWidthToResizing = + selectedDialog && needDialogInformation + ? '$message-view-container-wrapper-min-width' + : '1040px'; + const workHeight = isMobile + ? `calc(${height.toString()}px - ${uikitHeightOffset} - 28px)` + : `calc(100vh - ${uikitHeightOffset} - 28px)`; + const messagesContainerMobileHeight = showReplyMessage + ? `calc(${clientHeight}px - 128px - 64px - 16px)` + : `calc(${clientHeight}px - 128px - 16px)`; + const messagesContainerHeight = showReplyMessage + ? `calc(${clientHeight}px - 128px - 64px)` + : `calc(${clientHeight}px - 128px - 1px)`; + const clientContainerHeight = `${clientHeight - 5}px`; + const headerHeight = 64; + const dialogListScrollableHeight = clientHeight - headerHeight - 6; - // const [dialogMessagesCount, setDialogMessageCount] = useState(100); - // const [hasMore, setHasMore] = React.useState(true); - // const [messagesToView, setMessagesToView] = React.useState( - // [], - // ); + const [warningErrorText, setWarningErrorText] = useState(''); + const [useAudioWidget, setUseAudioWidget] = useState(false); + const [fileToSend, setFileToSend] = useState(null); + const [isRecording, setIsRecording] = useState(false); + const [permission, setPermission] = useState(false); + const [stream, setStream] = useState(); + const mediaRecorder = useRef(); + const [resultAudioBlob, setResultAudioBlob] = useState(); + const [audioChunks, setAudioChunks] = useState>([]); + const newModal = useModal(); + const [dialogToLeave, setDialogToLeave] = useState(); + const [showDialogList, setShowDialogList] = useState(true); + const [showDialogMessages, setShowDialogMessages] = useState(true); + const [showDialogInformation, setShowDialogInformation] = + useState(false); + const [isAllMembersShow, setIsAllMembersShow] = React.useState(false); + const [isOpen, setIsOpen] = useState(false); + + // functions + + const selectDialogActions = (item: BaseViewModel): void => { + if (isOnline) { + if (!dialogsViewModel.loading) { + setSelectedDialog(item.entity); + // dialogsViewModel.entity = item.entity; + } + } + }; - // инициализация СДК и загрузка тестовых данных, запуск пинга - может не быть - // todo: добавить метод в контекст const isAuthProcessed = (): boolean => { console.log('call isAuthProcessed'); const result = @@ -322,115 +340,6 @@ const QuickBloxUIKitDesktopLayout: React.FC< return result; }; - useEffect(() => { - const codeVersion = '0.3.0'; - - console.log(`React UIKit CODE VERSION IS ${codeVersion}`); - console.log('TestStage: GET DATA '); - console.log( - `auth data: ${JSON.stringify( - currentContext.InitParams.loginData, - )} at ${new Date().toLocaleTimeString()}`, - ); - if (isAuthProcessed()) { - console.log('auth is completed, CAN GET DATA'); - const pagination: Pagination = new Pagination(); - - dialogsViewModel?.getDialogs(pagination); - } - - return () => { - console.log('TestStage: USE EFFECT release'); - dialogsViewModel.release(); - }; - }, []); - - useEffect(() => { - console.log('TestStage: GET DATA AFTER User data has CHANGED'); - console.log( - `auth is ${JSON.stringify( - currentContext.InitParams.loginData, - )} at ${new Date().toLocaleTimeString()}`, - ); - - if (isAuthProcessed()) { - console.log('auth is completed, FETCH DATA'); - const pagination: Pagination = new Pagination(); - - dialogsViewModel?.getDialogs(pagination); - } - }, [currentContext.InitParams]); - - // const fetchMoreData = () => { - // if (messagesToView.length >= dialogMessagesCount) { - // setHasMore(false); - // - // return; - // } - // if ( - // hasMore && - // messagesToView.length > 0 && - // messagesToView.length < dialogMessagesCount - // ) { - // setMessagesToView((prevState) => { - // const newState = [...prevState]; - // - // const newMessageEntity: MessageEntity = - // messagesViewModel.messages[prevState.length]; - // - // newState.push(newMessageEntity); - // // newState.unshift(newMessageEntity); - // - // return newState; - // }); - // } - // }; - - // function prepareFirstPage(initData: MessageEntity[]) { - // const firstPageSize = messagesViewModel.messages.length; - // - // for (let i = firstPageSize - 1; i >= 0; i -= 1) { - // initData.push(messagesViewModel.messages[i]); - // } - // } - - // - // useEffect(() => { - // setDialogMessageCount(messagesViewModel?.messages?.length || 0); - // if (messagesToView?.length === 0 && messagesViewModel.messages.length > 0) { - // const initData: MessageEntity[] = []; - // - // console.log(JSON.stringify(messagesViewModel.messages)); - // prepareFirstPage(initData); - // setMessagesToView(initData); - // } else if (messagesViewModel.messages.length - messagesToView.length >= 1) { - // setHasMore(true); - // setScrollUpToDown(true); - // } - // }, [messagesViewModel.messages]); - // - // useEffect(() => { - // if (messagesViewModel.messages.length - messagesToView.length >= 1) { - // fetchMoreData(); - // } - // }, [dialogMessagesCount]); - const messagePerPage = 47; - - useEffect(() => { - if (messagesViewModel.entity) { - messagesViewModel.getMessages(new Pagination(0, messagePerPage)); - } - }, [messagesViewModel.entity]); - - useEffect(() => { - if (isOnline && needRefresh) { - if (messagesViewModel.entity) { - messagesViewModel.getMessages(new Pagination(0, messagePerPage)); - - setNeedRefresh(false); - } - } - }, [isOnline]); const fetchMoreData = () => { if (messagesViewModel.pagination.hasNextPage()) { const newPagination = messagesViewModel.pagination; @@ -442,8 +351,6 @@ const QuickBloxUIKitDesktopLayout: React.FC< } }; - const userViewModel = useUsersListViewModel(selectedDialog); - const [dialogAvatarUrl, setDialogAvatarUrl] = React.useState(''); const getUserAvatarByUid = async () => { let result = ''; const participants: Array = @@ -469,18 +376,6 @@ const QuickBloxUIKitDesktopLayout: React.FC< } } - useEffect(() => { - getDialogPhotoFileForPreview(); - if (dialogsViewModel.entity) { - userViewModel.entity = dialogsViewModel.entity; - } - - return () => { - if (dialogAvatarUrl) { - URL.revokeObjectURL(dialogAvatarUrl); - } - }; - }, [dialogsViewModel.entity]); // eslint-disable-next-line consistent-return const renderIconForTypeDialog = (dialogEntity: DialogEntity) => { if (dialogEntity.type === DialogType.group) { @@ -510,67 +405,11 @@ const QuickBloxUIKitDesktopLayout: React.FC< } }; - useEffect(() => { - console.log( - `Clear selected dialog: ${ - selectedDialog?.name || 'Dialog Name is empty' - }`, - ); - if (!dialogsViewModel.entity) { - setSelectedDialog(undefined); - } - }, [dialogsViewModel.entity]); - - const [needDialogInformation, setNeedDialogInformation] = useState(false); - const informationCloseHandler = (): void => { - setNeedDialogInformation(false); - }; - const informationOpenHandler = (): void => { - setNeedDialogInformation(true); - }; - // - const maxTokensForAIRephrase = - currentContext.InitParams.qbConfig.configAIApi.AIRephraseWidgetConfig - .maxTokens; - - const rephraseTones: Tone[] = - currentContext.InitParams.qbConfig.configAIApi.AIRephraseWidgetConfig.Tones; - - const { maxFileSize } = currentContext.InitParams; - // - const [waitAIWidget, setWaitAIWidget] = useState(false); - const [messageText, setMessageText] = useState(''); - - const [warningErrorText, setWarningErrorText] = useState(''); - // const [showErrorToast, setShowErrorToast] = useState(false); - // const [messageErrorToast, setMessageErrorToast] = useState(''); - - const [useAudioWidget, setUseAudioWidget] = useState(false); - - const [fileToSend, setFileToSend] = useState(null); - - const [isRecording, setIsRecording] = useState(false); - // - const [permission, setPermission] = useState(false); - - // const [recordingStatus, setRecordingStatus] = useState('inactive'); - - const [stream, setStream] = useState(); - // const [mediaRecorder, setMediaRecorder] = useState(); - const mediaRecorder = useRef(); - const [resultAudioBlob, setResultAudioBlob] = useState(); - - const [audioChunks, setAudioChunks] = useState>([]); - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const mimeType = 'audio/webm;codecs=opus'; // audio/ogg audio/mpeg audio/webm audio/x-wav audio/mp4 - // eslint-disable-next-line @typescript-eslint/no-unused-vars - - const showErrorMessage = (errorMessage: string) => { - setWarningErrorText(errorMessage); - setTimeout(() => { - setWarningErrorText(''); - }, 3000); + const showErrorMessage = (errorMessage: string) => { + setWarningErrorText(errorMessage); + setTimeout(() => { + setWarningErrorText(''); + }, 3000); }; const closeReplyMessageFlowHandler = () => { @@ -601,41 +440,6 @@ const QuickBloxUIKitDesktopLayout: React.FC< }); }; - useEffect(() => { - const MAXSIZE = maxFileSize || 90 * 1000000; - const MAXSIZE_FOR_MESSAGE = MAXSIZE / (1024 * 1024); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const flag = fileToSend?.size && fileToSend?.size < MAXSIZE; - - if (fileToSend?.size && fileToSend?.size < MAXSIZE) { - if (showReplyMessage && messagesToReply?.length > 0) { - const replyData: ReplyMessagesParams = { - messagesToReply, - relatedFileMessage: fileToSend, - relatedTextMessage: - messageText || MessageDTOMapper.REPLY_MESSAGE_PREFIX, - }; - - repliedActions(replyData); - } else if (isOnline) { - // eslint-disable-next-line promise/catch-or-return - messagesViewModel - .sendAttachmentMessage(fileToSend) - .then((resultOperation) => { - // eslint-disable-next-line promise/always-return - if (!resultOperation) { - toast(`Incorrect data`); - } - }); - } - } else if (fileToSend) { - toast( - `file size ${fileToSend?.size} must be less then ${MAXSIZE_FOR_MESSAGE} mb.`, - ); - } - }, [fileToSend]); - - // const [isVoiceMessage, setVoiceMessage] = useState(true); const getMicrophonePermission = async () => { if (window) { try { @@ -747,80 +551,6 @@ const QuickBloxUIKitDesktopLayout: React.FC< return resultFile; }; - useEffect(() => { - const fileExt = 'mp4'; - - if (resultAudioBlob) { - const voiceMessage = blobToFile( - resultAudioBlob, - `${userName || ''}_voice_message.${fileExt}`, - ); - - setFileToSend(voiceMessage); - if (useAudioWidget) { - setUseAudioWidget(false); - } - // - } - }, [resultAudioBlob]); - - useEffect(() => { - // setFileToSend(null); - if (isRecording) { - if (!permission) { - // eslint-disable-next-line promise/catch-or-return,promise/always-return - getMicrophonePermission().catch(() => { - showErrorMessage(`Have no audio.`); - }); - } else { - // eslint-disable-next-line promise/catch-or-return,promise/always-return - startRecording().then(() => { - setWarningErrorText(`Your voice is recording during for 1 minutes`); - }); - } - } else { - if (permission && mediaRecorder.current) { - stopRecording(); - } - setWarningErrorText(''); - } - }, [isRecording]); - - useEffect(() => { - if (isRecording && permission) { - // eslint-disable-next-line promise/always-return,promise/catch-or-return - startRecording().then(() => { - setWarningErrorText(`Your voice is recording during for 1 minutes`); - }); - } - }, [permission]); - - useEffect(() => { - setWaitAIWidget(false); - if ( - defaultAIRephraseWidget?.textToContent && - defaultAIRephraseWidget?.textToContent.length > 0 - ) { - setMessageText(defaultAIRephraseWidget?.textToContent); - } - }, [defaultAIRephraseWidget?.textToContent]); - - useEffect(() => { - setWaitAIWidget(false); - }, [defaultAITranslateWidget?.textToContent]); - - useEffect(() => { - setWaitAIWidget(false); - if ( - defaultAIAssistWidget?.textToContent && - defaultAIAssistWidget?.textToContent.length > 0 - ) { - setMessageText(defaultAIAssistWidget?.textToContent); - } - }, [defaultAIAssistWidget?.textToContent]); - - // - function sendTextMessageActions(textToSend: string) { if (isOnline) { // closeReplyMessageFlowHandler @@ -850,29 +580,6 @@ const QuickBloxUIKitDesktopLayout: React.FC< } } } - // - useEffect(() => { - messagesViewModel.entity = dialogsViewModel.entity; - // setMessagesToView([]); - setMessageText(''); - }, [dialogsViewModel.entity]); - - // - useEffect(() => { - if (!isMobile && messagesViewModel.entity) { - dialogsViewModel.setWaitLoadingStatus(messagesViewModel?.loading); - const timeoutId = setTimeout(() => { - dialogsViewModel.setWaitLoadingStatus(false); // wait only for 3 sec - }, 3000); - - return () => clearTimeout(timeoutId); - } - - return () => { - // Placeholder: Cleanup handler is not required - }; - }, [messagesViewModel?.loading]); - // const ChangeFileHandler = (event: React.ChangeEvent) => { if (isOnline) { @@ -889,13 +596,6 @@ const QuickBloxUIKitDesktopLayout: React.FC< } }; - // - // - const maxWidthToResizing = - selectedDialog && needDialogInformation - ? '$message-view-container-wrapper-min-width' - : '1040px'; - const handleOnReply = (message: MessageEntity): void => { setMessagesToReply([message]); setShowReplyMessage(true); @@ -968,13 +668,107 @@ const QuickBloxUIKitDesktopLayout: React.FC< return sections; } - const [showDialogList, setShowDialogList] = useState(true); - const [showDialogMessages, setShowDialogMessages] = useState(true); - const [showDialogInformation, setShowDialogInformation] = - useState(false); + const handleHeightChange = (newHeight: number) => { + console.log('The new height is:', newHeight); + setClientHeight(newHeight); + }; + + const leaveDialogHandler = (dialog: DialogEntity) => { + if (isOnline) { + setDialogToLeave(dialog); + } + }; + + const handleDialogOnClick = () => { + if (isOpen) { + setDialogToLeave(undefined); + } + setIsOpen((state) => !state); + }; + + const handleLeaveDialog = () => { + if (dialogToLeave) { + dialogsViewModel + .deleteDialog(dialogToLeave as GroupDialogEntity) + .then((result) => { + // eslint-disable-next-line promise/always-return + if (!result) { + toast('Dialog have not been left'); + } + handleDialogOnClick(); + }) + .catch((e) => { + console.log(e); + toast("Can't leave dialog"); + }); + } + }; + // // eslint-disable-next-line react/prop-types,@typescript-eslint/no-unused-vars + // const defaultGetSenderName: GetUserNameFct = async (props: { + // userId?: number; + // sender?: UserEntity; + // }): Promise => { + // let result = 'undefined user'; // - const [isAllMembersShow, setIsAllMembersShow] = React.useState(false); + // // eslint-disable-next-line react/prop-types + // if (!props.sender) { + // // eslint-disable-next-line react/prop-types + // if (props.userId && props.userId > 0) { + // // eslint-disable-next-line react/prop-types,@typescript-eslint/no-unsafe-call + // const senderUser = await userViewModel.getUserById(props.userId); + // + // if (!senderUser) { + // return result; + // } + // result = + // senderUser.full_name || + // senderUser.login || + // senderUser.email || + // // eslint-disable-next-line @typescript-eslint/no-unsafe-call + // senderUser.id.toString(); + // } else return result; + // } else { + // result = + // // eslint-disable-next-line react/prop-types + // props.sender.full_name || + // // eslint-disable-next-line react/prop-types + // props.sender.login || + // // eslint-disable-next-line react/prop-types + // props.sender.email || + // // eslint-disable-next-line react/prop-types + // props.sender.id.toString(); + // } + // + // return result; + // }; + + const createDialogHandler = () => { + if (isOnline) { + newModal.toggleModal(); + } + }; + + useEffect(() => { + const codeVersion = '0.3.0'; + + console.log(`React UIKit CODE VERSION IS ${codeVersion}`); + if (isAuthProcessed()) { + const pagination: Pagination = new Pagination(); + dialogsViewModel?.getDialogs(pagination); + } + + return () => { + dialogsViewModel.release(); + }; + }, []); + useEffect(() => { + if (isAuthProcessed()) { + const pagination: Pagination = new Pagination(); + + dialogsViewModel?.getDialogs(pagination); + } + }, [currentContext.InitParams]); useEffect(() => { if (isMobile) { if (!selectedDialog) { @@ -999,16 +793,78 @@ const QuickBloxUIKitDesktopLayout: React.FC< setShowDialogInformation(true); } // - const sizeChangingLogString = `SIZE INFO: height: ${height.toString()} clientHeight: ${clientHeight} width: ${width.toString()} breakpont: ${breakpoint.toString()} isMobile: - ${isMobile?.toString()} selectedDialog: - ${selectedDialog ? 'true' : 'false'} showDialogMessages: - ${showDialogMessages?.toString()} showDialogList: - ${showDialogList?.toString()} showDialogInformation: - ${showDialogInformation?.toString()}`; - - console.log(sizeChangingLogString); + // const sizeChangingLogString = `SIZE INFO: height: ${height.toString()} clientHeight: ${clientHeight} width: ${width.toString()} breakpont: ${breakpoint.toString()} isMobile: + // ${isMobile?.toString()} selectedDialog: + // ${selectedDialog ? 'true' : 'false'} showDialogMessages: + // ${showDialogMessages?.toString()} showDialogList: + // ${showDialogList?.toString()} showDialogInformation: + // ${showDialogInformation?.toString()}`; + // + // console.log(sizeChangingLogString); }, [isMobile]); + useEffect(() => { + if (browserOnline) { + setIsOnline(true); + // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/ban-ts-comment + // @ts-ignore + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + toast.dismiss(toastConnectionErrorId.current); + } else { + setIsOnline(false); + // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/ban-ts-comment + // @ts-ignore + toastConnectionErrorId.current = toast('Connection ...', { + autoClose: false, + isLoading: true, + }); + } + }, [browserOnline && connectionStatus]); + useEffect(() => { + if (!isOnline) { + setNeedRefresh(true); + } + }, [isOnline]); + useEffect(() => { + if (isOnline && needRefresh) { + if (messagesViewModel.entity) { + messagesViewModel.getMessages(new Pagination(0, messagePerPage)); + + setNeedRefresh(false); + } + } + }, [isOnline]); + useEffect(() => { + getDialogPhotoFileForPreview(); + if (dialogsViewModel.entity) { + userViewModel.entity = dialogsViewModel.entity; + } + return () => { + if (dialogAvatarUrl) { + URL.revokeObjectURL(dialogAvatarUrl); + } + }; + }, [dialogsViewModel.entity]); + useEffect(() => { + console.log( + `Clear selected dialog: ${ + selectedDialog?.name || 'Dialog Name is empty' + }`, + ); + if (!dialogsViewModel.entity) { + setSelectedDialog(undefined); + } + }, [dialogsViewModel.entity]); + useEffect(() => { + messagesViewModel.entity = dialogsViewModel.entity; + // setMessagesToView([]); + setMessageText(''); + }, [dialogsViewModel.entity]); + useEffect(() => { + if (userViewModel.entity) { + userViewModel.getUsers(); + } + }, [userViewModel.entity]); useEffect(() => { if (selectedDialog && selectedDialog) { dialogsViewModel.entity = selectedDialog; @@ -1022,13 +878,124 @@ const QuickBloxUIKitDesktopLayout: React.FC< setShowDialogList(true); } }, [selectedDialog]); + useEffect(() => { + if (messagesViewModel.entity) { + messagesViewModel.getMessages(new Pagination(0, messagePerPage)); + } + }, [messagesViewModel.entity]); + useEffect(() => { + if (!isMobile && messagesViewModel.entity) { + dialogsViewModel.setWaitLoadingStatus(messagesViewModel?.loading); + const timeoutId = setTimeout(() => { + dialogsViewModel.setWaitLoadingStatus(false); // wait only for 3 sec + }, 3000); + + return () => clearTimeout(timeoutId); + } + return () => { + // Placeholder: Cleanup handler is not required + }; + }, [messagesViewModel?.loading]); useEffect(() => { - if (userViewModel.entity) { - userViewModel.getUsers(); + const MAXSIZE = maxFileSize || 90 * 1000000; + const MAXSIZE_FOR_MESSAGE = MAXSIZE / (1024 * 1024); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const flag = fileToSend?.size && fileToSend?.size < MAXSIZE; + + if (fileToSend?.size && fileToSend?.size < MAXSIZE) { + if (showReplyMessage && messagesToReply?.length > 0) { + const replyData: ReplyMessagesParams = { + messagesToReply, + relatedFileMessage: fileToSend, + relatedTextMessage: + messageText || MessageDTOMapper.REPLY_MESSAGE_PREFIX, + }; + + repliedActions(replyData); + } else if (isOnline) { + // eslint-disable-next-line promise/catch-or-return + messagesViewModel + .sendAttachmentMessage(fileToSend) + .then((resultOperation) => { + // eslint-disable-next-line promise/always-return + if (!resultOperation) { + toast(`Incorrect data`); + } + }); + } + } else if (fileToSend) { + toast( + `file size ${fileToSend?.size} must be less then ${MAXSIZE_FOR_MESSAGE} mb.`, + ); } - }, [userViewModel.entity]); + }, [fileToSend]); + useEffect(() => { + const fileExt = 'mp4'; + if (resultAudioBlob) { + const voiceMessage = blobToFile( + resultAudioBlob, + `${userName || ''}_voice_message.${fileExt}`, + ); + + setFileToSend(voiceMessage); + if (useAudioWidget) { + setUseAudioWidget(false); + } + // + } + }, [resultAudioBlob]); + useEffect(() => { + // setFileToSend(null); + if (isRecording) { + if (!permission) { + // eslint-disable-next-line promise/catch-or-return,promise/always-return + getMicrophonePermission().catch(() => { + showErrorMessage(`Have no audio.`); + }); + } else { + // eslint-disable-next-line promise/catch-or-return,promise/always-return + startRecording().then(() => { + setWarningErrorText(`Your voice is recording during for 1 minutes`); + }); + } + } else { + if (permission && mediaRecorder.current) { + stopRecording(); + } + setWarningErrorText(''); + } + }, [isRecording]); + useEffect(() => { + if (isRecording && permission) { + // eslint-disable-next-line promise/always-return,promise/catch-or-return + startRecording().then(() => { + setWarningErrorText(`Your voice is recording during for 1 minutes`); + }); + } + }, [permission]); + useEffect(() => { + setWaitAIWidget(false); + if ( + defaultAIRephraseWidget?.textToContent && + defaultAIRephraseWidget?.textToContent.length > 0 + ) { + setMessageText(defaultAIRephraseWidget?.textToContent); + } + }, [defaultAIRephraseWidget?.textToContent]); + useEffect(() => { + setWaitAIWidget(false); + }, [defaultAITranslateWidget?.textToContent]); + useEffect(() => { + setWaitAIWidget(false); + if ( + defaultAIAssistWidget?.textToContent && + defaultAIAssistWidget?.textToContent.length > 0 + ) { + setMessageText(defaultAIAssistWidget?.textToContent); + } + }, [defaultAIAssistWidget?.textToContent]); useEffect(() => { if (isMobile) { if (needDialogInformation) { @@ -1040,110 +1007,12 @@ const QuickBloxUIKitDesktopLayout: React.FC< } } }, [needDialogInformation]); - - const handleHeightChange = (newHeight: number) => { - console.log('The new height is:', newHeight); - setClientHeight(newHeight); - }; - const workHeight = isMobile - ? `calc(${height.toString()}px - ${uikitHeightOffset} - 28px)` - : `calc(100vh - ${uikitHeightOffset} - 28px)`; - - const [dialogToLeave, setDialogToLeave] = useState(); - const leaveDialogHandler = (dialog: DialogEntity) => { - if (isOnline) { - setDialogToLeave(dialog); - } - }; - - const [isOpen, setIsOpen] = useState(false); - - const handleDialogOnClick = () => { - if (isOpen) { - setDialogToLeave(undefined); - } - setIsOpen((state) => !state); - }; - useEffect(() => { if (dialogToLeave) { handleDialogOnClick(); } }, [dialogToLeave]); - const handleLeaveDialog = () => { - if (dialogToLeave) { - dialogsViewModel - .deleteDialog(dialogToLeave as GroupDialogEntity) - .then((result) => { - // eslint-disable-next-line promise/always-return - if (!result) { - toast('Dialog have not been left'); - } - handleDialogOnClick(); - }) - .catch((e) => { - console.log(e); - toast("Can't leave dialog"); - }); - } - }; - // eslint-disable-next-line react/prop-types,@typescript-eslint/no-unused-vars - const defaultGetSenderName: GetUserNameFct = async (props: { - userId?: number; - sender?: UserEntity; - }): Promise => { - let result = 'undefined user'; - - // eslint-disable-next-line react/prop-types - if (!props.sender) { - // eslint-disable-next-line react/prop-types - if (props.userId && props.userId > 0) { - // eslint-disable-next-line react/prop-types,@typescript-eslint/no-unsafe-call - const senderUser = await userViewModel.getUserById(props.userId); - - if (!senderUser) { - return result; - } - result = - senderUser.full_name || - senderUser.login || - senderUser.email || - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - senderUser.id.toString(); - } else return result; - } else { - result = - // eslint-disable-next-line react/prop-types - props.sender.full_name || - // eslint-disable-next-line react/prop-types - props.sender.login || - // eslint-disable-next-line react/prop-types - props.sender.email || - // eslint-disable-next-line react/prop-types - props.sender.id.toString(); - } - - return result; - }; - const messagesContainerMobileHeight = showReplyMessage - ? `calc(${clientHeight}px - 128px - 64px - 16px)` - : `calc(${clientHeight}px - 128px - 16px)`; - const messagesContainerHeight = showReplyMessage - ? `calc(${clientHeight}px - 128px - 64px)` - : `calc(${clientHeight}px - 128px - 1px)`; - const clientContainerHeight = `${clientHeight - 5}px`; - const headerHeight = 64; - const dialogListScrollableHeight = clientHeight - headerHeight - 6; - - const newModal = useModal(); - - const createDialogHandler = () => { - if (isOnline) { - newModal.toggleModal(); - } - }; - return (
diff --git a/src/QBconfig.ts b/src/QBconfig.ts index 4ccdc3c..e0217e6 100644 --- a/src/QBconfig.ts +++ b/src/QBconfig.ts @@ -1,9 +1,9 @@ export const QBConfig = { credentials: { - appId: 75949, - accountKey: 'uK_8uinNyz8-npTNB6tx', - authKey: 'DdS7zxMEm5Q7DaS', - authSecret: 'g88RhdOjnDOqFkv', + appId: -1, + accountKey: '', + authKey: '', + authSecret: '', sessionToken: '', }, configAIApi: { diff --git a/src/docs/Introduction.mdx b/src/docs/Introduction.mdx index 2c8c670..1123dbd 100644 --- a/src/docs/Introduction.mdx +++ b/src/docs/Introduction.mdx @@ -90,7 +90,7 @@ import { QBConfig } from './QBconfig'; // this line is new In order to enhance the organization and maintainability of your project, it is recommended to make changes to the structure of the App.tsx in the src folder. You need to add a constant called "currentUser" inside the App() function in the App.tsx file, which describes your user registered in the admin panel, and configure the QuickBloxUIKitProvider. Additionally, import the necessary entities from quickblox-react-ui-kit. -As a result, you should have the code below: +As a result, you should have the code like code below: ```ts import React from 'react';