Fixed the large-channel loading problem.

Fixed the large-channel loading problem.

Changes:

- Channel lists now load only channel metadata, instead of downloading all posts, comments, votes, and images for every listed channel.
- Full content loads only after opening a channel.
- Reduced content batches from 200 items to 25.
- Failed oversized responses automatically split into progressively smaller requests.
- Added response validation to avoid crashes when RetroShare returns incomplete data.
This commit is contained in:
defnax 2026-08-11 17:41:44 +02:00
parent 23a3f0d0f5
commit 8ae71106e1
2 changed files with 37 additions and 6 deletions

View File

@ -363,6 +363,12 @@ const ChannelView = () => {
if (Data.Posts[v.attrs.id]) {
plist = Data.Posts[v.attrs.id];
}
// Channel lists load metadata only. Fetch the selected channel's content
// here so large channels do not block or overload the list page.
util.updatedisplaychannels(v.attrs.id).then(() => {
plist = Data.Posts[v.attrs.id] || {};
m.redraw();
});
},
view: (v) => [
m(

View File

@ -34,7 +34,7 @@ const Data = {
// getChannelContent takes a set of ids, so a whole channel is fetched in a few
// requests instead of one per item. Chunked rather than sent as a single call so
// that no request grows unbounded and so the UI can paint as batches land.
const CONTENT_BATCH_SIZE = 200;
const CONTENT_BATCH_SIZE = 25;
function storePost(post, channelid) {
const msgId = post.mMeta && post.mMeta.mMsgId;
@ -91,7 +91,7 @@ function storeVote(vote) {
async function updatecontent(contentIds, channelid) {
const ids = Array.isArray(contentIds) ? contentIds : [contentIds];
if (ids.length === 0) {
return;
return true;
}
const res = await rs.rsJsonApiRequest('/rsgxschannels/getChannelContent', {
channelId: channelid,
@ -99,19 +99,39 @@ async function updatecontent(contentIds, channelid) {
});
// rsJsonApiRequest resolves to undefined when the request never made it out
if (!res || !res.body || !res.body.retval) {
return;
return false;
}
// A batch mixes the three kinds, so all three lists have to be walked. The
// metadata of each item is used rather than the summary it was asked from.
(res.body.posts || []).forEach((post) => storePost(post, channelid));
(res.body.comments || []).forEach(storeComment);
(res.body.votes || []).forEach(storeVote);
return true;
}
async function updatedisplaychannels(keyid, details) {
// Large posts can contain base64 media. If RetroShare truncates a response,
// retry it as two smaller requests until the problematic batch is isolated.
async function updateContentBatch(contentIds, channelid) {
const loaded = await updatecontent(contentIds, channelid);
if (loaded || contentIds.length <= 1) {
if (!loaded) {
console.warn('Unable to load channel content item', contentIds[0]);
}
return;
}
const middle = Math.ceil(contentIds.length / 2);
await updateContentBatch(contentIds.slice(0, middle), channelid);
await updateContentBatch(contentIds.slice(middle), channelid);
}
async function updatedisplaychannels(keyid, details, loadContent = true) {
const res1 = await rs.rsJsonApiRequest('/rsgxschannels/getChannelsInfo', {
chanIds: [keyid],
});
if (!res1 || !res1.body || !Array.isArray(res1.body.channelsInfo) || !res1.body.channelsInfo[0]) {
return;
}
details = res1.body.channelsInfo[0];
Data.DisplayChannels[keyid] = {
// struct for a channel
@ -132,6 +152,11 @@ async function updatedisplaychannels(keyid, details) {
if (Data.Posts[keyid] === undefined) {
Data.Posts[keyid] = {};
}
// Channel lists only need metadata. Fetching every post, comment, vote and
// embedded image for every listed channel made large lists extremely slow.
if (!loadContent) {
return;
}
const res2 = await rs.rsJsonApiRequest('/rsgxschannels/getContentSummaries', {
channelId: keyid,
});
@ -144,7 +169,7 @@ async function updatedisplaychannels(keyid, details) {
// Sequential on purpose: this runs once per channel of the list, so firing the
// batches concurrently would put the browser back where it started.
for (let i = 0; i < ids.length; i += CONTENT_BATCH_SIZE) {
await updatecontent(ids.slice(i, i + CONTENT_BATCH_SIZE), keyid);
await updateContentBatch(ids.slice(i, i + CONTENT_BATCH_SIZE), keyid);
m.redraw();
}
}
@ -177,7 +202,7 @@ const ChannelSummary = () => {
return {
oninit: (v) => {
keyid = v.attrs.details.mGroupId;
updatedisplaychannels(keyid);
updatedisplaychannels(keyid, undefined, false);
},
view: (v) => {},