<commit_before>import { ChangeEvent, Dispatch, SetStateAction } from 'react';

import { c } from 'ttag';

import { MAX_SIZE_SCREENSHOT } from '@proton/shared/lib/constants';
import { resize, toBlob } from '@proton/shared/lib/helpers/image';
import { getKnowledgeBaseUrl } from '@proton/shared/lib/helpers/url';
import removeItem from '@proton/utils/removeIndex';

import { Button, FileInput, Icon, Info, Table, TableBody, TableCell, TableRow } from '../../components';
import { useNotifications } from '../../hooks';

export interface Screenshot {
    name: string;
    blob: Blob;
}

interface Props {
    id: string;
    screenshots: Screenshot[];
    setScreenshots: Dispatch<SetStateAction<Screenshot[]>>;
    uploading: boolean;
    setUploading: Dispatch<SetStateAction<boolean>>;
    disabled?: boolean;
}

const AttachScreenshot = ({ id, screenshots, setScreenshots, uploading, setUploading, disabled }: Props) => {
    const { createNotification } = useNotifications();

    const handleChange = async ({ target }: ChangeEvent<HTMLInputElement>) => {
        setUploading(true);

        try {
            const targetImages = target.files ? [...target.files].filter(({ type }) => /^image\//i.test(type)) : [];

            if (!targetImages.length) {
                return createNotification({
                    type: 'error',
                    text: c('Error notification in the bug report modal when the user upload file')
                        .t`No image selected`,
                });
            }

            const uploadedScreenshots = await Promise.all(
                targetImages.map((img) =>
                    resize(img, MAX_SIZE_SCREENSHOT).then((base64str) => ({
                        name: img.name,
                        blob: toBlob(base64str),
                    }))
                )
            );
            setScreenshots(uploadedScreenshots);
        } finally {
            setUploading(false);
        }
    };

    const removeUploadedScreenShot = (screenshot: Screenshot) => {
        const index = screenshots.indexOf(screenshot);

        if (index === -1) {
            return;
        }

        setScreenshots((items) => removeItem(items, index));
    };

    return (
        <>
            <label className="text-semibold block" htmlFor={id}>
                <span className="mr0-5 align-middle">{c('Label').t`Attach screenshot(s)`}</span>
                <Info url={getKnowledgeBaseUrl('/screenshot-reporting-bugs')} />
            </label>
            <div>
                <FileInput
                    multiple
                    accept="image/*"
                    id={id}
                    onChange={handleChange}
                    disabled={uploading || disabled}<commit_msg>Disallow svg attachments in bug report form<commit_after>import { ChangeEvent, Dispatch, SetStateAction } from 'react';

import { c } from 'ttag';

import { MAX_SIZE_SCREENSHOT } from '@proton/shared/lib/constants';
import { resize, toBlob } from '@proton/shared/lib/helpers/image';
import { getKnowledgeBaseUrl } from '@proton/shared/lib/helpers/url';
import removeItem from '@proton/utils/removeIndex';

import { Button, FileInput, Icon, Info, Table, TableBody, TableCell, TableRow } from '../../components';
import { useNotifications } from '../../hooks';

export interface Screenshot {
    name: string;
    blob: Blob;
}

interface Props {
    id: string;
    screenshots: Screenshot[];
    setScreenshots: Dispatch<SetStateAction<Screenshot[]>>;
    uploading: boolean;
    setUploading: Dispatch<SetStateAction<boolean>>;
    disabled?: boolean;
}

const AttachScreenshot = ({ id, screenshots, setScreenshots, uploading, setUploading, disabled }: Props) => {
    const { createNotification } = useNotifications();

    const handleChange = async ({ target }: ChangeEvent<HTMLInputElement>) => {
        setUploading(true);

        try {
            const targetImages = target.files ? [...target.files].filter(({ type }) => /^image\//i.test(type)) : [];

            if (!targetImages.length) {
                return createNotification({
                    type: 'error',
                    text: c('Error notification in the bug report modal when the user upload file')
                        .t`No image selected`,
                });
            }

            const uploadedScreenshots = await Promise.all(
                targetImages.map((img) =>
                    resize(img, MAX_SIZE_SCREENSHOT).then((base64str) => ({
                        name: img.name,
                        blob: toBlob(base64str),
                    }))
                )
            );
            setScreenshots(uploadedScreenshots);
        } finally {
            setUploading(false);
        }
    };

    const removeUploadedScreenShot = (screenshot: Screenshot) => {
        const index = screenshots.indexOf(screenshot);

        if (index === -1) {
            return;
        }

        setScreenshots((items) => removeItem(items, index));
    };

    return (
        <>
            <label className="text-semibold block" htmlFor={id}>
                <span className="mr0-5 align-middle">{c('Label').t`Attach screenshot(s)`}</span>
                <Info url={getKnowledgeBaseUrl('/screenshot-reporting-bugs')} />
            </label>
            <div>
                <FileInput
                    multiple
                    accept="image/bmp, image/apng, image/png, image/jpeg, image/gif, image/tiff, image/webp"
                    id={id}
                    onChange={handleChange}
                    disabled={uploading || disabled}
{'fraction_non_alphanumeric': 0.12580299785867238, 'fraction_numerical': 0.0024982155603140615, 'mean_word_length': 2.0313683071930773, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 41, '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': '3520207', 'n_tokens_mistral': 1598, 'n_tokens_neox': 1504, 'n_words': 327}