1
Fork 0
mirror of https://github.com/jech/galene.git synced 2024-11-22 08:35:57 +01:00

Timestamp chat messages.

This commit is contained in:
Juliusz Chroboczek 2020-09-30 00:33:23 +02:00
parent 480922268e
commit 3bd9a1db4e
6 changed files with 89 additions and 11 deletions

View file

@ -63,6 +63,7 @@ func IceConfiguration() webrtc.Configuration {
type ChatHistoryEntry struct { type ChatHistoryEntry struct {
Id string Id string
User string User string
Time uint64
Kind string Kind string
Value string Value string
} }
@ -393,7 +394,7 @@ func (g *Group) ClearChatHistory() {
g.history = nil 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() g.mu.Lock()
defer g.mu.Unlock() 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 = g.history[:len(g.history)-1]
} }
g.history = append(g.history, 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},
) )
} }

View file

@ -142,6 +142,7 @@ type clientMessage struct {
Permissions group.ClientPermissions `json:"permissions,omitempty"` Permissions group.ClientPermissions `json:"permissions,omitempty"`
Group string `json:"group,omitempty"` Group string `json:"group,omitempty"`
Value string `json:"value,omitempty"` Value string `json:"value,omitempty"`
Time uint64 `json:"time,omitempty"`
Offer *webrtc.SessionDescription `json:"offer,omitempty"` Offer *webrtc.SessionDescription `json:"offer,omitempty"`
Answer *webrtc.SessionDescription `json:"answer,omitempty"` Answer *webrtc.SessionDescription `json:"answer,omitempty"`
Candidate *webrtc.ICECandidateInit `json:"candidate,omitempty"` Candidate *webrtc.ICECandidateInit `json:"candidate,omitempty"`
@ -149,6 +150,20 @@ type clientMessage struct {
Request rateMap `json:"request,omitempty"` 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 { type closeMessage struct {
data []byte data []byte
} }
@ -714,6 +729,7 @@ func clientLoop(c *webClient, ws *websocket.Conn) error {
Type: "chat", Type: "chat",
Id: m.Id, Id: m.Id,
Username: m.User, Username: m.User,
Time: m.Time,
Value: m.Value, Value: m.Value,
Kind: m.Kind, Kind: m.Kind,
}) })
@ -984,12 +1000,23 @@ func handleClientMessage(c *webClient, m clientMessage) error {
log.Printf("ICE: %v", err) log.Printf("ICE: %v", err)
} }
case "chat": 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) clients := c.group.GetClients(nil)
for _, cc := range clients { for _, cc := range clients {
cc, ok := cc.(*webClient) cc, ok := cc.(*webClient)
if ok { if ok {
cc.write(m) cc.write(mm)
} }
} }
case "groupaction": case "groupaction":

22
rtpconn/webclient_test.go Normal file
View file

@ -0,0 +1,22 @@
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)
}
}

View file

@ -124,7 +124,7 @@ function ServerConnection() {
/** /**
* onchat is called whenever a new chat message is received. * 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; this.onchat = null;
/** /**
@ -284,7 +284,9 @@ ServerConnection.prototype.connect = async function(url) {
break; break;
case 'chat': case 'chat':
if(sc.onchat) 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; break;
case 'clearchat': case 'clearchat':
if(sc.onclearchat) if(sc.onclearchat)

View file

@ -321,12 +321,16 @@ textarea.form-reply {
color: #202035; color: #202035;
} }
.message-user { .message-header {
margin: 0; margin: 0;
font-style: italic; font-style: italic;
text-shadow: none; text-shadow: none;
} }
.message-time {
margin-left: 1em;
}
.message-me-asterisk, .message-me-user { .message-me-asterisk, .message-me-user {
margin-right: 0.33em; margin-right: 0.33em;
} }

View file

@ -1211,6 +1211,18 @@ function formatLines(lines) {
return elt; 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 * @typedef {Object} lastMessage
* @property {string} [nick] * @property {string} [nick]
@ -1223,10 +1235,11 @@ let lastMessage = {};
/** /**
* @param {string} peerId * @param {string} peerId
* @param {string} nick * @param {string} nick
* @param {number} time
* @param {string} kind * @param {string} kind
* @param {string} message * @param {string} message
*/ */
function addToChatbox(peerId, nick, kind, message){ function addToChatbox(peerId, nick, time, kind, message){
let userpass = getUserPass(); let userpass = getUserPass();
let row = document.createElement('div'); let row = document.createElement('div');
row.classList.add('message-row'); row.classList.add('message-row');
@ -1241,10 +1254,19 @@ function addToChatbox(peerId, nick, kind, message){
if(kind !== 'me') { if(kind !== 'me') {
let p = formatLines(message.split('\n')); let p = formatLines(message.split('\n'));
if (lastMessage.nick !== nick || lastMessage.peerId !== peerId) { 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.textContent = nick;
user.classList.add('message-user'); 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'); p.classList.add('message-content');
container.appendChild(p); container.appendChild(p);
@ -1365,7 +1387,7 @@ function handleInput() {
let s = ""; let s = "";
for(let key in settings) for(let key in settings)
s = s + `${key}: ${JSON.stringify(settings[key])}\n` s = s + `${key}: ${JSON.stringify(settings[key])}\n`
addToChatbox(null, null, null, s); addToChatbox(null, null, Date.now(), null, s);
return; return;
} }
let parsed = parseCommand(rest); let parsed = parseCommand(rest);