undo-redo.tsx 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import type { FC } from 'react'
  2. import { memo, useEffect, useState } from 'react'
  3. import { useTranslation } from 'react-i18next'
  4. import {
  5. RiArrowGoBackLine,
  6. RiArrowGoForwardFill,
  7. } from '@remixicon/react'
  8. import TipPopup from '../operator/tip-popup'
  9. import { useWorkflowHistoryStore } from '../workflow-history-store'
  10. import Divider from '../../base/divider'
  11. import { useNodesReadOnly } from '@/app/components/workflow/hooks'
  12. import ViewWorkflowHistory from '@/app/components/workflow/header/view-workflow-history'
  13. import classNames from '@/utils/classnames'
  14. import { useAppDetailContext } from '@/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout-main'
  15. export type UndoRedoProps = { handleUndo: () => void; handleRedo: () => void }
  16. const UndoRedo: FC<UndoRedoProps> = ({ handleUndo, handleRedo }) => {
  17. const { detail, isCreate, isEdit, isOperation } = useAppDetailContext()
  18. const { t } = useTranslation()
  19. const { store } = useWorkflowHistoryStore()
  20. const [buttonsDisabled, setButtonsDisabled] = useState({ undo: true, redo: true })
  21. useEffect(() => {
  22. const unsubscribe = store.temporal.subscribe((state) => {
  23. setButtonsDisabled({
  24. undo: state.pastStates.length === 0,
  25. redo: state.futureStates.length === 0,
  26. })
  27. })
  28. return () => unsubscribe()
  29. }, [store])
  30. const { nodesReadOnly } = useNodesReadOnly()
  31. return (
  32. <div className='flex items-center space-x-0.5 rounded-lg border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg p-0.5 shadow-lg backdrop-blur-[5px]'>
  33. <TipPopup title={t('workflow.common.undo')!} shortcuts={['ctrl', 'z']}>
  34. <div
  35. data-tooltip-id='workflow.undo'
  36. className={
  37. classNames('flex items-center px-1.5 w-8 h-8 rounded-md system-sm-medium text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary cursor-pointer select-none',
  38. (nodesReadOnly || buttonsDisabled.undo)
  39. && 'hover:bg-transparent text-text-disabled hover:text-text-disabled cursor-not-allowed')}
  40. onClick={() => !nodesReadOnly && !buttonsDisabled.undo && handleUndo()}
  41. >
  42. <RiArrowGoBackLine className='h-4 w-4' />
  43. </div>
  44. </TipPopup >
  45. <TipPopup title={t('workflow.common.redo')!} shortcuts={['ctrl', 'y']}>
  46. <div
  47. data-tooltip-id='workflow.redo'
  48. className={
  49. classNames('flex items-center px-1.5 w-8 h-8 rounded-md system-sm-medium text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary cursor-pointer select-none',
  50. (nodesReadOnly || buttonsDisabled.redo)
  51. && 'hover:bg-transparent text-text-disabled hover:text-text-disabled cursor-not-allowed',
  52. )}
  53. onClick={() => !nodesReadOnly && !buttonsDisabled.redo && handleRedo()}
  54. >
  55. <RiArrowGoForwardFill className='h-4 w-4' />
  56. </div>
  57. </TipPopup>
  58. {
  59. isEdit && (<>
  60. <Divider type='vertical' className="mx-0.5 h-3.5" />
  61. <ViewWorkflowHistory />
  62. </>)
  63. }
  64. </div >
  65. )
  66. }
  67. export default memo(UndoRedo)