diff --git a/CHANGELOG.md b/CHANGELOG.md index beb6c981f8..ac4e850921 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ [unreleased] +* Better descriptions of the joining process + * Update custom deps repositiries (upload-s3-action, ipfs-pubsub-peer-monitor) * Add certificates validation. diff --git a/packages/backend/src/nest/connections-manager/connections-manager.service.ts b/packages/backend/src/nest/connections-manager/connections-manager.service.ts index 5784f38fc3..67fbce9027 100644 --- a/packages/backend/src/nest/connections-manager/connections-manager.service.ts +++ b/packages/backend/src/nest/connections-manager/connections-manager.service.ts @@ -419,6 +419,9 @@ export class ConnectionsManagerService extends EventEmitter implements OnModuleI private attachTorEventsListeners() { this.logger('attachTorEventsListeners') + this.tor.on(SocketActionTypes.CONNECTION_PROCESS_INFO, data => { + this.serverIoProvider.io.emit(SocketActionTypes.CONNECTION_PROCESS_INFO, data) + }) this.socketService.on(SocketActionTypes.CONNECTION_PROCESS_INFO, data => { this.serverIoProvider.io.emit(SocketActionTypes.CONNECTION_PROCESS_INFO, data) }) diff --git a/packages/backend/src/nest/socket/socket.service.ts b/packages/backend/src/nest/socket/socket.service.ts index b1218cb7ec..b8169ec131 100644 --- a/packages/backend/src/nest/socket/socket.service.ts +++ b/packages/backend/src/nest/socket/socket.service.ts @@ -154,7 +154,7 @@ export class SocketService extends EventEmitter implements OnModuleInit { await new Promise(resolve => setTimeout(() => resolve(), 2000)) - this.emit(SocketActionTypes.CONNECTION_PROCESS_INFO, ConnectionProcessInfo.WAITING_FOR_METADATA) + this.emit(SocketActionTypes.CONNECTION_PROCESS_INFO, ConnectionProcessInfo.CONNECTING_TO_COMMUNITY) }) socket.on(SocketActionTypes.REGISTER_OWNER_CERTIFICATE, async (payload: RegisterOwnerCertificatePayload) => { diff --git a/packages/backend/src/nest/tor/tor.service.ts b/packages/backend/src/nest/tor/tor.service.ts index be7183103e..ca8af5febc 100644 --- a/packages/backend/src/nest/tor/tor.service.ts +++ b/packages/backend/src/nest/tor/tor.service.ts @@ -5,7 +5,7 @@ import path from 'path' import getPort from 'get-port' import { removeFilesFromDir } from '../common/utils' import { EventEmitter } from 'events' -import { SocketActionTypes, SupportedPlatform } from '@quiet/types' +import { ConnectionProcessInfo, SocketActionTypes, SupportedPlatform } from '@quiet/types' import { Inject, OnModuleInit } from '@nestjs/common' import { ConfigOptions, ServerIoProviderTypes } from '../types' import { CONFIG_OPTIONS, QUIET_DIR, SERVER_IO_PROVIDER, TOR_PARAMS_PROVIDER, TOR_PASSWORD_PROVIDER } from '../const' @@ -227,6 +227,7 @@ export class Tor extends EventEmitter implements OnModuleInit { this.process.stdout.on('data', (data: any) => { this.logger(data.toString()) + const regexp = /Bootstrapped 0/ if (regexp.test(data.toString())) { this.spawnHiddenServices() diff --git a/packages/desktop/src/renderer/components/LoadingPanel/JoiningPanelComponent.test.tsx b/packages/desktop/src/renderer/components/LoadingPanel/JoiningPanelComponent.test.tsx index ed9b2927d0..83b3ac84a7 100644 --- a/packages/desktop/src/renderer/components/LoadingPanel/JoiningPanelComponent.test.tsx +++ b/packages/desktop/src/renderer/components/LoadingPanel/JoiningPanelComponent.test.tsx @@ -1,6 +1,7 @@ import React from 'react' import { renderComponent } from '../../testUtils/renderComponent' import JoiningPanelComponent from './JoiningPanelComponent' +import { ConnectionProcessInfo } from '@quiet/types' describe('Create JoiningPanelComponent', () => { it('renders component - owner false', () => { @@ -10,7 +11,7 @@ describe('Create JoiningPanelComponent', () => { openUrl={jest.fn()} open={true} isOwner={false} - torConnectionInfo={{ number: 50, text: 'Initializing storage' }} + connectionInfo={{ number: 50, text: ConnectionProcessInfo.BACKEND_MODULES }} /> ) expect(result.baseElement).toMatchInlineSnapshot(` @@ -70,7 +71,7 @@ describe('Create JoiningPanelComponent', () => { style="width: 600px;" >
{
+

- Initializing storage + Initialized backend modules

{ openUrl={jest.fn()} open={true} isOwner={true} - torConnectionInfo={{ number: 50, text: 'Initializing storage' }} + connectionInfo={{ number: 50, text: ConnectionProcessInfo.BACKEND_MODULES }} /> ) expect(result.baseElement).toMatchInlineSnapshot(` @@ -204,7 +208,7 @@ describe('Create JoiningPanelComponent', () => { style="width: 600px;" >

{
+

- Initializing storage + Initialized backend modules

({ @@ -67,14 +70,31 @@ const StyledGrid = styled(Grid)(({ theme, width }) => ({ overflow: 'hidden', marginBottom: '8px', }, - [`& .${classes.progress}`]: { + '@keyframes width': { + from: { width: '150px' }, + to: { width: '300px' }, + }, + [`& .${classes.animatedProgress}`]: { + animationName: 'width', + animationDuration: '4s', + animationTimingFunction: 'linear', + animationIterationCount: 'infinite', + transition: '3s all', backgroundColor: theme.palette.colors.lushSky, + position: 'absolute', + zIndex: 1, + height: '4px', + }, + [`& .${classes.progress}`]: { + backgroundColor: theme.palette.colors.blue, width: width, height: '4px', position: 'relative', + zIndex: 2, }, [`& .${classes.progressBarWrapper}`]: { - // margin: '16px 0 40px' + // margin: '16px 0 40px', + margin: '16px 0 20px', }, })) @@ -83,7 +103,7 @@ export interface JoiningPanelComponentProps { open: boolean handleClose: () => void openUrl: (url: string) => void - torConnectionInfo: { number: number; text: string } + connectionInfo: { number: number; text: ConnectionProcessInfo } isOwner: boolean } @@ -91,12 +111,12 @@ const JoiningPanelComponent: React.FC = ({ open, handleClose, openUrl, - torConnectionInfo, + connectionInfo, isOwner, }) => { return ( - + = ({

+ +
- {torConnectionInfo.text} + {connectionInfo.text}
diff --git a/packages/desktop/src/renderer/components/LoadingPanel/LoadingPanel.stories.tsx b/packages/desktop/src/renderer/components/LoadingPanel/LoadingPanel.stories.tsx index 96f55f7118..1107935fab 100644 --- a/packages/desktop/src/renderer/components/LoadingPanel/LoadingPanel.stories.tsx +++ b/packages/desktop/src/renderer/components/LoadingPanel/LoadingPanel.stories.tsx @@ -3,6 +3,7 @@ import { ComponentStory, ComponentMeta } from '@storybook/react' import { withTheme } from '../../storybook/decorators' import JoiningPanelComponent, { JoiningPanelComponentProps } from './JoiningPanelComponent' import StartingPanelComponent, { StartingPanelComponentProps } from './StartingPanelComponent' +import { ConnectionProcessInfo } from '@quiet/types' const JoiningPanelTemplate: ComponentStory = args => { return @@ -18,7 +19,7 @@ const JoiningPanelArgs: JoiningPanelComponentProps = { open: true, handleClose: function (): void {}, openUrl: () => console.log('OpenURL'), - torConnectionInfo: { number: 10, text: 'Fetching' }, + connectionInfo: { number: 10, text: ConnectionProcessInfo.BACKEND_MODULES }, isOwner: false, } const StartingPanelArgs: StartingPanelComponentProps = { diff --git a/packages/desktop/src/renderer/components/LoadingPanel/LoadingPanel.tsx b/packages/desktop/src/renderer/components/LoadingPanel/LoadingPanel.tsx index 2fa62e7088..ff8caee4b3 100644 --- a/packages/desktop/src/renderer/components/LoadingPanel/LoadingPanel.tsx +++ b/packages/desktop/src/renderer/components/LoadingPanel/LoadingPanel.tsx @@ -3,7 +3,7 @@ import { useDispatch, useSelector } from 'react-redux' import { useModal } from '../../containers/hooks' import { ModalName } from '../../sagas/modals/modals.types' import { socketSelectors } from '../../sagas/socket/socket.selectors' -import { communities, publicChannels, users, identity, connection, network, errors } from '@quiet/state-manager' +import { communities, publicChannels, users, connection, network, errors } from '@quiet/state-manager' import { modalsActions } from '../../sagas/modals/modals.slice' import { shell } from 'electron' import JoiningPanelComponent from './JoiningPanelComponent' @@ -16,38 +16,23 @@ const LoadingPanel = () => { const loadingPanelModal = useModal(ModalName.loadingPanel) const isConnected = useSelector(socketSelectors.isConnected) - const currentCommunity = useSelector(communities.selectors.currentCommunity) const isChannelReplicated = Boolean(useSelector(publicChannels.selectors.publicChannels)?.length > 0) - - const currentChannelDisplayableMessages = useSelector(publicChannels.selectors.currentChannelMessagesMergedBySender) - const community = useSelector(communities.selectors.currentCommunity) const owner = Boolean(community?.CA) const usersData = Object.keys(useSelector(users.selectors.certificates)) const isOnlyOneUser = usersData.length === 1 + const connectionProcessSelector = useSelector(connection.selectors.connectionProcess) + const isJoiningCompletedSelector = useSelector(connection.selectors.isJoiningCompleted) - const torBootstrapProcessSelector = useSelector(connection.selectors.torBootstrapProcess) - const torConnectionProcessSelector = useSelector(connection.selectors.torConnectionProcess) - - const communityId = useSelector(communities.selectors.currentCommunityId) - const initializedCommunities = useSelector(network.selectors.initializedCommunities) - const isCommunityInitialized = Boolean(initializedCommunities[communityId]) const error = useSelector(errors.selectors.registrarErrors) const registrationError = error?.code === ErrorCodes.FORBIDDEN useEffect(() => { - const areMessagesLoaded = Object.values(currentChannelDisplayableMessages).length > 0 - console.log('HUNTING for haisenbug:') - console.log('isConnected', isConnected) - console.log('communityId', communityId) - console.log('isCommunityInitialized', isCommunityInitialized) - console.log('areMessagesLoaded?', areMessagesLoaded) - console.log('registrationError', registrationError) - if ((isConnected && isCommunityInitialized && areMessagesLoaded) || registrationError) { + if (isJoiningCompletedSelector || registrationError) { loadingPanelModal.handleClose() } - }, [isConnected, torBootstrapProcessSelector, isCommunityInitialized, currentChannelDisplayableMessages, error]) + }, [isJoiningCompletedSelector, error]) useEffect(() => { if (isConnected) { @@ -77,7 +62,7 @@ const LoadingPanel = () => { ) diff --git a/packages/mobile/src/components/ChannelList/ChannelList.test.tsx b/packages/mobile/src/components/ChannelList/ChannelList.test.tsx index 9b58a3d646..7c022bae10 100644 --- a/packages/mobile/src/components/ChannelList/ChannelList.test.tsx +++ b/packages/mobile/src/components/ChannelList/ChannelList.test.tsx @@ -1,5 +1,4 @@ import React from 'react' - import { renderComponent } from '../../utils/functions/renderComponent/renderComponent' import { ChannelList } from './ChannelList.component' diff --git a/packages/mobile/src/components/ConnectionProcess/ConnectionProcess.component.tsx b/packages/mobile/src/components/ConnectionProcess/ConnectionProcess.component.tsx index 042cb6826c..e696ceaec8 100644 --- a/packages/mobile/src/components/ConnectionProcess/ConnectionProcess.component.tsx +++ b/packages/mobile/src/components/ConnectionProcess/ConnectionProcess.component.tsx @@ -5,6 +5,7 @@ import { Typography } from '../Typography/Typography.component' import { ConnectionProcessComponentProps } from './ConnectionProcess.types' import JoinCommunityImg from '../../../assets/icons/join-community.png' import { Site } from '@quiet/common' +import { ConnectionProcessInfo } from '@quiet/types' const ConnectionProcessComponent: FC = ({ connectionProcess, openUrl }) => { const animationValue = useRef(new Animated.Value(0)).current @@ -25,6 +26,28 @@ const ConnectionProcessComponent: FC = ({ conne outputRange: ['0deg', '360deg'], }) + const processAnimation = useRef(new Animated.Value(0)).current + + useEffect(() => { + if (connectionProcess.text === ConnectionProcessInfo.CONNECTING_TO_COMMUNITY) { + Animated.loop( + Animated.timing(processAnimation, { + toValue: 1, + duration: 6000, + easing: Easing.linear, + useNativeDriver: false, + }) + ).start() + } else { + processAnimation.stopAnimation() + } + }, [processAnimation, connectionProcess]) + + const processAnimationWidth = processAnimation.interpolate({ + inputRange: [0, 1], + outputRange: [150, 300], + }) + return ( = ({ conne Joining now! - + + + {connectionProcess.text === ConnectionProcessInfo.CONNECTING_TO_COMMUNITY && ( + + )} ( console.log('open')} /> diff --git a/packages/mobile/src/components/ConnectionProcess/ConnectionProcess.test.tsx b/packages/mobile/src/components/ConnectionProcess/ConnectionProcess.test.tsx index aa7ce33a0b..bfb2a28158 100644 --- a/packages/mobile/src/components/ConnectionProcess/ConnectionProcess.test.tsx +++ b/packages/mobile/src/components/ConnectionProcess/ConnectionProcess.test.tsx @@ -85,17 +85,21 @@ describe('ConnectionProcessComponent', () => { "backgroundColor": "#F0F0F0", "borderRadius": 4, "height": 4, + "position": "relative", "width": 300, + "zIndex": 1, } } > diff --git a/packages/mobile/src/components/ConnectionProcess/ConnectionProcess.types.ts b/packages/mobile/src/components/ConnectionProcess/ConnectionProcess.types.ts index 537899221e..9c790b13e2 100644 --- a/packages/mobile/src/components/ConnectionProcess/ConnectionProcess.types.ts +++ b/packages/mobile/src/components/ConnectionProcess/ConnectionProcess.types.ts @@ -1,4 +1,6 @@ +import { ConnectionProcessInfo } from '@quiet/types' + export interface ConnectionProcessComponentProps { - connectionProcess: { number: number; text: string } + connectionProcess: { number: number; text: ConnectionProcessInfo } openUrl: (url: string) => void } diff --git a/packages/mobile/src/screens/ConnectionProcess/ConnectionProcess.screen.tsx b/packages/mobile/src/screens/ConnectionProcess/ConnectionProcess.screen.tsx index 06a1d5a4e1..ea8c617616 100644 --- a/packages/mobile/src/screens/ConnectionProcess/ConnectionProcess.screen.tsx +++ b/packages/mobile/src/screens/ConnectionProcess/ConnectionProcess.screen.tsx @@ -1,5 +1,5 @@ import React, { FC, useCallback, useEffect } from 'react' -import { communities, connection, ErrorCodes, errors, publicChannels, users } from '@quiet/state-manager' +import { connection, ErrorCodes, errors } from '@quiet/state-manager' import { useDispatch, useSelector } from 'react-redux' import ConnectionProcessComponent from '../../components/ConnectionProcess/ConnectionProcess.component' import { Linking } from 'react-native' @@ -9,17 +9,10 @@ import { ScreenNames } from '../../const/ScreenNames.enum' export const ConnectionProcessScreen: FC = () => { const dispatch = useDispatch() - const connectionProcessSelector = useSelector(connection.selectors.torConnectionProcess) - const error = useSelector(errors.selectors.registrarErrors) - - const community = useSelector(communities.selectors.currentCommunity) - const isOwner = Boolean(community?.CA) - - const channelsStatusSorted = useSelector(publicChannels.selectors.channelsStatusSorted) - const messageNotNull = channelsStatusSorted.filter(channel => channel.newestMessage !== undefined) + const connectionProcessSelector = useSelector(connection.selectors.connectionProcess) + const isJoiningCompletedSelector = useSelector(connection.selectors.isJoiningCompleted) - const certificatesMapping = useSelector(users.selectors.certificatesMapping) - const channels = useSelector(publicChannels.selectors.publicChannels) + const error = useSelector(errors.selectors.registrarErrors) const openUrl = useCallback((url: string) => { void Linking.openURL(url) @@ -36,17 +29,14 @@ export const ConnectionProcessScreen: FC = () => { }, [error, dispatch]) useEffect(() => { - const areChannelsLoaded = channels.length > 0 - const areCertificatesLoaded = Object.values(certificatesMapping).length > 0 - const isAllDataLoaded = areChannelsLoaded && areCertificatesLoaded - console.log({ areChannelsLoaded, areCertificatesLoaded }) - if (isOwner ? connectionProcessSelector.number == 85 : isAllDataLoaded && messageNotNull.length !== 0) { + if (isJoiningCompletedSelector) { dispatch( navigationActions.replaceScreen({ screen: ScreenNames.ChannelListScreen, }) ) } - }, [connectionProcessSelector, messageNotNull, certificatesMapping, channels]) + }, [isJoiningCompletedSelector]) + return } diff --git a/packages/mobile/src/store/init/deepLink/deepLink.saga.test.ts b/packages/mobile/src/store/init/deepLink/deepLink.saga.test.ts index e6218b7de9..2fa8e09743 100644 --- a/packages/mobile/src/store/init/deepLink/deepLink.saga.test.ts +++ b/packages/mobile/src/store/init/deepLink/deepLink.saga.test.ts @@ -217,7 +217,7 @@ describe('deepLinkSaga', () => { store.dispatch(communities.actions.setCurrentCommunity(community.id)) - store.dispatch(connection.actions.setTorConnectionProcess(ConnectionProcessInfo.REGISTERING_USER_CERTIFICATE)) + store.dispatch(connection.actions.setConnectionProcess(ConnectionProcessInfo.REGISTERING_USER_CERTIFICATE)) const reducer = combineReducers(reducers) await expectSaga(deepLinkSaga, initActions.deepLink(validCode)) diff --git a/packages/mobile/src/tests/joining.process.test.tsx b/packages/mobile/src/tests/joining.process.test.tsx index 2a400b9ca5..a4055017f2 100644 --- a/packages/mobile/src/tests/joining.process.test.tsx +++ b/packages/mobile/src/tests/joining.process.test.tsx @@ -52,16 +52,15 @@ describe('Joining process', () => { expect(connectionProcessScreen).toBeVisible() const processText = screen.getByTestId('connection-process-text') - expect(processText.props.children).toEqual('Connecting process started') + expect(processText.props.children).toEqual(ConnectionProcessInfo.CONNECTION_STARTED) - store.dispatch(connection.actions.setTorConnectionProcess(ConnectionProcessInfo.INITIALIZING_LIBP2P)) + store.dispatch(connection.actions.setConnectionProcess(ConnectionProcessInfo.INITIALIZING_IPFS)) await act(async () => {}) const processText2 = screen.getByTestId('connection-process-text') console.log(processText2.props) - expect(processText2.props.children).toEqual('Initializing libp2p') + expect(processText2.props.children).toEqual(ConnectionProcessInfo.BACKEND_MODULES) - store.dispatch(connection.actions.setTorConnectionProcess(ConnectionProcessInfo.LAUNCHED_COMMUNITY)) await act(async () => {}) const channelList = screen.getByTestId('channels_list') diff --git a/packages/state-manager/src/sagas/appConnection/connection.helpers.ts b/packages/state-manager/src/sagas/appConnection/connection.helpers.ts index ab7f754cac..7d715d6e03 100644 --- a/packages/state-manager/src/sagas/appConnection/connection.helpers.ts +++ b/packages/state-manager/src/sagas/appConnection/connection.helpers.ts @@ -1,17 +1,17 @@ -import { TOR_BOOTSTRAP_COMPLETE } from '@quiet/types' +import { ConnectionProcessInfo, TOR_BOOTSTRAP_COMPLETE } from '@quiet/types' export function resetStateAndSaveTorConnectionData() { const torBootstrapProcess = TOR_BOOTSTRAP_COMPLETE - const torConnectionProcess = { + const connectionProcess = { number: 5, - text: 'Connecting process started', + text: ConnectionProcessInfo.CONNECTION_STARTED, } const freshState = { Connection: { torBootstrapProcess, - torConnectionProcess, + connectionProcess, peerStats: { ids: [], entities: {} }, }, } diff --git a/packages/state-manager/src/sagas/appConnection/connection.selectors.ts b/packages/state-manager/src/sagas/appConnection/connection.selectors.ts index fdd6536512..a1ef6a371b 100644 --- a/packages/state-manager/src/sagas/appConnection/connection.selectors.ts +++ b/packages/state-manager/src/sagas/appConnection/connection.selectors.ts @@ -1,13 +1,14 @@ import { StoreKeys } from '../store.keys' import { createSelector } from 'reselect' import { type CreatedSelectors, type StoreState } from '../store.types' -import { allUsers } from '../users/users.selectors' +import { allUsers, areCertificatesLoaded } from '../users/users.selectors' import { communitiesSelectors } from '../communities/communities.selectors' import { peersStatsAdapter } from './connection.adapter' -import { connectedPeers } from '../network/network.selectors' +import { connectedPeers, isCurrentCommunityInitialized } from '../network/network.selectors' import { type NetworkStats } from './connection.types' import { type User } from '../users/users.types' import { filterAndSortPeers } from '@quiet/common' +import { areMessagesLoaded, areChannelsLoaded } from '../publicChannels/publicChannels.selectors' const connectionSlice: CreatedSelectors[StoreKeys.Connection] = (state: StoreState) => state[StoreKeys.Connection] @@ -17,7 +18,7 @@ export const torBootstrapProcess = createSelector(connectionSlice, reducerState export const isTorInitialized = createSelector(connectionSlice, reducerState => reducerState.isTorInitialized) -export const torConnectionProcess = createSelector(connectionSlice, reducerState => reducerState.torConnectionProcess) +export const connectionProcess = createSelector(connectionSlice, reducerState => reducerState.connectionProcess) export const socketIOSecret = createSelector(connectionSlice, reducerState => reducerState.socketIOSecret) @@ -54,12 +55,24 @@ export const connectedPeersMapping = createSelector(allUsers, connectedPeers, (c }, {}) }) +export const isJoiningCompleted = createSelector( + isCurrentCommunityInitialized, + areMessagesLoaded, + areChannelsLoaded, + areCertificatesLoaded, + (isCommunity, areMessages, areChannels, areCertificates) => { + console.log({ isCommunity, areMessages, areChannels, areCertificates }) + return isCommunity && areMessages && areChannels && areCertificates + } +) + export const connectionSelectors = { lastConnectedTime, connectedPeersMapping, peerList, torBootstrapProcess, - torConnectionProcess, + connectionProcess, isTorInitialized, socketIOSecret, + isJoiningCompleted, } diff --git a/packages/state-manager/src/sagas/appConnection/connection.slice.test.ts b/packages/state-manager/src/sagas/appConnection/connection.slice.test.ts index a76e85df88..b4d17f971c 100644 --- a/packages/state-manager/src/sagas/appConnection/connection.slice.test.ts +++ b/packages/state-manager/src/sagas/appConnection/connection.slice.test.ts @@ -3,16 +3,23 @@ import { connectionSelectors } from './connection.selectors' import { connectionActions } from './connection.slice' import { type identityActions } from '../identity/identity.slice' import { prepareStore } from '../../utils/tests/prepareStore' -import { getFactory } from '../../utils/tests/factories' + import { setupCrypto } from '@quiet/identity' import { networkActions } from '../network/network.slice' -import { networkSelectors } from '../network/network.selectors' -import { type Identity } from '@quiet/types' +import { initializedCommunities, networkSelectors } from '../network/network.selectors' +import { Community, ConnectionProcessInfo, PublicChannel, type Identity, ChannelMessage } from '@quiet/types' import { usersSelectors } from '../users/users.selectors' +import { communitiesSelectors } from '../communities/communities.selectors' +import { communitiesActions } from '../communities/communities.slice' +import { publicChannelsSelectors } from '../publicChannels/publicChannels.selectors' +import { generateMessageFactoryContentWithId, getFactory, publicChannels } from '../..' describe('connectionReducer', () => { let store: Store let alice: Identity + let community: Community + let generalChannel: PublicChannel + let generalChannelId: string beforeEach(async () => { setupCrypto() @@ -24,6 +31,20 @@ describe('connectionReducer', () => { alice = await factory.create['payload']>('Identity', { nickname: 'alice', }) + + community = await factory.create['payload']>('Community') + + const generalChannelState = publicChannelsSelectors.generalChannel(store.getState()) + if (generalChannelState) generalChannel = generalChannelState + expect(generalChannel).not.toBeUndefined() + expect(generalChannel).toBeDefined() + generalChannelId = generalChannel?.id || '' + + await factory.create['payload']>('Message', { + identity: alice, + message: generateMessageFactoryContentWithId(generalChannelId), + verifyAutomatically: true, + }) }) it('add initialized communities should add correctly data into the store', () => { @@ -87,19 +108,29 @@ describe('connectionReducer', () => { expect(torBootstrapInfo).toEqual(expectedTorBootstrapInfo) }) - it('setTorConnectionProcess', () => { - const payload1 = 'Initializing storage' + it('set connectionProcess', () => { + const payload2 = ConnectionProcessInfo.INITIALIZING_IPFS - store.dispatch(connectionActions.setTorConnectionProcess(payload1)) + store.dispatch(connectionActions.setConnectionProcess(payload2)) - const payload2 = 'Initializing IPFS' + const { number, text } = connectionSelectors.connectionProcess(store.getState()) - store.dispatch(connectionActions.setTorConnectionProcess(payload2)) + expect(number).toEqual(30) + + expect(text).toEqual(ConnectionProcessInfo.BACKEND_MODULES) + }) + + it('isJoiningCompleted - false', async () => { + const isJoiningCompleted = connectionSelectors.isJoiningCompleted(store.getState()) + + expect(isJoiningCompleted).toBeFalsy() + }) - const { number, text } = connectionSelectors.torConnectionProcess(store.getState()) + it('isJoiningCompleted - true', async () => { + store.dispatch(networkActions.addInitializedCommunity('1')) - expect(number).toEqual(70) + const isJoiningCompleted = connectionSelectors.isJoiningCompleted(store.getState()) - expect(text).toEqual(payload2) + expect(isJoiningCompleted).toBeFalsy() }) }) diff --git a/packages/state-manager/src/sagas/appConnection/connection.slice.ts b/packages/state-manager/src/sagas/appConnection/connection.slice.ts index 9cec6a30b4..a49ccc5a11 100644 --- a/packages/state-manager/src/sagas/appConnection/connection.slice.ts +++ b/packages/state-manager/src/sagas/appConnection/connection.slice.ts @@ -10,9 +10,9 @@ export class ConnectionState { public isTorInitialized = false public socketIOSecret: string | null = null public torBootstrapProcess = 'Bootstrapped 0% (starting)' - public torConnectionProcess: { number: number; text: string } = { + public connectionProcess: { number: number; text: ConnectionProcessInfo } = { number: 5, - text: 'Connecting process started', + text: ConnectionProcessInfo.CONNECTION_STARTED, } } @@ -51,48 +51,25 @@ export const connectionSlice = createSlice({ setSocketIOSecret: (state, action: PayloadAction) => { state.socketIOSecret = action.payload }, - - setTorConnectionProcess: (state, action: PayloadAction) => { + setConnectionProcess: (state, action: PayloadAction) => { const info = action.payload + switch (info) { - case ConnectionProcessInfo.CONNECTING_TO_COMMUNITY: - state.torConnectionProcess = { number: 20, text: info } - break case ConnectionProcessInfo.REGISTERING_OWNER_CERTIFICATE: - state.torConnectionProcess = { number: 20, text: info } - break - case ConnectionProcessInfo.LAUNCHING_COMMUNITY: - state.torConnectionProcess = { number: 30, text: info } - break - case ConnectionProcessInfo.SPAWNING_HIDDEN_SERVICE: - state.torConnectionProcess = { number: 40, text: info } - break - case ConnectionProcessInfo.INITIALIZING_LIBP2P: - state.torConnectionProcess = { number: 50, text: info } - break - case ConnectionProcessInfo.INITIALIZING_STORAGE: - state.torConnectionProcess = { number: 60, text: info } + state.connectionProcess = { number: 50, text: ConnectionProcessInfo.REGISTERING_OWNER_CERTIFICATE } break case ConnectionProcessInfo.INITIALIZING_IPFS: - state.torConnectionProcess = { number: 70, text: info } - break - case ConnectionProcessInfo.LOADED_CERTIFICATES: - state.torConnectionProcess = { number: 75, text: info } - break - case ConnectionProcessInfo.INITIALIZED_DBS: - state.torConnectionProcess = { number: 80, text: info } + if (state.connectionProcess.number > 30) break + state.connectionProcess = { number: 30, text: ConnectionProcessInfo.BACKEND_MODULES } break - case ConnectionProcessInfo.LAUNCHED_COMMUNITY: - state.torConnectionProcess = { number: 85, text: info } - break - case ConnectionProcessInfo.WAITING_FOR_METADATA: - state.torConnectionProcess = { number: 87, text: info } - break - case ConnectionProcessInfo.CHANNELS_REPLICATED: - state.torConnectionProcess = { number: 90, text: info } + case ConnectionProcessInfo.CONNECTING_TO_COMMUNITY: + if (state.connectionProcess.number == 50) break + state.connectionProcess = { number: 50, text: ConnectionProcessInfo.CONNECTING_TO_COMMUNITY } break - case ConnectionProcessInfo.CERTIFICATES_REPLICATED: - state.torConnectionProcess = { number: 95, text: info } + case ConnectionProcessInfo.CHANNELS_REPLICATED || ConnectionProcessInfo.CERTIFICATES_REPLICATED: + let number = 90 + if (state.connectionProcess.number == 90) number = 95 + state.connectionProcess = { number, text: ConnectionProcessInfo.LOADING_MESSAGES } break } }, diff --git a/packages/state-manager/src/sagas/appConnection/connection.transform.ts b/packages/state-manager/src/sagas/appConnection/connection.transform.ts index 30d188af12..b211ca4cce 100644 --- a/packages/state-manager/src/sagas/appConnection/connection.transform.ts +++ b/packages/state-manager/src/sagas/appConnection/connection.transform.ts @@ -1,6 +1,7 @@ import { createTransform } from 'redux-persist' import { StoreKeys } from '../store.keys' import { type ConnectionState } from './connection.slice' +import { ConnectionProcessInfo } from '@quiet/types' export const ConnectionTransform = createTransform( (inboundState: ConnectionState, _key: any) => { @@ -10,9 +11,9 @@ export const ConnectionTransform = createTransform( return { ...outboundState, torBootstrapProcess: 'Bootstrapped 0% (starting)', - torConnectionProcess: { + connectionProcess: { number: 5, - text: 'Connecting process started', + text: ConnectionProcessInfo.CONNECTION_STARTED, }, isTorInitialized: false, socketIOSecret: null, diff --git a/packages/state-manager/src/sagas/network/network.selectors.ts b/packages/state-manager/src/sagas/network/network.selectors.ts index 12c4919c73..796e9174fb 100644 --- a/packages/state-manager/src/sagas/network/network.selectors.ts +++ b/packages/state-manager/src/sagas/network/network.selectors.ts @@ -15,9 +15,7 @@ export const initializedCommunities = createSelector(networkSlice, reducerState export const isCurrentCommunityInitialized = createSelector( initializedCommunities, currentCommunity, - (initializedCommunities, currentCommunity) => { - return currentCommunity && initializedCommunities[currentCommunity.id] - } + (initializedCommunities, currentCommunity) => currentCommunity && initializedCommunities[currentCommunity.id] ) export const connectedPeers = createSelector(networkSlice, reducerState => { diff --git a/packages/state-manager/src/sagas/publicChannels/publicChannels.selectors.ts b/packages/state-manager/src/sagas/publicChannels/publicChannels.selectors.ts index 580d4f1ed1..d775d2dd22 100644 --- a/packages/state-manager/src/sagas/publicChannels/publicChannels.selectors.ts +++ b/packages/state-manager/src/sagas/publicChannels/publicChannels.selectors.ts @@ -262,6 +262,13 @@ export const unreadChannels = createSelector(channelsStatus, status => { }, []) }) +export const areMessagesLoaded = createSelector( + currentChannelMessagesMergedBySender, + currentChannelMessages => Object.values(currentChannelMessages).length > 0 +) + +export const areChannelsLoaded = createSelector(publicChannels, channels => channels.length > 0) + export const publicChannelsSelectors = { publicChannels, subscribedChannels, @@ -283,4 +290,6 @@ export const publicChannelsSelectors = { pendingGeneralChannelRecreation, generalChannel, getChannelById, + areMessagesLoaded, + areChannelsLoaded, } diff --git a/packages/state-manager/src/sagas/socket/const/actionTypes.ts b/packages/state-manager/src/sagas/socket/const/actionTypes.ts index 3a8044322a..b5e8e9a3c5 100644 --- a/packages/state-manager/src/sagas/socket/const/actionTypes.ts +++ b/packages/state-manager/src/sagas/socket/const/actionTypes.ts @@ -73,7 +73,7 @@ export enum SocketActionTypes { SUBSCRIBE_FOR_DIRECT_MESSAGE_THREAD = 'subscribeToDirectMessageThread', // T TOR_INITIALIZED = 'torInitialized', - CONNECTION_PROCESS_INFO = 'torConnectionProcess', + CONNECTION_PROCESS_INFO = 'connectionProcess', // U UPDATE_MESSAGE_MEDIA = 'updateMessageMedia', UPLOAD_FILE = 'uploadFile', diff --git a/packages/state-manager/src/sagas/socket/startConnection/startConnection.saga.ts b/packages/state-manager/src/sagas/socket/startConnection/startConnection.saga.ts index 55d7ffeaba..23675bd82d 100644 --- a/packages/state-manager/src/sagas/socket/startConnection/startConnection.saga.ts +++ b/packages/state-manager/src/sagas/socket/startConnection/startConnection.saga.ts @@ -43,6 +43,7 @@ import { type SendOwnerCertificatePayload, CommunityMetadata, SendCsrsResponse, + ConnectionProcessInfo, } from '@quiet/types' const log = logger('socket') @@ -86,7 +87,7 @@ export function subscribe(socket: Socket) { | ReturnType | ReturnType | ReturnType - | ReturnType + | ReturnType | ReturnType | ReturnType | ReturnType @@ -100,7 +101,7 @@ export function subscribe(socket: Socket) { emit(connectionActions.setTorInitialized()) }) socket.on(SocketActionTypes.CONNECTION_PROCESS_INFO, (payload: string) => { - emit(connectionActions.setTorConnectionProcess(payload)) + emit(connectionActions.setConnectionProcess(payload)) }) // Misc socket.on(SocketActionTypes.PEER_CONNECTED, (payload: { peers: string[] }) => { diff --git a/packages/state-manager/src/sagas/users/users.selectors.ts b/packages/state-manager/src/sagas/users/users.selectors.ts index 059c053e3b..6971cb57e2 100644 --- a/packages/state-manager/src/sagas/users/users.selectors.ts +++ b/packages/state-manager/src/sagas/users/users.selectors.ts @@ -160,6 +160,11 @@ export const duplicateCerts = createSelector(certificatesMapping, certs => { return Boolean(allUsernames.length !== uniqueUsernames.length) }) +export const areCertificatesLoaded = createSelector( + certificatesMapping, + certificates => Object.values(certificates).length > 0 +) + export const usersSelectors = { csrs, certificates, @@ -170,4 +175,5 @@ export const usersSelectors = { allUsers, duplicateCerts, getUserByPubKey, + areCertificatesLoaded, } diff --git a/packages/types/src/connection.ts b/packages/types/src/connection.ts index 541ff28fd1..60e00d6224 100644 --- a/packages/types/src/connection.ts +++ b/packages/types/src/connection.ts @@ -16,11 +16,7 @@ export interface NetworkStats { } export enum ConnectionProcessInfo { - CONNECTING_TO_COMMUNITY = 'Connecting to community owner via Tor', REGISTERING_USER_CERTIFICATE = 'Registering user certificate', - // SAVING_USER_CSR = 'Saving user csr', - WAITING_FOR_METADATA = 'Waiting for metadata', - REGISTERING_OWNER_CERTIFICATE = 'Registering owner certificate', LAUNCHING_COMMUNITY = 'Launching community', SPAWNING_HIDDEN_SERVICE = 'Spawning hidden service for community', INITIALIZING_STORAGE = 'Initializing storage', @@ -32,6 +28,12 @@ export enum ConnectionProcessInfo { LAUNCHED_COMMUNITY = 'Launched community', CHANNELS_REPLICATED = 'Channels replicated', CERTIFICATES_REPLICATED = 'Certificates replicated', + + CONNECTION_STARTED = 'Connecting process started', + LOADING_MESSAGES = 'Loading messages', + BACKEND_MODULES = 'Initialized backend modules', + REGISTERING_OWNER_CERTIFICATE = 'Registering owner certificate', + CONNECTING_TO_COMMUNITY = 'Connecting to community members via Tor', } export const TOR_BOOTSTRAP_COMPLETE = 'Bootstrapped 100% (done)' diff --git a/packages/types/src/socket.ts b/packages/types/src/socket.ts index 3612a77a9a..72306ef583 100644 --- a/packages/types/src/socket.ts +++ b/packages/types/src/socket.ts @@ -67,7 +67,7 @@ export enum SocketActionTypes { SUBSCRIBE_FOR_DIRECT_MESSAGE_THREAD = 'subscribeToDirectMessageThread', // T TOR_INITIALIZED = 'torInitialized', - CONNECTION_PROCESS_INFO = 'torConnectionProcess', + CONNECTION_PROCESS_INFO = 'connectionProcess', // U UPDATE_MESSAGE_MEDIA = 'updateMessageMedia', UPLOAD_FILE = 'uploadFile',