-
+
diff --git a/renderer/components/timelines/Search.tsx b/renderer/components/timelines/Search.tsx
new file mode 100644
index 00000000..26bcfcde
--- /dev/null
+++ b/renderer/components/timelines/Search.tsx
@@ -0,0 +1,104 @@
+import { Input, Tab, TabPanel, Tabs, TabsBody, TabsHeader } from '@material-tailwind/react'
+import { Entity, MegalodonInterface } from 'megalodon'
+import { useRouter } from 'next/router'
+import { FormEvent, useEffect, useState } from 'react'
+import { FaMagnifyingGlass } from 'react-icons/fa6'
+import { FormattedMessage, useIntl } from 'react-intl'
+import Statuses from './search/Statuses'
+import { Account } from '@/db'
+
+type Props = {
+ client: MegalodonInterface
+ account: Account
+ openMedia: (media: Array, index: number) => void
+}
+
+export default function Search(props: Props) {
+ const router = useRouter()
+ const { formatMessage } = useIntl()
+
+ const [query, setQuery] = useState('')
+ const [activeTab, setActiveTab] = useState('statuses')
+ const [results, setResults] = useState({
+ accounts: [],
+ hashtags: [],
+ statuses: []
+ })
+
+ useEffect(() => {
+ if (router.query.q) {
+ setQuery(router.query.q as string)
+ search(router.query.q as string)
+ }
+ }, [router.query.q])
+
+ const search = (query: string) => {
+ setResults({
+ accounts: [],
+ hashtags: [],
+ statuses: []
+ })
+ props.client.search(query).then(res => {
+ setResults(res.data)
+ })
+ }
+
+ const submit = (ev: FormEvent) => {
+ ev.preventDefault()
+ const word = ((ev.target as HTMLFormElement).elements[0] as HTMLInputElement).value
+ if (word.length > 0) {
+ router.push({
+ query: Object.assign({}, router.query, {
+ timeline: 'search',
+ q: word
+ })
+ })
+ }
+ }
+
+ return (
+ <>
+
+
+
+
+
+
+
+ setActiveTab('statuses')}>
+
+
+ setActiveTab('accounts')}>
+
+
+ setActiveTab('hashtags')}>
+
+
+
+
+
+
+
+ accounts
+ hashtags
+
+
+
+
+ >
+ )
+}
diff --git a/renderer/components/timelines/Timeline.tsx b/renderer/components/timelines/Timeline.tsx
index 65a305b9..b4e5bb04 100644
--- a/renderer/components/timelines/Timeline.tsx
+++ b/renderer/components/timelines/Timeline.tsx
@@ -1,6 +1,6 @@
import { Account } from '@/db'
import { Entity, MegalodonInterface, WebSocketInterface } from 'megalodon'
-import { useEffect, useState, useCallback, useRef } from 'react'
+import { useEffect, useState, useCallback, useRef, FormEvent } from 'react'
import { Virtuoso } from 'react-virtuoso'
import Status from './status/Status'
import { FormattedMessage, useIntl } from 'react-intl'
@@ -244,6 +244,19 @@ export default function Timeline(props: Props) {
})
}
+ const search = (ev: FormEvent) => {
+ ev.preventDefault()
+ const word = ((ev.target as HTMLFormElement).elements[0] as HTMLInputElement).value
+ if (word.length > 0) {
+ router.push({
+ query: Object.assign({}, router.query, {
+ timeline: 'search',
+ q: word
+ })
+ })
+ }
+ }
+
return (
@@ -252,14 +265,13 @@ export default function Timeline(props: Props) {
{props.timeline.match(/list_(\d+)/) ? <>{list && list.title}> : }
-
diff --git a/renderer/components/timelines/search/Statuses.tsx b/renderer/components/timelines/search/Statuses.tsx
new file mode 100644
index 00000000..23c7bed0
--- /dev/null
+++ b/renderer/components/timelines/search/Statuses.tsx
@@ -0,0 +1,43 @@
+import { Entity, MegalodonInterface } from 'megalodon'
+import { Virtuoso } from 'react-virtuoso'
+import Status from '../status/Status'
+import { Account } from '@/db'
+import { Spinner } from '@material-tailwind/react'
+
+type Props = {
+ client: MegalodonInterface
+ account: Account
+ statuses: Array
+ openMedia: (media: Array, index: number) => void
+}
+
+export default function Statuses(props: Props) {
+ return (
+ <>
+
+ {props.statuses.length > 0 ? (
+
(
+ {}}
+ filters={[]}
+ />
+ )}
+ />
+ ) : (
+
+
+
+ )}
+
+ >
+ )
+}
diff --git a/renderer/pages/_app.tsx b/renderer/pages/_app.tsx
index 9579946c..053930a7 100644
--- a/renderer/pages/_app.tsx
+++ b/renderer/pages/_app.tsx
@@ -340,12 +340,7 @@ export default function MyApp({ Component, pageProps }: AppProps) {
},
tabsHeader: {
defaultProps: {
- className: ''
- },
- styles: {
- base: {
- bg: 'bg-blue-gray-50 dark:bg-blue-gray-800'
- }
+ className: 'rounded-none border-b border-blue-gray-50 dark:border-blue-gray-900 bg-transparent p-0'
}
},
tab: {
@@ -360,9 +355,6 @@ export default function MyApp({ Component, pageProps }: AppProps) {
initial: {
color: 'text-blue-gray-900 dark:text-blue-gray-200'
}
- },
- indicator: {
- bg: 'bg-white dark:bg-gray-700'
}
}
}
diff --git a/renderer/pages/accounts/[id]/[timeline].tsx b/renderer/pages/accounts/[id]/[timeline].tsx
index 0f72773d..8b3eaab3 100644
--- a/renderer/pages/accounts/[id]/[timeline].tsx
+++ b/renderer/pages/accounts/[id]/[timeline].tsx
@@ -4,6 +4,7 @@ import { useEffect, useReducer, useState } from 'react'
import { Account, db } from '@/db'
import generator, { Entity, MegalodonInterface } from 'megalodon'
import Notifications from '@/components/timelines/Notifications'
+import Search from '@/components/timelines/Search'
import Media from '@/components/Media'
import Report from '@/components/report/Report'
@@ -69,14 +70,26 @@ export default function Page() {
}
/>
) : (
- , index: number) =>
- dispatch({ target: 'media', value: true, object: media, index: index })
- }
- />
+ <>
+ {(router.query.timeline as string) === 'search' ? (
+ , index: number) =>
+ dispatch({ target: 'media', value: true, object: media, index: index })
+ }
+ />
+ ) : (
+ , index: number) =>
+ dispatch({ target: 'media', value: true, object: media, index: index })
+ }
+ />
+ )}
+ >
)}
Date: Mon, 24 Jun 2024 01:29:28 +0900
Subject: [PATCH 2/4] refs #4792 Implement search for accounts
---
renderer/components/timelines/Search.tsx | 26 ++++++--
.../components/timelines/search/Accounts.tsx | 66 +++++++++++++++++++
.../components/timelines/search/Statuses.tsx | 11 +++-
3 files changed, 95 insertions(+), 8 deletions(-)
create mode 100644 renderer/components/timelines/search/Accounts.tsx
diff --git a/renderer/components/timelines/Search.tsx b/renderer/components/timelines/Search.tsx
index 26bcfcde..017a7a21 100644
--- a/renderer/components/timelines/Search.tsx
+++ b/renderer/components/timelines/Search.tsx
@@ -6,6 +6,7 @@ import { FaMagnifyingGlass } from 'react-icons/fa6'
import { FormattedMessage, useIntl } from 'react-intl'
import Statuses from './search/Statuses'
import { Account } from '@/db'
+import Accounts from './search/Accounts'
type Props = {
client: MegalodonInterface
@@ -24,6 +25,7 @@ export default function Search(props: Props) {
hashtags: [],
statuses: []
})
+ const [loading, setLoading] = useState(false)
useEffect(() => {
if (router.query.q) {
@@ -33,14 +35,20 @@ export default function Search(props: Props) {
}, [router.query.q])
const search = (query: string) => {
+ setLoading(true)
setResults({
accounts: [],
hashtags: [],
statuses: []
})
- props.client.search(query).then(res => {
- setResults(res.data)
- })
+ props.client
+ .search(query)
+ .then(res => {
+ setResults(res.data)
+ })
+ .finally(() => {
+ setLoading(false)
+ })
}
const submit = (ev: FormEvent) => {
@@ -91,9 +99,17 @@ export default function Search(props: Props) {
-
+
+
+
+
- accounts
hashtags
diff --git a/renderer/components/timelines/search/Accounts.tsx b/renderer/components/timelines/search/Accounts.tsx
new file mode 100644
index 00000000..6215db05
--- /dev/null
+++ b/renderer/components/timelines/search/Accounts.tsx
@@ -0,0 +1,66 @@
+import { Avatar, Spinner } from '@material-tailwind/react'
+import { Entity, MegalodonInterface } from 'megalodon'
+import emojify from '@/utils/emojify'
+import { Virtuoso } from 'react-virtuoso'
+import { useRouter } from 'next/router'
+
+type Props = {
+ client: MegalodonInterface
+ users: Array
+ loading: boolean
+}
+
+export default function Accounts(props: Props) {
+ const router = useRouter()
+
+ const openUser = (id: string) => {
+ router.push({ query: { id: router.query.id, timeline: router.query.timeline, user_id: id, detail: true } })
+ }
+
+ return (
+ <>
+
+ {props.users.length > 0 ? (
+
}
+ />
+ ) : (
+ <>
+ {props.loading && (
+
+
+
+ )}
+ >
+ )}
+
+ >
+ )
+}
+
+type UserProps = {
+ user: Entity.Account
+ openUser: (id: string) => void
+}
+
+function User(props: UserProps) {
+ return (
+
+
props.openUser(props.user.id)}>
+
+
+
+
+ )
+}
diff --git a/renderer/components/timelines/search/Statuses.tsx b/renderer/components/timelines/search/Statuses.tsx
index 23c7bed0..4f214dc5 100644
--- a/renderer/components/timelines/search/Statuses.tsx
+++ b/renderer/components/timelines/search/Statuses.tsx
@@ -8,6 +8,7 @@ type Props = {
client: MegalodonInterface
account: Account
statuses: Array
+ loading: boolean
openMedia: (media: Array, index: number) => void
}
@@ -33,9 +34,13 @@ export default function Statuses(props: Props) {
)}
/>
) : (
-
-
-
+ <>
+ {props.loading && (
+
+
+
+ )}
+ >
)}
>
From 247116ebcbfe7d04b212afa95a30a2b2507d18b4 Mon Sep 17 00:00:00 2001
From: AkiraFukushima