Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbed37b4

Browse files
authored
feat: use wildcard url for local links in the web terminal (#6070)
1 parent135a4d8 commitbed37b4

File tree

4 files changed

+123
-21
lines changed

4 files changed

+123
-21
lines changed

‎site/src/components/PortForwardButton/PortForwardButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export interface PortForwardButtonProps {
2626
agentId:string
2727
}
2828

29-
constportForwardURL=(
29+
exportconstportForwardURL=(
3030
host:string,
3131
port:number,
3232
agentName:string,

‎site/src/components/TemplateVersionEditor/TemplateVersionEditor.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ export const TemplateVersionEditor: FC<TemplateVersionEditorProps> = ({
293293
</div>
294294

295295
<divclassName={styles.editorPane}>
296-
<divclassName={styles.editor}>
296+
<divclassName={styles.editor}data-chromatic="ignore">
297297
{activeFile ?(
298298
<MonacoEditor
299299
value={activeFile?.content}

‎site/src/pages/TerminalPage/TerminalPage.tsx

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import{makeStyles}from"@material-ui/core/styles"
22
import{useMachine}from"@xstate/react"
3+
import{portForwardURL}from"components/PortForwardButton/PortForwardButton"
34
import{Stack}from"components/Stack/Stack"
4-
import{FC,useEffect,useRef,useState}from"react"
5+
import{FC,useCallback,useEffect,useRef,useState}from"react"
56
import{Helmet}from"react-helmet-async"
67
import{useNavigate,useParams,useSearchParams}from"react-router-dom"
78
import{colors}from"theme/colors"
@@ -95,9 +96,55 @@ const TerminalPage: FC<
9596
workspaceAgentError,
9697
workspaceAgent,
9798
websocketError,
99+
applicationsHost,
98100
}=terminalState.context
99101
constreloading=useReloading(isDisconnected)
100102

103+
// handleWebLink handles opening of URLs in the terminal!
104+
consthandleWebLink=useCallback(
105+
(uri:string)=>{
106+
if(!workspaceAgent||!workspace||!username||!applicationsHost){
107+
return
108+
}
109+
110+
constopen=(uri:string)=>{
111+
// Copied from: https://github.com/xtermjs/xterm.js/blob/master/addons/xterm-addon-web-links/src/WebLinksAddon.ts#L23
112+
constnewWindow=window.open()
113+
if(newWindow){
114+
try{
115+
newWindow.opener=null
116+
}catch{
117+
// no-op, Electron can throw
118+
}
119+
newWindow.location.href=uri
120+
}else{
121+
console.warn("Opening link blocked as opener could not be cleared")
122+
}
123+
}
124+
125+
try{
126+
consturl=newURL(uri)
127+
constlocalHosts=["0.0.0.0","127.0.0.1","localhost"]
128+
if(!localHosts.includes(url.hostname)){
129+
open(uri)
130+
return
131+
}
132+
open(
133+
portForwardURL(
134+
applicationsHost,
135+
parseInt(url.port),
136+
workspaceAgent.name,
137+
workspace,
138+
username,
139+
),
140+
)
141+
}catch(ex){
142+
open(uri)
143+
}
144+
},
145+
[workspaceAgent,workspace,username,applicationsHost],
146+
)
147+
101148
// Create the terminal!
102149
useEffect(()=>{
103150
if(!xtermRef.current){
@@ -116,7 +163,11 @@ const TerminalPage: FC<
116163
constfitAddon=newFitAddon()
117164
setFitAddon(fitAddon)
118165
terminal.loadAddon(fitAddon)
119-
terminal.loadAddon(newWebLinksAddon())
166+
terminal.loadAddon(
167+
newWebLinksAddon((_,uri)=>{
168+
handleWebLink(uri)
169+
}),
170+
)
120171
terminal.onData((data)=>{
121172
sendEvent({
122173
type:"WRITE",
@@ -145,7 +196,7 @@ const TerminalPage: FC<
145196
window.removeEventListener("resize",listener)
146197
terminal.dispose()
147198
}
148-
},[renderer,sendEvent,xtermRef])
199+
},[renderer,sendEvent,xtermRef,handleWebLink])
149200

150201
// Triggers the initial terminal connection using
151202
// the reconnection token and workspace name found

‎site/src/xServices/terminal/terminalXService.ts

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export interface TerminalContext {
1010
workspaceAgentError?:Error|unknown
1111
websocket?:WebSocket
1212
websocketError?:Error|unknown
13+
applicationsHost?:string
1314

1415
// Assigned by connecting!
1516
// The workspace agent is entirely optional. If the agent is omitted the
@@ -47,6 +48,9 @@ export const terminalMachine =
4748
getWorkspace:{
4849
data:TypesGen.Workspace
4950
}
51+
getApplicationsHost:{
52+
data:TypesGen.AppHostResponse
53+
}
5054
getWorkspaceAgent:{
5155
data:TypesGen.WorkspaceAgent
5256
}
@@ -55,24 +59,61 @@ export const terminalMachine =
5559
}
5660
},
5761
},
58-
initial:"gettingWorkspace",
62+
initial:"setup",
5963
states:{
60-
gettingWorkspace:{
61-
invoke:{
62-
src:"getWorkspace",
63-
id:"getWorkspace",
64-
onDone:[
65-
{
66-
actions:["assignWorkspace","clearWorkspaceError"],
67-
target:"gettingWorkspaceAgent",
64+
setup:{
65+
type:"parallel",
66+
states:{
67+
getApplicationsHost:{
68+
initial:"gettingApplicationsHost",
69+
states:{
70+
gettingApplicationsHost:{
71+
invoke:{
72+
src:"getApplicationsHost",
73+
id:"getApplicationsHost",
74+
onDone:{
75+
actions:[
76+
"assignApplicationsHost",
77+
"clearApplicationsHostError",
78+
],
79+
target:"success",
80+
},
81+
},
82+
},
83+
success:{
84+
type:"final",
85+
},
6886
},
69-
],
70-
onError:[
71-
{
72-
actions:"assignWorkspaceError",
73-
target:"disconnected",
87+
},
88+
getWorkspace:{
89+
initial:"gettingWorkspace",
90+
states:{
91+
gettingWorkspace:{
92+
invoke:{
93+
src:"getWorkspace",
94+
id:"getWorkspace",
95+
onDone:[
96+
{
97+
actions:["assignWorkspace","clearWorkspaceError"],
98+
target:"success",
99+
},
100+
],
101+
onError:[
102+
{
103+
actions:"assignWorkspaceError",
104+
target:"success",
105+
},
106+
],
107+
},
108+
},
109+
success:{
110+
type:"final",
111+
},
74112
},
75-
],
113+
},
114+
},
115+
onDone:{
116+
target:"gettingWorkspaceAgent",
76117
},
77118
},
78119
gettingWorkspaceAgent:{
@@ -129,7 +170,7 @@ export const terminalMachine =
129170
on:{
130171
CONNECT:{
131172
actions:"assignConnection",
132-
target:"gettingWorkspace",
173+
target:"gettingWorkspaceAgent",
133174
},
134175
},
135176
},
@@ -146,6 +187,9 @@ export const terminalMachine =
146187
context.workspaceName,
147188
)
148189
},
190+
getApplicationsHost:async()=>{
191+
returnAPI.getApplicationsHost()
192+
},
149193
getWorkspaceAgent:async(context)=>{
150194
if(!context.workspace||!context.workspaceName){
151195
thrownewError("workspace or workspace name is not set")
@@ -218,6 +262,13 @@ export const terminalMachine =
218262
...context,
219263
workspaceError:undefined,
220264
})),
265+
assignApplicationsHost:assign({
266+
applicationsHost:(_,{ data})=>data.host,
267+
}),
268+
clearApplicationsHostError:assign((context)=>({
269+
...context,
270+
applicationsHostError:undefined,
271+
})),
221272
assignWorkspaceAgent:assign({
222273
workspaceAgent:(_,event)=>event.data,
223274
}),

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp