minor-ref
This commit is contained in:
parent
cd436dd34d
commit
7c614c66d9
|
@ -6,8 +6,8 @@ import { useLocalize } from '~/context/localize'
|
|||
import { useReactions } from '~/context/reactions'
|
||||
import { useSession } from '~/context/session'
|
||||
import { Author, Reaction, ReactionKind, ReactionSort } from '~/graphql/schema/core.gen'
|
||||
import { byCreated, byStat } from '~/lib/sort'
|
||||
import { SortFunction } from '~/types/common'
|
||||
import { byCreated, byStat } from '~/utils/sort'
|
||||
import { Button } from '../_shared/Button'
|
||||
import { ShowIfAuthenticated } from '../_shared/ShowIfAuthenticated'
|
||||
import styles from './Article.module.scss'
|
||||
|
|
|
@ -5,8 +5,8 @@ import { Icon } from '~/components/_shared/Icon'
|
|||
import { useFeed } from '~/context/feed'
|
||||
import { useLocalize } from '~/context/localize'
|
||||
import type { Shout } from '~/graphql/schema/core.gen'
|
||||
import { byScore } from '~/lib/sort'
|
||||
import { restoreScrollPosition, saveScrollPosition } from '~/utils/scroll'
|
||||
import { byScore } from '~/utils/sort'
|
||||
import { FEED_PAGE_SIZE } from '../Views/Feed/Feed'
|
||||
import styles from './SearchModal.module.scss'
|
||||
import { SearchResultItem } from './SearchResultItem'
|
||||
|
@ -23,7 +23,7 @@ const getSearchCoincidences = ({ str, intersection }: { str: string; intersectio
|
|||
)}</span>`
|
||||
|
||||
const prepareSearchResults = (list: Shout[], searchValue: string) =>
|
||||
list.sort(byScore() as (a: Shout, b: Shout) => number).map((article, index) => ({
|
||||
list.sort(byScore as (a: Shout, b: Shout) => number).map((article, index) => ({
|
||||
...article,
|
||||
id: index,
|
||||
title: article.title
|
||||
|
|
|
@ -5,7 +5,7 @@ import { Icon } from '~/components/_shared/Icon'
|
|||
import { useLocalize } from '~/context/localize'
|
||||
import { useTopics } from '~/context/topics'
|
||||
import type { Topic } from '~/graphql/schema/core.gen'
|
||||
import { getRandomTopicsFromArray } from '~/lib/getRandomTopicsFromArray'
|
||||
import { getRandomItemsFromArray } from '~/utils/random'
|
||||
import styles from './TopicsNav.module.scss'
|
||||
|
||||
export const RandomTopics = () => {
|
||||
|
@ -17,11 +17,11 @@ export const RandomTopics = () => {
|
|||
createEffect(
|
||||
on(sortedTopics, (ttt: Topic[]) => {
|
||||
if (ttt?.length) {
|
||||
setRandomTopics(getRandomTopicsFromArray(ttt))
|
||||
setRandomTopics(getRandomItemsFromArray(ttt))
|
||||
}
|
||||
})
|
||||
)
|
||||
onMount(() => sortedTopics() && getRandomTopicsFromArray(sortedTopics()))
|
||||
onMount(() => sortedTopics() && getRandomItemsFromArray(sortedTopics()))
|
||||
return (
|
||||
<ul class="nodash">
|
||||
<Show when={randomTopics().length > 0}>
|
||||
|
|
|
@ -9,8 +9,8 @@ import { SearchField } from '~/components/_shared/SearchField'
|
|||
import { useAuthors } from '~/context/authors'
|
||||
import { useLocalize } from '~/context/localize'
|
||||
import type { Author } from '~/graphql/schema/core.gen'
|
||||
import { dummyFilter } from '~/intl/dummyFilter'
|
||||
import { authorLetterReduce, translateAuthor } from '~/intl/translate'
|
||||
import { dummyFilter } from '~/lib/dummyFilter'
|
||||
// import { byFirstChar, byStat } from '~/lib/sort'
|
||||
import { scrollHandler } from '~/utils/scroll'
|
||||
import styles from './AllAuthors.module.scss'
|
||||
|
|
|
@ -6,7 +6,7 @@ import { SearchField } from '~/components/_shared/SearchField'
|
|||
import { useLocalize } from '~/context/localize'
|
||||
import { useTopics } from '~/context/topics'
|
||||
import type { Topic } from '~/graphql/schema/core.gen'
|
||||
import { dummyFilter } from '~/lib/dummyFilter'
|
||||
import { dummyFilter } from '~/intl/dummyFilter'
|
||||
import { scrollHandler } from '~/utils/scroll'
|
||||
import { TopicBadge } from '../../Topic/TopicBadge'
|
||||
import styles from './AllTopics.module.scss'
|
||||
|
|
|
@ -11,7 +11,7 @@ import { graphqlClientCreate } from '~/graphql/client'
|
|||
import getAuthorFollowersQuery from '~/graphql/query/core/author-followers'
|
||||
import getAuthorFollowsQuery from '~/graphql/query/core/author-follows'
|
||||
import type { Author, Reaction, Shout, Topic } from '~/graphql/schema/core.gen'
|
||||
import { byCreated } from '~/lib/sort'
|
||||
import { byCreated } from '~/utils/sort'
|
||||
import stylesArticle from '../../Article/Article.module.scss'
|
||||
import { Comment } from '../../Article/Comment'
|
||||
import { AuthorCard } from '../../Author/AuthorCard'
|
||||
|
|
|
@ -17,8 +17,8 @@ import { useUI } from '~/context/ui'
|
|||
import { loadUnratedShouts } from '~/graphql/api/private'
|
||||
import { graphqlClientCreate } from '~/graphql/client'
|
||||
import type { Author, Reaction, Shout } from '~/graphql/schema/core.gen'
|
||||
import { byCreated } from '~/lib/sort'
|
||||
import { FeedSearchParams } from '~/routes/feed/[...order]'
|
||||
import { byCreated } from '~/utils/sort'
|
||||
import { CommentDate } from '../../Article/CommentDate'
|
||||
import { getShareUrl } from '../../Article/SharePopup'
|
||||
import { AuthorBadge } from '../../Author/AuthorBadge'
|
||||
|
|
|
@ -21,7 +21,6 @@ import { useSnackbar, useUI } from '~/context/ui'
|
|||
import { InputMaybe, ProfileInput } from '~/graphql/schema/core.gen'
|
||||
import { getImageUrl } from '~/lib/getThumbUrl'
|
||||
import { handleImageUpload } from '~/lib/handleImageUpload'
|
||||
import { profileSocialLinks } from '~/lib/profileSocialLinks'
|
||||
import { clone } from '~/utils/clone'
|
||||
import { validateUrl } from '~/utils/validate'
|
||||
import { ProfileSettingsNavigation } from '../../ProfileNav'
|
||||
|
@ -33,6 +32,7 @@ import { Modal } from '../../_shared/Modal'
|
|||
import { Popover } from '../../_shared/Popover'
|
||||
import { SocialNetworkInput } from '../../_shared/SocialNetworkInput'
|
||||
import styles from './Settings.module.scss'
|
||||
import { profileSocialLinks } from './profileSocialLinks'
|
||||
|
||||
const SimplifiedEditor = lazy(() => import('~/components/Editor/SimplifiedEditor'))
|
||||
const GrowingTextarea = lazy(() => import('~/components/_shared/GrowingTextarea/GrowingTextarea'))
|
||||
|
|
|
@ -5,7 +5,7 @@ import { SearchField } from '~/components/_shared/SearchField'
|
|||
import { FollowsFilter, useFollowing } from '~/context/following'
|
||||
import { useLocalize } from '~/context/localize'
|
||||
import { Author, Topic } from '~/graphql/schema/core.gen'
|
||||
import { dummyFilter } from '~/lib/dummyFilter'
|
||||
import { dummyFilter } from '~/intl/dummyFilter'
|
||||
import stylesSettings from '../../../styles/FeedSettings.module.scss'
|
||||
import { AuthorBadge } from '../../Author/AuthorBadge'
|
||||
import { ProfileSettingsNavigation } from '../../ProfileNav'
|
||||
|
|
|
@ -2,9 +2,9 @@ import { JSX, Show, createEffect, createSignal, on, onMount } from 'solid-js'
|
|||
import { Button } from '~/components/_shared/Button'
|
||||
import { useLocalize } from '~/context/localize'
|
||||
import { Author, Reaction, Shout } from '~/graphql/schema/core.gen'
|
||||
import { byCreated } from '~/lib/sort'
|
||||
import { SortFunction } from '~/types/common'
|
||||
import { restoreScrollPosition, saveScrollPosition } from '~/utils/scroll'
|
||||
import { byCreated } from '~/utils/sort'
|
||||
|
||||
export type LoadMoreItems = Shout[] | Author[] | Reaction[]
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ import {
|
|||
Shout,
|
||||
Topic
|
||||
} from '~/graphql/schema/core.gen'
|
||||
import { byStat } from '~/lib/sort'
|
||||
import { FilterFunction, SortFunction } from '~/types/common'
|
||||
import { byStat } from '~/utils/sort'
|
||||
import { useFeed } from './feed'
|
||||
|
||||
const TOP_AUTHORS_COUNT = 5
|
||||
|
|
|
@ -12,7 +12,7 @@ import {
|
|||
Topic
|
||||
} from '~/graphql/schema/core.gen'
|
||||
import { graphqlClientCreate } from '../graphql/client'
|
||||
import { byStat } from '../lib/sort'
|
||||
import { byStat } from '../utils/sort'
|
||||
import { useSession } from './session'
|
||||
|
||||
export const PRERENDERED_ARTICLES_COUNT = 5
|
||||
|
|
|
@ -12,8 +12,8 @@ import {
|
|||
} from 'solid-js'
|
||||
import { loadTopics } from '~/graphql/api/public'
|
||||
import { Topic } from '~/graphql/schema/core.gen'
|
||||
import { getRandomTopicsFromArray } from '~/lib/getRandomTopicsFromArray'
|
||||
import { byTopicStatDesc } from '../lib/sort'
|
||||
import { getRandomItemsFromArray } from '~/utils/random'
|
||||
import { byTopicStatDesc } from '../utils/sort'
|
||||
|
||||
type TopicsContextType = {
|
||||
topicEntities: Accessor<{ [topicSlug: string]: Topic }>
|
||||
|
@ -198,7 +198,7 @@ export const TopicsProvider = (props: { children: JSX.Element }) => {
|
|||
const topics = isCacheValid ? req : await loadAllTopics()
|
||||
console.info(`[context.topics] got ${(topics as Topic[]).length || 0} topics from idb`)
|
||||
addTopics(topics as Topic[])
|
||||
setRandomTopic(getRandomTopicsFromArray(topics || [], 1).pop())
|
||||
setRandomTopic(getRandomItemsFromArray(topics || [], 1).pop())
|
||||
}
|
||||
},
|
||||
{ defer: true }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { Author, Topic } from '~/graphql/schema/core.gen'
|
||||
import { translit } from '../intl/translit'
|
||||
import { translit } from './translit'
|
||||
|
||||
const prepareQuery = (searchQuery: string, lang: string) => {
|
||||
const q = searchQuery.toLowerCase()
|
|
@ -1,8 +0,0 @@
|
|||
import { Topic } from '~/graphql/schema/core.gen'
|
||||
import { RANDOM_TOPICS_COUNT } from '../components/Views/Home'
|
||||
|
||||
export const getRandomTopicsFromArray = (topics: Topic[], count: number = RANDOM_TOPICS_COUNT): Topic[] => {
|
||||
if (!Array.isArray(topics)) return [] as Topic[]
|
||||
const shuffledTopics = [...topics].sort(() => 0.5 - Math.random())
|
||||
return shuffledTopics.slice(0, count)
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
import type { Author, Maybe, Reaction, Shout, Topic, TopicStat } from '~/graphql/schema/core.gen'
|
||||
|
||||
export const byFirstChar = (a: Author | Topic, b: Author | Topic) =>
|
||||
((a as Author).name || (a as Topic).title || '').localeCompare(
|
||||
(b as Author).name || (b as Topic).title || ''
|
||||
)
|
||||
|
||||
export const byCreated = (a: { created_at?: number }, b: { created_at?: number }) => {
|
||||
return (a?.created_at || 0) - (b?.created_at || 0)
|
||||
}
|
||||
|
||||
export const byPublished = (a: Shout, b: Shout) => {
|
||||
return (a?.published_at || 0) - (b?.published_at || 0)
|
||||
}
|
||||
|
||||
export const byLength = (
|
||||
a: (Shout | Reaction | Topic | Author)[],
|
||||
b: (Shout | Reaction | Topic | Author)[]
|
||||
) => {
|
||||
const x = a.length
|
||||
const y = b.length
|
||||
|
||||
if (x > y) return -1
|
||||
|
||||
if (x < y) return 1
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
export type SomeStat = { [x: string]: Maybe<number> } | undefined | null
|
||||
|
||||
export const byStat = (metric: string) => {
|
||||
if (metric === 'name' || metric === 'title') return byFirstChar
|
||||
return (a: { stat?: SomeStat }, b: { stat?: SomeStat }) => {
|
||||
const aStat = a.stat?.[metric] ?? 0
|
||||
const bStat = b.stat?.[metric] ?? 0
|
||||
return aStat - bStat
|
||||
}
|
||||
}
|
||||
|
||||
export const byTopicStatDesc = (metric: keyof TopicStat) => {
|
||||
return (a: Topic, b: Topic) => {
|
||||
const x = a.stat?.[metric] || 0
|
||||
const y = b.stat?.[metric] || 0
|
||||
if (x > y) return -1
|
||||
if (x < y) return 1
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
export const byScore = () => {
|
||||
return (a: { score: number }, b: { score: number }) => {
|
||||
const x = a?.score || 0
|
||||
const y = b?.score || 0
|
||||
if (x > y) return -1
|
||||
if (x < y) return 1
|
||||
return 0
|
||||
}
|
||||
}
|
8
src/utils/random.ts
Normal file
8
src/utils/random.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
export const getRandomItemsFromArray = <T>(items: T[], count = 10): T[] => {
|
||||
if (!Array.isArray(items)) {
|
||||
return []
|
||||
}
|
||||
|
||||
const shuffledItems = [...items].sort(() => 0.5 - Math.random())
|
||||
return shuffledItems.slice(0, count)
|
||||
}
|
57
src/utils/sort.ts
Normal file
57
src/utils/sort.ts
Normal file
|
@ -0,0 +1,57 @@
|
|||
import { Maybe } from 'graphql/jsutils/Maybe'
|
||||
|
||||
type WithNameOrTitle = { name?: string } | { title?: string }
|
||||
type WithCreatedAt = { created_at?: number }
|
||||
type WithPublishedAt = { published_at?: number }
|
||||
type WithStat = { stat?: { [key: string]: Maybe<number> } | undefined | null }
|
||||
type WithScore = { score: number }
|
||||
|
||||
export const byFirstChar = <T extends WithNameOrTitle>(a: T, b: T) => {
|
||||
const aValue = 'name' in a ? a.name : (a as { title?: string }).title || ''
|
||||
const bValue = 'name' in b ? b.name : (b as { title?: string }).title || ''
|
||||
|
||||
return aValue?.localeCompare(bValue || '')
|
||||
}
|
||||
export const byCreated = <T extends WithCreatedAt>(a: T, b: T) => {
|
||||
return (a?.created_at || 0) - (b?.created_at || 0)
|
||||
}
|
||||
|
||||
export const byPublished = <T extends WithPublishedAt>(a: T, b: T) => {
|
||||
return (a?.published_at || 0) - (b?.published_at || 0)
|
||||
}
|
||||
|
||||
export const byLength = <T>(a: T[], b: T[]) => {
|
||||
const x = a.length
|
||||
const y = b.length
|
||||
|
||||
if (x > y) return -1
|
||||
if (x < y) return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
export const byStat = (metric: string) => {
|
||||
if (metric === 'name' || metric === 'title') return byFirstChar
|
||||
return <T extends WithStat>(a: T, b: T) => {
|
||||
const aStat = a.stat?.[metric] ?? 0
|
||||
const bStat = b.stat?.[metric] ?? 0
|
||||
return aStat - bStat
|
||||
}
|
||||
}
|
||||
|
||||
export const byTopicStatDesc = <T extends WithStat>(metric: string) => {
|
||||
return (a: T, b: T) => {
|
||||
const x = a.stat?.[metric] || 0
|
||||
const y = b.stat?.[metric] || 0
|
||||
if (x > y) return -1
|
||||
if (x < y) return 1
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
export const byScore = <T extends WithScore>(a: T, b: T) => {
|
||||
const x = a?.score || 0
|
||||
const y = b?.score || 0
|
||||
if (x > y) return -1
|
||||
if (x < y) return 1
|
||||
return 0
|
||||
}
|
Loading…
Reference in New Issue
Block a user