mirror of
https://github.com/cheeaun/phanpy.git
synced 2025-03-14 04:08:32 +03:00
Add follow requests section in Notifications
This commit is contained in:
parent
d37537c61e
commit
dcf7d3c750
6 changed files with 162 additions and 48 deletions
|
@ -1312,6 +1312,9 @@ body:has(.media-modal-container + .status-deck) .media-post-link {
|
|||
.tag .icon {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.tag.collapsed {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* MENU POPUP */
|
||||
|
||||
|
|
54
src/components/follow-request-buttons.jsx
Normal file
54
src/components/follow-request-buttons.jsx
Normal file
|
@ -0,0 +1,54 @@
|
|||
import { useState } from 'preact/hooks';
|
||||
|
||||
import { api } from '../utils/api';
|
||||
|
||||
import Loader from './loader';
|
||||
|
||||
function FollowRequestButtons({ accountID, onChange }) {
|
||||
const { masto } = api();
|
||||
const [uiState, setUIState] = useState('default');
|
||||
return (
|
||||
<p class="follow-request-buttons">
|
||||
<button
|
||||
type="button"
|
||||
disabled={uiState === 'loading'}
|
||||
onClick={() => {
|
||||
setUIState('loading');
|
||||
(async () => {
|
||||
try {
|
||||
await masto.v1.followRequests.authorize(accountID);
|
||||
onChange();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
setUIState('default');
|
||||
}
|
||||
})();
|
||||
}}
|
||||
>
|
||||
Accept
|
||||
</button>{' '}
|
||||
<button
|
||||
type="button"
|
||||
disabled={uiState === 'loading'}
|
||||
class="light danger"
|
||||
onClick={() => {
|
||||
setUIState('loading');
|
||||
(async () => {
|
||||
try {
|
||||
await masto.v1.followRequests.reject(accountID);
|
||||
onChange();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
setUIState('default');
|
||||
}
|
||||
})();
|
||||
}}
|
||||
>
|
||||
Reject
|
||||
</button>
|
||||
<Loader hidden={uiState !== 'loading'} />
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
export default FollowRequestButtons;
|
|
@ -2,6 +2,7 @@ import states from '../utils/states';
|
|||
import store from '../utils/store';
|
||||
|
||||
import Avatar from './avatar';
|
||||
import FollowRequestButtons from './follow-request-buttons';
|
||||
import Icon from './icon';
|
||||
import Link from './link';
|
||||
import NameText from './name-text';
|
||||
|
@ -205,51 +206,4 @@ function Notification({ notification, instance }) {
|
|||
);
|
||||
}
|
||||
|
||||
function FollowRequestButtons({ accountID, onChange }) {
|
||||
const { masto } = api();
|
||||
const [uiState, setUIState] = useState('default');
|
||||
return (
|
||||
<p>
|
||||
<button
|
||||
type="button"
|
||||
disabled={uiState === 'loading'}
|
||||
onClick={() => {
|
||||
setUIState('loading');
|
||||
(async () => {
|
||||
try {
|
||||
await masto.v1.followRequests.authorize(accountID);
|
||||
onChange();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
setUIState('default');
|
||||
}
|
||||
})();
|
||||
}}
|
||||
>
|
||||
Accept
|
||||
</button>{' '}
|
||||
<button
|
||||
type="button"
|
||||
disabled={uiState === 'loading'}
|
||||
class="light danger"
|
||||
onClick={() => {
|
||||
setUIState('loading');
|
||||
(async () => {
|
||||
try {
|
||||
await masto.v1.followRequests.reject(accountID);
|
||||
onChange();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
setUIState('default');
|
||||
}
|
||||
})();
|
||||
}}
|
||||
>
|
||||
Reject
|
||||
</button>
|
||||
<Loader hidden={uiState !== 'loading'} />
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
export default Notification;
|
||||
|
|
|
@ -135,11 +135,20 @@ function NotificationsMenu({ anchorRef, state, onClose }) {
|
|||
return allNotifications;
|
||||
}
|
||||
|
||||
const [hasFollowRequests, setHasFollowRequests] = useState(false);
|
||||
function fetchFollowRequests() {
|
||||
return masto.v1.followRequests.list({
|
||||
limit: 1,
|
||||
});
|
||||
}
|
||||
|
||||
function loadNotifications() {
|
||||
setUIState('loading');
|
||||
(async () => {
|
||||
try {
|
||||
await fetchNotifications();
|
||||
const followRequests = await fetchFollowRequests();
|
||||
setHasFollowRequests(!!followRequests?.length);
|
||||
setUIState('default');
|
||||
} catch (e) {
|
||||
setUIState('error');
|
||||
|
@ -204,7 +213,15 @@ function NotificationsMenu({ anchorRef, state, onClose }) {
|
|||
<Icon icon="at" /> <span>Mentions</span>
|
||||
</Link>
|
||||
<Link to="/notifications" class="button plain2">
|
||||
<b>See all</b> <Icon icon="arrow-right" />
|
||||
{hasFollowRequests ? (
|
||||
<>
|
||||
<span class="tag collapsed">New</span>{' '}
|
||||
<span>Follow Requests</span>
|
||||
</>
|
||||
) : (
|
||||
<b>See all</b>
|
||||
)}{' '}
|
||||
<Icon icon="arrow-right" />
|
||||
</Link>
|
||||
</footer>
|
||||
</ControlledMenu>
|
||||
|
|
|
@ -152,3 +152,41 @@
|
|||
color: var(--text-color);
|
||||
background-color: var(--bg-color);
|
||||
}
|
||||
|
||||
.follow-requests {
|
||||
padding-block-end: 16px;
|
||||
}
|
||||
.follow-requests ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
max-height: 50vh;
|
||||
max-height: 50dvh;
|
||||
overflow: auto;
|
||||
border-bottom: var(--hairline-width) solid var(--outline-color);
|
||||
}
|
||||
.follow-requests ul li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
border-bottom: var(--hairline-width) solid var(--outline-color);
|
||||
justify-content: space-between;
|
||||
column-gap: 16px;
|
||||
row-gap: 4px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.follow-requests ul li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
.follow-requests ul li .follow-request-buttons {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
gap: 4px;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
.follow-requests ul li .follow-request-buttons .loader-container {
|
||||
order: -1;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import { memo } from 'preact/compat';
|
|||
import { useCallback, useEffect, useRef, useState } from 'preact/hooks';
|
||||
import { useSnapshot } from 'valtio';
|
||||
|
||||
import AccountBlock from '../components/account-block';
|
||||
import FollowRequestButtons from '../components/follow-request-buttons';
|
||||
import Icon from '../components/icon';
|
||||
import Link from '../components/link';
|
||||
import Loader from '../components/loader';
|
||||
|
@ -31,6 +33,7 @@ function Notifications() {
|
|||
scrollableRef,
|
||||
});
|
||||
const hiddenUI = scrollDirection === 'end' && !nearReachStart;
|
||||
const [followRequests, setFollowRequests] = useState([]);
|
||||
|
||||
console.debug('RENDER Notifications');
|
||||
|
||||
|
@ -67,12 +70,39 @@ function Notifications() {
|
|||
return allNotifications;
|
||||
}
|
||||
|
||||
async function fetchFollowRequests() {
|
||||
const followRequests = await masto.v1.followRequests.list({
|
||||
limit: 80,
|
||||
});
|
||||
// Note: no pagination here yet because this better be on a separate page. Should be rare use-case???
|
||||
return followRequests;
|
||||
}
|
||||
|
||||
const loadFollowRequests = () => {
|
||||
setUIState('loading');
|
||||
(async () => {
|
||||
try {
|
||||
const requests = await fetchFollowRequests();
|
||||
setFollowRequests(requests);
|
||||
setUIState('default');
|
||||
} catch (e) {
|
||||
setUIState('error');
|
||||
}
|
||||
})();
|
||||
};
|
||||
|
||||
const loadNotifications = (firstLoad) => {
|
||||
setUIState('loading');
|
||||
(async () => {
|
||||
try {
|
||||
const { done } = await fetchNotifications(firstLoad);
|
||||
setShowMore(!done);
|
||||
|
||||
if (firstLoad) {
|
||||
const requests = await fetchFollowRequests();
|
||||
setFollowRequests(requests);
|
||||
}
|
||||
|
||||
setUIState('default');
|
||||
} catch (e) {
|
||||
setUIState('error');
|
||||
|
@ -184,6 +214,24 @@ function Notifications() {
|
|||
</button>
|
||||
)}
|
||||
</header>
|
||||
{followRequests.length > 0 && (
|
||||
<div class="follow-requests">
|
||||
<h2 class="timeline-header">Follow requests</h2>
|
||||
<ul>
|
||||
{followRequests.map((account) => (
|
||||
<li>
|
||||
<AccountBlock account={account} />
|
||||
<FollowRequestButtons
|
||||
accountID={account.id}
|
||||
onChange={() => {
|
||||
loadFollowRequests();
|
||||
}}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
<div id="mentions-option">
|
||||
<label>
|
||||
<input
|
||||
|
|
Loading…
Add table
Reference in a new issue