From cbfbcd768fcf72a0c7852bd9c9fa114f402124fb Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Fri, 8 Sep 2023 18:46:36 -0700 Subject: [PATCH] Chat Setting Menu + Various Tweaks * In place of the Help and Settings buttons, add a hamburger menu dropdown and place the links under there. * Also in the dropdown is Close All Cameras and Mute All Cameras (if you have any cams open; the links are hidden if not) * Also in the dropdown add a Logout button that just links to a new /logout route in order to unload the page and align with some users' expectations (not knowing closing out of the chat page was enough to log out of the room before) * Bring back "(offline)" indicators when a user is no longer in the room. --- pkg/pages.go | 13 +++++ pkg/server.go | 1 + src/App.vue | 99 +++++++++++++++++++++++++++++------ src/components/MessageBox.vue | 4 ++ web/templates/logout.html | 30 +++++++++++ 5 files changed, 132 insertions(+), 15 deletions(-) create mode 100644 web/templates/logout.html 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