diff --git a/src/app.css b/src/app.css index 8361df31..4adcee34 100644 --- a/src/app.css +++ b/src/app.css @@ -1099,7 +1099,7 @@ button.carousel-dot { font-weight: bold; color: var(--text-color); background-color: var(--bg-faded-blur-color); - border: var(--hairline-width) solid var(--outline-color); + border: 1px solid var(--outline-color); box-shadow: 0 4px 32px var(--drop-shadow-color); transition: all 0.2s ease-out; } diff --git a/src/app.jsx b/src/app.jsx index 0f491e94..3cdbbdf0 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -58,7 +58,7 @@ import { import { getAccessToken } from './utils/auth'; import openCompose from './utils/open-compose'; import showToast from './utils/show-toast'; -import states, { getStatus, saveStatus } from './utils/states'; +import states, { initStates, saveStatus } from './utils/states'; import store from './utils/store'; import { getCurrentAccount } from './utils/store-utils'; import useInterval from './utils/useInterval'; @@ -111,7 +111,7 @@ function App() { if (code) { console.log({ code }); // Clear the code from the URL - window.history.replaceState({}, document.title, '/'); + window.history.replaceState({}, document.title, location.pathname || '/'); const clientID = store.session.get('clientID'); const clientSecret = store.session.get('clientSecret'); @@ -130,6 +130,7 @@ function App() { initInstance(masto, instanceURL), initAccount(masto, instanceURL, accessToken), ]); + initStates(); initPreferences(masto); setIsLoggedIn(true); @@ -389,7 +390,7 @@ function App() { { + onClose={({ destination } = {}) => { states.showAccount = false; if (destination) { states.showAccounts = false; diff --git a/src/components/menu-confirm.jsx b/src/components/menu-confirm.jsx index 14e67746..40cd146b 100644 --- a/src/components/menu-confirm.jsx +++ b/src/components/menu-confirm.jsx @@ -1,5 +1,6 @@ import { Menu, MenuItem, SubMenu } from '@szhsin/react-menu'; import { cloneElement } from 'preact'; +import { useRef } from 'preact/hooks'; function MenuConfirm({ subMenu = false, @@ -20,8 +21,10 @@ function MenuConfirm({ return children; } const Parent = subMenu ? SubMenu : Menu; + const menuRef = useRef(); return ( { + if (e.pointerType === 'touch') { + menuRef.current?.openMenu?.(); + } + }, + onPointerLeave: (e) => { + if (e.pointerType === 'touch') { + menuRef.current?.openMenu?.(); + } + }, + }} > {confirmLabel} diff --git a/src/components/notification.jsx b/src/components/notification.jsx index 20a101ab..b7a50523 100644 --- a/src/components/notification.jsx +++ b/src/components/notification.jsx @@ -39,21 +39,25 @@ const contentText = { mention: 'mentioned you in their post.', status: 'published a post.', reblog: 'boosted your post.', + 'reblog+account': (count) => `boosted ${count} of your posts.`, reblog_reply: 'boosted your reply.', follow: 'followed you.', follow_request: 'requested to follow you.', favourite: 'favourited your post.', + 'favourite+account': (count) => `favourited ${count} of your posts.`, favourite_reply: 'favourited your reply.', poll: 'A poll you have voted in or created has ended.', 'poll-self': 'A poll you have created has ended.', 'poll-voted': 'A poll you have voted in has ended.', update: 'A post you interacted with has been edited.', 'favourite+reblog': 'boosted & favourited your post.', + 'favourite+reblog+account': (count) => + `boosted & favourited ${count} of your posts.`, 'favourite+reblog_reply': 'boosted & favourited your reply.', }; function Notification({ notification, instance, reload }) { - const { id, status, account, _accounts } = notification; + const { id, status, account, _accounts, _statuses } = notification; let { type } = notification; // status = Attached when type of the notification is favourite, reblog, status, mention, poll, or update @@ -90,12 +94,19 @@ function Notification({ notification, instance, reload }) { type === 'favourite' || type === 'favourite+reblog' ) { - text = - contentText[isReplyToOthers ? `${type}_reply` : type] || - contentText[type]; + if (_statuses?.length > 1) { + text = contentText[`${type}+account`]; + } else if (isReplyToOthers) { + text = contentText[`${type}_reply`]; + } else { + text = contentText[type]; + } } else { text = contentText[type]; } + if (typeof text === 'function') { + text = text(_statuses?.length || _accounts?.length); + } if (type === 'mention' && !status) { // Could be deleted @@ -206,7 +217,23 @@ function Notification({ notification, instance, reload }) { ))}

)} - {status && ( + {_statuses?.length > 1 && ( +
    + {_statuses.map((status) => ( +
  • + + + +
  • + ))} +
+ )} + {status && (!_statuses?.length || _statuses?.length <= 1) && ( * { pointer-events: none; } -.status-card :is(.content, .poll, .media-container) { +.status-card:not(.status-carousel .status) + :is(.content, .poll, .media-container) { max-height: 160px !important; overflow: hidden; } -.status.small .status-card :is(.content, .poll, .media-container) { +.status.small:not(.status-carousel .status) + .status-card + :is(.content, .poll, .media-container) { max-height: 80px !important; } .status-card :is(.content, .poll) { diff --git a/src/components/status.jsx b/src/components/status.jsx index 21c3877d..d47b7418 100644 --- a/src/components/status.jsx +++ b/src/components/status.jsx @@ -1170,9 +1170,7 @@ function Status({ (option) => `- ${option.title}${ option.votesCount >= 0 - ? ` (${option.votesCount} vote${ - option.votesCount !== 1 ? 's' : '' - })` + ? ` (${option.votesCount})` : '' }`, ) @@ -1436,6 +1434,7 @@ function Card({ card, instance }) { url, type, embedUrl, + language, } = card; /* type @@ -1499,6 +1498,7 @@ function Card({ card, instance }) { target={cardStatusURL ? null : '_blank'} rel="nofollow noopener noreferrer" class={`card link ${blurhashImage ? '' : size}`} + lang={language} >

diff --git a/src/pages/accounts.jsx b/src/pages/accounts.jsx index c7910b5a..47d90b01 100644 --- a/src/pages/accounts.jsx +++ b/src/pages/accounts.jsx @@ -143,7 +143,7 @@ function Accounts({ onClose }) { accounts.splice(i, 1); store.local.setJSON('accounts', accounts); // location.reload(); - location.href = '/'; + location.href = location.pathname || '/'; }} > diff --git a/src/pages/notifications.css b/src/pages/notifications.css index b986018a..9eb28951 100644 --- a/src/pages/notifications.css +++ b/src/pages/notifications.css @@ -92,6 +92,7 @@ filter: saturate(0.25); } .notification .status-link:not(.status-type-mention) > .status { + font-size: calc(var(--text-size) * 0.9); max-height: 160px; overflow: hidden; /* fade out mask gradient bottom */ @@ -134,6 +135,38 @@ margin-bottom: 8px; } +.notification-group-statuses { + margin: 0; + padding: 0; + list-style: none; +} +.notification-group-statuses > li { + margin: 0; + padding: 0; + list-style: none; + position: relative; + counter-increment: index; +} +.notification-group-statuses > li:before { + content: counter(index); + position: absolute; + left: 0; + font-size: 10px; + padding: 8px; + font-weight: bold; +} +.notification-group-statuses > li + li { + margin-top: -1px; +} +.notification-group-statuses > li:not(:last-child) .status-link { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} +.notification-group-statuses > li:not(:first-child) .status-link { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + #mentions-option { float: right; margin-top: 0.5em; diff --git a/src/pages/status.jsx b/src/pages/status.jsx index 8afa7050..44babe8e 100644 --- a/src/pages/status.jsx +++ b/src/pages/status.jsx @@ -336,6 +336,7 @@ function StatusThread({ id, closeLink = '/', instance: propInstance }) { ancestor: true, isThread: ancestorsIsThread, accountID: s.account.id, + account: s.account, repliesCount: s.repliesCount, weight: calcStatusWeight(s), })), @@ -705,6 +706,7 @@ function StatusThread({ id, closeLink = '/', instance: propInstance }) { block: 'start', }); }} + title="Go to main post" >