Compare commits
12 Commits
be7ea41d03
...
ae579cbec3
Author | SHA1 | Date | |
---|---|---|---|
|
ae579cbec3 | ||
|
a5af2538c6 | ||
|
d46ae03598 | ||
|
e63609a7c1 | ||
|
404cb0aaa7 | ||
|
d9213da268 | ||
|
12d2e99576 | ||
|
88eea9ca94 | ||
|
df65104c60 | ||
|
2018cc1f0b | ||
|
7c68eafa56 | ||
|
85a8fc5dcd |
@ -370,6 +370,7 @@ export default {
|
||||
${relationClause(type)}
|
||||
${whereClause(
|
||||
'"Item".created_at <= $1',
|
||||
'"Item"."deletedAt" IS NULL',
|
||||
subClause(sub, 4, subClauseTable(type), me, showNsfw),
|
||||
activeOrMine(me),
|
||||
await filterClause(me, models, type),
|
||||
@ -449,6 +450,7 @@ export default {
|
||||
FROM "Item"
|
||||
${whereClause(
|
||||
'"parentId" IS NULL',
|
||||
'"Item"."deletedAt" IS NULL',
|
||||
'created_at <= $1',
|
||||
'"pinId" IS NULL',
|
||||
subClause(sub, 4),
|
||||
@ -474,6 +476,7 @@ export default {
|
||||
sub ? '"Item"."pinId" IS NULL' : '',
|
||||
'"Item"."deletedAt" IS NULL',
|
||||
'"Item"."parentId" IS NULL',
|
||||
'"Item".outlawed = false',
|
||||
'"Item".bio = false',
|
||||
activeOrMine(me),
|
||||
subClause(sub, 3, 'Item', me, showNsfw),
|
||||
|
@ -124,3 +124,6 @@ riccardobl,pr,#1293,#1142,medium,high,,,500k,rblb@getalby.com,2024-08-18
|
||||
tsmith123,pr,#1306,#832,medium,,,,250k,stickymarch60@walletofsatoshi.com,2024-08-20
|
||||
riccardobl,pr,#1311,#864,medium,high,,pending unrelated refactor,500k,rblb@getalby.com,2024-08-27
|
||||
brugeman,issue,#1311,#864,medium,high,,,50k,brugeman@stacker.news,2024-08-27
|
||||
riccardobl,pr,#1342,#1141,hard,high,,pending unrelated rearchitecture,1m,rblb@getalby.com,2024-09-09
|
||||
SatsAllDay,issue,#1368,#1331,medium,,,,25k,weareallsatoshi@getalby.com,2024-09-16
|
||||
benalleng,helpfulness,#1368,#1170,medium,,,did a lot of it in #1175,25k,BenAllenG@stacker.news,2024-09-16
|
||||
|
|
@ -14,7 +14,7 @@ export default function Hat ({ user, badge, className = 'ms-1', height = 16, wid
|
||||
{badge
|
||||
? (
|
||||
<Badge bg='grey-medium' className='ms-2 d-inline-flex align-items-center'>
|
||||
<AnonIcon className={`${className} align-middle`} height={height} width={width} />
|
||||
<AnonIcon className={`${className} fill-dark align-middle`} height={height} width={width} />
|
||||
</Badge>)
|
||||
: <span><AnonIcon className={`${className} align-middle`} height={height} width={width} /></span>}
|
||||
</HatTooltip>
|
||||
@ -34,7 +34,7 @@ export default function Hat ({ user, badge, className = 'ms-1', height = 16, wid
|
||||
{badge
|
||||
? (
|
||||
<Badge bg='grey-medium' className='ms-2 d-inline-flex align-items-center'>
|
||||
<CowboyHatIcon className={className} height={height} width={width} />
|
||||
<CowboyHatIcon className={`${className} fill-dark`} height={height} width={width} />
|
||||
<span className='ms-1 text-dark'>{streak || 'new'}</span>
|
||||
</Badge>)
|
||||
: <span><CowboyHatIcon className={className} height={height} width={width} /></span>}
|
||||
|
@ -23,6 +23,7 @@ import { decodeProxyUrl, IMGPROXY_URL_REGEXP } from '@/lib/url'
|
||||
import { numWithUnits } from '@/lib/format'
|
||||
import { useQuoteReply } from './use-quote-reply'
|
||||
import { UNKNOWN_LINK_REL } from '@/lib/constants'
|
||||
import classNames from 'classnames'
|
||||
|
||||
function BioItem ({ item, handleClick }) {
|
||||
const { me } = useMe()
|
||||
@ -89,7 +90,7 @@ function TopLevelItem ({ item, noReply, ...props }) {
|
||||
belowTitle={item.forwards && item.forwards.length > 0 && <FwdUsers forwards={item.forwards} />}
|
||||
{...props}
|
||||
>
|
||||
<article className={styles.fullItemContainer} ref={textRef}>
|
||||
<article className={classNames(styles.fullItemContainer, 'topLevel')} ref={textRef}>
|
||||
{item.text && <ItemText item={item} />}
|
||||
{item.url && !item.outlawed && <ItemEmbed url={item.url} imgproxyUrls={item.imgproxyUrls} />}
|
||||
{item.poll && <Poll item={item} />}
|
||||
|
@ -93,8 +93,7 @@ export default function MediaOrLink ({ linkFallback = true, ...props }) {
|
||||
if (media.embed) {
|
||||
return (
|
||||
<Embed
|
||||
{...media.embed} src={media.src}
|
||||
className={media.className} onError={handleError} topLevel={props.topLevel}
|
||||
{...media.embed} topLevel={props.topLevel} src={media.src} onError={handleError}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@ -123,19 +122,15 @@ export const useMediaHelper = ({ src, srcSet: srcSetIntital, topLevel, tab }) =>
|
||||
// make sure it's not a false negative by trying to load URL as <img>
|
||||
const img = new window.Image()
|
||||
img.onload = () => setIsImage(true)
|
||||
img.onerror = () => setIsImage(false)
|
||||
img.src = src
|
||||
const video = document.createElement('video')
|
||||
video.onloadeddata = () => setIsVideo(true)
|
||||
video.onerror = () => setIsVideo(false)
|
||||
video.src = src
|
||||
|
||||
return () => {
|
||||
img.onload = null
|
||||
img.onerror = null
|
||||
img.src = ''
|
||||
video.onloadeddata = null
|
||||
video.onerror = null
|
||||
video.src = ''
|
||||
}
|
||||
}, [src, setIsImage, setIsVideo, showMedia, isVideo, embed])
|
||||
@ -187,7 +182,6 @@ export const useMediaHelper = ({ src, srcSet: srcSetIntital, topLevel, tab }) =>
|
||||
style,
|
||||
width,
|
||||
height,
|
||||
className: classNames(topLevel && styles.topLevel),
|
||||
image: (!me?.privates?.imgproxyOnly || trusted) && showMedia && isImage && !isVideo && !embed,
|
||||
video: !me?.privates?.imgproxyOnly && showMedia && isVideo && !embed,
|
||||
embed: !me?.privates?.imgproxyOnly && showMedia && embed
|
||||
|
@ -5,7 +5,7 @@ import TocIcon from '@/svgs/list-unordered.svg'
|
||||
import { fromMarkdown } from 'mdast-util-from-markdown'
|
||||
import { visit } from 'unist-util-visit'
|
||||
import { toString } from 'mdast-util-to-string'
|
||||
import GithubSlugger from 'github-slugger'
|
||||
import { slug } from 'github-slugger'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
export default function Toc ({ text }) {
|
||||
@ -17,11 +17,11 @@ export default function Toc ({ text }) {
|
||||
const toc = useMemo(() => {
|
||||
const tree = fromMarkdown(text)
|
||||
const toc = []
|
||||
const slugger = new GithubSlugger()
|
||||
visit(tree, 'heading', (node, position, parent) => {
|
||||
const str = toString(node)
|
||||
toc.push({ heading: str, slug: slugger.slug(str.replace(/[^\w\-\s]+/gi, '')), depth: node.depth })
|
||||
toc.push({ heading: str, slug: slug(str.replace(/[^\w\-\s]+/gi, '')), depth: node.depth })
|
||||
})
|
||||
|
||||
return toc
|
||||
}, [text])
|
||||
|
||||
|
@ -6,7 +6,7 @@ import atomDark from 'react-syntax-highlighter/dist/cjs/styles/prism/atom-dark'
|
||||
import mention from '@/lib/remark-mention'
|
||||
import sub from '@/lib/remark-sub'
|
||||
import React, { useState, memo, useRef, useCallback, useMemo, useEffect } from 'react'
|
||||
import GithubSlugger from 'github-slugger'
|
||||
import { slug } from 'github-slugger'
|
||||
import LinkIcon from '@/svgs/link.svg'
|
||||
import Thumb from '@/svgs/thumb-up-fill.svg'
|
||||
import { toString } from 'mdast-util-to-string'
|
||||
@ -82,12 +82,10 @@ export default memo(function Text ({ rel, imgproxyUrls, children, tab, itemId, o
|
||||
}
|
||||
}, [containerRef.current, setOverflowing])
|
||||
|
||||
const slugger = useMemo(() => new GithubSlugger(), [])
|
||||
|
||||
const Heading = useCallback(({ children, node, ...props }) => {
|
||||
const [copied, setCopied] = useState(false)
|
||||
const nodeText = toString(node)
|
||||
const id = useMemo(() => noFragments ? undefined : slugger?.slug(nodeText.replace(/[^\w\-\s]+/gi, '')), [nodeText, noFragments, slugger])
|
||||
const id = useMemo(() => noFragments ? undefined : slug(nodeText.replace(/[^\w\-\s]+/gi, '')), [nodeText, noFragments])
|
||||
const h = useMemo(() => {
|
||||
if (topLevel) {
|
||||
return node?.TagName
|
||||
@ -120,7 +118,7 @@ export default memo(function Text ({ rel, imgproxyUrls, children, tab, itemId, o
|
||||
</a>}
|
||||
</span>
|
||||
)
|
||||
}, [topLevel, noFragments, slugger])
|
||||
}, [topLevel, noFragments])
|
||||
|
||||
const Table = useCallback(({ node, ...props }) =>
|
||||
<span className='table-responsive'>
|
||||
|
@ -6,6 +6,7 @@
|
||||
overflow-y: hidden;
|
||||
position: relative;
|
||||
max-height: 200vh;
|
||||
--grid-gap: 0.5rem;
|
||||
}
|
||||
|
||||
|
||||
@ -98,45 +99,75 @@
|
||||
}
|
||||
|
||||
.text hr {
|
||||
border-top: 1px solid var(--theme-clickToContextColor);
|
||||
border-top: 3px solid var(--theme-quoteBar);
|
||||
}
|
||||
|
||||
.text.topLevel {
|
||||
--grid-gap: 0.75rem;
|
||||
}
|
||||
|
||||
.text .p {
|
||||
display: block;
|
||||
margin-bottom: .5rem;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
--grid-gap: 0.5rem;
|
||||
padding-top: .25rem;
|
||||
padding-bottom: .25rem;
|
||||
}
|
||||
|
||||
.text.topLevel .p {
|
||||
margin-bottom: 0.75rem;
|
||||
--grid-gap: 0.75rem;
|
||||
padding-top: .375rem;
|
||||
padding-bottom: .375rem;
|
||||
}
|
||||
|
||||
.text pre {
|
||||
margin-bottom: .5rem;
|
||||
.text>*:not(.heading) {
|
||||
padding-top: .25rem;
|
||||
padding-bottom: .25rem;
|
||||
}
|
||||
|
||||
.text.topLevel>*:not(.heading) {
|
||||
padding-top: .375rem;
|
||||
padding-bottom: .375rem;
|
||||
}
|
||||
|
||||
.text pre, .text blockquote {
|
||||
margin-top: .25rem;
|
||||
margin-bottom: .25rem;
|
||||
}
|
||||
|
||||
.text.topLevel pre, .text.topLevel blockquote {
|
||||
margin-top: .375rem;
|
||||
margin-bottom: .375rem;
|
||||
}
|
||||
|
||||
.text pre>div {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.text>*:last-child {
|
||||
.text>*:last-child:not(.textShowFull) {
|
||||
padding-bottom: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.text blockquote:last-child {
|
||||
margin-bottom: 0 !important;
|
||||
.text>*:first-child {
|
||||
padding-top: 0 !important;
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.text blockquote:has(+ :not(blockquote)) {
|
||||
margin-bottom: .5rem;
|
||||
.text blockquote, .text.topLevel blockquote {
|
||||
padding-top: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.text blockquote *:first-child, .text.topLevel blockquote *:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.text blockquote *:last-child, .text.topLevel blockquote *:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.mediaContainer {
|
||||
display: block;
|
||||
margin-bottom: .5rem;
|
||||
width: calc(100% - var(--grid-gap));
|
||||
max-width: calc(100% - var(--grid-gap));
|
||||
height: auto;
|
||||
@ -147,44 +178,40 @@
|
||||
|
||||
.p:has(> .mediaContainer) {
|
||||
white-space: normal;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.p:has(> .mediaContainer:only-child) ~ .p:has(> .mediaContainer:only-child) {
|
||||
display: inline-block;
|
||||
width: min-content;
|
||||
max-width: calc(100% - var(--grid-gap));
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.mediaContainer ~ .mediaContainer {
|
||||
display: inline-block;
|
||||
width: min-content;
|
||||
margin-right: var(--grid-gap);
|
||||
}
|
||||
|
||||
.p:has(> .mediaContainer:only-child) ~ .p:has(> .mediaContainer:only-child) > .mediaContainer:only-child {
|
||||
margin-right: var(--grid-gap);
|
||||
}
|
||||
|
||||
.p:has(> .mediaContainer:only-child) ~ .p:has(> .mediaContainer:only-child),
|
||||
.p:has(> .mediaContainer:only-child):has(+ .p > .mediaContainer:only-child) {
|
||||
display: inline-block;
|
||||
width: min-content;
|
||||
max-width: calc(100% - var(--grid-gap));
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.p:has(> .mediaContainer:only-child):has(+ .p > .mediaContainer:only-child) > .mediaContainer:only-child {
|
||||
margin-right: var(--grid-gap);
|
||||
}
|
||||
|
||||
.mediaContainer:has(+ .mediaContainer) {
|
||||
.mediaContainer ~ .mediaContainer, .mediaContainer:has(+ .mediaContainer) {
|
||||
display: inline-block;
|
||||
width: min-content;
|
||||
margin-right: var(--grid-gap);
|
||||
}
|
||||
|
||||
.mediaContainer:first-child:has(+ .mediaContainer) {
|
||||
margin-top: var(--grid-gap);
|
||||
.p:has(> .mediaContainer:only-child) ~ .p:has(> .mediaContainer:only-child) > .mediaContainer:only-child,
|
||||
.p:has(> .mediaContainer:only-child):has(+ .p > .mediaContainer:only-child) > .mediaContainer:only-child,
|
||||
.mediaContainer:first-child:has(+ .mediaContainer) {
|
||||
margin-right: var(--grid-gap);
|
||||
}
|
||||
|
||||
.p:has(> .mediaContainer:only-child) ~ .p:has(> .mediaContainer:only-child) > .mediaContainer:only-child img,
|
||||
.p:has(> .mediaContainer:only-child):has(+ .p > .mediaContainer:only-child) > .mediaContainer:only-child img,
|
||||
.mediaContainer ~ .mediaContainer img,
|
||||
.mediaContainer:has(+ .mediaContainer) img {
|
||||
block-size: revert-layer;
|
||||
max-width: stretch;
|
||||
}
|
||||
.p:has(> .mediaContainer:only-child) ~ .p:has(> .mediaContainer:only-child) > .mediaContainer:only-child video,
|
||||
.p:has(> .mediaContainer:only-child):has(+ .p > .mediaContainer:only-child) > .mediaContainer:only-child video,
|
||||
.mediaContainer ~ .mediaContainer video,
|
||||
.mediaContainer:has(+ .mediaContainer) video {
|
||||
block-size: stretch;
|
||||
}
|
||||
|
||||
.mediaContainer img, .mediaContainer video {
|
||||
@ -194,7 +221,6 @@
|
||||
max-height: inherit;
|
||||
height: 100%;
|
||||
aspect-ratio: var(--aspect-ratio);
|
||||
block-size: stretch;
|
||||
}
|
||||
|
||||
.mediaContainer img {
|
||||
@ -203,8 +229,7 @@
|
||||
object-position: left top;
|
||||
}
|
||||
|
||||
.mediaContainer.topLevel {
|
||||
margin-bottom: .75rem;
|
||||
.topLevel .mediaContainer, :global(.topLevel) .mediaContainer {
|
||||
max-height: 35vh;
|
||||
}
|
||||
|
||||
@ -233,9 +258,8 @@ img.fullScreen {
|
||||
}
|
||||
|
||||
.text blockquote {
|
||||
border-left: 2px solid var(--theme-quoteBar);
|
||||
border-left: 3px solid var(--theme-quoteBar);
|
||||
padding-left: .75rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.text li {
|
||||
@ -245,19 +269,10 @@ img.fullScreen {
|
||||
.text ul,
|
||||
.text ol {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
margin-bottom: 0rem;
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
.text ul:last-child, .text ol:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.text li > .p {
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.text ol ol,
|
||||
.text ul ol {
|
||||
list-style-type: lower-roman;
|
||||
@ -270,6 +285,11 @@ img.fullScreen {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
|
||||
.text h1, .text h2, .text h3, .text h4, .text h5, .text h6 {
|
||||
margin-top: 0.75rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.text h1 {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
@ -306,12 +326,24 @@ img.fullScreen {
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.videoWrapper {
|
||||
max-width: 320px;
|
||||
margin: 0.5rem 0;
|
||||
.twitterContainer, .nostrContainer, .videoWrapper, .wavlakeWrapper, .spotifyWrapper, .mediaContainer {
|
||||
margin-top: 0.25rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.videoWrapper.topLevel {
|
||||
.topLevel .twitterContainer, .topLevel .nostrContainer, .topLevel .videoWrapper,
|
||||
.topLevel .wavlakeWrapper, .topLevel .spotifyWrapper, .topLevel .mediaContainer,
|
||||
:global(.topLevel) .twitterContainer, :global(.topLevel) .nostrContainer, :global(.topLevel) .videoWrapper,
|
||||
:global(.topLevel) .wavlakeWrapper, :global(.topLevel) .spotifyWrapper, :global(.topLevel) .mediaContainer {
|
||||
margin-top: 0.375rem;
|
||||
margin-bottom: 0.375rem;
|
||||
}
|
||||
|
||||
.videoWrapper {
|
||||
max-width: 320px;
|
||||
}
|
||||
|
||||
.topLevel .videoWrapper, :global(.topLevel) .videoWrapper {
|
||||
max-width: 640px;
|
||||
margin: 0.75rem 0;
|
||||
}
|
||||
@ -333,15 +365,10 @@ img.fullScreen {
|
||||
}
|
||||
|
||||
.twitterContainer, .nostrContainer {
|
||||
margin-top: .25rem;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.twitterContainer:not(:first-child), .nostrContainer:not(:first-child) {
|
||||
margin-top: .75rem;
|
||||
}
|
||||
|
||||
.twitterContainer iframe, .nostrContainer iframe {
|
||||
border-radius: 13px;
|
||||
}
|
||||
@ -359,7 +386,7 @@ img.fullScreen {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.twitterContained.topLevel {
|
||||
.topLevel .twitterContained, :global(.topLevel) .twitterContained {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
@ -380,7 +407,7 @@ img.fullScreen {
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.tweetsSkeleton.topLevel {
|
||||
.topLevel .tweetsSkeleton, :global(.topLevel) .tweetsSkeleton {
|
||||
max-width: 550px;
|
||||
}
|
||||
|
||||
@ -395,7 +422,7 @@ img.fullScreen {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.topLevel .tweetSkeleton {
|
||||
.topLevel .tweetSkeleton, :global(.topLevel) .tweetSkeleton {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ async function bountyWinner (q) {
|
||||
|
||||
const bounty = await client.query({
|
||||
query: SEARCH,
|
||||
variables: { q: `${q} @grayruby`, sort: 'recent', what: 'posts', when: 'week' }
|
||||
variables: { q: `${q} @sn`, sort: 'recent', what: 'posts', when: 'week' }
|
||||
})
|
||||
|
||||
const items = bounty.data.search.items.filter(i => i.bountyPaidTo?.length > 0)
|
||||
|
@ -784,6 +784,10 @@ div[contenteditable]:focus,
|
||||
fill: white;
|
||||
}
|
||||
|
||||
.fill-dark {
|
||||
fill: #212529;
|
||||
}
|
||||
|
||||
.fill-success {
|
||||
fill: var(--bs-success);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user