1
0
Fork 0

Fix race conditions when accept/rejecting many follow requests

- No longer reload the whole list of follow requests and notifications for every accept/reject action
- Notifications list now exclude follow requests (experimental)
This commit is contained in:
Lim Chee Aun 2023-08-11 18:00:36 +08:00
parent 37ce48ae6e
commit 8b74a32168
5 changed files with 52 additions and 12 deletions

View file

@ -2,11 +2,17 @@ import { useState } from 'preact/hooks';
import { api } from '../utils/api';
import Icon from './icon';
import Loader from './loader';
function FollowRequestButtons({ accountID, onChange }) {
const { masto } = api();
const [uiState, setUIState] = useState('default');
const [requestState, setRequestState] = useState(null); // accept, reject
const [relationship, setRelationship] = useState(null);
const hasRelationship = relationship !== null;
return (
<p class="follow-request-buttons">
<button
@ -14,14 +20,19 @@ function FollowRequestButtons({ accountID, onChange }) {
disabled={uiState === 'loading'}
onClick={() => {
setUIState('loading');
setRequestState('accept');
(async () => {
try {
await masto.v1.followRequests.authorize(accountID);
const rel = await masto.v1.followRequests.authorize(accountID);
if (!rel?.followedBy) {
throw new Error('Follow request not accepted');
}
setRelationship(rel);
onChange();
} catch (e) {
console.error(e);
setUIState('default');
}
setUIState('default');
})();
}}
>
@ -33,9 +44,14 @@ function FollowRequestButtons({ accountID, onChange }) {
class="light danger"
onClick={() => {
setUIState('loading');
setRequestState('reject');
(async () => {
try {
await masto.v1.followRequests.reject(accountID);
const rel = await masto.v1.followRequests.reject(accountID);
if (rel?.followedBy) {
throw new Error('Follow request not rejected');
}
setRelationship(rel);
onChange();
} catch (e) {
console.error(e);
@ -46,7 +62,17 @@ function FollowRequestButtons({ accountID, onChange }) {
>
Reject
</button>
<Loader hidden={uiState !== 'loading'} />
<span class="follow-request-states">
{hasRelationship && requestState ? (
requestState === 'accept' ? (
<Icon icon="check-circle" alt="Accepted" class="follow-accepted" />
) : (
<Icon icon="x-circle" alt="Rejected" class="follow-rejected" />
)
) : (
<Loader hidden={uiState !== 'loading'} />
)}
</span>
</p>
);
}

View file

@ -13,6 +13,7 @@ const ICONS = {
heart: () => import('@iconify-icons/mingcute/heart-line'),
bookmark: () => import('@iconify-icons/mingcute/bookmark-line'),
'check-circle': () => import('@iconify-icons/mingcute/check-circle-line'),
'x-circle': () => import('@iconify-icons/mingcute/close-circle-line'),
transfer: () => import('@iconify-icons/mingcute/transfer-4-line'),
rocket: () => import('@iconify-icons/mingcute/rocket-line'),
'arrow-left': () => import('@iconify-icons/mingcute/arrow-left-line'),

View file

@ -137,7 +137,7 @@ function Notification({ notification, instance, reload }) {
<FollowRequestButtons
accountID={account.id}
onChange={() => {
reload();
// reload();
}}
/>
)}

View file

@ -204,7 +204,19 @@
justify-content: flex-end;
align-items: center;
}
.follow-requests ul li .follow-request-buttons .loader-container {
.follow-request-buttons .follow-request-states {
vertical-align: middle;
}
.follow-request-buttons .follow-request-states .icon {
margin-inline: 8px;
}
.follow-request-buttons .follow-request-states .icon.follow-accepted {
color: var(--green-color);
}
.follow-request-buttons .follow-request-states .icon.follow-rejected {
color: var(--red-color);
}
.follow-requests ul li .follow-request-buttons .follow-request-states {
order: -1;
}

View file

@ -49,6 +49,7 @@ function Notifications() {
// Reset iterator
notificationsIterator.current = masto.v1.notifications.list({
limit: LIMIT,
excludeTypes: ['follow_request'],
});
}
const allNotifications = await notificationsIterator.current.next();
@ -295,13 +296,13 @@ function Notifications() {
<summary>{followRequests.length} follow requests</summary>
<ul>
{followRequests.map((account) => (
<li>
<li key={account.id}>
<AccountBlock account={account} />
<FollowRequestButtons
accountID={account.id}
onChange={() => {
loadFollowRequests();
loadNotifications(true);
// loadFollowRequests();
// loadNotifications(true);
}}
/>
</li>
@ -311,13 +312,13 @@ function Notifications() {
) : (
<ul>
{followRequests.map((account) => (
<li>
<li key={account.id}>
<AccountBlock account={account} />
<FollowRequestButtons
accountID={account.id}
onChange={() => {
loadFollowRequests();
loadNotifications(true);
// loadFollowRequests();
// loadNotifications(true);
}}
/>
</li>