diff --git a/src/app.css b/src/app.css index 5a5e10b9..77c03e4c 100644 --- a/src/app.css +++ b/src/app.css @@ -747,6 +747,7 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) { margin-top: 16px; transform: translate(-50%, 0); font-size: 90%; + pointer-events: auto; } .updates-button .icon { vertical-align: top; @@ -1257,13 +1258,13 @@ meter.donut:is(.danger, .explode):after { } /* I'm just feeling bored, so having fun here */ @media (hover: hover) { - .avatars-stack > * { + .avatars-stack > * img { transition: transform 0.3s ease-in-out; } - .avatars-stack:hover > *:nth-of-type(odd) { + .avatars-stack:hover > *:nth-of-type(odd) img { transform: rotate(15deg); } - .avatars-stack:hover > *:nth-of-type(even) { + .avatars-stack:hover > *:nth-of-type(even) img { transform: rotate(-15deg); } } diff --git a/src/pages/notifications.css b/src/pages/notifications.css index b4a415b7..2a33c215 100644 --- a/src/pages/notifications.css +++ b/src/pages/notifications.css @@ -20,6 +20,7 @@ flex-shrink: 0; opacity: 0.75; color: var(--text-insignificant-color); + line-height: 0; } .notification-type.notification-mention { color: var(--reply-to-color); @@ -34,6 +35,54 @@ color: var(--link-color); } +.notification .reblog-icon { + color: var(--reblog-color); +} +.notification .favourite-icon { + color: var(--favourite-color); +} + +.notification .account-avatar-stack { + position: relative; + text-align: center; +} +.notification .account-avatar-stack .account-sub-icons { + display: block; + width: fit-content; + margin: -0.25em auto 0; + line-height: 1; + background-color: var(--bg-blur-color); + /* background-image: linear-gradient( + to bottom, + var(--bg-color), + var(--bg-blur-color) + ); */ + backdrop-filter: blur(16px) saturate(3); + padding: 2px 4px; + border-radius: 999px; + overflow: hidden; + border: var(--hairline-width) solid var(--bg-color); + box-shadow: 0 1px var(--drop-shadow-color); +} +.notification .avatars-stack .account-avatar-stack .account-sub-icons .icon { + transition: transform 0.2s ease-out; +} +.notification + .avatars-stack:hover + .account-avatar-stack + .account-sub-icons + .icon { + transform: rotate(-15deg); +} +.notification + .avatars-stack:hover + .account-avatar-stack + .account-sub-icons + .icon + + .icon { + transform: rotate(15deg); +} + .notification .status-link { border-radius: 8px; border: 1px solid var(--outline-color); diff --git a/src/pages/notifications.jsx b/src/pages/notifications.jsx index cd471cfc..58c19ad6 100644 --- a/src/pages/notifications.jsx +++ b/src/pages/notifications.jsx @@ -45,6 +45,18 @@ const contentText = { 'poll-self': 'A poll you have created has ended.', 'poll-voted': 'A poll you have voted in has ended.', update: 'A status you interacted with has been edited.', + 'favourite+reblog': 'boosted & favourited your status.', +}; + +const NOTIFICATION_ICONS = { + mention: 'comment', + status: 'notification', + reblog: 'rocket', + follow: 'follow', + follow_request: 'follow-add', + favourite: 'heart', + poll: 'poll', + update: 'pencil', }; const LIMIT = 30; // 30 is the maximum limit :( @@ -275,7 +287,8 @@ function Notifications() { ); } function Notification({ notification, instance }) { - const { id, type, status, account, _accounts } = notification; + const { id, status, account, _accounts } = notification; + let { type } = notification; // status = Attached when type of the notification is favourite, reblog, status, mention, poll, or update const actualStatusID = status?.reblog?.id || status?.id; @@ -284,6 +297,20 @@ function Notification({ notification, instance }) { const isSelf = currentAccount === account?.id; const isVoted = status?.poll?.voted; + let favsCount = 0; + let reblogsCount = 0; + if (type === 'favourite+reblog') { + for (const account of _accounts) { + if (account._types?.includes('favourite')) { + favsCount++; + } else if (account._types?.includes('reblog')) { + reblogsCount++; + } + } + if (!reblogsCount && favsCount) type = 'favourite'; + if (!favsCount && reblogsCount) type = 'reblog'; + } + const text = type === 'poll' ? contentText[isSelf ? 'poll-self' : isVoted ? 'poll-voted' : 'poll'] @@ -295,22 +322,18 @@ function Notification({ notification, instance }) { class={`notification-type notification-${type}`} title={new Date(notification.createdAt).toLocaleString()} > - + {type === 'favourite+reblog' ? ( + <> + + + + ) : ( + + )}
{type !== 'mention' && ( @@ -358,6 +381,7 @@ function Notification({ notification, instance }) { {' '} ))} @@ -458,15 +493,30 @@ function groupNotifications(notifications) { const notification = notifications[i]; const { status, account, type, createdAt } = notification; const date = new Date(createdAt).toLocaleDateString(); - const key = `${status?.id}-${type}-${date}`; + let virtualType = type; + if (type === 'favourite' || type === 'reblog') { + virtualType = 'favourite+reblog'; + } + const key = `${status?.id}-${virtualType}-${date}`; const mappedNotification = notificationsMap[key]; - if (type === 'follow_request') { + if (virtualType === 'follow_request') { cleanNotifications[j++] = notification; } else if (mappedNotification?.account) { - mappedNotification._accounts.push(account); + const mappedAccount = mappedNotification._accounts.find( + (a) => a.id === account.id, + ); + if (mappedAccount) { + mappedAccount._types.push(type); + mappedAccount._types.sort().reverse(); + } else { + account._types = [type]; + mappedNotification._accounts.push(account); + } } else { + account._types = [type]; let n = (notificationsMap[key] = { ...notification, + type: virtualType, _accounts: [account], }); cleanNotifications[j++] = n;