231 lines
8.3 KiB
TypeScript
Executable File
231 lines
8.3 KiB
TypeScript
Executable File
import modalHtml from '../components/login-modal/login-modal.html?raw';
|
|
import modalScript from '../components/login-modal/login-modal.js?raw';
|
|
import validationModalStyle from '../components/validation-modal/validation-modal.css?raw';
|
|
import Services from './service';
|
|
import { init, navigate } from '../router';
|
|
import { addressToEmoji } from '../utils/sp-address.utils';
|
|
import { RoleDefinition } from 'pkg/sdk_client';
|
|
import { initValidationModal } from '~/components/validation-modal/validation-modal';
|
|
import { interpolate } from '~/utils/html.utils';
|
|
|
|
interface ConfirmationModalOptions {
|
|
title: string;
|
|
content: string;
|
|
confirmText?: string;
|
|
cancelText?: string;
|
|
}
|
|
|
|
export default class ModalService {
|
|
private static instance: ModalService;
|
|
private stateId: string | null = null;
|
|
private processId: string | null = null;
|
|
private constructor() {}
|
|
private paired_addresses: string[] = [];
|
|
private modal: HTMLElement | null = null;
|
|
|
|
// Method to access the singleton instance of Services
|
|
public static async getInstance(): Promise<ModalService> {
|
|
if (!ModalService.instance) {
|
|
ModalService.instance = new ModalService();
|
|
}
|
|
return ModalService.instance;
|
|
}
|
|
|
|
public openLoginModal(myAddress: string, receiverAddress: string) {
|
|
const container = document.querySelector('.page-container');
|
|
let html = modalHtml;
|
|
html = html.replace('{{device1}}', myAddress);
|
|
html = html.replace('{{device2}}', receiverAddress);
|
|
if (container) container.innerHTML += html;
|
|
const modal = document.getElementById('login-modal');
|
|
if (modal) modal.style.display = 'flex';
|
|
const newScript = document.createElement('script');
|
|
|
|
newScript.setAttribute('type', 'module');
|
|
newScript.textContent = modalScript;
|
|
document.head.appendChild(newScript).parentNode?.removeChild(newScript);
|
|
}
|
|
|
|
async injectModal(members: any[]) {
|
|
const container = document.querySelector('#containerId');
|
|
if (container) {
|
|
let html = await fetch('/src/components/modal/confirmation-modal.html').then((res) => res.text());
|
|
html = html.replace('{{device1}}', await addressToEmoji(members[0]['sp_addresses'][0]));
|
|
html = html.replace('{{device2}}', await addressToEmoji(members[0]['sp_addresses'][1]));
|
|
container.innerHTML += html;
|
|
|
|
// Dynamically load the header JS
|
|
const script = document.createElement('script');
|
|
script.src = '/src/components/modal/confirmation-modal.ts';
|
|
script.type = 'module';
|
|
document.head.appendChild(script);
|
|
}
|
|
}
|
|
|
|
async injectCreationModal(members: any[]) {
|
|
const container = document.querySelector('#containerId');
|
|
if (container) {
|
|
let html = await fetch('/src/components/modal/creation-modal.html').then((res) => res.text());
|
|
html = html.replace('{{device1}}', await addressToEmoji(members[0]['sp_addresses'][0]));
|
|
container.innerHTML += html;
|
|
|
|
// Dynamically load the header JS
|
|
const script = document.createElement('script');
|
|
script.src = '/src/components/modal/confirmation-modal.ts';
|
|
script.type = 'module';
|
|
document.head.appendChild(script);
|
|
}
|
|
}
|
|
|
|
// Device 1 wait Device 2
|
|
async injectWaitingModal() {
|
|
const container = document.querySelector('#containerId');
|
|
if (container) {
|
|
let html = await fetch('/src/components/modal/waiting-modal.html').then((res) => res.text());
|
|
container.innerHTML += html;
|
|
}
|
|
}
|
|
|
|
async injectValidationModal(processDiff: any) {
|
|
const container = document.querySelector('#containerId');
|
|
if (container) {
|
|
let html = await fetch('/src/components/validation-modal/validation-modal.html').then((res) => res.text());
|
|
html = interpolate(html, {processId: processDiff.processId})
|
|
container.innerHTML += html;
|
|
|
|
// Dynamically load the header JS
|
|
const script = document.createElement('script');
|
|
script.id = 'validation-modal-script';
|
|
script.src = '/src/components/validation-modal/validation-modal.ts';
|
|
script.type = 'module';
|
|
document.head.appendChild(script);
|
|
const css = document.createElement('style');
|
|
css.id = 'validation-modal-css';
|
|
css.innerText = validationModalStyle;
|
|
document.head.appendChild(css);
|
|
initValidationModal(processDiff)
|
|
}
|
|
}
|
|
|
|
async closeValidationModal() {
|
|
const script = document.querySelector('#validation-modal-script');
|
|
const css = document.querySelector('#validation-modal-css');
|
|
const component = document.querySelector('#validation-modal');
|
|
script?.remove();
|
|
css?.remove();
|
|
component?.remove();
|
|
}
|
|
|
|
public async openPairingConfirmationModal(roleDefinition: Record<string, RoleDefinition>, processId: string, stateId: string) {
|
|
let members;
|
|
if (roleDefinition['pairing']) {
|
|
const owner = roleDefinition['pairing'];
|
|
members = owner.members;
|
|
} else {
|
|
throw new Error('No "pairing" role');
|
|
}
|
|
|
|
if (members.length != 1) {
|
|
throw new Error('Must have exactly 1 member');
|
|
}
|
|
|
|
console.log("MEMBERS:", members);
|
|
// We take all the addresses except our own
|
|
const service = await Services.getInstance();
|
|
const localAddress = service.getDeviceAddress();
|
|
for (const member of members) {
|
|
if (member.sp_addresses) {
|
|
for (const address of member.sp_addresses) {
|
|
if (address !== localAddress) {
|
|
this.paired_addresses.push(address);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this.processId = processId;
|
|
this.stateId = stateId;
|
|
|
|
if (members[0].sp_addresses.length === 1) {
|
|
await this.injectCreationModal(members);
|
|
this.modal = document.getElementById('creation-modal');
|
|
console.log("LENGTH:", members[0].sp_addresses.length);
|
|
} else {
|
|
await this.injectModal(members);
|
|
this.modal = document.getElementById('modal');
|
|
console.log("LENGTH:", members[0].sp_addresses.length);
|
|
}
|
|
|
|
if (this.modal) this.modal.style.display = 'flex';
|
|
|
|
// Close modal when clicking outside of it
|
|
window.onclick = (event) => {
|
|
if (event.target === this.modal) {
|
|
this.closeConfirmationModal();
|
|
}
|
|
};
|
|
}
|
|
confirmLogin() {
|
|
console.log('=============> Confirm Login');
|
|
}
|
|
async closeLoginModal() {
|
|
if (this.modal) this.modal.style.display = 'none';
|
|
}
|
|
|
|
async showConfirmationModal(options: ConfirmationModalOptions, fullscreen: boolean = false): Promise<boolean> {
|
|
// Create modal element
|
|
const modalElement = document.createElement('div');
|
|
modalElement.id = 'confirmation-modal';
|
|
modalElement.innerHTML = `
|
|
<div class="modal-overlay">
|
|
<div class="modal-content" ${fullscreen ? 'style="width: 100% !important; max-width: none !important; height: 100% !important; max-height: none !important; border-radius: 0 !important; margin: 0 !important;"' : ''}>
|
|
<h2>${options.title}</h2>
|
|
<div class="modal-body">
|
|
${options.content}
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button id="cancel-button" class="btn btn-secondary">${options.cancelText || 'Annuler'}</button>
|
|
<button id="confirm-button" class="btn btn-primary">${options.confirmText || 'Confirmer'}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
// Add modal to document
|
|
document.body.appendChild(modalElement);
|
|
|
|
// Return promise that resolves with user choice
|
|
return new Promise((resolve) => {
|
|
const confirmButton = modalElement.querySelector('#confirm-button');
|
|
const cancelButton = modalElement.querySelector('#cancel-button');
|
|
const modalOverlay = modalElement.querySelector('.modal-overlay');
|
|
|
|
const cleanup = () => {
|
|
modalElement.remove();
|
|
};
|
|
|
|
confirmButton?.addEventListener('click', () => {
|
|
cleanup();
|
|
resolve(true);
|
|
});
|
|
|
|
cancelButton?.addEventListener('click', () => {
|
|
cleanup();
|
|
resolve(false);
|
|
});
|
|
|
|
modalOverlay?.addEventListener('click', (e) => {
|
|
if (e.target === modalOverlay) {
|
|
cleanup();
|
|
resolve(false);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
async closeConfirmationModal() {
|
|
const service = await Services.getInstance();
|
|
await service.unpairDevice();
|
|
if (this.modal) this.modal.style.display = 'none';
|
|
}
|
|
}
|