diff --git a/app/javascript/flavours/glitch/components/content_warning.tsx b/app/javascript/flavours/glitch/components/content_warning.tsx
new file mode 100644
index 0000000000..82f9ca83ed
--- /dev/null
+++ b/app/javascript/flavours/glitch/components/content_warning.tsx
@@ -0,0 +1,27 @@
+/* Significantly rewritten from upstream to keep the old design for now */
+
+import { FormattedMessage } from 'react-intl';
+
+export const ContentWarning: React.FC<{
+ text: string;
+ expanded?: boolean;
+ onClick?: () => void;
+ icons?: React.ReactNode[];
+}> = ({ text, expanded, onClick, icons }) => (
+
(
+
- );
+ ));
}
if (hidden) {
@@ -422,15 +404,7 @@ class StatusContent extends PureComponent {
return (
-
-
- {' '}
-
-
+
{mentionsPlaceholder}
diff --git a/app/javascript/flavours/glitch/features/notifications_v2/components/embedded_status.tsx b/app/javascript/flavours/glitch/features/notifications_v2/components/embedded_status.tsx
index 3ff021e574..6a67b5c849 100644
--- a/app/javascript/flavours/glitch/features/notifications_v2/components/embedded_status.tsx
+++ b/app/javascript/flavours/glitch/features/notifications_v2/components/embedded_status.tsx
@@ -8,11 +8,13 @@ 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 { toggleStatusSpoilers } from 'flavours/glitch/actions/statuses';
import { Avatar } from 'flavours/glitch/components/avatar';
+import { ContentWarning } from 'flavours/glitch/components/content_warning';
import { DisplayName } from 'flavours/glitch/components/display_name';
import { Icon } from 'flavours/glitch/components/icon';
import type { Status } from 'flavours/glitch/models/status';
-import { useAppSelector } from 'flavours/glitch/store';
+import { useAppSelector, useAppDispatch } from 'flavours/glitch/store';
import { EmbeddedStatusContent } from './embedded_status_content';
@@ -23,6 +25,7 @@ export const EmbeddedStatus: React.FC<{ statusId: string }> = ({
}) => {
const history = useHistory();
const clickCoordinatesRef = useRef<[number, number] | null>();
+ const dispatch = useAppDispatch();
const status = useAppSelector(
(state) => state.statuses.get(statusId) as Status | undefined,
@@ -96,15 +99,21 @@ export const EmbeddedStatus: React.FC<{ statusId: string }> = ({
[],
);
+ const handleContentWarningClick = useCallback(() => {
+ dispatch(toggleStatusSpoilers(statusId));
+ }, [dispatch, statusId]);
+
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('spoilerHtml') as string;
const poll = status.get('poll');
const language = status.get('language') as string;
const mentions = status.get('mentions') as ImmutableList
;
+ const expanded = !status.get('hidden') || !contentWarning;
const mediaAttachmentsSize = (
status.get('media_attachments') as ImmutableList
).size;
@@ -124,14 +133,24 @@ export const EmbeddedStatus: React.FC<{ statusId: string }> = ({
-
+ {contentWarning && (
+
+ )}
- {(poll || mediaAttachmentsSize > 0) && (
+ {(!contentWarning || expanded) && (
+
+ )}
+
+ {expanded && (poll || mediaAttachmentsSize > 0) && (
{!!poll && (
<>
diff --git a/app/javascript/flavours/glitch/styles/components.scss b/app/javascript/flavours/glitch/styles/components.scss
index f044227c95..6ee86f5ee0 100644
--- a/app/javascript/flavours/glitch/styles/components.scss
+++ b/app/javascript/flavours/glitch/styles/components.scss
@@ -620,7 +620,7 @@ body > [data-popper-placement] {
.spoiler-input__input {
padding: 12px 12px - 5px;
- background: mix($ui-base-color, $ui-highlight-color, 85%);
+ background: rgba($ui-highlight-color, 0.05);
color: $highlight-text-color;
}
@@ -1365,7 +1365,7 @@ body > [data-popper-placement] {
.status__content__spoiler-link {
display: inline-flex; // glitch: media icon in spoiler button
border-radius: 2px;
- background: transparent;
+ background: $action-button-color; // glitch: design used in more places
border: 0;
color: $inverted-text-color;
font-weight: 700;
@@ -1378,7 +1378,8 @@ body > [data-popper-placement] {
align-items: center; // glitch: content indicator
&:hover {
- background: lighten($ui-base-color, 33%);
+ // glitch: design used in more places
+ background: lighten($action-button-color, 7%);
text-decoration: none;
}
@@ -1447,6 +1448,14 @@ body > [data-popper-placement] {
}
}
+ .content-warning {
+ margin-bottom: 10px;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+
.media-gallery,
.video-player,
.audio-player,
@@ -1771,6 +1780,14 @@ body > [data-popper-placement] {
.media-gallery__item-thumbnail {
cursor: default;
}
+
+ .content-warning {
+ margin-bottom: 16px;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
}
.status__prepend {
@@ -11185,39 +11202,59 @@ 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;
+ /* glitch: used for CWs */
+ p {
+ font-size: 15px;
+ color: $darker-text-color;
}
&__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;
+ }
}
}
@@ -11492,3 +11529,54 @@ noscript {
}
}
}
+
+.content-warning {
+ box-sizing: border-box;
+ 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);
+ padding: 8px (5px + 8px);
+ position: relative;
+ font-size: 15px;
+ line-height: 22px;
+
+ p {
+ margin-bottom: 8px;
+ }
+
+ .link-button {
+ font-size: inherit;
+ line-height: inherit;
+ font-weight: 500;
+ }
+
+ &::before,
+ &::after {
+ content: '';
+ display: block;
+ position: absolute;
+ height: 100%;
+ background: url('~images/warning-stripes.svg') repeat-y;
+ width: 5px;
+ top: 0;
+ }
+
+ &::before {
+ border-start-start-radius: 4px;
+ border-end-start-radius: 4px;
+ inset-inline-start: 0;
+ }
+
+ &::after {
+ border-start-end-radius: 4px;
+ border-end-end-radius: 4px;
+ inset-inline-end: 0;
+ }
+
+ &--filter::before,
+ &--filter::after {
+ background-image: url('~images/filter-stripes.svg');
+ }
+}