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

Commit4ef7106

Browse files
committed
Active Windows mode on Windows
1 parent3e1a0a4 commit4ef7106

File tree

8 files changed

+63
-71
lines changed

8 files changed

+63
-71
lines changed

‎agent/agent.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,8 @@ func (a *agent) handleReconnectingPTY(ctx context.Context, rawID string, conn ne
484484
}
485485
a.reconnectingPTYs.Store(id,rpty)
486486
gofunc() {
487+
// CommandContext isn't respected for Windows PTYs right now,
488+
// so we need to manually track the lifecycle.
487489
// When the context has been completed either:
488490
// 1. The timeout completed.
489491
// 2. The parent context was canceled.

‎site/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"react-dom":"17.0.2",
4242
"react-router-dom":"6.3.0",
4343
"swr":"1.2.2",
44+
"uuid":"^8.3.2",
4445
"xstate":"4.31.0",
4546
"xterm":"^4.18.0",
4647
"xterm-addon-fit":"^0.5.0",
@@ -65,6 +66,7 @@
6566
"@types/react":"17.0.44",
6667
"@types/react-dom":"17.0.16",
6768
"@types/superagent":"4.1.15",
69+
"@types/uuid":"^8.3.4",
6870
"@typescript-eslint/eslint-plugin":"5.21.0",
6971
"@typescript-eslint/parser":"5.21.0",
7072
"@xstate/cli":"0.1.7",

‎site/src/api/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export interface WorkspaceResource {
8787
exportinterfaceWorkspaceAgent{
8888
id:string
8989
name:string
90+
operating_system:string
9091
}
9192

9293
exportinterfaceAPIKeyResponse{

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

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import{waitFor}from"@testing-library/react"
2-
importcryptofrom"crypto"
32
import"jest-canvas-mock"
43
importWSfrom"jest-websocket-mock"
54
import{rest}from"msw"
@@ -25,12 +24,6 @@ Object.defineProperty(window, "matchMedia", {
2524
})),
2625
})
2726

28-
Object.defineProperty(window,"crypto",{
29-
value:{
30-
randomUUID:()=>crypto.randomUUID(),
31-
},
32-
})
33-
3427
Object.defineProperty(window,"TextEncoder",{
3528
value:TextEncoder,
3629
})

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

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { makeStyles } from "@material-ui/core/styles"
22
import{useMachine}from"@xstate/react"
33
importReactfrom"react"
44
import{useLocation,useNavigate,useParams}from"react-router-dom"
5+
import{v4asuuidv4}from"uuid"
56
import*asXTermfrom"xterm"
67
import{FitAddon}from"xterm-addon-fit"
78
import{WebLinksAddon}from"xterm-addon-web-links"
@@ -16,14 +17,6 @@ export const Language = {
1617
websocketErrorMessagePrefix:"WebSocket failed: ",
1718
}
1819

