From 49a7d40efbc3eb46af64efe37e1982aeb34b4386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Tue, 7 Feb 2023 15:38:31 +0100 Subject: [PATCH] Fix filters, restyle filters page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- app/soapbox/components/status.tsx | 6 +- app/soapbox/containers/status-container.tsx | 7 +- app/soapbox/features/filters/index.tsx | 146 ++++++++++-------- app/soapbox/features/forms/index.tsx | 8 - .../notifications/components/notification.tsx | 1 + .../status/components/thread-status.tsx | 1 + app/soapbox/features/status/index.tsx | 1 + app/soapbox/normalizers/filter.ts | 6 +- app/soapbox/selectors/index.ts | 9 +- app/styles/application.scss | 1 - app/styles/components/filters.scss | 93 ----------- app/styles/components/status.scss | 2 +- app/styles/forms.scss | 12 -- 13 files changed, 99 insertions(+), 194 deletions(-) delete mode 100644 app/styles/components/filters.scss diff --git a/app/soapbox/components/status.tsx b/app/soapbox/components/status.tsx index b9989ae4c..3996777fb 100644 --- a/app/soapbox/components/status.tsx +++ b/app/soapbox/components/status.tsx @@ -289,8 +289,10 @@ const Status: React.FC = (props) => { return ( -
- +
+ + +
); diff --git a/app/soapbox/containers/status-container.tsx b/app/soapbox/containers/status-container.tsx index 89c387ffd..5398547c9 100644 --- a/app/soapbox/containers/status-container.tsx +++ b/app/soapbox/containers/status-container.tsx @@ -6,8 +6,7 @@ import { makeGetStatus } from 'soapbox/selectors'; interface IStatusContainer extends Omit { id: string, - /** @deprecated Unused. */ - contextType?: any, + contextType?: string, /** @deprecated Unused. */ otherAccounts?: any, /** @deprecated Unused. */ @@ -21,10 +20,10 @@ interface IStatusContainer extends Omit { * @deprecated Use the Status component directly. */ const StatusContainer: React.FC = (props) => { - const { id, ...rest } = props; + const { id, contextType, ...rest } = props; const getStatus = useCallback(makeGetStatus(), []); - const status = useAppSelector(state => getStatus(state, { id })); + const status = useAppSelector(state => getStatus(state, { id, contextType })); if (status) { return ; diff --git a/app/soapbox/features/filters/index.tsx b/app/soapbox/features/filters/index.tsx index 79a7ff006..152892651 100644 --- a/app/soapbox/features/filters/index.tsx +++ b/app/soapbox/features/filters/index.tsx @@ -2,13 +2,9 @@ import React, { useEffect, useState } from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { fetchFilters, createFilter, deleteFilter } from 'soapbox/actions/filters'; -import Icon from 'soapbox/components/icon'; +import List, { ListItem } from 'soapbox/components/list'; import ScrollableList from 'soapbox/components/scrollable-list'; -import { Button, CardHeader, CardTitle, Column, Form, FormActions, FormGroup, Input, Text } from 'soapbox/components/ui'; -import { - FieldsGroup, - Checkbox, -} from 'soapbox/features/forms'; +import { Button, CardHeader, CardTitle, Column, Form, FormActions, FormGroup, HStack, IconButton, Input, Stack, Text, Toggle } from 'soapbox/components/ui'; import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; import toast from 'soapbox/toast'; @@ -33,6 +29,13 @@ const messages = defineMessages({ delete: { id: 'column.filters.delete', defaultMessage: 'Delete' }, }); +const contexts = { + home: messages.home_timeline, + public: messages.public_timeline, + notifications: messages.notifications, + thread: messages.conversations, +}; + // const expirations = { // null: 'Never', // // 3600: '30 minutes', @@ -85,8 +88,8 @@ const Filters = () => { }); }; - const handleFilterDelete: React.MouseEventHandler = e => { - dispatch(deleteFilter(e.currentTarget.dataset.value!)).then(() => { + const handleFilterDelete = (id: string) => () => { + dispatch(deleteFilter(id)).then(() => { return dispatch(fetchFilters()); }).catch(() => { toast.error(intl.formatMessage(messages.delete_error)); @@ -121,58 +124,68 @@ const Filters = () => { /> */} - - + + - + -
- + + + + setHomeTimeline(target.checked)} /> - + + setPublicTimeline(target.checked)} /> - + + setNotifications(target.checked)} /> - + + setConversations(target.checked)} /> -
+ + -
- - - + setIrreversible(target.checked)} - /> - + setIrreversible(target.checked)} + /> + + setWholeWord(target.checked)} - /> - + > + setWholeWord(target.checked)} + /> + + @@ -186,40 +199,41 @@ const Filters = () => { {filters.map((filter, i) => ( -
-
-
- - {filter.phrase} -
-
- - - {filter.context.map((context, i) => ( - {context} - ))} - -
-
- - + + + + + {' '} + {filter.phrase} + + + + {' '} + {filter.context.map(context => contexts[context] ? intl.formatMessage(contexts[context]) : context).join(', ')} + + + {filter.irreversible ? - : - - } - {filter.whole_word && - - } - -
-
-
- - -
-
+ : + } + + {filter.whole_word && ( + + + + )} + + + + ))}
diff --git a/app/soapbox/features/forms/index.tsx b/app/soapbox/features/forms/index.tsx index c01a3035d..54bd5994c 100644 --- a/app/soapbox/features/forms/index.tsx +++ b/app/soapbox/features/forms/index.tsx @@ -160,14 +160,6 @@ export const SimpleForm: React.FC = (props) => { ); }; -interface IFieldsGroup { - children: React.ReactNode, -} - -export const FieldsGroup: React.FC = ({ children }) => ( -
{children}
-); - interface ICheckbox { label?: React.ReactNode, hint?: React.ReactNode, diff --git a/app/soapbox/features/notifications/components/notification.tsx b/app/soapbox/features/notifications/components/notification.tsx index ccb15c143..1a2755800 100644 --- a/app/soapbox/features/notifications/components/notification.tsx +++ b/app/soapbox/features/notifications/components/notification.tsx @@ -329,6 +329,7 @@ const Notification: React.FC = (props) => { onMoveDown={handleMoveDown} onMoveUp={handleMoveUp} avatarSize={avatarSize} + contextType='notifications' /> ) : null; default: diff --git a/app/soapbox/features/status/components/thread-status.tsx b/app/soapbox/features/status/components/thread-status.tsx index a5fce9a75..1c6bc9ef2 100644 --- a/app/soapbox/features/status/components/thread-status.tsx +++ b/app/soapbox/features/status/components/thread-status.tsx @@ -8,6 +8,7 @@ import { useAppSelector } from 'soapbox/hooks'; interface IThreadStatus { id: string, + contextType?: string, focusedStatusId: string, onMoveUp: (id: string) => void, onMoveDown: (id: string) => void, diff --git a/app/soapbox/features/status/index.tsx b/app/soapbox/features/status/index.tsx index 86039244c..dfda21dd9 100644 --- a/app/soapbox/features/status/index.tsx +++ b/app/soapbox/features/status/index.tsx @@ -361,6 +361,7 @@ const Thread: React.FC = (props) => { focusedStatusId={status!.id} onMoveUp={handleMoveUp} onMoveDown={handleMoveDown} + contextType='thread' /> ); }; diff --git a/app/soapbox/normalizers/filter.ts b/app/soapbox/normalizers/filter.ts index 5f2f57960..5537acac9 100644 --- a/app/soapbox/normalizers/filter.ts +++ b/app/soapbox/normalizers/filter.ts @@ -5,11 +5,13 @@ */ import { List as ImmutableList, Map as ImmutableMap, Record as ImmutableRecord, fromJS } from 'immutable'; +export type ContextType = 'home' | 'public' | 'notifications' | 'thread'; + // https://docs.joinmastodon.org/entities/filter/ export const FilterRecord = ImmutableRecord({ id: '', phrase: '', - context: ImmutableList(), + context: ImmutableList(), whole_word: false, expires_at: '', irreversible: false, @@ -19,4 +21,4 @@ export const normalizeFilter = (filter: Record) => { return FilterRecord( ImmutableMap(fromJS(filter)), ); -}; \ No newline at end of file +}; diff --git a/app/soapbox/selectors/index.ts b/app/soapbox/selectors/index.ts index 032259b4d..5e518f082 100644 --- a/app/soapbox/selectors/index.ts +++ b/app/soapbox/selectors/index.ts @@ -12,6 +12,7 @@ import { validId } from 'soapbox/utils/auth'; import ConfigDB from 'soapbox/utils/config-db'; import { shouldFilter } from 'soapbox/utils/timelines'; +import type { ContextType } from 'soapbox/normalizers/filter'; import type { ReducerChat } from 'soapbox/reducers/chats'; import type { RootState } from 'soapbox/store'; import type { Filter as FilterEntity, Notification } from 'soapbox/types/entities'; @@ -85,7 +86,7 @@ export const findAccountByUsername = (state: RootState, username: string) => { } }; -const toServerSideType = (columnType: string): string => { +const toServerSideType = (columnType: string): ContextType => { switch (columnType) { case 'home': case 'notifications': @@ -105,10 +106,8 @@ type FilterContext = { contextType?: string }; export const getFilters = (state: RootState, query: FilterContext) => { return state.filters.filter((filter) => { - return query?.contextType - && filter.context.includes(toServerSideType(query.contextType)) - && (filter.expires_at === null - || Date.parse(filter.expires_at) > new Date().getTime()); + return (!query?.contextType || filter.context.includes(toServerSideType(query.contextType))) + && (filter.expires_at === null || Date.parse(filter.expires_at) > new Date().getTime()); }); }; diff --git a/app/styles/application.scss b/app/styles/application.scss index 4694fccb9..43f1a2761 100644 --- a/app/styles/application.scss +++ b/app/styles/application.scss @@ -29,7 +29,6 @@ @import 'components/react-toggle'; @import 'components/video-player'; @import 'components/audio-player'; -@import 'components/filters'; @import 'components/crypto-donate'; @import 'components/aliases'; @import 'components/icon'; diff --git a/app/styles/components/filters.scss b/app/styles/components/filters.scss deleted file mode 100644 index 4d985c8c0..000000000 --- a/app/styles/components/filters.scss +++ /dev/null @@ -1,93 +0,0 @@ -.filter-settings-panel { - .fields-group .two-col { - display: flex; - align-items: flex-start; - width: 100%; - justify-content: flex-start; - flex-wrap: wrap; - - div.input { - width: 45%; - margin-right: 20px; - - .label_input { - width: 100%; - } - } - - @media (max-width: 485px) { - div.input { - width: 100%; - margin-right: 5px; - - .label_input { - width: auto; - } - } - } - } - - .input.boolean { - .label_input { - @apply relative pl-7 text-black dark:text-white; - - label { - @apply text-sm; - } - - &__wrapper { - @apply static; - } - - input[type='checkbox'] { - position: absolute; - top: 3px; - left: 0; - } - } - - .hint { - @apply block pl-7 text-xs text-gray-500 dark:text-gray-400; - } - } - - .filter__container { - @apply flex justify-between py-5 px-2 text-sm text-black dark:text-white; - - .filter__phrase, - .filter__contexts, - .filter__details { - @apply py-1; - } - - span.filter__list-label { - @apply pr-1 text-gray-500 dark:text-gray-400; - } - - span.filter__list-value span { - @apply pr-1 capitalize; - - &::after { - content: ','; - } - - &:last-of-type { - &::after { - content: ''; - } - } - } - - .filter__delete { - @apply flex items-center h-5 m-2.5 cursor-pointer; - - span.filter__delete-label { - @apply text-gray-500 dark:text-gray-400 font-semibold; - } - - .filter__delete-icon { - @apply mx-1 text-gray-500 dark:text-gray-400; - } - } - } -} diff --git a/app/styles/components/status.scss b/app/styles/components/status.scss index b273c0e83..2e6ef4452 100644 --- a/app/styles/components/status.scss +++ b/app/styles/components/status.scss @@ -17,7 +17,7 @@ [column-type='filled'] .status__wrapper, [column-type='filled'] .status-placeholder { - @apply rounded-none shadow-none p-4; + @apply bg-transparent dark:bg-transparent rounded-none shadow-none p-4; } .status-check-box { diff --git a/app/styles/forms.scss b/app/styles/forms.scss index a0db30c20..f053a39d1 100644 --- a/app/styles/forms.scss +++ b/app/styles/forms.scss @@ -191,18 +191,6 @@ select { color: lighten($error-value-color, 12%); } - .fields-group { - margin-bottom: 25px; - - &:last-child { - margin-bottom: 0; - } - - .input:last-child { - margin-bottom: 0; - } - } - .input.radio_buttons .radio label { @apply text-gray-900; margin-bottom: 5px;