Anchor revert
This commit is contained in:
parent
ae32a0c4e4
commit
dab4bcd41e
|
@ -90,7 +90,6 @@ export const FullArticle = (props: ArticleProps) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const commentsRef: { current: HTMLDivElement } = { current: null }
|
const commentsRef: { current: HTMLDivElement } = { current: null }
|
||||||
|
|
||||||
const scrollToComments = () => {
|
const scrollToComments = () => {
|
||||||
window.scrollTo({
|
window.scrollTo({
|
||||||
top: commentsRef.current.offsetTop - 96,
|
top: commentsRef.current.offsetTop - 96,
|
||||||
|
@ -98,12 +97,20 @@ export const FullArticle = (props: ArticleProps) => {
|
||||||
behavior: 'smooth'
|
behavior: 'smooth'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const { searchParams } = useRouter()
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
if (props.scrollToComments) {
|
if (props.scrollToComments) {
|
||||||
scrollToComments()
|
scrollToComments()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const { changeSearchParam } = useRouter()
|
||||||
|
createEffect(() => {
|
||||||
|
if (searchParams()?.scrollTo === 'comments' && commentsRef.current) {
|
||||||
|
scrollToComments()
|
||||||
|
changeSearchParam('scrollTo', null)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const {
|
const {
|
||||||
actions: { loadReactionsBy }
|
actions: { loadReactionsBy }
|
||||||
|
|
|
@ -12,6 +12,8 @@ import stylesHeader from '../Nav/Header.module.scss'
|
||||||
import { getDescription } from '../../utils/meta'
|
import { getDescription } from '../../utils/meta'
|
||||||
import { FeedArticlePopup } from './FeedArticlePopup'
|
import { FeedArticlePopup } from './FeedArticlePopup'
|
||||||
import { useLocalize } from '../../context/localize'
|
import { useLocalize } from '../../context/localize'
|
||||||
|
import { openPage } from '@nanostores/router'
|
||||||
|
import { router, useRouter } from '../../stores/router'
|
||||||
|
|
||||||
interface ArticleCardProps {
|
interface ArticleCardProps {
|
||||||
settings?: {
|
settings?: {
|
||||||
|
@ -35,6 +37,7 @@ interface ArticleCardProps {
|
||||||
isBeside?: boolean
|
isBeside?: boolean
|
||||||
}
|
}
|
||||||
article: Shout
|
article: Shout
|
||||||
|
scrollTo: 'comments'
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTitleAndSubtitle = (article: Shout): { title: string; subtitle: string } => {
|
const getTitleAndSubtitle = (article: Shout): { title: string; subtitle: string } => {
|
||||||
|
@ -75,6 +78,13 @@ export const ArticleCard = (props: ArticleCardProps) => {
|
||||||
|
|
||||||
const { cover, layout, slug, authors, stat, body } = props.article
|
const { cover, layout, slug, authors, stat, body } = props.article
|
||||||
|
|
||||||
|
const { changeSearchParam } = useRouter()
|
||||||
|
const scrollToComments = (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
openPage(router, 'article', { slug: slug })
|
||||||
|
changeSearchParam('scrollTo', 'comments')
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
class={clsx(styles.shoutCard, `${props.settings?.additionalClass || ''}`)}
|
class={clsx(styles.shoutCard, `${props.settings?.additionalClass || ''}`)}
|
||||||
|
@ -172,7 +182,7 @@ export const ArticleCard = (props: ArticleCardProps) => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class={clsx(styles.shoutCardDetailsItem, styles.shoutCardComments)}>
|
<div class={clsx(styles.shoutCardDetailsItem, styles.shoutCardComments)}>
|
||||||
<a href={`/${slug + '#comments'}`}>
|
<a href="#" onClick={(event) => scrollToComments(event)}>
|
||||||
<Icon name="comment" class={clsx(styles.icon, styles.feedControlIcon)} />
|
<Icon name="comment" class={clsx(styles.icon, styles.feedControlIcon)} />
|
||||||
{stat?.commented || t('Add comment')}
|
{stat?.commented || t('Add comment')}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -80,7 +80,8 @@ export const Header = (props: Props) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const scrollToComments = (value) => {
|
const scrollToComments = (event, value) => {
|
||||||
|
event.preventDefault()
|
||||||
props.scrollToComments(value)
|
props.scrollToComments(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +111,6 @@ export const Header = (props: Props) => {
|
||||||
<Show when={props.title}>
|
<Show when={props.title}>
|
||||||
<div class={styles.articleHeader}>{props.title}</div>
|
<div class={styles.articleHeader}>{props.title}</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
<ul
|
<ul
|
||||||
class={clsx(styles.mainNavigation, 'col text-xl inline-flex')}
|
class={clsx(styles.mainNavigation, 'col text-xl inline-flex')}
|
||||||
classList={{ fixed: fixed() }}
|
classList={{ fixed: fixed() }}
|
||||||
|
@ -144,7 +144,7 @@ export const Header = (props: Props) => {
|
||||||
containerCssClass={styles.control}
|
containerCssClass={styles.control}
|
||||||
trigger={<Icon name="share-outline" class={styles.icon} />}
|
trigger={<Icon name="share-outline" class={styles.icon} />}
|
||||||
/>
|
/>
|
||||||
<div onClick={() => scrollToComments(true)} class={styles.control}>
|
<div onClick={(event) => scrollToComments(event, true)} class={styles.control}>
|
||||||
<Icon name="comments-outline" class={styles.icon} />
|
<Icon name="comments-outline" class={styles.icon} />
|
||||||
</div>
|
</div>
|
||||||
<a href={getPagePath(router, 'create')} class={styles.control}>
|
<a href={getPagePath(router, 'create')} class={styles.control}>
|
||||||
|
|
|
@ -35,24 +35,12 @@ const LOAD_MORE_PAGE_SIZE = 9
|
||||||
|
|
||||||
export const AuthorView = (props: AuthorProps) => {
|
export const AuthorView = (props: AuthorProps) => {
|
||||||
const { t } = useLocalize()
|
const { t } = useLocalize()
|
||||||
const { sortedArticles } = useArticlesStore({
|
const { sortedArticles } = useArticlesStore({ shouts: props.shouts })
|
||||||
shouts: props.shouts
|
|
||||||
})
|
|
||||||
const { authorEntities } = useAuthorsStore({ authors: [props.author] })
|
|
||||||
const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false)
|
|
||||||
|
|
||||||
const author = createMemo(() => authorEntities()[props.authorSlug])
|
|
||||||
const [followers, setFollowers] = createSignal<Author[]>([])
|
|
||||||
onMount(async () => {
|
|
||||||
try {
|
|
||||||
const authorSubscribers = await apiClient.getAuthorFollowers({ slug: props.author.slug })
|
|
||||||
setFollowers(authorSubscribers)
|
|
||||||
} catch (error) {
|
|
||||||
console.log('[getAuthorSubscribers]', error)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const { searchParams, changeSearchParam } = useRouter<AuthorPageSearchParams>()
|
const { searchParams, changeSearchParam } = useRouter<AuthorPageSearchParams>()
|
||||||
|
const { authorEntities } = useAuthorsStore({ authors: [props.author] })
|
||||||
|
const author = authorEntities()[props.authorSlug]
|
||||||
|
const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false)
|
||||||
|
const [followers, setFollowers] = createSignal<Author[]>([])
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (!searchParams().by) {
|
if (!searchParams().by) {
|
||||||
|
@ -63,7 +51,7 @@ export const AuthorView = (props: AuthorProps) => {
|
||||||
const loadMore = async () => {
|
const loadMore = async () => {
|
||||||
saveScrollPosition()
|
saveScrollPosition()
|
||||||
const { hasMore } = await loadShouts({
|
const { hasMore } = await loadShouts({
|
||||||
filters: { author: author().slug },
|
filters: { author: props.authorSlug },
|
||||||
limit: LOAD_MORE_PAGE_SIZE,
|
limit: LOAD_MORE_PAGE_SIZE,
|
||||||
offset: sortedArticles().length
|
offset: sortedArticles().length
|
||||||
})
|
})
|
||||||
|
@ -73,7 +61,7 @@ export const AuthorView = (props: AuthorProps) => {
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
if (sortedArticles().length === PRERENDERED_ARTICLES_COUNT) {
|
if (sortedArticles().length === PRERENDERED_ARTICLES_COUNT) {
|
||||||
loadMore()
|
await loadMore()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -91,6 +79,16 @@ export const AuthorView = (props: AuthorProps) => {
|
||||||
)
|
)
|
||||||
|
|
||||||
const [commented, setCommented] = createSignal([])
|
const [commented, setCommented] = createSignal([])
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
try {
|
||||||
|
const authorSubscribers = await apiClient.getAuthorFollowers({ slug: props.authorSlug })
|
||||||
|
setFollowers(authorSubscribers)
|
||||||
|
} catch (error) {
|
||||||
|
console.log('[getAuthorSubscribers]', error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
createEffect(async () => {
|
createEffect(async () => {
|
||||||
if (searchParams().by === 'commented') {
|
if (searchParams().by === 'commented') {
|
||||||
try {
|
try {
|
||||||
|
@ -107,7 +105,7 @@ export const AuthorView = (props: AuthorProps) => {
|
||||||
return (
|
return (
|
||||||
<div class="author-page">
|
<div class="author-page">
|
||||||
<div class="wide-container">
|
<div class="wide-container">
|
||||||
<AuthorFull author={author()} />
|
<AuthorFull author={author} />
|
||||||
<div class="row group__controls">
|
<div class="row group__controls">
|
||||||
<div class="col-md-16">
|
<div class="col-md-16">
|
||||||
<ul class="view-switcher">
|
<ul class="view-switcher">
|
||||||
|
@ -197,9 +195,7 @@ export const AuthorView = (props: AuthorProps) => {
|
||||||
>
|
>
|
||||||
<Match when={searchParams().by === 'about'}>
|
<Match when={searchParams().by === 'about'}>
|
||||||
<div class="wide-container">
|
<div class="wide-container">
|
||||||
<Show when={author().bio}>
|
<p>{author.bio}</p>
|
||||||
<p>{author().bio}</p>
|
|
||||||
</Show>
|
|
||||||
</div>
|
</div>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={searchParams().by === 'commented'}>
|
<Match when={searchParams().by === 'commented'}>
|
||||||
|
|
|
@ -2,7 +2,6 @@ import type { Accessor } from 'solid-js'
|
||||||
import { createRouter, createSearchParams } from '@nanostores/router'
|
import { createRouter, createSearchParams } from '@nanostores/router'
|
||||||
import { isServer } from 'solid-js/web'
|
import { isServer } from 'solid-js/web'
|
||||||
import { useStore } from '@nanostores/solid'
|
import { useStore } from '@nanostores/solid'
|
||||||
import { getPageLoadManagerPromise } from '../utils/pageLoadManager'
|
|
||||||
|
|
||||||
export const ROUTES = {
|
export const ROUTES = {
|
||||||
home: '/',
|
home: '/',
|
||||||
|
@ -103,33 +102,9 @@ const handleClientRouteLinkClick = async (event) => {
|
||||||
top: 0,
|
top: 0,
|
||||||
left: 0
|
left: 0
|
||||||
})
|
})
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
await getPageLoadManagerPromise()
|
|
||||||
|
|
||||||
const images = document.querySelectorAll('img')
|
|
||||||
|
|
||||||
let imagesLoaded = 0
|
|
||||||
|
|
||||||
const imageLoadEventHandler = () => {
|
|
||||||
imagesLoaded++
|
|
||||||
if (imagesLoaded === images.length) {
|
|
||||||
scrollToHash(url.hash)
|
scrollToHash(url.hash)
|
||||||
images.forEach((image) => image.removeEventListener('load', imageLoadEventHandler))
|
|
||||||
images.forEach((image) => image.removeEventListener('error', imageLoadEventHandler))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
images.forEach((image) => {
|
|
||||||
if (image.complete) {
|
|
||||||
imagesLoaded++
|
|
||||||
}
|
|
||||||
|
|
||||||
image.addEventListener('load', imageLoadEventHandler)
|
|
||||||
image.addEventListener('error', imageLoadEventHandler)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initRouter = (pathname: string, search: Record<string, string>) => {
|
export const initRouter = (pathname: string, search: Record<string, string>) => {
|
||||||
|
|
|
@ -2,7 +2,6 @@ import type { FollowingEntity } from '../../graphql/types.gen'
|
||||||
import { apiClient } from '../../utils/apiClient'
|
import { apiClient } from '../../utils/apiClient'
|
||||||
|
|
||||||
export const follow = async ({ what, slug }: { what: FollowingEntity; slug: string }) => {
|
export const follow = async ({ what, slug }: { what: FollowingEntity; slug: string }) => {
|
||||||
console.log('!!! follow:')
|
|
||||||
await apiClient.follow({ what, slug })
|
await apiClient.follow({ what, slug })
|
||||||
}
|
}
|
||||||
export const unfollow = async ({ what, slug }: { what: FollowingEntity; slug: string }) => {
|
export const unfollow = async ({ what, slug }: { what: FollowingEntity; slug: string }) => {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user