<commit_before>import React, { useEffect, useState, useRef, MutableRefObject, useImperativeHandle } from 'react';
import { getRelativeApiHostname } from '@proton/shared/lib/helpers/url';
import { useConfig } from '../../hooks';

// The sizes for these are hardcoded since the widget calculates it based on the viewport, and since it's in
// an iframe it needs to have something reasonable.
// The main chat widget.
const OPENED_SIZE = {
    height: `${572 / 16}rem`,
    width: `${374 / 16}rem`,
};
// The small button to toggle the chat.
const CLOSED_SIZE = {
    height: `${70 / 16}rem`,
    width: `${140 / 16}rem`,
};

const getIframeUrl = (apiUrl: string, zendeskKey: string) => {
    const url = new URL(apiUrl, window.location.origin);
    url.hostname = getRelativeApiHostname(url.hostname);
    url.pathname = '/core/v4/resources/zendesk';
    url.searchParams.set('Key', zendeskKey);
    return url;
};

export interface ZendeskRef {
    run: (data: object) => void;
    show: () => void;
}

interface Props {
    zendeskKey: string;
    zendeskRef?: MutableRefObject<ZendeskRef | undefined>;
    name?: string;
    email?: string;
    onLoaded: () => void;
    locale: string;
}

const LiveChatZendesk = ({ zendeskKey, zendeskRef, name, email, onLoaded, locale }: Props) => {
    const { API_URL } = useConfig();
    const [style, setStyle] = useState({
        position: 'absolute',
        bottom: 0,
        right: 0,
        maxHeight: '100%',
        maxWidth: '100%',
        ...CLOSED_SIZE,
    });
    const [state, setState] = useState({ loaded: false, connected: false });
    const iframeRef = useRef<HTMLIFrameElement>(null);
    const pendingLoadingRef = useRef<{ show?: boolean; locale?: string }>({});

    const iframeUrl = getIframeUrl(API_URL, zendeskKey);

    const src = iframeUrl.toString();
    const targetOrigin = iframeUrl.origin;

    const handleRun = (args: any) => {
        const contentWindow = iframeRef.current?.contentWindow;
        if (!contentWindow || !state.loaded) {
            return;
        }
        contentWindow.postMessage({ args }, targetOrigin);
    };

    const handleShow = () => {
        pendingLoadingRef.current.show = true;
        handleRun(['webWidget', 'toggle']);
    };

    useImperativeHandle(zendeskRef, () => ({
        run: handleRun,
        show: handleShow,
    }));

    useEffect(() => {
        if (!state.loaded) {
            return;
        }
        handleRun([
            'webWidget',
            'prefill',
            {
                name: { value: name, readOnly: true },
                email: { value: email, readOnly: true },
            },
        ]);
    }, [state.loaded, name, email]);

    useEffect(() => {
        if (!state.loaded) {
            return;
        }
        handleRun(['webWidget', 'setLocale', locale]);
    }, [state.loaded, locale]);

    useEffect(() => {
        if (!state.loaded || !pendingLoadingRef.current) {
            return;
        }
        const oldPending = pendingLoadingRef.current;
        pendingLoadingRef.current = {};
        if (oldPending.show) {
            handleShow();
        }
    }, [state.loaded]);

    useEffect(() => {
        let globalId = 1;
        const handlers: { [key: string]: [(value: any) => void, (reason?: any) => void, number] } = {};<commit_msg>Enable writable email field in zendesk chat<commit_after>import React, { useEffect, useState, useRef, MutableRefObject, useImperativeHandle } from 'react';
import { getRelativeApiHostname } from '@proton/shared/lib/helpers/url';
import { useConfig } from '../../hooks';

// The sizes for these are hardcoded since the widget calculates it based on the viewport, and since it's in
// an iframe it needs to have something reasonable.
// The main chat widget.
const OPENED_SIZE = {
    height: `${572 / 16}rem`,
    width: `${374 / 16}rem`,
};
// The small button to toggle the chat.
const CLOSED_SIZE = {
    height: `${70 / 16}rem`,
    width: `${140 / 16}rem`,
};

const getIframeUrl = (apiUrl: string, zendeskKey: string) => {
    const url = new URL(apiUrl, window.location.origin);
    url.hostname = getRelativeApiHostname(url.hostname);
    url.pathname = '/core/v4/resources/zendesk';
    url.searchParams.set('Key', zendeskKey);
    return url;
};

export interface ZendeskRef {
    run: (data: object) => void;
    show: () => void;
}

interface Props {
    zendeskKey: string;
    zendeskRef?: MutableRefObject<ZendeskRef | undefined>;
    name?: string;
    email?: string;
    onLoaded: () => void;
    locale: string;
}

const LiveChatZendesk = ({ zendeskKey, zendeskRef, name, email, onLoaded, locale }: Props) => {
    const { API_URL } = useConfig();
    const [style, setStyle] = useState({
        position: 'absolute',
        bottom: 0,
        right: 0,
        maxHeight: '100%',
        maxWidth: '100%',
        ...CLOSED_SIZE,
    });
    const [state, setState] = useState({ loaded: false, connected: false });
    const iframeRef = useRef<HTMLIFrameElement>(null);
    const pendingLoadingRef = useRef<{ show?: boolean; locale?: string }>({});

    const iframeUrl = getIframeUrl(API_URL, zendeskKey);

    const src = iframeUrl.toString();
    const targetOrigin = iframeUrl.origin;

    const handleRun = (args: any) => {
        const contentWindow = iframeRef.current?.contentWindow;
        if (!contentWindow || !state.loaded) {
            return;
        }
        contentWindow.postMessage({ args }, targetOrigin);
    };

    const handleShow = () => {
        pendingLoadingRef.current.show = true;
        handleRun(['webWidget', 'toggle']);
    };

    useImperativeHandle(zendeskRef, () => ({
        run: handleRun,
        show: handleShow,
    }));

    useEffect(() => {
        if (!state.loaded) {
            return;
        }
        handleRun([
            'webWidget',
            'prefill',
            {
                name: { value: name, readOnly: true },
                email: { value: email, readOnly: Boolean(email) },
            },
        ]);
    }, [state.loaded, name, email]);

    useEffect(() => {
        if (!state.loaded) {
            return;
        }
        handleRun(['webWidget', 'setLocale', locale]);
    }, [state.loaded, locale]);

    useEffect(() => {
        if (!state.loaded || !pendingLoadingRef.current) {
            return;
        }
        const oldPending = pendingLoadingRef.current;
        pendingLoadingRef.current = {};
        if (oldPending.show) {
            handleShow();
        }
    }, [state.loaded]);

    useEffect(() => {
        let globalId = 1;
        const handlers: { [key: string]: [(value: any) => void, (reason?: any) => void, number] } = {};
{'fraction_non_alphanumeric': 0.1470059880239521, 'fraction_numerical': 0.008682634730538923, 'mean_word_length': 2.467047223663726, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4552749', 'n_tokens_mistral': 2065, 'n_tokens_neox': 2004, 'n_words': 508}