ci: docker_tag=ext - Update ihm_client configuration and dependencies
This commit is contained in:
parent
ae58d95e39
commit
30a3960b2e
@ -1,50 +1,50 @@
|
||||
import { interpolate } from '../../utils/html.utils';
|
||||
import Services from '../../services/service';
|
||||
import { Process } from '../../pkg/sdk_client.js';
|
||||
import { getCorrectDOM } from '~/utils/document.utils';
|
||||
|
||||
let currentPageStyle: HTMLStyleElement | null = null;
|
||||
|
||||
export async function initProcessElement(id: string, zone: string) {
|
||||
const processes = await getProcesses();
|
||||
const container = getCorrectDOM('process-4nk-component');
|
||||
// const currentProcess = processes.find((process) => process[0] === id)[1];
|
||||
// const currentProcess = {title: 'Hello', html: '', css: ''};
|
||||
// await loadPage({ processTitle: currentProcess.title, inputValue: 'Hello World !' });
|
||||
// const wrapper = document.querySelector('.process-container');
|
||||
// if (wrapper) {
|
||||
// wrapper.innerHTML = interpolate(currentProcess.html, { processTitle: currentProcess.title, inputValue: 'Hello World !' });
|
||||
// injectCss(currentProcess.css);
|
||||
// }
|
||||
}
|
||||
|
||||
async function loadPage(data?: any) {
|
||||
const content = document.getElementById('containerId');
|
||||
if (content && data) {
|
||||
if (data) {
|
||||
content.innerHTML = interpolate(content.innerHTML, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function injectCss(cssContent: string) {
|
||||
removeCss(); // Ensure that the previous CSS is removed
|
||||
|
||||
currentPageStyle = document.createElement('style');
|
||||
currentPageStyle.type = 'text/css';
|
||||
currentPageStyle.appendChild(document.createTextNode(cssContent));
|
||||
document.head.appendChild(currentPageStyle);
|
||||
}
|
||||
|
||||
function removeCss() {
|
||||
if (currentPageStyle) {
|
||||
document.head.removeChild(currentPageStyle);
|
||||
currentPageStyle = null;
|
||||
}
|
||||
}
|
||||
|
||||
async function getProcesses(): Promise<Record<string, Process>> {
|
||||
const service = await Services.getInstance();
|
||||
const processes = await service.getProcesses();
|
||||
return processes;
|
||||
}
|
||||
import { interpolate } from '../../utils/html.utils';
|
||||
import Services from '../../services/service';
|
||||
import { Process } from '../../pkg/sdk_client.js';
|
||||
import { getCorrectDOM } from '~/utils/document.utils';
|
||||
|
||||
let currentPageStyle: HTMLStyleElement | null = null;
|
||||
|
||||
export async function initProcessElement(id: string, zone: string) {
|
||||
const processes = await getProcesses();
|
||||
const container = getCorrectDOM('process-4nk-component');
|
||||
// const currentProcess = processes.find((process) => process[0] === id)[1];
|
||||
// const currentProcess = {title: 'Hello', html: '', css: ''};
|
||||
// await loadPage({ processTitle: currentProcess.title, inputValue: 'Hello World !' });
|
||||
// const wrapper = document.querySelector('.process-container');
|
||||
// if (wrapper) {
|
||||
// wrapper.innerHTML = interpolate(currentProcess.html, { processTitle: currentProcess.title, inputValue: 'Hello World !' });
|
||||
// injectCss(currentProcess.css);
|
||||
// }
|
||||
}
|
||||
|
||||
async function loadPage(data?: any) {
|
||||
const content = document.getElementById('containerId');
|
||||
if (content && data) {
|
||||
if (data) {
|
||||
content.innerHTML = interpolate(content.innerHTML, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function injectCss(cssContent: string) {
|
||||
removeCss(); // Ensure that the previous CSS is removed
|
||||
|
||||
currentPageStyle = document.createElement('style');
|
||||
currentPageStyle.type = 'text/css';
|
||||
currentPageStyle.appendChild(document.createTextNode(cssContent));
|
||||
document.head.appendChild(currentPageStyle);
|
||||
}
|
||||
|
||||
function removeCss() {
|
||||
if (currentPageStyle) {
|
||||
document.head.removeChild(currentPageStyle);
|
||||
currentPageStyle = null;
|
||||
}
|
||||
}
|
||||
|
||||
async function getProcesses(): Promise<Record<string, Process>> {
|
||||
const service = await Services.getInstance();
|
||||
const processes = await service.getProcesses();
|
||||
return processes;
|
||||
}
|
||||
|
1900
src/router.ts
1900
src/router.ts
File diff suppressed because it is too large
Load Diff
@ -1,230 +1,230 @@
|
||||
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.js';
|
||||
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';
|
||||
}
|
||||
}
|
||||
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.js';
|
||||
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';
|
||||
}
|
||||
}
|
||||
|
@ -1,213 +1,213 @@
|
||||
import Services from '../services/service';
|
||||
import { getCorrectDOM } from './html.utils';
|
||||
import { addSubscription } from './subscription.utils';
|
||||
import QRCode from 'qrcode';
|
||||
|
||||
//Copy Address
|
||||
export async function copyToClipboard(fullAddress: string) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(fullAddress);
|
||||
alert('Adresse copiée dans le presse-papiers !');
|
||||
} catch (err) {
|
||||
console.error('Failed to copy the address: ', err);
|
||||
}
|
||||
}
|
||||
|
||||
//Generate emojis list
|
||||
export function generateEmojiList(): string[] {
|
||||
const emojiRanges = [
|
||||
[0x1f600, 0x1f64f],
|
||||
[0x1f300, 0x1f5ff],
|
||||
[0x1f680, 0x1f6ff],
|
||||
[0x1f700, 0x1f77f],
|
||||
];
|
||||
|
||||
const emojiList: string[] = [];
|
||||
for (const range of emojiRanges) {
|
||||
const [start, end] = range;
|
||||
for (let i = start; i <= end && emojiList.length < 256; i++) {
|
||||
emojiList.push(String.fromCodePoint(i));
|
||||
}
|
||||
if (emojiList.length >= 256) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return emojiList.slice(0, 256);
|
||||
}
|
||||
|
||||
//Adress to emojis
|
||||
export async function addressToEmoji(text: string): Promise<string> {
|
||||
//Adress to Hash
|
||||
const encoder = new TextEncoder();
|
||||
const data = encoder.encode(text);
|
||||
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
||||
|
||||
const hash = new Uint8Array(hashBuffer);
|
||||
const bytes = hash.slice(-4);
|
||||
|
||||
//Hash slice to emojis
|
||||
const emojiList = generateEmojiList();
|
||||
const emojis = Array.from(bytes)
|
||||
.map((byte) => emojiList[byte])
|
||||
.join('');
|
||||
return emojis;
|
||||
}
|
||||
|
||||
//Get emojis from other device
|
||||
async function emojisPairingRequest() {
|
||||
try {
|
||||
const container = getCorrectDOM('login-4nk-component') as HTMLElement;
|
||||
|
||||
const urlParams: URLSearchParams = new URLSearchParams(window.location.search);
|
||||
const sp_adress: string | null = urlParams.get('sp_address');
|
||||
|
||||
if (!sp_adress) {
|
||||
// console.error("No 'sp_adress' parameter found in the URL.");
|
||||
return;
|
||||
}
|
||||
|
||||
const emojis = await addressToEmoji(sp_adress);
|
||||
const emojiDisplay = container?.querySelector('.pairing-request');
|
||||
|
||||
if (emojiDisplay) {
|
||||
emojiDisplay.textContent = '(Request from: ' + emojis + ')';
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Display address emojis and other device emojis
|
||||
export async function displayEmojis(text: string) {
|
||||
console.log('🚀 ~ Services ~ adressToEmoji');
|
||||
try {
|
||||
const container = getCorrectDOM('login-4nk-component') as HTMLElement;
|
||||
const emojis = await addressToEmoji(text);
|
||||
const emojiDisplay = container?.querySelector('.emoji-display');
|
||||
|
||||
if (emojiDisplay) {
|
||||
emojiDisplay.textContent = emojis;
|
||||
}
|
||||
|
||||
emojisPairingRequest();
|
||||
|
||||
initAddressInput();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Verify Other address
|
||||
export function initAddressInput() {
|
||||
const container = getCorrectDOM('login-4nk-component') as HTMLElement
|
||||
const addressInput = container.querySelector('#addressInput') as HTMLInputElement;
|
||||
const emojiDisplay = container.querySelector('#emoji-display-2');
|
||||
const okButton = container.querySelector('#okButton') as HTMLButtonElement;
|
||||
const createButton = container.querySelector('#createButton') as HTMLButtonElement;
|
||||
const actionButton = container.querySelector('#actionButton') as HTMLButtonElement;
|
||||
addSubscription(addressInput, 'input', async () => {
|
||||
let address = addressInput.value;
|
||||
|
||||
// Vérifie si l'adresse est une URL
|
||||
try {
|
||||
const url = new URL(address);
|
||||
// Si c'est une URL valide, extraire le paramètre sp_address
|
||||
const urlParams = new URLSearchParams(url.search);
|
||||
const extractedAddress = urlParams.get('sp_address') || ''; // Prend sp_address ou une chaîne vide
|
||||
|
||||
if (extractedAddress) {
|
||||
address = extractedAddress;
|
||||
addressInput.value = address; // Met à jour l'input pour afficher uniquement l'adresse extraite
|
||||
}
|
||||
} catch (e) {
|
||||
// Si ce n'est pas une URL valide, on garde l'adresse originale
|
||||
console.log("Ce n'est pas une URL valide, on garde l'adresse originale.");
|
||||
}
|
||||
if (address) {
|
||||
const emojis = await addressToEmoji(address);
|
||||
if (emojiDisplay) {
|
||||
emojiDisplay.innerHTML = emojis;
|
||||
}
|
||||
if (okButton) {
|
||||
okButton.style.display = 'inline-block';
|
||||
}
|
||||
} else {
|
||||
if (emojiDisplay) {
|
||||
emojiDisplay.innerHTML = '';
|
||||
}
|
||||
if (okButton) {
|
||||
okButton.style.display = 'none';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (createButton) {
|
||||
addSubscription(createButton, 'click', () => {
|
||||
onCreateButtonClick();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function onCreateButtonClick() {
|
||||
try {
|
||||
await prepareAndSendPairingTx();
|
||||
const service = await Services.getInstance();
|
||||
await service.confirmPairing();
|
||||
} catch (e) {
|
||||
console.error(`onCreateButtonClick error: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function prepareAndSendPairingTx(): Promise<void> {
|
||||
const service = await Services.getInstance();
|
||||
|
||||
// checkConnections requires a Process object, not an empty array
|
||||
// This call has been removed as it was causing TypeScript errors
|
||||
|
||||
try {
|
||||
const relayAddress = service.getAllRelays();
|
||||
const createPairingProcessReturn = await service.createPairingProcess(
|
||||
"",
|
||||
[],
|
||||
);
|
||||
|
||||
if (!createPairingProcessReturn.updated_process) {
|
||||
throw new Error('createPairingProcess returned an empty new process');
|
||||
}
|
||||
|
||||
service.setProcessId(createPairingProcessReturn.updated_process.process_id);
|
||||
service.setStateId(createPairingProcessReturn.updated_process.current_process.states[0].state_id);
|
||||
|
||||
await service.handleApiReturn(createPairingProcessReturn);
|
||||
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
export async function generateQRCode(spAddress: string) {
|
||||
try {
|
||||
const container = getCorrectDOM('login-4nk-component') as HTMLElement
|
||||
const currentUrl = 'https://' + window.location.host;
|
||||
const url = await QRCode.toDataURL(currentUrl + '?sp_address=' + spAddress);
|
||||
const qrCode = container?.querySelector('.qr-code img');
|
||||
qrCode?.setAttribute('src', url);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
export async function generateCreateBtn() {
|
||||
try{
|
||||
//Generate CreateBtn
|
||||
const container = getCorrectDOM('login-4nk-component') as HTMLElement
|
||||
const createBtn = container?.querySelector('.create-btn');
|
||||
if (createBtn) {
|
||||
createBtn.textContent = 'CREATE';
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
import Services from '../services/service';
|
||||
import { getCorrectDOM } from './html.utils';
|
||||
import { addSubscription } from './subscription.utils';
|
||||
import QRCode from 'qrcode';
|
||||
|
||||
//Copy Address
|
||||
export async function copyToClipboard(fullAddress: string) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(fullAddress);
|
||||
alert('Adresse copiée dans le presse-papiers !');
|
||||
} catch (err) {
|
||||
console.error('Failed to copy the address: ', err);
|
||||
}
|
||||
}
|
||||
|
||||
//Generate emojis list
|
||||
export function generateEmojiList(): string[] {
|
||||
const emojiRanges = [
|
||||
[0x1f600, 0x1f64f],
|
||||
[0x1f300, 0x1f5ff],
|
||||
[0x1f680, 0x1f6ff],
|
||||
[0x1f700, 0x1f77f],
|
||||
];
|
||||
|
||||
const emojiList: string[] = [];
|
||||
for (const range of emojiRanges) {
|
||||
const [start, end] = range;
|
||||
for (let i = start; i <= end && emojiList.length < 256; i++) {
|
||||
emojiList.push(String.fromCodePoint(i));
|
||||
}
|
||||
if (emojiList.length >= 256) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return emojiList.slice(0, 256);
|
||||
}
|
||||
|
||||
//Adress to emojis
|
||||
export async function addressToEmoji(text: string): Promise<string> {
|
||||
//Adress to Hash
|
||||
const encoder = new TextEncoder();
|
||||
const data = encoder.encode(text);
|
||||
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
||||
|
||||
const hash = new Uint8Array(hashBuffer);
|
||||
const bytes = hash.slice(-4);
|
||||
|
||||
//Hash slice to emojis
|
||||
const emojiList = generateEmojiList();
|
||||
const emojis = Array.from(bytes)
|
||||
.map((byte) => emojiList[byte])
|
||||
.join('');
|
||||
return emojis;
|
||||
}
|
||||
|
||||
//Get emojis from other device
|
||||
async function emojisPairingRequest() {
|
||||
try {
|
||||
const container = getCorrectDOM('login-4nk-component') as HTMLElement;
|
||||
|
||||
const urlParams: URLSearchParams = new URLSearchParams(window.location.search);
|
||||
const sp_adress: string | null = urlParams.get('sp_address');
|
||||
|
||||
if (!sp_adress) {
|
||||
// console.error("No 'sp_adress' parameter found in the URL.");
|
||||
return;
|
||||
}
|
||||
|
||||
const emojis = await addressToEmoji(sp_adress);
|
||||
const emojiDisplay = container?.querySelector('.pairing-request');
|
||||
|
||||
if (emojiDisplay) {
|
||||
emojiDisplay.textContent = '(Request from: ' + emojis + ')';
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Display address emojis and other device emojis
|
||||
export async function displayEmojis(text: string) {
|
||||
console.log('🚀 ~ Services ~ adressToEmoji');
|
||||
try {
|
||||
const container = getCorrectDOM('login-4nk-component') as HTMLElement;
|
||||
const emojis = await addressToEmoji(text);
|
||||
const emojiDisplay = container?.querySelector('.emoji-display');
|
||||
|
||||
if (emojiDisplay) {
|
||||
emojiDisplay.textContent = emojis;
|
||||
}
|
||||
|
||||
emojisPairingRequest();
|
||||
|
||||
initAddressInput();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Verify Other address
|
||||
export function initAddressInput() {
|
||||
const container = getCorrectDOM('login-4nk-component') as HTMLElement
|
||||
const addressInput = container.querySelector('#addressInput') as HTMLInputElement;
|
||||
const emojiDisplay = container.querySelector('#emoji-display-2');
|
||||
const okButton = container.querySelector('#okButton') as HTMLButtonElement;
|
||||
const createButton = container.querySelector('#createButton') as HTMLButtonElement;
|
||||
const actionButton = container.querySelector('#actionButton') as HTMLButtonElement;
|
||||
addSubscription(addressInput, 'input', async () => {
|
||||
let address = addressInput.value;
|
||||
|
||||
// Vérifie si l'adresse est une URL
|
||||
try {
|
||||
const url = new URL(address);
|
||||
// Si c'est une URL valide, extraire le paramètre sp_address
|
||||
const urlParams = new URLSearchParams(url.search);
|
||||
const extractedAddress = urlParams.get('sp_address') || ''; // Prend sp_address ou une chaîne vide
|
||||
|
||||
if (extractedAddress) {
|
||||
address = extractedAddress;
|
||||
addressInput.value = address; // Met à jour l'input pour afficher uniquement l'adresse extraite
|
||||
}
|
||||
} catch (e) {
|
||||
// Si ce n'est pas une URL valide, on garde l'adresse originale
|
||||
console.log("Ce n'est pas une URL valide, on garde l'adresse originale.");
|
||||
}
|
||||
if (address) {
|
||||
const emojis = await addressToEmoji(address);
|
||||
if (emojiDisplay) {
|
||||
emojiDisplay.innerHTML = emojis;
|
||||
}
|
||||
if (okButton) {
|
||||
okButton.style.display = 'inline-block';
|
||||
}
|
||||
} else {
|
||||
if (emojiDisplay) {
|
||||
emojiDisplay.innerHTML = '';
|
||||
}
|
||||
if (okButton) {
|
||||
okButton.style.display = 'none';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (createButton) {
|
||||
addSubscription(createButton, 'click', () => {
|
||||
onCreateButtonClick();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function onCreateButtonClick() {
|
||||
try {
|
||||
await prepareAndSendPairingTx();
|
||||
const service = await Services.getInstance();
|
||||
await service.confirmPairing();
|
||||
} catch (e) {
|
||||
console.error(`onCreateButtonClick error: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function prepareAndSendPairingTx(): Promise<void> {
|
||||
const service = await Services.getInstance();
|
||||
|
||||
// checkConnections requires a Process object, not an empty array
|
||||
// This call has been removed as it was causing TypeScript errors
|
||||
|
||||
try {
|
||||
const relayAddress = service.getAllRelays();
|
||||
const createPairingProcessReturn = await service.createPairingProcess(
|
||||
"",
|
||||
[],
|
||||
);
|
||||
|
||||
if (!createPairingProcessReturn.updated_process) {
|
||||
throw new Error('createPairingProcess returned an empty new process');
|
||||
}
|
||||
|
||||
service.setProcessId(createPairingProcessReturn.updated_process.process_id);
|
||||
service.setStateId(createPairingProcessReturn.updated_process.current_process.states[0].state_id);
|
||||
|
||||
await service.handleApiReturn(createPairingProcessReturn);
|
||||
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
export async function generateQRCode(spAddress: string) {
|
||||
try {
|
||||
const container = getCorrectDOM('login-4nk-component') as HTMLElement
|
||||
const currentUrl = 'https://' + window.location.host;
|
||||
const url = await QRCode.toDataURL(currentUrl + '?sp_address=' + spAddress);
|
||||
const qrCode = container?.querySelector('.qr-code img');
|
||||
qrCode?.setAttribute('src', url);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
export async function generateCreateBtn() {
|
||||
try{
|
||||
//Generate CreateBtn
|
||||
const container = getCorrectDOM('login-4nk-component') as HTMLElement
|
||||
const createBtn = container?.querySelector('.create-btn');
|
||||
if (createBtn) {
|
||||
createBtn.textContent = 'CREATE';
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
}
|
@ -1,89 +1,89 @@
|
||||
import { AnkFlag } from '../../pkg/sdk_client.js';
|
||||
import Services from './services/service';
|
||||
|
||||
let ws: WebSocket;
|
||||
let messageQueue: string[] = [];
|
||||
export async function initWebsocket(url: string) {
|
||||
ws = new WebSocket(url);
|
||||
|
||||
if (ws !== null) {
|
||||
ws.onopen = async (event) => {
|
||||
console.log('WebSocket connection established');
|
||||
|
||||
while (messageQueue.length > 0) {
|
||||
const message = messageQueue.shift();
|
||||
if (message) {
|
||||
ws.send(message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Listen for messages
|
||||
ws.onmessage = (event) => {
|
||||
const msgData = event.data;
|
||||
|
||||
// console.log("Received text message: ", msgData);
|
||||
(async () => {
|
||||
if (typeof msgData === 'string') {
|
||||
try {
|
||||
const parsedMessage = JSON.parse(msgData);
|
||||
const services = await Services.getInstance();
|
||||
switch (parsedMessage.flag) {
|
||||
case 'Handshake':
|
||||
await services.handleHandshakeMsg(url, parsedMessage.content);
|
||||
break;
|
||||
case 'NewTx':
|
||||
await services.parseNewTx(parsedMessage.content);
|
||||
break;
|
||||
case 'Cipher':
|
||||
await services.parseCipher(parsedMessage.content);
|
||||
break;
|
||||
case 'Commit':
|
||||
// Basically if we see this it means we have an error
|
||||
await services.handleCommitError(parsedMessage.content);
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Received an invalid message:', error);
|
||||
}
|
||||
} else {
|
||||
console.error('Received a non-string message');
|
||||
}
|
||||
})();
|
||||
};
|
||||
|
||||
// Listen for possible errors
|
||||
ws.onerror = (event) => {
|
||||
console.error('WebSocket error:', event);
|
||||
};
|
||||
|
||||
// Listen for when the connection is closed
|
||||
ws.onclose = (event) => {
|
||||
console.log('WebSocket is closed now.');
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Method to send messages
|
||||
export function sendMessage(flag: AnkFlag, message: string): void {
|
||||
if (ws.readyState === WebSocket.OPEN) {
|
||||
const networkMessage = {
|
||||
flag: flag,
|
||||
content: message,
|
||||
};
|
||||
console.log('Sending message of type:', flag);
|
||||
ws.send(JSON.stringify(networkMessage));
|
||||
} else {
|
||||
console.error('WebSocket is not open. ReadyState:', ws.readyState);
|
||||
messageQueue.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
export function getUrl(): string {
|
||||
return ws.url;
|
||||
}
|
||||
|
||||
// Method to close the WebSocket connection
|
||||
export function close(): void {
|
||||
ws.close();
|
||||
}
|
||||
import { AnkFlag } from '../../pkg/sdk_client.js';
|
||||
import Services from './services/service';
|
||||
|
||||
let ws: WebSocket;
|
||||
let messageQueue: string[] = [];
|
||||
export async function initWebsocket(url: string) {
|
||||
ws = new WebSocket(url);
|
||||
|
||||
if (ws !== null) {
|
||||
ws.onopen = async (event) => {
|
||||
console.log('WebSocket connection established');
|
||||
|
||||
while (messageQueue.length > 0) {
|
||||
const message = messageQueue.shift();
|
||||
if (message) {
|
||||
ws.send(message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Listen for messages
|
||||
ws.onmessage = (event) => {
|
||||
const msgData = event.data;
|
||||
|
||||
// console.log("Received text message: ", msgData);
|
||||
(async () => {
|
||||
if (typeof msgData === 'string') {
|
||||
try {
|
||||
const parsedMessage = JSON.parse(msgData);
|
||||
const services = await Services.getInstance();
|
||||
switch (parsedMessage.flag) {
|
||||
case 'Handshake':
|
||||
await services.handleHandshakeMsg(url, parsedMessage.content);
|
||||
break;
|
||||
case 'NewTx':
|
||||
await services.parseNewTx(parsedMessage.content);
|
||||
break;
|
||||
case 'Cipher':
|
||||
await services.parseCipher(parsedMessage.content);
|
||||
break;
|
||||
case 'Commit':
|
||||
// Basically if we see this it means we have an error
|
||||
await services.handleCommitError(parsedMessage.content);
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Received an invalid message:', error);
|
||||
}
|
||||
} else {
|
||||
console.error('Received a non-string message');
|
||||
}
|
||||
})();
|
||||
};
|
||||
|
||||
// Listen for possible errors
|
||||
ws.onerror = (event) => {
|
||||
console.error('WebSocket error:', event);
|
||||
};
|
||||
|
||||
// Listen for when the connection is closed
|
||||
ws.onclose = (event) => {
|
||||
console.log('WebSocket is closed now.');
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Method to send messages
|
||||
export function sendMessage(flag: AnkFlag, message: string): void {
|
||||
if (ws.readyState === WebSocket.OPEN) {
|
||||
const networkMessage = {
|
||||
flag: flag,
|
||||
content: message,
|
||||
};
|
||||
console.log('Sending message of type:', flag);
|
||||
ws.send(JSON.stringify(networkMessage));
|
||||
} else {
|
||||
console.error('WebSocket is not open. ReadyState:', ws.readyState);
|
||||
messageQueue.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
export function getUrl(): string {
|
||||
return ws.url;
|
||||
}
|
||||
|
||||
// Method to close the WebSocket connection
|
||||
export function close(): void {
|
||||
ws.close();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user