@@ -3,10 +3,13 @@ import { useDialog } from "@tui/ui/dialog"
33import { DialogSelect , type DialogSelectOption } from "@tui/ui/dialog-select"
44import { useSync } from "@tui/context/sync"
55import { useProject } from "@tui/context/project"
6+ import { useRoute } from "@tui/context/route"
67import { createMemo , createSignal , onMount } from "solid-js"
78import { errorMessage } from "@/util/error"
89import { useSDK } from "../context/sdk"
910import { useToast } from "../ui/toast"
11+ import { DialogAlert } from "../ui/dialog-alert"
12+ import { DialogWorkspaceFileChanges } from "./dialog-workspace-file-changes"
1013
1114type Adapter = {
1215 type : string
@@ -38,13 +41,15 @@ export function recentConnectedWorkspaces<WorkspaceInfo extends { id: string }>(
3841 get : ( workspaceID : string ) => WorkspaceInfo | undefined
3942 status : ( workspaceID : string ) => string | undefined
4043 limit ?: number
44+ omitWorkspaceID ?: string
4145} ) {
4246 const workspaces = input . sessions
4347 . toSorted ( ( a , b ) => b . time . updated - a . time . updated )
4448 . flatMap ( ( session ) => {
4549 const workspace = session . workspaceID ? input . get ( session . workspaceID ) : undefined
4650 return workspace && input . status ( workspace . id ) === "connected" ? [ workspace ] : [ ]
4751 } )
52+ . filter ( ( workspace ) => workspace . id !== input . omitWorkspaceID )
4853 . filter ( ( workspace , index , list ) => list . findIndex ( ( item ) => item . id === workspace . id ) === index )
4954 const recent = workspaces . slice ( 0 , input . limit ?? 3 )
5055
@@ -93,17 +98,29 @@ export async function warpWorkspaceSession(input: {
9398 sync : ReturnType < typeof useSync >
9499 project : ReturnType < typeof useProject >
95100 toast : ReturnType < typeof useToast >
101+ sourceWorkspaceID ?: string
96102 workspaceID : string | null
97103 sessionID : string
104+ copyChanges : boolean
98105 done ?: ( ) => void
99106} ) : Promise < boolean > {
100107 const result = await input . sdk . client . experimental . workspace
101108 . warp ( {
102109 id : input . workspaceID ,
103110 sessionID : input . sessionID ,
111+ copyChanges : input . copyChanges ,
104112 } )
105113 . catch ( ( ) => undefined )
106114 if ( ! result ?. data ) {
115+ if ( result ?. error ?. name === "VcsApplyError" ) {
116+ await DialogAlert . show (
117+ input . dialog ,
118+ "Unable to Warp Session" ,
119+ "Unable to apply file changes to this workspace. It has existing changes that conflict or is based off a different branch. Session has not been warped." ,
120+ )
121+ return false
122+ }
123+
107124 input . toast . show ( {
108125 message : `Failed to warp session: ${ errorMessage ( result ?. error ?? "no response" ) } ` ,
109126 variant : "error" ,
@@ -143,16 +160,29 @@ export async function warpWorkspaceSession(input: {
143160 return true
144161}
145162
163+ export async function confirmWorkspaceFileChanges ( input : {
164+ dialog : ReturnType < typeof useDialog >
165+ sdk : ReturnType < typeof useSDK >
166+ sourceWorkspaceID ?: string
167+ } ) {
168+ const status = await input . sdk . client . vcs . status ( { workspace : input . sourceWorkspaceID } ) . catch ( ( ) => undefined )
169+ const fileChangeChoice = status ?. data ?. length ? await DialogWorkspaceFileChanges . show ( input . dialog , status . data ) : "no"
170+ if ( ! fileChangeChoice ) return
171+ return fileChangeChoice === "yes"
172+ }
173+
146174export function DialogWorkspaceSelect ( props : {
147175 adapters ?: Adapter [ ]
148176 onSelect : ( selection : WorkspaceSelection ) => Promise < void > | void
149177} ) {
150178 const dialog = useDialog ( )
151179 const project = useProject ( )
180+ const route = useRoute ( )
152181 const sync = useSync ( )
153182 const sdk = useSDK ( )
154183 const toast = useToast ( )
155184 const [ adapters , setAdapters ] = createSignal < Adapter [ ] | undefined > ( props . adapters )
185+ const omittedWorkspaceID = createMemo ( ( ) => ( route . data . type === "session" ? project . workspace . current ( ) : undefined ) )
156186
157187 onMount ( ( ) => {
158188 dialog . setSize ( "medium" )
@@ -171,6 +201,7 @@ export function DialogWorkspaceSelect(props: {
171201 sessions : sync . data . session ,
172202 get : project . workspace . get ,
173203 status : project . workspace . status ,
204+ omitWorkspaceID : omittedWorkspaceID ( ) ,
174205 } )
175206 return [
176207 ...list . map ( ( adapter ) => ( {
@@ -231,19 +262,23 @@ export function DialogWorkspaceSelect(props: {
231262 return
232263 }
233264
234- dialog . replace ( ( ) => < DialogExistingWorkspaceSelect onSelect = { props . onSelect } /> )
265+ dialog . replace ( ( ) => < DialogExistingWorkspaceSelect omitWorkspaceID = { omittedWorkspaceID ( ) } onSelect = { props . onSelect } /> )
235266 } }
236267 />
237268 )
238269}
239270
240- function DialogExistingWorkspaceSelect ( props : { onSelect : ( selection : WorkspaceSelection ) => Promise < void > | void } ) {
271+ function DialogExistingWorkspaceSelect ( props : {
272+ omitWorkspaceID ?: string
273+ onSelect : ( selection : WorkspaceSelection ) => Promise < void > | void
274+ } ) {
241275 const project = useProject ( )
242276
243277 const options = createMemo < DialogSelectOption < ExistingWorkspaceSelectValue > [ ] > ( ( ) =>
244278 project . workspace
245279 . list ( )
246280 . filter ( ( workspace ) => project . workspace . status ( workspace . id ) === "connected" )
281+ . filter ( ( workspace ) => workspace . id !== props . omitWorkspaceID )
247282 . map ( ( workspace : Workspace ) => ( {
248283 title : workspace . name ,
249284 description : `(${ workspace . type } )` ,
0 commit comments