Coder Social home page Coder Social logo

element-hq / hydrogen-web Goto Github PK

View Code? Open in Web Editor NEW
605.0 23.0 119.0 21.95 MB

Lightweight matrix client with legacy and mobile browser support

License: Apache License 2.0

JavaScript 39.88% HTML 7.95% Shell 0.10% CSS 3.04% Dockerfile 0.04% TypeScript 48.99%

hydrogen-web's Introduction

Hydrogen

A minimal Matrix chat client, focused on performance, offline functionality, and broad browser support. This is work in progress and not yet ready for primetime. Bug reports are welcome, but please don't file any feature requests or other missing things to be on par with Element Web.

Goals

Hydrogen's goals are:

  • Work well on desktop as well as mobile browsers
  • UI components can be easily used in isolation
  • It is a standalone webapp, but can also be easily embedded into an existing website/webapp to add chat capabilities.
  • Loading (unused) parts of the application after initial page load should be supported

For embedded usage, see the SDK instructions.

If you find this interesting, come and discuss on #hydrogen:matrix.org.

How to use

Hydrogen is deployed to hydrogen.element.io. You can also deploy Hydrogen on your own web server:

  1. Download the latest release package.
  2. Extract the package to the public directory of your web server.
  3. If this is your first deploy:
    1. copy config.sample.json to config.json and if needed, make any modifications (unless you've set up your own sygnal instance, you don't need to change anything in the push section).

    2. Disable caching entirely on the server for:

      • index.html
      • sw.js
      • config.json
      • All theme manifests referenced in the themeManifests of config.json, these files are typically called theme-{name}.json.

      These resources will still be cached client-side by the service worker. Because of this; you'll still need to refresh the app twice before config.json changes are applied.

Set up a dev environment

You can run Hydrogen locally by the following commands in the terminal:

  • yarn install (only the first time)
  • yarn start in the terminal

Now point your browser to http://localhost:3000. If you prefer, you can also use docker.

PS: You need nodejs, running yarn on top of any other js platform is not supported.

FAQ

Some frequently asked questions are answered here.

hydrogen-web's People

Contributors

aaaaalbert avatar ajbura avatar ara4n avatar benbz avatar bwindels avatar chagai95 avatar danilafe avatar elonsatoshi avatar germain-gg avatar half-shot avatar hughns avatar ibeckermayer avatar jcgruenhage avatar johennes avatar jryans avatar kaki-in avatar leccyril avatar madlittlemods avatar mattcen avatar melroy89 avatar midhunsureshr avatar moritzdietz avatar newbytee avatar prathap-p avatar psrpinto avatar robertlong avatar ryushar avatar sandhose avatar tawfiek avatar ynerant avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hydrogen-web's Issues

Unread state and notification in room list

  • show unread state in room list. A function should be passed to the session to determine whether an event can be displayed and hence should cause a room to be marked as unread. This will check in the viewmodel whether there is a tile for it.
  • show notification count; use highlight_count and notification_count in sync response
  • sort room list by recent activity and notification count.

File & image uploads/downloads

  • show images in timeline
  • automatically load images (when in view?), have service worker cache them.
  • show files in timeline, allow download
  • upload files, storing them locally in indexedb before sending

SSO Login

SAML / OpenID Connect login support

Heroes don't handle member leave events well

{
  "type": "m.room.member",
  "sender": "@bruno1:localhost",
  "content": {
    "membership": "leave"
  },
  "state_key": "@bruno1:localhost",
  "origin_server_ts": 1598466841459,
  "unsigned": {
    "replaces_state": "$JGaEFO-E10_WO8ii6gHAtb5kYRRqFIGa15RZqH23Ntc",
    "prev_content": {
      "membership": "join",
      "displayname": "Problembär Bruno",
      "avatar_url": "mxc://localhost/lsZyAmPfrxGYbtQTUdXWenjC"
    },
    "prev_sender": "@bruno1:localhost",
    "age": 83
  },
  "event_id": "$DY_s7cDSr_HvgyjQe183kSYeyxHFcRLAGbiX8Vepduo"
}

Synapse doesn't send displayname nor avatar_url, hydrogen updates the member without these fields and the sort function in Heroes.applyChanges fails, bricking opening a session.

Throwing while adding to the timeline will result in all the messages in the backfill or load-from-storage missing from the timeline

E.g. element-hq/element-meta#1390 was an image in with no content.url which threw in ImageTile, blocking 10 or so messages from ever being displayed, without a clear error.

We should have a mechanism where we render the tile with errorToDOM or something similar.

Also we should have a safe function to read fields/paths of an event, and act predictably when that field is missing/wrong type/ ...

Room list ordering isn't always stable

Sometimes when you close a room/go to another one that was unread, the room you left goes all the way to the bottom or somewhere close.

One reason could be that the properties of the room have changed without causing a rerendering somehow, so what you see isn't what is being sorted anymore. Unsure how that could happen though.

Another reason could be that lastMessageTimestamp ends up something else than null or a number (e.g. undefined).

Redactions

I don't think we need the "relations infrastructure" for this, as we when we receive a redaction, we either:

  • have the redacted event in storage, and we remove the fields, etc ...
  • don't have the redacted event. We don't need to do anything, and if we fetch it in the future, we will get the already redacted version.

Accept invites

  • invite_state doesn't update over /sync
  • can we reuse room summary? need to clear when joining
  • rely on filter operator to split membership=join from membership=invite?

Session backup (read-only)

Implement session backup so we can read encrypted history from before we logged in.

As we don't have a concept of trust yet, we will only verify that the backup came from a session we trust by the fact that you enter the 4S passphrase, which gives us the session backup key.

Accept invites

  • invite_state doesn't update over /sync
  • can we reuse room summary? need to clear when joining
  • rely on filter operator to split membership=join from membership=invite?

Add support for IE11

  • compile down to ES5
  • include all needed polyfills
  • implement XHR request handling (instead of fetch)
  • initial loading message isn't rendered for some reason. Problem with bindings?
  • find solution for usage of DOMElement.closest
  • fix likely storage errors
  • Element.remove method not supported

Messages are sent out of order

used to happen only after we got rate limited and we had to refresh. Recently I've seen it happen when only sending 2 messages in fresh page load.

Sync after reconnecting can stall

After the /versions response comes back successfully to the Reconnector, sync will be retried. If the server is not fully ready yet to respond to sync requests, this can stall (seemingly) forever with "Trying to reconnect now ...". Not sure how this can happen as the sync request has a timeout of of 30+80s now... I waited for what I think was longer than 1min50s.

End-to-end encryption

TODO

  • have a basic idea of how we would build a wasm/asm.js version of the sdk. See https://github.com/vector-im/crypto-wrapper-hydrogen/, but deciding not to go this way, mainly because it's a PITA to debug and because we will need more flexibility to make E2EE fast enough in IE11 than the sdk can offer (run olm decryption in a web worker, ...), and asm.js seems very slow in IE11 so the fewer asm.js (e.g. libolm) we can run, the better.
  • persist olm account in session store
  • upload identity keys and OTKs after login
  • sync device_one_time_keys_count and upload more OTKs if needed
  • device tracking in e2ee rooms
  • decrypt olm messages, persisting olm sessions
  • handle to_device messages and decrypt them
  • store room keys shared over olm as inbound megolm sessions
  • decrypt megolm encrypted messages
  • don't remove olmAccount and areDeviceKeysUploaded keys from session store when clearing the session, otherwise e2ee keys would rotate while keeping same device id/access token. Important to do this before doing a release!
  • encrypt olm messages over to_device
  • start new megolm outbound sessions, store them and share them over olm with required devices
  • send megolm encrypted messages
  • mark events as verified
  • rotate megolm session when member changes , and share our outbound session at the current ratchet position with new members?
  • make it fast on IE11
  • make sure decryption errors don't block other events from being decryption, or block the client.
  • block multiple open sessions
  • write unit tests

Remaining questions/remarks wrt to rust-sdk (not relevant anymore atm)

  • how to implement CryptoStore? Try to anticipate all the data that will be requested and preload a memory store? Or actually implement something that calls into idb? If this breaks, it would be painful to debug. E.g. before we call receive_sync_response, go over all to_device messages encrypted with olm and get their sender_key.
  • One way or another, I don't think it will be very feasible to have the OlmMachine live longer than one of our txns.
  • sync responses will be parsed and loaded into memory twice :(

Show display name and avatar on messages

We need to store either the most recent m.room.member eventId or the display name and avatar on an incoming event. We can have a FILO cache of x members for synced messages, and load a state event from store if it's not in there. But how do we handle filling gaps? How do we find out what the room state was at the beginning of the fragment we're trying to backfill (end, forward-fill, respectively).

Structural persisted logging

  • implement logger persisted in IDB
  • reduce sync logging volume by setting loglevel in smart way
    • log catchup syncs in detail
    • log any sync taking over 1 second?
    • log device messages in detail always
    • log room ids in sync
    • only log detailed sync if there is a error
    • only log requests if they are >= 400
  • log sending messages
  • log opening a room
  • log login
  • log opening account
  • add export/clear button in settings
  • add button to upload to rageshake server

Join room

Join room from room directory & link.

This will allow hydrogen to be added to matrix.to as well

failing to persist initial sync events and fragments

failing to persist initial sync on firefox with local "main" synapse on bruno2

I get a ton of:

Error: add on undefined failed: (name: TransactionInactiveError) (code: TransactionInactiveError) A request was placed against a transaction which is currently not active, or which is finished.

and no items in timelineEvents or timelineFragments are stored, presumably something is going wrong in the SyncWriter.
The error was not introduced in bwindels/fixconstrainterror-part2, and is already on master. Use git bisect to find out where it was introduced?

it's easy to repro on my local ff, just clear the bruno2 session and click on it to do an initial sync. the console is full of errors

Timeline does not update even though sync is running

Timeline stopped showing new incoming message. Clicking the room tile again (several times? can't remember) refreshed the timeline. Might have clicked the room tile quite a few times before and/or have scrolled up/filled gaps before this happened.

Confirmed sync was running with the devtools. No errors in the console.

Did something close the timeline (e.g. disposed the TimelineViewModel?) this is on bwindels/reconnect btw.

Unread state and notification in room list

  • show unread state in room list. A function should be passed to the session to determine whether an event can be displayed and hence should cause a room to be marked as unread. This will check in the viewmodel whether there is a tile for it.
  • mute toggle per room
  • show notification count; use highlight_count and notification_count in sync response
  • sort room list by recent activity and notification count.

Constraint error on byEventId during sync

Error in status bar:

Sync failed because of Error: wrapped DOMException: (name: ConstraintError) (code: ConstraintError) Unable to add key to index 'byEventId': at least one key does not satisfy the uniqueness requirements.

In console:

Uncaught (in promise) Error: add on undefined failed: (name: ConstraintError) (code: ConstraintError) Unable to add key to index 'byEventId': at least one key does not satisfy the uniqueness requirements.
    at Store.add (brawl.js:3685)
8brawl.js:3685 Uncaught (in promise) Error: add on undefined failed: (name: AbortError) (code: AbortError) The transaction was aborted, so the request cannot be fulfilled.
    at Store.add (brawl.js:3685)
brawl.js:3676 Uncaught (in promise) Error: put on undefined failed: (name: AbortError) (code: AbortError) The transaction was aborted, so the request cannot be fulfilled.
    at Store.put (brawl.js:3676)
brawl.js:686 unable to commit sync tranaction
_syncRequest @ brawl.js:686

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.