Skip to content

Commit

Permalink
add types into the sdk
Browse files Browse the repository at this point in the history
  • Loading branch information
JoelEinbinder committed Mar 11, 2024
1 parent 027af82 commit d5f123c
Show file tree
Hide file tree
Showing 23 changed files with 104 additions and 52 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,23 @@ Use `⇧⌘P` to open the command menu. Terminal apps can also add their own act
Don't know how to quit vim? With `edit`, you get the full monaco text editor right in your terminal. And you can just click the x to close.

<img src="screenshots/edit.png" width="487">

## Creating Rich Apps

```js
// backend.js
const { display } = require('snail-sdk');
display(require.resolve('./web.ts'));
```

```ts
// web.ts
import { setHeight } from 'snail-sdk/web';
document.body.append('Hello World!');
setHeight(document.body.offsetHeight);
```

```
> node backend.js
Hello World!
```
8 changes: 1 addition & 7 deletions host/ShellHost.d.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
export type MenuItem = {
title?: string;
enabled?: boolean;
checked?: boolean;
callback?: () => void;
submenu?: MenuItem[];
};
import type { MenuItem } from '../slug/sdk/web';

export interface ShellHost {
obtainWebSocketId(): number;
Expand Down
2 changes: 1 addition & 1 deletion slug/apps/edit/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference path="../../iframe/types.d.ts" />
import * as snail from '../../sdk/web';
/// <reference path="../../../node_modules/monaco-editor/monaco.d.ts" />
import './index.css';
import { RPC } from '../../sdk/rpc-js';
Expand Down
2 changes: 1 addition & 1 deletion slug/apps/html/html.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference path="../../iframe/types.d.ts" />
import * as snail from '../../sdk/web';
const {args} = await snail.waitForMessage<{
args: string[],
}>();
Expand Down
2 changes: 1 addition & 1 deletion slug/apps/kang/web.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference path="../../iframe/types.d.ts" />
import * as snail from '../../sdk/web';
import './web.css';
import { RPC } from '../../sdk/rpc-js';
import { Editor } from '../../editor/js/editor';
Expand Down
2 changes: 1 addition & 1 deletion slug/apps/logbook/web.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference path="../../iframe/types.d.ts" />
import * as snail from '../../sdk/web';
import { RPC } from '../../sdk/rpc-js';
import { LogBookView } from './LogBookView';
snail.setIsFullscreen(true);
Expand Down
2 changes: 1 addition & 1 deletion slug/apps/ls/web.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference path="../../iframe/types.d.ts" />
import * as snail from '../../sdk/web';
import './web.css';
import {iconPathForPath, looksLikeImageOrVideo} from '../../icon_service/iconService';
import {DataGrid} from '../../datagrid/datagrid';
Expand Down
2 changes: 1 addition & 1 deletion slug/apps/reconnect/web.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference path="../../iframe/types.d.ts" />
import * as snail from '../../sdk/web';
import type { Metadata } from '../../shell/metadata';
import './reconnect.css';

Expand Down
2 changes: 1 addition & 1 deletion slug/apps/show/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
///<reference path="../../iframe/types.d.ts" />
import * as snail from '../../sdk/web';
import { JoelEvent } from '../../cdp-ui/JoelEvent';
import { renderExcalidraw } from './excalidraw';
import './index.css';
Expand Down
2 changes: 1 addition & 1 deletion slug/apps/top/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference path="../../iframe/types.d.ts" />
import * as snail from '../../sdk/web';
import './index.css';

window.onresize = updateSize;
Expand Down
2 changes: 1 addition & 1 deletion slug/apps/xkcd/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
///<reference path="../../iframe/types.d.ts" />
import * as snail from '../../sdk/web';
import './index.css';
window.onresize = updateSize;
function updateSize() {
Expand Down
2 changes: 1 addition & 1 deletion slug/datagrid/datagrid.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference path="../iframe/types.d.ts" />
import * as snail from '../sdk/web';
import './datagrid.css';

export interface ColumnDelegate<T extends object> {
Expand Down
2 changes: 1 addition & 1 deletion slug/debugger/TargetManager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference path="../iframe/types.d.ts" />
import * as snail from '../sdk/web';
import { RPC, type Transport} from '../protocol/RPC-ts';
import type { Protocol } from '../../src/protocol';

Expand Down
1 change: 1 addition & 0 deletions slug/debugger/elements/ChromiumDOM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { ChromiumSession } from '../TargetManager';
import type { Protocol } from '../../../src/protocol';
import { JoelEvent } from '../../cdp-ui/JoelEvent';
import { RPC, type Transport} from '../../protocol/RPC-ts';
import * as snail from '../../sdk/web';

export interface DOM {
documentNodeForFrame(frameUUID: string|undefined, listener: {
Expand Down
2 changes: 1 addition & 1 deletion slug/debugger/web.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference path="../iframe/types.d.ts" />
import * as snail from '../sdk/web';
import {TargetManager} from './TargetManager';
import { Console } from './Console';
import { Elements } from './elements/Elements';
Expand Down
1 change: 0 additions & 1 deletion slug/iframe/error.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/// <reference path="./types.d.ts" />
const error = atob(window.snail_error);
document.body.textContent = error;
snail.setToJSON({ error });
Expand Down
31 changes: 16 additions & 15 deletions slug/iframe/iframe.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/// <reference path="./types.d.ts" />
//@ts-check
const messages = [];
const callbacks = [];
/** @type {import('../../src/shortcutParser').ParsedShortcut[]} */
Expand All @@ -14,8 +14,8 @@ async function waitForMessage() {
function sendMessageToParent(message) {
if (window.parent && window.parent !== window)
window.parent.postMessage(message, '*');
else if (window.electronAPI)
window.electronAPI.notify(message);
else if (window['electronAPI'])
window['electronAPI'].notify(message);
else if (window['webkit'])
window['webkit'].messageHandlers.wkMessage.postMessage(message);
else
Expand All @@ -36,8 +36,8 @@ if (window.parent && window.parent !== window) {
return;
onMessage(event.data);
});
} else if (window.electronAPI) {
window.electronAPI.onEvent('postMessage', onMessage);
} else if (window['electronAPI']) {
window['electronAPI'].onEvent('postMessage', onMessage);
} else if (window['webkit']) {
window['webkit_callback'] = onMessage;
} else {
Expand Down Expand Up @@ -120,7 +120,7 @@ window.addEventListener('keydown', event => {
event.stopImmediatePropagation();
}
} else {
if (event.key === 'Shift' || event.key === 'Control' && event.key === 'Alt' || event.key === 'Meta')
if (event.key === 'Shift' || event.key === 'Control' || event.key === 'Alt' || event.key === 'Meta')
return;
chording = false;
sendMessageToParent({method: 'chordPressed', params: {
Expand Down Expand Up @@ -181,10 +181,10 @@ window.addEventListener('keydown', event => {
});

/**
* @param {HTMLElement} target
* @param {EventTarget|null} target
*/
function isEditing(target) {
if (!target)
if (!target || !(target instanceof HTMLElement))
return false;
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA')
return true;
Expand All @@ -196,10 +196,11 @@ function isEditing(target) {
const contextMenuCallbacks = new Map();
let lastCallback = 0;
/**
* @param {MenuItem[]} menuItems
* @param {import('../sdk/web').MenuItem[]} menuItems
*/
function serializeMenuItems(menuItems) {
return menuItems.map(item => {
/** @type {any} */
const serialized = {
...item,
};
Expand All @@ -214,7 +215,7 @@ function serializeMenuItems(menuItems) {
});
}
/**
* @param {MenuItem[]} menuItems
* @param {import('../sdk/web').MenuItem[]} descriptor
* @param {boolean=} noDefaultItems
*/
function createContextMenu(descriptor, noDefaultItems) {
Expand Down Expand Up @@ -255,15 +256,15 @@ async function getDevicePixelRatio() {
return dprPromise;
}

/** @type {{onMessage: (message: any, browserViewUUID?: string) => void, onDebuggeesChanged: (debuggees: {[key: string]: import('../src/CDPManager').DebuggingInfo}) => void}} */
/** @type {{onMessage: (message: any, browserViewUUID?: string) => void, onDebuggeesChanged: (debuggees: {[key: string]: import('../sdk/web').DebuggingInfo}) => void}} */
let cdpListener;

function openDevTools() {
sendMessageToParent({method: 'openDevTools'});
}

const ua = navigator.userActivation;
function tryToRunCommand(command) {
async function tryToRunCommand(command) {
if (!ua.isActive)
return;
sendMessageToParent({method: 'tryToRunCommand', params: {command}});
Expand Down Expand Up @@ -320,12 +321,12 @@ function expectingUserInput(name = 'Anonymous Work Context') {
return () => sendMessageToParent({method: 'resolveUserInput', params: {id}});
}

/** @type {(params: import('../../src/Find').FindParams) => void} */
/** @type {(params: import('../sdk/web').FindParams|null) => void} */
let findHandler;
/** @type {import('../../src/Find').FindParams|null} */
/** @type {import('../sdk/web').FindParams|null} */
let findParams = null;
/**
* @param {string} message
* @param {(params: import('../sdk/web').FindParams|null) => void} _findHandler
*/
function setFindHandler(_findHandler) {
findHandler = _findHandler;
Expand Down
40 changes: 40 additions & 0 deletions slug/sdk/web.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
export type MenuItem = {
title?: string;
enabled?: boolean;
checked?: boolean;
callback?: () => void;
submenu?: MenuItem[];
};

export type Action = {
id: string;
title: string;
shortcut?: string;
callback: () => void;
};

export type FindParams = { regex: RegExp, report: (matches: number) => void };

export type DebuggingInfo = {
browserViewUUID?: string;
frameUUID?: string;
type: 'webkit'|'chromium'|'node';
};

export function waitForMessage<T>(): Promise<T>;
export function setHeight(height: number): void;
export function setIsFullscreen(isFullscreen: boolean): void;
export function sendInput(input: string): void;
export function createContextMenu(items: MenuItem[], noDefaultItems?: boolean): void;
export function saveItem(key: string, value: any): void;
export function loadItem(key: string): Promise<any>;
export function getDevicePixelRatio(): Promise<number>;
export function attachToCDP(listener: {onMessage: (message: any, browserViewUUID?: string) => void, onDebuggeesChanged: (debuggees: {[key: string]: DebuggingInfo}) => void}): Promise<(message: any, browserViewUUID?: string) => void>;
export function openDevTools(): void;
export function setToJSON(toJSON: any | (()=>any)): void;
export function setActions(actions: Action[] | (()=>Action[])): void;
export function startAsyncWork(name?: string): () => void;
export function expectingUserInput(name?: string): () => void;
export function tryToRunCommand(command: string): Promise<void>;
export function close(): void;
export function setFindHandler(findHandler: (params: FindParams|null) => void);
1 change: 1 addition & 0 deletions slug/sdk/web.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = window.snail;
7 changes: 2 additions & 5 deletions src/CDPManager.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { host } from "./host";

export type DebuggingInfo = {
browserViewUUID?: string;
frameUUID?: string;
type: 'webkit'|'chromium'|'node';
};
import type { DebuggingInfo } from '../slug/sdk/web';
export type { DebuggingInfo } from '../slug/sdk/web';

interface CDPListener {
onMessage(message: any, browserViewUUID?: string): void;
Expand Down
4 changes: 3 additions & 1 deletion src/Find.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { AntiFlicker } from './AntiFlicker';
import './find.css';

import type { FindParams } from '../slug/sdk/web';
export type { FindParams } from '../slug/sdk/web';

export class Find {
private _element = document.createElement('div');
private _input = document.createElement('input');
Expand Down Expand Up @@ -98,7 +101,6 @@ export class Find {
this._input.select();
}
}
export type FindParams = { regex: RegExp, report: (matches: number) => void };
export interface Findable {
setFind(params: FindParams|null): void;
}
Expand Down
9 changes: 3 additions & 6 deletions src/actions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { rootBlock } from "./GridPane";
import { shortcutParser, type ParsedShortcut } from './shortcutParser';

import type { Action } from '../slug/sdk/web';
export type { Action } from '../slug/sdk/web';

const globalActions: Action[] = [];
export function registerGlobalAction(action: Action): void {
const existing = globalActions.findIndex(a => a.id === action.id);
Expand All @@ -18,12 +21,6 @@ export function availableActions(): Action[] {
return true;
});
}
export type Action = {
id: string;
title: string;
shortcut?: string;
callback: () => void;
}

let continuationActions: {shortcut: ParsedShortcut, action: Action}[] = null;

Expand Down
10 changes: 5 additions & 5 deletions src/host.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/// <reference path="../slug/iframe/types.d.ts" />
import type { ShellHost } from '../host/ShellHost';
export interface IHostAPI {
sendMessage<Key extends keyof ShellHost>(message: {method: Key, params?: Parameters<ShellHost[Key]>[0]}): Promise<ReturnType<ShellHost[Key]>>;
Expand All @@ -22,8 +21,9 @@ function makeHostAPI(): IHostAPI {
});
return host;
}
if (window.snail) {
window.snail.setIsFullscreen(true);
if (window['snail']) {
const snail: typeof import('../slug/sdk/web') = window['snail'];
snail.setIsFullscreen(true);
const {host, callback} = hostApiHelper('snail', message => {
if (message.method === 'contextMenu') {
// async contextMenu({ menuItems }, client, sender) {
Expand Down Expand Up @@ -69,11 +69,11 @@ function makeHostAPI(): IHostAPI {
snail.createContextMenu(unserializeMenuItems(message.params.menuItems));
return;
}
window.snail.sendInput(JSON.stringify(message) + '\n');
snail.sendInput(JSON.stringify(message) + '\n');
});
(async function() {
while(true) {
const message = await window.snail.waitForMessage();
const message = await snail.waitForMessage();
callback(message);
}
})();
Expand Down

0 comments on commit d5f123c

Please sign in to comment.