From 3bef7c69ff0b21157f70ec60ca3bfbd0d76755d3 Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 9 Sep 2022 10:43:33 -0400 Subject: [PATCH 1/8] Map paginated results into normalized Tag --- app/soapbox/reducers/search.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/soapbox/reducers/search.ts b/app/soapbox/reducers/search.ts index eb2c1ed8d..911008505 100644 --- a/app/soapbox/reducers/search.ts +++ b/app/soapbox/reducers/search.ts @@ -82,7 +82,7 @@ const paginateResults = (state: State, searchType: SearchFilter, results: APIEnt const data = results[searchType]; // Hashtags are a list of maps. Others are IDs. if (searchType === 'hashtags') { - return (items as ImmutableOrderedSet).concat(fromJS(data)); + return (items as ImmutableOrderedSet).concat((fromJS(data) as Record).map(normalizeTag)); } else { return (items as ImmutableOrderedSet).concat(toIds(data)); } From ac52071e2fa7a8029c0dc86c10c0aa6c51388365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Fri, 9 Sep 2022 23:20:26 +0200 Subject: [PATCH 2/8] Do not reset tab/searched account when clearing search input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- app/soapbox/actions/search.ts | 19 +++++++++++++++---- .../features/compose/components/search.tsx | 3 ++- .../compose/components/search_results.tsx | 6 +++--- app/soapbox/reducers/search.ts | 16 +++++++++++++++- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/app/soapbox/actions/search.ts b/app/soapbox/actions/search.ts index e8718d479..a2f165ac0 100644 --- a/app/soapbox/actions/search.ts +++ b/app/soapbox/actions/search.ts @@ -8,9 +8,10 @@ import type { SearchFilter } from 'soapbox/reducers/search'; import type { AppDispatch, RootState } from 'soapbox/store'; import type { APIEntity } from 'soapbox/types/entities'; -const SEARCH_CHANGE = 'SEARCH_CHANGE'; -const SEARCH_CLEAR = 'SEARCH_CLEAR'; -const SEARCH_SHOW = 'SEARCH_SHOW'; +const SEARCH_CHANGE = 'SEARCH_CHANGE'; +const SEARCH_CLEAR = 'SEARCH_CLEAR'; +const SEARCH_SHOW = 'SEARCH_SHOW'; +const SEARCH_RESULTS_CLEAR = 'SEARCH_RESULTS_CLEAR'; const SEARCH_FETCH_REQUEST = 'SEARCH_FETCH_REQUEST'; const SEARCH_FETCH_SUCCESS = 'SEARCH_FETCH_SUCCESS'; @@ -28,7 +29,11 @@ const changeSearch = (value: string) => (dispatch: AppDispatch) => { // If backspaced all the way, clear the search if (value.length === 0) { - return dispatch(clearSearch()); + dispatch(clearSearchResults()); + return dispatch({ + type: SEARCH_CHANGE, + value, + }); } else { return dispatch({ type: SEARCH_CHANGE, @@ -41,6 +46,10 @@ const clearSearch = () => ({ type: SEARCH_CLEAR, }); +const clearSearchResults = () => ({ + type: SEARCH_RESULTS_CLEAR, +}); + const submitSearch = (filter?: SearchFilter) => (dispatch: AppDispatch, getState: () => RootState) => { const value = getState().search.value; @@ -167,6 +176,7 @@ export { SEARCH_CHANGE, SEARCH_CLEAR, SEARCH_SHOW, + SEARCH_RESULTS_CLEAR, SEARCH_FETCH_REQUEST, SEARCH_FETCH_SUCCESS, SEARCH_FETCH_FAIL, @@ -177,6 +187,7 @@ export { SEARCH_ACCOUNT_SET, changeSearch, clearSearch, + clearSearchResults, submitSearch, fetchSearchRequest, fetchSearchSuccess, diff --git a/app/soapbox/features/compose/components/search.tsx b/app/soapbox/features/compose/components/search.tsx index ec7c89468..9402b8785 100644 --- a/app/soapbox/features/compose/components/search.tsx +++ b/app/soapbox/features/compose/components/search.tsx @@ -9,6 +9,7 @@ import { useHistory } from 'react-router-dom'; import { changeSearch, clearSearch, + clearSearchResults, setSearchAccount, showSearch, submitSearch, @@ -72,7 +73,7 @@ const Search = (props: ISearch) => { event.preventDefault(); if (value.length > 0 || submitted) { - dispatch(clearSearch()); + dispatch(clearSearchResults()); } }; diff --git a/app/soapbox/features/compose/components/search_results.tsx b/app/soapbox/features/compose/components/search_results.tsx index b1cb833ba..8f8fa5938 100644 --- a/app/soapbox/features/compose/components/search_results.tsx +++ b/app/soapbox/features/compose/components/search_results.tsx @@ -2,7 +2,7 @@ import classNames from 'clsx'; import React, { useEffect, useRef } from 'react'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; -import { clearSearch, expandSearch, setFilter } from 'soapbox/actions/search'; +import { expandSearch, setFilter, setSearchAccount } from 'soapbox/actions/search'; import { fetchTrendingStatuses } from 'soapbox/actions/trending_statuses'; import Hashtag from 'soapbox/components/hashtag'; import IconButton from 'soapbox/components/icon_button'; @@ -43,7 +43,7 @@ const SearchResults = () => { const handleLoadMore = () => dispatch(expandSearch(selectedFilter)); - const handleClearSearch = () => dispatch(clearSearch()); + const handleUnsetAccount = () => dispatch(setSearchAccount(null)); const selectFilter = (newActiveFilter: SearchFilter) => dispatch(setFilter(newActiveFilter)); @@ -196,7 +196,7 @@ const SearchResults = () => { <> {filterByAccount ? ( - + Date: Fri, 9 Sep 2022 23:06:18 +0200 Subject: [PATCH 3/8] Allow searching your own posts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- app/soapbox/features/account/components/header.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/soapbox/features/account/components/header.tsx b/app/soapbox/features/account/components/header.tsx index 3f4d239bf..c9620485b 100644 --- a/app/soapbox/features/account/components/header.tsx +++ b/app/soapbox/features/account/components/header.tsx @@ -74,6 +74,7 @@ const messages = defineMessages({ suggestUser: { id: 'admin.users.actions.suggest_user', defaultMessage: 'Suggest @{name}' }, unsuggestUser: { id: 'admin.users.actions.unsuggest_user', defaultMessage: 'Unsuggest @{name}' }, search: { id: 'account.search', defaultMessage: 'Search from @{name}' }, + searchSelf: { id: 'account.search_self', defaultMessage: 'Search your posts' }, unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' }, blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Hide entire domain' }, @@ -378,6 +379,13 @@ const Header: React.FC = ({ account }) => { to: '/settings', icon: require('@tabler/icons/settings.svg'), }); + if (features.searchFromAccount) { + menu.push({ + text: intl.formatMessage(messages.searchSelf, { name: account.username }), + action: onSearch, + icon: require('@tabler/icons/search.svg'), + }); + } menu.push(null); menu.push({ text: intl.formatMessage(messages.mutes), From 82edcc4bd8f68a770a5c23ccf83d199c8e9515be Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 10 Sep 2022 12:04:08 -0500 Subject: [PATCH 4/8] Delete unused "introduction" feature --- app/soapbox/features/introduction/index.js | 172 --------------------- 1 file changed, 172 deletions(-) delete mode 100644 app/soapbox/features/introduction/index.js diff --git a/app/soapbox/features/introduction/index.js b/app/soapbox/features/introduction/index.js deleted file mode 100644 index a35ba341a..000000000 --- a/app/soapbox/features/introduction/index.js +++ /dev/null @@ -1,172 +0,0 @@ -import classNames from 'clsx'; -import PropTypes from 'prop-types'; -import React from 'react'; -import { FormattedMessage } from 'react-intl'; -import { connect } from 'react-redux'; -import ReactSwipeableViews from 'react-swipeable-views'; - -import { closeOnboarding } from '../../actions/onboarding'; - -const FrameWelcome = ({ domain, onNext }) => ( -
-
-

-

{domain} }} />

