mirror of
https://github.com/RetroShare/RSNewWebUI.git
synced 2026-09-14 11:05:47 +05:00
webui v141: stop the endless getIdDetails retry, and one copy path
fetchIdDetails() restored `undefined` after its five attempts, which is the very value that makes it fire a request -- and two of its callers sit inside a view (people_sidebar's filter and map). Every redraw therefore restarted the whole six request chain, forever, for any identity the core never resolves. Mark the give-up state with `null` instead, like the loading state: attempted, not to be asked again. The copy icon still ran the old inline execCommand path, so copyId() was only reachable through shareId()'s fallback and its clipboard call could reject with no feedback at all. The icon now calls copyId(), the Clipboard API failure falls back to execCommand, and the popup reports a refused copy instead of claiming success. Same role/tabindex/keyboard treatment as the share icon next to it.
This commit is contained in:
parent
4b523cb8ec
commit
2c38f04fa1
@ -79,15 +79,39 @@ const retroshareId = () => {
|
||||
el.style.height = el.scrollHeight + 'px';
|
||||
}
|
||||
|
||||
function copyIdFallback() {
|
||||
const field = document.getElementById('retroId');
|
||||
if (!field) return false;
|
||||
field.select();
|
||||
// Deprecated, but the Clipboard API is only exposed in a secure context
|
||||
// and the web UI is normally served over plain http on the LAN.
|
||||
return document.execCommand('copy');
|
||||
}
|
||||
|
||||
async function copyId(value) {
|
||||
let copied;
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
await navigator.clipboard.writeText(value);
|
||||
try {
|
||||
await navigator.clipboard.writeText(value);
|
||||
copied = true;
|
||||
} catch (_) {
|
||||
// Denied permission or an unfocused document: fall back rather than
|
||||
// leaving the promise rejected and no feedback at all.
|
||||
copied = copyIdFallback();
|
||||
}
|
||||
} else {
|
||||
const field = document.getElementById('retroId');
|
||||
field.select();
|
||||
document.execCommand('copy');
|
||||
copied = copyIdFallback();
|
||||
}
|
||||
widget.popupMessage(m(ConfirmCopied), 'copy-confirmation-modal');
|
||||
widget.popupMessage(
|
||||
copied
|
||||
? m(ConfirmCopied)
|
||||
: [
|
||||
m('h3', 'Copy failed'),
|
||||
m('hr'),
|
||||
m('p', 'Your browser refused the copy. Select the ID above and copy it by hand.'),
|
||||
],
|
||||
'copy-confirmation-modal'
|
||||
);
|
||||
}
|
||||
|
||||
async function shareId(value) {
|
||||
@ -124,10 +148,16 @@ const retroshareId = () => {
|
||||
v.attrs.ownCert
|
||||
),
|
||||
m('i.fas.fa-copy', {
|
||||
onclick: () => {
|
||||
document.getElementById('retroId').select();
|
||||
document.execCommand('copy');
|
||||
widget.popupMessage(m(ConfirmCopied), 'copy-confirmation-modal');
|
||||
role: 'button',
|
||||
tabindex: 0,
|
||||
title: 'Copy RetroShare ID',
|
||||
'aria-label': 'Copy RetroShare ID',
|
||||
onclick: () => copyId(v.attrs.ownCert),
|
||||
onkeydown: (event) => {
|
||||
if (event.key === 'Enter' || event.key === ' ') {
|
||||
event.preventDefault();
|
||||
copyId(v.attrs.ownCert);
|
||||
}
|
||||
},
|
||||
}),
|
||||
m('i.fas.fa-share-alt', {
|
||||
|
||||
@ -114,7 +114,7 @@ const navbar = () => {
|
||||
? 'Connected to RetroShare Core'
|
||||
: 'Connection Lost',
|
||||
}),
|
||||
m('span.webui-version', { style: { fontSize: '0.7em' } }, 'v140'),
|
||||
m('span.webui-version', { style: { fontSize: '0.7em' } }, 'v141'),
|
||||
m('i.fas.fa-sync-alt.refresh-icon', {
|
||||
style: { cursor: 'pointer', fontSize: '0.8em' },
|
||||
onclick: () => window.location.reload(true),
|
||||
@ -236,7 +236,7 @@ const MobileStatus = () => {
|
||||
m('small', statusbar.formatBytes(state.totalOut)),
|
||||
]),
|
||||
]),
|
||||
m('.mobile-status-sheet__version', 'WebUI v140'),
|
||||
m('.mobile-status-sheet__version', 'WebUI v141'),
|
||||
])),
|
||||
];
|
||||
},
|
||||
|
||||
@ -65,7 +65,12 @@ function fetchIdDetails(gxsId, attempt = 0) {
|
||||
fetchIdDetails(gxsId, attempt + 1);
|
||||
}, 250 * (attempt + 1));
|
||||
} else {
|
||||
State.gxsIdToDetailsMap[gxsId] = undefined;
|
||||
// Give up on this id, but do NOT restore `undefined`: that is the
|
||||
// value which makes this function fire a request, and two of the
|
||||
// callers sit inside a view (people_sidebar). Every redraw would then
|
||||
// start the whole six request chain again, forever, for any id the
|
||||
// core never resolves. `null` keeps the entry marked as attempted.
|
||||
State.gxsIdToDetailsMap[gxsId] = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user