Commit Graph

575 Commits

Author SHA1 Message Date
jolavillette
489ecec3a2 webui v158: an invitation must be refusable, and the label was lost in the merges
The Chat badge now counts pending room invitations, but the web UI only offered
to accept one: denyLobbyInvite() exists in the core and was called nowhere. An
invitation left alone therefore kept the badge lit for good, with no action able
to clear it. It can be declined now -- the entry leaves the room list with it,
since it came from the invitation and not from the nearby lobbies.

An invitation also carries no participant count: ChatLobbyInvite has lobby_id,
peer_id, lobby_name, lobby_topic and lobby_flags, and total_number_of_peers only
exists on the records the nearby list returns. The detail panel claimed "0 users"
for every invited room, and the join-failure message read the same missing field
to conclude the room was "no longer advertised by an online participant" --
a wrong diagnosis when the real cause was a refused identity.

The version label also went back to v154 on the way in: the four merges of #23
to #26 each resolved main.js by keeping the lower number, so the branch says
v154 while carrying the code of v157. Set to v158 rather than restoring v157,
since the composer spacing and the invitations landed after it.
2026-08-27 19:48:05 +02:00
defnax
df9cd7d24e Fixed the room invite was missed before 2026-08-27 18:16:45 +02:00
defnax
7b1c182e91
Merge branch 'improvements_v2' into feature/chatroom-load-older-for-121 2026-08-27 15:20:58 +02:00
defnax
973ed7e6c6
Merge branch 'improvements_v2' into fix/mail-unread-badge-for-121 2026-08-27 15:18:50 +02:00
defnax
385ab35584
Merge pull request #23 from jolavillette/fix/chat-image-viewer-modal-for-121
Image preview: Escape, Tab and focus restore
2026-08-27 15:17:43 +02:00
jolavillette
597ef472d8 webui v157: read further back in a room by scrolling up
A room opens on its last 20 messages and that was all there ever was: reaching
the top of the pane loaded nothing, so anything older was only reachable through
the separate history browser.

Scrolling near the top now asks for a larger slice. p3HistoryMgr::getMessages
takes a count and nothing else -- no cursor, no "before this message" -- and
always answers with the newest ones, so the only way to reach older text is to
ask for more and let addMessages() drop what is already held. It re-sends what
we have, which is the price of that API; the slice is small, and the core keeps
ten days at most anyway.

An answer shorter than the count asked for means there is nothing older left,
and the pane stops asking. The opening slice stays at 20: every room opening
pays for it, and on a phone each request is a fresh connection on a core that
answers one at a time.

Older messages are inserted above what is on screen, which would push the
conversation down by their height; that height goes back into scrollTop, so the
reader does not move while a slice lands.
2026-08-27 13:44:39 +02:00
jolavillette
e67c4c3170 webui v156: a chat room dragged the reader back to the last message
The message pane scrolled to the bottom from its onupdate, unconditionally. That
hook runs on every redraw of the chat hub -- an incoming message, a poll answer,
a keystroke in the composer -- so scrolling up to read anything older was undone
a few tens of milliseconds later, every time.

It now follows the reader: the pane stays pinned while it is already at the
bottom, stops as soon as it is scrolled away from it, and pins again when it
comes back. Sending a message still jumps down whatever the state, and switching
room opens on its last message, since the pane is reused rather than recreated
and its oncreate does not run again.

The scroll handler sets event.redraw = false: mithril redraws after every
handler by default, and this one fires continuously while the pane is dragged.
2026-08-27 13:35:05 +02:00
defnax
b1394a3935 Improved phone composer spacing
- Fixed to get more space for the text field
2026-08-27 13:34:59 +02:00
jolavillette
2501adcae7 webui v155: marking a mail read must not take it out of the trash
markReadLocally() clears the whole 0xf0 nibble, but RS_MSG_TRASH is 0x20 and
lives inside it (rsmail.h). Opening a message from the Trash therefore cleared
its trash flag as well, and the row showed as an ordinary read mail until the
next load. Only the two unread bits are cleared now.

The badge itself is read from the navigation view, so unreadCount() ran a full
pass over the inbox on every redraw -- once for the rail and twice more for the
bottom bar, which asks for the value twice per item. The count is kept instead,
recomputed when the inbox changes: after a load, and after a message is marked
read.
2026-08-27 13:31:04 +02:00
defnax
97a4dd5578 Fixed to use counters badges only for new chats 2026-08-27 13:06:22 +02:00
jolavillette
e9cf4e74f3 webui v154: the image preview claims to be a modal, so let it behave like one
The overlay carries role=dialog and aria-modal=true, but its Escape handler sits
on the overlay itself and therefore only sees what bubbles through it. The close
button is focused on open, so Escape works -- until the first tap on the picture,
which moves the focus to <body>: from then on the only way out is the close
button or the Back button.

