refactor by separating sp address view from service
This commit is contained in:
parent
46622e2a7a
commit
4a59424d05
@ -193,7 +193,7 @@ body {
|
||||
align-items: center;
|
||||
}
|
||||
.process-container {
|
||||
grid-column: 3 / 5;
|
||||
grid-column: 3 / 6;
|
||||
grid-row: 3 ;
|
||||
|
||||
.card {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { currentRoute } from '../../router';
|
||||
import { INotification } from '~/models/notification.model';
|
||||
import { currentRoute, navigate } from '../../router';
|
||||
import Services from '../../services/service';
|
||||
|
||||
let notifications = [];
|
||||
@ -6,6 +7,7 @@ let notifications = [];
|
||||
export async function unpair() {
|
||||
const service = await Services.getInstance();
|
||||
await service.unpairDevice();
|
||||
navigate('home')
|
||||
}
|
||||
|
||||
(window as any).unpair = unpair;
|
||||
@ -25,8 +27,7 @@ function toggleMenu() {
|
||||
async function getNotifications() {
|
||||
const service = await Services.getInstance();
|
||||
notifications = service.getNotifications();
|
||||
const badge = document.querySelector('.notification-badge') as HTMLDivElement;
|
||||
if (badge) badge.innerHTML = notifications.length.toString();
|
||||
return notifications
|
||||
}
|
||||
function openCloseNotifications() {
|
||||
const notifications = document.querySelector('.notification-board') as HTMLDivElement;
|
||||
@ -39,7 +40,7 @@ export async function initHeader() {
|
||||
if (currentRoute === 'home') {
|
||||
hideSomeFunctionnalities();
|
||||
} else {
|
||||
getNotifications();
|
||||
launchNotificationWorker()
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,3 +56,43 @@ function hideSomeFunctionnalities() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function setNotification(notifications: INotification[]): Promise<void> {
|
||||
const badge = document.querySelector('.notification-badge') as HTMLDivElement;
|
||||
const noNotifications = document.querySelector('.no-notification') as HTMLDivElement;
|
||||
if (notifications?.length) {
|
||||
badge.innerText = notifications.length.toString();
|
||||
const notificationBoard = document.querySelector('.notification-board') as HTMLDivElement;
|
||||
noNotifications.style.display = 'none';
|
||||
for (const notif of notifications) {
|
||||
const notifElement = document.createElement('div');
|
||||
notifElement.className = 'notification-element';
|
||||
notifElement.setAttribute('notif-id', notif.id.toString());
|
||||
notifElement.innerHTML = `
|
||||
<div>${notif.title}</div>
|
||||
<div>${notif.description}</div>
|
||||
`;
|
||||
// this.addSubscription(notifElement, 'click', 'goToProcessPage')
|
||||
notificationBoard.appendChild(notifElement);
|
||||
}
|
||||
} else {
|
||||
noNotifications.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
function launchNotificationWorker() {
|
||||
if (window.Worker) {
|
||||
// Initialize the worker
|
||||
const worker = new Worker('/src/workers/notification.worker.ts', { type: 'module' });
|
||||
|
||||
// Listen for messages from the worker
|
||||
worker.addEventListener('message', (event) => {
|
||||
const data = event.data;
|
||||
console.log('Received data from worker:', data);
|
||||
setNotification(data);
|
||||
});
|
||||
} else {
|
||||
console.error('Your browser doesn\'t support web workers.');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { Html5QrcodeScanner } from 'html5-qrcode';
|
||||
import Routing from '../../services/routing.service';
|
||||
import Routing from '../../services/modal.service';
|
||||
import Services from '../../services/service';
|
||||
import { addSubscription } from '../../utils/subscription.utils';
|
||||
import { displayEmojis } from '../../utils/sp-address.utils';
|
||||
|
||||
let resultContainer = document.getElementById('qr-reader-results');
|
||||
let lastResult: any,
|
||||
@ -21,9 +23,10 @@ export async function initHomePage(): Promise<void> {
|
||||
const service = await Services.getInstance();
|
||||
const spAddress = await service.getDeviceAddress()
|
||||
service.generateQRCode(spAddress)
|
||||
service.displayEmojis(spAddress)
|
||||
displayEmojis(spAddress)
|
||||
|
||||
document.getElementById('notification-bell')?.addEventListener('click', openCloseNotifications);
|
||||
const notifBell = document.getElementById('notification-bell')
|
||||
if(notifBell) addSubscription(notifBell, 'click', openCloseNotifications)
|
||||
|
||||
var html5QrcodeScanner = new Html5QrcodeScanner('qr-reader', { fps: 10, qrbox: 250 }, undefined);
|
||||
html5QrcodeScanner.render(onScanSuccess, undefined);
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { addSubscription } from '../../utils/subscription.utils';
|
||||
import { navigate } from '../../router';
|
||||
import Services from '../../services/service';
|
||||
|
||||
@ -6,7 +7,7 @@ export async function init() {
|
||||
const element = document.querySelector('select') as HTMLSelectElement;
|
||||
// Create div that wroaps all the elements inside (select, elements selected, search div) to put select inside
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.addEventListener('click', clickOnWrapper);
|
||||
if(wrapper) addSubscription(wrapper, 'click', clickOnWrapper)
|
||||
wrapper.classList.add('multi-select-component');
|
||||
wrapper.classList.add('input-field');
|
||||
|
||||
@ -17,14 +18,16 @@ export async function init() {
|
||||
input.classList.add('selected-input');
|
||||
input.setAttribute('autocomplete', 'off');
|
||||
input.setAttribute('tabindex', '0');
|
||||
input.addEventListener('keyup', inputChange);
|
||||
input.addEventListener('keydown', deletePressed);
|
||||
input.addEventListener('click', openOptions);
|
||||
if(input) {
|
||||
addSubscription(input, 'keyup', inputChange)
|
||||
addSubscription(input, 'keydown', deletePressed)
|
||||
addSubscription(input, 'click', openOptions)
|
||||
}
|
||||
|
||||
const dropdown_icon = document.createElement('a');
|
||||
dropdown_icon.classList.add('dropdown-icon');
|
||||
|
||||
dropdown_icon.addEventListener('click', clickDropdown);
|
||||
if(dropdown_icon) addSubscription(dropdown_icon, 'click', clickDropdown)
|
||||
const autocomplete_list = document.createElement('ul');
|
||||
autocomplete_list.classList.add('autocomplete-list');
|
||||
search_div.appendChild(input);
|
||||
@ -128,7 +131,7 @@ function createToken(wrapper: HTMLElement, value: any) {
|
||||
close.setAttribute('data-option', value);
|
||||
close.setAttribute('data-hits', '0');
|
||||
close.innerText = 'x';
|
||||
close.addEventListener('click', removeToken);
|
||||
if(close) addSubscription(close, 'click', removeToken)
|
||||
token.appendChild(token_span);
|
||||
token.appendChild(close);
|
||||
inputInderline?.appendChild(token);
|
||||
@ -185,7 +188,7 @@ function populateAutocompleteList(select: HTMLSelectElement, query: string, drop
|
||||
const li = document.createElement('li');
|
||||
li.innerText = options_to_show[0];
|
||||
li.setAttribute('data-value', options_to_show[0]);
|
||||
li.addEventListener('click', selectOption);
|
||||
if(li) addSubscription(li, 'click', selectOption)
|
||||
autocomplete_list?.appendChild(li);
|
||||
if (query.length == options_to_show[0].length) {
|
||||
const event = new Event('click');
|
||||
@ -196,7 +199,7 @@ function populateAutocompleteList(select: HTMLSelectElement, query: string, drop
|
||||
const li = document.createElement('li');
|
||||
li.innerText = options_to_show[i];
|
||||
li.setAttribute('data-value', options_to_show[i]);
|
||||
li.addEventListener('click', selectOption);
|
||||
if(li) addSubscription(li, 'click', selectOption)
|
||||
autocomplete_list?.appendChild(li);
|
||||
}
|
||||
} else {
|
||||
@ -299,10 +302,10 @@ function removeToken(e: Event) {
|
||||
}
|
||||
|
||||
// Listen for 2 sequence of hits on the delete key, if this happens delete the last token if exist
|
||||
function deletePressed(e: KeyboardEvent) {
|
||||
function deletePressed(e: Event) {
|
||||
const input_search = e.target as HTMLInputElement;
|
||||
const wrapper = input_search?.parentNode?.parentNode;
|
||||
const key = e.keyCode || e.charCode;
|
||||
const key = (e as KeyboardEvent).keyCode || (e as KeyboardEvent).charCode;
|
||||
const tokens = wrapper?.querySelectorAll('.selected-wrapper');
|
||||
|
||||
if (tokens?.length) {
|
||||
@ -327,7 +330,7 @@ function deletePressed(e: KeyboardEvent) {
|
||||
}
|
||||
|
||||
// Dismiss on outside click
|
||||
document.addEventListener('click', () => {
|
||||
addSubscription(document, 'click', () => {
|
||||
// get select that has the options available
|
||||
const select = document.querySelectorAll('[data-multi-select-plugin]');
|
||||
for (let i = 0; i < select.length; i++) {
|
||||
@ -345,7 +348,7 @@ document.addEventListener('click', () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
async function showSelectedProcess(elem: MouseEvent) {
|
||||
if (elem) {
|
||||
@ -369,9 +372,7 @@ async function showSelectedProcess(elem: MouseEvent) {
|
||||
zoneElement.setAttribute('process-title', process[1].title);
|
||||
zoneElement.setAttribute('process-id', `${process[0]}_${zone.id}`);
|
||||
zoneElement.innerHTML = `${zone.title}: ${zone.description}`;
|
||||
const service = await Services.getInstance();
|
||||
// service.addSubscription(zoneElement, 'click', 'goToProcessPage');
|
||||
zoneElement.addEventListener('click', select);
|
||||
addSubscription(zoneElement, 'click', select);
|
||||
processDiv.appendChild(zoneElement);
|
||||
}
|
||||
if (cardContent) cardContent.appendChild(processDiv);
|
||||
@ -379,7 +380,7 @@ async function showSelectedProcess(elem: MouseEvent) {
|
||||
}
|
||||
}
|
||||
|
||||
function select(event: MouseEvent) {
|
||||
function select(event: Event) {
|
||||
const target = event.target as HTMLElement;
|
||||
const oldSelectedProcess = document.querySelector('.selected-process-zone');
|
||||
oldSelectedProcess?.classList.remove('selected-process-zone');
|
||||
@ -406,7 +407,6 @@ function goToProcessPage() {
|
||||
async function getProcesses(): Promise<any[]> {
|
||||
const service = await Services.getInstance();
|
||||
const processes = await service.getProcesses();
|
||||
console.log('🚀 ~ Services ~ getProcesses ~ processes:', processes);
|
||||
|
||||
return processes;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import '../public/style/4nk.css';
|
||||
import { initHeader } from './components/header/header';
|
||||
import Services from './services/service';
|
||||
import { cleanSubscriptions } from './utils/subscription.utils';
|
||||
|
||||
const routes: { [key: string]: string } = {
|
||||
home: '/src/pages/home/home.html',
|
||||
@ -11,6 +12,7 @@ const routes: { [key: string]: string } = {
|
||||
export let currentRoute = '';
|
||||
|
||||
export async function navigate(path: string) {
|
||||
cleanSubscriptions()
|
||||
path = path.replace(/^\//, '');
|
||||
if (path.includes('/')) {
|
||||
const parsedPath = path.split('/')[0];
|
||||
@ -86,7 +88,7 @@ async function init(): Promise<void> {
|
||||
if (pairingAddress) {
|
||||
setTimeout(async () => await services.sendPairingTx(pairingAddress), 2000);
|
||||
}
|
||||
await navigate('home');
|
||||
await navigate('process');
|
||||
}
|
||||
}, 200);
|
||||
} catch (error) {
|
||||
|
@ -5,9 +5,10 @@ import confirmationModalScript from '../html/confirmation-modal.js?raw';
|
||||
import Services from './service';
|
||||
import { U32_MAX } from './service';
|
||||
import { navigate } from '../router';
|
||||
import { addressToEmoji } from '../utils/sp-address.utils';
|
||||
|
||||
export default class Routing {
|
||||
private static instance: Routing;
|
||||
export default class ModalService {
|
||||
private static instance: ModalService;
|
||||
private sdkClient: any;
|
||||
private currentPrd: any;
|
||||
private currentOutpoint?: string;
|
||||
@ -15,16 +16,11 @@ export default class Routing {
|
||||
private paired_addresses: string[] = [];
|
||||
|
||||
// Method to access the singleton instance of Services
|
||||
public static async getInstance(): Promise<Routing> {
|
||||
if (!Routing.instance) {
|
||||
Routing.instance = new Routing();
|
||||
await Routing.instance.init();
|
||||
public static async getInstance(): Promise<ModalService> {
|
||||
if (!ModalService.instance) {
|
||||
ModalService.instance = new ModalService();
|
||||
}
|
||||
return Routing.instance;
|
||||
}
|
||||
|
||||
public async init(): Promise<void> {
|
||||
this.sdkClient = await import('../../dist/pkg/sdk_client');
|
||||
return ModalService.instance;
|
||||
}
|
||||
|
||||
public openLoginModal(myAddress: string, receiverAddress: string) {
|
||||
@ -43,23 +39,22 @@ export default class Routing {
|
||||
}
|
||||
|
||||
public async openConfirmationModal(pcd: any, outpointCommitment: string) {
|
||||
console.log('');
|
||||
let roles = JSON.parse(pcd['roles']); // ['members'][0];
|
||||
console.log(roles);
|
||||
let members = roles['owner']['members'];
|
||||
console.log(members);
|
||||
// We take all the addresses except our own
|
||||
const local_address = this.sdkClient.get_address();
|
||||
const service = await Services.getInstance()
|
||||
const localAddress = await service.getDeviceAddress();
|
||||
console.log('🚀 ~ Routing ~ openConfirmationModal ~ pcd:', pcd);
|
||||
for (const address of members[0]['sp_addresses']) {
|
||||
if (address !== local_address) {
|
||||
if (address !== localAddress) {
|
||||
this.paired_addresses.push(address);
|
||||
}
|
||||
}
|
||||
let html = confirmationModalHtml;
|
||||
let services = await Services.getInstance();
|
||||
html = html.replace('{{device1}}', await services.addressToEmoji(members[0]['sp_addresses'][0]));
|
||||
html = html.replace('{{device2}}', await services.addressToEmoji(members[0]['sp_addresses'][1]));
|
||||
html = html.replace('{{device1}}', await addressToEmoji(members[0]['sp_addresses'][0]));
|
||||
html = html.replace('{{device2}}', await addressToEmoji(members[0]['sp_addresses'][1]));
|
||||
this.currentOutpoint = outpointCommitment as string;
|
||||
const container = document.querySelector('.page-container');
|
||||
|
||||
@ -99,7 +94,7 @@ export default class Routing {
|
||||
const commitmentOutpoint = `${emptyTxid}:${U32_MAX}`;
|
||||
|
||||
// We take the paired device(s) from the contract
|
||||
await this.sdkClient.pair_device(commitmentOutpoint, this.paired_addresses);
|
||||
await service.pairDevice(commitmentOutpoint, this.paired_addresses);
|
||||
this.paired_addresses = [];
|
||||
const newDevice = await service.dumpDevice();
|
||||
await service.saveDevice(newDevice);
|
@ -5,8 +5,9 @@ import { IProcess } from '~/models/process.model';
|
||||
import { WebSocketClient } from '../websockets';
|
||||
import QRCode from 'qrcode';
|
||||
import { ApiReturn, Member } from '../../dist/pkg/sdk_client';
|
||||
import Routing from './routing.service';
|
||||
import { currentRoute, navigate } from '../router';
|
||||
import ModalService from './modal.service';
|
||||
import { navigate } from '../router';
|
||||
import { copyToClipboard } from '../utils/sp-address.utils';
|
||||
|
||||
type ProcessesCache = {
|
||||
[key: string]: any;
|
||||
@ -25,6 +26,7 @@ export default class Services {
|
||||
private notifications: INotification[] | null = null;
|
||||
private subscriptions: { element: Element; event: string; eventHandler: string }[] = [];
|
||||
private database: any;
|
||||
private routingInstance!: ModalService;
|
||||
// Private constructor to prevent direct instantiation from outside
|
||||
private constructor() {}
|
||||
|
||||
@ -38,6 +40,7 @@ export default class Services {
|
||||
Services.initializing = (async () => {
|
||||
const instance = new Services();
|
||||
await instance.init();
|
||||
instance.routingInstance = await ModalService.getInstance()
|
||||
return instance;
|
||||
})();
|
||||
}
|
||||
@ -79,162 +82,13 @@ export default class Services {
|
||||
}
|
||||
const copyBtn = document.getElementById('copyBtn');
|
||||
if (copyBtn) {
|
||||
copyBtn.addEventListener('click', () => this.copyToClipboard(currentUrl + '?sp_address=' + text));
|
||||
copyBtn.addEventListener('click', () => copyToClipboard(currentUrl + '?sp_address=' + text));
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
//Copy Address
|
||||
public async 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
|
||||
public 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
|
||||
public addressToEmoji = async (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 = this.generateEmojiList();
|
||||
const emojis = Array.from(bytes)
|
||||
.map((byte) => emojiList[byte])
|
||||
.join('');
|
||||
return emojis;
|
||||
};
|
||||
|
||||
//Get emojis from other device
|
||||
public async emojisPairingRequest() {
|
||||
try {
|
||||
const container = document.getElementById('containerId');
|
||||
|
||||
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 this.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
|
||||
displayEmojis = async (text: string) => {
|
||||
console.log('🚀 ~ Services ~ adressToEmoji');
|
||||
try {
|
||||
const container = document.getElementById('containerId');
|
||||
const emojis = await this.addressToEmoji(text);
|
||||
const emojiDisplay = container?.querySelector('.emoji-display');
|
||||
|
||||
if (emojiDisplay) {
|
||||
emojiDisplay.textContent = emojis;
|
||||
}
|
||||
|
||||
this.emojisPairingRequest();
|
||||
|
||||
this.initAddressInput();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
// Verify Other address
|
||||
public initAddressInput() {
|
||||
const addressInput = document.getElementById('addressInput') as HTMLInputElement;
|
||||
const emojiDisplay = document.getElementById('emoji-display-2');
|
||||
const okButton = document.getElementById('okButton');
|
||||
|
||||
addressInput.addEventListener('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 this.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 (okButton) {
|
||||
okButton.addEventListener('click', () => {
|
||||
this.onOkButtonClick();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async onOkButtonClick() {
|
||||
const addressInput = (document.getElementById('addressInput') as HTMLInputElement).value;
|
||||
await this.sendPairingTx(addressInput);
|
||||
}
|
||||
|
||||
public isPaired(): boolean | undefined {
|
||||
try {
|
||||
return this.sdkClient.is_linking();
|
||||
@ -382,8 +236,7 @@ export default class Services {
|
||||
if (proposals && proposals.length != 0) {
|
||||
const actual_proposal = JSON.parse(proposals[0]); // We just don't acknowledge concurrent proposals for now
|
||||
console.info(actual_proposal);
|
||||
let router = await Routing.getInstance();
|
||||
await router.openConfirmationModal(actual_proposal, processCommitment);
|
||||
await this.routingInstance.openConfirmationModal(actual_proposal, processCommitment);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
@ -409,15 +262,18 @@ export default class Services {
|
||||
}, 0);
|
||||
}
|
||||
|
||||
async pairDevice(prd: any, outpointCommitment: string) {
|
||||
async pairDevice(commitmentTx: string, spAddressList: string[]) {
|
||||
await this.sdkClient.pair_device(commitmentTx, spAddressList);
|
||||
}
|
||||
|
||||
async validatePairingDevice(prd: any, outpointCommitment: string) {
|
||||
console.log('🚀 ~ Services ~ pairDevice ~ prd:', prd);
|
||||
const service = await Services.getInstance();
|
||||
const spAddress = (await this.getDeviceAddress()) as any;
|
||||
const sender = JSON.parse(prd?.sender);
|
||||
const senderAddress = sender?.sp_addresses?.find((address: string) => address !== spAddress);
|
||||
console.log('🚀 ~ Services ~ pairDevice ~ senderAddress:', senderAddress);
|
||||
if (senderAddress) {
|
||||
const proposal = service.sdkClient.get_update_proposals(outpointCommitment);
|
||||
const proposal = this.sdkClient.get_update_proposals(outpointCommitment);
|
||||
console.log('🚀 ~ Services ~ pairDevice ~ proposal:', proposal);
|
||||
// const pairingTx = proposal.pairing_tx.replace(/^\"+|\"+$/g, '')
|
||||
const parsedProposal = JSON.parse(proposal[0]);
|
||||
@ -436,7 +292,7 @@ export default class Services {
|
||||
let txid = '0'.repeat(64);
|
||||
console.log('🚀 ~ Services ~ pairDevice ~ pairingTx:', pairingTx, `${txid}:4294967295`);
|
||||
|
||||
const pairing = await service.sdkClient.pair_device(`${txid}:4294967295`, [senderAddress]);
|
||||
const pairing = await this.sdkClient.pair_device(`${txid}:4294967295`, [senderAddress]);
|
||||
const device = this.dumpDevice();
|
||||
console.log('🚀 ~ Services ~ pairDevice ~ device:', device);
|
||||
this.saveDevice(device);
|
||||
@ -446,10 +302,10 @@ export default class Services {
|
||||
console.log('🚀 ~ Services ~ pairDevice ~ process:', outpointCommitment, prd, prd.payload);
|
||||
const prdString = JSON.stringify(prd).trim();
|
||||
console.log('🚀 ~ Services ~ pairDevice ~ prdString:', prdString);
|
||||
let tx = await service.sdkClient.response_prd(outpointCommitment, prdString, true);
|
||||
let tx = await this.sdkClient.response_prd(outpointCommitment, prdString, true);
|
||||
console.log('🚀 ~ Services ~ pairDevice ~ tx:', tx);
|
||||
if (tx.ciphers_to_send) {
|
||||
tx.ciphers_to_send.forEach((cipher: string) => service.websocketConnection?.sendMessage('Cipher', cipher));
|
||||
tx.ciphers_to_send.forEach((cipher: string) => this.websocketConnection?.sendMessage('Cipher', cipher));
|
||||
}
|
||||
navigate('process');
|
||||
}
|
||||
@ -505,12 +361,7 @@ export default class Services {
|
||||
console.log('🚀 ~ Services ~ createFaucetMessage ~ message:', message);
|
||||
return message;
|
||||
}
|
||||
|
||||
addSubscription(element: Element, event: string, eventHandler: string): void {
|
||||
this.subscriptions.push({ element, event, eventHandler });
|
||||
element.addEventListener(event, (this as any)[eventHandler]);
|
||||
}
|
||||
|
||||
|
||||
async createNewDevice() {
|
||||
let spAddress = '';
|
||||
try {
|
||||
@ -696,48 +547,6 @@ export default class Services {
|
||||
}
|
||||
}
|
||||
|
||||
private cleanSubscriptions(): void {
|
||||
for (const sub of this.subscriptions) {
|
||||
const el = sub.element;
|
||||
const eventHandler = sub.eventHandler;
|
||||
el.removeEventListener(sub.event, (this as any)[eventHandler].bind(this));
|
||||
}
|
||||
this.subscriptions = [];
|
||||
}
|
||||
|
||||
public async setProcessesInSelectElement(processList: any[]) {
|
||||
console.log('🚀 ~ Services ~ setProcessesInSelectElement ~ processList:', processList);
|
||||
const select = document.querySelector('.select-field');
|
||||
if (select) {
|
||||
for (const process of processList) {
|
||||
const option = document.createElement('option');
|
||||
option.setAttribute('value', process.name);
|
||||
option.innerText = process.name;
|
||||
select.appendChild(option);
|
||||
}
|
||||
}
|
||||
const optionList = document.querySelector('.autocomplete-list');
|
||||
if (optionList) {
|
||||
const observer = new MutationObserver((mutations, observer) => {
|
||||
const options = optionList.querySelectorAll('li');
|
||||
if (options) {
|
||||
for (const option of options) {
|
||||
this.addSubscription(option, 'click', 'showSelectedProcess');
|
||||
}
|
||||
}
|
||||
});
|
||||
observer.observe(document, {
|
||||
subtree: true,
|
||||
attributes: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public async listenToOptionListPopulating(event: Event) {
|
||||
const target = event.target as HTMLUListElement;
|
||||
const options = target?.querySelectorAll('li');
|
||||
}
|
||||
|
||||
getNotifications(): INotification[] {
|
||||
return [
|
||||
{
|
||||
@ -763,28 +572,4 @@ export default class Services {
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
async setNotification(): Promise<void> {
|
||||
const badge = document.querySelector('.notification-badge') as HTMLDivElement;
|
||||
const notifications = this.notifications;
|
||||
const noNotifications = document.querySelector('.no-notification') as HTMLDivElement;
|
||||
if (notifications?.length) {
|
||||
badge.innerText = notifications.length.toString();
|
||||
const notificationBoard = document.querySelector('.notification-board') as HTMLDivElement;
|
||||
noNotifications.style.display = 'none';
|
||||
for (const notif of notifications) {
|
||||
const notifElement = document.createElement('div');
|
||||
notifElement.className = 'notification-element';
|
||||
notifElement.setAttribute('notif-id', notif.id.toString());
|
||||
notifElement.innerHTML = `
|
||||
<div>${notif.title}</div>
|
||||
<div>${notif.description}</div>
|
||||
`;
|
||||
// this.addSubscription(notifElement, 'click', 'goToProcessPage')
|
||||
notificationBoard.appendChild(notifElement);
|
||||
}
|
||||
} else {
|
||||
noNotifications.style.display = 'block';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
152
src/utils/sp-address.utils.ts
Normal file
152
src/utils/sp-address.utils.ts
Normal file
@ -0,0 +1,152 @@
|
||||
import Services from "../services/service";
|
||||
import { addSubscription } from "./subscription.utils";
|
||||
|
||||
//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 = document.getElementById('containerId');
|
||||
|
||||
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 = document.getElementById('containerId');
|
||||
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 addressInput = document.getElementById('addressInput') as HTMLInputElement;
|
||||
const emojiDisplay = document.getElementById('emoji-display-2');
|
||||
const okButton = document.getElementById('okButton');
|
||||
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 (okButton) {
|
||||
okButton.addEventListener('click', () => {
|
||||
onOkButtonClick();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function onOkButtonClick() {
|
||||
const service = await Services.getInstance()
|
||||
const addressInput = (document.getElementById('addressInput') as HTMLInputElement).value;
|
||||
await service.sendPairingTx(addressInput);
|
||||
}
|
16
src/utils/subscription.utils.ts
Normal file
16
src/utils/subscription.utils.ts
Normal file
@ -0,0 +1,16 @@
|
||||
let subscriptions: { element: Element | Document, event: any, eventHandler: EventListenerOrEventListenerObject }[] = [];
|
||||
|
||||
export function cleanSubscriptions(): void {
|
||||
console.log("🚀 ~ cleanSubscriptions ~ sub:", subscriptions)
|
||||
for (const sub of subscriptions) {
|
||||
const el = sub.element;
|
||||
const eventHandler = sub.eventHandler;
|
||||
el.removeEventListener(sub.event, eventHandler);
|
||||
}
|
||||
subscriptions = [];
|
||||
}
|
||||
|
||||
export function addSubscription(element: Element | Document, event: any, eventHandler: EventListenerOrEventListenerObject): void {
|
||||
subscriptions.push({ element, event, eventHandler });
|
||||
element.addEventListener(event, eventHandler);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user