19-
// TypeScript doesn't have the randomUUID type on Crypto yet. See:
20-
// https://github.com/denoland/deno/issues/12754#issuecomment-970386235
21-
declare global{
22-
interfaceCrypto{
23-
randomUUID:()=>string
24-
}
25-
}
26-
2720
exportconstTerminalPage:React.FC<{
2821
readonlyrenderer?:XTerm.RendererType
2922
}>=({ renderer})=>{
@@ -39,13 +32,14 @@ export const TerminalPage: React.FC<{
3932
// a round-trip, and must be a UUIDv4.
4033
const[reconnectionToken]=React.useState<string>(()=>{
4134
constsearch=newURLSearchParams(location.search)
42-
letreconnect=search.get("reconnect")
43-
if(reconnect===null){
44-
reconnect=crypto.randomUUID()
45-
}
46-
returnreconnect
35+
returnsearch.get("reconnect")??uuidv4()
4736
})
4837
const[terminalState,sendEvent]=useMachine(terminalMachine,{
38+
context:{
39+
reconnection:reconnectionToken,
40+
workspaceName:workspace,
41+
username:username,
42+
},
4943
actions:{
5044
readMessage:(_,event)=>{
5145
if(typeofevent.data==="string"){
@@ -59,6 +53,8 @@ export const TerminalPage: React.FC<{
5953
},
6054
})
6155
constisConnected=terminalState.matches("connected")
56+
const{ organizationsError, workspaceError, workspaceAgentError, workspaceAgent, websocketError}=
57+
terminalState.context
6258

6359
// Create the terminal!
6460
React.useEffect(()=>{
@@ -125,13 +121,7 @@ export const TerminalPage: React.FC<{
125121
replace:true,
126122
},
127123
)
128-
sendEvent({
129-
type:"CONNECT",
130-
reconnection:reconnectionToken,
131-
workspaceName:workspace,
132-
username:username,
133-
})
134-
},[location.search,navigate,workspace,username,sendEvent,reconnectionToken])
124+
},[location.search,navigate,reconnectionToken])
135125

136126
// Apply terminal options based on connection state.
137127
React.useEffect(()=>{
@@ -150,17 +140,17 @@ export const TerminalPage: React.FC<{
150140
terminal.options={
151141
disableStdin:true,
152142
}
153-
if(terminalState.context.organizationsErrorinstanceofError){
154-
terminal.writeln(Language.organizationsErrorMessagePrefix+terminalState.context.organizationsError.message)
143+
if(organizationsErrorinstanceofError){
144+
terminal.writeln(Language.organizationsErrorMessagePrefix+organizationsError.message)
155145
}
156-
if(terminalState.context.workspaceErrorinstanceofError){
157-
terminal.writeln(Language.workspaceErrorMessagePrefix+terminalState.context.workspaceError.message)
146+
if(workspaceErrorinstanceofError){
147+
terminal.writeln(Language.workspaceErrorMessagePrefix+workspaceError.message)
158148
}
159-
if(terminalState.context.workspaceAgentErrorinstanceofError){
160-
terminal.writeln(Language.workspaceAgentErrorMessagePrefix+terminalState.context.workspaceAgentError.message)
149+
if(workspaceAgentErrorinstanceofError){
150+
terminal.writeln(Language.workspaceAgentErrorMessagePrefix+workspaceAgentError.message)
161151
}
162-
if(terminalState.context.websocketErrorinstanceofError){
163-
terminal.writeln(Language.websocketErrorMessagePrefix+terminalState.context.websocketError.message)
152+
if(websocketErrorinstanceofError){
153+
terminal.writeln(Language.websocketErrorMessagePrefix+websocketError.message)
164154
}
165155
return
166156
}
@@ -174,6 +164,7 @@ export const TerminalPage: React.FC<{
174164
terminal.focus()
175165
terminal.options={
176166
disableStdin:false,
167+
windowsMode:workspaceAgent?.operating_system==="windows",
177168
}
178169

179170
// Update the terminal size post-fit.
@@ -185,10 +176,11 @@ export const TerminalPage: React.FC<{
185176
},
186177
})
187178
},[
188-
terminalState.context.workspaceError,
189-
terminalState.context.organizationsError,
190-
terminalState.context.workspaceAgentError,
191-
terminalState.context.websocketError,
179+
workspaceError,
180+
organizationsError,
181+
workspaceAgentError,
182+
websocketError,
183+
workspaceAgent,
192184
terminal,
193185
fitAddon,
194186
isConnected,
@@ -199,7 +191,9 @@ export const TerminalPage: React.FC<{
199191
<>
200192
{/* This overlay makes it more obvious that the terminal is disconnected. */}
201193
{/* It's nice for situations where Coder restarts, and they are temporarily disconnected. */}
202-
<divclassName={`${styles.overlay}${isConnected ?"connected" :""}`}/>
194+
<divclassName={`${styles.overlay}${isConnected ?"connected" :""}`}>
195+
<span>Disconnected</span>
196+
</div>
203197
<divclassName={styles.terminal}ref={xtermRef}data-testid="terminal"/>
204198
</>
205199
)
@@ -214,6 +208,12 @@ const useStyles = makeStyles(() => ({
214208
bottom:0,
215209
right:0,
216210
zIndex:1,
211+
alignItems:"center",
212+
justifyContent:"center",
213+
display:"flex",
214+
color:"white",
215+
fontFamily:MONOSPACE_FONT_FAMILY,
216+
fontSize:18,
217217
backgroundColor:"rgba(0, 0, 0, 0.5)",
218218
"&.connected":{
219219
opacity:0,

‎site/src/testHelpers/entities.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ export const MockWorkspace: Workspace = {
102102
exportconstMockWorkspaceAgent:WorkspaceAgent={
103103
id:"test-workspace-agent",
104104
name:"a-workspace-agent",
105+
operating_system:"linux",
105106
}
106107

107108
exportconstMockWorkspaceResource:WorkspaceResource={

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

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export const terminalMachine =
4848
},
4949
},
5050
id:"terminalState",
51-
initial:"disconnected",
51+
initial:"gettingOrganizations",
5252
states:{
5353
gettingOrganizations:{
5454
invoke:{
@@ -150,13 +150,13 @@ export const terminalMachine =
150150
{
151151
services:{
152152
getOrganizations:API.getOrganizations,
153-
getWorkspace:async(context:TerminalContext)=>{
153+
getWorkspace:async(context)=>{
154154
if(!context.organizations||!context.workspaceName){
155155
thrownewError("organizations or workspace not set")
156156
}
157157
returnAPI.getWorkspace(context.organizations[0].id,context.username,context.workspaceName)
158158
},
159-
getWorkspaceAgent:async(context:TerminalContext)=>{
159+
getWorkspaceAgent:async(context)=>{
160160
if(!context.workspace||!context.workspaceName){
161161
thrownewError("workspace or workspace name is not set")
162162
}
@@ -167,38 +167,29 @@ export const terminalMachine =
167167
constagentName=workspaceNameParts[1]
168168

169169
constresources=awaitAPI.getWorkspaceResources(context.workspace.latest_build.id)
170-
for(leti=0;i<resources.length;i++){
171-
constresource=resources[i]
172-
if(!resource.agents){
173-
continue
174-
}
175-
if(resource.agents.length<=0){
176-
continue
177-
}
178-
if(!agentName){
179-
returnresource.agents[0]
180-
}
181-
for(leta=0;a<resource.agents.length;a++){
182-
constagent=resource.agents[a]
183-
if(agent.name!==agentName){
184-
continue
170+
171+
constagent=resources
172+
.map((resource)=>{
173+
if(!resource.agents||resource.agents.length<1){
174+
return
185175
}
186-
returnagent
187-
}
176+
if(!agentName){
177+
returnresource.agents[0]
178+
}
179+
returnresource.agents.find((agent)=>agent.name===agentName)
180+
})
181+
.filter((a)=>a)[0]
182+
if(!agent){
183+
thrownewError("no agent found with id")
188184
}
189-
thrownewError("noagent found with id")
185+
returnagent
190186
},
191-
connect:(context:TerminalContext)=>(send)=>{
187+
connect:(context)=>(send)=>{
192188
returnnewPromise<WebSocket>((resolve,reject)=>{
193189
if(!context.workspaceAgent){
194190
returnreject("workspace agent is not set")
195191
}
196-
letproto=location.protocol
197-
if(proto==="https:"){
198-
proto="wss:"
199-
}else{
200-
proto="ws:"
201-
}
192+
constproto=location.protocol==="https:" ?"wss:" :"ws:"
202193
constsocket=newWebSocket(
203194
`${proto}//${location.host}/api/v2/workspaceagents/${context.workspaceAgent.id}/pty?reconnect=${context.reconnection}`,
204195
)
@@ -275,9 +266,6 @@ export const terminalMachine =
275266
}
276267
context.websocket.send(newTextEncoder().encode(JSON.stringify(event.request)))
277268
},
278-
readMessage:()=>{
279-
// Override this with the terminal writer!
280-
},
281269
disconnect:(context:TerminalContext)=>{
282270
// Code 1000 is a successful exit!
283271
context.websocket?.close(1000)

‎site/yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3194,6 +3194,11 @@
31943194
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d"
31953195
integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==
31963196

3197+
"@types/uuid@^8.3.4":
3198+
version "8.3.4"
3199+
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc"
3200+
integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==
3201+
31973202
"@types/webpack-env@^1.16.0":
31983203
version "1.16.3"
31993204
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.16.3.tgz#b776327a73e561b71e7881d0cd6d34a1424db86a"

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp