5180 fichiers 38.5 Mo 0 téléchargements 490 vues mis à jour il y a 7 heures ui
nitro-v36-with-renderer-v36 / src / components / room / widgets / furniture / FurnitureWiredChestRewardView.tsx
FurnitureWiredChestRewardView.tsx 6.1 Ko Télécharger le fichier
import { AddLinkEventTracker, CreateLinkEvent, FurnitureType, ILinkEventTracker, IWiredTradeNode, RemoveLinkEventTracker, WIRED_TRADE_NODE_COINS, WIRED_TRADE_NODE_FURNI } from '@octane/renderer';
import { FC, useEffect } from 'react';
import { localizeWithFallback, ProductImageUtility, WIRED_CHEST_REWARD_LINK } from '../../../../api';
import { BaseButton, Button, Column, Flex, LayoutCurrencyIcon, OctaneCardContentView, OctaneCardHeaderView, OctaneCardView, Text } from '../../../../common';
import { useRoom } from '../../../../hooks';
import { IWiredRewardReceipt, useWiredRewardStore, WIRED_REWARD_MAX_OPEN } from '../../../../hooks/rooms/widgets/wiredRewardStore';
import '../../../../css/room/FurniWindowsCAir.css';
import { NativeTextTree } from '../../../../common/native-text/NativeTextTree';

/** AIR RewardNotificationView: the frame is 276 px wide. */
const REWARD_WIDTH = 276;

/** AIR RewardNotificationView.hasCreditNode: coins of a reward wait in the earnings window. */
export const wiredRewardHasCredits = (nodes: IWiredTradeNode[]): boolean => (nodes ?? []).some(node => node.type === WIRED_TRADE_NODE_COINS);

/** AIR RewardNotificationController: each further window is pushed 25 px out, alternating sides. */
export const wiredRewardOffset = (index: number): number =>
{
    const slot = index % WIRED_REWARD_MAX_OPEN;

    if(slot <= 0) return 0;

    const step = 25 * Math.trunc((slot + 1) / 2);

    return ((slot + 1) % 2 === 0) ? step : -step;
};

/** `wiredrewards.earnings` is html with one `event:` link (the earnings window); it is drawn as text and a link. */
const EARNINGS_LINK = /^([\s\S]*?)<a\s+href="event:([^"]+)"[^>]*>([\s\S]*?)<\/a>([\s\S]*)$/i;

const EarningsText: FC = () =>
{
    const text = localizeWithFallback('wiredrewards.earnings', 'You can claim the credits in the <a href="event:habboUI/open/vault">earnings window</a>');
    const match = EARNINGS_LINK.exec(text);

    if(!match) return <Text small>{ text.replace(/<[^>]+>/g, '') }</Text>;

    return (
        <NativeTextTree>
            <Text small className="octane-wired-chest-reward-earnings">
                { match[1] }
                <BaseButton className="octane-wired-chest-reward-link" onClick={ () => CreateLinkEvent(match[2]) }>{ match[3] }</BaseButton>
                { match[4] }
            </Text>
        </NativeTextTree>
    );
};

const RewardWindow: FC<{ receipt: IWiredRewardReceipt; index: number; onClose: () => void }> = ({ receipt, index, onClose }) =>
{
    const title = localizeWithFallback('wiredrewards.title', 'Rewards');
    const offset = wiredRewardOffset(index);

    return (
        <NativeTextTree>
            <OctaneCardView theme="primary-slim" className="octane-wired-chest-reward" uniqueKey={ `wired-reward-${ receipt.id }` } offsetLeft={ offset } offsetTop={ offset } style={ { width: REWARD_WIDTH } }>
                <OctaneCardHeaderView headerText={ title } onCloseClick={ onClose } />
                <OctaneCardContentView>
                    <Column gap={ 2 }>
                        <Text>{ receipt.text || localizeWithFallback('wiredrewards.desc_default', 'Congratulations! You received some stuff :)') }</Text>
                        <Flex gap={ 2 } className="flex-wrap">
                            { receipt.nodes.map((node, position) =>
                                // AIR onClickNode: coins open the earnings window, furni the inventory.
                                <BaseButton key={ position } className="octane-wired-chest-reward-node" aria-label={ `${ node.amount }` }
                                    onClick={ () => CreateLinkEvent(node.type === WIRED_TRADE_NODE_COINS ? 'habboUI/open/vault' : 'inventory/show') }>
                                    { node.type === WIRED_TRADE_NODE_FURNI && node.itemType
                                        ? <img alt="" width={ 40 } height={ 40 } src={ ProductImageUtility.getProductImageUrl(node.itemType.isWallItem ? FurnitureType.WALL : FurnitureType.FLOOR, node.itemType.typeId, node.itemType.legacyPosterId) } />
                                        : <LayoutCurrencyIcon type={ -1 } /> }
                                    <Text bold>{ node.amount }</Text>
                                </BaseButton>) }
                        </Flex>
                        { wiredRewardHasCredits(receipt.nodes) && <EarningsText /> }
                        <Button onClick={ onClose }>{ localizeWithFallback('wiredrewards.ok', 'Yayy') }</Button>
                    </Column>
                </OctaneCardContentView>
            </OctaneCardView>
        </NativeTextTree>
    );
};

/**
 * The reward popups of WiredTransactionSuccess (type 2), after AIR RewardNotificationController / RewardNotificationView:
 * every reward keeps its id, up to ten windows are open at once, a reward that opens by itself does, and the others
 * open from their own notification (`wiredchestreward/open/<id>`). They belong to the room they arrived in.
 */
export const FurnitureWiredChestRewardView: FC = () =>
{
    const { roomSession = null } = useRoom();
    const roomId = roomSession?.roomId ?? -1;
    const receipts = useWiredRewardStore(state => state.receipts);
    const open = useWiredRewardStore(state => state.open);

    useEffect(() =>
    {
        useWiredRewardStore.getState().clear();
    }, [ roomId ]);

    useEffect(() =>
    {
        const linkTracker: ILinkEventTracker = {
            linkReceived: (url: string) =>
            {
                if(!url.startsWith(WIRED_CHEST_REWARD_LINK)) return;

                const id = Number(url.substring(WIRED_CHEST_REWARD_LINK.length + 1));

                if(Number.isInteger(id) && id > 0) useWiredRewardStore.getState().openReward(id);
            },
            eventUrlPrefix: 'wiredchestreward/',
        };

        AddLinkEventTracker(linkTracker);

        return () => RemoveLinkEventTracker(linkTracker);
    }, []);

    if(roomId === -1) return null;

    return (
        <>
            { open.map((id, index) => receipts[id] &&
                <RewardWindow key={ id } receipt={ receipts[id] } index={ index } onClose={ () => useWiredRewardStore.getState().closeReward(id) } />) }
        </>
    );
};
15Sujets
1Dépôts
20Membres
3En ligne
Profile
Inscrit
Dernière visite
Messages
0
Votes positifs
0
Votes négatifs
0

Nous utilisons des cookies pour assurer le bon fonctionnement du site et améliorer votre expérience. en savoir plus

Autoriser