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.
Fix bug introduced in 11fb32:
When loading an encrypted thumbnail, QML lacks the decryption dict for
half a second at first.
When calling python like this, python calls the wrong matrix API
for fetching the encrypted thumbnail, and the added retry code
would be forever stuck.
The retry code has been moved to QML, and now works for all HImage.
Current features:
- Show scaled up thumbnail while the full image is loading
- Click to alternate between scaling mode (or reset zoom if not 1x)
- Click outside of image to close
- Double click to toggle fullscreen
- Middle click to open externally (also for thumbnail in timeline)
- Right click anywhere to close
- Ctrl+wheel to zoom
- Click-drag to pan when image larger than window
Prevents this: user paste image (image provider retrieves the clipboard
image to show it as a thumbnail),
and immediatly presses enter (retrieves the image to convert it and send
to Python); the two calls would run at the same time instead of one
waiting for the other to set the cache.
Will be used to show a preview before uploading image from clipboard.
Transforming the clipboard image to PNG (or any other real format) is
slow and freezes the GUI, with the provider we can display it directly.
If the requested object in states.json exists but doesn't contain the
property we're looking for, return the default value (passed to the
function) instead of undefined.
When auto-expanding a pane and showing it as an overlay because of
narrow window, make the chat keep the width it had before.
This makes the transition less jarring, reduces the amount of text seen
through a transparent pane, and fix making one pane overlay expanding
the other.
If the room pane is below the default width (by user resizing or because
of narrow window), go to the room settings or a member profile will
automatically expand it as needed.
The pane goes back to its previous size once the settings/profile is
left.
If the window is narrow enough that expanding the pane normally would
reduce the timeline's width past its minimum, the pane is shown as an
overlay instead.
The attributes by mistake used nio.AsyncClient.user instead of the
proper user_id. If the user logged in with a partial username instead of
typing their full ID, the can_ attributes (e.g. can_kick) would always
be False.
The Timeline EventList is the only HListView that uses it. For other
list views, it interferes with items like text fields which need to set
cursor shape by themselves.
- Rename ButtonLayout module to just Buttons
- Rename ButtonLayout into AutoDirectionLayout and move it to Base,
it's useful not just for buttons
- Rename OtherButton into GroupButton, which is now the base of all
other Buttons buttons
- Add generic (Positive|Middle|Negative)Button components, which are now
the base for (Apply|Cancel)Button
If the account passed to `saved_accounts.update()` doesn't exist in the
config file, return instead of failing with a KeyError.
An account can be absent from the file if "Remember my account" was
unchecked on login, or if the file hasn't been updated yet on disk after
login (race condition).