phanpy/src/pages/account-statuses.jsx

198 lines
5.6 KiB
React
Raw Normal View History

import { useEffect, useMemo, useRef, useState } from 'preact/hooks';
2023-04-03 05:36:31 +03:00
import { useParams, useSearchParams } from 'react-router-dom';
2023-02-03 16:08:08 +03:00
import { useSnapshot } from 'valtio';
import AccountInfo from '../components/account-info';
2023-04-03 05:36:31 +03:00
import Icon from '../components/icon';
import Link from '../components/link';
import Timeline from '../components/timeline';
import { api } from '../utils/api';
import emojifyText from '../utils/emojify-text';
2023-01-31 14:08:10 +03:00
import states from '../utils/states';
import { saveStatus } from '../utils/states';
2023-02-03 16:08:08 +03:00
import useTitle from '../utils/useTitle';
const LIMIT = 20;
function AccountStatuses() {
2023-02-03 16:08:08 +03:00
const snapStates = useSnapshot(states);
const { id, ...params } = useParams();
2023-04-03 05:36:31 +03:00
const [searchParams, setSearchParams] = useSearchParams();
const excludeReplies = !searchParams.get('replies');
const tagged = searchParams.get('tagged');
const media = !!searchParams.get('media');
console.log({ excludeReplies });
const { masto, instance, authenticated } = api({ instance: params.instance });
const accountStatusesIterator = useRef();
async function fetchAccountStatuses(firstLoad) {
2023-02-17 05:12:59 +03:00
const results = [];
if (firstLoad) {
const { value: pinnedStatuses } = await masto.v1.accounts
.listStatuses(id, {
pinned: true,
})
.next();
2023-04-03 05:36:31 +03:00
if (pinnedStatuses?.length && !tagged && !media) {
2023-02-17 05:12:59 +03:00
pinnedStatuses.forEach((status) => {
status._pinned = true;
2023-03-18 17:25:02 +03:00
saveStatus(status, instance);
2023-02-17 05:12:59 +03:00
});
if (pinnedStatuses.length >= 3) {
const pinnedStatusesIds = pinnedStatuses.map((status) => status.id);
results.push({
id: pinnedStatusesIds,
items: pinnedStatuses,
type: 'pinned',
});
} else {
results.push(...pinnedStatuses);
}
2023-02-17 05:12:59 +03:00
}
}
if (firstLoad || !accountStatusesIterator.current) {
accountStatusesIterator.current = masto.v1.accounts.listStatuses(id, {
limit: LIMIT,
2023-04-03 05:36:31 +03:00
exclude_replies: excludeReplies,
only_media: media,
tagged,
});
}
2023-02-17 05:12:59 +03:00
const { value, done } = await accountStatusesIterator.current.next();
if (value?.length) {
results.push(...value);
value.forEach((item) => {
saveStatus(item, instance);
});
2023-02-17 05:12:59 +03:00
}
return {
value: results,
done,
};
}
const [account, setAccount] = useState();
2023-04-03 05:36:31 +03:00
const [featuredTags, setFeaturedTags] = useState([]);
useTitle(
2023-03-13 05:07:22 +03:00
`${account?.displayName ? account.displayName + ' ' : ''}@${
account?.acct ? account.acct : 'Account posts'
}`,
2023-02-11 11:27:40 +03:00
'/:instance?/a/:id',
);
useEffect(() => {
(async () => {
try {
const acc = await masto.v1.accounts.fetch(id);
console.log(acc);
setAccount(acc);
} catch (e) {
console.error(e);
}
2023-04-03 05:36:31 +03:00
try {
const featuredTags = await masto.v1.accounts.listFeaturedTags(id);
console.log({ featuredTags });
setFeaturedTags(featuredTags);
} catch (e) {
console.error(e);
}
})();
}, [id]);
const { displayName, acct, emojis } = account || {};
const TimelineStart = useMemo(() => {
const cachedAccount = snapStates.accounts[`${id}@${instance}`];
return (
2023-04-03 05:36:31 +03:00
<>
<AccountInfo
instance={instance}
account={cachedAccount || id}
fetchAccount={() => masto.v1.accounts.fetch(id)}
authenticated={authenticated}
standalone
/>
<div class="filter-bar">
<Icon icon="filter" class="insignificant" size="l" />
<Link
to={`/${instance}/a/${id}${excludeReplies ? '?replies=1' : ''}`}
class={excludeReplies ? '' : 'is-active'}
>
+ Replies
</Link>
<Link
to={`/${instance}/a/${id}${media ? '' : '?media=1'}`}
class={media ? 'is-active' : ''}
>
Media
</Link>
{featuredTags.map((tag) => (
<Link
to={`/${instance}/a/${id}${
tagged === tag.name
? ''
: `?tagged=${encodeURIComponent(tag.name)}`
}`}
class={tagged === tag.name ? 'is-active' : ''}
>
<span>
<span class="more-insignificant">#</span>
{tag.name}
</span>
{
// The count differs based on instance 😅
}
{/* <span class="filter-count">{tag.statusesCount}</span> */}
</Link>
))}
</div>
</>
);
2023-04-03 05:36:31 +03:00
}, [
id,
instance,
authenticated,
excludeReplies,
featuredTags,
tagged,
media,
]);
return (
<Timeline
key={id}
title={`${account?.acct ? '@' + account.acct : 'Posts'}`}
2023-01-31 14:08:10 +03:00
titleComponent={
<h1
class="header-account"
2023-02-17 05:14:44 +03:00
// onClick={() => {
// states.showAccount = {
// account,
// instance,
// };
// }}
2023-01-31 14:08:10 +03:00
>
<b
dangerouslySetInnerHTML={{
__html: emojifyText(displayName, emojis),
}}
/>
2023-01-31 14:08:10 +03:00
<div>
<span>@{acct}</span>
2023-01-31 14:08:10 +03:00
</div>
</h1>
}
2023-02-27 18:59:41 +03:00
id="account-statuses"
instance={instance}
emptyText="Nothing to see here yet."
errorText="Unable to load statuses"
fetchItems={fetchAccountStatuses}
useItemID
2023-02-03 16:08:08 +03:00
boostsCarousel={snapStates.settings.boostsCarousel}
timelineStart={TimelineStart}
2023-04-03 05:36:31 +03:00
refresh={excludeReplies + tagged + media}
/>
);
}
export default AccountStatuses;