@@ -27,7 +35,8 @@ export function TopicItem({ topic }) {
- { state.message }
+
+ { state.message?.text }
)
diff --git a/net/web/src/User/Conversation/TopicItem/useTopicItem.hook.js b/net/web/src/User/Conversation/TopicItem/useTopicItem.hook.js
index bc0cba2e..42b09158 100644
--- a/net/web/src/User/Conversation/TopicItem/useTopicItem.hook.js
+++ b/net/web/src/User/Conversation/TopicItem/useTopicItem.hook.js
@@ -13,6 +13,9 @@ export function useTopicItem(topic) {
imageUrl: null,
message: null,
created: null,
+ status: null,
+ transform: null,
+ assets: [],
});
const profile = useContext(ProfileContext);
@@ -24,10 +27,19 @@ export function useTopicItem(topic) {
}
useEffect(() => {
+
+ const { status, transform, data } = topic.data.topicDetail;
let message;
- if( topic.data.topicDetail.status === 'confirmed') {
+ let assets = [];
+ if (status === 'confirmed') {
try {
- message = JSON.parse(topic.data.topicDetail.data).text;
+ message = JSON.parse(data);
+ if (transform === 'complete') {
+ if (message.assets) {
+ assets = message.assets;
+ delete message.assets;
+ }
+ }
}
catch(err) {
console.log(err);
@@ -38,16 +50,19 @@ export function useTopicItem(topic) {
const { guid, created } = topic.data.topicDetail;
if (profile.state.profile.guid == guid) {
const { name, handle, imageUrl } = profile.actions.getProfile();
- updateState({ name, handle, imageUrl, message, created });
+ updateState({ name, handle, imageUrl, status, message, transform, assets, created });
}
else {
const { name, handle, imageUrl } = card.actions.getCardProfileByGuid(guid);
- updateState({ name, handle, imageUrl, message, created });
+ updateState({ name, handle, imageUrl, status, message, transform, assets, created });
}
}
}, [profile, card, conversation, topic]);
const actions = {
+ getAssetUrl: (assetId) => {
+ return conversation.actions.getAssetUrl(topic.id, assetId);
+ }
};
return { state, actions };
diff --git a/net/web/src/api/addChannelTopic.js b/net/web/src/api/addChannelTopic.js
index bae5f84e..15341a32 100644
--- a/net/web/src/api/addChannelTopic.js
+++ b/net/web/src/api/addChannelTopic.js
@@ -2,31 +2,72 @@ import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function addChannelTopic(token, channelId, message, assets ) {
- let subject = { data: JSON.stringify(message, (key, value) => {
- if (value !== null) return value
- }), datatype: 'superbasictopic' };
-
if (assets == null || assets.length == 0) {
+ let subject = { data: JSON.stringify(message, (key, value) => {
+ if (value !== null) return value
+ }), datatype: 'superbasictopic' };
+
let topic = await fetchWithTimeout(`/content/channels/${channelId}/topics?agent=${token}&confirm=true`,
{ method: 'POST', body: JSON.stringify(subject) });
checkResponse(topic);
}
else {
+
let topic = await fetchWithTimeout(`/content/channels/${channelId}/topics?agent=${token}`,
{ method: 'POST', body: JSON.stringify({}) });
checkResponse(topic);
let slot = await topic.json();
// add each asset
+ message.assets = [];
for (let asset of assets) {
- const formData = new FormData();
- formData.append('asset', asset.image);
- let transform = encodeURIComponent(JSON.stringify(["ithumb;photo"]));
- let topicAsset = await fetch(`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`, { method: 'POST', body: formData });
- checkResponse(topicAsset);
-console.log(await topicAsset.json());
+ if (asset.image) {
+ const formData = new FormData();
+ formData.append('asset', asset.image);
+ let transform = encodeURIComponent(JSON.stringify(["ithumb;photo", "icopy;photo"]));
+ let topicAsset = await fetch(`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`, { method: 'POST', body: formData });
+ checkResponse(topicAsset);
+ let assetEntry = await topicAsset.json();
+ message.assets.push({
+ image: {
+ thumb: assetEntry.find(item => item.transform === 'ithumb;photo').assetId,
+ full: assetEntry.find(item => item.transform === 'icopy;photo').assetId,
+ }
+ });
+ }
+ else if (asset.video) {
+ const formData = new FormData();
+ formData.append('asset', asset.video);
+ let transform = encodeURIComponent(JSON.stringify(["vthumb;video", "vcopy;video"]));
+ let topicAsset = await fetch(`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`, { method: 'POST', body: formData });
+ checkResponse(topicAsset);
+ let assetEntry = await topicAsset.json();
+ message.assets.push({
+ image: {
+ thumb: assetEntry.find(item => item.transform === 'vthumb;video').assetId,
+ full: assetEntry.find(item => item.transform === 'vcopy;video').assetId,
+ }
+ });
+ }
+ else if (asset.audio) {
+ const formData = new FormData();
+ formData.append('asset', asset.audio);
+ let transform = encodeURIComponent(JSON.stringify(["acopy;audio"]));
+ let topicAsset = await fetch(`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`, { method: 'POST', body: formData });
+ checkResponse(topicAsset);
+ let assetEntry = await topicAsset.json();
+ message.assets.push({
+ image: {
+ full: assetEntry.find(item => item.transform === 'acopy;audio').assetId,
+ }
+ });
+ }
}
+ let subject = { data: JSON.stringify(message, (key, value) => {
+ if (value !== null) return value
+ }), datatype: 'superbasictopic' };
+
let unconfirmed = await fetchWithTimeout(`/content/channels/${channelId}/topics/${slot.id}/subject?agent=${token}`,
{ method: 'PUT', body: JSON.stringify(subject) });
checkResponse(unconfirmed);
diff --git a/net/web/src/api/getChannelTopicAssetUrl.js b/net/web/src/api/getChannelTopicAssetUrl.js
new file mode 100644
index 00000000..c20fb234
--- /dev/null
+++ b/net/web/src/api/getChannelTopicAssetUrl.js
@@ -0,0 +1,4 @@
+export function getChannelTopicAssetUrl(token, channelId, topicId, assetId) {
+ return `/content/channels/${channelId}/topics/${topicId}/assets/${assetId}?agent=${token}`
+}
+
diff --git a/net/web/src/api/getContactChannelTopicAssetUrl.js b/net/web/src/api/getContactChannelTopicAssetUrl.js
new file mode 100644
index 00000000..6051f74b
--- /dev/null
+++ b/net/web/src/api/getContactChannelTopicAssetUrl.js
@@ -0,0 +1,4 @@
+export function getContactChannelTopicAssetUrl(server, token, channelId, topicId, assetId) {
+ return `https://${server}/content/channels/${channelId}/topics/${topicId}/assets/${assetId}?contact=${token}`
+}
+
diff --git a/net/web/src/context/useCardContext.hook.js b/net/web/src/context/useCardContext.hook.js
index 251b1f3b..f7ec578d 100644
--- a/net/web/src/context/useCardContext.hook.js
+++ b/net/web/src/context/useCardContext.hook.js
@@ -15,6 +15,7 @@ import { getCardCloseMessage } from 'api/getCardCloseMessage';
import { setCardCloseMessage } from 'api/setCardCloseMessage';
import { getContactChannelTopics } from 'api/getContactChannelTopics';
import { getContactChannelTopic } from 'api/getContactChannelTopic';
+import { getContactChannelTopicAssetUrl } from 'api/getContactChannelTopicAssetUrl';
import { addCard } from 'api/addCard';
import { removeCard } from 'api/removeCard';
@@ -249,6 +250,12 @@ export function useCardContext() {
setCardCloseMessage: async (server, message) => {
return await setCardCloseMessage(server, message);
},
+ getContactChannelTopicAssetUrl: (cardId, channelId, topicId, assetId) => {
+ let card = cards.current.get(cardId);
+ let node = card.data.cardProfile.node;
+ let token = card.data.cardProfile.guid + "." + card.data.cardDetail.token;
+ return getContactChannelTopicAssetUrl(node, token, channelId, topicId, assetId);
+ }
}
return { state, actions }
diff --git a/net/web/src/context/useChannelContext.hook.js b/net/web/src/context/useChannelContext.hook.js
index 710f7b70..2c1ef8db 100644
--- a/net/web/src/context/useChannelContext.hook.js
+++ b/net/web/src/context/useChannelContext.hook.js
@@ -5,6 +5,7 @@ import { addChannel } from 'api/addChannel';
import { addChannelTopic } from 'api/addChannelTopic';
import { getChannelTopics } from 'api/getChannelTopics';
import { getChannelTopic } from 'api/getChannelTopic';
+import { getChannelTopicAssetUrl } from 'api/getChannelTopicAssetUrl';
export function useChannelContext() {
const [state, setState] = useState({
@@ -91,6 +92,9 @@ export function useChannelContext() {
getChannelTopic: async (channelId, topicId) => {
return await getChannelTopic(access.current, channelId, topicId);
},
+ getChannelTopicAssetUrl: (channelId, topicId, assetId) => {
+ return getChannelTopicAssetUrl(access.current, channelId, topicId, assetId);
+ }
}
return { state, actions }
diff --git a/net/web/src/context/useConversationContext.hook.js b/net/web/src/context/useConversationContext.hook.js
index 75ebcf7b..1d724f26 100644
--- a/net/web/src/context/useConversationContext.hook.js
+++ b/net/web/src/context/useConversationContext.hook.js
@@ -13,6 +13,7 @@ export function useConversationContext() {
const channel = useContext(ChannelContext);
const topics = useRef(new Map());
const revision = useRef(null);
+ const count = useRef(0);
const conversationId = useRef(null);
const updateState = (value) => {
@@ -21,12 +22,11 @@ export function useConversationContext() {
const setTopics = async () => {
const { cardId, channelId } = conversationId.current;
-
+
if (cardId) {
let rev = card.actions.getChannelRevision(cardId, channelId);
if (revision.current != rev) {
let delta = await card.actions.getChannelTopics(cardId, channelId, revision.current);
- console.log(delta);
for (let topic of delta) {
if (topic.data == null) {
topics.current.delete(topic.id);
@@ -37,7 +37,7 @@ export function useConversationContext() {
cur = { id: topic.id, data: {} };
}
if (topic.data.detailRevision != cur.data.detailRevision) {
- if(topic.data.topicDetail != null) {
+ if(topic.data.topicDetail) {
cur.data.topicDetail = topic.data.topicDetail;
cur.data.detailRevision = topic.data.detailRevision;
}
@@ -108,11 +108,20 @@ export function useConversationContext() {
return;
}
- try {
- setTopics();
+ if (count.current == 0) {
+ count.current += 1;
+ while(count.current > 0) {
+ try {
+ await setTopics();
+ }
+ catch (err) {
+ console.log(err);
+ }
+ count.current -= 1;
+ }
}
- catch (err) {
- console.log(err);
+ else {
+ count.current += 1;
}
};
@@ -129,6 +138,15 @@ export function useConversationContext() {
topics.current = new Map();
updateState({ init: false, topics: topics.current });
updateConversation();
+ },
+ getAssetUrl: (topicId, assetId) => {
+ const { cardId, channelId } = conversationId.current;
+ if (conversationId.current.cardId) {
+ return card.actions.getContactChannelTopicAssetUrl(cardId, channelId, topicId, assetId);
+ }
+ else {
+ return channel.actions.getChannelTopicAssetUrl(channelId, topicId, assetId);
+ }
}
}