webui v164: only a live tunnel is adopted, and the version is in the header

v163 settled on any tunnel entry the core still held for the contact,
dead ones included -- a peer-opened tunnel that died stays in the core's
table with a "down" status it cannot re-dig itself -- so opening a chat
then waited on it for good, and since nothing called
initiateDistantChatConnexion any more, no desktop window popped either.

Only a tunnel that can talk (status 2) now decides the identity to chat
as; the conversation is then always opened through
initiateDistantChatConnexion, which hands back the same tunnel id for an
existing pair and pops the desktop window as before.

The version label moves into one constant, shown in the phone header
next to the brand -- the status sheet was the only place carrying it --
and the status sheet gets a Reload button beside it: the page keeps the
code it loaded until reloaded, and phone browsers hide that action.
This commit is contained in:
jolavillette 2026-08-29 13:00:02 +02:00
parent 74155dafbc
commit 4e3530cc20
4 changed files with 65 additions and 38 deletions

View File

@ -1,5 +1,8 @@
const m = require('mithril');
// Bumped at every change of the web UI (two places used to carry it).
const WEBUI_VERSION = 'v164';
const login = require('login');
const rs = require('rswebui');
const home = require('home');
@ -137,7 +140,7 @@ const navbar = () => {
? 'Connected to RetroShare Core'
: 'Connection Lost',
}),
m('span.webui-version', { style: { fontSize: '0.7em' } }, 'v163'),
m('span.webui-version', { style: { fontSize: '0.7em' } }, WEBUI_VERSION),
m('i.fas.fa-sync-alt.refresh-icon', {
style: { cursor: 'pointer', fontSize: '0.8em' },
onclick: () => window.location.reload(true),
@ -212,6 +215,7 @@ const MobileStatus = () => {
m('.mobile-app-header__brand', [
m('img', { src: 'images/retroshare.svg', alt: '' }),
m('strong', 'RetroShare'),
m('span.mobile-app-header__version', WEBUI_VERSION),
]),
m('button.mobile-status-trigger[type=button]', {
'aria-label': `Open connection status. ${summary.label}`,
@ -277,7 +281,15 @@ const MobileStatus = () => {
s.slowest.length > 0 && m('div', 'slowest: ' + s.slowest.map((e) => `${short(e.path)} ${e.ms}ms`).join(', ')),
]);
})(),
m('.mobile-status-sheet__version', 'WebUI v163'),
m('.mobile-status-sheet__version', [
'WebUI ' + WEBUI_VERSION,
// The page keeps the code it loaded until it is reloaded, and a
// phone browser hides that action away. A new build shows up
// here only after this.
m('button[type=button]', {
onclick: () => window.location.reload(true),
}, [m('i.fas.fa-sync-alt'), ' Reload']),
]),
])),
];
},

View File

@ -458,37 +458,27 @@ function initializeDistantChat(force = false) {
return;
}
// A tunnel to this peer may already exist without this page knowing:
// opened from the desktop window, or by the peer, possibly under another
// of our identities. Its id is sha1(sorted(own || peer)), so every
// candidate can be asked for by id before digging a new one -- which the
// core would do for any own identity other than the tunnel's, and the
// page then sat on "Connecting" beside a green tunnel in the desktop UI.
// Explicit identity switches (force) skip this: the user chose.
// A live tunnel to this peer may exist without this page knowing: opened
// from the desktop window, or by the peer, possibly under another of our
// identities. Its id is sha1(sorted(own || peer)), so every candidate can
// be asked for by id. When one is up, chat as that identity: asking the
// core for any other pair digs a second tunnel, and the page then sat on
// "Connecting" beside a green tunnel in the desktop UI.
//
// Only a tunnel that can talk (status 2) counts. The core also keeps
// entries for tunnels that died -- a peer-opened one it cannot re-dig
// itself -- and settling on one of those left the page waiting for good.
// Either way the conversation is then opened through
// initiateDistantChatConnexion: for an existing pair the core just hands
// back the same tunnel id, and its notify pops the desktop window as it
// always did. Explicit identity switches (force) skip the probe.
if (!force) {
const askedFor = State.selectedId;
adoptExistingTunnel(askedFor, (ownId, pid, info) => {
findLiveTunnelIdentity(askedFor, (ownId) => {
// The answers come back later; the user may have moved on.
if (State.selectedId !== askedFor) return;
if (!ownId) {
openDistantChat(session);
return;
}
State.selectedOwnGxsIdForChat = ownId;
session.pid = pid;
session.status = info;
session.disconnected = false;
State.chatPid = pid;
State.chatMessages = session.messages;
State.distantChatStatus = info;
State.chatDisconnected = false;
State.chatCloseFoundNothing = false;
State.statusPollFailures = 0;
State.chatInputMsg = session.inputMsg || '';
drainBufferedChatMessages(session);
loadChatMessages();
startStatusPolling();
m.redraw();
if (ownId) State.selectedOwnGxsIdForChat = ownId;
openDistantChat(session);
});
return;
}
@ -497,9 +487,8 @@ function initializeDistantChat(force = false) {
}
// Ask the core about every tunnel id we could share with this peer, one per
// own identity. Answers with the live one (status 2, "can talk") first, else
// any the core still holds, else nothing.
function adoptExistingTunnel(peerGxsId, done) {
// own identity, and answer with the identity of the one that can talk.
function findLiveTunnelIdentity(peerGxsId, done) {
const candidates = (State.ownGxsIds || [])
.map((ownId) => ({ ownId, pid: peopleUtil.distantChatPid(ownId, peerGxsId) }))
.filter((c) => c.pid);
@ -517,11 +506,8 @@ function adoptExistingTunnel(peerGxsId, done) {
}
left -= 1;
if (left > 0) return;
const live = found.find((f) => f.info.status === 2)
|| found.find((f) => f.ownId === State.selectedOwnGxsIdForChat)
|| found[0];
if (live) done(live.ownId, live.pid, live.info);
else done(null);
const live = found.find((f) => f.info.status === 2);
done(live ? live.ownId : null);
});
});
}

View File

@ -637,3 +637,32 @@
color: #64748b;
}
}
/* Version label in the phone header, and the reload button beside the
* version in the status sheet (main.js MobileStatus). */
.mobile-app-header__version {
margin-left: 0.4rem;
font-size: 0.7rem;
font-weight: 600;
color: #64748b;
align-self: flex-end;
padding-bottom: 0.15rem;
}
.mobile-status-sheet__version {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
button {
border: 1px solid #cbd5e1;
background: #f8fafc;
color: #334155;
border-radius: 0.375rem;
padding: 0.3rem 0.6rem;
font-size: 0.75rem;
font-weight: 600;
cursor: pointer;
}
}

File diff suppressed because one or more lines are too long