refactor: improve view and move code to ui and notes
cleanup code and move parts to ui.ts and notes.ts. simplify view and fix some weird animation issue, it should run pretty stable now. updated color and spacings. profile view now showing kind 0 name, but it is unnecessarily re-rendering. this part should probably go to a custom profil subscription callback in the future. keeping as is for now and refactor later.pull/72/head
parent
42fbd7c4c8
commit
c88cfa74bb
@ -0,0 +1,16 @@
|
|||||||
|
import {Event} from 'nostr-tools';
|
||||||
|
|
||||||
|
export type EventWithNip19 = Event & {
|
||||||
|
nip19: {
|
||||||
|
note: string;
|
||||||
|
npub: string;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const textNoteList: Array<EventWithNip19> = []; // could use indexDB
|
||||||
|
|
||||||
|
export type EventWithNip19AndReplyTo = EventWithNip19 & {
|
||||||
|
replyTo: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const replyList: Array<EventWithNip19AndReplyTo> = [];
|
@ -0,0 +1,84 @@
|
|||||||
|
import {Event} from 'nostr-tools';
|
||||||
|
import {elem, elemArticle, parseTextContent} from './utils/dom';
|
||||||
|
import {dateTime, formatTime} from './utils/time';
|
||||||
|
import {validatePow, sortByCreatedAt} from './events';
|
||||||
|
import {setViewElem} from './view';
|
||||||
|
import {config} from './settings';
|
||||||
|
import {getReactions, getReactionContents} from './reactions';
|
||||||
|
import {openWriteInput} from './write';
|
||||||
|
import {linkPreview} from './media';
|
||||||
|
import {getMetadata} from './profiles';
|
||||||
|
import {EventWithNip19, replyList} from './notes';
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
document.querySelectorAll('time[datetime]').forEach((timeElem: HTMLTimeElement) => {
|
||||||
|
timeElem.textContent = formatTime(new Date(timeElem.dateTime));
|
||||||
|
});
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
export const createTextNote = (
|
||||||
|
evt: EventWithNip19,
|
||||||
|
relay: string,
|
||||||
|
) => {
|
||||||
|
const {host, img, name, time, userName} = getMetadata(evt, relay);
|
||||||
|
const replies = replyList.filter(({replyTo}) => replyTo === evt.id);
|
||||||
|
// const isLongContent = evt.content.trimRight().length > 280;
|
||||||
|
// const content = isLongContent ? evt.content.slice(0, 280) : evt.content;
|
||||||
|
const reactions = getReactions(evt.id);
|
||||||
|
const didReact = reactions.length && !!reactions.find(reaction => reaction.pubkey === config.pubkey);
|
||||||
|
const [content, {firstLink}] = parseTextContent(evt.content);
|
||||||
|
const buttons = elem('div', {className: 'buttons'}, [
|
||||||
|
elem('button', {name: 'reply', type: 'button'}, [
|
||||||
|
elem('img', {height: 24, width: 24, src: '/assets/comment.svg'})
|
||||||
|
]),
|
||||||
|
elem('button', {name: 'star', type: 'button'}, [
|
||||||
|
elem('img', {
|
||||||
|
alt: didReact ? '✭' : '✩', // ♥
|
||||||
|
height: 24, width: 24,
|
||||||
|
src: `/assets/${didReact ? 'star-fill' : 'star'}.svg`,
|
||||||
|
title: getReactionContents(evt.id).join(' '),
|
||||||
|
}),
|
||||||
|
elem('small', {data: {reactions: ''}}, reactions.length || ''),
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
if (localStorage.getItem('reply_to') === evt.id) {
|
||||||
|
openWriteInput(buttons, evt.id);
|
||||||
|
}
|
||||||
|
const replyFeed: Array<HTMLElement> = replies[0] ? replies.sort(sortByCreatedAt).map(e => setViewElem(e.id, createTextNote(e, relay))) : [];
|
||||||
|
return elemArticle([
|
||||||
|
elem('div', {className: 'mbox-img'}, img),
|
||||||
|
elem('div', {className: 'mbox-body'}, [
|
||||||
|
elem('header', {
|
||||||
|
className: 'mbox-header',
|
||||||
|
title: `User: ${userName}\n${time}\n\nUser pubkey: ${evt.pubkey}\n\nRelay: ${host}\n\nEvent-id: ${evt.id}
|
||||||
|
${evt.tags.length ? `\nTags ${JSON.stringify(evt.tags)}\n` : ''}
|
||||||
|
${evt.content}`
|
||||||
|
}, [
|
||||||
|
elem('a', {className: `mbox-username${name ? ' mbox-kind0-name' : ''}`, href: `/${evt.nip19.npub}`}, name || userName),
|
||||||
|
' ',
|
||||||
|
elem('a', {href: `/${evt.nip19.note}`}, elem('time', {dateTime: time.toISOString()}, formatTime(time))),
|
||||||
|
]),
|
||||||
|
elem('div', {/* data: isLongContent ? {append: evt.content.slice(280)} : null*/}, [
|
||||||
|
...content,
|
||||||
|
(firstLink && validatePow(evt)) ? linkPreview(firstLink, evt.id, relay) : null,
|
||||||
|
]),
|
||||||
|
buttons,
|
||||||
|
]),
|
||||||
|
...(replies[0] ? [elem('div', {className: 'mobx-replies'}, replyFeed.reverse())] : []),
|
||||||
|
], {data: {id: evt.id, pubkey: evt.pubkey, relay}});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const renderRecommendServer = (evt: Event, relay: string) => {
|
||||||
|
const {img, name, time, userName} = getMetadata(evt, relay);
|
||||||
|
const body = elem('div', {className: 'mbox-body', title: dateTime.format(time)}, [
|
||||||
|
elem('header', {className: 'mbox-header'}, [
|
||||||
|
elem('small', {}, [
|
||||||
|
elem('strong', {}, userName)
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
` recommends server: ${evt.content}`,
|
||||||
|
]);
|
||||||
|
return elemArticle([
|
||||||
|
elem('div', {className: 'mbox-img'}, [img]), body
|
||||||
|
], {className: 'mbox-recommend-server', data: {id: evt.id, pubkey: evt.pubkey}});
|
||||||
|
};
|
Loading…
Reference in New Issue