1
0
mirror of https://git.tuxpa.in/a/code-server.git synced 2024-12-28 21:25:25 +00:00

Implement endpoint for getting recent directories

This commit is contained in:
Asher 2020-02-18 14:13:22 -06:00
parent 16bcf59cb0
commit 8793110941
No known key found for this signature in database
GPG Key ID: D63C1EF81242354A
6 changed files with 89 additions and 11 deletions

View File

@ -10,8 +10,17 @@ body {
background: #272727;
color: #f4f4f4;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol";
font-family:
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
Roboto,
Helvetica,
Arial,
sans-serif,
"Apple Color Emoji",
"Segoe UI Emoji",
"Segoe UI Symbol";
overflow: hidden;
}

View File

@ -33,8 +33,11 @@ export interface SessionResponse {
}
export interface RecentResponse {
readonly recent: ReadonlyArray<Application>
readonly running: ReadonlyArray<Application>
readonly paths: string[]
}
export interface RunningResponse {
readonly applications: ReadonlyArray<Application>
}
export interface HealthRequest {

View File

@ -19,6 +19,7 @@ export enum ApiEndpoint {
applications = "/applications",
recent = "/recent",
run = "/run",
running = "/running",
session = "/session",
status = "/status",
}

View File

@ -1,13 +1,17 @@
import { field, logger } from "@coder/logger"
import * as cp from "child_process"
import * as fs from "fs-extra"
import * as http from "http"
import * as net from "net"
import * as path from "path"
import * as url from "url"
import * as WebSocket from "ws"
import {
Application,
ApplicationsResponse,
ClientMessage,
RecentResponse,
RunningResponse,
ServerMessage,
SessionError,
SessionResponse,
@ -22,6 +26,12 @@ interface ServerSession {
readonly app: Application
}
interface VsRecents {
[key: string]: (string | object)[]
}
type VsSettings = [string, string][]
/**
* API HTTP provider.
*/
@ -29,7 +39,11 @@ export class ApiHttpProvider extends HttpProvider {
private readonly ws = new WebSocket.Server({ noServer: true })
private readonly sessions = new Map<string, ServerSession>()
public constructor(options: HttpProviderOptions, private readonly server: HttpServer) {
public constructor(
options: HttpProviderOptions,
private readonly server: HttpServer,
private readonly dataDir?: string,
) {
super(options)
}
@ -60,6 +74,11 @@ export class ApiHttpProvider extends HttpProvider {
return {
content: await this.recent(),
} as HttpResponse<RecentResponse>
case ApiEndpoint.running:
this.ensureMethod(request)
return {
content: await this.running(),
} as HttpResponse<RunningResponse>
}
return undefined
}
@ -280,12 +299,58 @@ export class ApiHttpProvider extends HttpProvider {
}
/**
* Return recent sessions.
* Return VS Code's recent paths.
*/
public async recent(): Promise<RecentResponse> {
try {
if (!this.dataDir) {
throw new Error("data directory is not set")
}
const state: VsSettings = JSON.parse(await fs.readFile(path.join(this.dataDir, "User/state/global.json"), "utf8"))
const setting = Array.isArray(state) && state.find((item) => item[0] === "recently.opened")
if (!setting) {
throw new Error("settings appear malformed")
}
const paths: { [key: string]: Promise<string> } = {}
Object.values(JSON.parse(setting[1]) as VsRecents).forEach((recents) => {
recents
.filter((recent) => typeof recent === "string")
.forEach((recent) => {
try {
const pathname = url.parse(recent as string).pathname
if (pathname && !paths[pathname]) {
paths[pathname] = new Promise<string>((resolve) => {
fs.stat(pathname)
.then(() => resolve(pathname))
.catch(() => resolve())
})
}
} catch (error) {
logger.debug("invalid path", field("path", recent))
}
})
})
return {
paths: await Promise.all(Object.values(paths)),
}
} catch (error) {
if (error.code !== "ENOENT") {
throw error
}
}
return { paths: [] }
}
/**
* Return running sessions.
*/
public async running(): Promise<RunningResponse> {
return {
recent: [], // TODO
running: Array.from(this.sessions).map(([sessionId, session]) => ({
applications: Array.from(this.sessions).map(([sessionId, session]) => ({
...session.app,
sessionId,
})),

View File

@ -90,14 +90,14 @@ export class MainHttpProvider extends HttpProvider {
}
public async getRoot(route: Route): Promise<HttpResponse> {
const recent = await this.api.recent()
const running = await this.api.running()
const apps = await this.api.installedApplications()
const response = await this.getUtf8Resource(this.rootPath, "src/browser/pages/home.html")
response.content = response.content
.replace(/{{COMMIT}}/g, this.options.commit)
.replace(/{{BASE}}/g, this.base(route))
.replace(/{{UPDATE:NAME}}/, await this.getUpdate())
.replace(/{{APP_LIST:RUNNING}}/, this.getAppRows(recent.running))
.replace(/{{APP_LIST:RUNNING}}/, this.getAppRows(running.applications))
.replace(
/{{APP_LIST:EDITORS}}/,
this.getAppRows(apps.filter((app) => app.categories && app.categories.includes("Editor"))),

View File

@ -44,7 +44,7 @@ const main = async (args: Args): Promise<void> => {
}
const httpServer = new HttpServer(options)
const api = httpServer.registerHttpProvider("/api", ApiHttpProvider, httpServer)
const api = httpServer.registerHttpProvider("/api", ApiHttpProvider, httpServer, args["user-data-dir"])
const update = httpServer.registerHttpProvider("/update", UpdateHttpProvider, !args["disable-updates"])
httpServer.registerHttpProvider("/vscode", VscodeHttpProvider, args)
httpServer.registerHttpProvider("/login", LoginHttpProvider)