Skip to content

Commit 8793110

Browse files
committed
Implement endpoint for getting recent directories
1 parent 16bcf59 commit 8793110

File tree

6 files changed

+89
-11
lines changed

6 files changed

+89
-11
lines changed

src/browser/pages/global.css

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,17 @@ body {
1010
background: #272727;
1111
color: #f4f4f4;
1212
margin: 0;
13-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji",
14-
"Segoe UI Emoji", "Segoe UI Symbol";
13+
font-family:
14+
-apple-system,
15+
BlinkMacSystemFont,
16+
"Segoe UI",
17+
Roboto,
18+
Helvetica,
19+
Arial,
20+
sans-serif,
21+
"Apple Color Emoji",
22+
"Segoe UI Emoji",
23+
"Segoe UI Symbol";
1524
overflow: hidden;
1625
}
1726

src/common/api.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@ export interface SessionResponse {
3333
}
3434

3535
export interface RecentResponse {
36-
readonly recent: ReadonlyArray<Application>
37-
readonly running: ReadonlyArray<Application>
36+
readonly paths: string[]
37+
}
38+
39+
export interface RunningResponse {
40+
readonly applications: ReadonlyArray<Application>
3841
}
3942

4043
export interface HealthRequest {

src/common/http.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export enum ApiEndpoint {
1919
applications = "/applications",
2020
recent = "/recent",
2121
run = "/run",
22+
running = "/running",
2223
session = "/session",
2324
status = "/status",
2425
}

src/node/app/api.ts

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import { field, logger } from "@coder/logger"
22
import * as cp from "child_process"
3+
import * as fs from "fs-extra"
34
import * as http from "http"
45
import * as net from "net"
6+
import * as path from "path"
7+
import * as url from "url"
58
import * as WebSocket from "ws"
69
import {
710
Application,
811
ApplicationsResponse,
912
ClientMessage,
1013
RecentResponse,
14+
RunningResponse,
1115
ServerMessage,
1216
SessionError,
1317
SessionResponse,
@@ -22,14 +26,24 @@ interface ServerSession {
2226
readonly app: Application
2327
}
2428

29+
interface VsRecents {
30+
[key: string]: (string | object)[]
31+
}
32+
33+
type VsSettings = [string, string][]
34+
2535
/**
2636
* API HTTP provider.
2737
*/
2838
export class ApiHttpProvider extends HttpProvider {
2939
private readonly ws = new WebSocket.Server({ noServer: true })
3040
private readonly sessions = new Map<string, ServerSession>()
3141

32-
public constructor(options: HttpProviderOptions, private readonly server: HttpServer) {
42+
public constructor(
43+
options: HttpProviderOptions,
44+
private readonly server: HttpServer,
45+
private readonly dataDir?: string,
46+
) {
3347
super(options)
3448
}
3549

@@ -60,6 +74,11 @@ export class ApiHttpProvider extends HttpProvider {
6074
return {
6175
content: await this.recent(),
6276
} as HttpResponse<RecentResponse>
77+
case ApiEndpoint.running:
78+
this.ensureMethod(request)
79+
return {
80+
content: await this.running(),
81+
} as HttpResponse<RunningResponse>
6382
}
6483
return undefined
6584
}
@@ -280,12 +299,58 @@ export class ApiHttpProvider extends HttpProvider {
280299
}
281300

282301
/**
283-
* Return recent sessions.
302+
* Return VS Code's recent paths.
284303
*/
285304
public async recent(): Promise<RecentResponse> {
305+
try {
306+
if (!this.dataDir) {
307+
throw new Error("data directory is not set")
308+
}
309+
310+
const state: VsSettings = JSON.parse(await fs.readFile(path.join(this.dataDir, "User/state/global.json"), "utf8"))
311+
const setting = Array.isArray(state) && state.find((item) => item[0] === "recently.opened")
312+
if (!setting) {
313+
throw new Error("settings appear malformed")
314+
}
315+
316+
const paths: { [key: string]: Promise<string> } = {}
317+
Object.values(JSON.parse(setting[1]) as VsRecents).forEach((recents) => {
318+
recents
319+
.filter((recent) => typeof recent === "string")
320+
.forEach((recent) => {
321+
try {
322+
const pathname = url.parse(recent as string).pathname
323+
if (pathname && !paths[pathname]) {
324+
paths[pathname] = new Promise<string>((resolve) => {
325+
fs.stat(pathname)
326+
.then(() => resolve(pathname))
327+
.catch(() => resolve())
328+
})
329+
}
330+
} catch (error) {
331+
logger.debug("invalid path", field("path", recent))
332+
}
333+
})
334+
})
335+
336+
return {
337+
paths: await Promise.all(Object.values(paths)),
338+
}
339+
} catch (error) {
340+
if (error.code !== "ENOENT") {
341+
throw error
342+
}
343+
}
344+
345+
return { paths: [] }
346+
}
347+
348+
/**
349+
* Return running sessions.
350+
*/
351+
public async running(): Promise<RunningResponse> {
286352
return {
287-
recent: [], // TODO
288-
running: Array.from(this.sessions).map(([sessionId, session]) => ({
353+
applications: Array.from(this.sessions).map(([sessionId, session]) => ({
289354
...session.app,
290355
sessionId,
291356
})),

src/node/app/app.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,14 @@ export class MainHttpProvider extends HttpProvider {
9090
}
9191

9292
public async getRoot(route: Route): Promise<HttpResponse> {
93-
const recent = await this.api.recent()
93+
const running = await this.api.running()
9494
const apps = await this.api.installedApplications()
9595
const response = await this.getUtf8Resource(this.rootPath, "src/browser/pages/home.html")
9696
response.content = response.content
9797
.replace(/{{COMMIT}}/g, this.options.commit)
9898
.replace(/{{BASE}}/g, this.base(route))
9999
.replace(/{{UPDATE:NAME}}/, await this.getUpdate())
100-
.replace(/{{APP_LIST:RUNNING}}/, this.getAppRows(recent.running))
100+
.replace(/{{APP_LIST:RUNNING}}/, this.getAppRows(running.applications))
101101
.replace(
102102
/{{APP_LIST:EDITORS}}/,
103103
this.getAppRows(apps.filter((app) => app.categories && app.categories.includes("Editor"))),

src/node/entry.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const main = async (args: Args): Promise<void> => {
4444
}
4545

4646
const httpServer = new HttpServer(options)
47-
const api = httpServer.registerHttpProvider("/api", ApiHttpProvider, httpServer)
47+
const api = httpServer.registerHttpProvider("/api", ApiHttpProvider, httpServer, args["user-data-dir"])
4848
const update = httpServer.registerHttpProvider("/update", UpdateHttpProvider, !args["disable-updates"])
4949
httpServer.registerHttpProvider("/vscode", VscodeHttpProvider, args)
5050
httpServer.registerHttpProvider("/login", LoginHttpProvider)

0 commit comments

Comments
 (0)