|
|
|
@ -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,7 +775,8 @@ async function upvote(eventId, relay) {
|
|
|
|
|
content: '+',
|
|
|
|
|
tags: [['e', eventId, relay, 'reply']],
|
|
|
|
|
created_at: Math.floor(Date.now() * 0.001),
|
|
|
|
|
}, difficulty);
|
|
|
|
|
}, 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) => {
|
|
|
|
@ -785,6 +789,7 @@ async function upvote(eventId, relay) {
|
|
|
|
|
}).catch(console.error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// send
|
|
|
|
|
const sendStatus = document.querySelector('#sendstatus');
|
|
|
|
@ -809,7 +814,8 @@ writeForm.addEventListener('submit', async (e) => {
|
|
|
|
|
pubkey,
|
|
|
|
|
tags,
|
|
|
|
|
created_at: Math.floor(Date.now() * 0.001),
|
|
|
|
|
}, difficulty);
|
|
|
|
|
}, difficulty, 10).catch(console.warn);
|
|
|
|
|
if (newEvent) {
|
|
|
|
|
const sig = await signEvent(newEvent, privatekey).catch(onSendError);
|
|
|
|
|
if (sig) {
|
|
|
|
|
const ev = await pool.publish({...newEvent, sig}, (status, url) => {
|
|
|
|
@ -830,6 +836,7 @@ writeForm.addEventListener('submit', async (e) => {
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
writeInput.addEventListener('input', () => {
|
|
|
|
@ -951,7 +958,8 @@ profileForm.addEventListener('submit', async (e) => {
|
|
|
|
|
content: JSON.stringify(Object.fromEntries(form)),
|
|
|
|
|
tags: [],
|
|
|
|
|
created_at: Math.floor(Date.now() * 0.001),
|
|
|
|
|
}, difficulty);
|
|
|
|
|
}, difficulty, 10).catch(console.warn);
|
|
|
|
|
if (newProfile) {
|
|
|
|
|
const sig = await signEvent(newProfile, privatekey).catch(console.error);
|
|
|
|
|
if (sig) {
|
|
|
|
|
const ev = await pool.publish({...newProfile, sig}, (status, url) => {
|
|
|
|
@ -965,8 +973,42 @@ profileForm.addEventListener('submit', async (e) => {
|
|
|
|
|
}
|
|
|
|
|
}).catch(console.error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
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 +1031,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);
|
|
|
|
|
}
|
|
|
|
|