Commit Graph

715 Commits

Author SHA1 Message Date
defnax
87f1aa8e28 feat(chat): support Ctrl+Enter and auto-resize for multiline chat messages
- Enable Ctrl+Enter (and Cmd+Enter) to insert a newline without sending
- Prevent plain Enter send handler when modifier keys (Ctrl/Cmd) are pressed
- Support dynamic multiline auto-resizing across Lobby, People, and Network chats
- Preserve Shift+Enter standard newline behavior
2026-09-09 22:59:37 +02:00
defnax
2bca038a4a fix(ui): remove button inset shadow and fix missing empty-state icons
- Prevent 3D inset box-shadow from bleeding into close and icon buttons
- Fix missing glyph in Chat History Browser by switching far.fa-comments to fas
- Add .far fallback mapping to Font Awesome Solid font family
- Add hover styling for modal close controls
2026-09-09 22:36:28 +02:00
defnax
20e2180cdf fix(ui): unify flat emoji picker styling
- Unify Mail composer emoji picker with standard flat design
- Remove duplicate SCSS blocks and prevent button shadow bleeding
2026-09-09 22:24:05 +02:00
defnax
0af8d7e7f6 Removed freshVnode and private tag inspection completely
Added standard component and view function support
2026-09-09 21:57:19 +02:00
defnax
09f071c97d Make shared comment component for boards and channels 2026-09-09 21:17:07 +02:00
defnax
7a57e78380 Removed the dead menu button 2026-09-09 21:04:16 +02:00
defnax
2c6aa9bf21 Fix the backdrop issue 2026-09-09 20:50:08 +02:00
defnax
f4663453fd Fixed. The mobile drawer backdrop is now visible and accepts clicks while open, allowing the existing tap-outside handler to close it. 2026-09-09 20:41:27 +02:00
defnax
7bdda39927 Fixed. Successful votes now fetch fresh content for the affected post, bypassing the board cache.
Any older board load finishes first so it can’t overwrite the new totals.
2026-09-09 20:36:58 +02:00
defnax
8b90b501b9 Fixed. The in-flight key is now removed in finally, so failed requests can be retried while concurrent duplicates remain blocked. 2026-09-09 20:34:58 +02:00
defnax
c364ef590e Fixed. Graph layout now runs in short batches that yield to the UI.
New requests or leaving the graph cancel unfinished calculations.
2026-09-09 20:32:24 +02:00
defnax
7aecf8fae7 Fixed. The friend cache now belongs to the current account, server, and login session.
Responses from an old login can’t repopulate it.
2026-09-09 20:29:31 +02:00
defnax
95e1e6d1cc Fixed. Hash-status polling now stops after five minutes, and Cancel works while hashing.
Late responses after cancellation are ignored.
2026-09-09 20:27:01 +02:00
defnax
4b69ef0d52 History callbacks now verify the active room and request before changing messages or pagination state. .
This covers initial and older-history loads
2026-09-09 20:24:00 +02:00
defnax
d7f55c16f1 Fixed. Valid retroshare://file attachments now survive HTML removal and provide a clickable download action. 2026-09-09 20:21:47 +02:00
defnax
158eb0af34 The send callback now uses saved peer and friend IDs.
It updates the original friend’s preview and only adds the message to the visible chat if it still matches.
2026-09-09 20:15:42 +02:00
defnax
05538da939 Send callbacks now use the original chat session, recipient, and identity.
Failed sends restore the original conversation’s draft without overwriting newer typing.
2026-09-09 20:13:25 +02:00
defnax
bfccebc673 Fixed. History preloading now uses the queue from network_data.js, limiting it to three simultaneous requests. Repeated calls share the active preload. 2026-09-09 20:10:06 +02:00
defnax
efb4028c78 Each request now keeps its own HTTP status, preventing concurrent requests from mixing up error results or connection status. 2026-09-09 20:03:05 +02:00
defnax
0c4256c5fe Fixed by placing a native button inside the heading, preserving its appearance and adding a visible keyboard focus outline
Enter and Space now trigger the existing comments action.
2026-09-09 19:59:34 +02:00
defnax
d60cf75dc7 Images extracted from post text now require embedded data.
- remote image URLs won’t load and expose readers’ IP addresses.
2026-09-09 19:47:37 +02:00
defnax
9b609012a2 Implemented for phone mode
In Chat → Details, every other participant now has three buttons:
- Chat — starts a private chat
- Mail — opens mail compose for that identity
- Details — opens their People profile
2026-08-31 12:24:41 +02:00
defnax
40087d1a5c Fixed the phone alignment 2026-08-31 12:01:55 +02:00
defnax
2c7f1e9cf3
Merge pull request #29 from jolavillette/fix/chat-fixes-for-121
Chat fixes from a phone: own messages, participants, distant chat, request storms, Debug page
2026-08-30 14:46:34 +02:00
jolavillette
2173503922 webui v170: scrolling up for older messages no longer reloads the page
On a phone, scrolling a conversation to its top to read further back is
the same gesture as the browser's pull-to-refresh once the pane cannot
scroll any more: the page reloaded in the middle of the conversation.
The message panes and the page containers now contain the overscroll,
and the document never turns it into a reload.
2026-08-30 13:54:15 +02:00
jolavillette
7a05827a2b webui v169: private chat reads further back by scrolling up
The private chat pane showed the last fifty messages of the tunnel just
opened and nothing else: no way to scroll further back, and nothing of
what was said with the same contact under another of our identities or
over direct chat -- all of that only in the history browser.

