diff --git a/src/components/Nav/Modal.module.scss b/src/components/Nav/Modal.module.scss
index 746202e0..c6b1fd39 100644
--- a/src/components/Nav/Modal.module.scss
+++ b/src/components/Nav/Modal.module.scss
@@ -23,15 +23,16 @@
position: absolute;
top: 1em;
cursor: pointer;
- height: 0.8em;
+ height: 18px;
+ width: 16px;
opacity: 1;
padding: 0;
right: 0;
transition: opacity 0.3s;
- width: 0.8em;
z-index: 1;
svg {
+ display: block;
pointer-events: none;
}
@@ -55,6 +56,7 @@
@media (min-width: 800px) and (max-width: 991px) {
width: 80%;
}
+
.close {
right: 12px;
top: 12px;
diff --git a/src/components/Topic/Card.module.scss b/src/components/Topic/Card.module.scss
index a4e63fe4..88faeca1 100644
--- a/src/components/Topic/Card.module.scss
+++ b/src/components/Topic/Card.module.scss
@@ -116,3 +116,7 @@
.buttonCompact {
margin-top: 0.6rem;
}
+
+.isSubscribing {
+ color: transparent;
+}
diff --git a/src/components/Topic/Card.tsx b/src/components/Topic/Card.tsx
index 6cdc394a..8dcd2f23 100644
--- a/src/components/Topic/Card.tsx
+++ b/src/components/Topic/Card.tsx
@@ -1,6 +1,6 @@
import { capitalize } from '../../utils'
import styles from './Card.module.scss'
-import { createMemo, Show } from 'solid-js'
+import { createEffect, createMemo, createSignal, Show } from 'solid-js'
import type { Topic } from '../../graphql/types.gen'
import { FollowingEntity } from '../../graphql/types.gen'
import { t } from '../../utils/intl'
@@ -9,6 +9,7 @@ import { getLogger } from '../../utils/logger'
import { clsx } from 'clsx'
import { useSession } from '../../context/session'
import { StatMetrics } from '../_shared/StatMetrics'
+import { ShowOnlyOnClient } from '../_shared/ShowOnlyOnClient'
const log = getLogger('TopicCard')
@@ -25,7 +26,12 @@ interface TopicProps {
}
export const TopicCard = (props: TopicProps) => {
- const { session } = useSession()
+ const {
+ session,
+ actions: { loadSession }
+ } = useSession()
+
+ const [isSubscribing, setIsSubscribing] = createSignal(false)
const subscribed = createMemo(() => {
if (!session()?.user?.slug || !session()?.news?.topics) {
@@ -35,14 +41,17 @@ export const TopicCard = (props: TopicProps) => {
return session()?.news.topics.includes(props.topic.slug)
})
- // FIXME use store actions
const subscribe = async (really = true) => {
- if (really) {
- follow({ what: FollowingEntity.Topic, slug: props.topic.slug })
- } else {
- unfollow({ what: FollowingEntity.Topic, slug: props.topic.slug })
- }
+ setIsSubscribing(true)
+
+ await (really
+ ? follow({ what: FollowingEntity.Topic, slug: props.topic.slug })
+ : unfollow({ what: FollowingEntity.Topic, slug: props.topic.slug }))
+
+ await loadSession()
+ setIsSubscribing(false)
}
+
return (
{
class={styles.controlContainer}
classList={{ 'col-md-3': !props.compact && !props.subscribeButtonBottom }}
>
-
+
- }
- >
-
-
+
+
)
diff --git a/src/components/Views/AllAuthors.tsx b/src/components/Views/AllAuthors.tsx
index d6115ddc..5e138c8e 100644
--- a/src/components/Views/AllAuthors.tsx
+++ b/src/components/Views/AllAuthors.tsx
@@ -1,7 +1,7 @@
import { createEffect, createMemo, createSignal, For, onMount, Show } from 'solid-js'
import type { Author } from '../../graphql/types.gen'
import { t } from '../../utils/intl'
-import { AuthorsSortBy, setAuthorsSort, useAuthorsStore } from '../../stores/zine/authors'
+import { setAuthorsSort, useAuthorsStore } from '../../stores/zine/authors'
import { useRouter } from '../../stores/router'
import { AuthorCard } from '../Author/Card'
import { clsx } from 'clsx'
@@ -22,36 +22,38 @@ type AllAuthorsViewProps = {
}
const PAGE_SIZE = 20
-const ALPHABET = [...'@АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ']
+const ALPHABET = [...'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ@']
export const AllAuthorsView = (props: AllAuthorsViewProps) => {
const [limit, setLimit] = createSignal(PAGE_SIZE)
- const { searchParams, changeSearchParam } = useRouter()
- const [filterResults, setFilterResults] = createSignal
([])
+ const { searchParams, changeSearchParam } = useRouter()
const { sortedAuthors } = useAuthorsStore({
authors: props.authors,
- sortBy: (searchParams().by || 'shouts') as AuthorsSortBy
+ sortBy: searchParams().by || 'shouts'
})
+ const [searchQuery, setSearchQuery] = createSignal('')
+
const { session } = useSession()
onMount(() => {
if (!searchParams().by) {
- setAuthorsSort('name')
- changeSearchParam('by', 'name')
+ changeSearchParam('by', 'shouts')
}
})
+
createEffect(() => {
- setAuthorsSort((searchParams().by || 'shouts') as AuthorsSortBy)
- setFilterResults(sortedAuthors())
- setLimit(PAGE_SIZE)
+ setAuthorsSort(searchParams().by || 'shouts')
})
const byLetter = createMemo<{ [letter: string]: Author[] }>(() => {
return sortedAuthors().reduce((acc, author) => {
let letter = author.name.trim().split(' ').pop().at(0).toUpperCase()
- if (!/[А-я]/i.test(letter) && locale() === 'ru') letter = '@'
+
+ if (/[^ËА-яё]/.test(letter) && locale() === 'ru') letter = '@'
+
if (!acc[letter]) acc[letter] = []
+
acc[letter].push(author)
return acc
}, {} as { [letter: string]: Author[] })
@@ -60,41 +62,34 @@ export const AllAuthorsView = (props: AllAuthorsViewProps) => {
const sortedKeys = createMemo(() => {
const keys = Object.keys(byLetter())
keys.sort()
+ keys.push(keys.shift())
return keys
})
const subscribed = (s) => Boolean(session()?.news?.authors && session()?.news?.authors?.includes(s || ''))
- // eslint-disable-next-line sonarjs/cognitive-complexity
- const filterAuthors = (value) => {
- /* very stupid filter by string algorithm with no deps */
- let q = value.toLowerCase()
- if (q.length > 0) {
- setFilterResults([])
- if (locale() === 'ru') q = translit(q, 'ru')
- const aaa: Author[] = sortedAuthors()
- sortedAuthors().forEach((author) => {
- let flag = false
- author.slug.split('-').forEach((w) => {
- if (w.startsWith(q)) flag = true
- })
+ const filteredAuthors = createMemo(() => {
+ let q = searchQuery().toLowerCase()
- if (!flag) {
- let wrds: string = author.name.toLowerCase()
- if (locale() === 'ru') wrds = translit(wrds, 'ru')
- wrds.split(' ').forEach((w: string) => {
- if (w.startsWith(q)) flag = true
- })
- }
-
- if (!flag && aaa.includes(author)) {
- const idx = aaa.indexOf(author)
- aaa.splice(idx, 1)
- }
- })
- setFilterResults(aaa)
+ if (q.length === 0) {
+ return sortedAuthors()
}
- }
+
+ if (locale() === 'ru') q = translit(q)
+
+ return sortedAuthors().filter((author) => {
+ if (author.slug.split('-').some((w) => w.startsWith(q))) {
+ return true
+ }
+
+ let name = author.name.toLowerCase()
+ if (locale() === 'ru') {
+ name = translit(name)
+ }
+
+ return name.split(' ').some((word) => word.startsWith(q))
+ })
+ })
const showMore = () => setLimit((oldLimit) => oldLimit + PAGE_SIZE)
const AllAuthorsHead = () => (
@@ -104,7 +99,7 @@ export const AllAuthorsView = (props: AllAuthorsViewProps) => {
{t('Subscribe who you like to tune your personal feed')}
- -
+
-
{t('By shouts')}
-
@@ -115,7 +110,7 @@ export const AllAuthorsView = (props: AllAuthorsViewProps) => {
-
-
+ setSearchQuery(value)} />
@@ -139,7 +134,10 @@ export const AllAuthorsView = (props: AllAuthorsViewProps) => {
scrollHandler(`letter-${index()}`)}
+ onClick={(event) => {
+ event.preventDefault()
+ scrollHandler(`letter-${index()}`)
+ }}
>
{letter}
@@ -152,9 +150,9 @@ export const AllAuthorsView = (props: AllAuthorsViewProps) => {