The handler moves to the document, in the capture phase, and is removed when the
preview closes. Tab is caught there too: aria-modal promises the rest of the page
is inert, and without it the focus walks straight out of the preview into the
message list behind it. Closing also puts the focus back on whatever opened the
preview rather than dropping it on <body>.
2026-08-26 17:42:48 +02:00
defnax
f716a61298 Fixed issue with edit identity on a phone 2026-08-25 19:14:52 +02:00
defnax
4bf5b21e61 Fixed to get work autojoin rooms 2026-08-25 18:37:36 +02:00
defnax
aac62d1268 Fixed issue on Android phone with picture viewing, to able to go back to the app 2026-08-25 18:18:36 +02:00
defnax
4960372e19
Merge branch 'improvements_v2' into fix/peer-address-fallback-for-121 2026-08-25 17:10:43 +02:00
defnax
7a6cbfa572
Merge pull request #21 from jolavillette/fix/statistics-page-for-121
Statistics page: overlapping polls, a second friend collection, a second formatBytes
2026-08-25 17:09:33 +02:00
jolavillette
a3aa6652dd webui v153: read the core's own local/external marker, and see IPv6
The address fallback deduces "local or external" from the RFC1918 ranges, but
the core already says which is which: getPeerDetails appends its own marker to
every ipAddressList entry, "    123 sec loc" or "    123 sec ext"
(p3peers.cc). Guessing instead gets two cases wrong -- a peer behind CGNAT
(100.64/10) or a double NAT has a private looking external address, and a
loopback entry is not external at all -- where the marker is always right.

The parser was also IPv4 only, which misses the very case the fallback exists
for: GetRetroshareInvite() clears extAddr and moves the address into
ipAddressList when it is IPv6, because the certificate format only carries IPv4
numbers, so a peer added by short invite over IPv6 has an empty external address
and an entry the regex could not read. RsUrl wraps IPv6 hosts in brackets and
escapes the % of a link-local scope id as %25; both are handled, and the entry
with no marker at all -- the one that invite path produces -- is external by
construction.
2026-08-25 09:57:10 +02:00
defnax
d42da25928 Fixed the phone-only channel post overlap 2026-08-24 22:24:38 +02:00
defnax
569de96a3a Fixed to keep the adress details when added via short id 2026-08-24 22:04:56 +02:00
defnax
509e51d011 Fixed the boards view freezes 2026-08-24 21:12:35 +02:00
jolavillette
4bb1a893cf webui v152: the statistics page polls, and collects, more than it needs
The Refresh button was guarded by a `loading` flag set once at oninit and never
raised again, so it only ever disabled itself before the first answer. After
that every click fired two more requests, on top of the five second interval,
with nothing preventing two runs from overlapping -- and on a phone they do
overlap, since each answer closes its connection and the core serves them one at
a time. `load()` now refuses to start while one is running and always clears the
flag, including on the paths that throw.

Friend names came from a second collection of the friend list -- getFriendList
plus one getPeerDetails per friend, all at once -- run exactly once, at oninit:
a friend added afterwards stayed `Peer 1a2b3c4d…` until the page was reloaded.
network_data already does that work and keeps it in NetworkData.gpgDetails for
the whole session, so the page reads that and asks for a refresh at most once a
minute rather than never.

`formatBytes` was a second implementation of `rs.formatBytes`, printing MiB
where the statusbar, the chat and the file lists print MB for the same number.

The pie segments are rotated back to twelve o'clock, where a pie chart is read
from; the totals in the middle stay upright.
2026-08-23 12:51:13 +02:00
defnax
ae31ed5842 added the stats page 2026-08-22 22:14:53 +02:00
defnax
9a8870bfb2 restored changes 2026-08-20 21:01:34 +02:00
defnax
f148d57b29 Fixed popup dialog to get better visible on a phone 2026-08-18 19:11:00 +02:00
jolavillette
2159eab08e webui v151: a peer's message could make the browser fetch a URL of their choosing
renderChatMessage turns any <img src="..."> found in a received message into a
real <img>, and the browser then goes and gets it. On a distant chat -- carried
by a turtle tunnel precisely so that neither end knows where the other is -- that
hands the reader's address to whatever host the sender picked, and tells them
the moment the message was read. Pictures embedded by RetroShare travel as data:
URIs; anything else is now shown as the text it is rather than fetched.

The rest of this commit is the People tab paying for its lists.

"All Users" is every identity the node has ever seen -- this profile's gxsid_db
is 35 MB -- and the sidebar rendered all of them, firing one getIdDetails per row
from inside its own view. The list is capped at 200 rows with a line saying how
many are left, and the search narrows it.

jdenticon redraws an avatar's SVG on every call, and that call sat in the view of
every avatar on screen: once per avatar per redraw, and a redraw happens on every
answer of every poll. Same id and same size, same drawing -- memoised.

The history browser is mounted with the page and draws nothing until asked for,
so its oninit was the moment a *conversation* opened, not the moment somebody
wanted the history: opening a chat ran "give me every message ever stored" for a
panel nobody had asked for. It loads when it opens now, which also fixes the
chat page, where the panel was loaded once at mount and never again. Its overlay
follows the three others onto dvh.

Two small ones: adding or removing a contact from the context menu reloaded the
identity summaries alone, while isContact is read from rs.userList.userMap, which
only loadUsers() refreshes -- so the list kept showing the old state; and about
250 lines of unreachable code are gone, people_own_contacts.js entirely, the
"Own Identities" widget of people_ownids.js, the second search box of
people_util.js and the isSearched marking those two shared, which contactlist()
and sortUsers() still wrote from inside a view.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 10:06:22 +02:00
jolavillette
f239e1aba6 webui: the distant chat draft, the identity switch and the paperclip
Three things in the People chat pane, all about what happens between two
conversations.

The text being typed lived in a single page-wide field that nothing cleared when
the selected peer changed, while the per-peer session carried an inputMsg nobody
ever read. A message written to one contact was still in the box when the next
conversation opened, one Enter away from the wrong recipient. Every write now
goes through the session, and opening a conversation restores its own draft.

Changing the identity we talk as opened a second tunnel and abandoned the first:
the id is sha1(sorted(own || peer)), so another identity means another tunnel,
and nothing closed the one being left. It is closed now, before the new one is
asked for.

The paperclip pasted the path itself into the message -- the peer received
"/home/me/x.iso" and nothing else. It now publishes the file as an extra file
and sends the retroshare:// link the core answers with, which is what the chat
page does; the hashing runs behind a banner that says what is being hashed and
can stop it, since a file that exists but cannot be read is dropped silently by
ftExtraList and would otherwise be waited on for ever.

And the failed-send alert blamed a packet size limit that does not exist:
getMaxMessageSecuritySize() answers 0, unlimited, for distant chat, and the core
slices anything past 15000 characters and reassembles it. The picture
compression stays -- several megabytes of base64 through a turtle tunnel is
still a bad idea -- but says why it is there.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 10:06:21 +02:00
jolavillette
ccb70fec35 webui: the profile pane read two core fields the way they are not written
"Type" tested `mFlags === 14` against a bitfield. 14 is PGP_LINKED | PGP_KNOWN |
IS_OWN_ID, so the only identities that ever matched were our own signed ones: a
friend's signed identity carries 6, or 7 with the contact bit, and was labelled
"Anonymous ID". The bit to look at is RS_IDENTITY_FLAGS_PGP_LINKED, 0x2.

"Usage Statistics" mapped mServiceId over 1..8, but that field is an
RsServiceType -- 0x0211 for the identities, 0x0215 for the forums, 0x0217 for
the channels, 0x0012 for the chat. No case could match, so every line of the
panel came out as "Unknown (533)". The usage codes next to it are right, they
really do run 0 to 21; it is the service that was being read from another table.

The two timestamps read `.xint64` straight out of the field instead of going
through get64Num, which exists for exactly that: a 64 bit value arrives as
{xint64, xstr64} and large ones carry the string alone, where the pane then
shows "Invalid Date".

Details were also fetched once and kept for the whole session -- deliberately,
it is what makes the lists cheap -- which froze the reputation, the usage record
and the avatar of the profile being *looked at*. That one is now asked again
after a minute, over the top of what is displayed rather than by clearing it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 10:06:21 +02:00
jolavillette
04d4b148a6 webui: editing an identity erased its name and its avatar
The Edit dialog opens on an empty name field -- it is never filled from the
identity it was given -- and Save sends whatever stands in it, so an edit meant
for the picture alone renames the identity to nothing. The picture goes anyway:
updateIdentity(id, name, avatar, pseudonimous, pgpPassword) takes the avatar as
a mandatory parameter, p3IdService assigns it with no condition attached
(group.mImage = avatar), and the request carried none. A missing JSON member is
not "keep what you have", it is an empty image. The line that would have sent
it has been sitting there commented out.

