Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

operation-dropdown.tsx 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. 'use client'
  2. import type { FC } from 'react'
  3. import React, { useCallback, useRef, useState } from 'react'
  4. import { useTranslation } from 'react-i18next'
  5. import { PluginSource } from '../types'
  6. import { RiArrowRightUpLine, RiMoreFill } from '@remixicon/react'
  7. import ActionButton from '@/app/components/base/action-button'
  8. // import Button from '@/app/components/base/button'
  9. import {
  10. PortalToFollowElem,
  11. PortalToFollowElemContent,
  12. PortalToFollowElemTrigger,
  13. } from '@/app/components/base/portal-to-follow-elem'
  14. import cn from '@/utils/classnames'
  15. import { useGlobalPublicStore } from '@/context/global-public-context'
  16. type Props = {
  17. source: PluginSource
  18. onInfo: () => void
  19. onCheckVersion: () => void
  20. onRemove: () => void
  21. detailUrl: string
  22. }
  23. const OperationDropdown: FC<Props> = ({
  24. source,
  25. detailUrl,
  26. onInfo,
  27. onCheckVersion,
  28. onRemove,
  29. }) => {
  30. const { t } = useTranslation()
  31. const [open, doSetOpen] = useState(false)
  32. const openRef = useRef(open)
  33. const setOpen = useCallback((v: boolean) => {
  34. doSetOpen(v)
  35. openRef.current = v
  36. }, [doSetOpen])
  37. const handleTrigger = useCallback(() => {
  38. setOpen(!openRef.current)
  39. }, [setOpen])
  40. const { enable_marketplace } = useGlobalPublicStore(s => s.systemFeatures)
  41. return (
  42. <PortalToFollowElem
  43. open={open}
  44. onOpenChange={setOpen}
  45. placement='bottom-end'
  46. offset={{
  47. mainAxis: -12,
  48. crossAxis: 36,
  49. }}
  50. >
  51. <PortalToFollowElemTrigger onClick={handleTrigger}>
  52. <div>
  53. <ActionButton className={cn(open && 'bg-state-base-hover')}>
  54. <RiMoreFill className='h-4 w-4' />
  55. </ActionButton>
  56. </div>
  57. </PortalToFollowElemTrigger>
  58. <PortalToFollowElemContent className='z-50'>
  59. <div className='w-[160px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1 shadow-lg'>
  60. {source === PluginSource.github && (
  61. <div
  62. onClick={() => {
  63. onInfo()
  64. handleTrigger()
  65. }}
  66. className='system-md-regular cursor-pointer rounded-lg px-3 py-1.5 text-text-secondary hover:bg-state-base-hover'
  67. >{t('plugin.detailPanel.operation.info')}</div>
  68. )}
  69. {source === PluginSource.github && (
  70. <div
  71. onClick={() => {
  72. onCheckVersion()
  73. handleTrigger()
  74. }}
  75. className='system-md-regular cursor-pointer rounded-lg px-3 py-1.5 text-text-secondary hover:bg-state-base-hover'
  76. >{t('plugin.detailPanel.operation.checkUpdate')}</div>
  77. )}
  78. {(source === PluginSource.marketplace || source === PluginSource.github) && enable_marketplace && (
  79. <a href={detailUrl} target='_blank' className='system-md-regular flex cursor-pointer items-center rounded-lg px-3 py-1.5 text-text-secondary hover:bg-state-base-hover'>
  80. <span className='grow'>{t('plugin.detailPanel.operation.viewDetail')}</span>
  81. <RiArrowRightUpLine className='h-3.5 w-3.5 shrink-0 text-text-tertiary' />
  82. </a>
  83. )}
  84. {(source === PluginSource.marketplace || source === PluginSource.github) && enable_marketplace && (
  85. <div className='my-1 h-px bg-divider-subtle'></div>
  86. )}
  87. <div
  88. onClick={() => {
  89. onRemove()
  90. handleTrigger()
  91. }}
  92. className='system-md-regular cursor-pointer rounded-lg px-3 py-1.5 text-text-secondary hover:bg-state-destructive-hover hover:text-text-destructive'
  93. >{t('plugin.detailPanel.operation.remove')}</div>
  94. </div>
  95. </PortalToFollowElemContent>
  96. </PortalToFollowElem>
  97. )
  98. }
  99. export default React.memo(OperationDropdown)