@@ -3,7 +3,7 @@ import path from 'path'
33import { getAppByName } from '@epic-web/workshop-utils/apps.server'
44import { launchEditor } from '@epic-web/workshop-utils/launch-editor.server'
55import fsExtra from 'fs-extra'
6- import { useEffect } from 'react'
6+ import { type MouseEvent , useEffect } from 'react'
77import { Link , useFetcher } from 'react-router'
88import { z , type ZodTypeAny } from 'zod'
99import { showProgressBarField } from '#app/components/progress-bar.tsx'
@@ -38,6 +38,7 @@ const LaunchSchema = z.intersection(
3838export async function action ( { request } : Route . ActionArgs ) {
3939 ensureUndeployed ( )
4040 const formData = await request . formData ( )
41+ const skipOpenAfterSync = formData . get ( 'skipOpenAfterSync' ) === 'true'
4142 const appFileValues = formData
4243 . getAll ( 'appFile' )
4344 . filter ( ( value ) : value is string => typeof value === 'string' )
@@ -134,7 +135,8 @@ export async function action({ request }: Route.ActionArgs) {
134135 }
135136
136137 const filesToOpen = await getFiles ( form )
137- if ( 'syncTo' in form && form . syncTo ) {
138+ const hasSyncTarget = 'syncTo' in form && Boolean ( form . syncTo )
139+ if ( hasSyncTarget && form . syncTo ) {
138140 const originFiles = await getFiles ( form . syncTo )
139141 for ( let index = 0 ; index < originFiles . length ; index ++ ) {
140142 const originFile = originFiles [ index ]
@@ -149,6 +151,9 @@ export async function action({ request }: Route.ActionArgs) {
149151 await fsExtra . promises . copyFile ( originFile . filepath , destFile . filepath )
150152 }
151153 }
154+ if ( hasSyncTarget && skipOpenAfterSync ) {
155+ return dataWithPE ( request , formData , { status : 'success' } as const )
156+ }
152157 const results : Array <
153158 { status : 'success' } | { status : 'error' ; message : string }
154159 > = [ ]
@@ -231,6 +236,15 @@ function LaunchEditorImpl({
231236} : LaunchEditorProps ) {
232237 const fetcher = useLaunchFetcher ( onUpdate )
233238 const peRedirectInput = usePERedirectInput ( )
239+ const handleSubmitButtonClick = ( event : MouseEvent < HTMLButtonElement > ) => {
240+ if ( ! syncTo || ! event . altKey || ! event . metaKey ) return
241+ event . preventDefault ( )
242+ const form = event . currentTarget . form
243+ if ( ! form ) return
244+ const formData = new FormData ( form )
245+ formData . set ( 'skipOpenAfterSync' , 'true' )
246+ void fetcher . submit ( formData , { method : 'POST' , action : '/launch-editor' } )
247+ }
234248
235249 if ( ! file && ! appFile ) {
236250 console . error ( 'LaunchEditor: requires either "file" or "appFile" prop.' )
@@ -270,6 +284,7 @@ function LaunchEditorImpl({
270284 ) : null }
271285 < button
272286 type = "submit"
287+ onClick = { handleSubmitButtonClick }
273288 className = { cn (
274289 'launch_button' ,
275290 fetcher . state === 'idle' ? null : 'cursor-progress' ,
0 commit comments