From 61b04929f03b12ecbcb09158be89d08eb22a3183 Mon Sep 17 00:00:00 2001 From: Audric Ackermann <audric@loki.network> Date: Tue, 1 Jun 2021 16:01:59 +1000 Subject: [PATCH] show a spinner while default rooms are loading --- .../session/SessionJoinableDefaultRooms.tsx | 43 +++++++++++-------- ts/opengroup/opengroupV2/ApiUtil.ts | 5 ++- ts/state/ducks/defaultRooms.tsx | 30 ++++++++++--- 3 files changed, 52 insertions(+), 26 deletions(-) diff --git a/ts/components/session/SessionJoinableDefaultRooms.tsx b/ts/components/session/SessionJoinableDefaultRooms.tsx index 250b8aaf9..a5fe30f71 100644 --- a/ts/components/session/SessionJoinableDefaultRooms.tsx +++ b/ts/components/session/SessionJoinableDefaultRooms.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useEffect, useReducer, useState } from 'react'; +import React, { useEffect } from 'react'; import { useSelector } from 'react-redux'; import { joinOpenGroupV2WithUIEvents, @@ -11,6 +11,7 @@ import { Avatar, AvatarSize } from '../Avatar'; import { Flex } from '../basic/Flex'; import { PillContainer } from '../basic/PillContainer'; import { H3 } from '../basic/Text'; +import { SessionSpinner } from './SessionSpinner'; // tslint:disable: no-void-expression export type JoinableRoomProps = { @@ -83,29 +84,35 @@ const SessionJoinableRoomRow = (props: JoinableRoomProps) => { export const SessionJoinableRooms = () => { const joinableRooms = useSelector((state: StateType) => state.defaultRooms); - if (!joinableRooms?.length) { - window?.log?.info('no default joinable rooms yet'); + if (!joinableRooms.inProgress && !joinableRooms.rooms?.length) { + window?.log?.info('no default joinable rooms yet and not in progress'); return <></>; } + const componentToRender = joinableRooms.inProgress ? ( + <SessionSpinner loading={true} /> + ) : ( + joinableRooms.rooms.map(r => { + return ( + <SessionJoinableRoomRow + key={r.id} + completeUrl={r.completeUrl} + name={r.name} + roomId={r.id} + base64Data={r.base64Data} + onClick={completeUrl => { + void joinOpenGroupV2WithUIEvents(completeUrl, true, false); + }} + /> + ); + }) + ); + return ( <Flex container={true} flexGrow={1} flexDirection="column" width="93%"> <H3 text={window.i18n('orJoinOneOfThese')} /> - <Flex container={true} flexGrow={1} flexWrap="wrap"> - {joinableRooms.map(r => { - return ( - <SessionJoinableRoomRow - key={r.id} - completeUrl={r.completeUrl} - name={r.name} - roomId={r.id} - base64Data={r.base64Data} - onClick={completeUrl => { - void joinOpenGroupV2WithUIEvents(completeUrl, true, false); - }} - /> - ); - })} + <Flex container={true} flexGrow={1} flexWrap="wrap" justifyContent="center"> + {componentToRender} </Flex> </Flex> ); diff --git a/ts/opengroup/opengroupV2/ApiUtil.ts b/ts/opengroup/opengroupV2/ApiUtil.ts index c1c63be42..7f9f5f20c 100644 --- a/ts/opengroup/opengroupV2/ApiUtil.ts +++ b/ts/opengroup/opengroupV2/ApiUtil.ts @@ -3,7 +3,7 @@ import { FileServerV2Request } from '../../fileserver/FileServerApiV2'; import { PubKey } from '../../session/types'; import { allowOnlyOneAtATime } from '../../session/utils/Promise'; import { fromBase64ToArrayBuffer, fromHex } from '../../session/utils/String'; -import { updateDefaultRooms } from '../../state/ducks/defaultRooms'; +import { updateDefaultRooms, updateDefaultRoomsInProgress } from '../../state/ducks/defaultRooms'; import { getCompleteUrlFromRoom } from '../utils/OpenGroupUtils'; import { parseOpenGroupV2 } from './JoinOpenGroupV2'; import { getAllRoomInfos } from './OpenGroupAPIV2'; @@ -120,7 +120,10 @@ const loadDefaultRoomsSingle = () => * This call will only run once at a time. */ export const loadDefaultRooms = async () => { + window.inboxStore?.dispatch(updateDefaultRoomsInProgress(true)); const allRooms: Array<OpenGroupV2InfoJoinable> = await loadDefaultRoomsSingle(); + window.inboxStore?.dispatch(updateDefaultRoomsInProgress(false)); + if (allRooms !== undefined) { window.inboxStore?.dispatch(updateDefaultRooms(allRooms)); } diff --git a/ts/state/ducks/defaultRooms.tsx b/ts/state/ducks/defaultRooms.tsx index a6c74aecb..6803f6dc9 100644 --- a/ts/state/ducks/defaultRooms.tsx +++ b/ts/state/ducks/defaultRooms.tsx @@ -1,9 +1,15 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { OpenGroupV2InfoJoinable } from '../../opengroup/opengroupV2/ApiUtil'; -export type DefaultRoomsState = Array<OpenGroupV2InfoJoinable>; +export type DefaultRoomsState = { + rooms: Array<OpenGroupV2InfoJoinable>; + inProgress: boolean; +}; -const initialState: DefaultRoomsState = []; +const initialState: DefaultRoomsState = { + rooms: [], + inProgress: false, +}; /** * Payload to dispatch to update the base64 data of a default room @@ -21,12 +27,18 @@ const defaultRoomsSlice = createSlice({ initialState, reducers: { updateDefaultRooms(state, action) { - window?.log?.warn('updating default rooms', action.payload); - return action.payload as DefaultRoomsState; + window?.log?.info('updating default rooms', action.payload); + const rooms = action.payload as Array<OpenGroupV2InfoJoinable>; + return { ...state, rooms: rooms }; + }, + updateDefaultRoomsInProgress(state, action) { + const inProgress = action.payload as boolean; + window?.log?.info('fetching default rooms inProgress?', action.payload); + return { ...state, inProgress }; }, updateDefaultBase64RoomData(state, action: PayloadAction<Base64Update>) { const payload = action.payload; - const newState = state.map(room => { + const newRoomsState = state.rooms.map(room => { if (room.id === payload.roomId) { return { ...room, @@ -35,11 +47,15 @@ const defaultRoomsSlice = createSlice({ } return room; }); - return newState; + return { ...state, rooms: newRoomsState }; }, }, }); const { actions, reducer } = defaultRoomsSlice; -export const { updateDefaultRooms, updateDefaultBase64RoomData } = actions; +export const { + updateDefaultRooms, + updateDefaultBase64RoomData, + updateDefaultRoomsInProgress, +} = actions; export const defaultRoomReducer = reducer;