Merge pull request #5028 from nileshtrivedi/followed_tags_in_sidebar
Show followed tags in the sidebar
This commit is contained in:
commit
98a9ddf7ad
|
@ -4,7 +4,7 @@ import generator, { Entity } from 'megalodon'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useHotkeys } from 'react-hotkeys-hook'
|
import { useHotkeys } from 'react-hotkeys-hook'
|
||||||
import { FaBell, FaBookmark, FaGlobe, FaHouse, FaList, FaStar, FaUsers } from 'react-icons/fa6'
|
import { FaBell, FaBookmark, FaGlobe, FaHouse, FaList, FaStar, FaUsers, FaHashtag } from 'react-icons/fa6'
|
||||||
import { useIntl } from 'react-intl'
|
import { useIntl } from 'react-intl'
|
||||||
import Jump from '../Jump'
|
import Jump from '../Jump'
|
||||||
import { useUnreads } from '@/provider/unreads'
|
import { useUnreads } from '@/provider/unreads'
|
||||||
|
@ -27,6 +27,7 @@ export default function Layout({ children }: LayoutProps) {
|
||||||
|
|
||||||
const [account, setAccount] = useState<Account | null>(null)
|
const [account, setAccount] = useState<Account | null>(null)
|
||||||
const [lists, setLists] = useState<Array<Entity.List>>([])
|
const [lists, setLists] = useState<Array<Entity.List>>([])
|
||||||
|
const [followedTags, setFollowedTags] = useState<Array<Entity.Tag>>([])
|
||||||
const [openJump, setOpenJump] = useState(false)
|
const [openJump, setOpenJump] = useState(false)
|
||||||
|
|
||||||
useHotkeys('mod+k', () => setOpenJump(current => !current))
|
useHotkeys('mod+k', () => setOpenJump(current => !current))
|
||||||
|
@ -50,6 +51,11 @@ export default function Layout({ children }: LayoutProps) {
|
||||||
setLists(res.data)
|
setLists(res.data)
|
||||||
}
|
}
|
||||||
f()
|
f()
|
||||||
|
const g = async () => {
|
||||||
|
const res = await c.getFollowedTags()
|
||||||
|
setFollowedTags(res.data)
|
||||||
|
}
|
||||||
|
g()
|
||||||
}, [account])
|
}, [account])
|
||||||
|
|
||||||
const pages: Array<Timeline> = [
|
const pages: Array<Timeline> = [
|
||||||
|
@ -136,6 +142,21 @@ export default function Layout({ children }: LayoutProps) {
|
||||||
<div className="sidebar-menu text-ellipsis whitespace-nowrap overflow-hidden">{list.title}</div>
|
<div className="sidebar-menu text-ellipsis whitespace-nowrap overflow-hidden">{list.title}</div>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
{followedTags.map(tag => (
|
||||||
|
<ListItem
|
||||||
|
key={tag.name}
|
||||||
|
selected={router.asPath.includes(`tag_${tag.name}`)}
|
||||||
|
onClick={() => router.push({ pathname: `/accounts/${router.query.id}/tag_${tag.name}` })}
|
||||||
|
className="sidebar-menu-item theme-text-primary overflow-hidden whitespace-nowrap"
|
||||||
|
title={tag.name}
|
||||||
|
>
|
||||||
|
<ListItemPrefix>
|
||||||
|
<FaHashtag />
|
||||||
|
</ListItemPrefix>
|
||||||
|
<div className="sidebar-menu text-ellipsis whitespace-nowrap overflow-hidden">{tag.name}</div>
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
</List>
|
</List>
|
||||||
</Card>
|
</Card>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
@ -27,6 +27,7 @@ export default function Timeline(props: Props) {
|
||||||
const [firstItemIndex, setFirstItemIndex] = useState(TIMELINE_MAX_STATUSES)
|
const [firstItemIndex, setFirstItemIndex] = useState(TIMELINE_MAX_STATUSES)
|
||||||
const [composeHeight, setComposeHeight] = useState(120)
|
const [composeHeight, setComposeHeight] = useState(120)
|
||||||
const [list, setList] = useState<Entity.List | null>(null)
|
const [list, setList] = useState<Entity.List | null>(null)
|
||||||
|
const [tag, setTag] = useState<Entity.Tag | null>(null)
|
||||||
const [filters, setFilters] = useState<Array<Entity.Filter>>([])
|
const [filters, setFilters] = useState<Array<Entity.Filter>>([])
|
||||||
const [nextMaxId, setNextMaxId] = useState<string | null>(null)
|
const [nextMaxId, setNextMaxId] = useState<string | null>(null)
|
||||||
|
|
||||||
|
@ -58,6 +59,7 @@ export default function Timeline(props: Props) {
|
||||||
const res = await loadTimeline(props.timeline, props.client)
|
const res = await loadTimeline(props.timeline, props.client)
|
||||||
setStatuses(res)
|
setStatuses(res)
|
||||||
setList(null)
|
setList(null)
|
||||||
|
setTag(null)
|
||||||
switch (props.timeline) {
|
switch (props.timeline) {
|
||||||
case 'home': {
|
case 'home': {
|
||||||
streaming.current = await props.client.userStreaming()
|
streaming.current = await props.client.userStreaming()
|
||||||
|
@ -77,6 +79,13 @@ export default function Timeline(props: Props) {
|
||||||
const res = await props.client.getList(match[1])
|
const res = await props.client.getList(match[1])
|
||||||
streaming.current = await props.client.listStreaming(match[1])
|
streaming.current = await props.client.listStreaming(match[1])
|
||||||
setList(res.data)
|
setList(res.data)
|
||||||
|
} else {
|
||||||
|
const tag_match = props.timeline.match(/tag_(\w+)/)
|
||||||
|
if (tag_match && tag_match[1] && typeof tag_match[1] === 'string') {
|
||||||
|
const res = await props.client.getTag(tag_match[1])
|
||||||
|
streaming.current = await props.client.tagStreaming(tag_match[1])
|
||||||
|
setTag(res.data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -169,9 +178,16 @@ export default function Timeline(props: Props) {
|
||||||
default: {
|
default: {
|
||||||
// Check list
|
// Check list
|
||||||
const match = tl.match(/list_(\d+)/)
|
const match = tl.match(/list_(\d+)/)
|
||||||
if (match[1] && typeof match[1] === 'string') {
|
if (match && match[1] && typeof match[1] === 'string') {
|
||||||
const res = await client.getListTimeline(match[1], options)
|
const res = await client.getListTimeline(match[1], options)
|
||||||
return res.data
|
return res.data
|
||||||
|
} else {
|
||||||
|
// Check tag
|
||||||
|
const tag_match = tl.match(/tag_(\w+)/)
|
||||||
|
if (tag_match && tag_match[1] && typeof tag_match[1] === 'string') {
|
||||||
|
const res = await client.getTagTimeline(tag_match[1], options)
|
||||||
|
return res.data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
@ -262,7 +278,10 @@ export default function Timeline(props: Props) {
|
||||||
<section className={`h-full ${timelineClass()}`}>
|
<section className={`h-full ${timelineClass()}`}>
|
||||||
<div className="w-full theme-bg theme-text-primary p-2 flex justify-between">
|
<div className="w-full theme-bg theme-text-primary p-2 flex justify-between">
|
||||||
<div className="text-lg font-bold cursor-pointer" onClick={() => backToTop()}>
|
<div className="text-lg font-bold cursor-pointer" onClick={() => backToTop()}>
|
||||||
{props.timeline.match(/list_(\d+)/) ? <>{list && list.title}</> : <FormattedMessage id={`timeline.${props.timeline}`} />}
|
{
|
||||||
|
props.timeline.match(/list_(\d+)/) ? <>{list && list.title}</> :
|
||||||
|
(props.timeline.match(/tag_(\w+)/) ? <>{tag && `# ${tag.name}`}</> :
|
||||||
|
<FormattedMessage id={`timeline.${props.timeline}`} />)}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-64 text-xs">
|
<div className="w-64 text-xs">
|
||||||
<form onSubmit={ev => search(ev)}>
|
<form onSubmit={ev => search(ev)}>
|
||||||
|
|
Loading…
Reference in New Issue