/******************************************************************************** * Copyright (c) 2019 TypeFox and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * SPDX-License-Identifier: EPL-2.0 ********************************************************************************/ import { FunctionComponent, useContext, useState, useEffect, useRef } from 'react'; import { Link as RouteLink } from 'react-router-dom'; import { Paper, Typography, Box, Grid, Fade } from '@mui/material'; import SaveAltIcon from '@mui/icons-material/SaveAlt'; import { MainContext } from '../../context'; import { ExtensionDetailRoutes } from '../extension-detail/extension-detail-routes'; import { SearchEntry } from '../../extension-registry-types'; import { ExtensionRatingStars } from '../extension-detail/extension-rating-stars'; import { createRoute } from '../../utils'; export const ExtensionListItem: FunctionComponent = props => { const [icon, setIcon] = useState(); const context = useContext(MainContext); const abortController = useRef(new AbortController()); useEffect(() => { updateChanges(); return () => { abortController.current.abort(); if (icon) { URL.revokeObjectURL(icon); } }; }, []); useEffect(() => { updateChanges(); }, [props.extension.namespace, props.extension.name, props.extension.version]); const updateChanges = async (): Promise => { if (icon) { URL.revokeObjectURL(icon); } try { const icon = await context.service.getExtensionIcon(abortController.current, props.extension); setIcon(icon); } catch (err) { context.handleError(err); } }; const { extension, filterSize, idx } = props; const route = createRoute([ExtensionDetailRoutes.ROOT, extension.namespace, extension.name]); const numberFormat = new Intl.NumberFormat(undefined, { notation: 'compact', compactDisplay: 'short' } as any); const downloadCountFormatted = numberFormat.format(extension.downloadCount ?? 0); return *': { '&:not(:last-child)': { marginBottom: '.5rem', } }, opacity: extension.deprecated ? 0.5 : undefined, filter: extension.deprecated ? 'grayscale(100%)' : undefined }} > {extension.displayName ?? extension.name} {extension.namespace} {extension.version}   {downloadCountFormatted != "0" && <> {downloadCountFormatted}} ; }; export interface ExtensionListItemProps { extension: SearchEntry; idx: number; filterSize: number; }