2022-04-28 18:30:54 +00:00
|
|
|
import { useEffect, useState, useRef, useContext } from 'react';
|
|
|
|
import { CardContext } from 'context/CardContext';
|
|
|
|
import { ChannelContext } from 'context/ChannelContext';
|
|
|
|
|
|
|
|
export function useConversationContext() {
|
2023-01-09 23:15:30 +00:00
|
|
|
const COUNT = 32;
|
2022-04-28 18:30:54 +00:00
|
|
|
|
|
|
|
const [state, setState] = useState({
|
2023-01-09 23:15:30 +00:00
|
|
|
offsync: false,
|
2022-04-28 18:30:54 +00:00
|
|
|
topics: new Map(),
|
2023-01-26 07:26:40 +00:00
|
|
|
card: null,
|
2023-01-09 23:15:30 +00:00
|
|
|
channel: null,
|
2023-01-18 07:42:22 +00:00
|
|
|
topicRevision: null,
|
2022-07-10 07:33:50 +00:00
|
|
|
});
|
|
|
|
|
2022-04-28 18:30:54 +00:00
|
|
|
const card = useContext(CardContext);
|
|
|
|
const channel = useContext(ChannelContext);
|
2023-01-09 23:15:30 +00:00
|
|
|
|
|
|
|
const reset = useRef(false);
|
|
|
|
const loadMore = useRef(false);
|
|
|
|
const force = useRef(false);
|
|
|
|
const syncing = useRef(false);
|
|
|
|
const marker = useRef(null);
|
|
|
|
const setTopicRevision = useRef(null);
|
|
|
|
const curTopicRevision = useRef(null);
|
|
|
|
const setDetailRevision = useRef(null);
|
|
|
|
const curDetailRevision = useRef(null);
|
|
|
|
const conversationId = useRef(null);
|
2022-04-28 18:30:54 +00:00
|
|
|
const topics = useRef(new Map());
|
|
|
|
|
2023-01-10 21:16:13 +00:00
|
|
|
const updateState = (value) => {
|
|
|
|
setState((s) => ({ ...s, ...value }))
|
|
|
|
}
|
2022-04-28 18:30:54 +00:00
|
|
|
|
2023-01-09 23:15:30 +00:00
|
|
|
const getTopicDelta = async (cardId, channelId, revision, count, begin, end) => {
|
|
|
|
if (cardId) {
|
2023-01-10 21:16:13 +00:00
|
|
|
return await card.actions.getTopics(cardId, channelId, revision, count, begin, end);
|
2022-12-15 21:57:36 +00:00
|
|
|
}
|
2023-01-10 21:16:13 +00:00
|
|
|
return await channel.actions.getTopics(channelId, revision, count, begin, end);
|
2022-12-15 21:57:36 +00:00
|
|
|
}
|
|
|
|
|
2023-01-09 23:15:30 +00:00
|
|
|
const getTopic = async (cardId, channelId, topicId) => {
|
|
|
|
if (cardId) {
|
2023-01-10 21:16:13 +00:00
|
|
|
return await card.actions.getTopic(cardId, channelId, topicId);
|
2022-07-11 07:19:59 +00:00
|
|
|
}
|
2023-01-10 21:16:13 +00:00
|
|
|
return await channel.actions.getTopic(channelId, topicId);
|
2023-01-09 23:15:30 +00:00
|
|
|
}
|
2022-07-11 07:19:59 +00:00
|
|
|
|
2023-01-09 23:15:30 +00:00
|
|
|
const removeChannel = async (cardId, channelId) => {
|
|
|
|
if (cardId) {
|
|
|
|
await card.actions.removeChannel(cardId, channelId);
|
|
|
|
await card.actions.resync();
|
2022-05-13 07:15:15 +00:00
|
|
|
}
|
2022-12-15 18:41:54 +00:00
|
|
|
else {
|
2023-01-09 23:15:30 +00:00
|
|
|
await channel.actions.removeChannel(channelId);
|
|
|
|
await channel.actions.resync();
|
2022-07-11 07:19:59 +00:00
|
|
|
}
|
2023-01-09 23:15:30 +00:00
|
|
|
};
|
2022-07-11 07:19:59 +00:00
|
|
|
|
2023-01-09 23:15:30 +00:00
|
|
|
const setChannelSubject = async (cardId, channelId, type, subject) => {
|
|
|
|
if (cardId) {
|
|
|
|
console.log('cannot update channel subject');
|
2022-05-13 07:15:15 +00:00
|
|
|
}
|
2023-01-09 23:15:30 +00:00
|
|
|
else {
|
|
|
|
await channel.actions.setChannelSubject(channelId, type, subject);
|
2022-05-13 07:15:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-10 07:16:11 +00:00
|
|
|
const setChannelCard = async (cardId, channelId, id) => {
|
2023-01-09 23:15:30 +00:00
|
|
|
if (cardId) {
|
|
|
|
console.log('cannot update channel card');
|
2022-05-23 22:10:33 +00:00
|
|
|
}
|
2023-01-09 23:15:30 +00:00
|
|
|
else {
|
2023-01-10 07:16:11 +00:00
|
|
|
await channel.actions.setChannelCard(channelId, id);
|
2023-01-09 23:15:30 +00:00
|
|
|
await channel.actions.resync();
|
2022-05-23 22:10:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-10 07:16:11 +00:00
|
|
|
const clearChannelCard = async (cardId, channelId, id) => {
|
2022-07-10 07:33:50 +00:00
|
|
|
if (cardId) {
|
2023-01-09 23:15:30 +00:00
|
|
|
console.log('cannot update channel card');
|
2022-07-10 07:33:50 +00:00
|
|
|
}
|
2023-01-09 23:15:30 +00:00
|
|
|
else {
|
2023-01-10 07:16:11 +00:00
|
|
|
await channel.actions.clearChannelCard(channelId, id);
|
2023-01-12 18:14:37 +00:00
|
|
|
await channel.actions.resync();
|
2023-01-09 23:15:30 +00:00
|
|
|
}
|
|
|
|
};
|
2022-07-10 07:33:50 +00:00
|
|
|
|
2023-01-09 23:15:30 +00:00
|
|
|
const addTopic = async (cardId, channelId, type, message, files) => {
|
2022-07-10 07:33:50 +00:00
|
|
|
if (cardId) {
|
2023-01-09 23:15:30 +00:00
|
|
|
await card.actions.addTopic(cardId, channelId, type, message, files);
|
2022-07-10 07:33:50 +00:00
|
|
|
}
|
2023-01-09 23:15:30 +00:00
|
|
|
else {
|
|
|
|
await channel.actions.addTopic(channelId, type, message, files);
|
|
|
|
}
|
2023-01-26 07:26:40 +00:00
|
|
|
resync();
|
2023-01-09 23:15:30 +00:00
|
|
|
};
|
2022-05-02 07:49:11 +00:00
|
|
|
|
2023-01-09 23:15:30 +00:00
|
|
|
const removeTopic = async (cardId, channelId, topicId) => {
|
2022-04-28 18:30:54 +00:00
|
|
|
if (cardId) {
|
2023-01-09 23:15:30 +00:00
|
|
|
await card.actions.removeTopic(cardId, channelId, topicId);
|
2022-07-10 07:33:50 +00:00
|
|
|
}
|
2023-01-09 23:15:30 +00:00
|
|
|
else {
|
|
|
|
await channel.actions.removeTopic(channelId, topicId);
|
|
|
|
}
|
|
|
|
await resync();
|
|
|
|
};
|
2022-07-10 07:33:50 +00:00
|
|
|
|
2023-01-27 00:01:35 +00:00
|
|
|
const setTopicSubject = async (cardId, channelId, topicId, type, subject) => {
|
2022-07-10 07:33:50 +00:00
|
|
|
if (cardId) {
|
2023-01-27 00:01:35 +00:00
|
|
|
await card.actions.setTopicSubject(cardId, channelId, topicId, type, subject);
|
2022-07-10 07:33:50 +00:00
|
|
|
}
|
2023-01-09 23:15:30 +00:00
|
|
|
else {
|
2023-01-27 00:01:35 +00:00
|
|
|
await channel.actions.setTopicSubject(channelId, topicId, type, subject);
|
2023-01-09 23:15:30 +00:00
|
|
|
}
|
|
|
|
await resync();
|
|
|
|
};
|
2022-07-10 07:33:50 +00:00
|
|
|
|
2023-01-26 07:26:40 +00:00
|
|
|
const getTopicAssetUrl = (cardId, channelId, topicId, assetId) => {
|
2023-01-09 23:15:30 +00:00
|
|
|
if (cardId) {
|
|
|
|
return card.actions.getTopicAssetUrl(cardId, channelId, topicId, assetId);
|
2022-04-28 18:30:54 +00:00
|
|
|
}
|
2023-01-09 23:15:30 +00:00
|
|
|
else {
|
|
|
|
return channel.actions.getTopicAssetUrl(channelId, topicId, assetId);
|
|
|
|
}
|
|
|
|
};
|
2022-07-10 07:33:50 +00:00
|
|
|
|
2023-01-10 21:16:13 +00:00
|
|
|
const setChannelRevision = (cardId, channelId) => {
|
|
|
|
let setChannel;
|
|
|
|
if (cardId) {
|
|
|
|
const setCard = card.state.cards.get(cardId);
|
|
|
|
setChannel = setCard?.channels.get(channelId);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
setChannel = channel.state.channels.get(channelId);
|
|
|
|
}
|
|
|
|
if (setChannel) {
|
|
|
|
const { topicRevision, detailRevision } = setChannel.data;
|
|
|
|
if (curTopicRevision.current !== topicRevision || curDetailRevision.current !== detailRevision) {
|
|
|
|
curTopicRevision.current = topicRevision;
|
|
|
|
curDetailRevision.current = detailRevision;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
console.log('conversation not found');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-10 07:16:11 +00:00
|
|
|
const resync = async () => {
|
2022-07-10 07:33:50 +00:00
|
|
|
try {
|
2023-01-09 23:15:30 +00:00
|
|
|
force.current = true;
|
|
|
|
await sync();
|
2022-07-10 07:33:50 +00:00
|
|
|
}
|
|
|
|
catch (err) {
|
2022-07-14 22:38:20 +00:00
|
|
|
console.log(err);
|
2022-04-28 18:30:54 +00:00
|
|
|
}
|
2023-01-09 23:15:30 +00:00
|
|
|
};
|
2022-04-28 18:30:54 +00:00
|
|
|
|
2023-01-09 23:15:30 +00:00
|
|
|
const sync = async () => {
|
|
|
|
if (!syncing.current && (reset.current || force.current || loadMore.current ||
|
|
|
|
setDetailRevision.current !== curDetailRevision.current || setTopicRevision.current !== curTopicRevision.current)) {
|
|
|
|
|
|
|
|
const more = loadMore.current;
|
|
|
|
const update = force.current;
|
|
|
|
const topicRevision = more ? setTopicRevision.current : curTopicRevision.current;
|
|
|
|
const detailRevision = curDetailRevision.current;
|
|
|
|
|
|
|
|
syncing.current = true;
|
|
|
|
force.current = false;
|
|
|
|
loadMore.current = false;
|
|
|
|
|
|
|
|
if (reset.current) {
|
|
|
|
reset.current = false;
|
|
|
|
marker.current = null;
|
|
|
|
setTopicRevision.current = null;
|
|
|
|
setDetailRevision.current = null;
|
|
|
|
topics.current = new Map();
|
|
|
|
updateState({ offsync: false, channel: null, topics: new Map() });
|
|
|
|
}
|
2022-04-28 18:30:54 +00:00
|
|
|
|
2023-01-10 21:16:13 +00:00
|
|
|
if (conversationId.current) {
|
|
|
|
const { cardId, channelId } = conversationId.current;
|
2022-07-11 07:19:59 +00:00
|
|
|
|
2023-01-09 23:15:30 +00:00
|
|
|
// sync channel details
|
|
|
|
if (setDetailRevision.current !== detailRevision) {
|
|
|
|
let channelSync;
|
2023-01-26 07:26:40 +00:00
|
|
|
let cardSync;
|
2023-01-10 21:16:13 +00:00
|
|
|
if (cardId) {
|
2023-01-26 07:26:40 +00:00
|
|
|
cardSync = card.state.cards.get(cardId);
|
2023-01-10 21:16:13 +00:00
|
|
|
channelSync = cardSync?.channels.get(channelId);
|
2023-01-09 23:15:30 +00:00
|
|
|
}
|
|
|
|
else {
|
2023-01-10 21:16:13 +00:00
|
|
|
channelSync = channel.state.channels.get(channelId);
|
2023-01-09 23:15:30 +00:00
|
|
|
}
|
|
|
|
if (channelSync) {
|
|
|
|
setDetailRevision.current = detailRevision;
|
2023-01-26 07:26:40 +00:00
|
|
|
updateState({ card: cardSync, channel: channelSync });
|
2022-07-11 07:19:59 +00:00
|
|
|
}
|
|
|
|
else {
|
2023-01-19 05:28:00 +00:00
|
|
|
syncing.current = false;
|
2023-01-09 23:15:30 +00:00
|
|
|
console.log("converstaion not found");
|
2023-01-19 05:28:00 +00:00
|
|
|
return;
|
2022-07-11 07:19:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-09 23:15:30 +00:00
|
|
|
try {
|
|
|
|
// sync channel topics
|
|
|
|
if (update || more || setTopicRevision.current !== topicRevision) {
|
|
|
|
let delta;
|
|
|
|
if (!marker.current) {
|
2023-01-10 21:16:13 +00:00
|
|
|
delta = await getTopicDelta(cardId, channelId, null, COUNT, null, null);
|
2023-01-09 23:15:30 +00:00
|
|
|
}
|
|
|
|
else if (more) {
|
2023-01-10 21:16:13 +00:00
|
|
|
delta = await getTopicDelta(cardId, channelId, null, COUNT, null, marker.current);
|
2023-01-09 23:15:30 +00:00
|
|
|
}
|
|
|
|
else {
|
2023-01-25 18:56:43 +00:00
|
|
|
delta = await getTopicDelta(cardId, channelId, setTopicRevision.current, null, marker.current, null);
|
2023-01-09 23:15:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (let topic of delta?.topics) {
|
|
|
|
if (topic.data == null) {
|
|
|
|
topics.current.delete(topic.id);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
let cur = topics.current.get(topic.id);
|
|
|
|
if (cur == null) {
|
|
|
|
cur = { id: topic.id, data: {} };
|
|
|
|
}
|
|
|
|
if (topic.data.detailRevision !== cur.data.detailRevision) {
|
|
|
|
if(topic.data.topicDetail) {
|
|
|
|
cur.data.topicDetail = topic.data.topicDetail;
|
|
|
|
cur.data.detailRevision = topic.data.detailRevision;
|
|
|
|
}
|
|
|
|
else {
|
2023-01-10 21:16:13 +00:00
|
|
|
const slot = await getTopic(cardId, channelId, topic.id);
|
2023-01-09 23:15:30 +00:00
|
|
|
cur.data.topicDetail = slot.data.topicDetail;
|
|
|
|
cur.data.detailRevision = slot.data.detailRevision;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cur.revision = topic.revision;
|
|
|
|
topics.current.set(topic.id, cur);
|
|
|
|
}
|
|
|
|
}
|
2023-01-10 23:35:57 +00:00
|
|
|
|
2023-01-25 18:56:43 +00:00
|
|
|
marker.current = delta.marker ? delta.marker : marker.current;
|
2023-01-09 23:15:30 +00:00
|
|
|
setTopicRevision.current = topicRevision;
|
2023-01-25 18:56:43 +00:00
|
|
|
|
2023-01-18 07:42:22 +00:00
|
|
|
updateState({ offsync: false, topicRevision: topicRevision, topics: topics.current });
|
2023-01-09 23:15:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (err) {
|
|
|
|
console.log(err);
|
|
|
|
updateState({ offsync: true });
|
2023-01-10 21:16:13 +00:00
|
|
|
syncing.current = false;
|
|
|
|
return;
|
2023-01-09 23:15:30 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 06:49:02 +00:00
|
|
|
syncing.current = false;
|
|
|
|
await sync();
|
|
|
|
}
|
2022-04-28 18:30:54 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-01-12 18:14:37 +00:00
|
|
|
useEffect(() => {
|
|
|
|
if (conversationId.current) {
|
|
|
|
const { cardId, channelId } = conversationId.current;
|
|
|
|
setChannelRevision(cardId, channelId);
|
|
|
|
sync();
|
|
|
|
}
|
|
|
|
// eslint-disable-next-line
|
|
|
|
}, [card.state, channel.state]);
|
|
|
|
|
2022-04-28 18:30:54 +00:00
|
|
|
const actions = {
|
2023-01-09 23:15:30 +00:00
|
|
|
setChannel: async (cardId, channelId) => {
|
|
|
|
conversationId.current = { cardId, channelId };
|
2023-01-10 21:16:13 +00:00
|
|
|
setChannelRevision(cardId, channelId);
|
2023-01-09 23:15:30 +00:00
|
|
|
reset.current = true;
|
|
|
|
await sync();
|
2022-07-10 07:33:50 +00:00
|
|
|
},
|
2023-01-09 23:15:30 +00:00
|
|
|
clearChannel: async () => {
|
|
|
|
conversationId.current = null;
|
2023-01-11 06:49:02 +00:00
|
|
|
curDetailRevision.current = null;
|
|
|
|
curTopicRevision.current = null;
|
2023-01-09 23:15:30 +00:00
|
|
|
reset.current = true;
|
|
|
|
await sync();
|
2022-05-02 07:49:11 +00:00
|
|
|
},
|
2023-01-09 23:15:30 +00:00
|
|
|
removeChannel: async () => {
|
|
|
|
const { cardId, channelId } = conversationId.current;
|
|
|
|
await removeChannel(cardId, channelId);
|
|
|
|
},
|
|
|
|
setChannelSubject: async (type, subject) => {
|
|
|
|
const { cardId, channelId } = conversationId.current;
|
|
|
|
await setChannelSubject(cardId, channelId, type, subject);
|
2022-05-15 18:04:27 +00:00
|
|
|
},
|
2023-01-10 07:16:11 +00:00
|
|
|
setChannelCard: async (id) => {
|
2023-01-09 23:15:30 +00:00
|
|
|
const { cardId, channelId } = conversationId.current;
|
2023-01-10 07:16:11 +00:00
|
|
|
await setChannelCard(cardId, channelId, id);
|
2022-05-24 22:21:12 +00:00
|
|
|
},
|
2023-01-10 07:16:11 +00:00
|
|
|
clearChannelCard: async (id) => {
|
2023-01-09 23:15:30 +00:00
|
|
|
const { cardId, channelId } = conversationId.current;
|
2023-01-10 07:16:11 +00:00
|
|
|
await clearChannelCard(cardId, channelId, id);
|
2022-05-24 22:21:12 +00:00
|
|
|
},
|
2023-01-09 23:15:30 +00:00
|
|
|
addTopic: async (type, message, files) => {
|
|
|
|
const { cardId, channelId } = conversationId.current;
|
|
|
|
await addTopic(cardId, channelId, type, message, files);
|
2022-05-12 06:33:00 +00:00
|
|
|
},
|
2023-01-09 23:15:30 +00:00
|
|
|
removeTopic: async (topicId) => {
|
|
|
|
const { cardId, channelId } = conversationId.current;
|
|
|
|
await removeTopic(cardId, channelId, topicId);
|
2022-05-12 06:33:00 +00:00
|
|
|
},
|
2023-01-27 00:01:35 +00:00
|
|
|
setTopicSubject: async (topicId, type, subject) => {
|
2023-01-09 23:15:30 +00:00
|
|
|
const { cardId, channelId } = conversationId.current;
|
2023-01-27 00:01:35 +00:00
|
|
|
await setTopicSubject(cardId, channelId, topicId, type, subject);
|
2022-12-15 21:57:36 +00:00
|
|
|
},
|
2023-01-26 07:26:40 +00:00
|
|
|
getTopicAssetUrl: (assetId, topicId) => {
|
2023-01-09 23:15:30 +00:00
|
|
|
const { cardId, channelId } = conversationId.current;
|
2023-01-10 07:16:11 +00:00
|
|
|
return getTopicAssetUrl(cardId, channelId, topicId, assetId);
|
2022-05-26 22:19:58 +00:00
|
|
|
},
|
2023-01-09 23:15:30 +00:00
|
|
|
loadMore: async () => {
|
|
|
|
loadMore.current = true;
|
2023-01-11 18:13:40 +00:00
|
|
|
await sync();
|
|
|
|
},
|
|
|
|
resync: async () => {
|
|
|
|
force.current = true;
|
|
|
|
await sync();
|
2022-12-16 20:02:12 +00:00
|
|
|
},
|
2022-04-28 18:30:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return { state, actions }
|
|
|
|
}
|
|
|
|
|
|
|
|
|