2727 v-model:value =" numCores"
2828 />
2929
30- <!-- Shared Home Folder -->
30+ <!-- Shared Folder -->
3131 <ConfigCard
3232 icon =" fluent:folder-link-32-filled"
33- title =" Shared Home Folder"
33+ title =" Shared Folder"
3434 type =" switch"
35- v-model:value =" shareHomeFolder "
35+ v-model:value =" shareFolder "
3636 >
3737 <template v-slot :desc >
38- If enabled, you will be able to access your Linux home folder within Windows under
38+ If enabled, you will be able to access your selected folder within Windows under
3939 <span class =" font-mono bg-neutral-700 rounded-md px-1 py-0.5" >Network\host.lan</span >
4040 </template >
4141 </ConfigCard >
4242
43+ <!-- Shared Folder Location -->
44+ <ConfigCard
45+ v-if =" shareFolder"
46+ icon =" mdi:folder-cog"
47+ title =" Shared Folder Location"
48+ type =" custom"
49+ >
50+ <template v-slot :desc >
51+ <span v-if =" sharedFolderPath" >
52+ Currently sharing: <span class =" font-mono bg-neutral-700 rounded-md px-1 py-0.5" >{{ sharedFolderPath }}</span >
53+ </span >
54+ <span v-else >
55+ Select a folder to share with Windows
56+ </span >
57+ </template >
58+ <x-button @click =" selectSharedFolder" >
59+ Browse
60+ </x-button >
61+ </ConfigCard >
62+
4363 <!-- Auto Start Container -->
4464 <ConfigCard
4565 icon =" clarity:power-solid"
@@ -455,7 +475,8 @@ import {
455475} from " ../lib/constants" ;
456476import { ComposePortEntry , ComposePortMapper , Range } from " ../utils/port" ;
457477const { app }: typeof import (" @electron/remote" ) = require (" @electron/remote" );
458-
478+ const electron: typeof import (" electron" ) = require (" electron" ).remote || require (" @electron/remote" );
479+ const os: typeof import (" os" ) = require (" node:os" );
459480
460481// For Resources
461482const compose = ref <ComposeConfig | null >(null );
@@ -465,8 +486,10 @@ const maxNumCores = ref(0);
465486const ramGB = ref (0 );
466487const origRamGB = ref (0 );
467488const maxRamGB = ref (0 );
468- const origShareHomeFolder = ref (false );
469- const shareHomeFolder = ref (false );
489+ const shareFolder = ref (false );
490+ const origShareFolder = ref (false );
491+ const sharedFolderPath = ref (" " );
492+ const origSharedFolderPath = ref (" " );
470493const origAutoStartContainer = ref (false );
471494const autoStartContainer = ref (false );
472495const freerdpPort = ref (0 );
@@ -490,7 +513,6 @@ const winboat = Winboat.getInstance();
490513const usbManager = USBManager .getInstance ();
491514
492515// Constants
493- const HOMEFOLDER_SHARE_STR = winboat .containerMgr ! .defaultCompose .services .windows .volumes .find (v => v .startsWith (" ${HOME}" ))! ;
494516const USB_BUS_PATH = " /dev/bus/usb:/dev/bus/usb" ;
495517const QMP_ARGUMENT = " -qmp tcp:0.0.0.0:7149,server,wait=off" ; // 7149 can remain hardcoded as it refers to a guest port
496518
@@ -512,8 +534,19 @@ async function assignValues() {
512534 ramGB .value = Number (compose .value .services .windows .environment .RAM_SIZE .split (" G" )[0 ]);
513535 origRamGB .value = ramGB .value ;
514536
515- shareHomeFolder .value = compose .value .services .windows .volumes .includes (HOMEFOLDER_SHARE_STR );
516- origShareHomeFolder .value = shareHomeFolder .value ;
537+ // Find any volume that ends with /shared
538+ const sharedVolume = compose .value .services .windows .volumes .find (v => v .includes (" /shared" ));
539+ if (sharedVolume ) {
540+ shareFolder .value = true ;
541+ // Extract the path before :/shared
542+ const [hostPath] = sharedVolume .split (" :" );
543+ sharedFolderPath .value = hostPath .replace (" ${HOME}" , os .homedir ());
544+ } else {
545+ shareFolder .value = false ;
546+ sharedFolderPath .value = " " ;
547+ }
548+ origShareFolder .value = shareFolder .value ;
549+ origSharedFolderPath .value = sharedFolderPath .value ;
517550
518551 autoStartContainer .value = compose .value .services .windows .restart === RESTART_ON_FAILURE ;
519552 origAutoStartContainer .value = autoStartContainer .value ;
@@ -536,16 +569,20 @@ async function saveCompose() {
536569 compose .value ! .services .windows .environment .RAM_SIZE = ` ${ramGB .value }G ` ;
537570 compose .value ! .services .windows .environment .CPU_CORES = ` ${numCores .value } ` ;
538571
539- const composeHasHomefolderShare = compose .value ! .services .windows .volumes .includes (HOMEFOLDER_SHARE_STR );
540-
541- if (shareHomeFolder .value && ! composeHasHomefolderShare ) {
542- compose .value ! .services .windows .volumes .push (HOMEFOLDER_SHARE_STR );
543- } else if (! shareHomeFolder .value && composeHasHomefolderShare ) {
572+ // Remove any existing shared volume
573+ const existingSharedVolume = compose .value ! .services .windows .volumes .find (v => v .includes (" /shared" ));
574+ if (existingSharedVolume ) {
544575 compose .value ! .services .windows .volumes = compose .value ! .services .windows .volumes .filter (
545- v => v !== HOMEFOLDER_SHARE_STR ,
576+ v => ! v . includes ( " /shared " ) ,
546577 );
547578 }
548579
580+ // Add the new shared volume if enabled
581+ if (shareFolder .value && sharedFolderPath .value ) {
582+ const volumeStr = ` ${sharedFolderPath .value }:/shared ` ;
583+ compose .value ! .services .windows .volumes .push (volumeStr );
584+ }
585+
549586 compose .value ! .services .windows .restart = autoStartContainer .value ? RESTART_ON_FAILURE : RESTART_NO ;
550587
551588 portMapper .value ! .setShortPortMapping (GUEST_RDP_PORT , freerdpPort .value , {
@@ -572,6 +609,23 @@ async function saveCompose() {
572609 }
573610}
574611
612+ /**
613+ * Opens a dialog to select a folder to share with Windows
614+ */
615+ function selectSharedFolder() {
616+ electron .dialog
617+ .showOpenDialog ({
618+ title: " Select Folder to Share" ,
619+ properties: [" openDirectory" ],
620+ defaultPath: sharedFolderPath .value || os .homedir (),
621+ })
622+ .then (result => {
623+ if (! result .canceled && result .filePaths .length > 0 ) {
624+ sharedFolderPath .value = result .filePaths [0 ];
625+ }
626+ });
627+ }
628+
575629/**
576630 * Adds the required fields for USB passthrough to work
577631 * to the Compose file if they don't already exist
@@ -668,7 +722,8 @@ const saveButtonDisabled = computed(() => {
668722 const hasResourceChanges =
669723 origNumCores .value !== numCores .value ||
670724 origRamGB .value !== ramGB .value ||
671- shareHomeFolder .value !== origShareHomeFolder .value ||
725+ shareFolder .value !== origShareFolder .value ||
726+ sharedFolderPath .value !== origSharedFolderPath .value ||
672727 (! Number .isNaN (freerdpPort .value ) && freerdpPort .value !== origFreerdpPort .value ) ||
673728 autoStartContainer .value !== origAutoStartContainer .value ;
674729
@@ -733,6 +788,13 @@ async function toggleExperimentalFeatures() {
733788 winboat .createQMPInterval ();
734789 }
735790}
791+
792+ // Watch for when shared folder is enabled and set default path
793+ watch (shareFolder , (newValue ) => {
794+ if (newValue && ! sharedFolderPath .value ) {
795+ sharedFolderPath .value = os .homedir ();
796+ }
797+ });
736798 </script >
737799
738800<style scoped>
0 commit comments