diff --git a/client/lib/user/user.d.ts b/client/lib/user/user.d.ts
index 92c672c3f9d92..3dafc6b05faf7 100644
--- a/client/lib/user/user.d.ts
+++ b/client/lib/user/user.d.ts
@@ -39,6 +39,7 @@ export type OptionalUserData = {
has_jetpack_partner_access?: boolean;
jetpack_partner_types?: string[];
social_login_connections: unknown;
+ user_login: string;
user_ip_country_code: string;
user_URL: string;
username: string;
diff --git a/client/reader/list-manage/types.d.ts b/client/reader/list-manage/types.d.ts
index 8d53ac73e90eb..0d7bf4515d662 100644
--- a/client/reader/list-manage/types.d.ts
+++ b/client/reader/list-manage/types.d.ts
@@ -3,6 +3,7 @@ export type List = {
description: string;
is_public: boolean;
is_owner: boolean;
+ owner: string;
slug: string;
title: string;
};
diff --git a/client/reader/user-stream/style.scss b/client/reader/user-stream/style.scss
index 31d67c5539792..2c74522a7e495 100644
--- a/client/reader/user-stream/style.scss
+++ b/client/reader/user-stream/style.scss
@@ -17,4 +17,23 @@
border-block-end: none;
}
}
+
+ .user-profile__lists-body {
+ max-width: 768px;
+ margin: 0 auto;
+
+ &-link {
+ color: var(--color-neutral-100);
+ cursor: pointer;
+ display: block;
+ line-height: 29px;
+ text-wrap: pretty;
+
+ .reader-post-card__title {
+ margin-top: 0;
+ font-size: 1.25rem;
+ font-weight: 600;
+ }
+ }
+ }
}
diff --git a/client/reader/user-stream/views/lists.tsx b/client/reader/user-stream/views/lists.tsx
index 84c3c99c21244..f953395178a51 100644
--- a/client/reader/user-stream/views/lists.tsx
+++ b/client/reader/user-stream/views/lists.tsx
@@ -1,27 +1,88 @@
import { formatListBullets, Icon } from '@wordpress/icons';
import { useTranslate } from 'i18n-calypso';
+import { useEffect, useState } from 'react';
+import { connect } from 'react-redux';
import EmptyContent from 'calypso/components/empty-content';
import { UserData } from 'calypso/lib/user/user';
+import { List } from 'calypso/reader/list-manage/types';
import UserProfileHeader from 'calypso/reader/user-stream/components/user-profile-header';
+import { requestUserLists } from 'calypso/state/reader/lists/actions';
+
+interface AppState {
+ reader: {
+ lists: {
+ userLists: Record< string, List[] >;
+ isRequestingUserLists: Record< string, boolean >;
+ };
+ };
+}
interface UserListsProps {
user: UserData;
+ requestUserLists?: ( userSlug: string ) => void;
+ lists?: List[];
+ isLoading?: boolean;
}
-const UserLists = ( { user }: UserListsProps ): JSX.Element => {
+const UserLists = ( { user, requestUserLists, lists, isLoading }: UserListsProps ): JSX.Element => {
const translate = useTranslate();
+ const [ hasRequested, setHasRequested ] = useState( false );
+ const userSlug = user.user_login;
+
+ useEffect( () => {
+ if ( ! hasRequested && requestUserLists && userSlug ) {
+ requestUserLists( userSlug );
+ setHasRequested( true );
+ }
+ }, [ userSlug, requestUserLists, hasRequested ] );
+
+ if ( isLoading || ! hasRequested ) {
+ return <>>;
+ }
+
+ if ( ! lists || lists.length === 0 ) {
+ return (
+
+
-
}
- title={ null }
- line={ translate( 'No lists yet.' ) }
- />
+
);
};
-export default UserLists;
+export default connect(
+ ( state: AppState, ownProps: UserListsProps ) => ( {
+ lists: state.reader.lists.userLists[ ownProps.user.user_login ?? '' ] ?? [],
+ isLoading: state.reader.lists.isRequestingUserLists[ ownProps.user.user_login ?? '' ] ?? false,
+ } ),
+ {
+ requestUserLists,
+ }
+)( UserLists );
diff --git a/client/state/data-layer/wpcom/read/lists/index.js b/client/state/data-layer/wpcom/read/lists/index.js
index 0bc12a4ce145e..f1f4a5de25240 100644
--- a/client/state/data-layer/wpcom/read/lists/index.js
+++ b/client/state/data-layer/wpcom/read/lists/index.js
@@ -12,6 +12,8 @@ import {
READER_LIST_UNFOLLOW,
READER_LIST_UPDATE,
READER_LISTS_REQUEST,
+ READER_USER_LISTS_REQUEST,
+ READER_USER_LISTS_RECEIVE,
} from 'calypso/state/reader/action-types';
import {
handleReaderListRequestFailure,
@@ -136,13 +138,14 @@ registerHandlers( 'state/data-layer/wpcom/read/lists/index.js', {
],
} ),
],
+ // Request public and private lists for the current user
[ READER_LISTS_REQUEST ]: [
dispatchRequest( {
fetch: ( action ) =>
http(
{
method: 'GET',
- path: `/read/lists`,
+ path: '/read/lists',
apiVersion: '1.2',
},
action
@@ -151,4 +154,24 @@ registerHandlers( 'state/data-layer/wpcom/read/lists/index.js', {
onError: () => noop,
} ),
],
+ // Request only public lists for a specific user
+ [ READER_USER_LISTS_REQUEST ]: [
+ dispatchRequest( {
+ fetch: ( action ) =>
+ http(
+ {
+ method: 'GET',
+ path: `/read/lists/${ action.userSlug }`,
+ apiVersion: '1',
+ },
+ action
+ ),
+ onSuccess: ( action, apiResponse ) => ( {
+ type: READER_USER_LISTS_RECEIVE,
+ userSlug: action.userSlug,
+ lists: apiResponse?.lists,
+ } ),
+ onError: () => noop,
+ } ),
+ ],
} );
diff --git a/client/state/reader/action-types.js b/client/state/reader/action-types.js
index 37443b0c278d7..52659e2ab0181 100644
--- a/client/state/reader/action-types.js
+++ b/client/state/reader/action-types.js
@@ -99,5 +99,7 @@ export const READER_UPDATE_NEW_POST_EMAIL_SUBSCRIPTION =
export const READER_USER_REQUEST = 'READER_USER_REQUEST';
export const READER_USER_REQUEST_FAILURE = 'READER_USER_REQUEST_FAILURE';
export const READER_USER_REQUEST_SUCCESS = 'READER_USER_REQUEST_SUCCESS';
+export const READER_USER_LISTS_REQUEST = 'READER_USER_LISTS_REQUEST';
+export const READER_USER_LISTS_RECEIVE = 'READER_USER_LISTS_RECEIVE';
export const READER_VIEWING_FULL_POST_SET = 'READER_VIEWING_FULL_POST_SET';
export const READER_VIEWING_FULL_POST_UNSET = 'READER_VIEWING_FULL_POST_UNSET';
diff --git a/client/state/reader/lists/actions.js b/client/state/reader/lists/actions.js
index a712a3506651a..6daa6617b1571 100644
--- a/client/state/reader/lists/actions.js
+++ b/client/state/reader/lists/actions.js
@@ -22,6 +22,7 @@ import {
READER_LIST_ITEM_ADD_TAG_RECEIVE,
READER_LISTS_RECEIVE,
READER_LISTS_REQUEST,
+ READER_USER_LISTS_REQUEST,
} from 'calypso/state/reader/action-types';
import 'calypso/state/data-layer/wpcom/read/lists';
import 'calypso/state/data-layer/wpcom/read/lists/delete';
@@ -271,3 +272,10 @@ export const deleteReaderList = ( listId, listOwner, listSlug ) => ( {
listOwner,
listSlug,
} );
+
+export function requestUserLists( userSlug ) {
+ return {
+ type: READER_USER_LISTS_REQUEST,
+ userSlug,
+ };
+}
diff --git a/client/state/reader/lists/reducer.js b/client/state/reader/lists/reducer.js
index a0f4e3ae3df9f..e7b658a13c267 100644
--- a/client/state/reader/lists/reducer.js
+++ b/client/state/reader/lists/reducer.js
@@ -19,6 +19,8 @@ import {
READER_LIST_ITEM_DELETE_SITE,
READER_LIST_ITEM_DELETE_TAG,
READER_LIST_ITEM_ADD_FEED_RECEIVE,
+ READER_USER_LISTS_RECEIVE,
+ READER_USER_LISTS_REQUEST,
} from 'calypso/state/reader/action-types';
import { combineReducers, withSchemaValidation } from 'calypso/state/utils';
import { itemsSchema, subscriptionsSchema } from './schema';
@@ -198,6 +200,35 @@ export function isRequestingLists( state = false, action ) {
return state;
}
+export const userLists = ( state = {}, action ) => {
+ switch ( action.type ) {
+ case READER_USER_LISTS_RECEIVE:
+ return {
+ ...state,
+ [ action.userSlug ]: action.lists,
+ };
+ default:
+ return state;
+ }
+};
+
+export const isRequestingUserLists = ( state = {}, action ) => {
+ switch ( action.type ) {
+ case READER_USER_LISTS_REQUEST:
+ return {
+ ...state,
+ [ action.userSlug ]: true,
+ };
+ case READER_USER_LISTS_RECEIVE:
+ return {
+ ...state,
+ [ action.userSlug ]: false,
+ };
+ default:
+ return state;
+ }
+};
+
export default combineReducers( {
items,
listItems,
@@ -206,4 +237,6 @@ export default combineReducers( {
isRequestingList,
isRequestingLists,
isUpdatingList,
+ userLists,
+ isRequestingUserLists,
} );