Nope but it'd be relatively straightforward to add...
If only I could code...
Well, I think you're probably not the only person interested in this feature, so someone else may add it :)
Thanks Tim - fyi, what's the formal status of Zulip as a project re: governance and commited developers - have Dropbox assigned people formally to Zulip etc. etc. The project looks great but it would be cool to know how much 'backing' there is, so to speak... can you point me at anything?
I was thinking about giving it a shot, but it might be a little out of my grasp. I looked at compose.js in static/js and saw there is a is_composing_message variable, and a compose.composing() method. Something like that needs to be paired with the specific chat room or private message they're composing in, and then sent to the server for relay to that chat room/person. I'm still wrapping my head around the code base though. Pointers appreciated.
On thinking about this a bit more, this is perhaps technically straightforward but is nontrivial from a UI design perspective.
I think we'll want to start with just doing it for PMs since the UI questions about where to display it are simpler there.
@r0fls you should check out the new feature tutorial (see #93) to see how to make data flow through the backend system. For the frontend piece, I think we'll want to add a hook that runs whenever composing a message starts (which is probably starting typing, not opening a compose box, since it's easy to do the latter with no intent to write) and ends and calls a new endpoint on the backend to notify about changes to a user's typing state. The zerver/lib/actions.py function to action a state change can update the stored status (maybe we want to use something fast and short-term like redis or memcached?) and then send an event notifying the target user's clients about the typing.
The tricky things for this feature in particular that come in are:
(1) How do we manage the logic around state changes and timeouts? This needs to be on the backend or the person being typed at's browser, for the case where a user starts typing and then their computer drops off the network.
(2) Where in the UI do we display typing notifications in a way that is visible but not obtrusive?
(2) is probably the hardest problem so we might want to try doing a simple mockup for where we'd put them before putting a lot of time into an implementation.
I would say that the "user is typing" notification could fade out if they have stopped typing (or the computer dropped off the network) for more than 10 seconds
I think a simple one-line message right above the "New stream message" and "New private message" buttons or above the name of the stream and topic if the compose input box is visible. This would be unintrusive but also directly where you have your focus at the bottom of the list of existing messages and above where you're composing your response. For streams, if multiple users are typing at once it could simply change to state "Users are typing..." instead of "John Smith is typing..."
Add a draft roadmap doc.
@timabbott, can I take a shot at this?
How about this design?
Looks great to me!
Sure, yeah, that seems like a great project. We can start with that design and iterate from there (most of the technical complexity is going to be in the backend implementation anyway). And is probably a good project for getting deeper familiarity with the Tornado event system.
A few notes on the data model for this:
A few thoughts - according to http://www.businessinsider.com/the-imessage-dots-explained-2016-1
These numbers can be changed, of course, in the following example they are:
Clients can make a GET request to (say) /users_typing/realm/thread_id once every thirty seconds based on whether a message was sent (either way) in this thread in the last ten minutes. The response will be a list of users that are currently typing.
This way clients can control how much traffic comes their way (one request every 30 seconds), and the typing indicators are not too incorrect (30 seconds seems reasonable, but this can be changed) or too unimportant (10 minutes is probably enough to say the conversation is not really active). Perhaps this could even be coupled with the heartbeat in some way.
On the side of the client that has a user typing, perhaps a dead man's switch of sorts could be implemented, with a POST request to /users_typing/realm/thread_id every 60 seconds (as long as there is text in the compose field). The server can drop the user if it does not receive a request in (let's say) two minutes. A DELETE request can be sent if the user clears the compose field (or changes the thread to which he is sending the message).
On the server, this can be implemented by having a Redis sorted set with the key namespaced by realm and thread_id whose members are user_ids scored by the timestamp of the last update from the user.
The server will also have to check that the user making the request belongs to the realm and thread.
Disadvantages to this implementation:
I think we can do this with far less work than your proposal if we take the basically stateless server approach I described, where clients subscribe to typing notifications the same way they subscribe to things like new message notifications (/api/v1/register), and when a client starts typing, that client sends a POST request to e.g. /api/v1/typing containing in the body the recipients (probably in the same format as we specify recipients when sending messages, so we can share the parsing logic), and the server uses our server -> client push system (i.e. send_event()) to send that information to all browser clients for the users who would receive the message. And we send another event if the user stops typing, probably with the same API call.
We should just make the various time threshholds configurable; I think a minute is way too long for out-of-date typing notification state (I'm thinking like 5-10s)), but the important part is to have it be easy to change.
I think with that design, the business logic for this feature will be almost entirely in the JS code. It's likely we'll end up having several constants at the top of the JS code for this that control how chatty it is:
And we can tweak those to get the right balance between quick status updates vs. Tornado traffic. It may be that Tornado traffic is so dominated by the heartbeat traffic that typing notifications aren't actually a material performance nonissue.
Sounds good 👍 I've put the checklist I'm using here
The PR for the backend is here: #1985
and the WIP PR for the frontend: #2089