post: improve write and reply to textnote usability

- use growing textarea input to support multiline textnotes
- keep replyTo id in localstorage instead of global variable
- render reply to form on load if there was a replyTo in storage
pull/13/head
OFF0 1 year ago
parent b10a63b932
commit 06686ba9a7
Signed by: offbyn
GPG Key ID: 94A2F643C51F37FA

@ -28,7 +28,8 @@ label {
}
input[type="password"],
input[type="text"] {
input[type="text"],
textarea {
background: var(--bgcolor-textinput);
border: .2rem solid #b7b7b7;
border-radius: .2rem;
@ -36,11 +37,22 @@ input[type="text"] {
margin: 0;
}
input[type="password"]:focus,
input[type="text"]:focus {
input[type="text"]:focus,
textarea:focus {
border-color: var(--focus-border-color);
outline-offset: 2px;
outline-offset: var(--focus-outline-offset);
outline: var(--focus-outline);
}
textarea {
max-height: 50vh;
min-height: 20px;
transition: min-height .1s ease-out, height .1s ease-out;
}
textarea:focus {
min-height: 3.5rem;
}
.buttons {
align-items: center;
display: flex;
@ -108,19 +120,25 @@ button:disabled {
gap: 1rem;
}
.cards .form-inline button,
.cards .form-inline input[type="text"] {
.cards .form-inline input[type="text"],
.cards .form-inline textarea {
margin: .4rem 0;
padding: .6rem 1rem;
}
.form-inline input[type="text"] {
.form-inline input[type="text"],
.form-inline textarea {
flex-grow: 1;
margin-bottom: 0;
}
.form-inline button {
flex-grow: 0;
}
.form-inline button#publish {
align-self: end;
}
.focus-active {
}

@ -25,7 +25,7 @@
<img class="mbox-img" id="bubble" src="assets/comment.svg" alt="">
<div class="mbox-body" id="newMessage">
<form action="#" class="form-inline" id="writeForm">
<textarea name="message"></textarea>
<textarea name="message" rows="1"></textarea>
<button type="submit" id="publish" disabled>send</button>
</form>
<small id="sendstatus" class="form-status"></small>

@ -6,7 +6,8 @@
/* 5px auto Highlight */
--focus-border-color: rgb(0, 122, 255);
--focus-border-radius: 2px;
--focus-outline-color: rgb(127, 189, 247);
--focus-outline-color: rgb(192, 227, 252);
--focus-outline-offset: 2px;
--focus-outline-style: solid;
--focus-outline-width: 2px;
--focus-outline: var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color);

@ -120,7 +120,8 @@ function handleReaction(evt, relay) {
// feed
const feedContainer = document.querySelector('#homefeed');
const feedDomMap = {};
const replyDomMap = window.replyDomMap = {};
const replyDomMap = {};
const restoredReplyTo = localStorage.getItem('reply_to');
const sortByCreatedAt = (evt1, evt2) => {
if (evt1.created_at === evt2.created_at) {
@ -191,6 +192,7 @@ function createTextNote(evt, relay) {
}, [elem('img', {height: 24, width: 24, src: 'assets/comment.svg'})]),
replies[0] ? elem('div', {className: 'mobx-replies'}, replyFeed.reverse()) : '',
]);
if (restoredReplyTo === evt.id) appendReplyForm(body.querySelector('button[name="reply"]'));
return rendernArticle([img, body]);
}
@ -359,23 +361,11 @@ function getMetadata(evt, relay) {
}
// reply
const writeForm = document.querySelector('#writeForm');
const input = document.querySelector('textarea[name="message"]');
let lastReplyBtn = null;
let replyTo = null;
feedContainer.addEventListener('click', (e) => {
const button = e.target.closest('button');
if (button && button.name === 'reply') {
if (lastReplyBtn) {
lastReplyBtn.hidden = false;
}
lastReplyBtn = button;
// button.hidden = true;
button.after(writeForm);
button.after(sendStatus);
writeForm.hidden = false;
replyTo = ['e', button.dataset.eventId, button.dataset.relay];
input.focus();
appendReplyForm(button);
localStorage.setItem('reply_to', button.dataset.eventId);
return;
}
if (button && button.name === 'star') {
@ -384,12 +374,21 @@ feedContainer.addEventListener('click', (e) => {
}
});
const writeForm = document.querySelector('#writeForm');
const writeInput = document.querySelector('textarea[name="message"]');
function appendReplyForm(el) {
el.after(writeForm);
el.after(sendStatus);
writeInput.focus();
}
const newMessageDiv = document.querySelector('#newMessage');
document.querySelector('#bubble').addEventListener('click', (e) => {
replyTo = null;
localStorage.removeItem('reply_to');
newMessageDiv.prepend(writeForm);
newMessageDiv.append(sendStatus);
input.focus();
writeInput.focus();
});
async function upvote(eventId, relay) {
@ -428,14 +427,15 @@ writeForm.addEventListener('submit', async (e) => {
if (!pubkey || !privatekey) {
return onSendError(new Error('no pubkey/privatekey'));
}
if (!input.value) {
if (!writeInput.value) {
return onSendError(new Error('message is empty'));
}
const tags = replyTo ? [replyTo] : [];
const replyTo = localStorage.getItem('reply_to');
const tags = replyTo ? [['e', replyTo, eventRelayMap[replyTo][0]]] : [];
const newEvent = {
kind: 1,
pubkey,
content: input.value,
content: writeInput.value,
tags,
created_at: Math.floor(Date.now() * 0.001),
};
@ -447,12 +447,11 @@ writeForm.addEventListener('submit', async (e) => {
}
if (status === 1) {
sendStatus.hidden = true;
input.value = '';
writeInput.value = '';
writeInput.style.removeProperty('height');
publish.disabled = true;
if (lastReplyBtn) {
lastReplyBtn.hidden = false;
lastReplyBtn = null;
replyTo = null;
if (replyTo) {
localStorage.removeItem('reply_to');
newMessageDiv.append(writeForm);
newMessageDiv.append(sendStatus);
}
@ -462,8 +461,22 @@ writeForm.addEventListener('submit', async (e) => {
}
});
input.addEventListener('input', () => publish.disabled = !input.value);
input.addEventListener('blur', () => sendStatus.textContent = '');
writeInput.addEventListener('input', () => {
publish.disabled = !writeInput.value;
updateElemHeight(writeInput);
});
writeInput.addEventListener('blur', () => sendStatus.textContent = '');
function updateElemHeight(el) {
el.style.removeProperty('height');
if (el.value) {
el.style.paddingBottom = 0;
el.style.paddingTop = 0;
el.style.height = el.scrollHeight + 'px';
el.style.removeProperty('padding-bottom');
el.style.removeProperty('padding-top');
}
}
// settings
const settingsForm = document.querySelector('form[name="settings"]');

Loading…
Cancel
Save