Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 68 additions & 64 deletions app/soapbox/features/notifications/components/filter_bar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useCallback, useMemo } from 'react';
import { defineMessages, useIntl } from 'react-intl';

import { openModal } from 'soapbox/actions/modals';
Expand All @@ -7,9 +7,10 @@ import Icon from 'soapbox/components/icon';
import { Tabs } from 'soapbox/components/ui';
import { useAppDispatch, useFeatures, useSettings } from 'soapbox/hooks';

import type { Item } from 'soapbox/components/ui/tabs/tabs';
import ClearColumnButton from './clear_column_button';

import type { Item } from 'soapbox/components/ui/tabs/tabs';

const messages = defineMessages({
all: { id: 'notifications.filter.all', defaultMessage: 'All' },
mentions: { id: 'notifications.filter.mentions', defaultMessage: 'Mentions' },
Expand All @@ -34,77 +35,80 @@ const NotificationFilterBar = () => {
const selectedFilter = settings.getIn(['notifications', 'quickFilter', 'active']) as string;
const advancedMode = settings.getIn(['notifications', 'quickFilter', 'advanced']);

const onClick = (notificationType: string) => () => dispatch(setFilter(notificationType));
const onClick = useCallback((notificationType: string) => () => dispatch(setFilter(notificationType)), [dispatch]);

const onClear = React.useCallback(() => {
const onClear = useCallback(() => {
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/eraser.svg'),
heading: intl.formatMessage(messages.clearHeading),
message: intl.formatMessage(messages.clearMessage),
confirm: intl.formatMessage(messages.clearConfirm),
onConfirm: () => dispatch(clearNotifications()),
}));
}, [dispatch, openModal, clearNotifications]);

}, [dispatch, intl]);

const items: Item[] = useMemo(() => {
const result: Item[] = [
{
text: intl.formatMessage(messages.all),
action: onClick('all'),
name: 'all',
},
];

const items: Item[] = [
{
text: intl.formatMessage(messages.all),
action: onClick('all'),
name: 'all',
},
];
if (!advancedMode) {
result.push({
text: intl.formatMessage(messages.mentions),
action: onClick('mention'),
name: 'mention',
});
} else {
result.push({
text: <Icon src={require('@tabler/icons/at.svg')} />,
title: intl.formatMessage(messages.mentions),
action: onClick('mention'),
name: 'mention',
});
result.push({
text: <Icon src={require('@tabler/icons/heart.svg')} />,
title: intl.formatMessage(messages.favourites),
action: onClick('favourite'),
name: 'favourite',
});
if (features.emojiReacts) result.push({
text: <Icon src={require('@tabler/icons/mood-smile.svg')} />,
title: intl.formatMessage(messages.emoji_reacts),
action: onClick('pleroma:emoji_reaction'),
name: 'pleroma:emoji_reaction',
});
result.push({
text: <Icon src={require('@tabler/icons/repeat.svg')} />,
title: intl.formatMessage(messages.boosts),
action: onClick('reblog'),
name: 'reblog',
});
result.push({
text: <Icon src={require('@tabler/icons/chart-bar.svg')} />,
title: intl.formatMessage(messages.polls),
action: onClick('poll'),
name: 'poll',
});
result.push({
text: <Icon src={require('@tabler/icons/bell-ringing.svg')} />,
title: intl.formatMessage(messages.statuses),
action: onClick('status'),
name: 'status',
});
result.push({
text: <Icon src={require('@tabler/icons/user-plus.svg')} />,
title: intl.formatMessage(messages.follows),
action: onClick('follow'),
name: 'follow',
});
}

if (!advancedMode) {
items.push({
text: intl.formatMessage(messages.mentions),
action: onClick('mention'),
name: 'mention',
});
} else {
items.push({
text: <Icon src={require('@tabler/icons/at.svg')} />,
title: intl.formatMessage(messages.mentions),
action: onClick('mention'),
name: 'mention',
});
items.push({
text: <Icon src={require('@tabler/icons/heart.svg')} />,
title: intl.formatMessage(messages.favourites),
action: onClick('favourite'),
name: 'favourite',
});
if (features.emojiReacts) items.push({
text: <Icon src={require('@tabler/icons/mood-smile.svg')} />,
title: intl.formatMessage(messages.emoji_reacts),
action: onClick('pleroma:emoji_reaction'),
name: 'pleroma:emoji_reaction',
});
items.push({
text: <Icon src={require('@tabler/icons/repeat.svg')} />,
title: intl.formatMessage(messages.boosts),
action: onClick('reblog'),
name: 'reblog',
});
items.push({
text: <Icon src={require('@tabler/icons/chart-bar.svg')} />,
title: intl.formatMessage(messages.polls),
action: onClick('poll'),
name: 'poll',
});
items.push({
text: <Icon src={require('@tabler/icons/bell-ringing.svg')} />,
title: intl.formatMessage(messages.statuses),
action: onClick('status'),
name: 'status',
});
items.push({
text: <Icon src={require('@tabler/icons/user-plus.svg')} />,
title: intl.formatMessage(messages.follows),
action: onClick('follow'),
name: 'follow',
});
}
return result;
}, [advancedMode, features.emojiReacts, intl, onClick]);