So the name is filled in from the identity, an empty one is refused, and the
current avatar is always sent back -- with a file picker to replace it, since
the dialog now has to carry it either way.

Deleting had the opposite problem: it announced success without reading retval,
and refreshed nothing. watchOwnIds() is not a watcher, it listens for the event
refreshOwnIds() emits, so an identity deleted from this page stayed in the list
until something else happened to reload it.

Two more in the same file: a refused passphrase left the Create button disabled
on "Creating…" for good, since only .catch() cleared the flag and a refusal is a
perfectly valid answer; and the passphrase dialog asked for a "passpharse" then
reported "Successfully created identity." after an update.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 10:06:21 +02:00
jolavillette
00459bbbcb webui v150: Leave Chat reported a closed tunnel whatever the core answered
rsJsonApiRequest hands the callback the HTTP status, not the answer, and the
button read that as "the tunnel is closed": any reply at all, including one that
says nothing was closed, ended the conversation on screen. The core does report
it, in retval, so that is what is read now, and the ended card says which of the
two happened -- closed on request, or already gone before the click.

The status poll had the same deafness and is what let it happen. Once a tunnel
is gone from the core -- died of inaction, closed by the peer --
getDistantChatStatus answers false, and the poll only ever looked at the branch
where it answers true. So the last known status stayed on screen for good: a
conversation whose tunnel had been dead for a while kept its green dot and its
"You can talk", and Leave Chat then had, quite correctly, nothing to close. Two
consecutive false answers now end the conversation, with a line saying so, which
is the state the user was in.

Needs the libretroshare side to be meaningful:
fix/distant-chat-close-keeps-contact makes closeDistantChatConnexion report
whether it closed anything, and drop the distant chat contact it used to leave
behind.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 09:26:52 +02:00
jolavillette
6f2b72c3f1 webui v149: selecting a contact in People opened a distant chat tunnel
The right pane keeps its last tab in State.activeTab, and that state is global
rather than per contact. So the list item handler ends on "if the chat tab is
the one showing, connect" -- which is never true on a fresh page, and always
true afterwards. Once a conversation has been opened, every later click in the
contact list requests a GXS tunnel toward whoever was just selected: a network
action the other side sees, from a click that only meant "show me this profile".

Selecting somebody now shows their profile, and the tunnel waits for the Chat
Conversation tab. The three places that do mean it -- the tab itself, the Start
Chat button, the Chats list and its context menu -- are untouched.

The mirror case was broken the other way round. "Start private chat" from a chat
room calls setSelectedId(id, 'chat'), which preselects the chat tab on a page
that is not mounted yet; nothing ever opened the tunnel there, so the pane sat
on its Connecting spinner for good. That intent is explicit, so it is now
remembered and honoured once the own identities are loaded.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 09:03:23 +02:00
jolavillette
ee3836cfab webui v148: the Chats badge counted a sweep of every identity the node knows
Clicking Chats sets the counter climbing for minutes. It is not counting
conversations, it is watching a probe walk the whole identity list: the tab
re-runs preloadAllChatHistory(), which asks /rsHistory/getMessages once per
known identity, and the badge is recomputed from the answers as they land. On a
node that has seen twenty thousand identities that is twenty thousand requests,
four at a time, against a JSON API that answers one at a time and closes the
connection after each -- and it starts over at every click, on top of the three
calls the layout and the sidebar already make when the page opens.

Neither half of the probe can find anything.

Distant chat history is not stored under the peer's GXS id. The core keys it by
the tunnel id, sha1 of the two GXS ids sorted and truncated to sixteen bytes
(p3GxsTunnelService::makeGxsTunnelId), so the query only ever answers an empty
list and the previews appear solely for chats opened in this session. There is
no API to derive that id and no crypto.subtle outside a secure context, the web
UI being served over plain HTTP, so people_util now computes the digest and the
probe asks for the tunnels of our own identities against that peer.

Private chat history is keyed by a location, not by a person: the query passed
the PGP id where an RsPeerId is expected. It is half the length, the core cannot
parse it, so it builds a null id -- which is the key of the public broadcast
history -- and prints a stack trace for every request. 1714 of them in one log
here, over 979 distinct PGP keys. It now asks per location of the friend behind
the identity, which is where the messages actually are.

