mirror of
https://github.com/jech/galene.git
synced 2024-11-25 01:55:57 +01:00
Implement group status.
We now inform clients of the status of a group (locked, etc.). Also cleans up the handling of administrative messages, which solves the issue of receiving "user" before "joined".
This commit is contained in:
parent
d78a750b8d
commit
52a26327d7
8 changed files with 166 additions and 65 deletions
1
README
1
README
|
@ -207,6 +207,7 @@ following fields are allowed:
|
||||||
respectively with operator privileges, with presenter privileges, and
|
respectively with operator privileges, with presenter privileges, and
|
||||||
as passive listeners;
|
as passive listeners;
|
||||||
- `public`: if true, then the group is visible on the landing page;
|
- `public`: if true, then the group is visible on the landing page;
|
||||||
|
- `displayName`: a human-friendly version of the group name;
|
||||||
- `description`: a human-readable description of the group; this is
|
- `description`: a human-readable description of the group; this is
|
||||||
displayed on the landing page for public groups;
|
displayed on the landing page for public groups;
|
||||||
- `contact`: a human-readable contact for this group, such as an e-mail
|
- `contact`: a human-readable contact for this group, such as an e-mail
|
||||||
|
|
|
@ -100,12 +100,15 @@ its permissions or in the recommended RTC configuration.
|
||||||
group: group,
|
group: group,
|
||||||
username: username,
|
username: username,
|
||||||
permissions: permissions,
|
permissions: permissions,
|
||||||
|
status: status,
|
||||||
rtcConfiguration: RTCConfiguration
|
rtcConfiguration: RTCConfiguration
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The `permissions` field is an array of strings that may contain the values
|
The `permissions` field is an array of strings that may contain the values
|
||||||
`present`, `op` and `record`.
|
`present`, `op` and `record`. The `status` field is a dictionary that
|
||||||
|
contains random information that can be usefully displayed in the user
|
||||||
|
interface.
|
||||||
|
|
||||||
## Maintaining group membership
|
## Maintaining group membership
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ func (client *Client) Status() map[string]interface{} {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) PushClient(id, username string, permissions *group.ClientPermissions, status map[string]interface{}, kind string) error {
|
func (client *Client) PushClient(group, kind, id, username string, permissions group.ClientPermissions, status map[string]interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,6 +103,10 @@ func (client *Client) Kick(id, user, message string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *Client) Joined(group, kind string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (client *Client) PushConn(g *group.Group, id string, up conn.Up, tracks []conn.UpTrack, replace string) error {
|
func (client *Client) PushConn(g *group.Group, id string, up conn.Up, tracks []conn.UpTrack, replace string) error {
|
||||||
if client.group != g {
|
if client.group != g {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -102,6 +102,7 @@ type Client interface {
|
||||||
OverridePermissions(*Group) bool
|
OverridePermissions(*Group) bool
|
||||||
PushConn(g *Group, id string, conn conn.Up, tracks []conn.UpTrack, replace string) error
|
PushConn(g *Group, id string, conn conn.Up, tracks []conn.UpTrack, replace string) error
|
||||||
RequestConns(target Client, g *Group, id string) error
|
RequestConns(target Client, g *Group, id string) error
|
||||||
PushClient(id, username string, permissions *ClientPermissions, status map[string]interface{}, kind string) error
|
Joined(group, kind string) error
|
||||||
|
PushClient(group, kind, id, username string, permissions ClientPermissions, status map[string]interface{}) error
|
||||||
Kick(id, user, message string) error
|
Kick(id, user, message string) error
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,12 +92,17 @@ func (g *Group) Locked() (bool, string) {
|
||||||
|
|
||||||
func (g *Group) SetLocked(locked bool, message string) {
|
func (g *Group) SetLocked(locked bool, message string) {
|
||||||
g.mu.Lock()
|
g.mu.Lock()
|
||||||
defer g.mu.Unlock()
|
|
||||||
if locked {
|
if locked {
|
||||||
g.locked = &message
|
g.locked = &message
|
||||||
} else {
|
} else {
|
||||||
g.locked = nil
|
g.locked = nil
|
||||||
}
|
}
|
||||||
|
clients := g.getClientsUnlocked(nil)
|
||||||
|
g.mu.Unlock()
|
||||||
|
|
||||||
|
for _, c := range clients {
|
||||||
|
c.Joined(g.Name(), "change")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Group) Public() bool {
|
func (g *Group) Public() bool {
|
||||||
|
@ -118,6 +123,12 @@ func (g *Group) AllowRecording() bool {
|
||||||
return g.description.AllowRecording
|
return g.description.AllowRecording
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *Group) DisplayName() string {
|
||||||
|
g.mu.Lock()
|
||||||
|
defer g.mu.Unlock()
|
||||||
|
return g.description.DisplayName
|
||||||
|
}
|
||||||
|
|
||||||
var groups struct {
|
var groups struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
groups map[string]*Group
|
groups map[string]*Group
|
||||||
|
@ -293,8 +304,16 @@ func APIFromNames(names []string) (*webrtc.API, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Add(name string, desc *Description) (*Group, error) {
|
func Add(name string, desc *Description) (*Group, error) {
|
||||||
|
g, notify, err := add(name, desc)
|
||||||
|
for _, c := range notify {
|
||||||
|
c.Joined(g.Name(), "change")
|
||||||
|
}
|
||||||
|
return g, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func add(name string, desc *Description) (*Group, []Client, error) {
|
||||||
if name == "" || strings.HasSuffix(name, "/") {
|
if name == "" || strings.HasSuffix(name, "/") {
|
||||||
return nil, UserError("illegal group name")
|
return nil, nil, UserError("illegal group name")
|
||||||
}
|
}
|
||||||
|
|
||||||
groups.mu.Lock()
|
groups.mu.Lock()
|
||||||
|
@ -311,7 +330,7 @@ func Add(name string, desc *Description) (*Group, error) {
|
||||||
if desc == nil {
|
if desc == nil {
|
||||||
desc, err = GetDescription(name)
|
desc, err = GetDescription(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,9 +340,10 @@ func Add(name string, desc *Description) (*Group, error) {
|
||||||
clients: make(map[string]Client),
|
clients: make(map[string]Client),
|
||||||
timestamp: time.Now(),
|
timestamp: time.Now(),
|
||||||
}
|
}
|
||||||
autoLockKick(g, g.getClientsUnlocked(nil))
|
clients := g.getClientsUnlocked(nil)
|
||||||
|
autoLockKick(g, clients)
|
||||||
groups.groups[name] = g
|
groups.groups[name] = g
|
||||||
return g, nil
|
return g, clients, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
g.mu.Lock()
|
g.mu.Lock()
|
||||||
|
@ -332,7 +352,7 @@ func Add(name string, desc *Description) (*Group, error) {
|
||||||
if desc != nil {
|
if desc != nil {
|
||||||
g.description = desc
|
g.description = desc
|
||||||
} else if !descriptionChanged(name, g.description) {
|
} else if !descriptionChanged(name, g.description) {
|
||||||
return g, nil
|
return g, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
desc, err = GetDescription(name)
|
desc, err = GetDescription(name)
|
||||||
|
@ -341,12 +361,13 @@ func Add(name string, desc *Description) (*Group, error) {
|
||||||
log.Printf("Reading group %v: %v", name, err)
|
log.Printf("Reading group %v: %v", name, err)
|
||||||
}
|
}
|
||||||
deleteUnlocked(g)
|
deleteUnlocked(g)
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
g.description = desc
|
g.description = desc
|
||||||
autoLockKick(g, g.getClientsUnlocked(nil))
|
clients := g.getClientsUnlocked(nil)
|
||||||
|
autoLockKick(g, clients)
|
||||||
|
|
||||||
return g, nil
|
return g, clients, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Range(f func(g *Group) bool) {
|
func Range(f func(g *Group) bool) {
|
||||||
|
@ -511,15 +532,19 @@ func AddClient(group string, c Client) (*Group, error) {
|
||||||
g.clients[c.Id()] = c
|
g.clients[c.Id()] = c
|
||||||
g.timestamp = time.Now()
|
g.timestamp = time.Now()
|
||||||
|
|
||||||
|
c.Joined(g.Name(), "join")
|
||||||
|
|
||||||
id := c.Id()
|
id := c.Id()
|
||||||
u := c.Username()
|
u := c.Username()
|
||||||
p := c.Permissions()
|
p := c.Permissions()
|
||||||
s := c.Status()
|
s := c.Status()
|
||||||
c.PushClient(c.Id(), u, &p, s, "add")
|
c.PushClient(g.Name(), "add", c.Id(), u, p, s)
|
||||||
for _, cc := range clients {
|
for _, cc := range clients {
|
||||||
pp := cc.Permissions()
|
pp := cc.Permissions()
|
||||||
c.PushClient(cc.Id(), cc.Username(), &pp, cc.Status(), "add")
|
c.PushClient(
|
||||||
cc.PushClient(id, u, &p, s, "add")
|
g.Name(), "add", cc.Id(), cc.Username(), pp, cc.Status(),
|
||||||
|
)
|
||||||
|
cc.PushClient(g.Name(), "add", id, u, p, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
return g, nil
|
return g, nil
|
||||||
|
@ -539,6 +564,11 @@ func autoLockKick(g *Group, clients []Client) {
|
||||||
if g.description.Autolock && g.locked == nil {
|
if g.description.Autolock && g.locked == nil {
|
||||||
m := "this group is locked"
|
m := "this group is locked"
|
||||||
g.locked = &m
|
g.locked = &m
|
||||||
|
go func(clients []Client) {
|
||||||
|
for _, c := range clients {
|
||||||
|
c.Joined(g.Name(), "change")
|
||||||
|
}
|
||||||
|
}(g.getClientsUnlocked(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
if g.description.Autokick {
|
if g.description.Autokick {
|
||||||
|
@ -552,23 +582,22 @@ func DelClient(c Client) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
g.mu.Lock()
|
g.mu.Lock()
|
||||||
defer g.mu.Unlock()
|
|
||||||
|
|
||||||
if g.clients[c.Id()] != c {
|
if g.clients[c.Id()] != c {
|
||||||
log.Printf("Deleting unknown client")
|
log.Printf("Deleting unknown client")
|
||||||
|
g.mu.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
delete(g.clients, c.Id())
|
delete(g.clients, c.Id())
|
||||||
g.timestamp = time.Now()
|
g.timestamp = time.Now()
|
||||||
|
|
||||||
clients := g.getClientsUnlocked(nil)
|
clients := g.getClientsUnlocked(nil)
|
||||||
|
g.mu.Unlock()
|
||||||
|
|
||||||
go func(clients []Client) {
|
c.Joined(g.Name(), "leave")
|
||||||
for _, cc := range clients {
|
for _, cc := range clients {
|
||||||
cc.PushClient(c.Id(), "", nil, nil, "delete")
|
cc.PushClient(
|
||||||
}
|
g.Name(), "delete", c.Id(), "", ClientPermissions{}, nil,
|
||||||
}(clients)
|
)
|
||||||
|
}
|
||||||
autoLockKick(g, clients)
|
autoLockKick(g, clients)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -740,6 +769,9 @@ type Description struct {
|
||||||
modTime time.Time `json:"-"`
|
modTime time.Time `json:"-"`
|
||||||
fileSize int64 `json:"-"`
|
fileSize int64 `json:"-"`
|
||||||
|
|
||||||
|
// The user-friendly group name
|
||||||
|
DisplayName string `json:"displayName,omitempty"`
|
||||||
|
|
||||||
// A user-readable description of the group.
|
// A user-readable description of the group.
|
||||||
Description string `json:"description,omitempty"`
|
Description string `json:"description,omitempty"`
|
||||||
|
|
||||||
|
|
|
@ -111,14 +111,9 @@ func (c *webClient) OverridePermissions(g *group.Group) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *webClient) PushClient(id, username string, permissions *group.ClientPermissions, status map[string]interface{}, kind string) error {
|
func (c *webClient) PushClient(group, kind, id, username string, permissions group.ClientPermissions, status map[string]interface{}) error {
|
||||||
return c.write(clientMessage{
|
return c.action(pushClientAction{
|
||||||
Type: "user",
|
group, kind, id, username, permissions, status,
|
||||||
Kind: kind,
|
|
||||||
Id: id,
|
|
||||||
Username: username,
|
|
||||||
Permissions: permissions,
|
|
||||||
Status: status,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -804,6 +799,17 @@ func (c *webClient) PushConn(g *group.Group, id string, up conn.Up, tracks []con
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getGroupStatus(g *group.Group) map[string]interface{} {
|
||||||
|
status := make(map[string]interface{})
|
||||||
|
if locked, _ := g.Locked(); locked {
|
||||||
|
status["locked"] = true
|
||||||
|
}
|
||||||
|
if dn := g.DisplayName(); dn != "" {
|
||||||
|
status["displayName"] = dn
|
||||||
|
}
|
||||||
|
return status
|
||||||
|
}
|
||||||
|
|
||||||
func readMessage(conn *websocket.Conn, m *clientMessage) error {
|
func readMessage(conn *websocket.Conn, m *clientMessage) error {
|
||||||
err := conn.SetReadDeadline(time.Now().Add(15 * time.Second))
|
err := conn.SetReadDeadline(time.Now().Add(15 * time.Second))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -880,8 +886,22 @@ type connectionFailedAction struct {
|
||||||
id string
|
id string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type pushClientAction struct {
|
||||||
|
group string
|
||||||
|
kind string
|
||||||
|
id string
|
||||||
|
username string
|
||||||
|
permissions group.ClientPermissions
|
||||||
|
status map[string]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
type permissionsChangedAction struct{}
|
type permissionsChangedAction struct{}
|
||||||
|
|
||||||
|
type joinedAction struct {
|
||||||
|
group string
|
||||||
|
kind string
|
||||||
|
}
|
||||||
|
|
||||||
type kickAction struct {
|
type kickAction struct {
|
||||||
id string
|
id string
|
||||||
username string
|
username string
|
||||||
|
@ -1067,6 +1087,37 @@ func handleAction(c *webClient, a interface{}) error {
|
||||||
"unknown connection")
|
"unknown connection")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case pushClientAction:
|
||||||
|
if a.group != c.group.Name() {
|
||||||
|
log.Printf("got client for wrong group")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return c.write(clientMessage{
|
||||||
|
Type: "user",
|
||||||
|
Kind: a.kind,
|
||||||
|
Id: a.id,
|
||||||
|
Username: a.username,
|
||||||
|
Permissions: &a.permissions,
|
||||||
|
Status: a.status,
|
||||||
|
})
|
||||||
|
case joinedAction:
|
||||||
|
var status map[string]interface{}
|
||||||
|
if a.group != "" {
|
||||||
|
g := group.Get(a.group)
|
||||||
|
if g != nil {
|
||||||
|
status = getGroupStatus(g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
perms := c.permissions
|
||||||
|
return c.write(clientMessage{
|
||||||
|
Type: "joined",
|
||||||
|
Kind: a.kind,
|
||||||
|
Group: a.group,
|
||||||
|
Username: c.username,
|
||||||
|
Permissions: &perms,
|
||||||
|
Status: status,
|
||||||
|
RTCConfiguration: ice.ICEConfiguration(),
|
||||||
|
})
|
||||||
case permissionsChangedAction:
|
case permissionsChangedAction:
|
||||||
g := c.Group()
|
g := c.Group()
|
||||||
if g == nil {
|
if g == nil {
|
||||||
|
@ -1079,6 +1130,7 @@ func handleAction(c *webClient, a interface{}) error {
|
||||||
Group: g.Name(),
|
Group: g.Name(),
|
||||||
Username: c.username,
|
Username: c.username,
|
||||||
Permissions: &perms,
|
Permissions: &perms,
|
||||||
|
Status: getGroupStatus(g),
|
||||||
RTCConfiguration: ice.ICEConfiguration(),
|
RTCConfiguration: ice.ICEConfiguration(),
|
||||||
})
|
})
|
||||||
if !c.permissions.Present {
|
if !c.permissions.Present {
|
||||||
|
@ -1101,7 +1153,9 @@ func handleAction(c *webClient, a interface{}) error {
|
||||||
clients := g.GetClients(nil)
|
clients := g.GetClients(nil)
|
||||||
go func(clients []group.Client) {
|
go func(clients []group.Client) {
|
||||||
for _, cc := range clients {
|
for _, cc := range clients {
|
||||||
cc.PushClient(id, user, &perms, s, "change")
|
cc.PushClient(
|
||||||
|
g.Name(), "change", id, user, perms, s,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}(clients)
|
}(clients)
|
||||||
case kickAction:
|
case kickAction:
|
||||||
|
@ -1212,6 +1266,10 @@ func (c *webClient) Kick(id, user, message string) error {
|
||||||
return c.action(kickAction{id, user, message})
|
return c.action(kickAction{id, user, message})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *webClient) Joined(group, kind string) error {
|
||||||
|
return c.action(joinedAction{group, kind})
|
||||||
|
}
|
||||||
|
|
||||||
func kickClient(g *group.Group, id, user, dest string, message string) error {
|
func kickClient(g *group.Group, id, user, dest string, message string) error {
|
||||||
client := g.GetClient(dest)
|
client := g.GetClient(dest)
|
||||||
if client == nil {
|
if client == nil {
|
||||||
|
@ -1243,14 +1301,6 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
||||||
return group.ProtocolError("you are not joined")
|
return group.ProtocolError("you are not joined")
|
||||||
}
|
}
|
||||||
leaveGroup(c)
|
leaveGroup(c)
|
||||||
perms := c.permissions
|
|
||||||
return c.write(clientMessage{
|
|
||||||
Type: "joined",
|
|
||||||
Kind: "leave",
|
|
||||||
Group: m.Group,
|
|
||||||
Username: c.username,
|
|
||||||
Permissions: &perms,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.Kind != "join" {
|
if m.Kind != "join" {
|
||||||
|
@ -1298,18 +1348,6 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
c.group = g
|
c.group = g
|
||||||
perms := c.permissions
|
|
||||||
err = c.write(clientMessage{
|
|
||||||
Type: "joined",
|
|
||||||
Kind: "join",
|
|
||||||
Group: m.Group,
|
|
||||||
Username: c.username,
|
|
||||||
Permissions: &perms,
|
|
||||||
RTCConfiguration: ice.ICEConfiguration(),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h := c.group.GetChatHistory()
|
h := c.group.GetChatHistory()
|
||||||
for _, m := range h {
|
for _, m := range h {
|
||||||
err := c.write(clientMessage{
|
err := c.write(clientMessage{
|
||||||
|
@ -1608,8 +1646,10 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
||||||
status := c.Status()
|
status := c.Status()
|
||||||
go func(clients []group.Client) {
|
go func(clients []group.Client) {
|
||||||
for _, cc := range clients {
|
for _, cc := range clients {
|
||||||
cc.PushClient(id, user, &perms, status,
|
cc.PushClient(
|
||||||
"change")
|
g.Name(), "change",
|
||||||
|
id, user, perms, status,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}(g.GetClients(nil))
|
}(g.GetClients(nil))
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -2091,12 +2091,35 @@ function displayUsername() {
|
||||||
|
|
||||||
let presentRequested = null;
|
let presentRequested = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} [title]
|
||||||
|
*/
|
||||||
|
function setTitle(title) {
|
||||||
|
function set(title) {
|
||||||
|
document.title = title;
|
||||||
|
document.getElementById('title').textContent = title;
|
||||||
|
}
|
||||||
|
if(title) {
|
||||||
|
set(title);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let t = group.charAt(0).toUpperCase() + group.slice(1);
|
||||||
|
if(t) {
|
||||||
|
set(t);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
set('Galène');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @this {ServerConnection}
|
* @this {ServerConnection}
|
||||||
* @param {string} group
|
* @param {string} group
|
||||||
* @param {Object<string,boolean>} perms
|
* @param {Object<string,boolean>} perms
|
||||||
|
* @param {Object<string,any>} status
|
||||||
|
* @param {string} message
|
||||||
*/
|
*/
|
||||||
async function gotJoined(kind, group, perms, message) {
|
async function gotJoined(kind, group, perms, status, message) {
|
||||||
let present = presentRequested;
|
let present = presentRequested;
|
||||||
presentRequested = null;
|
presentRequested = null;
|
||||||
|
|
||||||
|
@ -2108,7 +2131,7 @@ async function gotJoined(kind, group, perms, message) {
|
||||||
return;
|
return;
|
||||||
case 'redirect':
|
case 'redirect':
|
||||||
this.close();
|
this.close();
|
||||||
document.location = message;
|
document.location.href = message;
|
||||||
return;
|
return;
|
||||||
case 'leave':
|
case 'leave':
|
||||||
this.close();
|
this.close();
|
||||||
|
@ -2116,6 +2139,7 @@ async function gotJoined(kind, group, perms, message) {
|
||||||
return;
|
return;
|
||||||
case 'join':
|
case 'join':
|
||||||
case 'change':
|
case 'change':
|
||||||
|
setTitle(status.displayName || group);
|
||||||
displayUsername();
|
displayUsername();
|
||||||
setButtonsVisibility();
|
setButtonsVisibility();
|
||||||
if(kind === 'change')
|
if(kind === 'change')
|
||||||
|
@ -3061,12 +3085,7 @@ async function serverConnect() {
|
||||||
|
|
||||||
function start() {
|
function start() {
|
||||||
group = decodeURIComponent(location.pathname.replace(/^\/[a-z]*\//, ''));
|
group = decodeURIComponent(location.pathname.replace(/^\/[a-z]*\//, ''));
|
||||||
let title = group.charAt(0).toUpperCase() + group.slice(1);
|
setTitle();
|
||||||
if(group !== '') {
|
|
||||||
document.title = title;
|
|
||||||
document.getElementById('title').textContent = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
addFilters();
|
addFilters();
|
||||||
setMediaChoices(false).then(e => reflectSettings());
|
setMediaChoices(false).then(e => reflectSettings());
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,7 @@ function ServerConnection() {
|
||||||
*
|
*
|
||||||
* kind is one of 'join', 'fail', 'change' or 'leave'.
|
* kind is one of 'join', 'fail', 'change' or 'leave'.
|
||||||
*
|
*
|
||||||
* @type{(this: ServerConnection, kind: string, group: string, permissions: Object<string,boolean>, message: string) => void}
|
* @type{(this: ServerConnection, kind: string, group: string, permissions: Object<string,boolean>, status: Object<string,any>, message: string) => void}
|
||||||
*/
|
*/
|
||||||
this.onjoined = null;
|
this.onjoined = null;
|
||||||
/**
|
/**
|
||||||
|
@ -284,7 +284,7 @@ ServerConnection.prototype.connect = async function(url) {
|
||||||
sc.onuser.call(sc, id, 'delete');
|
sc.onuser.call(sc, id, 'delete');
|
||||||
}
|
}
|
||||||
if(sc.group && sc.onjoined)
|
if(sc.group && sc.onjoined)
|
||||||
sc.onjoined.call(sc, 'leave', sc.group, {}, '');
|
sc.onjoined.call(sc, 'leave', sc.group, {}, {}, '');
|
||||||
sc.group = null;
|
sc.group = null;
|
||||||
sc.username = null;
|
sc.username = null;
|
||||||
if(sc.onclose)
|
if(sc.onclose)
|
||||||
|
@ -336,6 +336,7 @@ ServerConnection.prototype.connect = async function(url) {
|
||||||
if(sc.onjoined)
|
if(sc.onjoined)
|
||||||
sc.onjoined.call(sc, m.kind, m.group,
|
sc.onjoined.call(sc, m.kind, m.group,
|
||||||
m.permissions || {},
|
m.permissions || {},
|
||||||
|
m.status,
|
||||||
m.value || null);
|
m.value || null);
|
||||||
break;
|
break;
|
||||||
case 'user':
|
case 'user':
|
||||||
|
|
Loading…
Reference in a new issue