mirror of
https://github.com/PrimalHQ/primal-web-app.git
synced 2024-09-29 00:10:50 +00:00
Compare commits
7 Commits
5b918336f4
...
16c7c1c650
Author | SHA1 | Date | |
---|---|---|---|
|
16c7c1c650 | ||
|
236909abb2 | ||
|
07b071bd61 | ||
|
d798c2cc70 | ||
|
09a0b0cc85 | ||
|
3dc1a9ddda | ||
|
4df8b8f57f |
@ -1,7 +1,7 @@
|
||||
import { useIntl } from '@cookbook/solid-intl';
|
||||
import { Component, createEffect, createSignal, Match, Show, Switch } from 'solid-js';
|
||||
import { APP_ID } from '../../App';
|
||||
import { Kind } from '../../constants';
|
||||
import { Kind, supportedBookmarkTypes } from '../../constants';
|
||||
import { useAccountContext } from '../../contexts/AccountContext';
|
||||
import { useAppContext } from '../../contexts/AppContext';
|
||||
import { getUserFeed } from '../../lib/feed';
|
||||
@ -24,12 +24,12 @@ const BookmarkArticle: Component<{ note: PrimalArticle | undefined, large?: bool
|
||||
const [isBookmarked, setIsBookmarked] = createSignal(false);
|
||||
const [bookmarkInProgress, setBookmarkInProgress] = createSignal(false);
|
||||
|
||||
|
||||
createEffect(() => {
|
||||
const note = props.note;
|
||||
|
||||
if (note) {
|
||||
setIsBookmarked(() => account?.bookmarks.includes(note.id) || false);
|
||||
const coor = `${note.msg.kind}:${note.pubkey}:${(note.msg.tags.find(t => t[0] === 'd') || [])[1]}`;
|
||||
setIsBookmarked(() => account?.bookmarks.includes(coor) || false);
|
||||
}
|
||||
})
|
||||
|
||||
@ -37,7 +37,7 @@ const BookmarkArticle: Component<{ note: PrimalArticle | undefined, large?: bool
|
||||
if (!account) return;
|
||||
|
||||
const bookmarks = bookmarkTags.reduce((acc, t) =>
|
||||
t[0] === 'e' ? [...acc, t[1]] : [...acc]
|
||||
supportedBookmarkTypes.includes(t[0]) ? [...acc, t[1]] : [...acc]
|
||||
, []);
|
||||
|
||||
const date = Math.floor((new Date()).getTime() / 1000);
|
||||
@ -52,8 +52,12 @@ const BookmarkArticle: Component<{ note: PrimalArticle | undefined, large?: bool
|
||||
};
|
||||
|
||||
const addBookmark = async (bookmarkTags: string[][]) => {
|
||||
if (account && props.note && !bookmarkTags.find(b => b[0] === 'e' && b[1] === props.note?.id)) {
|
||||
const bookmarksToAdd = [...bookmarkTags, ['e', props.note.id]];
|
||||
if (!account || !props.note) return;
|
||||
|
||||
const aTag = ['a', `${props.note.msg.kind}:${props.note.pubkey}:${(props.note.msg.tags.find(t => t[0] === 'd') || [])[1]}`];
|
||||
|
||||
if (!bookmarkTags.find(b => b[0] === aTag[0] && b[1] === aTag[1])) {
|
||||
const bookmarksToAdd = [...bookmarkTags, [ ...aTag ]];
|
||||
|
||||
if (bookmarksToAdd.length < 2) {
|
||||
logWarning('BOOKMARK ISSUE: ', `before_bookmark_${APP_ID}`);
|
||||
@ -78,8 +82,12 @@ const BookmarkArticle: Component<{ note: PrimalArticle | undefined, large?: bool
|
||||
}
|
||||
|
||||
const removeBookmark = async (bookmarks: string[][]) => {
|
||||
if (account && bookmarks.find(b => b[0] === 'e' && b[1] === props.note?.id)) {
|
||||
const bookmarksToAdd = bookmarks.filter(b => b[0] !== 'e' || b[1] !== props.note?.id);
|
||||
if (!account || !props.note) return;
|
||||
|
||||
const aTag = ['a', `${props.note.msg.kind}:${props.note.pubkey}:${(props.note.msg.tags.find(t => t[0] === 'd') || [])[1]}`];
|
||||
|
||||
if (bookmarks.find(b => b[0] === aTag[0] && b[1] === aTag[1])) {
|
||||
const bookmarksToAdd = bookmarks.filter(b => b[0] !== aTag[0] || b[1] !== aTag[1]);
|
||||
|
||||
if (bookmarksToAdd.length < 1) {
|
||||
logWarning('BOOKMARK ISSUE: ', `before_bookmark_${APP_ID}`);
|
||||
|
@ -102,7 +102,7 @@
|
||||
.articleSidebar {
|
||||
.section {
|
||||
margin-bottom: 28px;
|
||||
max-height: 526px;
|
||||
max-height: calc(100vh - 240px);
|
||||
overflow-y: scroll;
|
||||
|
||||
/* Hide scrollbar for Chrome, Safari and Opera */
|
||||
|
@ -6,6 +6,19 @@
|
||||
grid-template-columns: var(--left-col-w) var(--center-col-w) var(--right-col-w);
|
||||
}
|
||||
|
||||
.containerLF {
|
||||
--center-col-w: 680px;
|
||||
--right-col-w: 308px;
|
||||
--search-input-width: 260px;
|
||||
--central-content-width: 680px;
|
||||
|
||||
width: var(--full-site-w);
|
||||
margin: 0px auto;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: var(--left-col-w) var(--center-col-w) var(--right-col-w);
|
||||
}
|
||||
|
||||
.containerIOS {
|
||||
z-index: 1;
|
||||
margin-top: 54px;
|
||||
|
@ -97,6 +97,14 @@ const Layout: Component = () => {
|
||||
account?.actions.checkNostrKey();
|
||||
});
|
||||
|
||||
const containerClass = () => {
|
||||
if (isIOS() && showBanner()) return styles.containerIOS;
|
||||
|
||||
if (location.pathname.startsWith('/e/naddr')) return styles.containerLF;
|
||||
|
||||
return styles.container;
|
||||
}
|
||||
|
||||
return (
|
||||
<Show
|
||||
when={location.pathname !== '/'}
|
||||
@ -119,7 +127,7 @@ const Layout: Component = () => {
|
||||
</div>
|
||||
<div id="modal" class={styles.modal}></div>
|
||||
<BannerIOS />
|
||||
<div id="container" ref={container} class={isIOS() && showBanner() ? styles.containerIOS : styles.container}>
|
||||
<div id="container" ref={container} class={containerClass()}>
|
||||
<div class={styles.leftColumn}>
|
||||
<div>
|
||||
<div id="branding_holder" class={styles.leftHeader}>
|
||||
|
@ -547,6 +547,44 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.doZaps {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding-inline: 10px;
|
||||
padding-block: 2px;
|
||||
margin: 0;
|
||||
border-radius: 12px;
|
||||
background: var(--text-primary);
|
||||
width: fit-content;
|
||||
min-height: 26px;
|
||||
max-width: 100%;
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
|
||||
.zapIcon {
|
||||
width: 10px;
|
||||
height: 12px;
|
||||
background-color: var(--devider);
|
||||
-webkit-mask: url(../../assets/icons/feed_zap_fill_2.svg) no-repeat 0 / 100%;
|
||||
mask: url(../../assets/icons/feed_zap_fill_2.svg) no-repeat 0 / 100%;
|
||||
}
|
||||
|
||||
.zapText {
|
||||
color: var(--devider);
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
line-height: 12px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--text-secondary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.zapHighlightsCompact {
|
||||
|
@ -52,6 +52,7 @@ const Note: Component<{
|
||||
noteType?: 'feed' | 'primary' | 'notification' | 'reaction' | 'thread'
|
||||
onClick?: () => void,
|
||||
quoteCount?: number,
|
||||
size?: 'xwide' | 'wide' | 'normal' | 'short',
|
||||
}> = (props) => {
|
||||
|
||||
const threadContext = useThreadContext();
|
||||
@ -262,6 +263,8 @@ const Note: Component<{
|
||||
updateReactionsState('topZaps', () => [ ...(threadContext?.topZaps[props.note.post.id] || []) ]);
|
||||
});
|
||||
|
||||
const size = () => props.size ?? 'normal';
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
<Match when={noteType() === 'notification'}>
|
||||
@ -421,6 +424,7 @@ const Note: Component<{
|
||||
updateState={updateReactionsState}
|
||||
customZapInfo={customZapInfo()}
|
||||
onZapAnim={addTopZapFeed}
|
||||
size={size()}
|
||||
/>
|
||||
</A>
|
||||
</Match>
|
||||
|
@ -28,7 +28,7 @@ export const lottieDuration = () => zapMD.op * 1_000 / zapMD.fr;
|
||||
|
||||
const ArticleFooter: Component<{
|
||||
note: PrimalArticle,
|
||||
size?: 'wide' | 'normal' | 'short',
|
||||
size?: 'xwide' | 'wide' | 'normal' | 'short',
|
||||
id?: string,
|
||||
state: NoteReactionsState,
|
||||
updateState: SetStoreFunction<NoteReactionsState>,
|
||||
@ -228,6 +228,11 @@ const ArticleFooter: Component<{
|
||||
let newLeft = 33;
|
||||
let newTop = -6;
|
||||
|
||||
if (size() === 'xwide') {
|
||||
newLeft = 46;
|
||||
newTop = -7;
|
||||
}
|
||||
|
||||
if (size() === 'wide' && props.large) {
|
||||
newLeft = 14;
|
||||
newTop = -10;
|
||||
@ -238,6 +243,8 @@ const ArticleFooter: Component<{
|
||||
newTop = -6;
|
||||
}
|
||||
|
||||
console.log('SIZE: ', newLeft);
|
||||
|
||||
medZapAnimation.style.left = `${newLeft}px`;
|
||||
medZapAnimation.style.top = `${newTop}px`;
|
||||
|
||||
|
@ -65,6 +65,16 @@
|
||||
max-width: 20px;
|
||||
}
|
||||
|
||||
&.xwide {
|
||||
grid-template-columns: 153px 153px 153px 153px auto;
|
||||
|
||||
.bookmarkFoot {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&.wide {
|
||||
grid-template-columns: 148px 148px 148px 148px auto;
|
||||
|
||||
|
@ -27,7 +27,7 @@ export const lottieDuration = () => zapMD.op * 1_000 / zapMD.fr;
|
||||
|
||||
const NoteFooter: Component<{
|
||||
note: PrimalNote,
|
||||
size?: 'wide' | 'normal' | 'short',
|
||||
size?: 'xwide' | 'wide' | 'normal' | 'short',
|
||||
id?: string,
|
||||
state: NoteReactionsState,
|
||||
updateState: SetStoreFunction<NoteReactionsState>,
|
||||
@ -228,6 +228,11 @@ const NoteFooter: Component<{
|
||||
let newLeft = 33;
|
||||
let newTop = -6;
|
||||
|
||||
if (size() === 'xwide') {
|
||||
newLeft = 46;
|
||||
newTop = -7;
|
||||
}
|
||||
|
||||
if (size() === 'wide' && props.large) {
|
||||
newLeft = 14;
|
||||
newTop = -10;
|
||||
|
@ -11,7 +11,8 @@ const NoteTopZaps: Component<{
|
||||
zapCount: number,
|
||||
action: () => void,
|
||||
id?: string,
|
||||
users?: PrimalUser[]
|
||||
users?: PrimalUser[],
|
||||
doZap?: () => void,
|
||||
}> = (props) => {
|
||||
|
||||
const threadContext = useThreadContext();
|
||||
@ -45,8 +46,8 @@ const NoteTopZaps: Component<{
|
||||
const zapSender = (zap: TopZap) => {
|
||||
return (props.users || threadContext?.users || []).find(u => u.pubkey === zap.pubkey);
|
||||
};
|
||||
return (
|
||||
|
||||
return (
|
||||
<Show
|
||||
when={!threadContext?.isFetchingTopZaps}
|
||||
fallback={
|
||||
@ -64,49 +65,59 @@ const NoteTopZaps: Component<{
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div class={`${styles.zapHighlights}`}>
|
||||
<TransitionGroup
|
||||
name="top-zaps"
|
||||
enterClass={styles.topZapEnterTransition}
|
||||
exitClass={styles.topZapExitTransition}
|
||||
>
|
||||
<For each={topZaps()}>
|
||||
{(zap, index) => (
|
||||
<>
|
||||
<button
|
||||
class={`${styles.topZap}`}
|
||||
onClick={() => props.action()}
|
||||
style={`z-index: ${12 - index()};`}
|
||||
>
|
||||
<Avatar user={zapSender(zap)} size="micro" />
|
||||
<div class={styles.amount}>
|
||||
{zap.amount.toLocaleString()}
|
||||
</div>
|
||||
<Show when={index() === 0}>
|
||||
<div class={styles.description}>
|
||||
{zap.message}
|
||||
<div class={`${styles.zapHighlights}`}>
|
||||
<TransitionGroup
|
||||
name="top-zaps"
|
||||
enterClass={styles.topZapEnterTransition}
|
||||
exitClass={styles.topZapExitTransition}
|
||||
>
|
||||
<For each={topZaps()}>
|
||||
{(zap, index) => (
|
||||
<>
|
||||
<button
|
||||
class={`${styles.topZap}`}
|
||||
onClick={() => props.action()}
|
||||
style={`z-index: ${12 - index()};`}
|
||||
>
|
||||
<Avatar user={zapSender(zap)} size="micro" />
|
||||
<div class={styles.amount}>
|
||||
{zap.amount.toLocaleString()}
|
||||
</div>
|
||||
<Show when={index() === 0}>
|
||||
<div class={styles.description}>
|
||||
{zap.message}
|
||||
</div>
|
||||
</Show>
|
||||
</button>
|
||||
|
||||
<Show when={index() === 0 && props.topZaps.length > 3}>
|
||||
<div class={styles.break}></div>
|
||||
</Show>
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</For>
|
||||
|
||||
<Show when={index() === 0 && props.topZaps.length > 3}>
|
||||
<div class={styles.break}></div>
|
||||
</Show>
|
||||
</>
|
||||
)}
|
||||
</For>
|
||||
<Show when={hasMoreZaps()}>
|
||||
<button
|
||||
class={styles.moreZaps}
|
||||
onClick={() => props.action()}
|
||||
>
|
||||
<div class={styles.contextIcon}></div>
|
||||
</button>
|
||||
</Show>
|
||||
|
||||
<Show when={hasMoreZaps()}>
|
||||
<button
|
||||
class={styles.moreZaps}
|
||||
onClick={() => props.action()}
|
||||
>
|
||||
<div class={styles.contextIcon}></div>
|
||||
</button>
|
||||
</Show>
|
||||
</TransitionGroup>
|
||||
</div>
|
||||
</Show>
|
||||
<Show when={props.doZap}>
|
||||
<button
|
||||
class={styles.doZaps}
|
||||
onClick={props.doZap}
|
||||
>
|
||||
<div class={styles.zapIcon}></div>
|
||||
<div class={styles.zapText}>Zap</div>
|
||||
</button>
|
||||
</Show>
|
||||
</TransitionGroup>
|
||||
</div>
|
||||
</Show>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -10,19 +10,19 @@
|
||||
margin-block: 8px;
|
||||
|
||||
p {
|
||||
color: var(--text-primary);
|
||||
color: var(--brand-text);
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
line-height: 28px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: var(--text-primary);
|
||||
color: var(--brand-text);
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
@ -95,10 +95,10 @@
|
||||
content: '•';
|
||||
}
|
||||
padding-left: 8px;
|
||||
color: var(--text-primary);
|
||||
color: var(--brand-text);
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
line-height: 28px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 12px;
|
||||
|
||||
@ -115,10 +115,10 @@
|
||||
|
||||
li {
|
||||
padding-left: 8px;
|
||||
color: var(--text-primary);
|
||||
color: var(--brand-text);
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
line-height: 28px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 12px;
|
||||
|
||||
@ -135,18 +135,18 @@
|
||||
margin-bottom: 20px;
|
||||
|
||||
dt {
|
||||
color: var(--text-primary);
|
||||
color: var(--brand-text);
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
dd {
|
||||
padding-left: 8px;
|
||||
color: var(--text-primary);
|
||||
color: var(--brand-text);
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
line-height: 28px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 12px;
|
||||
|
||||
@ -170,10 +170,10 @@
|
||||
|
||||
|
||||
blockquote {
|
||||
color: var(--text-primary);
|
||||
color: var(--brand-text);
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
line-height: 28px;
|
||||
padding-left: 12px;
|
||||
padding-bottom: 0;
|
||||
margin-top: 0;
|
||||
@ -189,7 +189,7 @@
|
||||
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
pre, code, mark {
|
||||
@ -197,12 +197,12 @@
|
||||
}
|
||||
|
||||
code {
|
||||
color: var(--text-primary);
|
||||
color: var(--brand-text);
|
||||
font-family: "Fira Mono", monospace;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
ins {
|
||||
@ -218,7 +218,7 @@
|
||||
color: var(--text-primary);
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
line-height: 24px;
|
||||
line-height: 28px;
|
||||
border-bottom: 1px solid var(--text-secondary);
|
||||
padding: 12px 8px;
|
||||
* {
|
||||
@ -230,10 +230,10 @@
|
||||
}
|
||||
|
||||
td {
|
||||
color: var(--text-primary);
|
||||
color: var(--brand-text);
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
line-height: 28px;
|
||||
border-bottom: 1px solid var(--subtile-devider);
|
||||
padding: 12px 8px;
|
||||
* {
|
||||
|
@ -90,6 +90,7 @@ const account = useAccountContext();
|
||||
return <NoteImage
|
||||
class={`noteimage image_${props.noteId}`}
|
||||
src={img.src}
|
||||
width={640}
|
||||
/>
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
align-items: center;
|
||||
border-radius: 18px;
|
||||
background-color: var(--background-header-input);
|
||||
width: 300px;
|
||||
width: var(--search-input-width);
|
||||
height: 36px;
|
||||
margin-left: 8px;
|
||||
margin-bottom: 0;
|
||||
@ -20,7 +20,7 @@
|
||||
}
|
||||
|
||||
input {
|
||||
width: 240px;
|
||||
width: calc(var(--search-input-width) - 60px);
|
||||
height: 36px;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
@ -70,7 +70,7 @@
|
||||
|
||||
.searchHolder {
|
||||
position: relative;
|
||||
width: 316px;
|
||||
width: calc(var(--search-input-width) + 16px);
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
border-radius: 12px;
|
||||
@ -82,7 +82,7 @@
|
||||
|
||||
.searchSuggestions {
|
||||
margin-top: 8px;
|
||||
width: 316px;
|
||||
width: calc(var(--search-input-width) + 16px);
|
||||
visibility: visible;
|
||||
|
||||
&.hidden {
|
||||
|
@ -35,7 +35,7 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
max-width: 166px;
|
||||
max-width: calc(var(--search-input-width) * 0.5);
|
||||
}
|
||||
|
||||
.userName {
|
||||
|
@ -409,3 +409,5 @@ export const emptyInvoice: LnbcInvoice = {
|
||||
expiry: 0,
|
||||
route_hints: [],
|
||||
};
|
||||
|
||||
export const supportedBookmarkTypes = ['a', 'e'];
|
||||
|
@ -23,7 +23,7 @@ import {
|
||||
NostrEventContent,
|
||||
PrimalArticle,
|
||||
} from '../types/primal';
|
||||
import { Kind, pinEncodePrefix, relayConnectingTimeout } from "../constants";
|
||||
import { Kind, pinEncodePrefix, relayConnectingTimeout, supportedBookmarkTypes } from "../constants";
|
||||
import { isConnected, refreshSocketListeners, removeSocketListeners, socket, subscribeTo, reset, subTo } from "../sockets";
|
||||
import { sendContacts, sendLike, sendMuteList, triggerImportEvents } from "../lib/notes";
|
||||
// @ts-ignore Bad types in nostr-tools
|
||||
@ -1531,7 +1531,7 @@ export function AccountProvider(props: { children: JSXElement }) {
|
||||
}
|
||||
|
||||
const notes = content.tags.reduce((acc, t) => {
|
||||
if (t[0] === 'e') {
|
||||
if (supportedBookmarkTypes.includes(t[0])) {
|
||||
return [...acc, t[1]];
|
||||
}
|
||||
return [...acc];
|
||||
|
@ -68,6 +68,8 @@
|
||||
--full-site-w: 1172px;
|
||||
--header-height: 84px;
|
||||
|
||||
--search-input-width: 300px;
|
||||
|
||||
background-color: var(--background-site);
|
||||
|
||||
.mentioned_user {
|
||||
|
@ -3,6 +3,7 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
height: 85px;
|
||||
border-bottom: 1px solid var(--devider);
|
||||
|
||||
a {
|
||||
@ -89,9 +90,9 @@
|
||||
|
||||
.title {
|
||||
color: var(--text-primary);
|
||||
font-size: 36px;
|
||||
font-size: 44px;
|
||||
font-weight: 700;
|
||||
line-height: 44px;
|
||||
line-height: 52px;
|
||||
}
|
||||
|
||||
.summary {
|
||||
@ -109,7 +110,7 @@
|
||||
color: var(--text-primary);
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
line-height: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,7 @@ import { fetchNotes } from "../handleNotes";
|
||||
import { Tier, TierCost } from "../components/SubscribeToAuthorModal/SubscribeToAuthorModal";
|
||||
import ButtonPrimary from "../components/Buttons/ButtonPrimary";
|
||||
import { zapSubscription } from "../lib/zap";
|
||||
import Paginator from "../components/Paginator/Paginator";
|
||||
|
||||
export type LongFormData = {
|
||||
title: string,
|
||||
@ -106,199 +107,6 @@ const emptyStore: LongformThreadStore = {
|
||||
hasTiers: false,
|
||||
}
|
||||
|
||||
const test = `
|
||||
# h1 Heading 8-)
|
||||
## h2 Heading
|
||||
### h3 Heading
|
||||
#### h4 Heading
|
||||
##### h5 Heading
|
||||
###### h6 Heading
|
||||
|
||||
## Mentions
|
||||
|
||||
nostr:npub19f2765hdx8u9lz777w7azed2wsn9mqkf2gvn67mkldx8dnxvggcsmhe9da
|
||||
|
||||
nostr:note1tv033d7y088x8e90n5ut8htlsyy4yuwsw2fpgywq62w8xf0qcv8q8xvvhg
|
||||
|
||||
|
||||
## Horizontal Rules
|
||||
|
||||
___
|
||||
|
||||
---
|
||||
|
||||
***
|
||||
|
||||
|
||||
## Typographic replacements
|
||||
|
||||
Enable typographer option to see result.
|
||||
|
||||
(c) (C) (r) (R) (tm) (TM) (p) (P) +-
|
||||
|
||||
test.. test... test..... test?..... test!....
|
||||
|
||||
!!!!!! ???? ,, -- ---
|
||||
|
||||
"Smartypants, double quotes" and 'single quotes'
|
||||
|
||||
|
||||
## Emphasis
|
||||
|
||||
**This is bold text**
|
||||
|
||||
__This is bold text__
|
||||
|
||||
*This is italic text*
|
||||
|
||||
_This is italic text_
|
||||
|
||||
~~Strikethrough~~
|
||||
|
||||
|
||||
## Blockquotes
|
||||
|
||||
|
||||
> Blockquotes can also be nested...
|
||||
>> ...by using additional greater-than signs right next to each other...
|
||||
> > > ...or with spaces between arrows.
|
||||
|
||||
|
||||
## Lists
|
||||
|
||||
Unordered
|
||||
|
||||
+ Create a list by starting a line with \`+\`, \`-\`, or \`*\`
|
||||
+ Sub-lists are made by indenting 2 spaces:
|
||||
- Marker character change forces new list start:
|
||||
* Ac tristique libero volutpat at
|
||||
+ Facilisis in pretium nisl aliquet
|
||||
- Nulla volutpat aliquam velit
|
||||
+ Very easy!
|
||||
|
||||
Ordered
|
||||
|
||||
1. Lorem ipsum dolor sit amet
|
||||
2. Consectetur adipiscing elit
|
||||
3. Integer molestie lorem at massa
|
||||
|
||||
|
||||
## Code
|
||||
|
||||
Inline \`code\`
|
||||
|
||||
Indented code
|
||||
|
||||
// Some comments
|
||||
line 1 of code
|
||||
line 2 of code
|
||||
line 3 of code
|
||||
|
||||
|
||||
Block code "fences"
|
||||
|
||||
\`\`\`
|
||||
Sample text here...
|
||||
\`\`\`
|
||||
|
||||
Syntax highlighting
|
||||
|
||||
\`\`\` js
|
||||
var foo = function (bar) {
|
||||
return bar++;
|
||||
};
|
||||
|
||||
console.log(foo(5));
|
||||
\`\`\`
|
||||
|
||||
## Tables
|
||||
|
||||
| Option | Description |
|
||||
| ------ | ----------- |
|
||||
| data | path to data files to supply the data that will be passed into templates. |
|
||||
| engine | engine to be used for processing templates. Handlebars is the default. |
|
||||
| ext | extension to be used for dest files. |
|
||||
|
||||
Right aligned columns
|
||||
|
||||
| Option | Description |
|
||||
| ------:| -----------:|
|
||||
| data | path to data files to supply the data that will be passed into templates. |
|
||||
| engine | engine to be used for processing templates. Handlebars is the default. |
|
||||
| ext | extension to be used for dest files. |
|
||||
|
||||
|
||||
## Links
|
||||
|
||||
[link text](http://dev.nodeca.com)
|
||||
|
||||
[link with title](http://nodeca.github.io/pica/demo/ "title text!")
|
||||
|
||||
Autoconverted link https://github.com/nodeca/pica (enable linkify to see)
|
||||
|
||||
|
||||
## Images
|
||||
|
||||
![Minion](https://octodex.github.com/images/minion.png)
|
||||
![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat")[^image]
|
||||
|
||||
Like links, Images also have a footnote style syntax
|
||||
|
||||
With a reference later in the document defining the URL location, like this:
|
||||
|
||||
[^image]: https://octodex.github.com/images/dojocat.jpg "The Dojocat"
|
||||
|
||||
|
||||
## Optionals (should we support them?)
|
||||
|
||||
### [Subscript](https://github.com/markdown-it/markdown-it-sub) / [Superscript](https://github.com/markdown-it/markdown-it-sup)
|
||||
|
||||
- 19^th^
|
||||
- H~2~O
|
||||
|
||||
|
||||
### [\<ins>](https://github.com/markdown-it/markdown-it-ins)
|
||||
|
||||
there is some ++Inserted text++ here
|
||||
|
||||
|
||||
### [\<mark>](https://github.com/markdown-it/markdown-it-mark)
|
||||
|
||||
==Marked text==
|
||||
|
||||
|
||||
### [Footnotes](https://github.com/markdown-it/markdown-it-footnote)
|
||||
|
||||
Footnote 1 link[^first].
|
||||
|
||||
Footnote 2 link[^second].
|
||||
|
||||
Duplicated footnote reference[^second].
|
||||
|
||||
[^first]: Footnote **can have markup**
|
||||
|
||||
and multiple paragraphs.
|
||||
|
||||
[^second]: Footnote text.
|
||||
|
||||
|
||||
### [Definition lists](https://github.com/markdown-it/markdown-it-deflist)
|
||||
|
||||
Term 1
|
||||
|
||||
: Definition 1
|
||||
with lazy continuation.
|
||||
|
||||
Term 2 with *inline markup*
|
||||
|
||||
: Definition 2
|
||||
|
||||
{ some code, part of Definition 2 }
|
||||
|
||||
Third paragraph of definition 2.
|
||||
|
||||
`;
|
||||
|
||||
const Longform: Component< { naddr: string } > = (props) => {
|
||||
const account = useAccountContext();
|
||||
const app = useAppContext();
|
||||
@ -320,15 +128,31 @@ const Longform: Component< { naddr: string } > = (props) => {
|
||||
let latestTopZapFeed: string = '';
|
||||
let articleContextMenu: HTMLDivElement | undefined;
|
||||
|
||||
createEffect(() => {
|
||||
const article = store.article;
|
||||
|
||||
if (!article) return;
|
||||
|
||||
const {
|
||||
likes,
|
||||
reposts,
|
||||
replies,
|
||||
zaps,
|
||||
satszapped,
|
||||
} = article;
|
||||
|
||||
updateReactionsState(() => ({ likes, reposts, replies, zapCount: zaps, satsZapped: satszapped }));
|
||||
})
|
||||
|
||||
const [reactionsState, updateReactionsState] = createStore<NoteReactionsState>({
|
||||
likes: 0,
|
||||
likes: store.article?.likes || 0,
|
||||
liked: false,
|
||||
reposts: 0,
|
||||
reposts: store.article?.reposts || 0,
|
||||
reposted: false,
|
||||
replies: 0,
|
||||
replies: store.article?.replies || 0,
|
||||
replied: false,
|
||||
zapCount: 0,
|
||||
satsZapped: 0,
|
||||
zapCount: store.article?.zaps || 0,
|
||||
satsZapped: store.article?.satszapped || 0,
|
||||
zapped: false,
|
||||
zappedAmount: 0,
|
||||
zappedNow: false,
|
||||
@ -844,6 +668,7 @@ const Longform: Component< { naddr: string } > = (props) => {
|
||||
updateStore('article', () => ({ ...article }));
|
||||
|
||||
updateStore('isFetching', () => false);
|
||||
|
||||
// saveNotes(replies);
|
||||
|
||||
// const a = users.find(u => u.pubkey === article.author);
|
||||
@ -909,7 +734,7 @@ const Longform: Component< { naddr: string } > = (props) => {
|
||||
<A href={`/p/${store.article?.user.npub}`}>
|
||||
<div class={styles.author}>
|
||||
<Show when={store.article?.user}>
|
||||
<Avatar user={store.article?.user} size="xs" />
|
||||
<Avatar user={store.article?.user} size="sm" />
|
||||
|
||||
<div class={styles.userInfo}>
|
||||
<div class={styles.userName}>
|
||||
@ -984,7 +809,8 @@ const Longform: Component< { naddr: string } > = (props) => {
|
||||
topZaps={store.article?.topZaps}
|
||||
zapCount={reactionsState.zapCount}
|
||||
users={store.users}
|
||||
action={() => {}}
|
||||
action={() => openReactionModal('zaps')}
|
||||
doZap={() => app?.actions.openCustomZapModal(customZapInfo())}
|
||||
/>
|
||||
|
||||
<PrimalMarkdown
|
||||
@ -1016,6 +842,7 @@ const Longform: Component< { naddr: string } > = (props) => {
|
||||
updateState={updateReactionsState}
|
||||
customZapInfo={customZapInfo()}
|
||||
onZapAnim={addTopZapFeed}
|
||||
size="xwide"
|
||||
/>
|
||||
</div>
|
||||
</Show>
|
||||
@ -1030,7 +857,7 @@ const Longform: Component< { naddr: string } > = (props) => {
|
||||
|
||||
<div>
|
||||
<For each={store.replies}>
|
||||
{reply => <Note note={reply} />}
|
||||
{reply => <Note note={reply} noteType='feed' size="xwide" />}
|
||||
</For>
|
||||
</div>
|
||||
</>);
|
||||
|
Loading…
Reference in New Issue
Block a user