mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-03 23:00:14 -05:00
Updated ActivityPub collection retrieval to accommodate pagination (#21393)
refs [AP-526](https://linear.app/ghost/issue/AP-526/implement-pagination-for-fedify-collections) Updated followers, following, outbox and liked collection retrieval to accommodate pagination
This commit is contained in:
parent
4b32a3d9c3
commit
e6df621436
5 changed files with 271 additions and 177 deletions
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@tryghost/admin-x-activitypub",
|
||||
"version": "0.3.1",
|
||||
"version": "0.3.2",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
@ -199,7 +199,7 @@ describe('ActivityPubAPI', function () {
|
|||
},
|
||||
response: JSONResponse({
|
||||
type: 'Collection',
|
||||
items: []
|
||||
orderedItems: []
|
||||
})
|
||||
}
|
||||
});
|
||||
|
@ -224,8 +224,13 @@ describe('ActivityPubAPI', function () {
|
|||
},
|
||||
'https://activitypub.api/.ghost/activitypub/outbox/index': {
|
||||
response: JSONResponse({
|
||||
type: 'Collection',
|
||||
items: []
|
||||
type: 'OrderedCollection',
|
||||
first: 'https://activitypub.api/.ghost/activitypub/outbox/index?cursor=0'
|
||||
})
|
||||
},
|
||||
'https://activitypub.api/.ghost/activitypub/outbox/index?cursor=0': {
|
||||
response: JSONResponse({
|
||||
type: 'OrderedCollection'
|
||||
})
|
||||
}
|
||||
});
|
||||
|
@ -242,7 +247,7 @@ describe('ActivityPubAPI', function () {
|
|||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Returns all the items array when the outbox is not empty', async function () {
|
||||
test('Recursively retrieves all items and returns them when the outbox is not empty', async function () {
|
||||
const fakeFetch = Fetch({
|
||||
'https://auth.api/': {
|
||||
response: JSONResponse({
|
||||
|
@ -254,14 +259,32 @@ describe('ActivityPubAPI', function () {
|
|||
'https://activitypub.api/.ghost/activitypub/outbox/index': {
|
||||
response:
|
||||
JSONResponse({
|
||||
type: 'Collection',
|
||||
orderedItems: [{
|
||||
type: 'Create',
|
||||
object: {
|
||||
type: 'Note'
|
||||
}
|
||||
}]
|
||||
type: 'OrderedCollection',
|
||||
first: 'https://activitypub.api/.ghost/activitypub/outbox/index?cursor=0'
|
||||
})
|
||||
},
|
||||
'https://activitypub.api/.ghost/activitypub/outbox/index?cursor=0': {
|
||||
response: JSONResponse({
|
||||
type: 'OrderedCollection',
|
||||
next: 'https://activitypub.api/.ghost/activitypub/outbox/index?cursor=1',
|
||||
orderedItems: [{
|
||||
type: 'Create',
|
||||
object: {
|
||||
type: 'Note'
|
||||
}
|
||||
}]
|
||||
})
|
||||
},
|
||||
'https://activitypub.api/.ghost/activitypub/outbox/index?cursor=1': {
|
||||
response: JSONResponse({
|
||||
type: 'OrderedCollection',
|
||||
orderedItems: [{
|
||||
type: 'Create',
|
||||
object: {
|
||||
type: 'Article'
|
||||
}
|
||||
}]
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -279,48 +302,11 @@ describe('ActivityPubAPI', function () {
|
|||
object: {
|
||||
type: 'Note'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Returns an array when the orderedItems key is a single object', async function () {
|
||||
const fakeFetch = Fetch({
|
||||
'https://auth.api/': {
|
||||
response: JSONResponse({
|
||||
identities: [{
|
||||
token: 'fake-token'
|
||||
}]
|
||||
})
|
||||
},
|
||||
'https://activitypub.api/.ghost/activitypub/outbox/index': {
|
||||
response:
|
||||
JSONResponse({
|
||||
type: 'Collection',
|
||||
orderedItems: {
|
||||
type: 'Create',
|
||||
object: {
|
||||
type: 'Note'
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
const api = new ActivityPubAPI(
|
||||
new URL('https://activitypub.api'),
|
||||
new URL('https://auth.api'),
|
||||
'index',
|
||||
fakeFetch
|
||||
);
|
||||
|
||||
const actual = await api.getOutbox();
|
||||
const expected: Activity[] = [
|
||||
{
|
||||
type: 'Create',
|
||||
object: {
|
||||
type: 'Note'
|
||||
type: 'Article'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
@ -371,8 +357,13 @@ describe('ActivityPubAPI', function () {
|
|||
},
|
||||
'https://activitypub.api/.ghost/activitypub/following/index': {
|
||||
response: JSONResponse({
|
||||
type: 'Collection',
|
||||
items: []
|
||||
type: 'OrderedCollection',
|
||||
first: 'https://activitypub.api/.ghost/activitypub/following/index?cursor=0'
|
||||
})
|
||||
},
|
||||
'https://activitypub.api/.ghost/activitypub/following/index?cursor=0': {
|
||||
response: JSONResponse({
|
||||
type: 'OrderedCollection'
|
||||
})
|
||||
}
|
||||
});
|
||||
|
@ -389,7 +380,7 @@ describe('ActivityPubAPI', function () {
|
|||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Returns all the items array when the following is not empty', async function () {
|
||||
test('Recursively retrieves all items and returns them when the following is not empty', async function () {
|
||||
const fakeFetch = Fetch({
|
||||
'https://auth.api/': {
|
||||
response: JSONResponse({
|
||||
|
@ -401,11 +392,26 @@ describe('ActivityPubAPI', function () {
|
|||
'https://activitypub.api/.ghost/activitypub/following/index': {
|
||||
response:
|
||||
JSONResponse({
|
||||
type: 'Collection',
|
||||
orderedItems: [{
|
||||
type: 'Person'
|
||||
}]
|
||||
type: 'OrderedCollection',
|
||||
first: 'https://activitypub.api/.ghost/activitypub/following/index?cursor=0'
|
||||
})
|
||||
},
|
||||
'https://activitypub.api/.ghost/activitypub/following/index?cursor=0': {
|
||||
response: JSONResponse({
|
||||
type: 'OrderedCollection',
|
||||
next: 'https://activitypub.api/.ghost/activitypub/following/index?cursor=1',
|
||||
orderedItems: [{
|
||||
type: 'Person'
|
||||
}]
|
||||
})
|
||||
},
|
||||
'https://activitypub.api/.ghost/activitypub/following/index?cursor=1': {
|
||||
response: JSONResponse({
|
||||
type: 'OrderedCollection',
|
||||
orderedItems: [{
|
||||
type: 'Group'
|
||||
}]
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -420,43 +426,9 @@ describe('ActivityPubAPI', function () {
|
|||
const expected: Activity[] = [
|
||||
{
|
||||
type: 'Person'
|
||||
}
|
||||
];
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Returns an array when the items key is a single object', async function () {
|
||||
const fakeFetch = Fetch({
|
||||
'https://auth.api/': {
|
||||
response: JSONResponse({
|
||||
identities: [{
|
||||
token: 'fake-token'
|
||||
}]
|
||||
})
|
||||
},
|
||||
'https://activitypub.api/.ghost/activitypub/following/index': {
|
||||
response:
|
||||
JSONResponse({
|
||||
type: 'Collection',
|
||||
items: {
|
||||
type: 'Person'
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
const api = new ActivityPubAPI(
|
||||
new URL('https://activitypub.api'),
|
||||
new URL('https://auth.api'),
|
||||
'index',
|
||||
fakeFetch
|
||||
);
|
||||
|
||||
const actual = await api.getFollowing();
|
||||
const expected: Activity[] = [
|
||||
{
|
||||
type: 'Person'
|
||||
type: 'Group'
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -465,7 +437,7 @@ describe('ActivityPubAPI', function () {
|
|||
});
|
||||
|
||||
describe('getFollowers', function () {
|
||||
test('It passes the token to the followers endpoint', async function () {
|
||||
test('It passes the token to the following endpoint', async function () {
|
||||
const fakeFetch = Fetch({
|
||||
'https://auth.api/': {
|
||||
response: JSONResponse({
|
||||
|
@ -506,8 +478,13 @@ describe('ActivityPubAPI', function () {
|
|||
},
|
||||
'https://activitypub.api/.ghost/activitypub/followers/index': {
|
||||
response: JSONResponse({
|
||||
type: 'Collection',
|
||||
orderedItems: []
|
||||
type: 'OrderedCollection',
|
||||
first: 'https://activitypub.api/.ghost/activitypub/followers/index?cursor=0'
|
||||
})
|
||||
},
|
||||
'https://activitypub.api/.ghost/activitypub/followers/index?cursor=0': {
|
||||
response: JSONResponse({
|
||||
type: 'OrderedCollection'
|
||||
})
|
||||
}
|
||||
});
|
||||
|
@ -524,7 +501,7 @@ describe('ActivityPubAPI', function () {
|
|||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Returns all the items array when the followers is not empty', async function () {
|
||||
test('Recursively retrieves all items and returns them when the followers is not empty', async function () {
|
||||
const fakeFetch = Fetch({
|
||||
'https://auth.api/': {
|
||||
response: JSONResponse({
|
||||
|
@ -536,11 +513,26 @@ describe('ActivityPubAPI', function () {
|
|||
'https://activitypub.api/.ghost/activitypub/followers/index': {
|
||||
response:
|
||||
JSONResponse({
|
||||
type: 'Collection',
|
||||
orderedItems: [{
|
||||
type: 'Person'
|
||||
}]
|
||||
type: 'OrderedCollection',
|
||||
first: 'https://activitypub.api/.ghost/activitypub/followers/index?cursor=0'
|
||||
})
|
||||
},
|
||||
'https://activitypub.api/.ghost/activitypub/followers/index?cursor=0': {
|
||||
response: JSONResponse({
|
||||
type: 'OrderedCollection',
|
||||
next: 'https://activitypub.api/.ghost/activitypub/followers/index?cursor=1',
|
||||
orderedItems: [{
|
||||
type: 'Person'
|
||||
}]
|
||||
})
|
||||
},
|
||||
'https://activitypub.api/.ghost/activitypub/followers/index?cursor=1': {
|
||||
response: JSONResponse({
|
||||
type: 'OrderedCollection',
|
||||
orderedItems: [{
|
||||
type: 'Group'
|
||||
}]
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -555,6 +547,9 @@ describe('ActivityPubAPI', function () {
|
|||
const expected: Activity[] = [
|
||||
{
|
||||
type: 'Person'
|
||||
},
|
||||
{
|
||||
type: 'Group'
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -562,8 +557,8 @@ describe('ActivityPubAPI', function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('getFollowersExpanded', function () {
|
||||
test('It passes the token to the followers endpoint', async function () {
|
||||
describe('getLiked', function () {
|
||||
test('It passes the token to the liked endpoint', async function () {
|
||||
const fakeFetch = Fetch({
|
||||
'https://auth.api/': {
|
||||
response: JSONResponse({
|
||||
|
@ -572,7 +567,7 @@ describe('ActivityPubAPI', function () {
|
|||
}]
|
||||
})
|
||||
},
|
||||
'https://activitypub.api/.ghost/activitypub/followers-expanded/index': {
|
||||
'https://activitypub.api/.ghost/activitypub/liked/index': {
|
||||
async assert(_resource, init) {
|
||||
const headers = new Headers(init?.headers);
|
||||
expect(headers.get('Authorization')).toContain('fake-token');
|
||||
|
@ -590,10 +585,10 @@ describe('ActivityPubAPI', function () {
|
|||
fakeFetch
|
||||
);
|
||||
|
||||
await api.getFollowersExpanded();
|
||||
await api.getLiked();
|
||||
});
|
||||
|
||||
test('Returns an empty array when the followers is empty', async function () {
|
||||
test('Returns an empty array when the liked collection is empty', async function () {
|
||||
const fakeFetch = Fetch({
|
||||
'https://auth.api/': {
|
||||
response: JSONResponse({
|
||||
|
@ -602,10 +597,15 @@ describe('ActivityPubAPI', function () {
|
|||
}]
|
||||
})
|
||||
},
|
||||
'https://activitypub.api/.ghost/activitypub/followers-expanded/index': {
|
||||
'https://activitypub.api/.ghost/activitypub/liked/index': {
|
||||
response: JSONResponse({
|
||||
type: 'Collection',
|
||||
orderedItems: []
|
||||
type: 'OrderedCollection',
|
||||
first: 'https://activitypub.api/.ghost/activitypub/liked/index?cursor=0'
|
||||
})
|
||||
},
|
||||
'https://activitypub.api/.ghost/activitypub/liked/index?cursor=0': {
|
||||
response: JSONResponse({
|
||||
type: 'OrderedCollection'
|
||||
})
|
||||
}
|
||||
});
|
||||
|
@ -616,13 +616,13 @@ describe('ActivityPubAPI', function () {
|
|||
fakeFetch
|
||||
);
|
||||
|
||||
const actual = await api.getFollowersExpanded();
|
||||
const actual = await api.getLiked();
|
||||
const expected: never[] = [];
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
|
||||
test('Returns all the items array when the followers is not empty', async function () {
|
||||
test('Recursively retrieves all items and returns them when the liked collection is not empty', async function () {
|
||||
const fakeFetch = Fetch({
|
||||
'https://auth.api/': {
|
||||
response: JSONResponse({
|
||||
|
@ -631,14 +631,35 @@ describe('ActivityPubAPI', function () {
|
|||
}]
|
||||
})
|
||||
},
|
||||
'https://activitypub.api/.ghost/activitypub/followers-expanded/index': {
|
||||
'https://activitypub.api/.ghost/activitypub/liked/index': {
|
||||
response:
|
||||
JSONResponse({
|
||||
type: 'Collection',
|
||||
orderedItems: [{
|
||||
type: 'Person'
|
||||
}]
|
||||
type: 'OrderedCollection',
|
||||
first: 'https://activitypub.api/.ghost/activitypub/liked/index?cursor=0'
|
||||
})
|
||||
},
|
||||
'https://activitypub.api/.ghost/activitypub/liked/index?cursor=0': {
|
||||
response: JSONResponse({
|
||||
type: 'OrderedCollection',
|
||||
next: 'https://activitypub.api/.ghost/activitypub/liked/index?cursor=1',
|
||||
orderedItems: [{
|
||||
type: 'Create',
|
||||
object: {
|
||||
type: 'Note'
|
||||
}
|
||||
}]
|
||||
})
|
||||
},
|
||||
'https://activitypub.api/.ghost/activitypub/liked/index?cursor=1': {
|
||||
response: JSONResponse({
|
||||
type: 'OrderedCollection',
|
||||
orderedItems: [{
|
||||
type: 'Create',
|
||||
object: {
|
||||
type: 'Article'
|
||||
}
|
||||
}]
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -649,10 +670,19 @@ describe('ActivityPubAPI', function () {
|
|||
fakeFetch
|
||||
);
|
||||
|
||||
const actual = await api.getFollowersExpanded();
|
||||
const actual = await api.getLiked();
|
||||
const expected: Activity[] = [
|
||||
{
|
||||
type: 'Person'
|
||||
type: 'Create',
|
||||
object: {
|
||||
type: 'Note'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'Create',
|
||||
object: {
|
||||
type: 'Article'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
@ -92,35 +92,77 @@ export class ActivityPubAPI {
|
|||
}
|
||||
|
||||
async getOutbox(): Promise<Activity[]> {
|
||||
const json = await this.fetchJSON(this.outboxApiUrl);
|
||||
if (json === null) {
|
||||
const fetchOutboxPage = async (url: URL): Promise<Activity[]> => {
|
||||
const json = await this.fetchJSON(url);
|
||||
|
||||
if (json === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let items: Activity[] = [];
|
||||
|
||||
if ('orderedItems' in json) {
|
||||
items = Array.isArray(json.orderedItems) ? json.orderedItems : [json.orderedItems];
|
||||
}
|
||||
|
||||
if ('next' in json && typeof json.next === 'string') {
|
||||
const nextUrl = new URL(json.next);
|
||||
const nextItems = await fetchOutboxPage(nextUrl);
|
||||
|
||||
items = items.concat(nextItems);
|
||||
}
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
const initialJson = await this.fetchJSON(this.outboxApiUrl);
|
||||
|
||||
if (initialJson === null || !('first' in initialJson) || typeof initialJson.first !== 'string') {
|
||||
return [];
|
||||
}
|
||||
if ('orderedItems' in json) {
|
||||
return Array.isArray(json.orderedItems) ? json.orderedItems : [json.orderedItems];
|
||||
}
|
||||
if ('items' in json) {
|
||||
return Array.isArray(json.items) ? json.items : [json.items];
|
||||
}
|
||||
return [];
|
||||
|
||||
const firstPageUrl = new URL(initialJson.first);
|
||||
|
||||
return fetchOutboxPage(firstPageUrl);
|
||||
}
|
||||
|
||||
get followingApiUrl() {
|
||||
return new URL(`.ghost/activitypub/following/${this.handle}`, this.apiUrl);
|
||||
}
|
||||
|
||||
async getFollowing(): Promise<Activity[]> {
|
||||
const json = await this.fetchJSON(this.followingApiUrl);
|
||||
if (json === null) {
|
||||
async getFollowing(): Promise<Actor[]> {
|
||||
const fetchFollowingPage = async (url: URL): Promise<Actor[]> => {
|
||||
const json = await this.fetchJSON(url);
|
||||
|
||||
if (json === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let items: Actor[] = [];
|
||||
|
||||
if ('orderedItems' in json) {
|
||||
items = Array.isArray(json.orderedItems) ? json.orderedItems : [json.orderedItems];
|
||||
}
|
||||
|
||||
if ('next' in json && typeof json.next === 'string') {
|
||||
const nextUrl = new URL(json.next);
|
||||
const nextItems = await fetchFollowingPage(nextUrl);
|
||||
|
||||
items = items.concat(nextItems);
|
||||
}
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
const initialJson = await this.fetchJSON(this.followingApiUrl);
|
||||
|
||||
if (initialJson === null || !('first' in initialJson) || typeof initialJson.first !== 'string') {
|
||||
return [];
|
||||
}
|
||||
if ('orderedItems' in json) {
|
||||
return Array.isArray(json.orderedItems) ? json.orderedItems : [json.orderedItems];
|
||||
}
|
||||
if ('items' in json) {
|
||||
return Array.isArray(json.items) ? json.items : [json.items];
|
||||
}
|
||||
return [];
|
||||
|
||||
const firstPageUrl = new URL(initialJson.first);
|
||||
|
||||
return fetchFollowingPage(firstPageUrl);
|
||||
}
|
||||
|
||||
async getFollowingCount(): Promise<number> {
|
||||
|
@ -138,15 +180,39 @@ export class ActivityPubAPI {
|
|||
return new URL(`.ghost/activitypub/followers/${this.handle}`, this.apiUrl);
|
||||
}
|
||||
|
||||
async getFollowers(): Promise<Activity[]> {
|
||||
const json = await this.fetchJSON(this.followersApiUrl);
|
||||
if (json === null) {
|
||||
async getFollowers(): Promise<Actor[]> {
|
||||
const fetchFollowersPage = async (url: URL): Promise<Actor[]> => {
|
||||
const json = await this.fetchJSON(url);
|
||||
|
||||
if (json === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let items: Actor[] = [];
|
||||
|
||||
if ('orderedItems' in json) {
|
||||
items = Array.isArray(json.orderedItems) ? json.orderedItems : [json.orderedItems];
|
||||
}
|
||||
|
||||
if ('next' in json && typeof json.next === 'string') {
|
||||
const nextUrl = new URL(json.next);
|
||||
const nextItems = await fetchFollowersPage(nextUrl);
|
||||
|
||||
items = items.concat(nextItems);
|
||||
}
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
const initialJson = await this.fetchJSON(this.followersApiUrl);
|
||||
|
||||
if (initialJson === null || !('first' in initialJson) || typeof initialJson.first !== 'string') {
|
||||
return [];
|
||||
}
|
||||
if ('orderedItems' in json) {
|
||||
return Array.isArray(json.orderedItems) ? json.orderedItems : [json.orderedItems];
|
||||
}
|
||||
return [];
|
||||
|
||||
const firstPageUrl = new URL(initialJson.first);
|
||||
|
||||
return fetchFollowersPage(firstPageUrl);
|
||||
}
|
||||
|
||||
async getFollowersCount(): Promise<number> {
|
||||
|
@ -160,21 +226,6 @@ export class ActivityPubAPI {
|
|||
return 0;
|
||||
}
|
||||
|
||||
get followersExpandedApiUrl() {
|
||||
return new URL(`.ghost/activitypub/followers-expanded/${this.handle}`, this.apiUrl);
|
||||
}
|
||||
|
||||
async getFollowersExpanded(): Promise<Activity[]> {
|
||||
const json = await this.fetchJSON(this.followersExpandedApiUrl);
|
||||
if (json === null) {
|
||||
return [];
|
||||
}
|
||||
if ('orderedItems' in json) {
|
||||
return Array.isArray(json.orderedItems) ? json.orderedItems : [json.orderedItems];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
async getFollowersForProfile(handle: string, next?: string): Promise<GetFollowersForProfileResponse> {
|
||||
const url = new URL(`.ghost/activitypub/profile/${handle}/followers`, this.apiUrl);
|
||||
if (next) {
|
||||
|
@ -252,14 +303,38 @@ export class ActivityPubAPI {
|
|||
}
|
||||
|
||||
async getLiked() {
|
||||
const json = await this.fetchJSON(this.likedApiUrl);
|
||||
if (json === null) {
|
||||
const fetchLikedPage = async (url: URL): Promise<Activity[]> => {
|
||||
const json = await this.fetchJSON(url);
|
||||
|
||||
if (json === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let items: Activity[] = [];
|
||||
|
||||
if ('orderedItems' in json) {
|
||||
items = Array.isArray(json.orderedItems) ? json.orderedItems : [json.orderedItems];
|
||||
}
|
||||
|
||||
if ('next' in json && typeof json.next === 'string') {
|
||||
const nextUrl = new URL(json.next);
|
||||
const nextItems = await fetchLikedPage(nextUrl);
|
||||
|
||||
items = items.concat(nextItems);
|
||||
}
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
const initialJson = await this.fetchJSON(this.likedApiUrl);
|
||||
|
||||
if (initialJson === null || !('first' in initialJson) || typeof initialJson.first !== 'string') {
|
||||
return [];
|
||||
}
|
||||
if ('orderedItems' in json) {
|
||||
return Array.isArray(json.orderedItems) ? json.orderedItems : [json.orderedItems];
|
||||
}
|
||||
return [];
|
||||
|
||||
const firstPageUrl = new URL(initialJson.first);
|
||||
|
||||
return fetchLikedPage(firstPageUrl);
|
||||
}
|
||||
|
||||
async like(id: string): Promise<void> {
|
||||
|
|
|
@ -12,7 +12,7 @@ import ViewProfileModal from './global/ViewProfileModal';
|
|||
import {Button, Heading, List, NoValueLabel, Tab, TabView} from '@tryghost/admin-x-design-system';
|
||||
import {
|
||||
useFollowersCountForUser,
|
||||
useFollowersExpandedForUser,
|
||||
useFollowersForUser,
|
||||
useFollowingCountForUser,
|
||||
useFollowingForUser,
|
||||
useLikedForUser,
|
||||
|
@ -26,7 +26,7 @@ const Profile: React.FC<ProfileProps> = ({}) => {
|
|||
const {data: followersCount = 0} = useFollowersCountForUser('index');
|
||||
const {data: followingCount = 0} = useFollowingCountForUser('index');
|
||||
const {data: following = []} = useFollowingForUser('index');
|
||||
const {data: followers = []} = useFollowersExpandedForUser('index');
|
||||
const {data: followers = []} = useFollowersForUser('index');
|
||||
const {data: liked = []} = useLikedForUser('index');
|
||||
const {data: posts = []} = useOutboxForUser('index');
|
||||
|
||||
|
|
|
@ -193,17 +193,6 @@ export function useFollowersForUser(handle: string) {
|
|||
});
|
||||
}
|
||||
|
||||
export function useFollowersExpandedForUser(handle: string) {
|
||||
return useQuery({
|
||||
queryKey: [`followers_expanded:${handle}`],
|
||||
async queryFn() {
|
||||
const siteUrl = await getSiteUrl();
|
||||
const api = createActivityPubAPI(handle, siteUrl);
|
||||
return api.getFollowersExpanded();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function useAllActivitiesForUser({
|
||||
handle,
|
||||
includeOwn = false,
|
||||
|
|
Loading…
Add table
Reference in a new issue