The pane now reads the same sources as the browser: one distant chat
file per own identity (the tunnel id is derived from the pair) and the
direct chat file of every location of the friend behind the identity.
The first load takes a page of each; scrolling near the top asks every
source for a bigger slice, the same mechanism as the chat rooms since
v157, the reader kept in place while the slice is inserted above. Once
every source answers with fewer than asked, nothing older is fetched.
2026-08-30 10:51:07 +02:00
jolavillette
a04c3f4bee webui v168: scroll to the tunnel status line when it lands
"Tunnel is secured. You can talk!" was appended to the conversation
without scrolling to it, so on a phone it sat below the fold and the
tunnel looked stuck on connecting. Same for "Your partner closed the
conversation". Scroll when the line is really new (the helper drops
duplicates) and the contact is still the one on screen.
2026-08-29 19:02:00 +02:00
jolavillette
efdc5edd39 webui v167: a stale tunnel poll ended the next conversation
Selecting a contact from a chat room (setSelectedId) changed the
selected identity but left the page-wide chat fields -- chatPid, status,
messages -- pointing at the previous contact's tunnel. The People page
then started its status poll on that pid at mount; the core no longer
knew it, two "false" answers later the poll wrote "tunnel is gone" into
the NEW contact's session and flagged the conversation as ended, while
the real tunnel was still coming up in the desktop window. On a slow link
the poll answers land late enough to overwrite the state of the
conversation opened meanwhile.

setSelectedId now resets the page chat state to the selected contact's
own session; the mount-time poll only starts on a pid that belongs to the
selected contact; and every poll answer is dropped unless it is about the
pid and the contact it was asked for. The "ended" card also says what
happened when the tunnel went away by itself, instead of "you closed it".
2026-08-29 18:50:28 +02:00
jolavillette
1111019861 webui v166: the friend sweep, four requests per location, all at once
Every mount of the Network, People, Home, Statistics or Graph pages
redid Data.refreshGpgDetails(): getFriendList, then for every location
getPeerDetails, isOnline, getCustomStateString and getStatus -- four
requests per location, fired together through Promise.all. With two
thousand locations that is eight thousand requests filling the browser's
six sockets, and on a phone behind a slow link every interactive request
-- opening a distant chat, the tunnel status poll, a chat message --
queued for minutes behind them. The Debug page showed it as a scroll of
getPeerDetails.

Now: one getOnlineList replaces the per-location isOnline; the status
string and status value are asked only for peers that are online; the
getPeerDetails sweep runs three at a time, the list filling as answers
land on a first load; the result is kept for five minutes, later mounts
only refreshing the online flags with that one request, and concurrent
callers share the sweep in flight. Adding or removing a friend forces a
full sweep.
2026-08-29 18:43:14 +02:00
jolavillette
410359b4fa webui v165: a Debug page
The API timings went into the phone status sheet in v162; a page of
their own reads better and works in the wide layout too. /debug, in the
rail and in the phone's More sheet: the web UI build and the core
version with its round trip, a Reload button, requests in flight, the
last sendChat round trip, the five slowest and the twenty last requests,
the event stream (bytes, last event, reconnections), and a reset. The
status sheet keeps the version label and its Reload button only.
2026-08-29 13:01:50 +02:00
jolavillette
4e3530cc20 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.
2026-08-29 13:00:02 +02:00
jolavillette
74155dafbc webui v163: adopt a distant chat tunnel that already exists
A tunnel to a contact can exist without the web UI knowing: opened from
the desktop window, or by the peer, and possibly under another of our
identities. The page always asked the core for a tunnel from its own
default identity (the first one), so for any other identity the core dug
a second tunnel and the phone sat on "Connecting" while the desktop
showed the first one green.