So the probe covers the peers a conversation can exist with -- contacts, peers
already in the map, identities belonging to our friends -- instead of every
identity ever seen, and it will not run twice within thirty seconds however many
times the tab is clicked. The badge and the list read chatHistoryMap directly:
it only ever holds peers with a real message, so the sweep of the identity list
on every redraw bought nothing, and identity details are fetched for the handful
of peers actually listed. The History dialog was asking the same two impossible
questions and now asks the right ones.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 20:51:51 +02:00
jolavillette
cd1875547f webui v147: the People distant chat displayed nothing of what the peer answered
Select a contact, Profile details, Start chat: the tunnel goes green, what you
type leaves and is echoed, and the answers never appear. They do arrive -- the
core posts an RsChatMessageEvent for every incoming message and the handler runs
-- they are just written into a list nobody displays.

Giving each peer its own session pointed State.chatMessages, the array the view
renders, at session.messages. loadChatMessages() then kept doing
State.chatMessages = data.msgs: that reassignment does not update the session,
it detaches from it. From that answer on there are two arrays -- the visible one
holding the history, your echo and the status notices, and the session one where
the event handler pushes everything the peer says. The `else if` fallback of the
handler cannot save it either, since the session is always found first. It fires
every time: the JSON API answers msgs: [] rather than nothing, so an empty
history detaches just as surely as a full one.

The session array is now the only one: it is mutated in place and
State.chatMessages is never reassigned, only re-pointed at it. Messages carry a
key -- direction, send time and text -- shared by the three sources, so the same
message coming from the history and from the live event is stored once, and the
status notices no longer need their manual text scan.

Two windows were losing messages besides. The core emits its "starting distant
chat" notice from inside initiateDistantChatConnexion, before the caller knows
the pid, and rswebui buffers every chat event it cannot deliver; the tab also
unregisters its handler when the user walks away. Both are covered by draining
that buffer -- when the chat opens, when the tab mounts, and when the tunnel
turns secure -- and by adopting the visible conversation for a message that
names the pid the view is already showing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17 20:38:03 +02:00
jolavillette
9428fc5542 webui v146: the attach dialog must be escapable while it hashes
Once hashing starts there is no way out: Cancel is disabled, the backdrop click
is guarded by the same flag, and the overlay covers the whole viewport, nav
included. The only exits are the browser's Back button and a reload -- and Back
does not even stop the poll, since the setTimeout chain runs off module state
that nothing resets, so it keeps asking once a second for the rest of the
session and the dialog is waiting again on the way back.

That would be harmless if the wait always ended, but the core drops a file it
failed to hash without a word: ftExtraList only records successes, so the file
never enters mHashedList and ExtraFileStatus() answers "not ready" for ever.
hashExtraFile() has already refused missing paths and directories by then, so
this is the file that exists but cannot be read -- permissions, a share
unmounted, an I/O error.

The red button therefore stays enabled and reads Stop while hashing, the
backdrop closes again, and leaving the view stops the poll: it writes its file
link into that view's textarea, so once the view is gone the answer has nowhere
to land anyway. The poll also backs off from one second to ten, since a large
file legitimately takes minutes and each request opens a new connection.
2026-08-16 17:44:51 +02:00
defnax
cdd29ab86f Fixing for mobile phone 2026-08-16 14:16:40 +02:00
defnax
d659977275 Added avatars before identity nicknames in the chat-room join selection. 2026-08-16 13:50:58 +02:00
defnax
ea1dbbd450
Merge branch 'improvements_v2' into fix/modal-dismiss-details-for-121 2026-08-16 13:39:38 +02:00
defnax
e203558443 Improved the “Add new file” popup for phones. 2026-08-16 13:36:15 +02:00
defnax
74aff9da5e
Merge branch 'improvements_v2' into perf/phone-request-storms-for-121 2026-08-16 13:32:19 +02:00
defnax
84b11b6320
Merge pull request #17 from jolavillette/fix/pending-friends-ghost-for-121
Remembered friends must expire, and go when the friend goes
2026-08-16 13:21:18 +02:00
defnax
62079e1fd7 Improved the ShareManager mobile layout:
Uses nearly the full phone viewport with safe spacing.
Keeps the folder list independently scrollable.
Keeps Add New and Edit buttons visible at the bottom.
Converts folder rows into labeled mobile cards.
Replaces the stray 0 with “No shared folders yet.”
Ensures nested dialogs appear above ShareManager.
2026-08-16 13:17:18 +02:00
jolavillette
b3bb96e55c webui v145: the web help dialog stays open, and the close button drifts
The Ok button of the web help confirmation opens the documentation in another
tab and left the dialog standing behind it, with nothing left to ask. It closes
now, like the one in the copy confirmation.

