From 610864d5a9b5fbbb858ce7f307c74ab594204adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Wed, 3 May 2023 00:21:53 +0200 Subject: [PATCH] Add followed tags list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- app/soapbox/features/followed_tags/index.tsx | 52 ++++++++++++++++++++ app/soapbox/reducers/followed_tags.ts | 47 ++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 app/soapbox/features/followed_tags/index.tsx create mode 100644 app/soapbox/reducers/followed_tags.ts diff --git a/app/soapbox/features/followed_tags/index.tsx b/app/soapbox/features/followed_tags/index.tsx new file mode 100644 index 000000000..6745f5fc0 --- /dev/null +++ b/app/soapbox/features/followed_tags/index.tsx @@ -0,0 +1,52 @@ +import debounce from 'lodash/debounce'; +import React, { useEffect } from 'react'; +import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; + +import { fetchFollowedHashtags, expandFollowedHashtags } from 'soapbox/actions/tags'; +import Hashtag from 'soapbox/components/hashtag'; +import ScrollableList from 'soapbox/components/scrollable-list'; +import { Column } from 'soapbox/components/ui'; +import PlaceholderHashtag from 'soapbox/features/placeholder/components/placeholder-hashtag'; +import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; + +const messages = defineMessages({ + heading: { id: 'column.followed_tags', defaultMessage: 'Followed hashtags' }, +}); + +const handleLoadMore = debounce((dispatch) => { + dispatch(expandFollowedHashtags()); +}, 300, { leading: true }); + +const FollowedTags = () => { + const intl = useIntl(); + const dispatch = useAppDispatch(); + + useEffect(() => { + dispatch(fetchFollowedHashtags()); + }, []); + + const tags = useAppSelector((state => state.followed_tags.items)); + const isLoading = useAppSelector((state => state.followed_tags.isLoading)); + const hasMore = useAppSelector((state => !!state.followed_tags.next)); + + const emptyMessage = ; + + return ( + + handleLoadMore(dispatch)} + placeholderComponent={PlaceholderHashtag} + placeholderCount={5} + itemClassName='pb-3' + > + {tags.map(tag => )} + + + ); +}; + +export default FollowedTags; diff --git a/app/soapbox/reducers/followed_tags.ts b/app/soapbox/reducers/followed_tags.ts new file mode 100644 index 000000000..4f30a3f3a --- /dev/null +++ b/app/soapbox/reducers/followed_tags.ts @@ -0,0 +1,47 @@ +import { List as ImmutableList, Record as ImmutableRecord } from 'immutable'; + +import { + FOLLOWED_HASHTAGS_FETCH_REQUEST, + FOLLOWED_HASHTAGS_FETCH_SUCCESS, + FOLLOWED_HASHTAGS_FETCH_FAIL, + FOLLOWED_HASHTAGS_EXPAND_REQUEST, + FOLLOWED_HASHTAGS_EXPAND_SUCCESS, + FOLLOWED_HASHTAGS_EXPAND_FAIL, +} from 'soapbox/actions/tags'; +import { normalizeTag } from 'soapbox/normalizers'; + +import type { AnyAction } from 'redux'; +import type { APIEntity, Tag } from 'soapbox/types/entities'; + +const ReducerRecord = ImmutableRecord({ + items: ImmutableList(), + isLoading: false, + next: null, +}); + +export default function followed_tags(state = ReducerRecord(), action: AnyAction) { + switch (action.type) { + case FOLLOWED_HASHTAGS_FETCH_REQUEST: + return state.set('isLoading', true); + case FOLLOWED_HASHTAGS_FETCH_SUCCESS: + return state.withMutations(map => { + map.set('items', ImmutableList(action.followed_tags.map((item: APIEntity) => normalizeTag(item)))); + map.set('isLoading', false); + map.set('next', action.next); + }); + case FOLLOWED_HASHTAGS_FETCH_FAIL: + return state.set('isLoading', false); + case FOLLOWED_HASHTAGS_EXPAND_REQUEST: + return state.set('isLoading', true); + case FOLLOWED_HASHTAGS_EXPAND_SUCCESS: + return state.withMutations(map => { + map.update('items', list => list.concat(action.followed_tags.map((item: APIEntity) => normalizeTag(item)))); + map.set('isLoading', false); + map.set('next', action.next); + }); + case FOLLOWED_HASHTAGS_EXPAND_FAIL: + return state.set('isLoading', false); + default: + return state; + } +}