-
- -
- -
-
-); - -FrameWelcome.propTypes = { - domain: PropTypes.string.isRequired, - onNext: PropTypes.func.isRequired, -}; - -const FrameFederation = ({ onNext }) => ( -
-
-
-

-

-
-
- -
- -
-
-); - -FrameFederation.propTypes = { - onNext: PropTypes.func.isRequired, -}; - -const FrameInteractions = ({ onNext }) => ( -
-
-
-

-

-
- -
-

-

-
- -
-

-

-
-
- -
- -
-
-); - -FrameInteractions.propTypes = { - onNext: PropTypes.func.isRequired, -}; - -export default @connect(state => ({ domain: state.getIn(['meta', 'domain']) })) -class Introduction extends React.PureComponent { - - static propTypes = { - domain: PropTypes.string.isRequired, - dispatch: PropTypes.func.isRequired, - }; - - state = { - currentIndex: 0, - }; - - constructor(props) { - super(props); - this.pages = [ - , - , - , - ]; - } - - componentDidMount() { - window.addEventListener('keyup', this.handleKeyUp); - } - - componentWillUnmount() { - window.addEventListener('keyup', this.handleKeyUp); - } - - handleDot = (e) => { - const i = Number(e.currentTarget.getAttribute('data-index')); - e.preventDefault(); - this.setState({ currentIndex: i }); - } - - handlePrev = () => { - this.setState(({ currentIndex }) => ({ - currentIndex: Math.max(0, currentIndex - 1), - })); - } - - handleNext = () => { - const { pages } = this; - - this.setState(({ currentIndex }) => ({ - currentIndex: Math.min(currentIndex + 1, pages.length - 1), - })); - } - - handleSwipe = (index) => { - this.setState({ currentIndex: index }); - } - - handleFinish = () => { - this.props.dispatch(closeOnboarding()); - } - - handleKeyUp = ({ key }) => { - switch (key) { - case 'ArrowLeft': - this.handlePrev(); - break; - case 'ArrowRight': - this.handleNext(); - break; - } - } - - render() { - const { currentIndex } = this.state; - const { pages } = this; - - return ( -
- - {pages.map((page, i) => ( -
{page}
- ))} -
- -
- {pages.map((_, i) => ( -
- ))} -
-
- ); - } - -} From bcfbc394ab39adb1c6929942aee0d8d11be6ea4b Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sat, 10 Sep 2022 12:05:38 -0500 Subject: [PATCH 5/8] Delete Groups components --- app/soapbox/features/groups/create/index.js | 116 -------------- app/soapbox/features/groups/edit/index.js | 148 ------------------ app/soapbox/features/groups/index/card.js | 57 ------- app/soapbox/features/groups/index/index.js | 93 ----------- app/soapbox/features/groups/members/index.js | 76 --------- .../features/groups/removed_accounts/index.js | 94 ----------- .../features/groups/sidebar_panel/index.js | 53 ------- .../features/groups/sidebar_panel/item.js | 48 ------ .../groups/timeline/components/header.js | 92 ----------- .../groups/timeline/components/panel.js | 38 ----- .../timeline/containers/header_container.js | 21 --- app/soapbox/features/groups/timeline/index.js | 107 ------------- .../features/ui/util/async-components.ts | 24 --- app/soapbox/pages/group_page.js | 75 --------- app/soapbox/pages/groups_page.js | 60 ------- 15 files changed, 1102 deletions(-) delete mode 100644 app/soapbox/features/groups/create/index.js delete mode 100644 app/soapbox/features/groups/edit/index.js delete mode 100644 app/soapbox/features/groups/index/card.js delete mode 100644 app/soapbox/features/groups/index/index.js delete mode 100644 app/soapbox/features/groups/members/index.js delete mode 100644 app/soapbox/features/groups/removed_accounts/index.js delete mode 100644 app/soapbox/features/groups/sidebar_panel/index.js delete mode 100644 app/soapbox/features/groups/sidebar_panel/item.js delete mode 100644 app/soapbox/features/groups/timeline/components/header.js delete mode 100644 app/soapbox/features/groups/timeline/components/panel.js delete mode 100644 app/soapbox/features/groups/timeline/containers/header_container.js delete mode 100644 app/soapbox/features/groups/timeline/index.js delete mode 100644 app/soapbox/pages/group_page.js delete mode 100644 app/soapbox/pages/groups_page.js diff --git a/app/soapbox/features/groups/create/index.js b/app/soapbox/features/groups/create/index.js deleted file mode 100644 index d7189baa4..000000000 --- a/app/soapbox/features/groups/create/index.js +++ /dev/null @@ -1,116 +0,0 @@ -import classNames from 'clsx'; -import PropTypes from 'prop-types'; -import React from 'react'; -import { defineMessages, injectIntl } from 'react-intl'; -import { connect } from 'react-redux'; -import { withRouter } from 'react-router-dom'; - -import { changeValue, submit, reset } from '../../../actions/group_editor'; - -const messages = defineMessages({ - title: { id: 'groups.form.title', defaultMessage: 'Enter a new group title' }, - description: { id: 'groups.form.description', defaultMessage: 'Enter the group description' }, - coverImage: { id: 'groups.form.coverImage', defaultMessage: 'Upload a banner image' }, - coverImageChange: { id: 'groups.form.coverImageChange', defaultMessage: 'Banner image selected' }, - create: { id: 'groups.form.create', defaultMessage: 'Create group' }, -}); - -const mapStateToProps = state => ({ - title: state.getIn(['group_editor', 'title']), - description: state.getIn(['group_editor', 'description']), - coverImage: state.getIn(['group_editor', 'coverImage']), - disabled: state.getIn(['group_editor', 'isSubmitting']), -}); - -const mapDispatchToProps = dispatch => ({ - onTitleChange: value => dispatch(changeValue('title', value)), - onDescriptionChange: value => dispatch(changeValue('description', value)), - onCoverImageChange: value => dispatch(changeValue('coverImage', value)), - onSubmit: routerHistory => dispatch(submit(routerHistory)), - reset: () => dispatch(reset()), -}); - -export default @connect(mapStateToProps, mapDispatchToProps) -@injectIntl -@withRouter -class Create extends React.PureComponent { - - static propTypes = { - title: PropTypes.string.isRequired, - description: PropTypes.string.isRequired, - coverImage: PropTypes.object, - disabled: PropTypes.bool, - intl: PropTypes.object.isRequired, - onTitleChange: PropTypes.func.isRequired, - onSubmit: PropTypes.func.isRequired, - reset: PropTypes.func.isRequired, - onDescriptionChange: PropTypes.func.isRequired, - onCoverImageChange: PropTypes.func.isRequired, - history: PropTypes.object, - }; - - constructor(props) { - super(props); - props.reset(); - } - - handleTitleChange = e => { - this.props.onTitleChange(e.target.value); - } - - handleDescriptionChange = e => { - this.props.onDescriptionChange(e.target.value); - } - - handleCoverImageChange = e => { - this.props.onCoverImageChange(e.target.files[0]); - } - - handleSubmit = e => { - e.preventDefault(); - this.props.onSubmit(this.props.history); - } - - render() { - const { title, description, coverImage, disabled, intl } = this.props; - - return ( -
-
- -
-
-