@@ -36,6 +36,7 @@ import {
3636} from '@/lib/api/machines' ;
3737import {
3838 deleteWorkspaceAppearance ,
39+ listWorkspaceAppearances ,
3940 upsertWorkspaceAppearance ,
4041} from '@/lib/api/workspaceAppearances' ;
4142import { listFeatureSets , type FeatureSet } from '@/lib/api/featureSets' ;
@@ -50,6 +51,8 @@ import {
5051 bindingMachineId ,
5152 bindingScopeConflicts ,
5253 buildBindingPayload ,
54+ adoptBindingSeed ,
55+ findAdoptableSiblingBindings ,
5356 folderName ,
5457 normalizeIcon ,
5558 sameBindingInput ,
@@ -267,6 +270,7 @@ export function WorkspaceBindingPanel() {
267270 const [ clientMachineId , setClientMachineIdState ] = useState < string | null > ( null ) ;
268271 const [ showMachineCallout , setShowMachineCallout ] = useState ( false ) ;
269272 const [ adoptDismissed , setAdoptDismissed ] = useState ( false ) ;
273+ const [ appearanceIcon , setAppearanceIcon ] = useState < string | null > ( null ) ;
270274 const [ assignMachineId , setAssignMachineId ] = useState ( '' ) ;
271275 const [ creatingMachine , setCreatingMachine ] = useState ( false ) ;
272276 const [ newMachineName , setNewMachineName ] = useState ( '' ) ;
@@ -326,15 +330,17 @@ export function WorkspaceBindingPanel() {
326330 setCreatingMachine ( false ) ;
327331 setNewMachineName ( '' ) ;
328332 setAdoptDismissed ( false ) ;
333+ setAppearanceIcon ( null ) ;
329334
330335 void ( async ( ) => {
331336 try {
332- const [ loadedSpaces , loadedFs , loadedMachines , loadedBindings , loadedLocalId ] =
337+ const [ loadedSpaces , loadedFs , loadedMachines , loadedBindings , loadedAppearances , loadedLocalId ] =
333338 await Promise . all ( [
334339 listSpaces ( ) ,
335340 listFeatureSets ( ) ,
336341 listMachines ( ) . catch ( ( ) => [ ] as Machine [ ] ) ,
337342 listWorkspaceBindings ( ) . catch ( ( ) => [ ] as WorkspaceBinding [ ] ) ,
343+ listWorkspaceAppearances ( ) . catch ( ( ) => [ ] ) ,
338344 getLocalMachineId ( ) . catch ( ( ) => null ) ,
339345 ] ) ;
340346 if ( cancelled ) return ;
@@ -344,6 +350,14 @@ export function WorkspaceBindingPanel() {
344350 setAllBindings ( loadedBindings ) ;
345351 setLocalMachineId ( loadedLocalId ) ;
346352
353+ const rootForAppearance = payload . workspaceRoot ?? payload . binding ?. workspace_root ;
354+ if ( rootForAppearance ) {
355+ const appearance = loadedAppearances . find (
356+ ( entry ) => entry . workspace_root . toLowerCase ( ) === rootForAppearance . toLowerCase ( ) ,
357+ ) ;
358+ setAppearanceIcon ( appearance ?. icon ?? null ) ;
359+ }
360+
347361 if ( payload . mode === 'create-from-live' && payload . clientId ) {
348362 const existingClientMachine = await getClientMachineId ( payload . clientId ) . catch (
349363 ( ) => null ,
@@ -396,20 +410,18 @@ export function WorkspaceBindingPanel() {
396410 const isEdit = mode === 'edit' ;
397411 const rootEditable = mode !== 'create-from-live' ;
398412 const spaceLocked = payload ?. spaceLocked ?? false ;
399- const panelKey = `${ mode } :${ payload ?. binding ?. id ?? workspaceRoot ?? 'new' } :${ spaces . length } ` ;
413+ const panelKey = `${ mode } :${ payload ?. binding ?. id ?? workspaceRoot ?? 'new' } :${ spaces . length } : ${ allBindings . length } ` ;
400414
401415 const defaultTargetMachineId =
402416 clientMachineId ?? viewerMachineId ?? localMachineId ?? null ;
403417
404418 const siblingBindings = useMemo ( ( ) => {
405419 if ( mode !== 'create-from-live' || ! workspaceRoot ) return [ ] ;
406- const currentFolder = folderName ( workspaceRoot ) . toLowerCase ( ) ;
407- return allBindings . filter (
408- ( b ) =>
409- b . workspace_root . toLowerCase ( ) !== workspaceRoot . toLowerCase ( ) &&
410- folderName ( b . workspace_root ) . toLowerCase ( ) === currentFolder ,
411- ) ;
412- } , [ mode , workspaceRoot , allBindings ] ) ;
420+ return findAdoptableSiblingBindings ( allBindings , workspaceRoot , defaultTargetMachineId ) ;
421+ } , [ mode , workspaceRoot , allBindings , defaultTargetMachineId ] ) ;
422+
423+ const adoptSource =
424+ mode === 'create-from-live' && ! adoptDismissed ? siblingBindings [ 0 ] ?? null : null ;
413425
414426 const effectiveMachineId = isEdit
415427 ? bindingMachineId ( machineId )
@@ -418,11 +430,21 @@ export function WorkspaceBindingPanel() {
418430 useEffect ( ( ) => {
419431 if ( ! isOpen || ! payload || loadingData ) return ;
420432 const initial = formInitial ;
421- setRoot ( initial ?. workspace_root ?? payload . workspaceRoot ?? '' ) ;
422- setLabel ( initial ?. label ?? '' ) ;
423- setIcon ( initial ?. icon ?? payload . appearanceIcon ?? '' ) ;
424- setSpaceId ( initial ?. space_id ?? defaultSpaceId ) ;
425- setFsIds ( initial ?. feature_set_ids ?? [ ] ) ;
433+ const rootValue = initial ?. workspace_root ?? payload . workspaceRoot ?? '' ;
434+ const adopted = adoptSource ? adoptBindingSeed ( adoptSource , rootValue ) : null ;
435+ const resolvedIcon =
436+ adopted ?. icon ??
437+ initial ?. icon ??
438+ payload . appearanceIcon ??
439+ appearanceIcon ??
440+ '' ;
441+ const resolvedLabel = adopted ?. label ?? initial ?. label ?? '' ;
442+
443+ setRoot ( rootValue ) ;
444+ setLabel ( resolvedLabel ) ;
445+ setIcon ( resolvedIcon ) ;
446+ setSpaceId ( adopted ?. space_id ?? initial ?. space_id ?? defaultSpaceId ) ;
447+ setFsIds ( adopted ?. feature_set_ids ?? initial ?. feature_set_ids ?? [ ] ) ;
426448 setMachineId ( initial ?. machine_id ?? '' ) ;
427449 setMachineIds (
428450 mode === 'edit' ? [ ] : defaultTargetMachineId ? [ defaultTargetMachineId ] : [ ] ,
@@ -432,7 +454,7 @@ export function WorkspaceBindingPanel() {
432454 lastSavedRef . current = null ;
433455 pendingPayloadRef . current = null ;
434456 lastSavedAppearanceRef . current =
435- mode === 'create-from-live' ? normalizeIcon ( initial ?. icon ) : null ;
457+ mode === 'create-from-live' ? normalizeIcon ( resolvedIcon ) : null ;
436458 } , [
437459 panelKey ,
438460 loadingData ,
@@ -442,6 +464,8 @@ export function WorkspaceBindingPanel() {
442464 defaultSpaceId ,
443465 mode ,
444466 defaultTargetMachineId ,
467+ adoptSource ,
468+ appearanceIcon ,
445469 ] ) ;
446470
447471 useEffect ( ( ) => {
@@ -1039,7 +1063,7 @@ export function WorkspaceBindingPanel() {
10391063 </ div >
10401064 ) }
10411065
1042- { mode === 'create-from-live' && siblingBindings . length > 0 && ! adoptDismissed && (
1066+ { mode === 'create-from-live' && siblingBindings . length > 1 && ! adoptDismissed && (
10431067 < div
10441068 className = "rounded-xl border border-primary-200/80 dark:border-primary-800/50 bg-primary-50/50 dark:bg-primary-900/10 p-4 space-y-3"
10451069 data-testid = "workspace-binding-adopt-card"
@@ -1105,10 +1129,11 @@ export function WorkspaceBindingPanel() {
11051129 variant = "secondary"
11061130 size = "sm"
11071131 onClick = { ( ) => {
1108- setSpaceId ( sibling . space_id ) ;
1109- setFsIds ( sibling . feature_set_ids ) ;
1110- if ( sibling . label ) setLabel ( sibling . label ) ;
1111- if ( sibling . icon ) setIcon ( sibling . icon ) ;
1132+ const seed = adoptBindingSeed ( sibling , root ) ;
1133+ setSpaceId ( seed . space_id ) ;
1134+ setFsIds ( seed . feature_set_ids ) ;
1135+ setLabel ( seed . label ?? '' ) ;
1136+ setIcon ( seed . icon ?? '' ) ;
11121137 setAdoptDismissed ( true ) ;
11131138 } }
11141139 data-testid = { `workspace-binding-adopt-use-${ sibling . id } ` }
0 commit comments