diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2024-08-09 23:21:04 +0200 |
---|---|---|
committer | Eugen Rochko <eugen@zeonfederated.com> | 2024-08-09 23:21:04 +0200 |
commit | b85ce16d4f0f03c7abfc1ef6ea836487194727d6 (patch) | |
tree | a82bde8297e3ba450801160ec623d70f1512005e | |
parent | 8a5b57f66874dd936bcaa2532f0fb9d3fabc6e5c (diff) |
Change how content warnings are displayed in notifications in web UIfeature-notification-content-warning
4 files changed, 119 insertions, 14 deletions
diff --git a/app/javascript/mastodon/components/content_warning.tsx b/app/javascript/mastodon/components/content_warning.tsx new file mode 100644 index 00000000000..8498e3ccc66 --- /dev/null +++ b/app/javascript/mastodon/components/content_warning.tsx @@ -0,0 +1,30 @@ +import { FormattedMessage } from 'react-intl'; + +export const ContentWarning: React.FC<{ + text: string; + expanded?: boolean; + onClick?: () => void; +}> = ({ text, expanded, onClick }) => ( + <div className='content-warning'> + <div className='content-warning__border' /> + + <div className='content-warning__body'> + <p>{text}</p> + <button className='link-button' onClick={onClick}> + {expanded ? ( + <FormattedMessage + id='content_warning.hide' + defaultMessage='Hide post' + /> + ) : ( + <FormattedMessage + id='content_warning.show' + defaultMessage='Show anyway' + /> + )} + </button> + </div> + + <div className='content-warning__border' /> + </div> +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx b/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx index baec0161173..0dbf5dbf8da 100644 --- a/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx +++ b/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx @@ -1,4 +1,4 @@ -import { useCallback, useRef } from 'react'; +import { useCallback, useRef, useState } from 'react'; import { FormattedMessage } from 'react-intl'; @@ -9,6 +9,7 @@ import type { List as ImmutableList, RecordOf } from 'immutable'; import BarChart4BarsIcon from '@/material-icons/400-24px/bar_chart_4_bars.svg?react'; import PhotoLibraryIcon from '@/material-icons/400-24px/photo_library.svg?react'; import { Avatar } from 'mastodon/components/avatar'; +import { ContentWarning } from 'mastodon/components/content_warning'; import { DisplayName } from 'mastodon/components/display_name'; import { Icon } from 'mastodon/components/icon'; import type { Status } from 'mastodon/models/status'; @@ -23,6 +24,7 @@ export const EmbeddedStatus: React.FC<{ statusId: string }> = ({ }) => { const history = useHistory(); const clickCoordinatesRef = useRef<[number, number] | null>(); + const [expanded, setExpanded] = useState(false); const status = useAppSelector( (state) => state.statuses.get(statusId) as Status | undefined, @@ -96,12 +98,17 @@ export const EmbeddedStatus: React.FC<{ statusId: string }> = ({ [], ); + const handleContentWarningClick = useCallback(() => { + setExpanded((v) => !v); + }, [setExpanded]); + if (!status) { return null; } // Assign status attributes to variables with a forced type, as status is not yet properly typed const contentHtml = status.get('contentHtml') as string; + const contentWarning = status.get('spoiler_text') as string; const poll = status.get('poll'); const language = status.get('language') as string; const mentions = status.get('mentions') as ImmutableList<Mention>; @@ -124,12 +131,22 @@ export const EmbeddedStatus: React.FC<{ statusId: string }> = ({ <DisplayName account={account} /> </div> - <EmbeddedStatusContent - className='notification-group__embedded-status__content reply-indicator__content translate' - content={contentHtml} - language={language} - mentions={mentions} - /> + {contentWarning && ( + <ContentWarning + text={contentWarning} + onClick={handleContentWarningClick} + expanded={expanded} + /> + )} + + {(!contentWarning || expanded) && ( + <EmbeddedStatusContent + className='notification-group__embedded-status__content reply-indicator__content translate' + content={contentHtml} + language={language} + mentions={mentions} + /> + )} {(poll || mediaAttachmentsSize > 0) && ( <div className='notification-group__embedded-status__attachments reply-indicator__attachments'> diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 86afa7cd0d7..f4e0323a817 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -193,6 +193,8 @@ "confirmations.unfollow.confirm": "Unfollow", "confirmations.unfollow.message": "Are you sure you want to unfollow {name}?", "confirmations.unfollow.title": "Unfollow user?", + "content_warning.hide": "Hide post", + "content_warning.show": "Show anyway", "conversation.delete": "Delete conversation", "conversation.mark_as_read": "Mark as read", "conversation.open": "View conversation", diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 3c938ac4c59..d64901afd00 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -10438,39 +10438,53 @@ noscript { } &__embedded-status { + display: flex; + flex-direction: column; + gap: 8px; cursor: pointer; &__account { display: flex; align-items: center; gap: 4px; - margin-bottom: 8px; color: $dark-text-color; + font-size: 15px; + line-height: 22px; bdi { - color: inherit; + color: $darker-text-color; } } - .account__avatar { - opacity: 0.5; - } - &__content { display: -webkit-box; font-size: 15px; line-height: 22px; - color: $dark-text-color; + color: $darker-text-color; -webkit-line-clamp: 4; -webkit-box-orient: vertical; max-height: 4 * 22px; overflow: hidden; + p { + display: none; + + &:first-child { + display: initial; + } + } + p, a { color: inherit; } } + + .reply-indicator__attachments { + font-size: 15px; + line-height: 22px; + color: $dark-text-color; + } } } @@ -10740,3 +10754,45 @@ noscript { } } } + +.content-warning { + display: flex; + align-items: stretch; + gap: 8px; + background: rgba($ui-highlight-color, 0.05); + color: $secondary-text-color; + border-top: 1px solid; + border-bottom: 1px solid; + border-color: rgba($ui-highlight-color, 0.15); + + &__body { + flex: 1 1 auto; + padding: 8px 0; + font-size: 15px; + line-height: 22px; + + p { + margin-bottom: 8px; + } + + .link-button { + font-size: inherit; + line-height: inherit; + font-weight: 500; + } + } + + &__border { + background: url('../images/warning-stripes.svg') repeat-y; + width: 5px; + flex: 0 0 auto; + + &:first-child { + border-start-start-radius: 4px; + } + + &:last-child { + border-start-end-radius: 4px; + } + } +} |