Page MenuHomePhorge

D363.1775279794.diff
No OneTemporary

Authored By
Unknown
Size
6 KB
Referenced Files
None
Subscribers
None

D363.1775279794.diff

diff --git a/web/channels/system_channel.ex b/web/channels/system_channel.ex
--- a/web/channels/system_channel.ex
+++ b/web/channels/system_channel.ex
@@ -3,36 +3,59 @@
alias KolabChat.Presence
- def join("system", _, socket) do
- Process.flag(:trap_exit, true)
- :timer.send_interval(10000, :ping)
+ @status [
+ # user is available for chat
+ :online,
+ :away,
+ # user is connected and visible, but not available
+ :busy,
+ :unavailable,
+ # user is shown as offline
+ :invisible,
+ :offline
+ ]
+
+ def join("system", %{"context" => context}, socket) do
+ socket = assign(socket, :context, context)
send self(), :after_join
{:ok, socket}
end
def handle_info(:after_join, socket) do
+ push socket, "presence_state", Presence.list(socket)
+ push socket, "info", %{user: socket.assigns.user.username}
+
Presence.track(socket, socket.assigns.user.username, %{
- status: "online"
+ status: :online,
+ context: socket.assigns.context
})
- push socket, "info", %{user: socket.assigns.user.username}
- push socket, "presence_state", Presence.list(socket)
-
{:noreply, socket}
end
- def handle_info(:ping, socket) do
- push socket, "new:msg", %{user: "SYSTEM", body: "ping"}
-
+ def handle_in("set-status", %{"status" => status}, socket) do
+ update_presence_status(check_status(status), socket)
{:noreply, socket}
end
- def handle_in("set-status", %{"status" => status}, socket) do
+ defp update_presence_status(:invalid, _socket), do: :ok
+ defp update_presence_status(status, socket) do
{:ok, _} = Presence.update(socket, socket.assigns.user.username, %{
- status: status
+ status: status,
+ context: socket.assigns.context
})
+ end
- {:noreply, socket}
+ # Makes sure the provided status name is supported
+ # Returns status name as an atom
+ defp check_status(status) do
+ status = String.to_atom(status)
+
+ if Enum.member?(@status, status) do
+ status
+ else
+ :invalid
+ end
end
end
diff --git a/web/static/css/widgets.css b/web/static/css/widgets.css
--- a/web/static/css/widgets.css
+++ b/web/static/css/widgets.css
@@ -1,15 +1,18 @@
/* Style for chat application widgets */
-.status-online .glyphicon-user {
+.status-online .glyphicon-user,
+.status-away .glyphicon-user {
color: green;
}
-.status-away .glyphicon-user {
- color: grey;
+.status-busy .glyphicon-user,
+.status-unavailable .glyphicon-user {
+ color: red;
}
-.status-busy .glyphicon-user {
- color: red;
+.status-invisible .glyphicon-user,
+.status-offline .glyphicon-user {
+ color: gray;
}
.userlist .btn-group {
diff --git a/web/static/js/api.js b/web/static/js/api.js
--- a/web/static/js/api.js
+++ b/web/static/js/api.js
@@ -10,6 +10,7 @@
/**
* Configuration parameters:
* - token: User session token
+ * - context: KolabChat instance identifier
* - roomId: Chat room Id to join in
* - userListElement: Id of HTML element where to put userslist widget
* - userStatusElement: Id of HTML element where to put users status widget
@@ -19,6 +20,9 @@
constructor(config)
{
this.config = config || {}
+
+ if (!this.config.context)
+ this.config.context = location.hostname;
}
/**
@@ -34,7 +38,7 @@
// TODO: for integration with external systems we'll use configurable full wss:// url
this.socket = new Socket("/socket", {
- params: {token: this.config.token},
+ params: {token: this.config.token, context: this.config.context},
logger: ((kind, msg, data) => { console.log(`${kind}: ${msg}`, data) }),
})
@@ -91,7 +95,7 @@
*/
initPresence()
{
- this.system = this.socket.channel("system")
+ this.system = this.socket.channel("system", {context: this.config.context})
this.system.on("info", info => {
this.username = info.user
@@ -146,7 +150,7 @@
let userPresence
if (this.userStatusWidget && (userPresence = presences[this.username])) {
- userPresence = this.listBy(this.username, userPresence)
+ userPresence = this.listBy(this.username, userPresence, this.config.context)
this.userStatusWidget.render(userPresence)
}
@@ -156,11 +160,27 @@
}
}
- listBy(user, {metas: metas})
+ listBy(user, {metas: metas}, context)
{
+ let statusWeights = {
+ offline: 0,
+ busy: 10,
+ away: 20,
+ online: 30
+ }
+
+ // Find "best" availability status for the user
+ // If set, narrow the result to the current session context
+ let mostAvailableStatus = metas.reduce((best, meta) => {
+ if (context && context != meta.context)
+ return best
+ return statusWeights[best] > statusWeights[meta.status] ? best : meta.status
+ },
+ "offline")
+
return {
user: user,
- status: metas[0].status
+ status: mostAvailableStatus
}
}
diff --git a/web/static/js/widgets/userstatus.js b/web/static/js/widgets/userstatus.js
--- a/web/static/js/widgets/userstatus.js
+++ b/web/static/js/widgets/userstatus.js
@@ -9,6 +9,19 @@
{
this.config = config || {}
this.id = id
+
+ // FIXME: should we get that list from the backend?
+ this.status_list = [
+ // user is available for chat
+ "online",
+ "away",
+ // user is connected and visible, but not available
+ "busy",
+ "unavailable",
+ // user is shown as offline
+ "invisible",
+ "offline"
+ ];
}
/**
@@ -18,6 +31,11 @@
{
let userStatusElement = document.getElementById(this.id)
let icon = '<span class="glyphicon glyphicon-user"></span>'
+ let options = list => {
+ return $.map(list, status =>
+ `<li><a href="#" class="status-${status}">${icon} ${status}</a></li>`
+ ).join("\n")
+ }
userStatusElement.innerHTML = `
<div class="dropdown">
@@ -28,9 +46,7 @@
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
- <li><a href="#" class="status-online">${icon} Online</a></li>
- <li><a href="#" class="status-away">${icon} Away</a></li>
- <li><a href="#" class="status-busy">${icon} Busy</a></li>
+ ` + options(this.status_list) + `
</ul>
</div>
`

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 4, 5:16 AM (5 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18822689
Default Alt Text
D363.1775279794.diff (6 KB)

Event Timeline