Documentation
¶
Overview ¶
Package cchat is a set of stabilized interfaces for cchat implementations, joining the backend and frontend together.
Backend ¶
Methods implemented by the backend that have frontend containers as arguments can do IO. Frontends must NOT rely on individual backend caches and should always assume that they will block.
Methods that do not return an error must NOT do any IO to prevent blocking the main thread. Methods that do return an error may do IO, but they should be documented per method. ID() and Name() must never do any IO.
Backend implementations have certain conditions that should be adhered to:
- Storing MessagesContainer and ServersContainer are advised against; however, they should be done if need be.
- Other containers such as LabelContainer and IconContainer should also not be stored; however, the same rule as above applies.
- For the server list, icon updates and such that happen after their calls should use SetServers().
- For the nickname of the current server, the backend can store the state of the label container. It must, however, remove the container when the stop callback from JoinServer() is called.
- Some methods that take in a container may take in a context as well. Although implementations don't have to use this context, it should try to.
Note: IO in most cases usually refer to networking, but they should files and anything that could block, such as mutexes or semaphores.
Note: As mentioned above, contexts are optional for both the frontend and backend. The frontend may use it for cancellation, and the backend may ignore it.
Frontend ¶
Frontend contains all interfaces that a frontend can or must implement. The backend may call these methods any time from any goroutine. Thus, they should be thread-safe. They should also not block the call by doing so, as backends may call these methods in its own main thread.
It is worth pointing out that frontend container interfaces will not have an error handling API, as frontends can do that themselves. Errors returned by backend methods will be errors from the backend itself and never the frontend errors.
Index ¶
- type AuthenticateEntry
- type Authenticator
- type CommandCompleter
- type Commander
- type CompletionEntry
- type Configurator
- type ErrInvalidConfigAtField
- type ID
- type Icon
- type IconContainer
- type Identifier
- type ImageContainer
- type LabelContainer
- type ListMember
- type MemberListContainer
- type MemberListDynamicSection
- type MemberListSection
- type MessageAttachment
- type MessageAuthor
- type MessageAuthorAvatar
- type MessageCreate
- type MessageDelete
- type MessageHeader
- type MessageMentioned
- type MessageNonce
- type MessagePrepender
- type MessageUpdate
- type MessagesContainer
- type Namer
- type SendableMessage
- type SendableMessageAttachments
- type Server
- type ServerList
- type ServerMessage
- type ServerMessageActioner
- type ServerMessageAttachmentSender
- type ServerMessageBacklogger
- type ServerMessageEditor
- type ServerMessageMemberLister
- type ServerMessageSendCompleter
- type ServerMessageSender
- type ServerMessageTypingIndicator
- type ServerMessageUnreadIndicator
- type ServerNickname
- type ServersContainer
- type Service
- type Session
- type SessionRestorer
- type SessionSaver
- type Typer
- type TypingIndicator
- type UnreadIndicator
- type UserStatus
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AuthenticateEntry ¶
type AuthenticateEntry struct {
Name string
Placeholder string
Description string
Secret bool
Multiline bool
}
AuthenticateEntry represents a single authentication entry, usually an email or password prompt. Passwords or similar entries should have Secrets set to true, which should imply to frontends that the fields be masked.
type Authenticator ¶
type Authenticator interface {
// AuthenticateForm should return a list of authentication entries for
// the frontend to render.
AuthenticateForm() []AuthenticateEntry
// Authenticate will be called with a list of values with indices
// correspond to the returned slice of AuthenticateEntry.
Authenticate([]string) (Session, error)
}
The authenticator interface allows for a multistage initial authentication API that the backend could use. Multistage is done by calling AuthenticateForm then Authenticate again forever until no errors are returned.
var s *cchat.Session
var err error
for {
// Pseudo-function to render the form and return the results of those forms
// when the user confirms it.
outputs := renderAuthForm(svc.AuthenticateForm())
s, err = svc.Authenticate(outputs)
if err != nil {
renderError(errors.Wrap(err, "Error while authenticating"))
continue // retry
}
break // success
}
type CommandCompleter ¶
type CommandCompleter interface {
// CompleteCommand is called with the line and current word, which the
// backend should return with a list of new words.
CompleteCommand(words []string, wordIndex int) []string
}
CommandCompleter is an optional interface that a session could implement for completion support. This also depends on whether or not the frontend supports it.
type Commander ¶
type Commander interface {
// RunCommand executes the given command, with the slice being already split
// arguments, similar to os.Args. The function could return an output
// stream, in which the frontend must display it live and close it on EOF.
//
// The function must not do any IO; if it does, then they have to be in a
// goroutine and stream their results to the ReadCloser.
//
// The client should make guarantees that an empty string (and thus a
// zero-length string slice) should be ignored. The backend should be able
// to assume that the argument slice is always length 1 or more.
RunCommand([]string) (io.ReadCloser, error)
}
Commander is an optional interface that a session could implement for command support. This is different from just intercepting the SendMessage() API, as this extends globally to the entire session.
Commander can implement the following interfaces:
- CommandCompleter (optional)
type CompletionEntry ¶
type CompletionEntry struct {
// Raw is the text to be replaced in the input box.
Raw string
// Text is the label to be displayed.
Text text.Rich
// Secondary is the label to be displayed on the second line, on the right
// of Text, or not displayed at all. This should be optional. This text may
// be dimmed out as styling.
Secondary text.Rich
// IconURL is the URL to the icon that will be displayed on the left of the
// text. This field is optional.
IconURL string
// Image returns whether or not the icon URL is actually an image, which
// indicates that the frontend should not do rounded corners.
Image bool
}
CompletionEntry is a single completion entry returned by CompleteMessage. The icon URL field is optional.
type Configurator ¶
type Configurator interface {
Configuration() (map[string]string, error)
SetConfiguration(map[string]string) error
}
Configurator is what the backend can implement for an arbitrary configuration API.
type ErrInvalidConfigAtField ¶
ErrInvalidConfigAtField is the structure for an error at a specific configuration field. Frontends can use this and highlight fields if the backends support it.
func (*ErrInvalidConfigAtField) Error ¶
func (err *ErrInvalidConfigAtField) Error() string
func (*ErrInvalidConfigAtField) Unwrap ¶
func (err *ErrInvalidConfigAtField) Unwrap() error
type ID ¶ added in v0.0.49
type ID = string
ID is the type alias for an ID string. This type is used for clarification and documentation purposes only; implementations could either use this type or a string type.
type Icon ¶
type Icon interface {
Icon(context.Context, IconContainer) (stop func(), err error)
}
Icon is an extra interface that an interface could implement for an icon. Typically, Service would return the service logo, Session would return the user's avatar, and Server would return the server icon.
For session, the avatar should be the same as the one returned by messages sent by the current user.
type IconContainer ¶
type IconContainer interface {
SetIcon(url string)
}
IconContainer is a generic interface for any container that can hold an image. It's typically used for icons that can update itself. Frontends should round these icons. For images that shouldn't be rounded, use ImageContainer.
Methods may call SetIcon at any time in its main thread, so the frontend must do any I/O (including downloading the image) in another goroutine to avoid blocking the backend.
type Identifier ¶
type Identifier interface {
ID() ID
}
Identifier requires ID() to return a uniquely identifiable string for whatever this is embedded into. Typically, servers and messages have IDs. It is worth mentioning that IDs should be consistent throughout the lifespan of the program or maybe even forever.
type ImageContainer ¶
type ImageContainer interface {
SetImage(url string)
}
ImageContainer does nothing; it's reserved for future API usages. Typically, images don't have round corners while icons do.
type LabelContainer ¶
LabelContainer is a generic interface for any container that can hold texts. It's typically used for rich text labelling for usernames and server names.
Methods that takes in a LabelContainer typically holds it in the state and may call SetLabel any time it wants. Thus, the frontend should synchronize calls with the main thread if needed.
type ListMember ¶
type ListMember interface {
// Identifier identifies the individual member. This works similarly to
// MessageAuthor.
Identifier
// Namer returns the name of the member. This works similarly to a
// MessageAuthor.
Namer
// Status returns the status of the member. The backend does not have to
// show offline members with the offline status if it doesn't want to show
// offline menbers at all.
Status() UserStatus
// Secondary returns the subtext of this member. This could be anything,
// such as a user's custom status or away reason.
Secondary() text.Rich
}
ListMember represents a single member in the member list. This is a base interface that may implement more interfaces, such as Iconer for the user's avatar. The frontend may give everyone an avatar regardless, or it may not show any avatars at all.
This interface works similarly to a slightly extended MessageAuthor interface.
type MemberListContainer ¶
type MemberListContainer interface {
// SetSections (re)sets the list of sections to be the given slice. Members
// from the old section list should be transferred over to the new section
// entry if the section name's content is the same. Old sections that don't
// appear in the new slice should be removed.
SetSections(sections []MemberListSection)
// SetMember adds or updates (or upsert) a member into a section. This
// operation must not change the section's member count. As such, changes
// should be done separately in SetSection. If the section does not exist,
// then the client should ignore this member. As such, backends must call
// SetSections first before SetMember on a new section.
SetMember(sectionID ID, member ListMember)
// RemoveMember removes a member from a section. If neither the member nor
// the section exists, then the client should ignore it.
RemoveMember(sectionID, memberID ID)
}
MemberListContainer is a generic interface for any container that can display a member list. This is similar to Discord's right-side member list or IRC's users list. Below is a visual representation of a typical member list container:
+-MemberList-----------\ | +-Section------------| | | | | | Header - Total | | | | | | +-Member-----------| | | | Name | | | | Secondary | | | \__________________| | | | | | +-Member-----------| | | | Name | | | | Secondary | | | \__________________| \_\____________________/
type MemberListDynamicSection ¶ added in v0.0.48
type MemberListDynamicSection interface {
MemberListSection
// LoadMore is a method which the client can call to ask for more members.
// This method can do IO.
//
// Clients may call this method on the last section in the section slice;
// however, calling this method on any section is allowed. Clients may not
// call this method if the number of members in this section is equal to
// Total.
LoadMore() bool
// LoadLess is a method which the client must call after it is done
// displaying entries that were added from calling LoadMore.
//
// The client can call this method exactly as many times as it has called
// LoadMore. However, false should be returned if the client should stop,
// and future calls without LoadMore should still return false.
LoadLess() bool
}
MemberListDynamicSection represents a dynamically loaded member list section. The section behaves similarly to MemberListSection, except the information displayed will be considered incomplete until LoadMore returns false.
LoadLess can be called by the client to mark chunks as stale, which the server can then unsubscribe from.
type MemberListSection ¶
type MemberListSection interface {
// Identifier identifies the current section.
Identifier
// Namer returns the section name.
Namer
// Total returns the total member count.
Total() int
}
MemberListSection represents a member list section. The section name's content must be unique among other sections from the same list regardless of the rich segments.
type MessageAttachment ¶
MessageAttachment represents a single file attachment.
If needed, the frontend will close the reader after the message is sent, that is when the SendMessage function returns. The backend must not use the reader after that.
type MessageAuthor ¶
type MessageAuthor interface {
Identifier
Namer
}
MessageAuthor is the interface for an identifiable message author. The returned ID may or may not be used by the frontend, but clients must guarantee uniqueness for intended behaviors.
The frontend may also use this to squash messages with the same author together.
type MessageAuthorAvatar ¶
type MessageAuthorAvatar interface {
Avatar() (url string)
}
MessageAuthorAvatar is an optional interface that MessageAuthor could implement. A frontend may optionally support this. A backend may return an empty string, in which the frontend must handle, perhaps by using a placeholder.
type MessageCreate ¶
type MessageCreate interface {
MessageHeader
Author() MessageAuthor
Content() text.Rich
}
MessageCreate is the interface for an incoming message.
type MessageDelete ¶
type MessageDelete interface {
MessageHeader
}
MessageDelete is the interface for a message delete event.
type MessageHeader ¶
type MessageHeader interface {
Identifier
Time() time.Time
}
MessageHeader implements the minimum interface for any message event.
type MessageMentioned ¶
type MessageMentioned interface {
// Mentioned returns whether or not the message mentions the current user.
Mentioned() bool
}
MessageMentioned extends MessageCreate to add mentioning support. The frontend may or may not implement this. If it does, the frontend will typically format the message into a notification and play a sound.
type MessageNonce ¶
type MessageNonce interface {
Nonce() string
}
MessageNonce extends SendableMessage and MessageCreate to add nonce support. This is known in IRC as labeled responses. Clients could use this for various purposes, including knowing when a message has been sent successfully.
Both the backend and frontend must implement this for the feature to work properly. The backend must check if SendableMessage implements MessageNonce, and the frontend must check if MessageCreate implements MessageNonce.
type MessagePrepender ¶ added in v0.0.49
type MessagePrepender interface {
// PrependMessage prepends the given MessageCreate message into the top of
// the chat buffer.
PrependMessage(MessageCreate)
}
MessagePrepender extends MessagesContainer for backlog implementations. The backend is expected to call this interface's method from latest to earliest.
type MessageUpdate ¶
type MessageUpdate interface {
MessageHeader
Author() MessageAuthor // optional (nilable)
Content() text.Rich // optional (rich.Content == "")
}
MessageUpdate is the interface for a message update (or edit) event. If the returned text.Rich returns true for Empty(), then the element shouldn't be changed.
type MessagesContainer ¶
type MessagesContainer interface {
CreateMessage(MessageCreate)
UpdateMessage(MessageUpdate)
DeleteMessage(MessageDelete)
}
MessagesContainer is a view implementation that displays a list of messages live. This implements the 3 most common message events: CreateMessage, UpdateMessage and DeleteMessage. The frontend must handle all 3.
Since this container interface extends a single Server, the frontend is allowed to have multiple views. This is usually done with tabs or splits, but the backend should update them all nonetheless.
type Namer ¶
Namer requires Name() to return the name of the object. Typically, this implies usernames for sessions or service names for services.
type SendableMessage ¶
type SendableMessage interface {
Content() string
}
SendableMessage is the bare minimum interface of a sendable message, that is, a message that can be sent with SendMessage(). This allows the frontend to implement its own message data implementation.
An example of extending this interface is MessageNonce, which is similar to IRCv3's labeled response extension or Discord's nonces. The frontend could implement this interface and check if incoming MessageCreate events implement the same interface.
SendableMessage can implement the following interfaces:
- MessageNonce (optional)
- SendableMessageAttachments (optional): refer to ServerMessageAttachmentSender
type SendableMessageAttachments ¶
type SendableMessageAttachments interface {
Attachments() []MessageAttachment
}
SendableMessageAttachments extends SendableMessage which adds attachments into the message. Backends that can use this interface should implement ServerMessageAttachmentSender.
type Server ¶
type Server interface {
Identifier
Namer
}
Server is a single server-like entity that could translate to a guild, a channel, a chat-room, and such. A server must implement at least ServerList or ServerMessage, else the frontend must treat it as a no-op.
Server can implement the following interfaces:
- Identifier
- Namer
- ServerList and/or ServerMessage (and its interfaces)
- ServerNickname (optional)
- Icon (optional)
type ServerList ¶
type ServerList interface {
// Servers should call SetServers() on the given ServersContainer to render
// all servers. This function can do IO, and the frontend should run this in
// a goroutine.
Servers(ServersContainer) error
}
ServerList is for servers that contain children servers. This is similar to guilds containing channels in Discord, or IRC servers containing channels.
There isn't a similar stop callback API unlike other interfaces because all servers are expected to be listed. However, they could be hidden, such as collapsing a tree.
The backend should call both the container and other icon and label containers, if any.
type ServerMessage ¶
type ServerMessage interface {
// JoinServer joins a server that's capable of receiving messages. The
// server may not necessarily support sending messages.
JoinServer(context.Context, MessagesContainer) (stop func(), err error)
}
ServerMessage is for servers that contain messages. This is similar to Discord or IRC channels.
ServerMessage can implement the following interfaces:
- ServerMessageSender (optional): adds message sending capability.
- ServerMessageSendCompleter (optional): adds message input completion capability.
- ServerMessageAttachmentSender (optional): adds attachment sending capability.
- ServerMessageEditor (optional): adds message editing capability.
- ServerMessageActioner (optional): adds custom actions capability.
- ServerMessageUnreadIndicator (optional): adds unread indication capability.
- ServerMessageTypingIndicator (optional): adds typing indication capability.
- ServerMessageMemberLister (optional): adds member listing capability.
- ServerMessageBacklogger (optional): adds chat history capability.
type ServerMessageActioner ¶
type ServerMessageActioner interface {
// MessageActions returns a list of possible actions in pretty strings that
// the frontend will use to directly display. This function must not do any
// IO.
//
// The string slice returned can be nil or empty.
MessageActions(messageID string) []string
// DoMessageAction executes a message action on the given messageID, which
// would be taken from MessageHeader.ID(). This function is allowed to do
// IO; the frontend should take care of running this asynchronously.
DoMessageAction(action, messageID string) error
}
ServerMessageActioner optionally extends ServerMessage to add custom message action capabilities to the server. Similarly to ServerMessageEditor, these functions can have IO.
type ServerMessageAttachmentSender ¶
type ServerMessageAttachmentSender interface {
ServerMessageSender
// SendAttachments sends only message attachments. The frontend would
// most of the time use SendableMessage that implements
// SendableMessageAttachments, but this method is useful for detecting
// capabilities.
SendAttachments([]MessageAttachment) error
}
ServerMessageAttachmentSender optionally extends ServerMessageSender to indicate that the backend can accept attachments in its messages. The attachments will still be sent through SendMessage, though this interface will mostly be used to indicate the capability.
type ServerMessageBacklogger ¶ added in v0.0.49
type ServerMessageBacklogger interface {
// MessagesBefore fetches messages before the given message ID into the
// MessagesContainer.
MessagesBefore(ctx context.Context, before ID, c MessagePrepender) error
}
ServerMessageBacklogger indicates that the message container has a message history and is capable of fetching that. As there is no stop callback, if the backend needs to fetch messages asynchronously, it is expected to use the context to know when to cancel.
The frontend should usually call this method when the user scrolls to the top. It is expected to guarantee not to call MessagesBefore more than once on the same ID.
Note: Although backends might rely on this context, the frontend is still expected to invalidate the given container when the channel is changed.
type ServerMessageEditor ¶
type ServerMessageEditor interface {
// MessageEditable returns whether or not a message can be edited by the
// client.
MessageEditable(id ID) bool
// RawMessageContent gets the original message text for editing. Backends
// must not do IO.
RawMessageContent(id ID) (string, error)
// EditMessage edits the message with the given ID to the given content,
// which is the edited string from RawMessageContent. This method can do IO.
EditMessage(id ID, content string) error
}
ServerMessageEditor optionally extends ServerMessage to add message editing capability to the server. Only EditMessage can have IO.
type ServerMessageMemberLister ¶
type ServerMessageMemberLister interface {
// ListMembers assigns the given container to the channel's member list.
// The given context may be used to provide HTTP request cancellations, but
// frontends must not rely solely on this, as the general context rules
// applies.
ListMembers(context.Context, MemberListContainer) (stop func(), err error)
}
ServerMessageMemberLister optionally extends ServerMessage to add a member list into each channel. This function works similarly to ServerMessage's JoinServer.
type ServerMessageSendCompleter ¶
type ServerMessageSendCompleter interface {
// CompleteMessage returns the list of possible completion entries for the
// given word list and the current word index. It takes in a list of
// whitespace-split slice of string as well as the position of the cursor
// relative to the given string slice.
CompleteMessage(words []string, current int) []CompletionEntry
}
ServerMessageSendCompleter optionally extends ServerMessageSender to add autocompletion into the message composer. IO is not allowed and the backend should do that only in goroutines and update its state for future calls.
Frontends could utilize the split package inside utils for splitting words and index.
type ServerMessageSender ¶
type ServerMessageSender interface {
// SendMessage is called by the frontend to send a message to this channel.
SendMessage(SendableMessage) error
}
ServerMessageSender optionally extends ServerMessage to add message sending capability to the server.
type ServerMessageTypingIndicator ¶
type ServerMessageTypingIndicator interface {
// Typing is called by the client to indicate that the user is typing. This
// function can do IO calls, and the client will take care of calling it in
// a goroutine (or an asynchronous queue) as well as throttling it to
// TypingTimeout.
Typing() error
// TypingTimeout returns the interval between typing events sent by the
// client as well as the timeout before the client should remove the typer.
// Typically, a constant should be returned.
TypingTimeout() time.Duration
// TypingSubscribe subscribes the given indicator to typing events sent by
// the backend. The added event handlers have to be removed by the backend
// when the stop() callback is called.
//
// This method does not take in a context, as it's supposed to only use
// event handlers and not do any IO calls. Nonetheless, the client must
// treat it like it does and call it asynchronously.
TypingSubscribe(TypingIndicator) (stop func(), err error)
}
ServerMessageTypingIndicator optionally extends ServerMessage to provide bidirectional typing indicating capabilities. This is similar to typing events on Discord and typing client tags on IRCv3.
The client should remove a typer when a message is received with the same user ID, when RemoveTyper() is called by the backend or when the timeout returned from TypingTimeout() has been reached.
type ServerMessageUnreadIndicator ¶
type ServerMessageUnreadIndicator interface {
// UnreadIndicate subscribes the given unread indicator for unread and
// mention events. Examples include when a new message is arrived and the
// backend needs to indicate that it's unread.
//
// This function must provide a way to remove callbacks, as clients must
// call this when the old server is destroyed, such as when Servers is
// called.
UnreadIndicate(UnreadIndicator) (stop func(), err error)
}
ServerMessageUnreadIndicator is for servers that can contain messages and know from the state if that message makes the server unread and if it contains a message that mentions the user.
type ServerNickname ¶
type ServerNickname interface {
Nickname(context.Context, LabelContainer) (stop func(), err error)
}
ServerNickname extends Server to add a specific user nickname into a server. The frontend should not traverse up the server tree, and thus the backend must handle nickname inheritance. This also means that servers that don't implement ServerMessage also don't need to implement ServerNickname. By default, the session name should be used.
type ServersContainer ¶
type ServersContainer interface {
// SetServer is called by the backend service to request a reset of the
// server list. The frontend can choose to call Servers() on each of the
// given servers, or it can call that later. The backend should handle both
// cases.
SetServers([]Server)
}
ServersContainer is any type of view that displays the list of servers. It should implement a SetServers([]Server) that the backend could use to call anytime the server list changes (at all).
Typically, most frontends should implement this interface onto a tree node, as servers can be infinitely nested. Frontends should also reset the entire node and its children when SetServers is called again.
type Service ¶
type Service interface {
// Namer returns the name of the service.
Namer
// Authenticate begins the authentication process. It's put into a method so
// backends can easily restart the entire process.
Authenticate() Authenticator
}
A service is a complete service that's capable of multiple sessions. It has to implement the Authenticate() method, which returns an implementation of Authenticator.
A service can implement SessionRestorer, which would indicate the frontend that it can restore past sessions. Sessions are saved using the SessionSaver interface that Session can implement.
A service can also implement Configurator if it has additional configurations. The current API is a flat key-value map, which can be parsed by the backend itself into more meaningful data structures. All configurations must be optional, as frontends may not implement a configurator UI.
Service can implement the following interfaces:
- Namer
- SessionRestorer (optional)
- Configurator (optional)
- Icon (optional)
type Session ¶
type Session interface {
// Identifier should typically return the user ID.
Identifier
// Namer gives the name of the session, which is typically the username.
Namer
// Disconnect asks the service to disconnect. It does not necessarily mean
// removing the service.
//
// The frontend must cancel the active ServerMessage before disconnecting.
// The backend can rely on this behavior.
//
// The frontend will reuse the stored session data from SessionSaver to
// reconnect.
//
// When this function fails, the frontend may display the error upfront.
// However, it will treat the session as actually disconnected. If needed,
// the backend must implement reconnection by itself.
Disconnect() error
ServerList
}
A session is returned after authentication on the service. Session implements Name(), which should return the username most of the time. It also implements ID(), which might be used by frontends to check against MessageAuthor.ID() and other things.
A session can implement SessionSaver, which would allow the frontend to save the session into its keyring at any time. Whether the keyring is completely secure or not is up to the frontend. For a Gtk client, that would be using the GNOME Keyring daemon.
Session can implement the following interfaces:
- Identifier
- Namer
- ServerList
- Icon (optional)
- Commander (optional)
- SessionSaver (optional)
type SessionRestorer ¶
SessionRestorer extends Service and is called by the frontend to restore a saved session. The frontend may call this at any time, but it's usually on startup.
To save a session, refer to SessionSaver which extends Session.
type SessionSaver ¶
SessionSaver extends Session and is called by the frontend to save the current session. This is typically called right after authentication, but a frontend may call this any time, including when it's closing.
The frontend can ask to restore a session using SessionRestorer, which extends Service.
type Typer ¶
type Typer interface {
MessageAuthor
Time() time.Time
}
Typer is an individual user that's typing. This interface is used interchangably in TypingIndicator and thus ServerMessageTypingIndicator as well.
type TypingIndicator ¶
type TypingIndicator interface {
// AddTyper appends the typer into the frontend's list of typers, or it
// pushes this typer on top of others.
AddTyper(Typer)
// RemoveTyper explicitly removes the typer with the given user ID from the
// list of typers. This function is usually not needed, as the client will
// take care of removing them after TypingTimeout has been reached or other
// conditions listed in ServerMessageTypingIndicator are met.
RemoveTyper(ID)
}
TypingIndicator is a generic interface for any container that can display users typing in the current chatbox. The typing indicator must adhere to the TypingTimeout returned from ServerMessageTypingIndicator. The backend should assume that to be the case and send events appropriately.
For more documentation, refer to ServerMessageTypingIndicator.
type UnreadIndicator ¶
type UnreadIndicator interface {
// Unread sets the container's unread state to the given boolean. The
// frontend may choose how to represent this.
SetUnread(unread, mentioned bool)
}
UnreadIndicator is an interface that a single server container (such as a button or a tree node) can implement if it's capable of indicating the read and mentioned status for that channel.
Server containers that implement this has to implement both SetUnread and SetMentioned, and they should also represent those statuses differently. For example, a mentioned channel could have a red outline, while an unread channel could appear brighter.
Server containers are expected to represent this information in their parent nodes as well. For example, if a server is unread, then its parent servers as well as the session node should indicate the same status. Highlighting the session and service nodes are, however, implementation details, meaning that this decision is up to the frontend to decide.
type UserStatus ¶
type UserStatus uint8
UserStatus represents a user's status. This might be used by the frontend to visually display the status.
const ( UnknownStatus UserStatus = iota OnlineStatus IdleStatus BusyStatus // also known as Do Not Disturb AwayStatus OfflineStatus InvisibleStatus // reserved; currently unused )
func (UserStatus) String ¶
func (s UserStatus) String() string
String formats a user status as a title string, such as "Online" or "Unknown". It treats unknown constants as UnknownStatus.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package services provides a global repository of cchat services.
|
Package services provides a global repository of cchat services. |
|
plugins
Package plugins provides a source for cchat services as Go plugins.
|
Package plugins provides a source for cchat services as Go plugins. |
|
utils
|
|
|
split
Package split provides a simple string splitting utility for use with CompleteMessage.
|
Package split provides a simple string splitting utility for use with CompleteMessage. |