2023-02-10 17:10:13 +03:00
|
|
|
import './search.css';
|
|
|
|
|
|
|
|
import { useEffect, useRef, useState } from 'preact/hooks';
|
2023-02-12 14:36:55 +03:00
|
|
|
import { useParams, useSearchParams } from 'react-router-dom';
|
2023-02-10 17:10:13 +03:00
|
|
|
|
2023-02-12 14:29:03 +03:00
|
|
|
import AccountBlock from '../components/account-block';
|
2023-02-11 12:01:43 +03:00
|
|
|
import Icon from '../components/icon';
|
2023-02-10 17:10:13 +03:00
|
|
|
import Link from '../components/link';
|
2023-02-11 11:27:52 +03:00
|
|
|
import Loader from '../components/loader';
|
2023-02-10 17:10:13 +03:00
|
|
|
import Menu from '../components/menu';
|
|
|
|
import Status from '../components/status';
|
|
|
|
import { api } from '../utils/api';
|
2023-02-11 12:57:26 +03:00
|
|
|
import useTitle from '../utils/useTitle';
|
2023-02-10 17:10:13 +03:00
|
|
|
|
2023-02-18 15:48:24 +03:00
|
|
|
function Search(props) {
|
2023-02-12 14:36:55 +03:00
|
|
|
const params = useParams();
|
|
|
|
const { masto, instance, authenticated } = api({
|
|
|
|
instance: params.instance,
|
|
|
|
});
|
2023-02-10 19:05:18 +03:00
|
|
|
const [uiState, setUiState] = useState('default');
|
2023-02-10 17:10:13 +03:00
|
|
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
|
|
const searchFieldRef = useRef();
|
2023-02-18 15:48:24 +03:00
|
|
|
const q = props?.query || searchParams.get('q');
|
2023-02-11 12:57:26 +03:00
|
|
|
useTitle(q ? `Search: ${q}` : 'Search', `/search`);
|
|
|
|
|
2023-02-10 17:10:13 +03:00
|
|
|
const [statusResults, setStatusResults] = useState([]);
|
|
|
|
const [accountResults, setAccountResults] = useState([]);
|
2023-02-10 19:05:18 +03:00
|
|
|
const [hashtagResults, setHashtagResults] = useState([]);
|
2023-02-10 17:10:13 +03:00
|
|
|
useEffect(() => {
|
2023-02-17 20:27:59 +03:00
|
|
|
searchFieldRef.current?.focus?.();
|
2023-02-10 17:10:13 +03:00
|
|
|
if (q) {
|
|
|
|
searchFieldRef.current.value = q;
|
|
|
|
|
2023-02-10 19:05:18 +03:00
|
|
|
setUiState('loading');
|
2023-02-10 17:10:13 +03:00
|
|
|
(async () => {
|
|
|
|
const results = await masto.v2.search({
|
|
|
|
q,
|
|
|
|
limit: 20,
|
|
|
|
resolve: authenticated,
|
|
|
|
});
|
|
|
|
console.log(results);
|
|
|
|
setStatusResults(results.statuses);
|
|
|
|
setAccountResults(results.accounts);
|
2023-02-10 19:05:18 +03:00
|
|
|
setHashtagResults(results.hashtags);
|
|
|
|
setUiState('default');
|
2023-02-10 17:10:13 +03:00
|
|
|
})();
|
|
|
|
}
|
2023-02-12 14:36:55 +03:00
|
|
|
}, [q, instance]);
|
2023-02-10 17:10:13 +03:00
|
|
|
|
|
|
|
return (
|
|
|
|
<div id="search-page" class="deck-container">
|
|
|
|
<div class="timeline-deck deck">
|
|
|
|
<header>
|
|
|
|
<div class="header-grid">
|
|
|
|
<div class="header-side">
|
|
|
|
<Menu />
|
|
|
|
</div>
|
|
|
|
<form
|
|
|
|
onSubmit={(e) => {
|
|
|
|
e.preventDefault();
|
|
|
|
const { q } = e.target;
|
|
|
|
if (q.value) {
|
|
|
|
setSearchParams({ q: q.value });
|
2023-02-11 12:01:43 +03:00
|
|
|
} else {
|
|
|
|
setSearchParams({});
|
2023-02-10 17:10:13 +03:00
|
|
|
}
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<input
|
|
|
|
ref={searchFieldRef}
|
|
|
|
name="q"
|
|
|
|
type="search"
|
|
|
|
autofocus
|
2023-02-11 12:58:23 +03:00
|
|
|
placeholder="Search"
|
2023-02-11 15:39:37 +03:00
|
|
|
onSearch={(e) => {
|
|
|
|
if (!e.target.value) {
|
|
|
|
setSearchParams({});
|
|
|
|
}
|
|
|
|
}}
|
2023-02-10 17:10:13 +03:00
|
|
|
/>
|
|
|
|
</form>
|
|
|
|
<div class="header-side" />
|
|
|
|
</div>
|
|
|
|
</header>
|
|
|
|
<main>
|
2023-02-10 19:05:18 +03:00
|
|
|
{!!q && uiState !== 'loading' ? (
|
|
|
|
<>
|
|
|
|
<h2 class="timeline-header">Accounts</h2>
|
|
|
|
{accountResults.length > 0 ? (
|
|
|
|
<ul class="timeline flat accounts-list">
|
|
|
|
{accountResults.map((account) => (
|
|
|
|
<li>
|
2023-02-12 14:29:03 +03:00
|
|
|
<AccountBlock account={account} instance={instance} />
|
2023-02-10 19:05:18 +03:00
|
|
|
</li>
|
|
|
|
))}
|
|
|
|
</ul>
|
|
|
|
) : (
|
|
|
|
<p class="ui-state">No accounts found.</p>
|
|
|
|
)}
|
|
|
|
<h2 class="timeline-header">Hashtags</h2>
|
|
|
|
{hashtagResults.length > 0 ? (
|
2023-02-12 14:29:27 +03:00
|
|
|
<ul class="link-list hashtag-list">
|
2023-02-10 19:05:18 +03:00
|
|
|
{hashtagResults.map((hashtag) => (
|
|
|
|
<li>
|
|
|
|
<Link
|
|
|
|
to={
|
|
|
|
instance
|
|
|
|
? `/${instance}/t/${hashtag.name}`
|
|
|
|
: `/t/${hashtag.name}`
|
|
|
|
}
|
|
|
|
>
|
2023-02-11 12:01:43 +03:00
|
|
|
<Icon icon="hashtag" />
|
|
|
|
<span>{hashtag.name}</span>
|
2023-02-10 19:05:18 +03:00
|
|
|
</Link>
|
|
|
|
</li>
|
|
|
|
))}
|
|
|
|
</ul>
|
|
|
|
) : (
|
|
|
|
<p class="ui-state">No hashtags found.</p>
|
|
|
|
)}
|
|
|
|
<h2 class="timeline-header">Posts</h2>
|
|
|
|
{statusResults.length > 0 ? (
|
|
|
|
<ul class="timeline">
|
|
|
|
{statusResults.map((status) => (
|
|
|
|
<li>
|
|
|
|
<Link
|
|
|
|
class="status-link"
|
|
|
|
to={
|
|
|
|
instance
|
|
|
|
? `/${instance}/s/${status.id}`
|
|
|
|
: `/s/${status.id}`
|
|
|
|
}
|
|
|
|
>
|
|
|
|
<Status status={status} />
|
|
|
|
</Link>
|
|
|
|
</li>
|
|
|
|
))}
|
|
|
|
</ul>
|
|
|
|
) : (
|
|
|
|
<p class="ui-state">No posts found.</p>
|
|
|
|
)}
|
|
|
|
</>
|
2023-02-11 11:27:52 +03:00
|
|
|
) : uiState === 'loading' ? (
|
|
|
|
<p class="ui-state">
|
|
|
|
<Loader abrupt />
|
|
|
|
</p>
|
2023-02-10 19:05:18 +03:00
|
|
|
) : (
|
2023-02-11 12:57:44 +03:00
|
|
|
<p class="ui-state">
|
|
|
|
Enter your search term or paste a URL above to get started.
|
|
|
|
</p>
|
2023-02-10 17:10:13 +03:00
|
|
|
)}
|
|
|
|
</main>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export default Search;
|