return (
<>
Expand All @@ -117,4 +121,4 @@ const NotificationFilterBar = () => {
);
};

export default NotificationFilterBar;
export default React.memo(NotificationFilterBar);
60 changes: 30 additions & 30 deletions app/soapbox/features/notifications/components/notification.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useCallback } from 'react';
import React, { useCallback, useMemo } from 'react';
import { HotKeys } from 'react-hotkeys';
import { defineMessages, useIntl, FormattedMessage, IntlShape, MessageDescriptor } from 'react-intl';
import { useHistory } from 'react-router-dom';
Expand Down Expand Up @@ -163,39 +163,27 @@ const Notification: React.FC<INotificaton> = (props) => {
const type = notification.type;
const { account, status } = notification;

const getHandlers = () => ({
reply: handleMention,
favourite: handleHotkeyFavourite,
boost: handleHotkeyBoost,
mention: handleMention,
open: handleOpen,
openProfile: handleOpenProfile,
moveUp: handleMoveUp,
moveDown: handleMoveDown,
toggleHidden: handleHotkeyToggleHidden,
});
const handleOpenProfile = useCallback(() => {
if (account && typeof account === 'object') {
history.push(`/@${account.acct}`);
}
}, [account, history]);

const handleOpen = () => {
const handleOpen = useCallback(() => {
if (status && typeof status === 'object' && account && typeof account === 'object') {
history.push(`/@${account.acct}/posts/${status.id}`);
} else {
handleOpenProfile();
}
};

const handleOpenProfile = () => {
if (account && typeof account === 'object') {
history.push(`/@${account.acct}`);
}
};
}, [status, account, history, handleOpenProfile]);

const handleMention = useCallback((e?: KeyboardEvent) => {
e?.preventDefault();

if (account && typeof account === 'object') {
dispatch(mentionCompose(account));
}
}, [account]);
}, [account, dispatch]);

const handleHotkeyFavourite = useCallback((e?: KeyboardEvent) => {
if (status && typeof status === 'object') {
Expand All @@ -205,7 +193,7 @@ const Notification: React.FC<INotificaton> = (props) => {
dispatch(favourite(status));
}
}
}, [status]);
}, [dispatch, status]);

const handleHotkeyBoost = useCallback((e?: KeyboardEvent) => {
if (status && typeof status === 'object') {
Expand All @@ -224,7 +212,7 @@ const Notification: React.FC<INotificaton> = (props) => {
}
});
}
}, [status]);
}, [dispatch, status]);

const handleHotkeyToggleHidden = useCallback((e?: KeyboardEvent) => {
if (status && typeof status === 'object') {
Expand All @@ -234,19 +222,19 @@ const Notification: React.FC<INotificaton> = (props) => {
dispatch(hideStatus(status.id));
}
}
}, [status]);
}, [dispatch, status]);

const handleMoveUp = () => {
const handleMoveUp = useCallback(() => {
if (onMoveUp) {
onMoveUp(notification.id);
}
};
}, [onMoveUp, notification.id]);

const handleMoveDown = () => {
const handleMoveDown = useCallback(() => {
if (onMoveDown) {
onMoveDown(notification.id);
}
};
}, [onMoveDown, notification.id]);

const renderIcon = (): React.ReactNode => {
if (type === 'pleroma:emoji_reaction' && notification.emoji) {
Expand Down Expand Up @@ -332,8 +320,20 @@ const Notification: React.FC<INotificaton> = (props) => {
)
) : '';

const handlers = useMemo(() => ({
reply: handleMention,
favourite: handleHotkeyFavourite,
boost: handleHotkeyBoost,
mention: handleMention,
open: handleOpen,
openProfile: handleOpenProfile,
moveUp: handleMoveUp,
moveDown: handleMoveDown,
toggleHidden: handleHotkeyToggleHidden,
}), [handleMention, handleHotkeyFavourite, handleHotkeyBoost, handleOpen, handleOpenProfile, handleMoveUp, handleMoveDown, handleHotkeyToggleHidden]);

return (
<HotKeys handlers={getHandlers()} data-testid='notification'>
<HotKeys handlers={handlers} data-testid='notification'>
<div
className='notification focusable'
tabIndex={0}
Expand Down Expand Up @@ -366,4 +366,4 @@ const Notification: React.FC<INotificaton> = (props) => {
);
};

export default Notification;
export default React.memo(Notification);
Loading