Commit 3bd9a1db authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Timestamp chat messages.

parent 48092226
......@@ -63,6 +63,7 @@ func IceConfiguration() webrtc.Configuration {
type ChatHistoryEntry struct {
Id string
User string
Time uint64
Kind string
Value string
}
......@@ -393,7 +394,7 @@ func (g *Group) ClearChatHistory() {
g.history = nil
}
func (g *Group) AddToChatHistory(id, user, kind, value string) {
func (g *Group) AddToChatHistory(id, user string, time uint64, kind, value string) {
g.mu.Lock()
defer g.mu.Unlock()
......@@ -402,7 +403,7 @@ func (g *Group) AddToChatHistory(id, user, kind, value string) {
g.history = g.history[:len(g.history)-1]
}
g.history = append(g.history,
ChatHistoryEntry{Id: id, User: user, Kind: kind, Value: value},
ChatHistoryEntry{Id: id, User: user, Time: time, Kind: kind, Value: value},
)
}
......
......@@ -142,6 +142,7 @@ type clientMessage struct {
Permissions group.ClientPermissions `json:"permissions,omitempty"`
Group string `json:"group,omitempty"`
Value string `json:"value,omitempty"`
Time uint64 `json:"time,omitempty"`
Offer *webrtc.SessionDescription `json:"offer,omitempty"`
Answer *webrtc.SessionDescription `json:"answer,omitempty"`
Candidate *webrtc.ICECandidateInit `json:"candidate,omitempty"`
......@@ -149,6 +150,20 @@ type clientMessage struct {
Request rateMap `json:"request,omitempty"`
}
func fromJSTime(tm uint64) time.Time {
if tm == 0 {
return time.Time{}
}
return time.Unix(int64(tm)/1000, (int64(tm)%1000) * 1000000)
}
func toJSTime(tm time.Time) uint64 {
if tm.Before(time.Unix(0, 0)) {
return 0
}
return uint64((tm.Sub(time.Unix(0, 0)) + time.Millisecond / 2) / time.Millisecond)
}
type closeMessage struct {
data []byte
}
......@@ -714,6 +729,7 @@ func clientLoop(c *webClient, ws *websocket.Conn) error {
Type: "chat",
Id: m.Id,
Username: m.User,
Time: m.Time,
Value: m.Value,
Kind: m.Kind,
})
......@@ -984,12 +1000,23 @@ func handleClientMessage(c *webClient, m clientMessage) error {
log.Printf("ICE: %v", err)
}
case "chat":
c.group.AddToChatHistory(m.Id, m.Username, m.Kind, m.Value)
tm := toJSTime(time.Now())
c.group.AddToChatHistory(
m.Id, m.Username, tm, m.Kind, m.Value,
)
mm := clientMessage{
Type: "chat",
Id: m.Id,
Username: m.Username,
Time: tm,
Kind: m.Kind,
Value: m.Value,
}
clients := c.group.GetClients(nil)
for _, cc := range clients {
cc, ok := cc.(*webClient)
if ok {
cc.write(m)
cc.write(mm)
}
}
case "groupaction":
......
package rtpconn
import (
"testing"
"time"
)
func TestJSTime(t *testing.T) {
tm := time.Now()
js := toJSTime(tm)
tm2 := fromJSTime(js)
js2 := toJSTime(tm2)
if js != js2 {
t.Errorf("%v != %v", js, js2)
}
delta := tm.Sub(tm2)
if delta < -time.Millisecond/2 || delta > time.Millisecond/2 {
t.Errorf("Delta %v, %v, %v", delta, tm, tm2)
}
}
......@@ -124,7 +124,7 @@ function ServerConnection() {
/**
* onchat is called whenever a new chat message is received.
*
* @type {(this: ServerConnection, id: string, username: string, kind: string, message: string) => void}
* @type {(this: ServerConnection, id: string, username: string, time: number, kind: string, message: string) => void}
*/
this.onchat = null;
/**
......@@ -284,7 +284,9 @@ ServerConnection.prototype.connect = async function(url) {
break;
case 'chat':
if(sc.onchat)
sc.onchat.call(sc, m.id, m.username, m.kind, m.value);
sc.onchat.call(
sc, m.id, m.username, m.time, m.kind, m.value,
);
break;
case 'clearchat':
if(sc.onclearchat)
......
......@@ -321,12 +321,16 @@ textarea.form-reply {
color: #202035;
}
.message-user {
.message-header {
margin: 0;
font-style: italic;
text-shadow: none;
}
.message-time {
margin-left: 1em;
}
.message-me-asterisk, .message-me-user {
margin-right: 0.33em;
}
......
......@@ -1211,6 +1211,18 @@ function formatLines(lines) {
return elt;
}
/**
* @param {number} time
* @returns {string}
*/
function formatTime(time) {
let delta = Date.now() - time;
let date = new Date(time);
if(delta >= 0)
return date.toTimeString().slice(null, 8);
return date.toLocaleString();
}
/**
* @typedef {Object} lastMessage
* @property {string} [nick]
......@@ -1223,10 +1235,11 @@ let lastMessage = {};
/**
* @param {string} peerId
* @param {string} nick
* @param {number} time
* @param {string} kind
* @param {string} message
*/
function addToChatbox(peerId, nick, kind, message){
function addToChatbox(peerId, nick, time, kind, message){
let userpass = getUserPass();
let row = document.createElement('div');
row.classList.add('message-row');
......@@ -1241,10 +1254,19 @@ function addToChatbox(peerId, nick, kind, message){
if(kind !== 'me') {
let p = formatLines(message.split('\n'));
if (lastMessage.nick !== nick || lastMessage.peerId !== peerId) {
let user = document.createElement('p');
let header = document.createElement('p');
let user = document.createElement('span');
user.textContent = nick;
user.classList.add('message-user');
container.appendChild(user);
header.appendChild(user);
if(time) {
let tm = document.createElement('span');
tm.textContent = formatTime(time);
tm.classList.add('message-time');
header.appendChild(tm);
}
header.classList.add('message-header');
container.appendChild(header);
}
p.classList.add('message-content');
container.appendChild(p);
......@@ -1365,7 +1387,7 @@ function handleInput() {
let s = "";
for(let key in settings)
s = s + `${key}: ${JSON.stringify(settings[key])}\n`
addToChatbox(null, null, null, s);
addToChatbox(null, null, Date.now(), null, s);
return;
}
let parsed = parseCommand(rest);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment