add rerun last mask button
This commit is contained in:
parent
1a865810f5
commit
183334f8f7
@ -63,6 +63,7 @@ import emitter, {
|
|||||||
EVENT_PROMPT,
|
EVENT_PROMPT,
|
||||||
EVENT_CUSTOM_MASK,
|
EVENT_CUSTOM_MASK,
|
||||||
EVENT_PAINT_BY_EXAMPLE,
|
EVENT_PAINT_BY_EXAMPLE,
|
||||||
|
RERUN_LAST_MASK,
|
||||||
} from '../../event'
|
} from '../../event'
|
||||||
import FileSelect from '../FileSelect/FileSelect'
|
import FileSelect from '../FileSelect/FileSelect'
|
||||||
import InteractiveSeg from '../InteractiveSeg/InteractiveSeg'
|
import InteractiveSeg from '../InteractiveSeg/InteractiveSeg'
|
||||||
@ -515,6 +516,28 @@ export default function Editor() {
|
|||||||
}
|
}
|
||||||
}, [runInpainting])
|
}, [runInpainting])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
emitter.on(RERUN_LAST_MASK, () => {
|
||||||
|
if (lastLineGroup.length !== 0) {
|
||||||
|
// 使用上一次手绘的 mask 生成
|
||||||
|
runInpainting(true, undefined, prevInteractiveSegMask)
|
||||||
|
} else if (prevInteractiveSegMask) {
|
||||||
|
// 使用上一次 IS 的 mask 生成
|
||||||
|
runInpainting(false, undefined, prevInteractiveSegMask)
|
||||||
|
} else {
|
||||||
|
setToastState({
|
||||||
|
open: true,
|
||||||
|
desc: 'No mask to reuse',
|
||||||
|
state: 'error',
|
||||||
|
duration: 1500,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return () => {
|
||||||
|
emitter.off(RERUN_LAST_MASK)
|
||||||
|
}
|
||||||
|
}, [runInpainting])
|
||||||
|
|
||||||
const hadRunInpainting = () => {
|
const hadRunInpainting = () => {
|
||||||
return renders.length !== 0
|
return renders.length !== 0
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { FolderIcon, PhotoIcon } from '@heroicons/react/24/outline'
|
import { FolderIcon, PhotoIcon } from '@heroicons/react/24/outline'
|
||||||
import { PlayIcon } from '@radix-ui/react-icons'
|
import { PlayIcon, ReloadIcon } from '@radix-ui/react-icons'
|
||||||
import React, { useState } from 'react'
|
import React, { useCallback, useState } from 'react'
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import * as PopoverPrimitive from '@radix-ui/react-popover'
|
import * as PopoverPrimitive from '@radix-ui/react-popover'
|
||||||
import {
|
import {
|
||||||
@ -19,7 +19,7 @@ import { ThemeChanger } from './ThemeChanger'
|
|||||||
import SettingIcon from '../Settings/SettingIcon'
|
import SettingIcon from '../Settings/SettingIcon'
|
||||||
import PromptInput from './PromptInput'
|
import PromptInput from './PromptInput'
|
||||||
import CoffeeIcon from '../CoffeeIcon/CoffeeIcon'
|
import CoffeeIcon from '../CoffeeIcon/CoffeeIcon'
|
||||||
import emitter, { EVENT_CUSTOM_MASK } from '../../event'
|
import emitter, { EVENT_CUSTOM_MASK, RERUN_LAST_MASK } from '../../event'
|
||||||
import { useImage } from '../../utils'
|
import { useImage } from '../../utils'
|
||||||
import useHotKey from '../../hooks/useHotkey'
|
import useHotKey from '../../hooks/useHotkey'
|
||||||
|
|
||||||
@ -49,6 +49,21 @@ const Header = () => {
|
|||||||
[showFileManager, enableFileManager, isInpainting]
|
[showFileManager, enableFileManager, isInpainting]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const handleRerunLastMask = useCallback(() => {
|
||||||
|
emitter.emit(RERUN_LAST_MASK)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useHotKey(
|
||||||
|
'r',
|
||||||
|
() => {
|
||||||
|
if (!isInpainting) {
|
||||||
|
handleRerunLastMask()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
[isInpainting, handleRerunLastMask]
|
||||||
|
)
|
||||||
|
|
||||||
const renderHeader = () => {
|
const renderHeader = () => {
|
||||||
return (
|
return (
|
||||||
<header>
|
<header>
|
||||||
@ -57,7 +72,7 @@ const Header = () => {
|
|||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: 8,
|
gap: 4,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{enableFileManager ? (
|
{enableFileManager ? (
|
||||||
@ -136,41 +151,53 @@ const Header = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<PopoverPrimitive.Root open={openMaskPopover}>
|
{mask ? (
|
||||||
<PopoverPrimitive.Trigger
|
<PopoverPrimitive.Root open={openMaskPopover}>
|
||||||
className="btn-primary side-panel-trigger"
|
<PopoverPrimitive.Trigger
|
||||||
onMouseEnter={() => setOpenMaskPopover(true)}
|
className="btn-primary side-panel-trigger"
|
||||||
onMouseLeave={() => setOpenMaskPopover(false)}
|
onMouseEnter={() => setOpenMaskPopover(true)}
|
||||||
style={{
|
onMouseLeave={() => setOpenMaskPopover(false)}
|
||||||
visibility: mask ? 'visible' : 'hidden',
|
|
||||||
outline: 'none',
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
if (mask) {
|
|
||||||
emitter.emit(EVENT_CUSTOM_MASK, { mask })
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<PlayIcon />
|
|
||||||
</PopoverPrimitive.Trigger>
|
|
||||||
<PopoverPrimitive.Portal>
|
|
||||||
<PopoverPrimitive.Content
|
|
||||||
style={{
|
style={{
|
||||||
|
visibility: mask ? 'visible' : 'hidden',
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
}}
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
if (mask) {
|
||||||
|
emitter.emit(EVENT_CUSTOM_MASK, { mask })
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{maskImageLoaded ? (
|
<PlayIcon />
|
||||||
<img
|
</PopoverPrimitive.Trigger>
|
||||||
src={maskImage.src}
|
<PopoverPrimitive.Portal>
|
||||||
alt="mask"
|
<PopoverPrimitive.Content
|
||||||
className="mask-preview"
|
style={{
|
||||||
/>
|
outline: 'none',
|
||||||
) : (
|
}}
|
||||||
<></>
|
>
|
||||||
)}
|
{maskImageLoaded ? (
|
||||||
</PopoverPrimitive.Content>
|
<img
|
||||||
</PopoverPrimitive.Portal>
|
src={maskImage.src}
|
||||||
</PopoverPrimitive.Root>
|
alt="mask"
|
||||||
|
className="mask-preview"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</PopoverPrimitive.Content>
|
||||||
|
</PopoverPrimitive.Portal>
|
||||||
|
</PopoverPrimitive.Root>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Button
|
||||||
|
icon={<ReloadIcon style={{ height: 16, width: 16 }} />}
|
||||||
|
style={{ border: 0, gap: 0 }}
|
||||||
|
disabled={isInpainting}
|
||||||
|
toolTip="Rerun last mask [r]"
|
||||||
|
onClick={handleRerunLastMask}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ export default function ShortcutsModal() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="shortcut-options-column">
|
<div className="shortcut-options-column">
|
||||||
|
<ShortCut content="Rerun last mask" keys={['R']} />
|
||||||
<ShortCut content="Undo" keys={[CmdOrCtrl, 'Z']} />
|
<ShortCut content="Undo" keys={[CmdOrCtrl, 'Z']} />
|
||||||
<ShortCut content="Redo" keys={[CmdOrCtrl, 'Shift', 'Z']} />
|
<ShortCut content="Redo" keys={[CmdOrCtrl, 'Shift', 'Z']} />
|
||||||
<ShortCut content="Copy Result" keys={[CmdOrCtrl, 'C']} />
|
<ShortCut content="Copy Result" keys={[CmdOrCtrl, 'C']} />
|
||||||
|
@ -12,6 +12,8 @@ export interface PaintByExampleEventData {
|
|||||||
image: File
|
image: File
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const RERUN_LAST_MASK = 'rerun_last_mask'
|
||||||
|
|
||||||
const emitter = mitt()
|
const emitter = mitt()
|
||||||
|
|
||||||
export default emitter
|
export default emitter
|
||||||
|
Loading…
Reference in New Issue
Block a user