The tunnel id is sha1(sorted(own || peer)), computable here, so before
opening one the page now asks getDistantChatStatus for the id of every
own identity and adopts the live tunnel (status 2), else any the core
still holds, switching "Chatting as" to that identity. An explicit
identity switch keeps opening what the user asked for. Late answers for a
contact the user has left are dropped.
2026-08-29 12:53:47 +02:00
jolavillette
62a3ced094 webui v162: API timings in the phone status sheet
A message typed on a phone far from the core takes ten to twenty seconds
to show up, and nothing on the phone says where the seconds go: a slow
request on its own points at the core, many requests pending at once
points at the browser's six sockets -- one of them held by the event
stream -- or at the link in between.

rswebui.js now counts requests in flight, times every request, keeps the
last /rsChats/sendChat round trip and the five slowest requests, and
stamps the event stream (bytes received, last event, reconnections). The
phone status sheet shows them under the version label.
2026-08-29 12:37:17 +02:00
jolavillette
e9d9db3021 webui v161: chat room participants reachable on a phone
Below 900px the participants column of a room was simply display: none,
and the only way to a participant's menu -- Start private chat, Send
Message, mute, opinions -- was a right click, which a phone does not have.
The Details tab lists the room's known identities, but from the static
getChatLobbyInfo answer and without the menu.

Add a Participants button to the room header, shown below 900px only,
that opens the same column as a sheet over the messages, with a close
button in its title. Where the sheet applies, or on a device without
hover, a tap on a participant opens its menu; the right click keeps
working elsewhere. The sheet closes when a menu item leaves the page and
whenever another room is loaded.
2026-08-29 12:18:11 +02:00
jolavillette
c2c2312dfb webui v160: show our own chat room messages typed in another client
A chat room message sent from the desktop GUI (or any other client of the
same core) never appeared live in the web UI; it only showed up after
leaving and reopening the room, through the history.

The core posts a peer's message twice on RsEventType::CHAT_SERVICE, as an
RsChatServiceEvent {mEventCode: CHAT_MESSAGE_RECEIVED, mMsg} and as an
RsChatMessageEvent {mChatMessage} (p3ChatService::handleRecvChatMsgItem).
Our own messages are posted once, as the RsChatServiceEvent only
(DistributedChatService::sendLobbyChat, p3ChatService::sendChat). The
event queue handler only read mChatMessage, so the RsChatServiceEvent fell
through to the administrative branch and was dropped.

Read the message from mMsg as well, but only when incoming === false: a
peer's message must keep arriving once, since the room and direct chat
unread counters are bumped before the receivers dedup by message key.
Our own message typed in the web UI itself still arrives (echo + event)
and is dropped by that dedup.
2026-08-29 11:55:23 +02:00
defnax
3037e6c634
Merge pull request #28 from jolavillette/fix/decline-invite-resync-for-121
Decline invitation: resync when the core no longer holds it
2026-08-28 11:05:14 +02:00
jolavillette
7e50f5c5d6 webui v159: a refused invitation the core no longer has must leave the list
Reported: Decline answers "RetroShare could not decline this invitation".

denyLobbyInvite() returns false for exactly one reason -- the id is not in the
core's invite queue, and DistributedChatService prints "lobby invite not in
cache" when that happens. That queue lives in memory only, so a core restart
empties it while this list still shows what it held before; the entry then can
be neither accepted nor refused, and it keeps the Chat badge lit for good, which
is what the Decline button was added to prevent.

So a refusal the core does not recognise now removes the invitation here anyway
and re-reads the queue, and says so. A request that gets no answer at all is
kept apart: nothing was decided, so nothing is dropped.
2026-08-28 03:17:10 +02:00
defnax
de06c5fcae
Merge pull request #27 from jolavillette/fix/chatroom-invites-for-121
Room invitations: allow declining, and stop reading a field they do not carry
2026-08-27 20:01:36 +02:00
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
b2c4bb703c
Merge pull request #26 from jolavillette/feature/chatroom-load-older-for-121
Chat rooms: read further back by scrolling up
2026-08-27 15:21:09 +02:00
defnax
7b1c182e91
Merge branch 'improvements_v2' into feature/chatroom-load-older-for-121 2026-08-27 15:20:58 +02:00
defnax
2f89c804fe
Merge pull request #24 from jolavillette/fix/mail-unread-badge-for-121
Mail badge: reading a message must not untrash it, and stop recounting per redraw
2026-08-27 15:18:59 +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