in desktop/flipper-ui-core/src/NotificationsHub.tsx [214:427]
category ? () => this.onHideCategory(category) : undefined
}
selectPlugin={this.props.selectPlugin}
logger={this.props.logger}
/>
);
})
.reverse();
const invalidatedNotifications = this.props.invalidatedNotifications
.filter(this.getFilter())
.map((n: PluginNotification) => (
<NotificationItem
key={n.notification.id}
{...n}
plugin={this.getPlugin(n.pluginId)}
onClear={this.props.onClear}
inactive
/>
))
.reverse();
return (
<ContextMenu items={this.contextMenuItems} component={Content}>
{activeNotifications.length > 0 && (
<Fragment>
<Heading>Active notifications</Heading>
<FlexColumn shrink={false}>{activeNotifications}</FlexColumn>
</Fragment>
)}
{invalidatedNotifications.length > 0 && (
<Fragment>
<Heading>Past notifications</Heading>
<FlexColumn shrink={false}>{invalidatedNotifications}</FlexColumn>
</Fragment>
)}
{activeNotifications.length + invalidatedNotifications.length === 0 && (
<NoContent>
<Glyph
name="bell-null"
size={24}
variant="outline"
color={colors.light30}
/>
No Notifications
</NoContent>
)}
</ContextMenu>
);
}
}
export const ConnectedNotificationsTable = connect<
StateFromProps,
DispatchFromProps,
OwnProps,
StoreState
>(
({
notifications: {
activeNotifications,
invalidatedNotifications,
blocklistedPlugins,
blocklistedCategories,
},
plugins: {devicePlugins, clientPlugins},
}) => ({
activeNotifications,
invalidatedNotifications,
blocklistedPlugins,
blocklistedCategories,
devicePlugins,
clientPlugins,
}),
{
updatePluginBlocklist,
updateCategoryBlocklist,
selectPlugin,
},
)(Searchable(NotificationsTable));
const shadow = (
props: {isSelected?: boolean; inactive?: boolean},
_hover?: boolean,
) => {
if (props.inactive) {
return `inset 0 0 0 1px ${colors.light10}`;
}
const shadow = ['1px 1px 5px rgba(0,0,0,0.1)'];
if (props.isSelected) {
shadow.push(`inset 0 0 0 2px ${colors.macOSTitleBarIconSelected}`);
}
return shadow.join(',');
};
const SEVERITY_COLOR_MAP = {
warning: colors.yellow,
error: colors.red,
};
type NotificationBoxProps = {
inactive?: boolean;
isSelected?: boolean;
severity: keyof typeof SEVERITY_COLOR_MAP;
};
const NotificationBox = styled(FlexRow)<NotificationBoxProps>((props) => ({
backgroundColor: props.inactive ? 'transparent' : colors.white,
opacity: props.inactive ? 0.5 : 1,
alignItems: 'flex-start',
borderRadius: 5,
padding: 10,
flexShrink: 0,
overflow: 'hidden',
position: 'relative',
marginBottom: 10,
boxShadow: shadow(props),
'::before': {
content: '""',
display: !props.inactive && !props.isSelected ? 'block' : 'none',
position: 'absolute',
left: 0,
top: 0,
bottom: 0,
width: 3,
backgroundColor: SEVERITY_COLOR_MAP[props.severity] || colors.info,
},
':hover': {
boxShadow: shadow(props, true),
'& > *': {
opacity: 1,
},
},
}));
const Title = styled.div({
minWidth: 150,
color: colors.light80,
flexShrink: 0,
marginBottom: 6,
fontWeight: 500,
lineHeight: 1,
fontSize: '1.1em',
});
const NotificationContent = styled(FlexColumn)<{isSelected?: boolean}>(
(props) => ({
marginLeft: 6,
marginRight: 10,
flexGrow: 1,
overflow: 'hidden',
maxHeight: props.isSelected ? 'none' : 56,
lineHeight: 1.4,
color: props.isSelected ? colors.light50 : colors.light30,
userSelect: 'text',
}),
);
const Actions = styled(FlexRow)({
alignItems: 'center',
justifyContent: 'space-between',
color: colors.light20,
marginTop: 12,
borderTop: `1px solid ${colors.light05}`,
paddingTop: 8,
});
const NotificationButton = styled.div({
border: `1px solid ${colors.light20}`,
color: colors.light50,
borderRadius: 4,
textAlign: 'center',
padding: 4,
width: 80,
marginBottom: 4,
opacity: 0,
transition: '0.15s opacity',
'[data-role="notification"]:hover &': {
opacity: 0.5,
},
':last-child': {
marginBottom: 0,
},
'[data-role="notification"] &:hover': {
opacity: 1,
},
});
type ItemProps = {
onHighlight?: () => any;
onHidePlugin?: () => any;
onHideCategory?: () => any;
onClear?: () => any;
isSelected?: boolean;
inactive?: boolean;
selectPlugin?: typeof selectPlugin;
logger?: Logger;
plugin: PluginDefinition | null | undefined;
};
type ItemState = {
reportedNotHelpful: boolean;
};
class NotificationItem extends Component<
ItemProps & PluginNotification,
ItemState
> {
constructor(props: ItemProps & PluginNotification) {
super(props);
const items: Array<ContextMenuItem> = [];
if (props.onHidePlugin && props.plugin) {
items.push({