/**
* Copyright (C) 2024 Puter Technologies Inc.
*
* This file is part of Puter.
*
* Puter 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 .
*/
import UIWindow from './UIWindow.js'
import UIAlert from './UIAlert.js'
function UIWindowEmailConfirmationRequired(options){
return new Promise(async (resolve) => {
options = options ?? {};
let final_code = '';
let is_checking_code = false;
const submit_btn_txt = 'Confirm Email'
let h = '';
h += `
×
`;
h += ``;
h += `
`;
h += `
Confirm Your Email Address `;
h += `
`;
h += `
`;
h += `Re-send Confirmation Code `;
if(options.logout_in_footer){
h += ` • `;
h += `Log Out `;
}
h += `
`;
h += `
`;
const el_window = await UIWindow({
title: null,
icon: null,
uid: null,
is_dir: false,
body_content: h,
has_head: false,
selectable_body: false,
draggable_body: true,
allow_context_menu: false,
is_draggable: options.is_draggable ?? true,
is_droppable: false,
is_resizable: false,
stay_on_top: options.stay_on_top ?? false,
allow_native_ctxmenu: true,
allow_user_select: true,
backdrop: true,
width: 390,
dominant: true,
onAppend: function(el_window){
$(el_window).find('.digit-input').first().focus();
},
window_class: 'window-item-properties',
window_css:{
height: 'initial',
},
body_css: {
padding: '30px',
width: 'initial',
height: 'initial',
'background-color': 'rgb(247 251 255)',
'backdrop-filter': 'blur(3px)',
}
})
$(el_window).find('.digit-input').first().focus();
$(el_window).find('.email-confirm-btn').on('click submit', function(e){
e.preventDefault();
e.stopPropagation();
$(el_window).find('.email-confirm-btn').prop('disabled', true);
$(el_window).find('.error').hide();
// Check if already checking code to prevent multiple requests
if(is_checking_code)
return;
// Confirm button
is_checking_code = true;
// set animation
$(el_window).find('.email-confirm-btn').html(`circle anim `);
setTimeout(() => {
$.ajax({
url: api_origin + "/confirm-email",
type: 'POST',
data: JSON.stringify({
code: final_code,
}),
async: true,
contentType: "application/json",
headers: {
"Authorization": "Bearer "+auth_token
},
statusCode: {
401: function () {
logout();
},
},
success: function (res){
if(res.email_confirmed){
$(el_window).close();
refresh_user_data(window.auth_token)
resolve(true);
}else{
$(el_window).find('.error').html('Invalid confirmation code.');
$(el_window).find('.error').fadeIn();
$(el_window).find('.digit-input').val('');
$(el_window).find('.digit-input').first().focus();
$(el_window).find('.email-confirm-btn').prop('disabled', false);
$(el_window).find('.email-confirm-btn').html(submit_btn_txt);
}
},
error: function(res){
$(el_window).find('.error').html(res.responseJSON.error);
$(el_window).find('.error').fadeIn();
$(el_window).find('.digit-input').val('');
$(el_window).find('.digit-input').first().focus();
$(el_window).find('.email-confirm-btn').prop('disabled', false);
$(el_window).find('.email-confirm-btn').html(submit_btn_txt);
},
complete: function(){
is_checking_code = false;
}
})
}, 1000);
})
// send email confirmation
$(el_window).find('.send-conf-email').on('click', function(e){
$.ajax({
url: api_origin + "/send-confirm-email",
type: 'POST',
async: true,
contentType: "application/json",
headers: {
"Authorization": "Bearer "+auth_token
},
statusCode: {
401: function () {
logout();
},
},
success: async function (res){
await UIAlert({
message: `A new confirmation code has been sent to ${window.user.email} .`,
body_icon: window.icons['c-check.svg'],
stay_on_top: true,
backdrop: true,
})
$(el_window).find('.digit-input').first().focus();
},
complete: function(){
}
})
})
// logout
$(el_window).find('.conf-email-log-out').on('click', function(e){
logout();
$(el_window).close();
})
// Elements
const numberCodeForm = document.querySelector('[data-number-code-form]');
const numberCodeInputs = [...numberCodeForm.querySelectorAll('[data-number-code-input]')];
// Event listeners
numberCodeForm.addEventListener('input', ({ target }) => {
if(!target.value.length) { return target.value = null; }
const inputLength = target.value.length;
let currentIndex = Number(target.dataset.numberCodeInput);
if(inputLength === 2){
const inputValues = target.value.split('');
target.value = inputValues[0];
}
else if (inputLength > 1) {
const inputValues = target.value.split('');
inputValues.forEach((value, valueIndex) => {
const nextValueIndex = currentIndex + valueIndex;
if (nextValueIndex >= numberCodeInputs.length) { return; }
numberCodeInputs[nextValueIndex].value = value;
});
currentIndex += inputValues.length - 2;
}
const nextIndex = currentIndex + 1;
if (nextIndex < numberCodeInputs.length) {
numberCodeInputs[nextIndex].focus();
}
// Concatenate all inputs into one string to create the final code
final_code = '';
for(let i=0; i< numberCodeInputs.length; i++){
final_code += numberCodeInputs[i].value;
}
// Automatically submit if 6 digits entered
if(final_code.length === 6){
$(el_window).find('.email-confirm-btn').prop('disabled', false);
$(el_window).find('.email-confirm-btn').trigger('click');
}
});
numberCodeForm.addEventListener('keydown', (e) => {
const { code, target } = e;
const currentIndex = Number(target.dataset.numberCodeInput);
const previousIndex = currentIndex - 1;
const nextIndex = currentIndex + 1;
const hasPreviousIndex = previousIndex >= 0;
const hasNextIndex = nextIndex <= numberCodeInputs.length - 1
switch (code) {
case 'ArrowLeft':
case 'ArrowUp':
if (hasPreviousIndex) {
numberCodeInputs[previousIndex].focus();
}
e.preventDefault();
break;
case 'ArrowRight':
case 'ArrowDown':
if (hasNextIndex) {
numberCodeInputs[nextIndex].focus();
}
e.preventDefault();
break;
case 'Backspace':
if (!e.target.value.length && hasPreviousIndex) {
numberCodeInputs[previousIndex].value = null;
numberCodeInputs[previousIndex].focus();
}
break;
default:
break;
}
});
})
}
export default UIWindowEmailConfirmationRequired