Every modal that gets a phone layout drops its padding from 1.5rem to 1rem, but
.close-btn is positioned against the box rather than the content, so it stayed
1.5rem from the edge and lined up with nothing. Corrected once in the modal
layout instead of in each of the five pages that override the padding.
2026-08-16 13:09:18 +02:00
jolavillette
2748b44fb2 webui v144: remembered friends must expire, and go when the friend goes
refreshGpgDetails() re-injects every remembered friend the core does not return,
and nothing ever removed one: a short-invite peer that never validates, or one
the user deletes, came back on the next refresh and survived a browser restart,
with no way to get rid of it from the web UI.

A remembered friend is a placeholder for the seconds the core needs to catch up
with an add that has just returned, so it now carries the time it was made and
is dropped once that window has passed. Removing a friend drops it immediately,
before the refresh that would have restored it -- and that refresh now waits for
removeFriend to answer instead of racing it.

The store is also keyed per node: it lives in localStorage, which is shared by
every RetroShare profile reached from the same browser, and their friend lists
have nothing to do with each other.
2026-08-16 13:08:25 +02:00
jolavillette
6b988dffa8 webui v143: the channel list never refreshed, and three different periods
The scope predicate of the channel list background task was entirely commented
out, so it returned undefined: setBackgroundTask stopped after the first
interval and the list was loaded once, never refreshed while the page stayed
open. It now tests the route like the boards one does.

The three group lists polled at three different periods: forums every 5 s,
boards every 30 s, channels never. Each poll fetches the whole summaries list,
and on a phone it costs a fresh TCP handshake on a server that answers one
request at a time. All three now share the boards period, named per page.
2026-08-16 13:06:50 +02:00
jolavillette
543a65f210 webui v142: stop three request storms that only hurt on a phone
Every JSON API answer carries `Connection: close` and the server runs its
service on a single thread, so each request costs a full TCP handshake and they
are answered one at a time. Over loopback a round trip is 0.1 ms and none of
this shows; over WiFi or 4G it is 20 to 80 ms and the three patterns below turn
into seconds of blank screen.

Chat room list: one getChatLobbyInfo per subscribed room, and nothing was
painted until the last answer arrived -- then only did the public room list get
asked for. Paint each room as it lands and start the public list immediately.

Forum post bodies: loadPostContent() is called from the view, and the body stays
null for the whole round trip, so every redraw fired the same getForumContent
again -- and each of the other posts' answers causes a redraw. An open thread
multiplied one request per post into one per post per redraw. Guarded by an
in-flight set, kept on failure so an unavailable post is asked for once per
visit rather than forever.

Chat history preload: two getMessages per known identity, hundreds of them at
once, filling the browser's six sockets and the single service thread while the
user waits for something else. Run four at a time. The duplicated response
handling of the two branches is now one function.
2026-08-16 13:05:57 +02:00
defnax
3190b4cb58 Fixes for phones
- The Graph shortcut is hidden from the default friend list.
- After selecting a friend, Network Graph remains available in the detail tabs.
- Desktop behavior is unchanged.
- File and picture attachments now share one paperclip button.
- The message field gains more horizontal space on phones.
2026-08-16 12:06:20 +02:00
defnax
d9a0428a26 Fixed mail composer popup heigth 2026-08-16 11:36:37 +02:00
jolavillette
2c38f04fa1 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.
2026-08-16 09:45:02 +02:00
defnax
4b523cb8ec Fixed issue on phone to view parcipants list 2026-08-15 22:59:21 +02:00
defnax
71688feac2 Fixes Ui issues
- Correct full-certificate friends being incorrectly marked “Pending validation.”
- Refresh identity lists immediately after creating an identity.
Update open chat-room and distant-chat identity selectors automatically.
- Replace the broken signed-identity password popup with a responsive mobile form.
- Allow creation of the first signed identity without requiring an existing signed identity.
Filter temporary all-zero GXS IDs.
- Wait for RetroShare to expose the real generated identity ID.
- Retry identity-detail loading when RetroShare temporarily returns empty data.
- Display the fetched nickname instead of “Unknown.”
2026-08-15 22:43:19 +02:00
defnax
1c615bdb89 Fixing adding friends via Short ID 2026-08-15 17:33:08 +02:00