switch to new model of ws notification -> screen update fetch

This commit is contained in:
sawka
2023-03-31 21:02:44 -07:00
parent 10da862942
commit 8599e2b57c
6 changed files with 211 additions and 68 deletions
+5 -1
View File
@@ -36,7 +36,7 @@ class SimpleBlobRendererModel {
this.savedHeight = params.savedHeight; this.savedHeight = params.savedHeight;
this.ptyDataSource = params.ptyDataSource; this.ptyDataSource = params.ptyDataSource;
if (this.isDone.get()) { if (this.isDone.get()) {
this.reload(0); setTimeout(() => this.reload(0), 10);
} }
} }
@@ -74,6 +74,10 @@ class SimpleBlobRendererModel {
this.loading.set(true); this.loading.set(true);
})(); })();
let rtnp = this.ptyDataSource(this.context); let rtnp = this.ptyDataSource(this.context);
if (rtnp == null) {
console.log("no promise returned from ptyDataSource (simplerenderer)", this.context);
return;
}
rtnp.then((ptydata) => { rtnp.then((ptydata) => {
setTimeout(() => { setTimeout(() => {
this.ptyData = ptydata; this.ptyData = ptydata;
+5 -1
View File
@@ -109,7 +109,7 @@ class TermWrap {
if (opts.customKeyHandler != null) { if (opts.customKeyHandler != null) {
this.terminal.attachCustomKeyEventHandler((e) => opts.customKeyHandler(e, this)); this.terminal.attachCustomKeyEventHandler((e) => opts.customKeyHandler(e, this));
} }
this.reload(0); setTimeout(() => this.reload(0), 10);
} }
getUsedRows() : number { getUsedRows() : number {
@@ -281,6 +281,10 @@ class TermWrap {
this.reloading = true; this.reloading = true;
this.terminal.reset(); this.terminal.reset();
let rtnp = this.ptyDataSource(this.termContext); let rtnp = this.ptyDataSource(this.termContext);
if (rtnp == null) {
console.log("no promise returned from ptyDataSource (termwrap)", this.termContext);
return;
}
rtnp.then((ptydata) => { rtnp.then((ptydata) => {
setTimeout(() => { setTimeout(() => {
this._reloadThenHandler(ptydata); this._reloadThenHandler(ptydata);
+3 -11
View File
@@ -535,9 +535,11 @@ type WebCmd = {
}; };
type WebFullScreen = { type WebFullScreen = {
screenid : string,
screen : WebScreen, screen : WebScreen,
lines : WebLine[], lines : WebLine[],
cmds : WebCmd[], cmds : WebCmd[],
cmdptymap : Record<string, number>,
vts : number, vts : number,
} }
@@ -548,16 +550,6 @@ type PtyDataUpdate = {
data : string, data : string,
}; };
type WebScreenUpdate = {
type : string,
screenid : string,
screen : WebScreen,
lines : WebLine[],
cmds : WebCmd[],
ptydata : PtyDataUpdate[],
removedlines : string[],
};
type WebShareWSMessage = { type WebShareWSMessage = {
type : string, type : string,
screenid : string, screenid : string,
@@ -589,4 +581,4 @@ type RendererContainerType = {
type LineHeightChangeCallbackType = (lineNum : number, newHeight : number, oldHeight : number) => void; type LineHeightChangeCallbackType = (lineNum : number, newHeight : number, oldHeight : number) => void;
export type {SessionDataType, LineType, RemoteType, RemoteStateType, RemoteInstanceType, HistoryItem, CmdRemoteStateType, FeCmdPacketType, TermOptsType, CmdStartPacketType, CmdDataType, ScreenDataType, ScreenOptsType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, RemotePtrType, UIContextType, HistoryInfoType, HistoryQueryOpts, WatchScreenPacketType, TermWinSize, FeInputPacketType, RemoteInputPacketType, RemoteEditType, FeStateType, ContextMenuOpts, RendererContext, WindowSize, RendererModel, PtyDataType, BookmarkType, ClientDataType, PlaybookType, PlaybookEntryType, HistoryViewDataType, RenderModeType, AlertMessageType, HistorySearchParams, ScreenLinesType, FocusTypeStrs, HistoryTypeStrs, RendererOpts, RendererPluginType, SimpleBlobRendererComponent, RendererModelContainerApi, RendererModelInitializeParams, RendererOptsUpdate, ClientMigrationInfo, WebShareOpts, RemoteStatusTypeStrs, WebFullScreen, WebScreen, WebLine, WebCmd, RemoteTermContext, TermContextUnion, WebRemote, WebScreenUpdate, PtyDataUpdate, WebShareWSMessage, LineHeightChangeCallbackType, LineFactoryProps, LineInterface, RendererContainerType}; export type {SessionDataType, LineType, RemoteType, RemoteStateType, RemoteInstanceType, HistoryItem, CmdRemoteStateType, FeCmdPacketType, TermOptsType, CmdStartPacketType, CmdDataType, ScreenDataType, ScreenOptsType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, RemotePtrType, UIContextType, HistoryInfoType, HistoryQueryOpts, WatchScreenPacketType, TermWinSize, FeInputPacketType, RemoteInputPacketType, RemoteEditType, FeStateType, ContextMenuOpts, RendererContext, WindowSize, RendererModel, PtyDataType, BookmarkType, ClientDataType, PlaybookType, PlaybookEntryType, HistoryViewDataType, RenderModeType, AlertMessageType, HistorySearchParams, ScreenLinesType, FocusTypeStrs, HistoryTypeStrs, RendererOpts, RendererPluginType, SimpleBlobRendererComponent, RendererModelContainerApi, RendererModelInitializeParams, RendererOptsUpdate, ClientMigrationInfo, WebShareOpts, RemoteStatusTypeStrs, WebFullScreen, WebScreen, WebLine, WebCmd, RemoteTermContext, TermContextUnion, WebRemote, PtyDataUpdate, WebShareWSMessage, LineHeightChangeCallbackType, LineFactoryProps, LineInterface, RendererContainerType};
+2 -3
View File
@@ -24,7 +24,6 @@ type OMap<K,V> = mobx.ObservableMap<K,V>;
let foo = LinesView; let foo = LinesView;
// TODO reshare // TODO reshare
// TODO debounce some of the updates
function makeFullRemoteRef(ownerName : string, remoteRef : string, name : string) : string { function makeFullRemoteRef(ownerName : string, remoteRef : string, name : string) : string {
if (isBlank(ownerName) && isBlank(name)) { if (isBlank(ownerName) && isBlank(name)) {
@@ -624,7 +623,7 @@ class WebScreenView extends React.Component<{}, {}> {
} }
render() { render() {
let fullScreen = WebShareModel.screen.get(); let fullScreen = WebShareModel.fullScreen.get();
if (fullScreen == null || fullScreen.lines.length == 0) { if (fullScreen == null || fullScreen.lines.length == 0) {
return this.renderEmpty(); return this.renderEmpty();
} }
@@ -643,7 +642,7 @@ class WebShareMain extends React.Component<{}, {}> {
} }
render() { render() {
let screen = WebShareModel.screen.get(); let screen = WebShareModel.fullScreen.get();
let errMessage = WebShareModel.errMessage.get(); let errMessage = WebShareModel.errMessage.get();
let shareName = ""; let shareName = "";
if (screen != null) { if (screen != null) {
+195 -51
View File
@@ -14,6 +14,10 @@ type OArr<V> = mobx.IObservableArray<V>;
type OMap<K,V> = mobx.ObservableMap<K,V>; type OMap<K,V> = mobx.ObservableMap<K,V>;
type CV<V> = mobx.IComputedValue<V>; type CV<V> = mobx.IComputedValue<V>;
type PtyListener = {
receiveData(ptyPos : number, data : Uint8Array, reason? : string);
};
function isBlank(s : string) { function isBlank(s : string) {
return (s == null || s == ""); return (s == null || s == "");
} }
@@ -30,7 +34,7 @@ class WebShareModelClass {
viewKey : string; viewKey : string;
screenId : string; screenId : string;
errMessage : OV<string> = mobx.observable.box(null, {name: "errMessage"}); errMessage : OV<string> = mobx.observable.box(null, {name: "errMessage"});
screen : OV<T.WebFullScreen> = mobx.observable.box(null, {name: "webScreen"}); fullScreen : OV<T.WebFullScreen> = mobx.observable.box(null, {name: "webScreen"});
terminals : Record<string, TermWrap> = {}; // lineid => TermWrap terminals : Record<string, TermWrap> = {}; // lineid => TermWrap
renderers : Record<string, T.RendererModel> = {}; // lineid => RendererModel renderers : Record<string, T.RendererModel> = {}; // lineid => RendererModel
contentHeightCache : Record<string, number> = {}; // lineid => height contentHeightCache : Record<string, number> = {}; // lineid => height
@@ -39,12 +43,17 @@ class WebShareModelClass {
selectedLine : OV<number> = mobx.observable.box(0, {name: "selectedLine"}); selectedLine : OV<number> = mobx.observable.box(0, {name: "selectedLine"});
syncSelectedLine : OV<boolean> = mobx.observable.box(true, {name: "syncSelectedLine"}); syncSelectedLine : OV<boolean> = mobx.observable.box(true, {name: "syncSelectedLine"});
lastScreenSize : T.WindowSize = null; lastScreenSize : T.WindowSize = null;
activePtyFetch : Record<string, boolean> = {}; // lineid -> active
localPtyOffsetMap : Record<string, number> = {};
remotePtyOffsetMap : Record<string, number> = {};
activeUpdateFetch : boolean = false;
remoteScreenVts : number = 0;
constructor() { constructor() {
let urlParams = new URLSearchParams(window.location.search); let urlParams = new URLSearchParams(window.location.search);
this.viewKey = urlParams.get("viewkey"); this.viewKey = urlParams.get("viewkey");
this.screenId = urlParams.get("screenid"); this.screenId = urlParams.get("screenid");
setTimeout(() => this.loadFullScreenData(), 10); setTimeout(() => this.loadFullScreenData(false), 10);
this.wsControl = new WebShareWSControl(getBaseWSUrl(), this.screenId, this.viewKey, this.wsMessageCallback.bind(this)); this.wsControl = new WebShareWSControl(getBaseWSUrl(), this.screenId, this.viewKey, this.wsMessageCallback.bind(this));
document.addEventListener("keydown", this.docKeyDownHandler.bind(this)); document.addEventListener("keydown", this.docKeyDownHandler.bind(this));
} }
@@ -59,7 +68,7 @@ class WebShareModelClass {
mobx.action(() => { mobx.action(() => {
this.syncSelectedLine.set(val); this.syncSelectedLine.set(val);
if (val) { if (val) {
let fullScreen = this.screen.get(); let fullScreen = this.fullScreen.get();
if (fullScreen != null) { if (fullScreen != null) {
this.selectedLine.set(fullScreen.screen.selectedline); this.selectedLine.set(fullScreen.screen.selectedline);
} }
@@ -103,7 +112,7 @@ class WebShareModelClass {
} }
getServerSelectedLine() : number { getServerSelectedLine() : number {
let fullScreen = this.screen.get(); let fullScreen = this.fullScreen.get();
if (fullScreen != null) { if (fullScreen != null) {
return fullScreen.screen.selectedline; return fullScreen.screen.selectedline;
} }
@@ -116,7 +125,7 @@ class WebShareModelClass {
} }
updateSelectedLineIndex(delta : number) : void { updateSelectedLineIndex(delta : number) : void {
let fullScreen = this.screen.get(); let fullScreen = this.fullScreen.get();
if (fullScreen == null) { if (fullScreen == null) {
return; return;
} }
@@ -209,14 +218,20 @@ class WebShareModelClass {
fullScreen.cmds.push(newCmd); fullScreen.cmds.push(newCmd);
} }
mergeUpdate(msg : T.WebScreenUpdate) { mergeUpdate(msg : T.WebFullScreen) {
if (msg.screenid != this.screenId) { if (msg.screenid != this.screenId) {
console.log("bad WebScreenUpdate, wrong screenid", msg.screenid); console.log("bad WebFullScreen update, wrong screenid", msg.screenid);
return; return;
} }
console.log("merge", msg); console.log("merge screen-update", "vts=" + msg.vts);
// console.log("merge", "vts=" + msg.vts, msg);
mobx.action(() => { mobx.action(() => {
let fullScreen = this.screen.get(); let fullScreen = this.fullScreen.get();
if (fullScreen.vts >= msg.vts) {
console.log("stale merge", "cur-vts=" + fullScreen.vts, "merge-vts=" + msg.vts);
return;
}
fullScreen.vts = msg.vts;
if (msg.screen) { if (msg.screen) {
fullScreen.screen = msg.screen; fullScreen.screen = msg.screen;
if (this.syncSelectedLine.get()) { if (this.syncSelectedLine.get()) {
@@ -225,6 +240,10 @@ class WebShareModelClass {
} }
if (msg.lines != null && msg.lines.length > 0) { if (msg.lines != null && msg.lines.length > 0) {
for (let line of msg.lines) { for (let line of msg.lines) {
if (line.archived) {
this.removeLine(fullScreen, line.lineid);
continue;
}
this.mergeLine(fullScreen, line); this.mergeLine(fullScreen, line);
} }
} }
@@ -233,33 +252,118 @@ class WebShareModelClass {
this.mergeCmd(fullScreen, cmd); this.mergeCmd(fullScreen, cmd);
} }
} }
if (msg.ptydata != null && msg.ptydata.length > 0) { this.handleCmdPtyMap(msg.cmdptymap);
for (let data of msg.ptydata) { })();
let termWrap = this.getTermWrap(data.lineid); }
if (termWrap == null) {
continue; handleCmdPtyMap(ptyMap : Record<string, number>) {
} if (ptyMap == null) {
let dataArr = base64ToArray(data.data); return;
termWrap.receiveData(data.ptypos, dataArr, "ws:ptydata"); }
} for (let lineId in ptyMap) {
let newOffset = ptyMap[lineId];
this.remotePtyOffsetMap[lineId] = newOffset;
let localOffset = this.localPtyOffsetMap[lineId];
if (localOffset != null && localOffset < newOffset) {
this.runPtyFetch(lineId);
} }
if (msg.removedlines != null && msg.removedlines.length > 0) { }
for (let lineid of msg.removedlines) { }
this.removeLine(fullScreen, lineid);
runPtyFetch(lineId : string) {
let prtn = this.checkFetchPtyData(lineId, false);
let ptyListener = this.getPtyListener(lineId);
if (ptyListener != null) {
prtn.then((ptydata) => {
ptyListener.receiveData(ptydata.pos, ptydata.data, "model-fetch");
if (ptydata.data.length > 0) {
setTimeout(() => this.checkFetchPtyData(lineId, false), 100);
} }
});
}
}
getPtyListener(lineId : string) {
let termWrap = this.getTermWrap(lineId);
if (termWrap != null) {
return termWrap;
}
let renderer = this.getRenderer(lineId);
if (renderer != null) {
return renderer;
}
return null;
}
receivePtyData(lineId : string, ptyPos : number, data : Uint8Array, reason? : string) : void {
let termWrap = this.getTermWrap(lineId);
if (termWrap != null) {
termWrap.receiveData(ptyPos, data, reason);
}
let renderer = this.getRenderer(lineId);
if (renderer != null) {
renderer.receiveData(ptyPos, data, reason);
}
}
checkFetchPtyData(lineId : string, reload : boolean) : Promise<T.PtyDataType> {
let lineNum = this.getLineNumFromId(lineId);
if (this.activePtyFetch[lineId]) {
// console.log("check-fetch", lineNum, "already running");
return;
}
if (reload) {
this.localPtyOffsetMap[lineId] = 0;
}
let ptyOffset = this.localPtyOffsetMap[lineId];
if (ptyOffset == null) {
// console.log("check-fetch", lineNum, "no local offset");
return;
}
let remotePtyOffset = this.remotePtyOffsetMap[lineId];
if (ptyOffset >= remotePtyOffset) {
// up to date
return Promise.resolve({pos: ptyOffset, data: new Uint8Array(0)});
}
this.activePtyFetch[lineId] = true;
let viewKey = WebShareModel.viewKey;
// console.log("fetch pty", lineNum, "pos=" + ptyOffset);
let usp = new URLSearchParams({screenid: this.screenId, viewkey: viewKey, lineid: lineId, pos: String(ptyOffset)});
let url = new URL(getBaseUrl() + "/webshare/ptydata?" + usp.toString());
return fetch(url, {method: "GET", mode: "cors", cache: "no-cache"}).then((resp) => {
if (!resp.ok) {
throw new Error(sprintf("Bad fetch response for /webshare/ptydata: %d %s", resp.status, resp.statusText));
} }
})(); let ptyOffsetStr = resp.headers.get("X-PtyDataOffset");
if (ptyOffsetStr != null && !isNaN(parseInt(ptyOffsetStr))) {
ptyOffset = parseInt(ptyOffsetStr);
}
return resp.arrayBuffer();
}).then((buf) => {
let dataArr = new Uint8Array(buf);
let newOffset = ptyOffset + dataArr.length;
console.log("fetch pty success", lineNum, "len=" + dataArr.length, "pos => " + newOffset);
this.localPtyOffsetMap[lineId] = newOffset;
return {pos: ptyOffset, data: dataArr};
}).finally(() => {
this.activePtyFetch[lineId] = false;
});
} }
wsMessageCallback(msg : any) { wsMessageCallback(msg : any) {
if (msg.type == "webscreen:update") { if (msg.type == "webscreen:update") {
this.mergeUpdate(msg); console.log("[ws] update vts", msg.vts);
if (msg.vts > this.remoteScreenVts) {
this.remoteScreenVts = msg.vts;
setTimeout(() => this.checkUpdateScreenData(), 10);
}
return; return;
} }
console.log("ws message", msg); console.log("[ws] unhandled message", msg);
} }
setWebFullScreen(screen : T.WebFullScreen) { setWebFullScreen(screen : T.WebFullScreen) {
console.log("got initial screen", "vts=" + screen.vts);
mobx.action(() => { mobx.action(() => {
if (screen.lines == null) { if (screen.lines == null) {
screen.lines = []; screen.lines = [];
@@ -267,7 +371,9 @@ class WebShareModelClass {
if (screen.cmds == null) { if (screen.cmds == null) {
screen.cmds = []; screen.cmds = [];
} }
this.screen.set(screen); this.handleCmdPtyMap(screen.cmdptymap);
screen.cmdptymap = null;
this.fullScreen.set(screen);
this.wsControl.reconnect(true); this.wsControl.reconnect(true);
if (this.syncSelectedLine.get()) { if (this.syncSelectedLine.get()) {
this.selectedLine.set(screen.screen.selectedline); this.selectedLine.set(screen.screen.selectedline);
@@ -303,6 +409,10 @@ class WebShareModelClass {
onUpdateContentHeight: (termContext : T.RendererContext, height : number) => { this.setContentHeight(termContext, height); }, onUpdateContentHeight: (termContext : T.RendererContext, height : number) => { this.setContentHeight(termContext, height); },
}); });
this.terminals[lineId] = termWrap; this.terminals[lineId] = termWrap;
if (this.localPtyOffsetMap[lineId] == null) {
this.localPtyOffsetMap[lineId] = 0;
}
this.localPtyOffsetMap[lineId] = 0;
if (this.getSelectedLine() == line.linenum) { if (this.getSelectedLine() == line.linenum) {
termWrap.giveFocus(); termWrap.giveFocus();
} }
@@ -358,6 +468,7 @@ class WebShareModelClass {
term.dispose(); term.dispose();
delete this.terminals[lineId]; delete this.terminals[lineId];
} }
delete this.localPtyOffsetMap[lineId];
} }
getUsedRows(context : T.RendererContext, line : T.WebLine, cmd : T.WebCmd, width : number) : number { getUsedRows(context : T.RendererContext, line : T.WebLine, cmd : T.WebCmd, width : number) : number {
@@ -391,11 +502,26 @@ class WebShareModelClass {
return this.renderers[lineId]; return this.renderers[lineId];
} }
registerRenderer(cmdId : string, renderer : T.RendererModel) { registerRenderer(lineId : string, renderer : T.RendererModel) {
this.renderers[cmdId] = renderer; this.renderers[lineId] = renderer;
if (this.localPtyOffsetMap[lineId] == null) {
this.localPtyOffsetMap[lineId] = 0;
}
} }
loadFullScreenData() : void { checkUpdateScreenData() : void {
let fullScreen = this.fullScreen.get();
if (fullScreen == null) {
return;
}
// console.log("check-update", "vts=" + fullScreen.vts, "remote-vts=" + this.remoteScreenVts);
if (fullScreen.vts >= this.remoteScreenVts) {
return;
}
this.loadFullScreenData(true);
}
loadFullScreenData(update : boolean) : void {
if (isBlank(this.screenId)) { if (isBlank(this.screenId)) {
this.setErrMessage("No ScreenId Specified, Cannot Load."); this.setErrMessage("No ScreenId Specified, Cannot Load.");
return; return;
@@ -404,20 +530,53 @@ class WebShareModelClass {
this.setErrMessage("No ViewKey Specified, Cannot Load."); this.setErrMessage("No ViewKey Specified, Cannot Load.");
return; return;
} }
let usp = new URLSearchParams({screenid: this.screenId, viewkey: this.viewKey}); if (this.activeUpdateFetch) {
// console.log("there is already an active update fetch");
return;
}
// console.log("running screen-data update");
this.activeUpdateFetch = true;
let urlParams : Record<string, string> = {screenid: this.screenId, viewkey: this.viewKey};
if (update) {
let fullScreen = this.fullScreen.get();
if (fullScreen != null) {
urlParams.vts = String(fullScreen.vts);
}
}
let usp = new URLSearchParams(urlParams);
let url = new URL(getBaseUrl() + "/webshare/screen?" + usp.toString()); let url = new URL(getBaseUrl() + "/webshare/screen?" + usp.toString());
fetch(url, {method: "GET", mode: "cors", cache: "no-cache"}).then((resp) => handleJsonFetchResponse(url, resp)).then((data) => { fetch(url, {method: "GET", mode: "cors", cache: "no-cache"}).then((resp) => handleJsonFetchResponse(url, resp)).then((data) => {
mobx.action(() => { let screen : T.WebFullScreen = data;
let screen : T.WebFullScreen = data; if (update) {
this.mergeUpdate(screen);
}
else {
this.setWebFullScreen(screen); this.setWebFullScreen(screen);
})(); }
setTimeout(() => this.checkUpdateScreenData(), 300);
}).catch((err) => { }).catch((err) => {
this.errMessage.set("Cannot get screen: " + err.message); this.errMessage.set("Cannot get screen: " + err.message);
}).finally(() => {
this.activeUpdateFetch = false;
}); });
} }
getLineNumFromId(lineId : string) : number {
let fullScreen = this.fullScreen.get();
if (fullScreen == null) {
return -1;
}
for (let i=0; i<fullScreen.lines.length; i++) {
let line = fullScreen.lines[i];
if (line.lineid == lineId) {
return line.linenum;
}
}
return -1;
}
getLineIndex(lineNum : number) : number { getLineIndex(lineNum : number) : number {
let fullScreen = this.screen.get(); let fullScreen = this.fullScreen.get();
if (fullScreen == null) { if (fullScreen == null) {
return -1; return -1;
} }
@@ -431,7 +590,7 @@ class WebShareModelClass {
} }
getNumLines() : number { getNumLines() : number {
let fullScreen = this.screen.get(); let fullScreen = this.fullScreen.get();
if (fullScreen == null) { if (fullScreen == null) {
return 0; return 0;
} }
@@ -439,7 +598,7 @@ class WebShareModelClass {
} }
getCmdById(lineId : string) : T.WebCmd { getCmdById(lineId : string) : T.WebCmd {
let fullScreen = this.screen.get(); let fullScreen = this.fullScreen.get();
if (fullScreen == null) { if (fullScreen == null) {
return null; return null;
} }
@@ -468,22 +627,7 @@ function getTermPtyData(termContext : T.TermContextUnion) : Promise<T.PtyDataTyp
if ("remoteId" in termContext) { if ("remoteId" in termContext) {
throw new Error("remote term ptydata is not supported in webshare"); throw new Error("remote term ptydata is not supported in webshare");
} }
let ptyOffset = 0; return WebShareModel.checkFetchPtyData(termContext.lineId, true);
let viewKey = WebShareModel.viewKey;
let usp = new URLSearchParams({screenid: termContext.screenId, viewkey: viewKey, lineid: termContext.lineId});
let url = new URL(getBaseUrl() + "/webshare/ptydata?" + usp.toString());
return fetch(url, {method: "GET", mode: "cors", cache: "no-cache"}).then((resp) => {
if (!resp.ok) {
throw new Error(sprintf("Bad fetch response for /webshare/ptydata: %d %s", resp.status, resp.statusText));
}
let ptyOffsetStr = resp.headers.get("X-PtyDataOffset");
if (ptyOffsetStr != null && !isNaN(parseInt(ptyOffsetStr))) {
ptyOffset = parseInt(ptyOffsetStr);
}
return resp.arrayBuffer();
}).then((buf) => {
return {pos: ptyOffset, data: new Uint8Array(buf)};
});
} }
let WebShareModel : WebShareModelClass = null; let WebShareModel : WebShareModelClass = null;
+1 -1
View File
@@ -23,7 +23,7 @@ class WebShareWSControl {
this.viewKey = viewKey; this.viewKey = viewKey;
this.open = mobx.observable.box(false, {name: "WSOpen"}); this.open = mobx.observable.box(false, {name: "WSOpen"});
this.closed = true; this.closed = true;
setInterval(this.sendPing, 15000); setInterval(this.sendPing, 20000);
} }
close() : void { close() : void {