undo-redo.tsx 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  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. export type UndoRedoProps = { handleUndo: () => void; handleRedo: () => void }
  15. const UndoRedo: FC<UndoRedoProps> = ({ handleUndo, handleRedo }) => {
  16. const { t } = useTranslation()
  17. const { store } = useWorkflowHistoryStore()
  18. const [buttonsDisabled, setButtonsDisabled] = useState({ undo: true, redo: true })
  19. useEffect(() => {
  20. const unsubscribe = store.temporal.subscribe((state) => {
  21. setButtonsDisabled({
  22. undo: state.pastStates.length === 0,
  23. redo: state.futureStates.length === 0,
  24. })
  25. })
  26. return () => unsubscribe()
  27. }, [store])
  28. const { nodesReadOnly } = useNodesReadOnly()
  29. return (
  30. <div className='flex items-center space-x-0.5 p-0.5 backdrop-blur-[5px] rounded-lg border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg shadow-lg'>
  31. <TipPopup title={t('workflow.common.undo')!} shortcuts={['ctrl', 'z']}>
  32. <div
  33. data-tooltip-id='workflow.undo'
  34. className={
  35. 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',
  36. (nodesReadOnly || buttonsDisabled.undo)
  37. && 'hover:bg-transparent text-text-disabled hover:text-text-disabled cursor-not-allowed')}
  38. onClick={() => !nodesReadOnly && !buttonsDisabled.undo && handleUndo()}
  39. >
  40. <RiArrowGoBackLine className='h-4 w-4' />
  41. </div>
  42. </TipPopup >
  43. <TipPopup title={t('workflow.common.redo')!} shortcuts={['ctrl', 'y']}>
  44. <div
  45. data-tooltip-id='workflow.redo'
  46. className={
  47. 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',
  48. (nodesReadOnly || buttonsDisabled.redo)
  49. && 'hover:bg-transparent text-text-disabled hover:text-text-disabled cursor-not-allowed',
  50. )}
  51. onClick={() => !nodesReadOnly && !buttonsDisabled.redo && handleRedo()}
  52. >
  53. <RiArrowGoForwardFill className='h-4 w-4' />
  54. </div>
  55. </TipPopup>
  56. <Divider type='vertical' className="h-3.5 mx-0.5" />
  57. <ViewWorkflowHistory />
  58. </div >
  59. )
  60. }
  61. export default memo(UndoRedo)