Send a pseudo-reply consisting of two messages: a `m.text` which is just
a reply with an empty body, then the file event itself.
This is a workaround to the restriction imposed by the Matrix API,
which prevents us from simply attaching a reply to a media event:
https://matrix.org/docs/spec/client_server/latest#rich-replies
These cause problems with the composer alias parsing code.
If an alias from the config file has whitespace, only the first word
will be taken into account (ignoring any leading or trailing whitespace).
Simplify the code, make it more declarative, and improve the reliability
of sending typing notifications (notably when changing the used alias in
the middle of a message).
If the chat was opened under e.g. "@user1:example.org", but the
composer text is "o abc" where "o" is a composer alias for
"@other_account:example.org", save the composer text to state.json as
"@user1:example.org" and not the alias user.
thumbnail() and download() were remaining.
Use a direct and carefully chosen MatrixClient's methods instead to
avoid problems mentioned in the previous commit 7502c1.
Causes problem if one of the candidate client is on a server that
doesn't federate (e.g. a local one). Move the `get_profile()` function
from Backend to MatrixClient.
Having a HoverHandler covering the root ApplicationWindow causes
problems for some Qt Quick Controls with pen/touch, e.g. it's impossible
to focus a TextArea/TextField.
The HoverHandler is moved to HToolTip (since it's used for those),
targets the ApplicationWindow but is now only enabled while a tooltip is
visible.
Fix the AutoCompletedMembers filter model to ensure that it doesn't
pick all the items from the corresponding room member model on startup,
wait until the user actually uses the completion feature to fill it.
If the display name of a user is blank (e.g. just a space character),
autocomplete it as a user ID.
If the display name starts or ends with whitespace, trim it.
`preeditText` is partial input from IME and touchscreen
autocompleting keyboards, consider it together with `text` for the
`getWordAt()` function.
This should allow user autocompletion to work properly in these
specific conditions.
Bug introduced in 6b907, made the cursor stay as a normal arrow when
hovering text fields/areas inside a HFlickable due to the
HKineticScrollingDisabler's width/height being incorrectly set.
rather than passing an entire filter dict for every single syncs.
This shortens the request URL and prevents troubles with some servers
that have an absurdly low max URL length (e.g. halogen.city).
Previously, member events in initial syncs (unless user had "hide member
events" and "hide profile events" set to false in their config) were
completely discarded with the help of a sync filter, instead of simply
being hidden like events loaded from room backfilling.
This was done due to the common case of rooms getting only
userconfig-ignored/hidden events on startup (especially with the
low number of initial events requested for lazy initial sync),
and thus having nothing to show as "last message" in
the room list (room delegate subtitles).
Other problems resulted from this, like missing join/leave events
when the config was set to hide profile events but not other
member events, and the "Members not synced" (#54) in encrypted room
with recent discarded member events.
The discarding filter is no longer used. Instead, if a room in the room
list has no visible "last message" and is currently visible to the user,
messages will be lazily fetched until we find something adequate or the
room goes out of view.
Contact the server's .well-known API before anything to get
available login flows instead of blindly assuming it will be
m.login.password, and to get the server's real URL instead of
requiring users to remember that e.g. it's "chat.privacytools.io"
and not just "privacytools.io" despite user IDs making it look like so.
The server field will also now remember the last accepted URL.
While a user file write operation #1 was queued in the _write_loop,
it was possible meanwhile for another function to read the file
(the current old version on disk), add some data to it,
add submit the write (operation #2).
The modifications from operatio #1 were then completly lost at best.
Compression with Pillow can take long, especially with large
clipboard PNG images.
Doing this in a separate process prevents the async event loop from
getting blocked, and allows multiple compression operations to run in
parallel.
Making the window narrow enough to switch to "mobile mode", then big
again would trigger a signal in SettingsView that switched focus to it,
even when it wasn't visible.
It's possible to get a MatrixForbidden error when trying to retrieve a
offline room member's presence, if that member actually left the room
but the server hasn't yet sent the update.
This required us to set the media downloaded local path on events
entirely from python instead of simply lazy-fetching them when needed
from QML, due to pyotherside's async nature and files that must be open
in a certain order.
A healthy client must not only have a sync task running, but also have
finished its initial sync and have been succesful in its last sync
attempt.
The previous weak requirement caused this issue:
Have two clients, one on a failing server, and try to fetch a media,
thumbnail or profile: since these functions don't need auth, any
healthy client is picked to do the request, but the previous
requirement made it possible to pick the failing client.
When an event was highlighted with the keyboard, right clicking a
message and clicking "Copy text" would always copy the message that was
highlighted instead of the one the user aimed for.
Replace the poorly implemented 2-in-1 "copy address" media event
menu option with:
- Copy <mediaType> address: visible for non-encrypted media, always
copies the http URL
- Copy local path: always visible for already downloaded media, even if
they were downloaded before mirage was started
This involved a refactoring to move all the media handling functions
(downloading, opening externally, etc) out of the Event delegates and
into the EventList, which manage keybinds instead.
This should also be better for performance since all these functions are
no longer duplicated for every Event in view.
Other user-noticable change: clicking on non-image media will
always download and open them no matter if the room is encrypted or not,
instead of opening non-encrypted files in browser like before. It will
be possible to still do that with an "open externally" command later.