1
0
mirror of https://github.com/h3poteto/whalebird-desktop synced 2024-12-28 01:32:15 +01:00
Whalebird-desktop-client-ma.../renderer/components/layouts/timelines.tsx

216 lines
7.0 KiB
TypeScript
Raw Normal View History

2023-11-01 17:20:27 +01:00
import { Account, db } from '@/db'
2024-01-28 14:17:47 +01:00
import { Card, Chip, List, ListItem, ListItemPrefix, ListItemSuffix } from '@material-tailwind/react'
import generator, { Entity, MegalodonInterface } from 'megalodon'
2023-11-01 17:20:27 +01:00
import { useRouter } from 'next/router'
import { createContext, useContext, useEffect, useState } from 'react'
2024-01-12 14:14:33 +01:00
import { useHotkeys } from 'react-hotkeys-hook'
2024-10-12 07:46:04 +02:00
import { FaBell, FaBookmark, FaGlobe, FaHouse, FaList, FaStar, FaUsers, FaHashtag, FaUserPlus } from 'react-icons/fa6'
2023-11-04 07:32:37 +01:00
import { useIntl } from 'react-intl'
2024-01-12 14:14:33 +01:00
import Jump from '../Jump'
import { useUnreads } from '@/provider/unreads'
2023-11-01 17:20:27 +01:00
type Context = {
reloadMenu: () => Promise<void>
}
const TimelinesContext = createContext<Context>({
reloadMenu: async () => {}
})
TimelinesContext.displayName = 'TimelinesContext'
export const useTimelines = () => {
return useContext(TimelinesContext)
}
2023-11-01 17:20:27 +01:00
type LayoutProps = {
children: React.ReactNode
}
2024-03-08 16:42:55 +01:00
export type Timeline = {
id: string
title: string
icon: JSX.Element
path: string
}
2023-11-01 17:20:27 +01:00
export default function Layout({ children }: LayoutProps) {
const router = useRouter()
2023-11-04 07:32:37 +01:00
const { formatMessage } = useIntl()
2024-10-12 07:46:04 +02:00
const { unreads, setUnreads } = useUnreads()
2023-11-01 17:20:27 +01:00
const [account, setAccount] = useState<Account | null>(null)
2023-12-29 14:42:35 +01:00
const [lists, setLists] = useState<Array<Entity.List>>([])
2024-09-01 05:24:36 +02:00
const [followedTags, setFollowedTags] = useState<Array<Entity.Tag>>([])
2024-01-12 14:14:33 +01:00
const [openJump, setOpenJump] = useState(false)
const [client, setClient] = useState<MegalodonInterface>()
2024-10-12 07:46:04 +02:00
const [followRequests, setFollowRequests] = useState<Array<Timeline>>([])
2024-01-12 14:14:33 +01:00
2024-01-13 04:55:42 +01:00
useHotkeys('mod+k', () => setOpenJump(current => !current))
2023-12-29 14:42:35 +01:00
2023-11-01 17:20:27 +01:00
useEffect(() => {
if (router.query.id) {
const f = async () => {
const acct = await db.accounts.get(parseInt(router.query.id as string))
if (!acct) return
setAccount(acct)
}
f()
}
}, [router.query.id])
2023-12-29 14:42:35 +01:00
useEffect(() => {
if (!account) return
const c = generator(account.sns, account.url, account.access_token, 'Whalebird')
setClient(c)
2023-12-29 14:42:35 +01:00
const f = async () => {
const res = await c.getLists()
setLists(res.data)
}
f()
2024-09-01 05:24:36 +02:00
const g = async () => {
2024-10-12 07:46:04 +02:00
try {
const res = await c.getFollowedTags()
setFollowedTags(res.data)
} catch (err) {
setFollowedTags([])
console.error(err)
}
2024-09-01 05:24:36 +02:00
}
g()
2024-10-12 07:46:04 +02:00
const r = async () => {
const res = await c.getFollowRequests()
if (res.data.length > 0) {
setUnreads(current =>
Object.assign({}, current, {
[`${account.id?.toString()}_follow_requests`]: res.data.length
})
)
console.log(unreads)
setFollowRequests([
{
id: 'follow_requests',
title: formatMessage({ id: 'timeline.follow_requests' }),
icon: <FaUserPlus />,
path: `/accounts/${router.query.id}/follow_requests`
}
])
} else {
setFollowRequests([])
}
}
r()
2023-12-29 14:42:35 +01:00
}, [account])
2024-03-08 16:42:55 +01:00
const pages: Array<Timeline> = [
2023-11-01 17:20:27 +01:00
{
id: 'home',
2023-11-04 07:32:37 +01:00
title: formatMessage({ id: 'timeline.home' }),
icon: <FaHouse />,
2023-11-01 17:20:27 +01:00
path: `/accounts/${router.query.id}/home`
},
{
id: 'notifications',
2023-11-04 07:32:37 +01:00
title: formatMessage({ id: 'timeline.notifications' }),
icon: <FaBell />,
2023-11-01 17:20:27 +01:00
path: `/accounts/${router.query.id}/notifications`
},
{
id: 'local',
2023-11-04 07:32:37 +01:00
title: formatMessage({ id: 'timeline.local' }),
icon: <FaUsers />,
2023-11-01 17:20:27 +01:00
path: `/accounts/${router.query.id}/local`
},
{
id: 'public',
2023-11-04 07:32:37 +01:00
title: formatMessage({ id: 'timeline.public' }),
icon: <FaGlobe />,
2023-11-01 17:20:27 +01:00
path: `/accounts/${router.query.id}/public`
2024-03-08 16:42:55 +01:00
},
2024-03-08 16:51:13 +01:00
{
id: 'favourites',
title: formatMessage({ id: 'timeline.favourites' }),
icon: <FaStar />,
path: `/accounts/${router.query.id}/favourites`
},
2024-03-08 16:42:55 +01:00
{
id: 'bookmarks',
title: formatMessage({ id: 'timeline.bookmarks' }),
icon: <FaBookmark />,
path: `/accounts/${router.query.id}/bookmarks`
2023-11-01 17:20:27 +01:00
}
]
const reloadMenu = async () => {
const res = await client.getFollowedTags()
setFollowedTags(res.data)
}
2023-11-01 17:20:27 +01:00
return (
<section className="flex h-screen w-full overflow-hidden">
2024-03-08 16:42:55 +01:00
<Jump opened={openJump} close={() => setOpenJump(false)} timelines={pages} />
2024-03-09 10:26:43 +01:00
<Card className="theme-text-primary sidebar w-64 theme-bg rounded-none">
<div className="max-w-full pl-4 mt-2 mb-4 my-profile">
<p>{account?.username}</p>
<p>@{account?.domain}</p>
</div>
<List className="min-w-[64px]">
2024-10-12 07:46:04 +02:00
{pages.concat(followRequests).map(page => (
<ListItem
key={page.id}
selected={router.asPath.includes(page.path)}
onClick={() => router.push(page.path)}
2024-03-09 10:26:43 +01:00
className="sidebar-menu-item theme-text-primary overflow-hidden whitespace-nowrap"
2024-01-24 15:22:50 +01:00
title={page.title}
>
<ListItemPrefix>{page.icon}</ListItemPrefix>
2024-01-28 04:15:08 +01:00
<span className="sidebar-menu text-ellipsis whitespace-nowrap overflow-hidden">{page.title}</span>
2024-10-12 07:46:04 +02:00
{(page.id === 'notifications' && unreads[account?.id?.toString()]) ||
(page.id === 'follow_requests' && unreads[`${account.id.toString()}_follow_requests`]) ? (
2024-01-31 15:17:48 +01:00
<ListItemSuffix className="sidebar-toolchip">
2024-01-28 14:17:47 +01:00
<Chip
2024-10-12 07:46:04 +02:00
value={unreads[account.id.toString()] || unreads[`${account.id.toString()}_follow_requests`]}
2024-01-28 14:17:47 +01:00
variant="ghost"
size="sm"
2024-03-09 10:26:43 +01:00
className="rounded-full theme-text-primary theme-badge"
2024-01-28 14:17:47 +01:00
/>
</ListItemSuffix>
) : null}
</ListItem>
))}
{lists.map(list => (
<ListItem
key={list.id}
selected={router.asPath.includes(`list_${list.id}`)}
onClick={() => router.push({ pathname: `/accounts/${router.query.id}/list_${list.id}` })}
2024-03-09 10:26:43 +01:00
className="sidebar-menu-item theme-text-primary overflow-hidden whitespace-nowrap"
2024-01-24 15:22:50 +01:00
title={list.title}
>
<ListItemPrefix>
<FaList />
</ListItemPrefix>
2024-01-28 04:15:08 +01:00
<div className="sidebar-menu text-ellipsis whitespace-nowrap overflow-hidden">{list.title}</div>
</ListItem>
))}
2024-09-01 05:24:36 +02:00
{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>
</Card>
<TimelinesContext.Provider value={{ reloadMenu }}>{children}</TimelinesContext.Provider>
2023-11-01 17:20:27 +01:00
</section>
)
}