Platform-history icon indicating copy to clipboard operation
Platform-history copied to clipboard

Streams/chat

Open EGreg opened this issue 11 years ago • 0 comments

Please implement a Streams/chat tool with corresponding Streams/chat action (verbs: GET, POST).

There is already an existing implementation of Streams/chat, but it should be completely re-done. You can take the files and copy them to some directory on your system, so you can check out the various DocBlock comments.

The Streams/chat tool should take the following options:

publisherId: The publisher id of the stream to which chat messages are posted (required)

streamName: The name of the stream to which chat messages are posted (required)

messageMaxHeight: See below

messagesToLoad: The number of "Streams/chat" messages to load when the chat container's "loadMore" mechanism is invoked (described below). Defaults to 10.

loadMore: May be "scroll", "click" or null/false. Defaults to "scroll".

  • "click" will show label with "Click to see earlier messages" (configurable in Q.text.Streams.chat.loadMore.click string), and when the user clicks it, new messages will be loaded
  • "scroll" means new messages will be loaded when the scrollbar of the chat container reaches the top (for desktop) or whole document scrollbar reaches the top (android). On all other browsers it would use pull-to-refresh ... meaning, it will show "Pull to see earlier messages" (html configurable in Q.text.Streams.chat.loadMore.pull string) and as you pull "too far" you trigger the load. As for the indicator of "pulling too far", we will worry about that later, for now skip it. But remember to discuss it with me afterwards.
  • null/false/etc. - no interface to load earlier messages

The chat itself should look like this:

[ Users/avatar with icon ]                              [ date (float-right) ]
[ ...icon ]      [ html-escaped text  with String.prototype.encodeHTML]
                 [ more lines of html-escaped ]

[ icon... ]   Gregory Magarshak                         [ date (float-right) ]
[ ...icon ]      [ html-escaped text  with String.prototype.encodeHTML]
                 [ more lines of html-escaped ]
                 [ more lines of html-escaped ]
                 [ more lines of html-escaped ]
                 [ last line of html-escaped... ] ****

[ Textarea with one line, that expands as you type with Q/autogrow ]

**** if there are too many lines, exceeding messageMaxHeight then you should have the css style text-overflow: ellipsis at the end, and when that text is clicked, show a dialog with that icon/avatar/date/full text, and (x) to close it. The messageMaxHeight should be a configurable option with a default like 200 or something.

When you finish typing in the textarea and hit Return (Go), the text you typed should be posted to Streams/chat as content parameter. It should be saved in the database as the original, un-html-escaped text (we escape it when we render it). If you focus somewhere else, then you don't post the message but you keep the text in the textarea.

Later, we will add other things that we can post in the chat, but for now it will be just text. Due to the above mechanism, line breaks won't be sent in the text, but instead will cause the message to be posted.

Finally, why POST to a special handler Streams/chat instead of simply Streams/message? Because messages whose type begins with Streams/ are special, and the server doesn't let the client post them. This includes Streams/join and other messages like that. So, we have a special handler which accepts Streams/chat and posts them using the server-side API, $stream->post($message).

And of course, the whole mechanism where the message is posted and sent to all participants, or via notifications, etc. is already implemented.

Your Streams/chat tool will have to listen for Streams/chat messages coming in on that stream. To do that, you simply use the event factory Q.Streams.onMessage or better yet, if you have a stream object which you got via Q.Streams.get, you simply call stream.onMessage on it.

What you are building is called a stream player in Q. It is a tool that can just be placed on a page and interpret certain types of messages, or a certain type of stream. For example a document renderer or a chess game board or something like that. Here, the stream type can be anything, and the messages are all of type Streams/chat.

It would also be nice if your player could listen for Streams/join and Streams/leave messages, and write the following in between the lines:

Greg Magarshak left the chat
Vladimir Lunev entered the chat

of course, prefixes all the css classes here with Streams_chat, and assign styles in Streams.css . For example, for the leaving/entering messages, it would be nice to have class="Streams_chat_activity Streams_chat_leave" and class="Streams_chat_activity Streams_chat_leave" so others can style it.

That's about it.

EGreg avatar Jul 16 '14 16:07 EGreg