|
|
|
@ -297,7 +297,7 @@ function handleReaction(evt, relay) {
|
|
|
|
|
replies = eventTags.filter((tags) => tags[3] === undefined);
|
|
|
|
|
}
|
|
|
|
|
if (replies.length !== 1) {
|
|
|
|
|
console.log('call me', evt);
|
|
|
|
|
// console.log('call me', evt);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -740,6 +740,9 @@ function appendReplyForm(el) {
|
|
|
|
|
requestAnimationFrame(() => writeInput.focus());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const lockScroll = () => document.body.style.overflow = 'hidden';
|
|
|
|
|
const unlockScroll = () => document.body.style.removeProperty('overflow');
|
|
|
|
|
|
|
|
|
|
const newMessageDiv = document.querySelector('#newMessage');
|
|
|
|
|
document.querySelector('#bubble').addEventListener('click', (e) => {
|
|
|
|
|
localStorage.removeItem('reply_to'); // should it forget old replyto context?
|
|
|
|
@ -749,7 +752,7 @@ document.querySelector('#bubble').addEventListener('click', (e) => {
|
|
|
|
|
if (writeInput.value.trimRight()) {
|
|
|
|
|
writeInput.style.removeProperty('height');
|
|
|
|
|
}
|
|
|
|
|
document.body.style.overflow = 'hidden';
|
|
|
|
|
lockScroll();
|
|
|
|
|
requestAnimationFrame(() => updateElemHeight(writeInput));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
@ -760,7 +763,7 @@ document.body.addEventListener('keyup', (e) => {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function hideNewMessage(hide) {
|
|
|
|
|
document.body.style.removeProperty('overflow');
|
|
|
|
|
unlockScroll();
|
|
|
|
|
newMessageDiv.hidden = hide;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -772,17 +775,19 @@ async function upvote(eventId, relay) {
|
|
|
|
|
content: '+',
|
|
|
|
|
tags: [['e', eventId, relay, 'reply']],
|
|
|
|
|
created_at: Math.floor(Date.now() * 0.001),
|
|
|
|
|
}, difficulty);
|
|
|
|
|
const sig = await signEvent(newReaction, privatekey).catch(console.error);
|
|
|
|
|
if (sig) {
|
|
|
|
|
const ev = await pool.publish({...newReaction, sig}, (status, url) => {
|
|
|
|
|
if (status === 0) {
|
|
|
|
|
console.info(`publish request sent to ${url}`);
|
|
|
|
|
}
|
|
|
|
|
if (status === 1) {
|
|
|
|
|
console.info(`event published by ${url}`);
|
|
|
|
|
}
|
|
|
|
|
}).catch(console.error);
|
|
|
|
|
}, difficulty, 10).catch(console.warn);
|
|
|
|
|
if (newReaction) {
|
|
|
|
|
const sig = await signEvent(newReaction, privatekey).catch(console.error);
|
|
|
|
|
if (sig) {
|
|
|
|
|
const ev = await pool.publish({...newReaction, sig}, (status, url) => {
|
|
|
|
|
if (status === 0) {
|
|
|
|
|
console.info(`publish request sent to ${url}`);
|
|
|
|
|
}
|
|
|
|
|
if (status === 1) {
|
|
|
|
|
console.info(`event published by ${url}`);
|
|
|
|
|
}
|
|
|
|
|
}).catch(console.error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -809,7 +814,7 @@ writeForm.addEventListener('submit', async (e) => {
|
|
|
|
|
pubkey,
|
|
|
|
|
tags,
|
|
|
|
|
created_at: Math.floor(Date.now() * 0.001),
|
|
|
|
|
}, difficulty);
|
|
|
|
|
}, difficulty, 10);
|
|
|
|
|
const sig = await signEvent(newEvent, privatekey).catch(onSendError);
|
|
|
|
|
if (sig) {
|
|
|
|
|
const ev = await pool.publish({...newEvent, sig}, (status, url) => {
|
|
|
|
@ -951,7 +956,7 @@ profileForm.addEventListener('submit', async (e) => {
|
|
|
|
|
content: JSON.stringify(Object.fromEntries(form)),
|
|
|
|
|
tags: [],
|
|
|
|
|
created_at: Math.floor(Date.now() * 0.001),
|
|
|
|
|
}, difficulty);
|
|
|
|
|
}, difficulty, 10);
|
|
|
|
|
const sig = await signEvent(newProfile, privatekey).catch(console.error);
|
|
|
|
|
if (sig) {
|
|
|
|
|
const ev = await pool.publish({...newProfile, sig}, (status, url) => {
|
|
|
|
@ -967,6 +972,39 @@ profileForm.addEventListener('submit', async (e) => {
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const errorOverlay = document.querySelector('#errorOverlay');
|
|
|
|
|
|
|
|
|
|
function promptError(error, options = {}) {
|
|
|
|
|
const {onAgain, onCancel} = options;
|
|
|
|
|
lockScroll();
|
|
|
|
|
errorOverlay.replaceChildren(
|
|
|
|
|
elem('h1', {className: 'error-title'}, error),
|
|
|
|
|
elem('p', {}, 'something went wrong'),
|
|
|
|
|
elem('div', {className: 'buttons'}, [
|
|
|
|
|
onCancel ? elem('button', {data: {action: 'close'}}, 'close') : '',
|
|
|
|
|
onAgain ? elem('button', {data: {action: 'again'}}, 'try again') : '',
|
|
|
|
|
]),
|
|
|
|
|
);
|
|
|
|
|
const handleOverlayClick = (e) => {
|
|
|
|
|
const button = e.target.closest('button');
|
|
|
|
|
if (button) {
|
|
|
|
|
switch(button.dataset.action) {
|
|
|
|
|
case 'close':
|
|
|
|
|
onCancel();
|
|
|
|
|
break;
|
|
|
|
|
case 'again':
|
|
|
|
|
onAgain();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
errorOverlay.removeEventListener('click', handleOverlayClick);
|
|
|
|
|
errorOverlay.hidden = true;
|
|
|
|
|
unlockScroll();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
errorOverlay.addEventListener('click', handleOverlayClick);
|
|
|
|
|
errorOverlay.hidden = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* check that the event has the id has the desired number of leading zero bits
|
|
|
|
|
* @param {EventObj} evt to validate
|
|
|
|
@ -989,14 +1027,20 @@ function validatePow(evt) {
|
|
|
|
|
* powEvent returns a rejected promise if the funtion runs for longer than timeout.
|
|
|
|
|
* a zero timeout makes mineEvent run without a time limit.
|
|
|
|
|
*/
|
|
|
|
|
function powEvent(evt, difficulty, timeout) {
|
|
|
|
|
function powEvent(evt, difficulty, timeout = 0) {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
const worker = new Worker('./worker.js');
|
|
|
|
|
|
|
|
|
|
worker.onmessage = (msg) => {
|
|
|
|
|
worker.terminate();
|
|
|
|
|
if (msg.data.error) {
|
|
|
|
|
reject(msg.data.error);
|
|
|
|
|
promptError(msg.data.error, {
|
|
|
|
|
onCancel: () => reject('canceled'),
|
|
|
|
|
onAgain: async () => {
|
|
|
|
|
const result = await powEvent(evt, difficulty, timeout).catch(console.warn);
|
|
|
|
|
resolve(result);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
resolve(msg.data.event);
|
|
|
|
|
}
|
|
|
|
|