From b7d822fc5984820467871b709c730a28fb3cf597 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 5 Jun 2024 12:29:43 +0200 Subject: [PATCH] WIP --- .../components/moderation_warning.tsx | 17 +- .../relationships_severance_event.jsx | 10 +- .../components/avatar_group.tsx | 19 ++ .../components/embedded_status.tsx | 36 ++++ .../components/names_list.tsx | 21 ++ .../components/notification_admin_report.tsx | 57 +++++ .../components/notification_admin_sign_up.tsx | 20 ++ .../components/notification_favourite.tsx | 21 ++ .../components/notification_follow.tsx | 20 ++ .../notification_follow_request.tsx | 20 ++ .../components/notification_group.tsx | 98 +++++++-- .../notification_group_with_status.tsx | 43 ++++ .../components/notification_mention.tsx | 20 ++ .../notification_moderation_warning.tsx | 11 + .../components/notification_poll.tsx | 20 ++ .../components/notification_reblog.tsx | 20 +- .../notification_severed_relationships.tsx | 13 ++ .../components/notification_status.tsx | 20 ++ .../components/notification_update.tsx | 20 ++ .../components/notification_with_status.tsx | 31 +++ app/javascript/mastodon/locales/en.json | 5 + .../styles/mastodon/components.scss | 201 ++++++++++++++++-- 22 files changed, 687 insertions(+), 56 deletions(-) create mode 100644 app/javascript/mastodon/features/notifications_v2/components/avatar_group.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/names_list.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_admin_report.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_admin_sign_up.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_favourite.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_follow.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_follow_request.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_group_with_status.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_mention.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_moderation_warning.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_poll.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_severed_relationships.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_status.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_update.tsx create mode 100644 app/javascript/mastodon/features/notifications_v2/components/notification_with_status.tsx diff --git a/app/javascript/mastodon/features/notifications/components/moderation_warning.tsx b/app/javascript/mastodon/features/notifications/components/moderation_warning.tsx index 2c1683e218..e7ca77f423 100644 --- a/app/javascript/mastodon/features/notifications/components/moderation_warning.tsx +++ b/app/javascript/mastodon/features/notifications/components/moderation_warning.tsx @@ -56,23 +56,18 @@ export const ModerationWarning: React.FC = ({ action, id, hidden }) => { } return ( - - +
+
-
+

{intl.formatMessage(messages[action])}

- +
- +
- +
); }; diff --git a/app/javascript/mastodon/features/notifications/components/relationships_severance_event.jsx b/app/javascript/mastodon/features/notifications/components/relationships_severance_event.jsx index 738159fc5a..310be8eb13 100644 --- a/app/javascript/mastodon/features/notifications/components/relationships_severance_event.jsx +++ b/app/javascript/mastodon/features/notifications/components/relationships_severance_event.jsx @@ -21,14 +21,14 @@ export const RelationshipsSeveranceEvent = ({ type, target, followingCount, foll } return ( - - +
+
-
+ - +
); }; diff --git a/app/javascript/mastodon/features/notifications_v2/components/avatar_group.tsx b/app/javascript/mastodon/features/notifications_v2/components/avatar_group.tsx new file mode 100644 index 0000000000..de404faa52 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/avatar_group.tsx @@ -0,0 +1,19 @@ +import { Avatar } from 'mastodon/components/avatar'; +import { useAppSelector } from 'mastodon/store'; +import { Link } from 'react-router-dom'; + +const AvatarWrapper = ({ accountId }) => { + const account = useAppSelector(state => state.getIn(['accounts', accountId])); + + return ( + + + + ); +}; + +export const AvatarGroup = ({ accountIds }) => ( +
+ {accountIds.map(accountId => )} +
+); diff --git a/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx b/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx new file mode 100644 index 0000000000..1e5caf301d --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/embedded_status.tsx @@ -0,0 +1,36 @@ +import { useAppSelector } from 'mastodon/store'; +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 { Icon } from 'mastodon/components/icon'; +import { FormattedMessage } from 'react-intl'; +import { Avatar } from 'mastodon/components/avatar'; +import { DisplayName } from 'mastodon/components/display_name'; + +export const EmbeddedStatus = ({ statusId }) => { + const status = useAppSelector(state => state.getIn(['statuses', statusId])); + const account = useAppSelector(state => state.getIn(['accounts', status?.get('account')])); + + if (!status) { + return null; + } + + const content = { __html: status.get('contentHtml') }; + + return ( +
+
+ + +
+ +
+ + {(status.get('poll') || status.get('media_attachments').size > 0) && ( +
+ {status.get('poll') && <>} + {status.get('media_attachments').size > 0 && <>} +
+ )} +
+ ); +} diff --git a/app/javascript/mastodon/features/notifications_v2/components/names_list.tsx b/app/javascript/mastodon/features/notifications_v2/components/names_list.tsx new file mode 100644 index 0000000000..9890363f74 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/names_list.tsx @@ -0,0 +1,21 @@ +import { useAppSelector } from 'mastodon/store'; +import { FormattedMessage } from 'react-intl'; +import { Link } from 'react-router-dom'; + +export const NamesList = ({ accountIds, total }) => { + const lastAccountId = accountIds[0]; + const account = useAppSelector(state => state.getIn(['accounts', lastAccountId])); + const displayedName = ; + + if (total === 1) { + return displayedName; + } + + return ( + + ); +}; diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_admin_report.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_admin_report.tsx new file mode 100644 index 0000000000..68a64c69d6 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_admin_report.tsx @@ -0,0 +1,57 @@ +import type { NotificationGroupAdminReport } from 'mastodon/models/notification_group'; +import FlagIcon from '@/material-icons/400-24px/flag-fill.svg?react'; +import { NamesList } from './names_list'; +import { Icon } from 'mastodon/components/icon'; +import { FormattedMessage, useIntl, defineMessages } from 'react-intl'; +import { useAppSelector } from 'mastodon/store'; +import { RelativeTimestamp } from 'mastodon/components/relative_timestamp'; + +// This needs to be kept in sync with app/models/report.rb +const messages = defineMessages({ + other: { id: 'report_notification.categories.other', defaultMessage: 'Other' }, + spam: { id: 'report_notification.categories.spam', defaultMessage: 'Spam' }, + legal: { id: 'report_notification.categories.legal', defaultMessage: 'Legal' }, + violation: { id: 'report_notification.categories.violation', defaultMessage: 'Rule violation' }, +}); + +export const NotificationAdminReport: React.FC<{ + notification: NotificationGroupAdminReport; +}> = ({ notification, notification: { report } }) => { + const intl = useIntl(); + const targetAccount = useAppSelector(state => state.getIn(['accounts', report.target_account.id])); + const account = useAppSelector(state => state.getIn(['accounts', notification.sampleAccountsIds[0]])); + const values = { name: , target: , category: intl.formatMessage(messages[report.category]), count: report.status_ids.length }; + + let message; + + if (report.status_ids.length > 0) { + if (report.category === 'other') { + message = ; + } else { + message = ; + } + } else { + if (report.category === 'other') { + message = ; + } else { + message = ; + } + } + + return ( + +
+ +
+
+
+ {message} + +
+
+ + {report.comment.length > 0 &&
“{report.comment}”
} +
+
+ ); +}; diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_admin_sign_up.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_admin_sign_up.tsx new file mode 100644 index 0000000000..f7f6d5fcba --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_admin_sign_up.tsx @@ -0,0 +1,20 @@ +import type { NotificationGroupAdminSignUp } from 'mastodon/models/notification_group'; +import PersonAddIcon from '@/material-icons/400-24px/person_add-fill.svg?react'; +import { FormattedMessage } from 'react-intl'; +import { NotificationGroupWithStatus } from './notification_group_with_status'; + +const labelRenderer = values => + ; + +export const NotificationAdminSignUp: React.FC<{ + notification: NotificationGroupAdminSignUp; +}> = ({ notification }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_favourite.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_favourite.tsx new file mode 100644 index 0000000000..0903fa0693 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_favourite.tsx @@ -0,0 +1,21 @@ +import type { NotificationGroupFavourite } from 'mastodon/models/notification_group'; +import StarIcon from '@/material-icons/400-24px/star-fill.svg?react'; +import { FormattedMessage } from 'react-intl'; +import { NotificationGroupWithStatus } from './notification_group_with_status'; + +const labelRenderer = values => + ; + +export const NotificationFavourite: React.FC<{ + notification: NotificationGroupFavourite; +}> = ({ notification }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_follow.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_follow.tsx new file mode 100644 index 0000000000..1b0a3f156f --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_follow.tsx @@ -0,0 +1,20 @@ +import type { NotificationGroupFollow } from 'mastodon/models/notification_group'; +import PersonAddIcon from '@/material-icons/400-24px/person_add-fill.svg?react'; +import { FormattedMessage } from 'react-intl'; +import { NotificationGroupWithStatus } from './notification_group_with_status'; + +const labelRenderer = values => + ; + +export const NotificationFollow: React.FC<{ + notification: NotificationGroupFollow; +}> = ({ notification }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_follow_request.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_follow_request.tsx new file mode 100644 index 0000000000..e7b276b84b --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_follow_request.tsx @@ -0,0 +1,20 @@ +import type { NotificationGroupFollowRequest } from 'mastodon/models/notification_group'; +import PersonAddIcon from '@/material-icons/400-24px/person_add-fill.svg?react'; +import { FormattedMessage } from 'react-intl'; +import { NotificationGroupWithStatus } from './notification_group_with_status'; + +const labelRenderer = values => + ; + +export const NotificationFollowRequest: React.FC<{ + notification: NotificationGroupFollowRequest; +}> = ({ notification }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_group.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_group.tsx index 48ea2282b0..cb3a3aded6 100644 --- a/app/javascript/mastodon/features/notifications_v2/components/notification_group.tsx +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_group.tsx @@ -1,14 +1,28 @@ import type { NotificationGroup as NotificationGroupModel } from 'mastodon/models/notification_group'; +import { useMemo } from 'react'; import { useAppSelector } from 'mastodon/store'; +import { HotKeys } from 'react-hotkeys'; + import { NotificationReblog } from './notification_reblog'; +import { NotificationFavourite } from './notification_favourite'; +import { NotificationSeveredRelationships } from './notification_severed_relationships'; +import { NotificationMention } from './notification_mention'; +import { NotificationFollow } from './notification_follow'; +import { NotificationFollowRequest } from './notification_follow_request'; +import { NotificationPoll } from './notification_poll'; +import { NotificationStatus } from './notification_status'; +import { NotificationUpdate } from './notification_update'; +import { NotificationAdminSignUp } from './notification_admin_sign_up'; +import { NotificationAdminReport } from './notification_admin_report'; +import { NotificationModerationWarning } from './notification_moderation_warning'; export const NotificationGroup: React.FC<{ notificationGroupId: NotificationGroupModel['group_key']; unread: boolean; onMoveUp: unknown; onMoveDown: unknown; -}> = ({ notificationGroupId }) => { +}> = ({ notificationGroupId, onMoveUp, onMoveDown }) => { const notificationGroup = useAppSelector((state) => state.notificationsGroups.groups.find( (item) => item.type !== 'gap' && item.group_key === notificationGroupId, @@ -17,26 +31,76 @@ export const NotificationGroup: React.FC<{ if (!notificationGroup || notificationGroup.type === 'gap') return null; + let content; + switch (notificationGroup.type) { case 'reblog': - return ; - case 'follow': - case 'follow_request': + content = ; + break; case 'favourite': - case 'mention': - case 'poll': - case 'status': - case 'update': - case 'admin.sign_up': - case 'admin.report': - case 'moderation_warning': + content = ; + break; case 'severed_relationships': + content = ; + break; + case 'mention': + content = ;; + break; + case 'follow': + content = ; + break; + case 'follow_request': + content = ; + break; + case 'poll': + content = ; + break; + case 'status': + content = ; + break; + case 'update': + content = ; + break; + case 'admin.sign_up': + content = ; + break; + case 'admin.report': + content = ; + break; + case 'moderation_warning': + content = ; + break; default: - return ( -
-
{JSON.stringify(notificationGroup, undefined, 2)}
-
-
- ); + return null; } + + const handlers = useMemo(() => ({ + moveUp: () => { + onMoveUp(notificationGroupId) + }, + + moveDown: () => { + onMoveDown(notificationGroupId) + }, + + reply: () => {}, + + favourite: () => {}, + + boost: () => {}, + + mention: () => {}, + + open: () => {}, + + openProfile: () => {}, + + toggleHidden: () => {}, + }), [notificationGroupId, onMoveUp, onMoveDown]); + + return ( + + {content} + + ); }; diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_group_with_status.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_group_with_status.tsx new file mode 100644 index 0000000000..1cbcb60de6 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_group_with_status.tsx @@ -0,0 +1,43 @@ +import { useMemo } from 'react'; +import { Icon } from 'mastodon/components/icon'; +import { AvatarGroup } from './avatar_group'; +import { RelativeTimestamp } from 'mastodon/components/relative_timestamp'; +import { NamesList } from './names_list'; +import { FormattedMessage } from 'react-intl'; +import { EmbeddedStatus } from './embedded_status'; + +export const NotificationGroupWithStatus = ({ + icon, + timestamp, + accountIds, + count, + statusId, + labelRenderer, + type, +}) => { + const label = useMemo(() => + labelRenderer({ name: }), [labelRenderer, accountIds, count]); + + return ( +
+
+ +
+
+ + +
+ {label} + +
+
+ + {statusId && ( +
+ +
+ )} +
+
+ ); +}; diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_mention.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_mention.tsx new file mode 100644 index 0000000000..31aa99872a --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_mention.tsx @@ -0,0 +1,20 @@ +import type { NotificationGroupMention } from 'mastodon/models/notification_group'; +import ReplyIcon from '@/material-icons/400-24px/reply-fill.svg?react'; +import { FormattedMessage } from 'react-intl'; +import { NotificationWithStatus } from './notification_with_status'; + +const labelRenderer = values => + ; + +export const NotificationMention: React.FC<{ + notification: NotificationGroupMention; +}> = ({ notification }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_moderation_warning.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_moderation_warning.tsx new file mode 100644 index 0000000000..7fa1070051 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_moderation_warning.tsx @@ -0,0 +1,11 @@ +import type { NotificationGroupModerationWarning } from 'mastodon/models/notification_group'; +import { ModerationWarning } from 'mastodon/features/notifications/components/moderation_warning'; + +export const NotificationModerationWarning: React.FC<{ + notification: NotificationGroupModerationWarning; +}> = ({ notification: { event } }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_poll.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_poll.tsx new file mode 100644 index 0000000000..abf4929529 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_poll.tsx @@ -0,0 +1,20 @@ +import type { NotificationGroupPoll } from 'mastodon/models/notification_group'; +import BarChart4BarsIcon from '@/material-icons/400-20px/bar_chart_4_bars.svg?react'; +import { FormattedMessage } from 'react-intl'; +import { NotificationWithStatus } from './notification_with_status'; + +const labelRenderer = values => + ; + +export const NotificationPoll: React.FC<{ + notification: NotificationGroupPoll; +}> = ({ notification }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_reblog.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_reblog.tsx index 0f06511ac1..53fb073528 100644 --- a/app/javascript/mastodon/features/notifications_v2/components/notification_reblog.tsx +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_reblog.tsx @@ -1,7 +1,21 @@ import type { NotificationGroupReblog } from 'mastodon/models/notification_group'; +import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react'; +import { FormattedMessage } from 'react-intl'; +import { NotificationGroupWithStatus } from './notification_group_with_status'; + +const labelRenderer = values => + ; export const NotificationReblog: React.FC<{ notification: NotificationGroupReblog; -}> = ({ notification }) => { - return
reblog {notification.group_key}
; -}; +}> = ({ notification }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_severed_relationships.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_severed_relationships.tsx new file mode 100644 index 0000000000..51192e707b --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_severed_relationships.tsx @@ -0,0 +1,13 @@ +import type { NotificationGroupSeveredRelationships } from 'mastodon/models/notification_group'; +import { RelationshipsSeveranceEvent } from 'mastodon/features/notifications/components/relationships_severance_event'; + +export const NotificationSeveredRelationships: React.FC<{ + notification: NotificationGroupSeveredRelationships; +}> = ({ notification: { event } }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_status.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_status.tsx new file mode 100644 index 0000000000..c097a40aad --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_status.tsx @@ -0,0 +1,20 @@ +import type { NotificationGroupStatus } from 'mastodon/models/notification_group'; +import NotificationsActiveIcon from '@/material-icons/400-24px/notifications_active-fill.svg?react'; +import { FormattedMessage } from 'react-intl'; +import { NotificationWithStatus } from './notification_with_status'; + +const labelRenderer = values => + ; + +export const NotificationStatus: React.FC<{ + notification: NotificationGroupStatus; +}> = ({ notification }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_update.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_update.tsx new file mode 100644 index 0000000000..f1d8298865 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_update.tsx @@ -0,0 +1,20 @@ +import type { NotificationGroupUpdate } from 'mastodon/models/notification_group'; +import EditIcon from '@/material-icons/400-24px/edit.svg?react'; +import { FormattedMessage } from 'react-intl'; +import { NotificationWithStatus } from './notification_with_status'; + +const labelRenderer = values => + ; + +export const NotificationUpdate: React.FC<{ + notification: NotificationGroupUpdate; +}> = ({ notification }) => ( + +); diff --git a/app/javascript/mastodon/features/notifications_v2/components/notification_with_status.tsx b/app/javascript/mastodon/features/notifications_v2/components/notification_with_status.tsx new file mode 100644 index 0000000000..2dfddf29a6 --- /dev/null +++ b/app/javascript/mastodon/features/notifications_v2/components/notification_with_status.tsx @@ -0,0 +1,31 @@ +import { useMemo } from 'react'; +import Status from 'mastodon/containers/status_container'; +import { Icon } from 'mastodon/components/icon'; +import { NamesList } from './names_list'; +import { FormattedMessage } from 'react-intl'; + +export const NotificationWithStatus = ({ + icon, + accountIds, + statusId, + count, + labelRenderer, + type, +}) => { + const label = useMemo(() => labelRenderer({ name: }), [labelRenderer, accountIds, count]); + + return ( +
+
+
+ {label} +
+ + +
+ ); +}; diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 63298d59e3..c58777580f 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -1,4 +1,5 @@ { + "a9ng3b": "{name} and {count, plural, one {# other} other {# others}}", "about.blocks": "Moderated servers", "about.contact": "Contact:", "about.disclaimer": "Mastodon is free, open-source software, and a trademark of Mastodon gGmbH.", @@ -469,6 +470,10 @@ "navigation_bar.security": "Security", "not_signed_in_indicator.not_signed_in": "You need to login to access this resource.", "notification.admin.report": "{name} reported {target}", + "notification.admin.report_account": "{name} reported {count, plural, one {one post} other {# posts}} from {target} for {category}", + "notification.admin.report_account_other": "{name} reported {count, plural, one {one post} other {# posts}} from {target}", + "notification.admin.report_statuses": "{name} reported {target} for {category}", + "notification.admin.report_statuses_other": "{name} reported {target}", "notification.admin.sign_up": "{name} signed up", "notification.favourite": "{name} favorited your post", "notification.follow": "{name} followed you", diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss index 4f36d85aa9..cd581c3a16 100644 --- a/app/javascript/styles/mastodon/components.scss +++ b/app/javascript/styles/mastodon/components.scss @@ -2180,41 +2180,28 @@ a.account__display-name { } } -.notification__relationships-severance-event, -.notification__moderation-warning { - display: flex; - gap: 16px; +.notification-group--link { color: $secondary-text-color; text-decoration: none; - align-items: flex-start; - padding: 16px 32px; - border-bottom: 1px solid var(--background-border-color); - &:hover { - color: $primary-text-color; - } - - .icon { - padding: 2px; - color: $highlight-text-color; - } - - &__content { + .notification-group__main { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; flex-grow: 1; - font-size: 16px; - line-height: 24px; + font-size: 15px; + line-height: 22px; - strong { + strong, + bdi { font-weight: 700; } .link-button { font-size: inherit; line-height: inherit; + font-weight: inherit; } } } @@ -10266,3 +10253,177 @@ noscript { } } } + +.notification-group { + display: flex; + align-items: flex-start; + gap: 8px; + padding: 16px; + border-bottom: 1px solid var(--background-border-color); + + &__icon { + width: 40px; + display: flex; + align-items: center; + justify-content: center; + flex: 0 0 auto; + color: $highlight-text-color; + + .icon { + width: 28px; + height: 28px; + } + } + + &--favourite &__icon { + color: $gold-star;; + } + + &--reblog &__icon { + color: $valid-value-color; + } + + &--relationships-severance-event &__icon, + &--admin-report &__icon, + &--admin-sign-up &__icon { + color: $dark-text-color; + } + + &--moderation-warning &__icon { + color: $red-bookmark; + } + + &__main { + display: flex; + flex-direction: column; + gap: 8px; + flex: 1 1 auto; + + &__header { + display: flex; + flex-direction: column; + gap: 8px; + + &__label { + display: flex; + gap: 8px; + font-size: 15px; + line-height: 22px; + color: $darker-text-color; + + a { + color: inherit; + text-decoration: none; + } + + bdi { + font-weight: 700; + color: $primary-text-color; + } + + time { + color: $dark-text-color; + } + } + } + + &__status { + border: 1px solid var(--background-border-color); + border-radius: 8px; + padding: 8px; + } + } + + &__avatar-group { + display: flex; + gap: 8px; + } + + .status { + padding: 0; + border: 0; + } + + &__embedded-status { + &__account { + display: flex; + align-items: center; + gap: 4px; + margin-bottom: 8px; + color: $dark-text-color; + + bdi { + color: inherit; + } + } + + .account__avatar { + opacity: 0.5; + } + + &__content { + font-size: 15px; + line-height: 22px; + color: $dark-text-color; + + p, + a { + color: inherit; + } + } + } +} + +.notification-ungrouped { + padding: 16px; + border-bottom: 1px solid var(--background-border-color); + + &__header { + display: flex; + align-items: center; + gap: 8px; + color: $dark-text-color; + font-size: 15px; + line-height: 22px; + font-weight: 500; + padding-inline-start: 24px; + margin-bottom: 16px; + + &__icon { + display: flex; + align-items: center; + justify-content: center; + flex: 0 0 auto; + + .icon { + width: 16px; + height: 16px; + } + } + + a { + color: inherit; + text-decoration: none; + } + } + + .status { + border: 0; + padding: 0; + + &__avatar { + width: 40px; + height: 40px; + + .account__avatar { + width: 40px !important; + height: 40px !important; + } + } + } + + .notification__report { + border: 0; + padding: 0; + } +}