support resyncing conversations

This commit is contained in:
Roland Osborne 2022-07-14 15:38:20 -07:00
parent 2f5a6ae241
commit d7f8c0bbd9
4 changed files with 32 additions and 9 deletions

View File

@ -1,8 +1,8 @@
import React, { useState, useEffect, useRef } from 'react' import React, { useState, useEffect, useRef } from 'react'
import { ExclamationCircleOutlined, CloseOutlined, UserOutlined } from '@ant-design/icons'; import { ExclamationCircleOutlined, CloseOutlined, UserOutlined } from '@ant-design/icons';
import { useConversation } from './useConversation.hook'; import { useConversation } from './useConversation.hook';
import { Button, Input, Checkbox, Modal, Spin } from 'antd' import { Button, Input, Checkbox, Modal, Spin, Tooltip } from 'antd'
import { ConversationWrapper, ConversationButton, EditButton, CloseButton, ListItem, BusySpin } from './Conversation.styled'; import { ConversationWrapper, ConversationButton, EditButton, CloseButton, ListItem, BusySpin, Offsync } from './Conversation.styled';
import { AutoSizer, CellMeasurer, CellMeasurerCache, List } from 'react-virtualized'; import { AutoSizer, CellMeasurer, CellMeasurerCache, List } from 'react-virtualized';
import { AddTopic } from './AddTopic/AddTopic'; import { AddTopic } from './AddTopic/AddTopic';
import { VirtualList } from 'VirtualList/VirtualList'; import { VirtualList } from 'VirtualList/VirtualList';
@ -82,6 +82,13 @@ export function Conversation() {
<Icon /> <Icon />
<div class="subject">{ subject }</div> <div class="subject">{ subject }</div>
<Edit /> <Edit />
{ state.error && (
<Tooltip placement="right" title="sync failed: click to retry">
<Offsync onClick={() => {actions.resync()}}>
<ExclamationCircleOutlined />
</Offsync>
</Tooltip>
)}
</div> </div>
<div class="control"> <div class="control">
<div class="buttons"> <div class="buttons">

View File

@ -103,3 +103,9 @@ export const BusySpin = styled(Spin)`
left: calc(50% - 16px); left: calc(50% - 16px);
top: calc(50% - 16px); top: calc(50% - 16px);
`; `;
export const Offsync = styled.div`
padding-left: 8px;
color: #ff8888;
cursor: pointer;
`

View File

@ -36,6 +36,9 @@ export function useConversation() {
}, },
more: () => { more: () => {
conversation.actions.addHistory(); conversation.actions.addHistory();
},
resync: () => {
conversation.actions.resync();
} }
}; };
@ -60,6 +63,7 @@ export function useConversation() {
cardId: conversation.state.cardId, cardId: conversation.state.cardId,
channelId: conversation.state.channelId, channelId: conversation.state.channelId,
members: conversation.state.members, members: conversation.state.members,
error: conversation.state.error,
topics, topics,
}); });
if (conversation.state.init) { if (conversation.state.init) {

View File

@ -8,6 +8,7 @@ export function useConversationContext() {
const [state, setState] = useState({ const [state, setState] = useState({
init: false, init: false,
error: false,
loading: false, loading: false,
cardId: null, cardId: null,
channelId: null, channelId: null,
@ -21,6 +22,7 @@ export function useConversationContext() {
const EVENT_OPEN = 1; const EVENT_OPEN = 1;
const EVENT_MORE = 2; const EVENT_MORE = 2;
const EVENT_UPDATE = 3; const EVENT_UPDATE = 3;
const EVENT_RESYNC = 4;
const events = useRef([]); const events = useRef([]);
const channelView = useRef({ const channelView = useRef({
@ -181,7 +183,7 @@ export function useConversationContext() {
channelView.current.begin = delta.marker; channelView.current.begin = delta.marker;
} }
} }
else if (ev.type == EVENT_UPDATE) { else if (ev.type == EVENT_UPDATE || ev.type == EVENT_RESYNC) {
let deltaRevision = getChannelRevision(); let deltaRevision = getChannelRevision();
if (channelView.current.init && deltaRevision != channelView.current.revision) { if (channelView.current.init && deltaRevision != channelView.current.revision) {
let delta = await getTopicDelta(channelView.current.revision, null, channelView.current.begin, null); let delta = await getTopicDelta(channelView.current.revision, null, channelView.current.begin, null);
@ -197,6 +199,7 @@ export function useConversationContext() {
let members = getMembers(chan); let members = getMembers(chan);
updateState({ updateState({
init: true, init: true,
error: false,
subject, subject,
contacts, contacts,
members, members,
@ -206,9 +209,10 @@ export function useConversationContext() {
} }
} }
catch (err) { catch (err) {
if (!channelView.current.error) { console.log(err);
window.alert("This converstaion failed to update"); updateState({ error: true });
channelView.current.error = true; if (ev.type == EVENT_RESYNC) {
window.alert("failed to syncrhonize conversation");
} }
} }
} }
@ -248,14 +252,12 @@ export function useConversationContext() {
const actions = { const actions = {
setConversationId: (cardId, channelId) => { setConversationId: (cardId, channelId) => {
view.current += 1; view.current += 1;
updateState({ init: false, loading: true }); updateState({ init: false, loading: true });
events.current = [{ type: EVENT_OPEN, data: { cardId, channelId }}]; events.current = [{ type: EVENT_OPEN, data: { cardId, channelId }}];
updateState({ subject: null, cardId, channelId, topics: new Map() }); updateState({ subject: null, cardId, channelId, topics: new Map() });
topics.current = new Map(); topics.current = new Map();
updateConversation(); updateConversation();
}, },
addHistory: () => { addHistory: () => {
updateState({ loading: true }); updateState({ loading: true });
@ -306,6 +308,10 @@ export function useConversationContext() {
else { else {
return await channel.actions.setChannelTopicSubject(channelId, topicId, data); return await channel.actions.setChannelTopicSubject(channelId, topicId, data);
} }
},
resync: () => {
events.current.push({ type: EVENT_RESYNC });
updateConversation();
} }
} }