Merge pull request #801 from kmycode/upstream-20240817
Upstream 20240817
This commit is contained in:
commit
fef0b7e28b
97 changed files with 1377 additions and 472 deletions
|
@ -51,14 +51,18 @@ class ColumnSettings extends PureComponent {
|
|||
|
||||
return (
|
||||
<div className='column-settings'>
|
||||
{alertsEnabled && browserSupport && browserPermission === 'denied' && (
|
||||
<span className='warning-hint'><FormattedMessage id='notifications.permission_denied' defaultMessage='Desktop notifications are unavailable due to previously denied browser permissions request' /></span>
|
||||
)}
|
||||
|
||||
<section>
|
||||
<ClearColumnButton onClick={onClear} />
|
||||
</section>
|
||||
|
||||
{alertsEnabled && browserSupport && browserPermission === 'denied' && (
|
||||
<section>
|
||||
<span className='warning-hint'>
|
||||
<FormattedMessage id='notifications.permission_denied' defaultMessage='Desktop notifications are unavailable due to previously denied browser permissions request' />
|
||||
</span>
|
||||
</section>
|
||||
)}
|
||||
|
||||
{alertsEnabled && browserSupport && browserPermission === 'default' && (
|
||||
<section>
|
||||
<span className='warning-hint'>
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import PersonAddIcon from '@/material-icons/400-24px/person_add-fill.svg?react';
|
||||
import { FollowersCounter } from 'mastodon/components/counters';
|
||||
import { FollowButton } from 'mastodon/components/follow_button';
|
||||
import { ShortNumber } from 'mastodon/components/short_number';
|
||||
import type { NotificationGroupFollow } from 'mastodon/models/notification_group';
|
||||
import { useAppSelector } from 'mastodon/store';
|
||||
|
||||
import type { LabelRenderer } from './notification_group_with_status';
|
||||
import { NotificationGroupWithStatus } from './notification_group_with_status';
|
||||
|
@ -14,18 +18,45 @@ const labelRenderer: LabelRenderer = (values) => (
|
|||
/>
|
||||
);
|
||||
|
||||
const FollowerCount: React.FC<{ accountId: string }> = ({ accountId }) => {
|
||||
const account = useAppSelector((s) => s.accounts.get(accountId));
|
||||
|
||||
if (!account) return null;
|
||||
|
||||
return (
|
||||
<ShortNumber value={account.followers_count} renderer={FollowersCounter} />
|
||||
);
|
||||
};
|
||||
|
||||
export const NotificationFollow: React.FC<{
|
||||
notification: NotificationGroupFollow;
|
||||
unread: boolean;
|
||||
}> = ({ notification, unread }) => (
|
||||
<NotificationGroupWithStatus
|
||||
type='follow'
|
||||
icon={PersonAddIcon}
|
||||
iconId='person-add'
|
||||
accountIds={notification.sampleAccountIds}
|
||||
timestamp={notification.latest_page_notification_at}
|
||||
count={notification.notifications_count}
|
||||
labelRenderer={labelRenderer}
|
||||
unread={unread}
|
||||
/>
|
||||
);
|
||||
}> = ({ notification, unread }) => {
|
||||
let actions: JSX.Element | undefined;
|
||||
let additionalContent: JSX.Element | undefined;
|
||||
|
||||
if (notification.sampleAccountIds.length === 1) {
|
||||
// only display those if the group contains 1 account, otherwise it does not makes sense
|
||||
const account = notification.sampleAccountIds[0];
|
||||
|
||||
if (account) {
|
||||
actions = <FollowButton accountId={notification.sampleAccountIds[0]} />;
|
||||
additionalContent = <FollowerCount accountId={account} />;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<NotificationGroupWithStatus
|
||||
type='follow'
|
||||
icon={PersonAddIcon}
|
||||
iconId='person-add'
|
||||
accountIds={notification.sampleAccountIds}
|
||||
timestamp={notification.latest_page_notification_at}
|
||||
count={notification.notifications_count}
|
||||
labelRenderer={labelRenderer}
|
||||
unread={unread}
|
||||
actions={actions}
|
||||
additionalContent={additionalContent}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -46,7 +46,7 @@ export const NotificationFollowRequest: React.FC<{
|
|||
}, [dispatch, notification.sampleAccountIds]);
|
||||
|
||||
const actions = (
|
||||
<div className='notification-group__actions'>
|
||||
<>
|
||||
<IconButton
|
||||
title={intl.formatMessage(messages.reject)}
|
||||
icon='times'
|
||||
|
@ -59,7 +59,7 @@ export const NotificationFollowRequest: React.FC<{
|
|||
iconComponent={CheckIcon}
|
||||
onClick={onAuthorize}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -34,6 +34,7 @@ export const NotificationGroupWithStatus: React.FC<{
|
|||
labelSeeMoreHref?: string;
|
||||
type: string;
|
||||
unread: boolean;
|
||||
additionalContent?: JSX.Element;
|
||||
}> = ({
|
||||
icon,
|
||||
iconId,
|
||||
|
@ -47,6 +48,7 @@ export const NotificationGroupWithStatus: React.FC<{
|
|||
labelSeeMoreHref,
|
||||
type,
|
||||
unread,
|
||||
additionalContent,
|
||||
}) => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
|
@ -103,7 +105,9 @@ export const NotificationGroupWithStatus: React.FC<{
|
|||
/>
|
||||
<AvatarGroup accountIds={group.sampleAccountIds} />
|
||||
|
||||
{actions}
|
||||
{actions && (
|
||||
<div className='notification-group__actions'>{actions}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
@ -112,7 +116,9 @@ export const NotificationGroupWithStatus: React.FC<{
|
|||
<div className='notification-group__main__header__wrapper'>
|
||||
<AvatarGroup accountIds={accountIds} />
|
||||
|
||||
{actions}
|
||||
{actions && (
|
||||
<div className='notification-group__actions'>{actions}</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
@ -127,6 +133,12 @@ export const NotificationGroupWithStatus: React.FC<{
|
|||
<EmbeddedStatus statusId={statusId} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{additionalContent && (
|
||||
<div className='notification-group__main__additional-content'>
|
||||
{additionalContent}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</HotKeys>
|
||||
|
|
|
@ -37,7 +37,11 @@ export const NotificationMention: React.FC<{
|
|||
unread: boolean;
|
||||
}> = ({ notification, unread }) => {
|
||||
const [isDirect, isReply] = useAppSelector((state) => {
|
||||
const status = state.statuses.get(notification.statusId) as Status;
|
||||
const status = state.statuses.get(notification.statusId) as
|
||||
| Status
|
||||
| undefined;
|
||||
|
||||
if (!status) return [false, false] as const;
|
||||
|
||||
return [
|
||||
status.get('visibility') === 'direct',
|
||||
|
|
|
@ -23,7 +23,7 @@ export const NotificationWithStatus: React.FC<{
|
|||
icon: IconProp;
|
||||
iconId: string;
|
||||
accountIds: string[];
|
||||
statusId: string;
|
||||
statusId: string | undefined;
|
||||
count: number;
|
||||
labelRenderer: LabelRenderer;
|
||||
unread: boolean;
|
||||
|
@ -78,6 +78,8 @@ export const NotificationWithStatus: React.FC<{
|
|||
[dispatch, statusId],
|
||||
);
|
||||
|
||||
if (!statusId) return null;
|
||||
|
||||
return (
|
||||
<HotKeys handlers={handlers}>
|
||||
<div
|
||||
|
|
|
@ -705,7 +705,7 @@ class Status extends ImmutablePureComponent {
|
|||
const isIndexable = !status.getIn(['account', 'noindex']);
|
||||
|
||||
if (!isLocal) {
|
||||
remoteHint = <TimelineHint url={status.get('url')} resource={<FormattedMessage id='timeline_hint.resources.replies' defaultMessage='Some replies' />} />;
|
||||
remoteHint = <TimelineHint className={classNames(!!descendants && 'timeline-hint--with-descendants')} url={status.get('url')} resource={<FormattedMessage id='timeline_hint.resources.replies' defaultMessage='Some replies' />} />;
|
||||
}
|
||||
|
||||
const handlers = {
|
||||
|
|
|
@ -25,7 +25,7 @@ export const ConfirmLogOutModal: React.FC<BaseConfirmationModalProps> = ({
|
|||
const intl = useIntl();
|
||||
|
||||
const onConfirm = useCallback(() => {
|
||||
logOut();
|
||||
void logOut();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue