@@ -359,6 +359,11 @@ function PromptBar({
359359 onIcLoraCondTypeChange,
360360 icLoraStrength,
361361 onIcLoraStrengthChange,
362+ seedLocked,
363+ lockedSeed,
364+ onSeedLockedChange,
365+ onLockedSeedChange,
366+ onRandomizeSeed,
362367} : {
363368 mode : 'image' | 'video' | 'retake' | 'ic-lora'
364369 onModeChange : ( mode : 'image' | 'video' | 'retake' | 'ic-lora' ) => void
@@ -390,6 +395,11 @@ function PromptBar({
390395 onIcLoraCondTypeChange ?: ( type : ICLoraConditioningType ) => void
391396 icLoraStrength ?: number
392397 onIcLoraStrengthChange ?: ( strength : number ) => void
398+ seedLocked : boolean
399+ lockedSeed : number
400+ onSeedLockedChange : ( locked : boolean ) => void
401+ onLockedSeedChange : ( seed : number ) => void
402+ onRandomizeSeed : ( ) => void
393403} ) {
394404 const inputRef = useRef < HTMLInputElement > ( null )
395405 const audioInputRef = useRef < HTMLInputElement > ( null )
@@ -407,6 +417,51 @@ function PromptBar({
407417 : [ '540p' , '720p' , '1080p' ]
408418 const videoFpsOptions = shouldVideoGenerateWithLtxApi ? [ ...FORCED_API_VIDEO_FPS ] : [ 24 , 25 , 50 ]
409419
420+ const seedControls = (
421+ < >
422+ < div className = "w-px h-4 bg-zinc-700 mx-0.5" />
423+ < SettingsDropdown
424+ title = "SEED"
425+ value = { seedLocked ? 'fixed' : 'random' }
426+ onChange = { ( value ) => onSeedLockedChange ( value === 'fixed' ) }
427+ options = { [
428+ { value : 'random' , label : 'Random Seed' } ,
429+ { value : 'fixed' , label : 'Fixed Seed' } ,
430+ ] }
431+ trigger = {
432+ < >
433+ < span className = "text-zinc-500 text-[10px]" > SEED</ span >
434+ < span className = "text-zinc-300 font-medium" > { seedLocked ? 'Fixed' : 'Random' } </ span >
435+ < ChevronUp className = "h-3 w-3 text-zinc-500" />
436+ </ >
437+ }
438+ />
439+ { seedLocked && (
440+ < div className = "flex items-center gap-1 ml-1 rounded-md bg-zinc-800/50 px-1 py-1" >
441+ < input
442+ type = "number"
443+ min = "0"
444+ max = "2147483647"
445+ value = { lockedSeed }
446+ onChange = { ( e ) => onLockedSeedChange ( parseInt ( e . target . value , 10 ) || 0 ) }
447+ className = "w-12 bg-transparent text-zinc-300 font-medium focus:outline-none"
448+ placeholder = "S"
449+ />
450+ < button
451+ type = "button"
452+ onClick = { onRandomizeSeed }
453+ className = "rounded p-1 text-zinc-500 transition-colors hover:bg-zinc-700 hover:text-white"
454+ title = "Generate random seed"
455+ >
456+ < svg className = "h-3.5 w-3.5" viewBox = "0 0 24 24" fill = "none" stroke = "currentColor" strokeWidth = "2" >
457+ < path d = "M21 2v6h-6M3 12a9 9 0 0 1 15-6.7L21 8M3 22v-6h6M21 12a9 9 0 0 1-15 6.7L3 16" />
458+ </ svg >
459+ </ button >
460+ </ div >
461+ ) }
462+ </ >
463+ )
464+
410465 const handleDrop = ( e : React . DragEvent ) => {
411466 e . preventDefault ( )
412467 setIsDragOver ( false )
@@ -569,7 +624,7 @@ function PromptBar({
569624 </ div >
570625
571626 { /* Bottom row: Mode selector + Settings */ }
572- < div className = "flex items-center gap-0.5 px-1.5 py-1.5 border-t border-zinc-800/60 text-xs text-zinc-400" >
627+ < div className = "flex flex-nowrap items-center gap-0.5 px-1.5 py-1.5 border-t border-zinc-800/60 text-xs text-zinc-400" >
573628 { /* Mode dropdown */ }
574629 < SettingsDropdown
575630 title = "MODE"
@@ -593,7 +648,10 @@ function PromptBar({
593648 < div className = "flex-1" />
594649
595650 { isRetake ? (
596- < div className = "text-[10px] text-zinc-500 pr-2" > Trim in the panel above, then retake</ div >
651+ < >
652+ < div className = "text-[10px] text-zinc-500 pr-2" > Trim in the panel above, then retake</ div >
653+ { seedControls }
654+ </ >
597655 ) : isIcLora ? (
598656 < >
599657 < SettingsDropdown
@@ -629,6 +687,7 @@ function PromptBar({
629687 </ >
630688 }
631689 />
690+ { seedControls }
632691 </ >
633692 ) : mode === 'image' ? (
634693 < >
@@ -673,7 +732,7 @@ function PromptBar({
673732 </ >
674733 }
675734 />
676-
735+ { seedControls }
677736 </ >
678737 ) : (
679738 < >
@@ -771,7 +830,7 @@ function PromptBar({
771830 </ >
772831 }
773832 />
774-
833+ { seedControls }
775834 </ >
776835 ) }
777836
@@ -879,7 +938,7 @@ export function GenSpace() {
879938 setGenSpaceIcLoraSource,
880939 setPendingIcLoraUpdate,
881940 } = useProjects ( )
882- const { shouldVideoGenerateWithLtxApi, forceApiGenerations, settings : appSettings } = useAppSettings ( )
941+ const { shouldVideoGenerateWithLtxApi, forceApiGenerations, settings : appSettings , updateSettings } = useAppSettings ( )
883942 const [ mode , setMode ] = useState < 'image' | 'video' | 'retake' | 'ic-lora' > ( 'video' )
884943 const [ prompt , setPrompt ] = useState ( '' )
885944 const [ inputImage , setInputImage ] = useState < string | null > ( null )
@@ -910,6 +969,22 @@ export function GenSpace() {
910969 }
911970 } | null > ( null )
912971 const [ settings , setSettings ] = useState ( ( ) => ( { ...DEFAULT_VIDEO_SETTINGS } ) )
972+ const handleSeedLockedChange = useCallback ( ( seedLocked : boolean ) => {
973+ updateSettings ( ( prev ) => ( { ...prev , seedLocked } ) )
974+ } , [ updateSettings ] )
975+ const handleLockedSeedChange = useCallback ( ( lockedSeed : number ) => {
976+ updateSettings ( ( prev ) => ( {
977+ ...prev ,
978+ lockedSeed : Math . max ( 0 , Math . min ( 2147483647 , lockedSeed ) ) ,
979+ } ) )
980+ } , [ updateSettings ] )
981+ const handleRandomizeSeed = useCallback ( ( ) => {
982+ updateSettings ( ( prev ) => ( {
983+ ...prev ,
984+ seedLocked : true ,
985+ lockedSeed : Math . floor ( Math . random ( ) * 2147483647 ) ,
986+ } ) )
987+ } , [ updateSettings ] )
913988 const applyForcedVideoSettings = useCallback (
914989 ( next : { model : string ; duration : number ; videoResolution : string ; fps : number ; audio : boolean ; aspectRatio : string ; imageResolution : string ; variations : number } ) => {
915990 if ( ! shouldVideoGenerateWithLtxApi || mode !== 'video' ) return next
@@ -1714,6 +1789,11 @@ export function GenSpace() {
17141789 onIcLoraCondTypeChange = { setIcLoraCondType }
17151790 icLoraStrength = { icLoraStrength }
17161791 onIcLoraStrengthChange = { setIcLoraStrength }
1792+ seedLocked = { appSettings . seedLocked }
1793+ lockedSeed = { appSettings . lockedSeed }
1794+ onSeedLockedChange = { handleSeedLockedChange }
1795+ onLockedSeedChange = { handleLockedSeedChange }
1796+ onRandomizeSeed = { handleRandomizeSeed }
17171797 />
17181798 </ div >
17191799
0 commit comments