assets: Use new websocket client
This commit is contained in:
parent
e91f1f2413
commit
6a739df24b
67 changed files with 437 additions and 562 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import './index.css'
|
||||
import callServerAction, { ResultMessage } from './proto'
|
||||
import { Result } from '../apiclient/websocket'
|
||||
import LocalCall from './local'
|
||||
|
||||
type Print = ((text: string, flush?: boolean) => void) & {
|
||||
paintedFrames: number
|
||||
|
|
@ -166,7 +167,7 @@ export function createModal (action: string, params: string[], opts: Partial<Mod
|
|||
finishButton.className = 'pure-button pure-button-success'
|
||||
finishButton.append(typeof opts?.onClose === 'function' ? 'Close & Finish' : 'Close')
|
||||
|
||||
let result: ResultMessage = { success: false, message: 'Nothing happened' }
|
||||
let result: Result = { success: false, message: 'Nothing happened' }
|
||||
finishButton.addEventListener('click', (event) => {
|
||||
event.preventDefault()
|
||||
|
||||
|
|
@ -194,7 +195,7 @@ export function createModal (action: string, params: string[], opts: Partial<Mod
|
|||
window.onbeforeunload = () => 'A remote session is in progress. Are you sure you want to leave?'
|
||||
|
||||
// when closing, add a button to the modal!
|
||||
const close = (message: ResultMessage): void => {
|
||||
const close = (message: Result): void => {
|
||||
result = message
|
||||
|
||||
if (result.success) {
|
||||
|
|
@ -214,32 +215,25 @@ export function createModal (action: string, params: string[], opts: Partial<Mod
|
|||
|
||||
print('Connecting ...', true)
|
||||
|
||||
// backendURL is the backend url to connect to
|
||||
const backendURL = location.protocol.replace('http', 'ws') + '//' + location.host + '/api/v1/ws'
|
||||
|
||||
// connect to the socket and send the action
|
||||
callServerAction(
|
||||
backendURL,
|
||||
{
|
||||
call: action,
|
||||
params
|
||||
},
|
||||
(
|
||||
send: (text: string) => void,
|
||||
cancel: () => void
|
||||
) => {
|
||||
cancelButton.removeAttribute('disabled')
|
||||
const call = new LocalCall({
|
||||
call: action,
|
||||
params
|
||||
});
|
||||
|
||||
call.beforeCall = function() {
|
||||
cancelButton.removeAttribute('disabled')
|
||||
cancelButton.addEventListener('click', (event) => {
|
||||
event.preventDefault()
|
||||
|
||||
print('^C\n', true)
|
||||
cancel()
|
||||
this.cancel()
|
||||
})
|
||||
print(' Connected.\n', true)
|
||||
},
|
||||
print
|
||||
).then(close)
|
||||
.catch(() => {
|
||||
close({ success: false, message: 'connection closed unexpectedly' })
|
||||
})
|
||||
}
|
||||
call.onLogLine = print;
|
||||
|
||||
call.connect()
|
||||
.then((result) => close(result))
|
||||
.catch(() => close({ success: false, message: 'connection closed unexpectedly' }));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
import { default as Call, CallSpec } from '../apiclient/websocket';
|
||||
|
||||
/** LocalCall is like Call, but uses the current page */
|
||||
export default class LocalCall extends Call {
|
||||
constructor(spec: CallSpec) {
|
||||
super({ url: location.protocol.replace('http', 'ws') + '//' + location.host + '/api/v1/ws'}, spec);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
import { Mutex } from 'async-mutex'
|
||||
|
||||
import { runMutexExclusive } from '~/src/lib/discard'
|
||||
|
||||
export interface CallMessage { call: string, params?: string[] | null }
|
||||
export type ResultMessage = { success: true } | { success: false, message: string }
|
||||
export interface SignalMessage { signal: string }
|
||||
function isResultMessage (value: any): value is ResultMessage {
|
||||
return typeof value === 'object' &&
|
||||
Object.prototype.hasOwnProperty.call(value, 'success') &&
|
||||
(
|
||||
(value.success === true) ||
|
||||
(value.success === false && Object.prototype.hasOwnProperty.call(value, 'message') && (typeof value.message === 'string'))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a WebSocket connection and calls a server action
|
||||
* @param endpoint Endpoint to call
|
||||
* @param call Function to call
|
||||
* @param onOpen callback for once the connection is opened. The send function can be used to send additional text to the server. It should include newlines.
|
||||
* @param onText called when the connection receives some text, including newlines.
|
||||
* @returns a promise that is resolved once the conneciton is closed. Rejected if the connection errors.
|
||||
*/
|
||||
export default async function callServerAction (
|
||||
endpoint: string,
|
||||
call: CallMessage,
|
||||
onOpen: (send: (text: string) => void, cancel: () => void) => void,
|
||||
onText: (text: string) => void
|
||||
): Promise<ResultMessage> {
|
||||
return await new Promise((resolve, reject) => {
|
||||
const mutex = new Mutex()
|
||||
|
||||
const socket = new WebSocket(endpoint)
|
||||
|
||||
let result: ResultMessage
|
||||
socket.onmessage = (msg) => {
|
||||
runMutexExclusive(mutex, async () => {
|
||||
if (typeof msg.data === 'string') {
|
||||
onText(msg.data)
|
||||
return
|
||||
}
|
||||
|
||||
if (msg.data instanceof Blob) {
|
||||
const object = JSON.parse(await msg.data.text())
|
||||
if (isResultMessage(object)) {
|
||||
if (object.success) {
|
||||
result = { success: true }
|
||||
} else {
|
||||
result = { success: false, message: object.message }
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
console.warn('Unknown message', msg)
|
||||
})
|
||||
}
|
||||
socket.onclose = () => {
|
||||
mutex.runExclusive(() => resolve(result)).then(() => {}).catch(console.error.bind(console))
|
||||
}
|
||||
socket.onerror = reject // if an error occurs, close the socket
|
||||
|
||||
socket.onopen = () => {
|
||||
const blob = new Blob([JSON.stringify(call)])
|
||||
socket.send(blob)
|
||||
|
||||
onOpen(
|
||||
(text: string) => {
|
||||
if (typeof text !== 'string') {
|
||||
console.warn('Ignoring send() call with unknown type', text)
|
||||
return
|
||||
}
|
||||
socket.send(text)
|
||||
},
|
||||
() => {
|
||||
const blob = new Blob([JSON.stringify({ signal: 'cancel' })])
|
||||
socket.send(blob)
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue