jam
Showing unread indicators / counts for a chat app using Phoenix channels
I’m using Phoenix channels to build a chat app similar to Discord. I’m new to Elixir and Phoenix and wouldn’t consider myself to be a backend wizard. I’m wondering how you might handle showing unread indicators / counts.
Let’s assume a user belongs to multiple organizations and each of those has multiple rooms. Similar to Discord, I’d like be able to show:
- An unread dot next to each organization with unreads
- Bold the name of the unread room within an organization
I’ve set up my channels like this:
channel "user:*", AppWeb.UserChannel
channel "org:*", AppWeb.OrgChannel
channel "room:*", AppWeb.RoomChannel
I have a somewhat working solution but it feels a bit hacky so I’m wondering what a best practice solution might look like. Currently, I’m doing this:
- I have
organizations,rooms,messages,org_membershipsandroom_membershipstables. - I store a
last_read_message_idon theroom_membershipstable and use it in my ecto queries. - When the user logs in, I join them to the
UserChannelwhich fetches their organizations and each has a virtualized boolean field forunread. - When the user navigates to an organization, I join them to the
OrgChannelwhich fetches the rooms for that organization and each has a virtualized field forunread_count. I assign theroomsto thesocket. - When the user navigates to a room, I join them to the
RoomChannelwhich fetches the messages for that room. - When a user sends a message, I determine which users should receive that message and use
Phoenix.PubSubto broadcast that back to their respectiveUserChannelto update the organization booleanunreadfield and to theOrgChannelto increment theunread_countfor that room if it’s found in the socket’srooms. These are both pushed to the client so that I can show the unread indicators as described above.
My solution also seems to kind of hit a roadblock when taking into account direct messages because they aren’t tied to a particular organization. Right now a direct message is treated the same as a regular room but with type: “dm” and organization_id: null. Open to ideas here too.
I considered sending the unread_count for all rooms a user is a member of after they log in but that seemed like a bad idea if they are in say 20+ organizations each with 20+ rooms. Maybe my intuition here is wrong and it’s ok as long as the payload is small with just the room_id, organization_id, and the unread_count?
I’m guessing this is well-trodden territory and would appreciate any tips you might have.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #hex









