| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 | 'use client'import type { FC } from 'react'import React, { useCallback, useState } from 'react'import type { Dependency, InstallStatusResponse, Plugin, VersionInfo } from '../../../types'import Button from '@/app/components/base/button'import { RiLoader2Line } from '@remixicon/react'import { useTranslation } from 'react-i18next'import InstallMulti from './install-multi'import { useInstallOrUpdate } from '@/service/use-plugins'import useRefreshPluginList from '../../hooks/use-refresh-plugin-list'const i18nPrefix = 'plugin.installModal'type Props = {  allPlugins: Dependency[]  onStartToInstall?: () => void  onInstalled: (plugins: Plugin[], installStatus: InstallStatusResponse[]) => void  onCancel: () => void  isFromMarketPlace?: boolean  isHideButton?: boolean}const Install: FC<Props> = ({  allPlugins,  onStartToInstall,  onInstalled,  onCancel,  isFromMarketPlace,  isHideButton,}) => {  const { t } = useTranslation()  const [selectedPlugins, setSelectedPlugins] = React.useState<Plugin[]>([])  const [selectedIndexes, setSelectedIndexes] = React.useState<number[]>([])  const selectedPluginsNum = selectedPlugins.length  const { refreshPluginList } = useRefreshPluginList()  const handleSelect = (plugin: Plugin, selectedIndex: number) => {    const isSelected = !!selectedPlugins.find(p => p.plugin_id === plugin.plugin_id)    let nextSelectedPlugins    if (isSelected)      nextSelectedPlugins = selectedPlugins.filter(p => p.plugin_id !== plugin.plugin_id)    else      nextSelectedPlugins = [...selectedPlugins, plugin]    setSelectedPlugins(nextSelectedPlugins)    const nextSelectedIndexes = isSelected ? selectedIndexes.filter(i => i !== selectedIndex) : [...selectedIndexes, selectedIndex]    setSelectedIndexes(nextSelectedIndexes)  }  const [canInstall, setCanInstall] = React.useState(false)  const [installedInfo, setInstalledInfo] = useState<Record<string, VersionInfo> | undefined>(undefined)  const handleLoadedAllPlugin = useCallback((installedInfo: Record<string, VersionInfo> | undefined) => {    setInstalledInfo(installedInfo)    setCanInstall(true)  }, [])  // Install from marketplace and github  const { mutate: installOrUpdate, isPending: isInstalling } = useInstallOrUpdate({    onSuccess: (res: InstallStatusResponse[]) => {      onInstalled(selectedPlugins, res.map((r, i) => {        return ({          ...r,          isFromMarketPlace: allPlugins[selectedIndexes[i]].type === 'marketplace',        })      }))      const hasInstallSuccess = res.some(r => r.success)      if (hasInstallSuccess)        refreshPluginList(undefined, true)    },  })  const handleInstall = () => {    onStartToInstall?.()    installOrUpdate({      payload: allPlugins.filter((_d, index) => selectedIndexes.includes(index)),      plugin: selectedPlugins,      installedInfo: installedInfo!,    })  }  return (    <>      <div className='flex flex-col items-start justify-center gap-4 self-stretch px-6 py-3'>        <div className='system-md-regular text-text-secondary'>          <p>{t(`${i18nPrefix}.${selectedPluginsNum > 1 ? 'readyToInstallPackages' : 'readyToInstallPackage'}`, { num: selectedPluginsNum })}</p>        </div>        <div className='w-full space-y-1 rounded-2xl bg-background-section-burn p-2'>          <InstallMulti            allPlugins={allPlugins}            selectedPlugins={selectedPlugins}            onSelect={handleSelect}            onLoadedAllPlugin={handleLoadedAllPlugin}            isFromMarketPlace={isFromMarketPlace}          />        </div>      </div>      {/* Action Buttons */}      {!isHideButton && (        <div className='flex items-center justify-end gap-2 self-stretch p-6 pt-5'>          {!canInstall && (            <Button variant='secondary' className='min-w-[72px]' onClick={onCancel}>              {t('common.operation.cancel')}            </Button>          )}          <Button            variant='primary'            className='flex min-w-[72px] space-x-0.5'            disabled={!canInstall || isInstalling || selectedPlugins.length === 0}            onClick={handleInstall}          >            {isInstalling && <RiLoader2Line className='h-4 w-4 animate-spin-slow' />}            <span>{t(`${i18nPrefix}.${isInstalling ? 'installing' : 'install'}`)}</span>          </Button>        </div>      )}    </>  )}export default React.memo(Install)
 |