mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-20 07:26:19 +00:00
9ef6983632
Two typecheck regressions surfaced after pulling duckietm PR #126 onto this branch: - NotificationBadgeReceivedBubbleView lost its `useEffectEvent` wrapper during conflict resolution. The PR rewrote the effect to use a plain `useEffect(..., [activeBadgeCodes.length])`; reintroduce the `requestBadgesIfEmpty = useEffectEvent(...)` shape that the rest of this branch uses, applied to the renamed activeBadgeCodes selector. - `src/bootstrap.ts` was importing `GetConfiguration` from the package alias `@nitrots/configuration`, which Vite resolves via filesystem alias but tsgo does not. Swap to the monolithic `@nitrots/nitro-renderer` re-export, matching how App.tsx already imports the same symbol. Both fixes get `yarn typecheck` green again and all 113 Vitest cases still pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
80 lines
3.3 KiB
TypeScript
80 lines
3.3 KiB
TypeScript
import { RequestBadgesComposer } from '@nitrots/nitro-renderer';
|
|
import { FC, useEffect, useEffectEvent } from 'react';
|
|
import { LocalizeText, NotificationBubbleItem, SendMessageComposer } from '../../../../api';
|
|
import { Flex, LayoutNotificationBubbleView, LayoutNotificationBubbleViewProps, Text } from '../../../../common';
|
|
import { useInventoryBadges } from '../../../../hooks';
|
|
|
|
export interface NotificationBadgeReceivedBubbleViewProps extends LayoutNotificationBubbleViewProps
|
|
{
|
|
item: NotificationBubbleItem;
|
|
}
|
|
|
|
export const NotificationBadgeReceivedBubbleView: FC<NotificationBadgeReceivedBubbleViewProps> = props =>
|
|
{
|
|
const { item = null, onClose = null, ...rest } = props;
|
|
const { activeBadgeCodes = [], toggleBadge = null, isWearingBadge = null, canWearBadges = null } = useInventoryBadges();
|
|
|
|
const requestBadgesIfEmpty = useEffectEvent(() =>
|
|
{
|
|
if(activeBadgeCodes.length === 0) SendMessageComposer(new RequestBadgesComposer());
|
|
});
|
|
|
|
useEffect(() =>
|
|
{
|
|
requestBadgesIfEmpty();
|
|
}, []);
|
|
|
|
const badgeCode = item?.linkUrl ?? null;
|
|
const isLoaded = activeBadgeCodes.length > 0;
|
|
const alreadyWearing = !!badgeCode && !!isWearingBadge && isWearingBadge(badgeCode);
|
|
const slotsAvailable = !!canWearBadges && canWearBadges();
|
|
const canShowWearButton = !!badgeCode && isLoaded && !alreadyWearing && slotsAvailable;
|
|
|
|
const handleWear = (event: React.MouseEvent) =>
|
|
{
|
|
event.stopPropagation();
|
|
|
|
if(canShowWearButton && toggleBadge) toggleBadge(badgeCode);
|
|
|
|
if(onClose) onClose();
|
|
};
|
|
|
|
const handleDismiss = (event: React.MouseEvent) =>
|
|
{
|
|
event.stopPropagation();
|
|
if(onClose) onClose();
|
|
};
|
|
|
|
return (
|
|
<LayoutNotificationBubbleView className="flex-col" onClose={ onClose } { ...rest }>
|
|
<div onClick={ (e) => e.stopPropagation() }>
|
|
<Flex alignItems="center" gap={ 2 } className="mb-2">
|
|
<Flex center className="w-[50px] h-[50px] shrink-0">
|
|
{ item.iconUrl && <img alt="" className="no-select" src={ item.iconUrl } /> }
|
|
</Flex>
|
|
<Flex column gap={ 0 }>
|
|
<Text bold variant="white">
|
|
{ item.senderName
|
|
? LocalizeText('notifications.text.received.badge', [ 'user_name' ], [ item.senderName ])
|
|
: LocalizeText('prereg.reward.you.received') }
|
|
</Text>
|
|
<Text variant="white" small>{ item.message }</Text>
|
|
</Flex>
|
|
</Flex>
|
|
<Flex alignItems="center" justifyContent="end" gap={ 2 }>
|
|
{ canShowWearButton &&
|
|
<button
|
|
className="btn btn-success w-full btn-sm"
|
|
type="button"
|
|
onClick={ handleWear }>
|
|
{ LocalizeText('inventory.badges.wearbadge') }
|
|
</button> }
|
|
<span className="underline cursor-pointer text-nowrap" onClick={ handleDismiss }>
|
|
{ LocalizeText('notifications.button.later') }
|
|
</span>
|
|
</Flex>
|
|
</div>
|
|
</LayoutNotificationBubbleView>
|
|
);
|
|
};
|