diff --git a/net/web/src/User/Conversation/Conversation.jsx b/net/web/src/User/Conversation/Conversation.jsx
index a4d4f28a..d09975e0 100644
--- a/net/web/src/User/Conversation/Conversation.jsx
+++ b/net/web/src/User/Conversation/Conversation.jsx
@@ -48,13 +48,24 @@ export function Conversation() {
const uploadProgress = () => {
let progress = [];
for (let entry of state.progress) {
- progress.push(
-
-
{ entry.index }/{ entry.count }
-
-
-
- );
+ if (entry.error) {
+ progress.push(
+
+
{ entry.index }/{ entry.count }
+
+
+
+ );
+ }
+ else {
+ progress.push(
+
+
{ entry.index }/{ entry.count }
+
+
+
+ );
+ }
}
return progress;
}
diff --git a/net/web/src/User/Conversation/useConversation.hook.js b/net/web/src/User/Conversation/useConversation.hook.js
index 74dd0d67..4f1369f9 100644
--- a/net/web/src/User/Conversation/useConversation.hook.js
+++ b/net/web/src/User/Conversation/useConversation.hook.js
@@ -50,7 +50,15 @@ export function useConversation() {
},
resync: () => {
conversation.actions.resync();
- }
+ },
+ cancel: (topicId) => {
+ if (cardId) {
+ upload.actions.cancelContactTopic(cardId, channelId, topicId);
+ }
+ else {
+ upload.actions.cancelTopic(channelId, topicId);
+ }
+ },
};
useEffect(() => {
diff --git a/net/web/src/context/useAppContext.hook.js b/net/web/src/context/useAppContext.hook.js
index 54424252..23a0020a 100644
--- a/net/web/src/context/useAppContext.hook.js
+++ b/net/web/src/context/useAppContext.hook.js
@@ -12,6 +12,7 @@ import { GroupContext } from './GroupContext';
import { CardContext } from './CardContext';
import { ChannelContext } from './ChannelContext';
import { StoreContext } from './StoreContext';
+import { UploadContext } from './UploadContext';
async function appCreate(username, password, token, updateState, setWebsocket) {
await addAccount(username, password, token);
@@ -60,6 +61,7 @@ export function useAppContext() {
})
}
+ const uploadContext = useContext(UploadContext);
const storeContext = useContext(StoreContext);
const accountContext = useContext(AccountContext);
const profileContext = useContext(ProfileContext);
@@ -83,6 +85,7 @@ export function useAppContext() {
logout: () => {
appLogout(updateState, clearWebsocket);
storeContext.actions.clear();
+ uploadContext.actions.clear();
resetData();
},
}
diff --git a/net/web/src/context/useCardContext.hook.js b/net/web/src/context/useCardContext.hook.js
index 7e6f27f4..b1e38627 100644
--- a/net/web/src/context/useCardContext.hook.js
+++ b/net/web/src/context/useCardContext.hook.js
@@ -290,11 +290,9 @@ export function useCardContext() {
if (files?.length) {
const topicId = await addContactChannelTopic(node, token, channelId, null, null);
upload.actions.addContactTopic(node, token, cardId, channelId, topicId, files, async (assets) => {
- console.log("success, finalize topic");
message.assets = assets;
await setContactChannelTopicSubject(node, token, channelId, topicId, message);
}, async () => {
- console.log("failed, delete topic");
try {
await removeContactChannelTopic(node, token, channelId, topicId);
}
diff --git a/net/web/src/context/useChannelContext.hook.js b/net/web/src/context/useChannelContext.hook.js
index 7efcea2a..513273fc 100644
--- a/net/web/src/context/useChannelContext.hook.js
+++ b/net/web/src/context/useChannelContext.hook.js
@@ -124,11 +124,9 @@ export function useChannelContext() {
if (files?.length) {
const topicId = await addChannelTopic(access.current, channelId, null, null);
upload.actions.addTopic(access.current, channelId, topicId, files, async (assets) => {
- console.log("success, finalize topic");
message.assets = assets;
await setChannelTopicSubject(access.current, channelId, topicId, message);
}, async () => {
- console.log("failed, delete topic");
try {
await removeChannelTopic(access.current, channelId, topicId);
}
diff --git a/net/web/src/context/useUploadContext.hook.js b/net/web/src/context/useUploadContext.hook.js
index 9e184d42..4331cd79 100644
--- a/net/web/src/context/useUploadContext.hook.js
+++ b/net/web/src/context/useUploadContext.hook.js
@@ -39,12 +39,25 @@ export function useUploadContext() {
if (assets.length) {
progress.set(channel, assets.sort((a, b) => (a.upload < b.upload) ? 1 : -1));
}
- updateState({ progress });
});
+ updateState({ progress });
+ }
+
+ const abort = (channelId, topicId) => {
+ const channel = channels.current.get(channelId);
+ if (channel) {
+ const topic = channel.get(topicId);
+ if (topic) {
+ topic.cancel.abort();
+ channel.delete(topicId);
+ updateProgress();
+ }
+ }
}
const actions = {
addTopic: (token, channelId, topicId, files, success, failure) => {
+ const controller = new AbortController();
const entry = {
index: index.current,
url: `/content/channels/${channelId}/topics/${topicId}/assets?agent=${token}`,
@@ -53,7 +66,8 @@ export function useUploadContext() {
current: null,
error: false,
success,
- failure
+ failure,
+ cancel: controller,
}
index.current += 1;
const key = `:${channelId}`;
@@ -65,8 +79,10 @@ export function useUploadContext() {
upload(entry, updateProgress, () => { updateComplete(key, topicId) } );
},
cancelTopic: (channelId, topicId) => {
+ abort(`:${channelId}`, topicId);
},
addContactTopic: (server, token, cardId, channelId, topicId, files, success, failure) => {
+ const controller = new AbortController();
const entry = {
index: index.current,
url: `https://${server}/content/channels/${channelId}/topics/${topicId}/assets?contact=${token}`,
@@ -75,7 +91,8 @@ export function useUploadContext() {
current: null,
error: false,
success,
- failure
+ failure,
+ cancel: controller,
}
index.current += 1;
const key = `${cardId}:${channelId}`;
@@ -87,8 +104,16 @@ export function useUploadContext() {
upload(entry, updateProgress, () => { updateComplete(key, topicId) });
},
cancelContactTopic: (cardId, channelId, topicId) => {
+ abort(`${cardId}:${channelId}`, topicId);
},
- reset: () => {
+ clear: () => {
+ channels.current.forEach((topics, channelId) => {
+ topics.forEach((assets, topicId) => {
+ assets.cancel.abort();
+ });
+ });
+ channels.current.clear();
+ updateProgress();
}
}
@@ -109,6 +134,7 @@ async function upload(entry, update, complete) {
formData.append('asset', file.image);
let transform = encodeURIComponent(JSON.stringify(["ithumb;photo", "icopy;photo"]));
let asset = await axios.post(`${entry.url}&transforms=${transform}`, formData, {
+ signal: entry.cancel.signal,
onUploadProgress: (ev) => {
const { loaded, total } = ev;
entry.active = { loaded, total }
@@ -128,6 +154,7 @@ async function upload(entry, update, complete) {
let thumb = 'vthumb;video;' + file.position;
let transform = encodeURIComponent(JSON.stringify(["vlq;video", "vhd;video", thumb]));
let asset = await axios.post(`${entry.url}&transforms=${transform}`, formData, {
+ signal: entry.cancel.signal,
onUploadProgress: (ev) => {
const { loaded, total } = ev;
entry.active = { loaded, total }
@@ -147,6 +174,7 @@ async function upload(entry, update, complete) {
formData.append('asset', file.audio);
let transform = encodeURIComponent(JSON.stringify(["acopy;audio"]));
let asset = await axios.post(`${entry.url}&transforms=${transform}`, formData, {
+ signal: entry.cancel.signal,
onUploadProgress: (ev) => {
const { loaded, total } = ev;
entry.active = { loaded, total }
@@ -167,6 +195,7 @@ async function upload(entry, update, complete) {
console.log(err);
entry.failure();
entry.error = true;
+ update();
}
}
}