diff --git a/pkg/pages.go b/pkg/pages.go index 61b712c..b8278eb 100644 --- a/pkg/pages.go +++ b/pkg/pages.go @@ -125,3 +125,16 @@ func AboutPage() http.HandlerFunc { tmpl.ExecuteTemplate(w, "index", values) }) } + +// LogoutPage returns the HTML template for the logout page. +func LogoutPage() http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Load the template, TODO: once on server startup. + tmpl := template.New("index") + tmpl, err := tmpl.ParseFiles("web/templates/logout.html") + if err != nil { + panic(err.Error()) + } + tmpl.ExecuteTemplate(w, "index", nil) + }) +} diff --git a/pkg/server.go b/pkg/server.go index cda97d0..a3ad1c4 100644 --- a/pkg/server.go +++ b/pkg/server.go @@ -32,6 +32,7 @@ func (s *Server) Setup() error { mux.Handle("/", IndexPage()) mux.Handle("/about", AboutPage()) + mux.Handle("/logout", LogoutPage()) mux.Handle("/ws", s.WebSocket()) mux.Handle("/api/statistics", s.Statistics()) mux.Handle("/api/blocklist", s.BlockList()) diff --git a/src/App.vue b/src/App.vue index ac3f9d6..159f5a3 100644 --- a/src/App.vue +++ b/src/App.vue @@ -116,6 +116,7 @@ export default { whoTab: 'online', whoSort: 'a-z', whoMap: {}, // map username to wholist entry + whoOnline: {}, // map users actually online right now muted: {}, // muted usernames for client side state // Misc. user preferences (TODO: move all of them here) @@ -512,6 +513,10 @@ export default { if (this.webcam.vipOnly && this.isVIP) status |= this.VideoFlag.VipOnly; return status; }, + numVideosOpen() { + // Return the count of other peoples videos we have open. + return Object.keys(this.WebRTC.streams).length; + }, sortedWhoList() { let result = [...this.whoList]; @@ -871,6 +876,7 @@ export default { // WhoList updates. onWho(msg) { this.whoList = msg.whoList; + this.whoOnline = {}; if (this.whoList == undefined) { this.whoList = []; @@ -880,6 +886,7 @@ export default { // off camera, close our side of the connection. for (let row of this.whoList) { this.whoMap[row.username] = row; + this.whoOnline[row.username] = true; if (this.WebRTC.streams[row.username] != undefined && !(row.video & this.VideoFlag.Active)) { this.closeVideo(row.username, "offerer"); @@ -1510,9 +1517,6 @@ export default { } return ""; }, - isUsernameOnline(username) { - return this.whoMap[username] != undefined; - }, getUser(username) { // Return the full User object from the Who List, or a dummy placeholder if not online. if (this.whoMap[username] != undefined) { @@ -1523,6 +1527,10 @@ export default { username: username, }; }, + isUserOffline(username) { + // Return if the username is not presently online in the chat. + return this.whoOnline[username] !== true; + }, avatarForUsername(username) { if (this.whoMap[username] != undefined && this.whoMap[username].avatar) { return this.avatarURL(this.whoMap[username]); @@ -1999,6 +2007,32 @@ export default { // Inform backend we have closed it. this.sendWatch(username, false); }, + closeOpenVideos() { + // Close all videos open of other users. + for (let username of Object.keys(this.WebRTC.streams)) { + this.closeVideo(username, "offerer"); + } + }, + muteAllVideos() { + // Mute the mic of all open videos. + let count = 0; + for (let username of Object.keys(this.WebRTC.streams)) { + if (this.WebRTC.muted[username]) continue; + + // Find the