Implement status detail drawer

This commit is contained in:
AkiraFukushima 2023-11-16 00:15:44 +09:00
parent a6a7e9da52
commit 974221d001
No known key found for this signature in database
GPG Key ID: B6E51BAC4DE1A957
6 changed files with 93 additions and 2 deletions

View File

@ -0,0 +1,44 @@
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
import { FaChevronLeft, FaX } from 'react-icons/fa6'
import Thread from './Thread'
import { MegalodonInterface } from 'megalodon'
type Props = {
client: MegalodonInterface
}
export default function Detail(props: Props) {
const [target, setTarget] = useState<'status' | null>(null)
const router = useRouter()
useEffect(() => {
if (router.query.status_id) {
setTarget('status')
} else {
setTarget(null)
}
}, [router.query])
const back = () => {
router.back()
}
const close = () => {
router.push({ query: { id: router.query.id, timeline: router.query.timeline } })
}
return (
<>
{target && (
<div className="w-96 h-full fixed top-0 right-0 bg-white shadow-md">
<div className="bg-blue-900 text-gray-200 flex justify-between p-2 items-center" style={{ height: '50px' }}>
<FaChevronLeft onClick={back} className="cursor-pointer text-lg" />
<FaX onClick={close} className="cursor-pointer text-lg" />
</div>
{target === 'status' && <Thread client={props.client} status_id={router.query.status_id as string} />}
</div>
)}
</>
)
}

View File

@ -0,0 +1,38 @@
import { Entity, MegalodonInterface } from 'megalodon'
import { useEffect, useState } from 'react'
import { Virtuoso } from 'react-virtuoso'
import Status from '../timelines/status/Status'
type Props = {
client: MegalodonInterface
status_id: string
}
export default function Thread(props: Props) {
const [ancestors, setAncestors] = useState<Array<Entity.Status>>([])
const [descendants, setDescendants] = useState<Array<Entity.Status>>([])
const [status, setStatus] = useState<Entity.Status | null>(null)
useEffect(() => {
if (props.status_id) {
const f = async () => {
const s = await props.client.getStatus(props.status_id)
setStatus(s.data)
const res = await props.client.getStatusContext(props.status_id)
setAncestors(res.data.ancestors)
setDescendants(res.data.descendants)
}
f()
}
}, [props.status_id])
return (
<>
<Virtuoso
style={{ height: '100%' }}
data={[...ancestors, status, ...descendants].filter(s => s !== null)}
itemContent={(_, status) => <Status client={props.client} status={status} key={status.id} onRefresh={() => {}} />}
/>
</>
)
}

View File

@ -70,7 +70,7 @@ export default function Layout({ children }: LayoutProps) {
<Sidebar.Items>
<Sidebar.ItemGroup>
{pages.map(page => (
<Sidebar.Item key={page.id} active={`${page.path}/` === router.asPath} onClick={() => router.push(page.path)}>
<Sidebar.Item key={page.id} active={router.asPath.includes(page.path)} onClick={() => router.push(page.path)}>
{page.title}
</Sidebar.Item>
))}

View File

@ -5,6 +5,7 @@ import { useEffect, useState, useCallback, useRef } from 'react'
import { Virtuoso } from 'react-virtuoso'
import Status from './status/Status'
import { FormattedMessage, useIntl } from 'react-intl'
import Detail from '../detail/Detail'
const TIMELINE_STATUSES_COUNT = 30
const TIMELINE_MAX_STATUSES = 2147483647
@ -159,6 +160,7 @@ export default function Timeline(props: Props) {
)}
/>
</div>
<Detail client={props.client} />
</section>
)
}

View File

@ -8,6 +8,7 @@ import Card from './Card'
import Poll from './Poll'
import { FormattedMessage } from 'react-intl'
import Actions from './Actions'
import { useRouter } from 'next/router'
type Props = {
status: Entity.Status
@ -17,12 +18,17 @@ type Props = {
export default function Status(props: Props) {
const status = originalStatus(props.status)
const router = useRouter()
const onRefresh = async () => {
const res = await props.client.getStatus(status.id)
props.onRefresh(res.data)
}
const openStatus = () => {
router.push({ query: { id: router.query.id, timeline: router.query.timeline, status_id: status.id } })
}
return (
<div className="border-b mr-2 py-1">
{rebloggedHeader(props.status)}
@ -39,7 +45,7 @@ export default function Status(props: Props) {
></span>
<span className="text-gray-600 text-ellipsis break-all overflow-hidden">@{status.account.acct}</span>
</div>
<div className="text-gray-600 text-right">
<div className="text-gray-600 text-right cursor-pointer" onClick={openStatus}>
<time dateTime={status.created_at}>{dayjs(status.created_at).format('YYYY-MM-DD HH:mm:ss')}</time>
</div>
</div>

View File

@ -16,6 +16,7 @@ export default function Page() {
useEffect(() => {
if (router.query.id) {
console.log(router)
const f = async () => {
const a = await db.accounts.get(parseInt(router.query.id as string))
if (a) {