Basic chat UI complete.
This commit is contained in:
parent
f109314163
commit
e81a4c0973
|
|
@ -150,17 +150,14 @@ class pmHandler{
|
||||||
* @returns {String} sanatized/validates message, returns null on validation failure
|
* @returns {String} sanatized/validates message, returns null on validation failure
|
||||||
*/
|
*/
|
||||||
sanatizeMessage(msg){
|
sanatizeMessage(msg){
|
||||||
//if msg is empty or null
|
//Normally I'd kill empty messages here
|
||||||
if(msg == null || msg == ''){
|
//But instead we're allowing them for sesh startups
|
||||||
//Pimp slap that shit into fucking oblivion
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Trim and Sanatize for XSS
|
//Trim and Sanatize for XSS
|
||||||
msg = validator.trim(validator.escape(msg));
|
msg = validator.trim(validator.escape(msg));
|
||||||
|
|
||||||
//Return whether or not the shit was long enough
|
//Return whether or not the shit was too long
|
||||||
if(validator.isLength(msg, {min: 1, max: 255})){
|
if(validator.isLength(msg, {min: 0, max: 255})){
|
||||||
//If it's valid return the message
|
//If it's valid return the message
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,13 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. %>
|
||||||
</div>
|
</div>
|
||||||
<div id="pm-panel-sesh-container">
|
<div id="pm-panel-sesh-container">
|
||||||
<div id="pm-panel-sesh-buffer">
|
<div id="pm-panel-sesh-buffer">
|
||||||
|
<div id="pm-panel-sesh-welcome">
|
||||||
|
<h1>Start a sesh to start chatting!</h1>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="control-prompt" id="pm-panel-sesh-control-div">
|
<div class="control-prompt" id="pm-panel-sesh-control-div">
|
||||||
<input class="control-prompt" id="pm-panel-message-prompt" placeholder="Chat...">
|
<input class="control-prompt" id="pm-panel-message-prompt" placeholder="Chat..." disabled>
|
||||||
<button class="positive-button" id="pm-panel-send-button">Send</button>
|
<button class="positive-button" id="pm-panel-send-button" disabled>Send</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -61,8 +61,32 @@ div.pm-panel-sesh-list-entry{
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
div.pm-panel-sesh-list-entry p{
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
div.pm-panel-sesh-list-entry, div.pm-panel-sesh-list-entry p{
|
div.pm-panel-sesh-list-entry, div.pm-panel-sesh-list-entry p{
|
||||||
margin: 0;
|
margin: 0;
|
||||||
text-wrap: nowrap;
|
text-wrap: nowrap;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pm-panel-sesh-buffer span{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pm-panel-sesh-message-sender, .pm-panel-sesh-message-content{
|
||||||
|
margin: 0;
|
||||||
|
font-size: 10pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pm-panel-sesh-welcome{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
27
www/css/popup/startChatSesh.css
Normal file
27
www/css/popup/startChatSesh.css
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*Canopy - The next generation of stoner streaming software
|
||||||
|
Copyright (C) 2024-2025 Rainbownapkin and the TTN Community
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||||
|
#pm-sesh-popup-div{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pm-sesh-popup-div p{
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pm-sesh-popup-sup{
|
||||||
|
font-size: 0.7em
|
||||||
|
}
|
||||||
|
|
@ -129,13 +129,13 @@ button{
|
||||||
border-radius: 0.5em;
|
border-radius: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
button:hover{
|
button:hover:not([disabled]){
|
||||||
color: var(--focus0-alt1);
|
color: var(--focus0-alt1);
|
||||||
background-color: var(--focus0-alt0);
|
background-color: var(--focus0-alt0);
|
||||||
box-shadow: var(--focus-glow0);
|
box-shadow: var(--focus-glow0);
|
||||||
}
|
}
|
||||||
|
|
||||||
button:active{
|
button:active:not([disabled]){
|
||||||
color: var(--focus0-alt0);
|
color: var(--focus0-alt0);
|
||||||
background-color: var(--focus0-alt1);
|
background-color: var(--focus0-alt1);
|
||||||
box-shadow: var(--focus-glow0-alt0);
|
box-shadow: var(--focus-glow0-alt0);
|
||||||
|
|
@ -179,13 +179,13 @@ textarea{
|
||||||
color: var(--accent1);
|
color: var(--accent1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.danger-button:hover, .critical-danger-button, .critical-danger-button:hover{
|
.danger-button:hover:not([disabled]), .critical-danger-button, .critical-danger-button:hover{
|
||||||
background-color: var(--danger0-alt1);
|
background-color: var(--danger0-alt1);
|
||||||
color: var(--danger0-alt0);
|
color: var(--danger0-alt0);
|
||||||
box-shadow: var(--danger-glow0);
|
box-shadow: var(--danger-glow0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical-danger-button:hover{
|
.critical-danger-button:hover:not([disabled]){
|
||||||
background-color: var(--danger0-alt2);
|
background-color: var(--danger0-alt2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,12 +219,12 @@ textarea{
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.positive-button:hover{
|
.positive-button:hover:not([disabled]){
|
||||||
color: var(--focus0-alt1);
|
color: var(--focus0-alt1);
|
||||||
background-color: var(--focus0-alt0);
|
background-color: var(--focus0-alt0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.positive-button:active{
|
.positive-button:active:not([disabled]){
|
||||||
color: var(--focus0-alt0);
|
color: var(--focus0-alt0);
|
||||||
background-color: var(--focus0-alt1);
|
background-color: var(--focus0-alt1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,9 @@ class emotePanel extends panelObj{
|
||||||
this.setupInput();
|
this.setupInput();
|
||||||
|
|
||||||
this.renderEmoteLists();
|
this.renderEmoteLists();
|
||||||
|
|
||||||
|
//Call derived method
|
||||||
|
super.docSwitch();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,11 @@ class pmPanel extends panelObj{
|
||||||
constructor(client, panelDocument){
|
constructor(client, panelDocument){
|
||||||
super(client, "Private Messaging", "/panel/pm", panelDocument);
|
super(client, "Private Messaging", "/panel/pm", panelDocument);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String to hold name of currently active sesh
|
||||||
|
*/
|
||||||
|
this.activeSesh = "";
|
||||||
|
|
||||||
this.defineListeners();
|
this.defineListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,33 +39,112 @@ class pmPanel extends panelObj{
|
||||||
}
|
}
|
||||||
|
|
||||||
docSwitch(){
|
docSwitch(){
|
||||||
|
this.startSeshButton = this.panelDocument.querySelector('#pm-panel-start-sesh');
|
||||||
this.seshList = this.panelDocument.querySelector('#pm-panel-sesh-list');
|
this.seshList = this.panelDocument.querySelector('#pm-panel-sesh-list');
|
||||||
|
this.seshBuffer = this.panelDocument.querySelector('#pm-panel-sesh-buffer');
|
||||||
|
this.seshPrompt = this.panelDocument.querySelector('#pm-panel-message-prompt');
|
||||||
|
this.seshSendButton = this.panelDocument.querySelector('#pm-panel-send-button');
|
||||||
|
|
||||||
this.setupInput();
|
this.setupInput();
|
||||||
|
|
||||||
this.renderSeshList();
|
this.renderSeshList();
|
||||||
|
|
||||||
|
//If we have an active sesh
|
||||||
|
if(this.activeSesh != null && this.activeSesh != ""){
|
||||||
|
//Render messages
|
||||||
|
this.renderMessages();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Call derived method
|
||||||
|
super.docSwitch();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines network related event listeners
|
* Defines network related event listeners
|
||||||
*/
|
*/
|
||||||
defineListeners(){
|
defineListeners(){
|
||||||
|
this.client.pmSocket.on("message", this.handlePM.bind(this));
|
||||||
|
this.client.pmSocket.on("sent", this.handlePM.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines input-related event handlers
|
* Defines input-related event handlers
|
||||||
*/
|
*/
|
||||||
setupInput(){
|
setupInput(){
|
||||||
|
this.startSeshButton.addEventListener('click', this.startSesh.bind(this));
|
||||||
|
this.seshPrompt.addEventListener("keydown", this.send.bind(this));
|
||||||
|
this.seshSendButton.addEventListener("click", this.send.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
startSesh(event){
|
||||||
|
new startSeshPopup(event, this.client, this.renderSeshList.bind(this), this.ownerDoc);
|
||||||
|
}
|
||||||
|
|
||||||
|
handlePM(data){
|
||||||
|
const nameObj = pmHandler.genSeshName(data);
|
||||||
|
|
||||||
|
//If this message is for the active sesh
|
||||||
|
if(nameObj.name == this.activeSesh){
|
||||||
|
//Render out the newest message
|
||||||
|
this.renderMessage(data);
|
||||||
|
}else{
|
||||||
|
//pull current session entry if it exists
|
||||||
|
const curEntry = this.panelDocument.querySelector(`[data-id="${nameObj.name}"]`);
|
||||||
|
|
||||||
|
//If it doesn't exist
|
||||||
|
if(curEntry == null){
|
||||||
|
//Re-render out the sesh list
|
||||||
|
this.renderSeshList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sends private message from sesh prompt to server
|
||||||
|
* @param {Event} event - Event passed down from Event Handler
|
||||||
|
*/
|
||||||
|
send(event){
|
||||||
|
if((!event || !event.key || event.key == "Enter") && this.seshPrompt.value && this.activeSesh != ''){
|
||||||
|
//Pull current sesh from sesh list
|
||||||
|
const sesh = this.client.pmHandler.seshList.get(this.activeSesh);
|
||||||
|
|
||||||
|
//Send message out to server
|
||||||
|
this.client.pmSocket.emit("pm", {
|
||||||
|
recipients: sesh.recipients,
|
||||||
|
msg: this.seshPrompt.value
|
||||||
|
});
|
||||||
|
|
||||||
|
//Clear our prompt
|
||||||
|
this.seshPrompt.value = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render out current sesh array to sesh list UI
|
* Render out current sesh array to sesh list UI
|
||||||
*/
|
*/
|
||||||
renderSeshList(){
|
renderSeshList(){
|
||||||
|
//Clear out the sesh list
|
||||||
|
this.seshList.innerHTML = "";
|
||||||
|
|
||||||
|
//Assemble temporary array from client PM Handler sesh list
|
||||||
|
const seshList = Array.from(this.client.pmHandler.seshList);
|
||||||
|
|
||||||
|
//If we have existing sessions and no active sesh
|
||||||
|
if(this.activeSesh == "" && seshList[0] != null){
|
||||||
|
//Enable UI elements
|
||||||
|
this.seshPrompt.disabled = false;
|
||||||
|
this.seshSendButton.disabled = false;
|
||||||
|
|
||||||
|
//Render out messages
|
||||||
|
this.renderMessages();
|
||||||
|
|
||||||
|
//Set the first one as active
|
||||||
|
this.activeSesh = seshList[0][1].id;
|
||||||
|
}
|
||||||
|
|
||||||
//For each session tracked by the pmHandler
|
//For each session tracked by the pmHandler
|
||||||
for(const sesh of this.client.pmHandler.seshList){
|
for(const seshEntry of seshList){
|
||||||
this.renderSeshListEntry(sesh);
|
this.renderSeshListEntry(seshEntry[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -72,17 +156,171 @@ class pmPanel extends panelObj{
|
||||||
const entryDiv = document.createElement('div');
|
const entryDiv = document.createElement('div');
|
||||||
//Set conatiner div classes
|
//Set conatiner div classes
|
||||||
entryDiv.classList.add('pm-panel-sesh-list-entry','interactive');
|
entryDiv.classList.add('pm-panel-sesh-list-entry','interactive');
|
||||||
|
//Set dataset sesh name
|
||||||
|
entryDiv.dataset.id = sesh.id;
|
||||||
|
|
||||||
|
//If the current entry is the active sesh
|
||||||
|
if(sesh.id == this.activeSesh){
|
||||||
|
//mark it as such
|
||||||
|
entryDiv.classList.add('positive');
|
||||||
|
}
|
||||||
|
|
||||||
//Create sesh label
|
//Create sesh label
|
||||||
const seshLabel = document.createElement('p');
|
const seshLabel = document.createElement('p');
|
||||||
//Create human-readable label out of members array
|
//Create human-readable label out of members array
|
||||||
seshLabel.textContent = utils.unescapeEntities(sesh.recipients.sort().join(', '));
|
seshLabel.textContent = utils.unescapeEntities(sesh.id);
|
||||||
|
|
||||||
//append sesh label to entry div
|
//append sesh label to entry div
|
||||||
entryDiv.appendChild(seshLabel);
|
entryDiv.appendChild(seshLabel);
|
||||||
|
|
||||||
//Append entry div to sesh list
|
//Append entry div to sesh list
|
||||||
this.seshList.appendChild(entryDiv);
|
this.seshList.appendChild(entryDiv);
|
||||||
|
|
||||||
|
//Add input-related event listener for entry div
|
||||||
|
entryDiv.addEventListener('click', this.selectSesh.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
selectSesh(event){
|
||||||
|
//Attempt to pull previously active sesh item from list
|
||||||
|
const wasActive = this.panelDocument.querySelector('.positive');
|
||||||
|
|
||||||
|
//If there was an active sesh
|
||||||
|
if(wasActive != null){
|
||||||
|
//Remove active sesh class from old item
|
||||||
|
wasActive.classList.remove('positive');
|
||||||
|
}
|
||||||
|
|
||||||
|
//Pull new active sesh name from target dataset
|
||||||
|
this.activeSesh = event.target.dataset.id;
|
||||||
|
|
||||||
|
//Set new sesh as active sesh
|
||||||
|
event.target.classList.add('positive');
|
||||||
|
|
||||||
|
//Re-render message buffer
|
||||||
|
this.renderMessages();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderMessages(){
|
||||||
|
//Empty out the sesh buffer
|
||||||
|
this.seshBuffer.innerHTML = "";
|
||||||
|
|
||||||
|
//Pull sesh from pmHandler
|
||||||
|
const sesh = this.client.pmHandler.seshList.get(this.activeSesh);
|
||||||
|
|
||||||
|
//If the sesh is real
|
||||||
|
if(sesh != null){
|
||||||
|
//for each message in the sesh
|
||||||
|
for(const message of sesh.messages){
|
||||||
|
//Render out messages to the buffer
|
||||||
|
this.renderMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderMessage(message){
|
||||||
|
const msgSpan = document.createElement('span');
|
||||||
|
|
||||||
|
const msgSender = document.createElement('p');
|
||||||
|
msgSender.innerText = utils.unescapeEntities(`${message.sender}:`);
|
||||||
|
msgSender.classList.add('pm-panel-sesh-message-sender');
|
||||||
|
|
||||||
|
const msgContent = document.createElement('p');
|
||||||
|
msgContent.innerText = utils.unescapeEntities(message.msg);
|
||||||
|
msgContent.classList.add('pm-panel-sesh-message-content');
|
||||||
|
|
||||||
|
msgSpan.appendChild(msgSender);
|
||||||
|
msgSpan.appendChild(msgContent);
|
||||||
|
|
||||||
|
this.seshBuffer.appendChild(msgSpan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class representing pop-up dialogue to start a private messaging sesh
|
||||||
|
*/
|
||||||
|
class startSeshPopup{
|
||||||
|
/**
|
||||||
|
* Instantiates a new schedule media Pop-up
|
||||||
|
* @param {Event} event - Event passed down from Event Listener
|
||||||
|
* @param {channel} client - Parent Client Management Object
|
||||||
|
* @param {String} url - URL/link to media to queue
|
||||||
|
* @param {String} title - Title of media to queue
|
||||||
|
* @param {Function} cb - Callback function, passed upon pop-up creation
|
||||||
|
* @param {Document} doc - Current owner documnet of the panel, so we know where to drop our pop-up
|
||||||
|
*/
|
||||||
|
constructor(event, client, cb, doc){
|
||||||
|
/**
|
||||||
|
* Parent Client Management Object
|
||||||
|
*/
|
||||||
|
this.client = client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback function, passed upon pop-up creation
|
||||||
|
*/
|
||||||
|
this.cb = cb;
|
||||||
|
|
||||||
|
//Create media popup and call async constructor when done
|
||||||
|
//unfortunately we cant call constructors asyncronously, and we cant call back to this from super, so we can't extend this as it stands :(
|
||||||
|
/**
|
||||||
|
* canopyUXUtils.popup() object
|
||||||
|
*/
|
||||||
|
this.popup = new canopyUXUtils.popup('/startChatSesh', true, this.asyncConstructor.bind(this), doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Continuation of object construction, called after child popup object construction
|
||||||
|
*/
|
||||||
|
asyncConstructor(){
|
||||||
|
//Grab required UI elements
|
||||||
|
this.startSeshButton = this.popup.contentDiv.querySelector('#pm-sesh-popup-button');
|
||||||
|
this.usernamePrompt = this.popup.contentDiv.querySelector('#pm-sesh-popup-prompt');
|
||||||
|
|
||||||
|
//Setup input
|
||||||
|
this.setupInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines input-related Event Handlers
|
||||||
|
*/
|
||||||
|
setupInput(){
|
||||||
|
//Setup input
|
||||||
|
this.startSeshButton.addEventListener('click', this.startSesh.bind(this));
|
||||||
|
this.popup.popupDiv.addEventListener('keydown', this.startSesh.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles sending request to schedule item to the queue
|
||||||
|
* @param {Event} event - Event passed down from Event Listener
|
||||||
|
*/
|
||||||
|
startSesh(event){
|
||||||
|
//If we clicked or hit enter
|
||||||
|
if(event.key == null || event.key == "Enter"){
|
||||||
|
/*
|
||||||
|
//Cook a new sesh from
|
||||||
|
const newSesh = new pmSesh({
|
||||||
|
//Split usernames by space
|
||||||
|
sender: this.client.user.user,
|
||||||
|
recipients: this.usernamePrompt.value.split(" ")
|
||||||
|
});
|
||||||
|
|
||||||
|
//Pop new sesh into pmHandler
|
||||||
|
this.client.pmHandler.seshList.set(newSesh.id, newSesh);
|
||||||
|
*/
|
||||||
|
|
||||||
|
//Send message out to server
|
||||||
|
this.client.pmSocket.emit("pm", {
|
||||||
|
recipients: this.usernamePrompt.value.split(" "),
|
||||||
|
msg: ""
|
||||||
|
});
|
||||||
|
|
||||||
|
//If we have a function
|
||||||
|
if(typeof this.cb == "function"){
|
||||||
|
//Call any callbacks we where given
|
||||||
|
this.cb();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Close the popup
|
||||||
|
this.popup.closePopup();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1542,7 +1542,7 @@ class reschedulePopup extends schedulePopup{
|
||||||
this.media = media;
|
this.media = media;
|
||||||
}
|
}
|
||||||
|
|
||||||
schedule(event){
|
startSesh(event){
|
||||||
//If we clicked or hit enter
|
//If we clicked or hit enter
|
||||||
if(event.key == null || event.key == "Enter"){
|
if(event.key == null || event.key == "Enter"){
|
||||||
//Get localized input date
|
//Get localized input date
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,9 @@ class settingsPanel extends panelObj{
|
||||||
|
|
||||||
this.renderSettings();
|
this.renderSettings();
|
||||||
this.setupInput();
|
this.setupInput();
|
||||||
|
|
||||||
|
//Call derived method
|
||||||
|
super.docSwitch();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ class pmHandler{
|
||||||
/**
|
/**
|
||||||
* List of PM Sessions
|
* List of PM Sessions
|
||||||
*/
|
*/
|
||||||
this.seshList = [];
|
this.seshList = new Map();
|
||||||
|
|
||||||
this.defineListeners();
|
this.defineListeners();
|
||||||
this.setupInput();
|
this.setupInput();
|
||||||
|
|
@ -66,50 +66,63 @@ class pmHandler{
|
||||||
//Store whether or not current message has been consumed by an existing sesh
|
//Store whether or not current message has been consumed by an existing sesh
|
||||||
let consumed = false;
|
let consumed = false;
|
||||||
|
|
||||||
|
const nameObj = pmHandler.genSeshName(data);
|
||||||
|
|
||||||
//Create members array from scratch to avoid changing the input data for further processing
|
//Create members array from scratch to avoid changing the input data for further processing
|
||||||
const members = [];
|
const members = nameObj.recipients;
|
||||||
|
|
||||||
//Manually iterate through recipients
|
|
||||||
for(const member of data.recipients){
|
|
||||||
//check to make sure we're not adding ourselves
|
|
||||||
if(member != this.client.user.user){
|
|
||||||
//Copy relevant array members by value instead of reference
|
|
||||||
members.push(member);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//If this wasn't our message
|
|
||||||
if(data.sender != this.client.user.user){
|
|
||||||
//Push sender onto members list
|
|
||||||
members.push(data.sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
//For each existing sesh
|
//For each existing sesh
|
||||||
for(let seshIndex in this.seshList){
|
for(const seshEntry of this.seshList){
|
||||||
//Get current sesh
|
//Pull sesh object from map entry
|
||||||
const sesh = this.seshList[seshIndex];
|
const sesh = seshEntry[1];
|
||||||
|
|
||||||
//Check to see if the length of sesh recipients equals current length (only check on arrays that actually make sense to save time)
|
//If currently checked sesh ID matches calculated message sesh id
|
||||||
if(sesh.recipients.length == members.length){
|
if(sesh.id == nameObj.name){
|
||||||
/*Feels like cheating to have the JS engine to the hard bits by just telling it to sort them.
|
//Dump collected message into the matching session
|
||||||
That being said, since the function is implemented into the JS Engine itself
|
sesh.messages.push(data);
|
||||||
It will be quicker than any custom comparison code we can write*/
|
|
||||||
|
|
||||||
//Sort recipient lists so lists with the same user will be equal when joined together in a string and compare, if they're the same...
|
//Add sesh to sesh map
|
||||||
if(sesh.recipients.sort().join() == members.sort().join()){
|
this.seshList.set(sesh.id, sesh);
|
||||||
//Dump collected message into the matching session
|
|
||||||
this.seshList[seshIndex].messages.push(data);
|
|
||||||
|
|
||||||
//Let the rest of the method know that we've consumed this message
|
//Let the rest of the method know that we've consumed this message
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//If we made it through the loop without consuming the message
|
//If we made it through the loop without consuming the message
|
||||||
if(!consumed){
|
if(!consumed){
|
||||||
//Add it to it's own fresh new sesh
|
//Generate a new sesh
|
||||||
this.seshList.push(new pmSesh(data, client));
|
const sesh = new pmSesh(data, client);
|
||||||
|
|
||||||
|
//Add it to the sesh list
|
||||||
|
this.seshList.set(sesh.id, sesh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static genSeshName(message){
|
||||||
|
const recipients = [];
|
||||||
|
|
||||||
|
//Manually iterate through recipients
|
||||||
|
for(const member of message.recipients){
|
||||||
|
//check to make sure we're not adding ourselves
|
||||||
|
if(member != client.user.user){
|
||||||
|
//Copy relevant array members by value instead of reference
|
||||||
|
recipients.push(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//If this wasn't our message
|
||||||
|
if(message.sender != client.user.user){
|
||||||
|
//Push sender onto members list
|
||||||
|
recipients.push(message.sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Sort recipients
|
||||||
|
recipients.sort();
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: recipients.join(', '),
|
||||||
|
recipients
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -128,29 +141,21 @@ class pmSesh{
|
||||||
*/
|
*/
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
|
||||||
|
const nameObj = pmHandler.genSeshName(message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Members of session excluding the currently logged in user
|
* Members of session excluding the currently logged in user
|
||||||
*/
|
*/
|
||||||
this.recipients = [];
|
this.recipients = nameObj.recipients
|
||||||
|
|
||||||
//Manually iterate through recipients
|
/**
|
||||||
for(const member of message.recipients){
|
* Name of the chat sesh, named after out-going recipients
|
||||||
//check to make sure we're not adding ourselves
|
*/
|
||||||
if(member != this.client.user.user){
|
this.id = nameObj.name;
|
||||||
//Copy relevant array members by value instead of reference
|
|
||||||
this.recipients.push(member);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//If this wasn't our message
|
|
||||||
if(message.sender != this.client.user.user){
|
|
||||||
//Push sender onto members list
|
|
||||||
this.recipients.push(message.sender);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array containing all session messages
|
* Array containing all session messages
|
||||||
*/
|
*/
|
||||||
this.messages = [message];
|
this.messages = (message.msg == "" || message.msg == null) ? [] : [message];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
23
www/popup/startChatSesh.html
Normal file
23
www/popup/startChatSesh.html
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!-- Canopy - The next generation of stoner streaming software
|
||||||
|
Copyright (C) 2024-2025 Rainbownapkin and the TTN Community
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>. -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="/css/popup/startChatSesh.css">
|
||||||
|
<h3 class="popup-title">Start Chat Sesh</h3>
|
||||||
|
<div id="pm-sesh-popup-div">
|
||||||
|
<p>Enter user(s) to chat with:</p>
|
||||||
|
<input id="pm-sesh-popup-prompt" placeholder="Username(s)">
|
||||||
|
<button class="positive-button" id="pm-sesh-popup-button">Start Sesh</button>
|
||||||
|
</div>
|
||||||
|
<sup id="pm-sesh-popup-sup">Users must be online and connected to a channel (it doesn't have to be the same one.)</sup>
|
||||||
Loading…
Reference in a new issue