2023-02-10 15:10:13 +01:00
|
|
|
|
import './search.css';
|
|
|
|
|
|
2023-10-30 02:24:36 +01:00
|
|
|
|
import { useAutoAnimate } from '@formkit/auto-animate/preact';
|
2023-09-04 08:49:39 +02:00
|
|
|
|
import { useEffect, useLayoutEffect, useRef, useState } from 'preact/hooks';
|
2024-04-15 18:09:53 +02:00
|
|
|
|
import { useHotkeys } from 'react-hotkeys-hook';
|
2023-06-28 17:36:37 +02:00
|
|
|
|
import { InView } from 'react-intersection-observer';
|
2023-02-12 12:36:55 +01:00
|
|
|
|
import { useParams, useSearchParams } from 'react-router-dom';
|
2023-02-10 15:10:13 +01:00
|
|
|
|
|
2023-02-12 12:29:03 +01:00
|
|
|
|
import AccountBlock from '../components/account-block';
|
2023-02-11 10:01:43 +01:00
|
|
|
|
import Icon from '../components/icon';
|
2023-02-10 15:10:13 +01:00
|
|
|
|
import Link from '../components/link';
|
2023-02-11 09:27:52 +01:00
|
|
|
|
import Loader from '../components/loader';
|
2023-04-26 07:09:44 +02:00
|
|
|
|
import NavMenu from '../components/nav-menu';
|
2023-09-04 08:49:39 +02:00
|
|
|
|
import SearchForm from '../components/search-form';
|
2023-02-10 15:10:13 +01:00
|
|
|
|
import Status from '../components/status';
|
|
|
|
|
import { api } from '../utils/api';
|
2023-12-20 06:55:56 +01:00
|
|
|
|
import { fetchRelationships } from '../utils/relationships';
|
2023-10-30 02:22:19 +01:00
|
|
|
|
import shortenNumber from '../utils/shorten-number';
|
2023-12-22 11:01:41 +01:00
|
|
|
|
import usePageVisibility from '../utils/usePageVisibility';
|
2023-02-11 10:57:26 +01:00
|
|
|
|
import useTitle from '../utils/useTitle';
|
2023-02-10 15:10:13 +01:00
|
|
|
|
|
2023-06-28 17:36:37 +02:00
|
|
|
|
const SHORT_LIMIT = 5;
|
|
|
|
|
const LIMIT = 40;
|
2023-12-22 11:01:41 +01:00
|
|
|
|
const emptySearchParams = new URLSearchParams();
|
2023-06-28 17:36:37 +02:00
|
|
|
|
|
2023-12-22 11:01:41 +01:00
|
|
|
|
function Search({ columnMode, ...props }) {
|
|
|
|
|
const params = columnMode ? {} : useParams();
|
2023-02-12 12:36:55 +01:00
|
|
|
|
const { masto, instance, authenticated } = api({
|
|
|
|
|
instance: params.instance,
|
|
|
|
|
});
|
2023-08-14 05:22:42 +02:00
|
|
|
|
const [uiState, setUIState] = useState('default');
|
2023-12-22 11:01:41 +01:00
|
|
|
|
const [searchParams] = columnMode ? [emptySearchParams] : useSearchParams();
|
2023-04-29 14:59:51 +02:00
|
|
|
|
const searchFormRef = useRef();
|
2023-02-18 13:48:24 +01:00
|
|
|
|
const q = props?.query || searchParams.get('q');
|
2023-12-22 11:01:41 +01:00
|
|
|
|
const type = columnMode
|
|
|
|
|
? 'statuses'
|
|
|
|
|
: props?.type || searchParams.get('type');
|
2023-04-29 14:59:51 +02:00
|
|
|
|
useTitle(
|
|
|
|
|
q
|
|
|
|
|
? `Search: ${q}${
|
|
|
|
|
type
|
|
|
|
|
? ` (${
|
|
|
|
|
{
|
|
|
|
|
statuses: 'Posts',
|
|
|
|
|
accounts: 'Accounts',
|
|
|
|
|
hashtags: 'Hashtags',
|
|
|
|
|
}[type]
|
|
|
|
|
})`
|
|
|
|
|
: ''
|
|
|
|
|
}`
|
|
|
|
|
: 'Search',
|
|
|
|
|
`/search`,
|
|
|
|
|
);
|
2023-02-11 10:57:26 +01:00
|
|
|
|
|
2023-06-28 17:36:37 +02:00
|
|
|
|
const [showMore, setShowMore] = useState(false);
|
|
|
|
|
const offsetRef = useRef(0);
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
offsetRef.current = 0;
|
2023-07-14 07:16:41 +02:00
|
|
|
|
}, [q, type]);
|
2023-06-28 17:36:37 +02:00
|
|
|
|
|
|
|
|
|
const scrollableRef = useRef();
|
|
|
|
|
useLayoutEffect(() => {
|
|
|
|
|
scrollableRef.current?.scrollTo?.(0, 0);
|
|
|
|
|
}, [q, type]);
|
|
|
|
|
|
2023-02-10 15:10:13 +01:00
|
|
|
|
const [statusResults, setStatusResults] = useState([]);
|
|
|
|
|
const [accountResults, setAccountResults] = useState([]);
|
2023-02-10 17:05:18 +01:00
|
|
|
|
const [hashtagResults, setHashtagResults] = useState([]);
|
2023-07-14 07:16:41 +02:00
|
|
|
|
useEffect(() => {
|
|
|
|
|
setStatusResults([]);
|
|
|
|
|
setAccountResults([]);
|
|
|
|
|
setHashtagResults([]);
|
|
|
|
|
}, [q]);
|
|
|
|
|
const setTypeResultsFunc = {
|
|
|
|
|
statuses: setStatusResults,
|
|
|
|
|
accounts: setAccountResults,
|
|
|
|
|
hashtags: setHashtagResults,
|
|
|
|
|
};
|
2023-06-28 17:36:37 +02:00
|
|
|
|
|
2023-12-20 06:55:56 +01:00
|
|
|
|
const [relationshipsMap, setRelationshipsMap] = useState({});
|
|
|
|
|
const loadRelationships = async (accounts) => {
|
|
|
|
|
if (!accounts?.length) return;
|
|
|
|
|
const relationships = await fetchRelationships(accounts, relationshipsMap);
|
|
|
|
|
if (relationships) {
|
|
|
|
|
setRelationshipsMap({
|
|
|
|
|
...relationshipsMap,
|
|
|
|
|
...relationships,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-06-28 17:36:37 +02:00
|
|
|
|
function loadResults(firstLoad) {
|
2023-12-22 11:01:41 +01:00
|
|
|
|
if (firstLoad) {
|
|
|
|
|
offsetRef.current = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-26 11:39:10 +02:00
|
|
|
|
if (!firstLoad && !authenticated) {
|
|
|
|
|
// Search results pagination is only available to authenticated users
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-14 05:22:42 +02:00
|
|
|
|
setUIState('loading');
|
2023-06-28 17:36:37 +02:00
|
|
|
|
if (firstLoad && !type) {
|
|
|
|
|
setStatusResults(statusResults.slice(0, SHORT_LIMIT));
|
|
|
|
|
setAccountResults(accountResults.slice(0, SHORT_LIMIT));
|
|
|
|
|
setHashtagResults(hashtagResults.slice(0, SHORT_LIMIT));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(async () => {
|
|
|
|
|
const params = {
|
|
|
|
|
q,
|
|
|
|
|
resolve: authenticated,
|
|
|
|
|
limit: SHORT_LIMIT,
|
|
|
|
|
};
|
|
|
|
|
if (type) {
|
|
|
|
|
params.limit = LIMIT;
|
|
|
|
|
params.type = type;
|
2023-09-15 07:08:34 +02:00
|
|
|
|
if (authenticated) params.offset = offsetRef.current;
|
2023-06-28 17:36:37 +02:00
|
|
|
|
}
|
2023-10-26 11:39:10 +02:00
|
|
|
|
|
2023-06-28 17:36:37 +02:00
|
|
|
|
try {
|
2023-10-12 06:48:09 +02:00
|
|
|
|
const results = await masto.v2.search.fetch(params);
|
2023-06-28 17:36:37 +02:00
|
|
|
|
console.log(results);
|
2023-07-14 07:16:41 +02:00
|
|
|
|
if (type) {
|
|
|
|
|
if (firstLoad) {
|
|
|
|
|
setTypeResultsFunc[type](results[type]);
|
|
|
|
|
const length = results[type]?.length;
|
|
|
|
|
offsetRef.current = LIMIT;
|
|
|
|
|
setShowMore(!!length);
|
|
|
|
|
} else {
|
|
|
|
|
setTypeResultsFunc[type]((prev) => [...prev, ...results[type]]);
|
|
|
|
|
const length = results[type]?.length;
|
|
|
|
|
offsetRef.current = offsetRef.current + LIMIT;
|
|
|
|
|
setShowMore(!!length);
|
2023-06-28 17:36:37 +02:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2023-12-03 04:00:24 +01:00
|
|
|
|
setStatusResults(results.statuses || []);
|
|
|
|
|
setAccountResults(results.accounts || []);
|
|
|
|
|
setHashtagResults(results.hashtags || []);
|
2023-07-14 07:16:41 +02:00
|
|
|
|
offsetRef.current = 0;
|
|
|
|
|
setShowMore(false);
|
2023-06-28 17:36:37 +02:00
|
|
|
|
}
|
2023-12-20 06:55:56 +01:00
|
|
|
|
loadRelationships(results.accounts);
|
|
|
|
|
|
2023-08-14 05:22:42 +02:00
|
|
|
|
setUIState('default');
|
2023-06-28 17:36:37 +02:00
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error(err);
|
2023-08-14 05:22:42 +02:00
|
|
|
|
setUIState('error');
|
2023-06-28 17:36:37 +02:00
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-22 11:01:41 +01:00
|
|
|
|
const lastHiddenTime = useRef();
|
|
|
|
|
usePageVisibility((visible) => {
|
2024-01-02 05:20:36 +01:00
|
|
|
|
const reachStart = scrollableRef.current?.scrollTop === 0;
|
2023-12-22 11:01:41 +01:00
|
|
|
|
if (visible && reachStart) {
|
|
|
|
|
const timeDiff = Date.now() - lastHiddenTime.current;
|
|
|
|
|
if (!lastHiddenTime.current || timeDiff > 1000 * 3) {
|
|
|
|
|
// 3 seconds
|
|
|
|
|
loadResults(true);
|
|
|
|
|
} else {
|
|
|
|
|
lastHiddenTime.current = Date.now();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2023-02-10 15:10:13 +01:00
|
|
|
|
useEffect(() => {
|
2023-12-22 16:03:05 +01:00
|
|
|
|
searchFormRef.current?.setValue?.(q || '');
|
2023-02-10 15:10:13 +01:00
|
|
|
|
if (q) {
|
2023-06-28 17:36:37 +02:00
|
|
|
|
loadResults(true);
|
2023-09-04 08:49:39 +02:00
|
|
|
|
} else {
|
|
|
|
|
searchFormRef.current?.focus?.();
|
2023-02-10 15:10:13 +01:00
|
|
|
|
}
|
2023-04-29 14:59:51 +02:00
|
|
|
|
}, [q, type, instance]);
|
2023-02-10 15:10:13 +01:00
|
|
|
|
|
2023-09-04 08:49:39 +02:00
|
|
|
|
useHotkeys(
|
2024-01-09 17:03:36 +01:00
|
|
|
|
['/', 'Slash'],
|
2023-09-04 08:49:39 +02:00
|
|
|
|
(e) => {
|
|
|
|
|
searchFormRef.current?.focus?.();
|
2024-04-03 03:28:59 +02:00
|
|
|
|
searchFormRef.current?.select?.();
|
2023-09-04 08:49:39 +02:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
preventDefault: true,
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
2023-10-30 02:24:36 +01:00
|
|
|
|
const [filterBarParent] = useAutoAnimate();
|
|
|
|
|
|
2023-02-10 15:10:13 +01:00
|
|
|
|
return (
|
2023-06-28 17:36:37 +02:00
|
|
|
|
<div id="search-page" class="deck-container" ref={scrollableRef}>
|
2023-02-10 15:10:13 +01:00
|
|
|
|
<div class="timeline-deck deck">
|
2023-10-20 06:53:23 +02:00
|
|
|
|
<header class={uiState === 'loading' ? 'loading' : ''}>
|
2023-02-10 15:10:13 +01:00
|
|
|
|
<div class="header-grid">
|
|
|
|
|
<div class="header-side">
|
2023-04-26 07:09:44 +02:00
|
|
|
|
<NavMenu />
|
2023-02-10 15:10:13 +01:00
|
|
|
|
</div>
|
2023-04-29 14:59:51 +02:00
|
|
|
|
<SearchForm ref={searchFormRef} />
|
2023-12-22 11:01:41 +01:00
|
|
|
|
<div class="header-side">
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
class="plain"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
loadResults(true);
|
|
|
|
|
}}
|
|
|
|
|
disabled={uiState === 'loading'}
|
|
|
|
|
>
|
|
|
|
|
<Icon icon="search" size="l" />
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
2023-02-10 15:10:13 +01:00
|
|
|
|
</div>
|
|
|
|
|
</header>
|
|
|
|
|
<main>
|
2023-12-22 11:01:41 +01:00
|
|
|
|
{!!q && !columnMode && (
|
2023-10-30 02:24:36 +01:00
|
|
|
|
<div
|
|
|
|
|
ref={filterBarParent}
|
|
|
|
|
class={`filter-bar ${uiState === 'loading' ? 'loading' : ''}`}
|
|
|
|
|
>
|
2023-09-04 11:01:06 +02:00
|
|
|
|
{!!type && (
|
|
|
|
|
<Link to={`/search${q ? `?q=${encodeURIComponent(q)}` : ''}`}>
|
|
|
|
|
‹ All
|
|
|
|
|
</Link>
|
|
|
|
|
)}
|
2023-04-29 14:59:51 +02:00
|
|
|
|
{[
|
|
|
|
|
{
|
|
|
|
|
label: 'Accounts',
|
|
|
|
|
type: 'accounts',
|
2023-09-04 11:01:06 +02:00
|
|
|
|
to: `/search?q=${encodeURIComponent(q)}&type=accounts`,
|
2023-04-29 14:59:51 +02:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: 'Hashtags',
|
|
|
|
|
type: 'hashtags',
|
2023-09-04 11:01:06 +02:00
|
|
|
|
to: `/search?q=${encodeURIComponent(q)}&type=hashtags`,
|
2023-04-29 14:59:51 +02:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: 'Posts',
|
|
|
|
|
type: 'statuses',
|
2023-09-04 11:01:06 +02:00
|
|
|
|
to: `/search?q=${encodeURIComponent(q)}&type=statuses`,
|
2023-04-29 14:59:51 +02:00
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
.sort((a, b) => {
|
|
|
|
|
if (a.type === type) return -1;
|
|
|
|
|
if (b.type === type) return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
})
|
|
|
|
|
.map((link) => (
|
2023-10-20 06:52:56 +02:00
|
|
|
|
<Link to={link.to} key={link.type}>
|
|
|
|
|
{link.label}
|
|
|
|
|
</Link>
|
2023-04-29 14:59:51 +02:00
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2023-06-28 17:36:37 +02:00
|
|
|
|
{!!q ? (
|
2023-02-10 17:05:18 +01:00
|
|
|
|
<>
|
2023-04-29 14:59:51 +02:00
|
|
|
|
{(!type || type === 'accounts') && (
|
|
|
|
|
<>
|
|
|
|
|
{type !== 'accounts' && (
|
2024-01-29 14:11:08 +01:00
|
|
|
|
<h2 class="timeline-header">
|
|
|
|
|
Accounts{' '}
|
|
|
|
|
<Link
|
|
|
|
|
to={`/search?q=${encodeURIComponent(q)}&type=accounts`}
|
|
|
|
|
>
|
|
|
|
|
<Icon icon="arrow-right" size="l" />
|
|
|
|
|
</Link>
|
|
|
|
|
</h2>
|
2023-04-29 14:59:51 +02:00
|
|
|
|
)}
|
|
|
|
|
{accountResults.length > 0 ? (
|
|
|
|
|
<>
|
|
|
|
|
<ul class="timeline flat accounts-list">
|
|
|
|
|
{accountResults.map((account) => (
|
2023-06-30 03:48:52 +02:00
|
|
|
|
<li key={account.id}>
|
2023-04-29 14:59:51 +02:00
|
|
|
|
<AccountBlock
|
|
|
|
|
account={account}
|
|
|
|
|
instance={instance}
|
2023-07-02 12:02:30 +02:00
|
|
|
|
showStats
|
2023-12-20 06:55:56 +01:00
|
|
|
|
relationship={relationshipsMap[account.id]}
|
2023-04-29 14:59:51 +02:00
|
|
|
|
/>
|
|
|
|
|
</li>
|
|
|
|
|
))}
|
|
|
|
|
</ul>
|
|
|
|
|
{type !== 'accounts' && (
|
|
|
|
|
<div class="ui-state">
|
|
|
|
|
<Link
|
|
|
|
|
class="plain button"
|
2024-01-29 14:11:08 +01:00
|
|
|
|
to={`/search?q=${encodeURIComponent(
|
|
|
|
|
q,
|
|
|
|
|
)}&type=accounts`}
|
2023-04-29 14:59:51 +02:00
|
|
|
|
>
|
|
|
|
|
See more accounts <Icon icon="arrow-right" />
|
|
|
|
|
</Link>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</>
|
|
|
|
|
) : (
|
2023-06-30 03:48:52 +02:00
|
|
|
|
!type &&
|
|
|
|
|
(uiState === 'loading' ? (
|
|
|
|
|
<p class="ui-state">
|
|
|
|
|
<Loader abrupt />
|
|
|
|
|
</p>
|
|
|
|
|
) : (
|
|
|
|
|
<p class="ui-state">No accounts found.</p>
|
|
|
|
|
))
|
2023-04-29 14:59:51 +02:00
|
|
|
|
)}
|
|
|
|
|
</>
|
2023-02-10 17:05:18 +01:00
|
|
|
|
)}
|
2023-04-29 14:59:51 +02:00
|
|
|
|
{(!type || type === 'hashtags') && (
|
|
|
|
|
<>
|
|
|
|
|
{type !== 'hashtags' && (
|
2024-01-29 14:11:08 +01:00
|
|
|
|
<h2 class="timeline-header">
|
|
|
|
|
Hashtags{' '}
|
|
|
|
|
<Link
|
|
|
|
|
to={`/search?q=${encodeURIComponent(q)}&type=hashtags`}
|
|
|
|
|
>
|
|
|
|
|
<Icon icon="arrow-right" size="l" />
|
|
|
|
|
</Link>
|
|
|
|
|
</h2>
|
2023-04-29 14:59:51 +02:00
|
|
|
|
)}
|
|
|
|
|
{hashtagResults.length > 0 ? (
|
|
|
|
|
<>
|
|
|
|
|
<ul class="link-list hashtag-list">
|
2023-10-30 02:22:19 +01:00
|
|
|
|
{hashtagResults.map((hashtag) => {
|
|
|
|
|
const { name, history } = hashtag;
|
2023-12-03 06:09:05 +01:00
|
|
|
|
const total = history?.reduce?.(
|
2023-10-30 02:22:19 +01:00
|
|
|
|
(acc, cur) => acc + +cur.uses,
|
|
|
|
|
0,
|
|
|
|
|
);
|
|
|
|
|
return (
|
2023-12-03 06:09:05 +01:00
|
|
|
|
<li key={`${name}-${total}`}>
|
2023-10-30 02:22:19 +01:00
|
|
|
|
<Link
|
|
|
|
|
to={
|
|
|
|
|
instance
|
2023-12-03 06:09:05 +01:00
|
|
|
|
? `/${instance}/t/${name}`
|
|
|
|
|
: `/t/${name}`
|
2023-10-30 02:22:19 +01:00
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
<Icon icon="hashtag" />
|
2023-12-03 06:09:05 +01:00
|
|
|
|
<span>{name}</span>
|
2023-10-30 02:22:19 +01:00
|
|
|
|
{!!total && (
|
|
|
|
|
<span class="count">
|
|
|
|
|
{shortenNumber(total)}
|
|
|
|
|
</span>
|
|
|
|
|
)}
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
);
|
|
|
|
|
})}
|
2023-04-29 14:59:51 +02:00
|
|
|
|
</ul>
|
|
|
|
|
{type !== 'hashtags' && (
|
|
|
|
|
<div class="ui-state">
|
|
|
|
|
<Link
|
|
|
|
|
class="plain button"
|
2024-01-29 14:11:08 +01:00
|
|
|
|
to={`/search?q=${encodeURIComponent(
|
|
|
|
|
q,
|
|
|
|
|
)}&type=hashtags`}
|
2023-04-29 14:59:51 +02:00
|
|
|
|
>
|
|
|
|
|
See more hashtags <Icon icon="arrow-right" />
|
|
|
|
|
</Link>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</>
|
|
|
|
|
) : (
|
2023-06-30 03:48:52 +02:00
|
|
|
|
!type &&
|
|
|
|
|
(uiState === 'loading' ? (
|
|
|
|
|
<p class="ui-state">
|
|
|
|
|
<Loader abrupt />
|
|
|
|
|
</p>
|
|
|
|
|
) : (
|
|
|
|
|
<p class="ui-state">No hashtags found.</p>
|
|
|
|
|
))
|
2023-04-29 14:59:51 +02:00
|
|
|
|
)}
|
|
|
|
|
</>
|
2023-02-10 17:05:18 +01:00
|
|
|
|
)}
|
2023-04-29 14:59:51 +02:00
|
|
|
|
{(!type || type === 'statuses') && (
|
|
|
|
|
<>
|
|
|
|
|
{type !== 'statuses' && (
|
2024-01-29 14:11:08 +01:00
|
|
|
|
<h2 class="timeline-header">
|
|
|
|
|
Posts{' '}
|
|
|
|
|
<Link
|
|
|
|
|
to={`/search?q=${encodeURIComponent(q)}&type=statuses`}
|
|
|
|
|
>
|
|
|
|
|
<Icon icon="arrow-right" size="l" />
|
|
|
|
|
</Link>
|
|
|
|
|
</h2>
|
2023-04-29 14:59:51 +02:00
|
|
|
|
)}
|
|
|
|
|
{statusResults.length > 0 ? (
|
|
|
|
|
<>
|
|
|
|
|
<ul class="timeline">
|
|
|
|
|
{statusResults.map((status) => (
|
2023-06-30 03:48:52 +02:00
|
|
|
|
<li key={status.id}>
|
2023-04-29 14:59:51 +02:00
|
|
|
|
<Link
|
|
|
|
|
class="status-link"
|
|
|
|
|
to={
|
|
|
|
|
instance
|
|
|
|
|
? `/${instance}/s/${status.id}`
|
|
|
|
|
: `/s/${status.id}`
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
<Status status={status} />
|
|
|
|
|
</Link>
|
|
|
|
|
</li>
|
|
|
|
|
))}
|
|
|
|
|
</ul>
|
|
|
|
|
{type !== 'statuses' && (
|
|
|
|
|
<div class="ui-state">
|
|
|
|
|
<Link
|
|
|
|
|
class="plain button"
|
2024-01-29 14:11:08 +01:00
|
|
|
|
to={`/search?q=${encodeURIComponent(
|
|
|
|
|
q,
|
|
|
|
|
)}&type=statuses`}
|
2023-04-29 14:59:51 +02:00
|
|
|
|
>
|
|
|
|
|
See more posts <Icon icon="arrow-right" />
|
|
|
|
|
</Link>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</>
|
|
|
|
|
) : (
|
2023-06-30 03:48:52 +02:00
|
|
|
|
!type &&
|
|
|
|
|
(uiState === 'loading' ? (
|
|
|
|
|
<p class="ui-state">
|
|
|
|
|
<Loader abrupt />
|
|
|
|
|
</p>
|
|
|
|
|
) : (
|
|
|
|
|
<p class="ui-state">No posts found.</p>
|
|
|
|
|
))
|
2023-04-29 14:59:51 +02:00
|
|
|
|
)}
|
|
|
|
|
</>
|
2023-02-10 17:05:18 +01:00
|
|
|
|
)}
|
2023-06-28 17:36:37 +02:00
|
|
|
|
{!!type &&
|
|
|
|
|
(uiState === 'default' ? (
|
|
|
|
|
showMore ? (
|
|
|
|
|
<InView
|
|
|
|
|
onChange={(inView) => {
|
|
|
|
|
if (inView) {
|
|
|
|
|
loadResults();
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
class="plain block"
|
|
|
|
|
onClick={() => loadResults()}
|
|
|
|
|
style={{ marginBlockEnd: '6em' }}
|
|
|
|
|
>
|
|
|
|
|
Show more…
|
|
|
|
|
</button>
|
|
|
|
|
</InView>
|
|
|
|
|
) : (
|
|
|
|
|
<p class="ui-state insignificant">The end.</p>
|
|
|
|
|
)
|
|
|
|
|
) : (
|
2023-07-14 07:16:41 +02:00
|
|
|
|
uiState === 'loading' && (
|
2023-06-28 17:36:37 +02:00
|
|
|
|
<p class="ui-state">
|
|
|
|
|
<Loader abrupt />
|
|
|
|
|
</p>
|
|
|
|
|
)
|
|
|
|
|
))}
|
2023-02-10 17:05:18 +01:00
|
|
|
|
</>
|
2023-02-11 09:27:52 +01:00
|
|
|
|
) : uiState === 'loading' ? (
|
|
|
|
|
<p class="ui-state">
|
|
|
|
|
<Loader abrupt />
|
|
|
|
|
</p>
|
2023-02-10 17:05:18 +01:00
|
|
|
|
) : (
|
2023-02-11 10:57:44 +01:00
|
|
|
|
<p class="ui-state">
|
|
|
|
|
Enter your search term or paste a URL above to get started.
|
|
|
|
|
</p>
|
2023-02-10 15:10:13 +01:00
|
|
|
|
)}
|
|
|
|
|
</main>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default Search;
|