@@ -3,6 +3,7 @@ import sidebarApps from "sidebarApps";
33import collapsableList from "components/collapsableList" ;
44import FileTree from "components/fileTree" ;
55import Sidebar from "components/sidebar" ;
6+ import { TerminalManager } from "components/terminal" ;
67import tile from "components/tile" ;
78import toast from "components/toast" ;
89import alert from "dialogs/alert" ;
@@ -27,6 +28,39 @@ const isAcodeTerminalPublicSafUri = (value = "") =>
2728const isTerminalSafUri = ( value = "" ) =>
2829 isTermuxSafUri ( value ) || isAcodeTerminalPublicSafUri ( value ) ;
2930
31+ const getTerminalPaths = ( ) => {
32+ const packageName = window . BuildInfo ?. packageName || "com.foxdebug.acode" ;
33+ const dataDir = `/data/user/0/${ packageName } ` ;
34+ const alpineRoot = `${ dataDir } /files/alpine` ;
35+ const publicDir = `${ dataDir } /files/public` ;
36+ return { alpineRoot, publicDir, dataDir } ;
37+ } ;
38+
39+ const isTerminalAccessiblePath = ( url = "" ) => {
40+ if ( isAcodeTerminalPublicSafUri ( url ) ) return true ;
41+ const { alpineRoot, publicDir } = getTerminalPaths ( ) ;
42+ const cleanUrl = url . replace ( / ^ f i l e : \/ \/ / , "" ) ;
43+ if ( cleanUrl . startsWith ( alpineRoot ) || cleanUrl . startsWith ( publicDir ) ) {
44+ return true ;
45+ }
46+ return false ;
47+ } ;
48+
49+ const convertToProotPath = ( url = "" ) => {
50+ const { alpineRoot, publicDir } = getTerminalPaths ( ) ;
51+ if ( isAcodeTerminalPublicSafUri ( url ) ) {
52+ return "/public" ;
53+ }
54+ const cleanUrl = url . replace ( / ^ f i l e : \/ \/ / , "" ) ;
55+ if ( cleanUrl . startsWith ( publicDir ) ) {
56+ return cleanUrl . replace ( publicDir , "/public" ) ;
57+ }
58+ if ( cleanUrl . startsWith ( alpineRoot ) ) {
59+ return cleanUrl . replace ( alpineRoot , "" ) || "/" ;
60+ }
61+ return cleanUrl ;
62+ } ;
63+
3064/**
3165 * @typedef {import('../components/collapsableList').Collapsible } Collapsible
3266 */
@@ -311,14 +345,34 @@ async function handleContextmenu(type, url, name, $target) {
311345 }
312346
313347 options . push ( NEW_FILE , NEW_FOLDER , OPEN_FOLDER , INSERT_FILE ) ;
348+
349+ if ( isTerminalAccessiblePath ( url ) ) {
350+ const OPEN_IN_TERMINAL = [
351+ "open-in-terminal" ,
352+ strings [ "open in terminal" ] || "Open in Terminal" ,
353+ "licons terminal" ,
354+ ] ;
355+ options . push ( OPEN_IN_TERMINAL ) ;
356+ }
314357 } else if ( type === "root" ) {
315358 options = [ ] ;
316359
317360 if ( clipBoard . url != null ) {
318361 options . push ( PASTE ) ;
319362 }
320363
321- options . push ( NEW_FILE , NEW_FOLDER , INSERT_FILE , CLOSE_FOLDER ) ;
364+ options . push ( NEW_FILE , NEW_FOLDER , INSERT_FILE ) ;
365+
366+ if ( isTerminalAccessiblePath ( url ) ) {
367+ const OPEN_IN_TERMINAL = [
368+ "open-in-terminal" ,
369+ strings [ "open in terminal" ] || "Open in Terminal" ,
370+ "licons terminal" ,
371+ ] ;
372+ options . push ( OPEN_IN_TERMINAL ) ;
373+ }
374+
375+ options . push ( CLOSE_FOLDER ) ;
322376 }
323377
324378 if ( clipBoard . action ) options . push ( CANCEL ) ;
@@ -378,6 +432,9 @@ function execOperation(type, action, url, $target, name) {
378432
379433 case "install-plugin" :
380434 return installPlugin ( ) ;
435+
436+ case "open-in-terminal" :
437+ return openInTerminal ( ) ;
381438 }
382439
383440 async function installPlugin ( ) {
@@ -396,6 +453,23 @@ function execOperation(type, action, url, $target, name) {
396453 }
397454 }
398455
456+ async function openInTerminal ( ) {
457+ try {
458+ const prootPath = convertToProotPath ( url ) ;
459+ const terminal = await TerminalManager . createTerminal ( {
460+ name : `Terminal - ${ name } ` ,
461+ render : true ,
462+ } ) ;
463+ if ( terminal ?. component ) {
464+ terminal . component . write ( `cd ${ JSON . stringify ( prootPath ) } \n` ) ;
465+ Sidebar . hide ( ) ;
466+ }
467+ } catch ( error ) {
468+ console . error ( "Failed to open terminal:" , error ) ;
469+ toast ( strings [ "error" ] || "Error" ) ;
470+ }
471+ }
472+
399473 async function deleteFile ( ) {
400474 const msg = strings [ "delete entry" ] . replace ( "{name}" , name ) ;
401475 const confirmation = await confirm ( strings . warning , msg ) ;
0 commit comments