mirror of
https://github.com/RetroShare/RSNewWebUI.git
synced 2026-09-12 19:50:04 +05:00
webui: the card view paginates and dedups its body fetches
Cards fetch a message body each, for a 110-character snippet -- and the card view (the default) rendered the WHOLE folder: one getMessage per mail plus an identity lookup per sender, in one burst, on a mailbox of any size. The cards now page at 50 like the table, with a small pager, and a body already being fetched is not requested again on remount. Also from the same audit: the Bcc row of own sent mail is displayed again; forwarding a message whose subject starts with "Re:" says "Fwd:" (the prefix follows the action, not the existing prefix); and the list rows follow the reading pane's star/spam toggles instead of keeping the stale icon until a remount. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
d0f34871be
commit
851d301731
@ -190,6 +190,8 @@ const MessageSummary = () => {
|
||||
isSpam = Boolean(details.msgflags & RS_MSG_SPAM);
|
||||
if (v.attrs.details && v.attrs.details.msgflags !== undefined) {
|
||||
details.msgflags = v.attrs.details.msgflags;
|
||||
isStarred = (details.msgflags & 0xf00) === RS_MSG_STAR;
|
||||
isSpam = Boolean(details.msgflags & RS_MSG_SPAM);
|
||||
}
|
||||
MessageCache[v.attrs.details.msgId] = details;
|
||||
}
|
||||
@ -210,6 +212,15 @@ const MessageSummary = () => {
|
||||
}
|
||||
});
|
||||
},
|
||||
// The reading pane's star/spam toggles refresh the summaries; the row's
|
||||
// closure flags must follow the refreshed attrs or the icon stays stale
|
||||
// until a remount.
|
||||
onupdate: (v) => {
|
||||
if (v.attrs.details && v.attrs.details.msgflags !== undefined) {
|
||||
isStarred = (v.attrs.details.msgflags & 0xf00) === RS_MSG_STAR;
|
||||
isSpam = Boolean(v.attrs.details.msgflags & RS_MSG_SPAM);
|
||||
}
|
||||
},
|
||||
view: (v) => {
|
||||
const spamActive = isSpam || Boolean((details.msgflags || v.attrs.details.msgflags) & RS_MSG_SPAM);
|
||||
function spamMessage(e) {
|
||||
@ -364,12 +375,18 @@ const MessageSummary = () => {
|
||||
};
|
||||
};
|
||||
|
||||
// Bodies already being fetched for a card: a remount during the round trip
|
||||
// (filter toggle, page change) must not fire the same getMessage again.
|
||||
const CardFetchesInFlight = new Set();
|
||||
|
||||
const MessageCard = () => {
|
||||
return {
|
||||
oninit: (v) => {
|
||||
const msgId = v.attrs.msg.msgId;
|
||||
if (!MessageCache[msgId]) {
|
||||
if (!MessageCache[msgId] && !CardFetchesInFlight.has(msgId)) {
|
||||
CardFetchesInFlight.add(msgId);
|
||||
rs.rsJsonApiRequest('/rsMail/getMessage', { msgId }).then((res) => {
|
||||
CardFetchesInFlight.delete(msgId);
|
||||
if (res && res.body && res.body.retval) {
|
||||
MessageCache[msgId] = res.body.msg;
|
||||
MessageCache[msgId].msgtags = v.attrs.msg.msgtags;
|
||||
@ -781,6 +798,7 @@ const MessageView = () => {
|
||||
const senderName = (senderAddr && UserNicknamesCache[senderAddr]) || (senderAddr && rs.userList.username(senderAddr)) || '[Unknown]';
|
||||
const toKeys = Object.keys(MailData.toList || {});
|
||||
const ccKeys = Object.keys(MailData.ccList || {});
|
||||
const bccKeys = Object.keys(MailData.bccList || {});
|
||||
|
||||
return m(
|
||||
'.msg-view.mail-reading-card',
|
||||
@ -888,6 +906,15 @@ const MessageView = () => {
|
||||
return m('span.recipient-chip', { title: addr }, name);
|
||||
}),
|
||||
]),
|
||||
// Own sent mail carries its Bcc list; the old view showed it.
|
||||
bccKeys.length > 0 &&
|
||||
m('.msg-recipients-row', [
|
||||
m('span.recipient-label', 'Bcc:'),
|
||||
bccKeys.map((addr) => {
|
||||
const name = UserNicknamesCache[addr] || rs.userList.username(addr) || addr.slice(0, 8);
|
||||
return m('span.recipient-chip', { title: addr }, name);
|
||||
}),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
@ -913,7 +940,12 @@ const MessageView = () => {
|
||||
senderId: senderAddr,
|
||||
recipientList: MailData.toList,
|
||||
ccList: MailData.ccList,
|
||||
subject: MailData.subject.startsWith('Re:') || MailData.subject.startsWith('Fwd:') ? MailData.subject : `${composeType === 'forward' ? 'Fwd' : 'Re'}: ${MailData.subject}`,
|
||||
// The prefix depends on the ACTION, not on whatever
|
||||
// prefix the subject already has: forwarding "Re: X"
|
||||
// must send "Fwd: Re: X", not "Re: X".
|
||||
subject: composeType === 'forward'
|
||||
? (MailData.subject.startsWith('Fwd:') ? MailData.subject : `Fwd: ${MailData.subject}`)
|
||||
: (MailData.subject.startsWith('Re:') ? MailData.subject : `Re: ${MailData.subject}`),
|
||||
replyMessage: MailData.message,
|
||||
timeStamp: new Date(MailData.timeStamp * 1000),
|
||||
setShowCompose,
|
||||
|
||||
@ -2150,3 +2150,28 @@ input.star-check {
|
||||
padding: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.mail-cards-pagination {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
padding: 0.75rem;
|
||||
border-top: 1px solid #e2e8f0;
|
||||
color: #475569;
|
||||
font-size: 0.9rem;
|
||||
|
||||
button {
|
||||
padding: 0.3rem 0.7rem;
|
||||
border: 1px solid #cbd5e1;
|
||||
background: #f8fafc;
|
||||
color: #334155;
|
||||
border-radius: 0.375rem;
|
||||
box-shadow: none;
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.45;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user