250 lines
7.6 KiB
JavaScript
250 lines
7.6 KiB
JavaScript
/*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/>.*/
|
|
|
|
class profileUpdatePrompt{
|
|
constructor(field){
|
|
this.field = field;
|
|
this.contentNode = document.querySelector(`#profile-${field}-content`);
|
|
this.promptNode = document.querySelector(`#profile-${field}-prompt`);
|
|
|
|
if(this.promptNode != null){
|
|
this.setupInput();
|
|
}
|
|
}
|
|
|
|
setupInput(){
|
|
this.contentNode.addEventListener('click', this.popPrompt.bind(this));
|
|
this.promptNode.addEventListener('keydown', this.closePrompt.bind(this));
|
|
}
|
|
|
|
popPrompt(){
|
|
this.promptNode.style.display = 'inline';
|
|
this.promptNode.focus();
|
|
}
|
|
|
|
closePrompt(event){
|
|
//Check if we're finished
|
|
const fin = event.key == "Escape" || event.key == "Enter";
|
|
|
|
//IF we are
|
|
if(fin){
|
|
//Display the prompt
|
|
this.promptNode.style.display = 'none';
|
|
}
|
|
|
|
//Return whether or not we're done
|
|
return fin;
|
|
}
|
|
}
|
|
|
|
class profileUpdateTextPrompt extends profileUpdatePrompt{
|
|
constructor(field, fillPrompt = false){
|
|
//call derived constructor
|
|
super(field);
|
|
|
|
//Set fill prompt
|
|
this.fillPrompt = fillPrompt;
|
|
}
|
|
|
|
popPrompt(){
|
|
//Call derived method
|
|
super.popPrompt();
|
|
|
|
//If we're filling the prompt
|
|
if(this.fillPrompt){
|
|
//Fill the prompt content and placeholder
|
|
this.promptNode.value = this.contentNode.textContent;
|
|
this.promptNode.placeholder = this.field;
|
|
//otherwise
|
|
}else{
|
|
//Just fill the placeholder
|
|
this.promptNode.placeholder = this.contentNode.textContent;
|
|
}
|
|
|
|
//Hide content
|
|
this.contentNode.style.display = 'none';
|
|
}
|
|
|
|
async closePrompt(event){
|
|
//Call derived constructor and check if we're finished, assuming we're finished...
|
|
if(super.closePrompt(event)){
|
|
//Display
|
|
this.contentNode.style.display = 'inline-block';
|
|
|
|
//If we're not cancelling
|
|
if(event.key == "Enter"){
|
|
//Create empty update object
|
|
let updateObj = {};
|
|
|
|
//Fill field
|
|
updateObj[this.field] = this.promptNode.value;
|
|
|
|
//Send er' off
|
|
const update = await utils.ajax.updateProfile(updateObj);
|
|
|
|
//Fill content from update
|
|
this.contentNode.innerHTML = update[this.field];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class profileUpdateImagePrompt extends profileUpdatePrompt{
|
|
constructor(){
|
|
//call derived constructor
|
|
super('img');
|
|
}
|
|
|
|
popPrompt(){
|
|
//Call derived method
|
|
super.popPrompt();
|
|
|
|
this.promptNode.placeholder = this.contentNode.src;
|
|
}
|
|
|
|
async closePrompt(event){
|
|
//Call derived constructor
|
|
super.closePrompt(event);
|
|
|
|
//If we're not cancelling
|
|
if(event.key == "Enter"){
|
|
//Create empty update object
|
|
let updateObj = {};
|
|
|
|
//Fill field
|
|
updateObj[this.field] = this.promptNode.value;
|
|
|
|
//Send er' off
|
|
const update = await utils.ajax.updateProfile(updateObj);
|
|
|
|
//Fill content from update
|
|
this.contentNode.src = update[this.field];
|
|
}
|
|
}
|
|
}
|
|
|
|
class passwordResetPrompt{
|
|
constructor(){
|
|
this.oldPassNode = document.querySelector('#account-settings-password-reset-old');
|
|
this.newPassNode = document.querySelector('#account-settings-password-reset-new');
|
|
this.confirmPassNode = document.querySelector('#account-settings-password-reset-confirm');
|
|
|
|
this.setupInput(this.oldPassNode);
|
|
this.setupInput(this.newPassNode);
|
|
this.setupInput(this.confirmPassNode);
|
|
}
|
|
|
|
setupInput(node){
|
|
if(node != null){
|
|
node.addEventListener("keydown", this.update.bind(this));
|
|
}
|
|
}
|
|
|
|
async update(event){
|
|
var hasVal = (this.oldPassNode.value && this.newPassNode.value && this.confirmPassNode.value);
|
|
if((!event || event.key == "Enter") && hasVal){
|
|
if(this.newPassNode.value == this.confirmPassNode.value){
|
|
const updateObj = {};
|
|
|
|
updateObj.passChange = {
|
|
oldPass: this.oldPassNode.value,
|
|
newPass: this.newPassNode.value,
|
|
confirmPass: this.confirmPassNode.value
|
|
};
|
|
|
|
const response = await utils.ajax.updateProfile(updateObj);
|
|
|
|
if(response != null){
|
|
//Return user homepage after good pass change, as we've probably been logged out by the server for security.
|
|
window.location.pathname = '/';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class tokeList{
|
|
constructor(){
|
|
this.tokeList = document.querySelector('#profile-tokes');
|
|
this.tokeListLabel = document.querySelector('.profile-toke-count');
|
|
this.tokeListToggleIcon = document.querySelector('#toggle-toke-list');
|
|
|
|
this.setupInput();
|
|
}
|
|
|
|
setupInput(){
|
|
this.tokeListLabel.addEventListener('click', this.toggleTokeList.bind(this));
|
|
}
|
|
|
|
toggleTokeList(){
|
|
if(this.tokeList.style.visibility == "visible"){
|
|
this.tokeList.style.visibility = "collapse";
|
|
this.tokeListToggleIcon.classList.replace("bi-caret-down-fill","bi-caret-left-fill");
|
|
}else{
|
|
this.tokeList.style.visibility = "visible";
|
|
this.tokeListToggleIcon.classList.replace("bi-caret-left-fill","bi-caret-down-fill");
|
|
}
|
|
}
|
|
}
|
|
|
|
class deleteAccountButton{
|
|
constructor(){
|
|
this.deleteLink = document.querySelector('#account-settings-delete-button');
|
|
|
|
if(this.deleteLink != null){
|
|
this.setupInput();
|
|
}
|
|
}
|
|
|
|
setupInput(){
|
|
this.deleteLink.addEventListener("click",this.deletePrompt.bind(this));
|
|
}
|
|
|
|
async deletePrompt(event){
|
|
this.popup = new deleteAccountPopup();
|
|
}
|
|
}
|
|
|
|
class deleteAccountPopup{
|
|
constructor(){
|
|
this.popup = new canopyUXUtils.popup("nukeUser", true, this.asyncConstructor.bind(this));
|
|
}
|
|
|
|
asyncConstructor(){
|
|
this.passwordPrompt = document.querySelector("#delete-account-popup-password");
|
|
|
|
this.setupInput();
|
|
}
|
|
|
|
setupInput(){
|
|
this.passwordPrompt.addEventListener("keydown", this.nukeAccount.bind(this));
|
|
}
|
|
|
|
async nukeAccount(event){
|
|
if(event.key == "Enter"){
|
|
await utils.ajax.deleteAccount(event.target.value);
|
|
}
|
|
}
|
|
}
|
|
|
|
//Object Instantiation
|
|
const imgPrompt = new profileUpdateImagePrompt();
|
|
const pronounsPrompt = new profileUpdateTextPrompt('pronouns');
|
|
const signaturePrompt = new profileUpdateTextPrompt('signature');
|
|
const bioPrompt = new profileUpdateTextPrompt('bio', true);
|
|
const profileTokeList = new tokeList();
|
|
const accountPassResetPrompt = new passwordResetPrompt();
|
|
const accountDeleteButton = new deleteAccountButton(); |