5180 fichiers 38.5 Mo 0 téléchargements 255 vues mis à jour il y a 5 heures ui
OctanepediaView.tsx 4.5 Ko Télécharger le fichier
import { AddLinkEventTracker, ILinkEventTracker, OctaneLogger, RemoveLinkEventTracker } from '@octane/renderer';
import { FC, useEffect, useRef, useState } from 'react';
import { GetConfigurationValue, OpenUrl, resolveHabboPageUrl, SanitizePageHtml } from '../../api';
import { OctaneCardContentView, OctaneCardHeaderView, OctaneCardView } from '../../common';
import '../../css/octanepedia/OctanepediaAirText.css';
import { NativeTextTree } from '../../common/native-text/NativeTextTree';
import { getClickedAnchor } from './getClickedAnchor';
import { createLatestRequest } from './latestRequest';

const NEW_LINE_REGEX = /\n\r|\n|\r/gm;

export const OctanepediaView: FC<{}> = (props) => {
    const [content, setContent] = useState<string>(null);
    const [header, setHeader] = useState<string>('');
    const [dimensions, setDimensions] = useState<{ width: number; height: number }>(null);
    const elementRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        const latest = createLatestRequest();

        const openPage = async (link: string) => {
            const signal = latest.start();

            try {
                const response = await fetch(link, { signal });

                if (!response?.ok || signal.aborted) return;

                const text = await response.text();

                // A newer page was asked for meanwhile: this one is not shown over it.
                if (signal.aborted) return;
                const splitData = text.split(NEW_LINE_REGEX);
                const line = splitData.shift().split('|');

                setHeader(line[0]);

                setDimensions((prevValue) => {
                    if (line[1] && line[1].split(';').length === 2) {
                        const [width, height] = line[1].split(';').map((value) => parseInt(value, 10));

                        if (Number.isFinite(width) && width > 0 && Number.isFinite(height) && height > 0) return { width, height };
                    }

                    return null;
                });

                setContent(SanitizePageHtml(splitData.join('')));
            } catch (error) {
                if (signal.aborted) return;

                OctaneLogger.error(`Failed to fetch ${link}`);
            }
        };

        const linkTracker: ILinkEventTracker = {
            linkReceived: (url: string) => {
                const value = url.split('/');

                if (value.length < 2) return;

                value.shift();

                const link = resolveHabboPageUrl(GetConfigurationValue<string>('habbopages.url'), value.join('/'));

                if (!link) {
                    OctaneLogger.warn(`Refused help page path "${value.join('/')}"`);
                    return;
                }

                openPage(link);
            },
            eventUrlPrefix: 'habbopages/'
        };

        AddLinkEventTracker(linkTracker);

        return () => {
            RemoveLinkEventTracker(linkTracker);
            latest.abort();
        };
    }, []);

    useEffect(() => {
        const handle = (event: MouseEvent) => {
            const anchor = getClickedAnchor(event.target);

            if (!anchor) return;

            // Only the links inside this window: the listener sits on the document, so without
            // this check it opened every link in the client (the profile's unblock link, chat
            // links...) in a new browser page, even with Octanepedia closed.
            if (!elementRef.current?.contains(anchor)) return;

            event.preventDefault();

            const link = anchor.href;

            if (!link || !link.length) return;

            OpenUrl(link);
        };

        document.addEventListener('click', handle);

        return () => {
            document.removeEventListener('click', handle);
        };
    }, []);

    if (!content) return null;

    return (
        <NativeTextTree>
            <OctaneCardView
                className="octanepedia w-[450px] h-[400px] max-w-[90vw] max-h-[85vh]"
                style={dimensions ? { width: dimensions.width, height: dimensions.height } : {}}
                theme="primary-slim">
                <OctaneCardHeaderView headerText={header} onCloseClick={() => setContent(null)} />
                <OctaneCardContentView>
                    <div ref={elementRef} className="octanepedia__page text-black size-full" dangerouslySetInnerHTML={{ __html: content }} />
                </OctaneCardContentView>
            </OctaneCardView>
        </NativeTextTree>
    );
};
15Sujets
1Dépôts
20Membres
2En 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