console.log('edit')}>
+ { !sealed && topic.creator && (
+
actions.setEditing(topic.text)}>
)}
@@ -101,9 +118,27 @@ export function TopicItem({ host, topic, remove }) {
)}
>
)}
-
+ { sealed && (
+
sealed message
+ )}
+ { !sealed && !state.editing && (
+
+ )}
+ { state.editing && (
+
+
actions.setMessage(e.target.value)} rows={3} bordered={false}/>
+
+
+
+
+
+
+
+ )}
>
)}
diff --git a/net/web/src/session/conversation/topicItem/TopicItem.styled.js b/net/web/src/session/conversation/topicItem/TopicItem.styled.js
index 99c0da3d..3b50a130 100644
--- a/net/web/src/session/conversation/topicItem/TopicItem.styled.js
+++ b/net/web/src/session/conversation/topicItem/TopicItem.styled.js
@@ -88,6 +88,7 @@ export const TopicItemWrapper = styled.div`
.sealed-message {
font-style: italic;
color: #aaaaaa;
+ padding-left: 72px;
}
.asset-placeholder {
@@ -103,6 +104,7 @@ export const TopicItemWrapper = styled.div`
.topic-assets {
padding-top: 4px;
+ padding-bottom: 4px;
}
.skeleton {
@@ -116,23 +118,24 @@ export const TopicItemWrapper = styled.div`
padding-left: 72px;
white-space: pre-line;
min-height: 4px;
+ }
- .editing {
+ .editing {
+ display: flex;
+ flex-direction: column;
+ border-radius: 4px;
+ border: 1px solid #aaaaaa;
+ margin-top: 8px;
+ margin-bottom: 8px;
+ margin-right: 16px;
+ margin-left: 72px;
+
+ .controls {
display: flex;
- flex-direction: column;
- border-radius: 4px;
- border: 1px solid #aaaaaa;
- width: 100%;
- margin-top: 8px;
- margin-bottom: 8px;
-
- .controls {
- display: flex;
- flex-direction: row;
- justify-content: flex-end;
- padding-bottom: 8px;
- padding-right: 8px;
- }
+ flex-direction: row;
+ justify-content: flex-end;
+ padding-bottom: 8px;
+ padding-right: 8px;
}
}
`;
diff --git a/net/web/src/session/conversation/topicItem/useTopicItem.hook.js b/net/web/src/session/conversation/topicItem/useTopicItem.hook.js
new file mode 100644
index 00000000..9cb1d2fd
--- /dev/null
+++ b/net/web/src/session/conversation/topicItem/useTopicItem.hook.js
@@ -0,0 +1,28 @@
+import { useEffect, useState } from 'react';
+
+export function useTopicItem() {
+
+ const [state, setState] = useState({
+ editing: false,
+ message: null,
+ });
+
+ const updateState = (value) => {
+ setState((s) => ({ ...s, ...value }));
+ }
+
+ const actions = {
+ setEditing: (message) => {
+ updateState({ editing: true, message });
+ },
+ clearEditing: () => {
+ updateState({ editing: false });
+ },
+ setMessage: (message) => {
+ updateState({ message });
+ },
+ };
+
+ return { state, actions };
+}
+
diff --git a/net/web/src/session/conversation/useConversation.hook.js b/net/web/src/session/conversation/useConversation.hook.js
index e895240c..491a8055 100644
--- a/net/web/src/session/conversation/useConversation.hook.js
+++ b/net/web/src/session/conversation/useConversation.hook.js
@@ -6,7 +6,7 @@ import { UploadContext } from 'context/UploadContext';
import { StoreContext } from 'context/StoreContext';
import { CardContext } from 'context/CardContext';
import { ProfileContext } from 'context/ProfileContext';
-import { isUnsealed, getChannelSeals, getContentKey } from 'context/sealUtil';
+import { isUnsealed, getChannelSeals, getContentKey, encryptTopicSubject } from 'context/sealUtil';
import { JSEncrypt } from 'jsencrypt'
import { decryptTopicSubject } from 'context/sealUtil';
@@ -23,6 +23,7 @@ export function useConversation(cardId, channelId) {
loading: false,
sealed: false,
contentKey: null,
+ busy: false,
});
const profile = useContext(ProfileContext);
@@ -120,7 +121,17 @@ export function useConversation(cardId, channelId) {
// eslint-disable-next-line
}, [cardId, channelId]);
- const syncTopic = async (item, value) => {
+ useEffect(() => {
+ syncChannel();
+ // eslint-disable-next-line
+ }, [conversation.state, profile.state, card.state]);
+
+ useEffect(() => {
+ topics.current = new Map();
+ syncChannel();
+ }, [state.contentKey]);
+
+ const syncTopic = (item, value) => {
const revision = value.data?.detailRevision;
const detail = value.data?.topicDetail || {};
const identity = profile.state.identity || {};
@@ -172,42 +183,34 @@ export function useConversation(cardId, channelId) {
}
}
- if (detail.dataType === 'superbasictopic') {
- if (item.revision !== revision) {
- try {
+ if (item.revision !== revision) {
+ try {
+ if (detail.dataType === 'superbasictopic') {
const message = JSON.parse(detail.data);
item.assets = message.assets;
item.text = message.text;
item.textColor = message.textColor ? message.textColor : '#444444';
item.textSize = message.textSize ? message.textSize : 14;
}
- catch (err) {
- console.log(err);
- }
- }
- }
- if (detail.dataType === 'sealedtopic') {
- if (item.revision !== revision || item.contentKey !== state.contentKey) {
- item.contentKey = state.contentKey;
- try {
+ if (detail.dataType === 'sealedtopic') {
const subject = decryptTopicSubject(detail.data, state.contentKey);
item.assets = subject.message.assets;
item.text = subject.message.text;
item.textColor = subject.message.textColor ? subject.message.textColor : '#444444';
item.textSize = subject.message.textSize ? subject.message.textSize : 14;
}
- catch (err) {
- console.log(err);
- }
}
+ catch (err) {
+ console.log(err);
+ }
+ item.revision = revision;
}
item.transform = detail.transform;
item.status = detail.status;
item.assetUrl = conversation.actions.getTopicAssetUrl;
- item.revision = revision;
};
- useEffect(() => {
+ const syncChannel = () => {
const messages = new Map();
conversation.state.topics.forEach((value, id) => {
const curCardId = conversation.state.card?.id;
@@ -233,8 +236,7 @@ export function useConversation(cardId, channelId) {
});
updateState({ topics: sorted });
- // eslint-disable-next-line
- }, [conversation.state, profile.state, card.state, state.contentKey]);
+ }
const actions = {
more: () => {
@@ -251,6 +253,34 @@ export function useConversation(cardId, channelId) {
removeTopic: async (topicId) => {
await conversation.actions.removeTopic(topicId);
},
+ updateTopic: async (topic, text) => {
+ const { assets, textSize, textColor } = topic;
+ const message = { text, textSize, textColor, assets };
+ console.log("UPDATE", message);
+
+ if (!state.busy) {
+ updateState({ busy: true });
+ try {
+ if (state.sealed) {
+ if (state.contentKey) {
+ const subject = encryptTopicSubject({ message }, state.contentKey);
+ await conversation.actions.setTopicSubject(topic.id, 'sealedtopic', subject);
+ }
+ }
+ else {
+ await conversation.actions.setTopicSubject(topic.id, 'superbasictopic', message);
+ }
+ updateState({ busy: false });
+ }
+ catch(err) {
+ updateState({ busy: false });
+ throw new Error("topic update failed");
+ }
+ }
+ else {
+ throw new Error("operation in progress");
+ }
+ },
};
return { state, actions };