784 строки
31 KiB
TypeScript
784 строки
31 KiB
TypeScript
///<reference path='refs.ts'/>
|
|
|
|
|
|
module TDev {
|
|
|
|
export var onWallClose:() => void = null;
|
|
|
|
export class RuntimeHostBase
|
|
implements RuntimeHost {
|
|
public currentGuid: string;
|
|
public currentRt: Runtime;
|
|
public getWall() { return elt("theWall"); }
|
|
private wallContainer = div('');
|
|
public backBtnDiv = div(null); // FIXME t-mikhab: do something with lack of protected visibility
|
|
private scriptTitleDiv = div("scriptTitle");
|
|
private titleDiv = div("title");
|
|
private subtitleDiv = div("subtitle");
|
|
private titleContainer = div("wallTitleDiv");
|
|
private cloudSymbol = div("wallCloudSymbol");
|
|
private cloudStatus = div("wallCloudStatus");
|
|
private cloudContainer: HTMLElement;
|
|
private bottomBtnsDiv: HTMLElement;
|
|
private topBtnRow: HTMLElement;
|
|
private fullScreenBtnRow: HTMLElement;
|
|
private bgPictureContainer = div("wallBgPictureHorizontal");
|
|
private fullScreenContainer = div("wallFullScreenContainer");
|
|
private adContainer = div('wallAdContainer');
|
|
|
|
public wallWidth = 1000;
|
|
public wallHeight = 1000;
|
|
public wallOrientation = 0;
|
|
public wallVisible = false;
|
|
|
|
public copyrightHeight = 26;
|
|
public showCopyright = !Browser.isWP8app;
|
|
private keyState: any = null;
|
|
public localProxyAsync : (path: string, data: any) => Promise = undefined;
|
|
|
|
public isHeadless()
|
|
{
|
|
return Browser.isHeadless || this.currentRt.headlessPluginMode
|
|
}
|
|
|
|
public fullWallHeight() {
|
|
this.computeCopyrightHeight()
|
|
return SizeMgr.windowHeight - (this.showCopyright ? this.copyrightHeight : 0);
|
|
}
|
|
|
|
private computeCopyrightHeight()
|
|
{
|
|
this.copyrightHeight = Math.round(SizeMgr.topFontSize*0.7*1.66);
|
|
}
|
|
|
|
public userWallHeight() {
|
|
if (!this.currentRt.getCurrentPage().chromeVisible) return this.fullWallHeight();
|
|
this.computeCopyrightHeight()
|
|
return SizeMgr.windowHeight - 4 * SizeMgr.topFontSize - (this.showCopyright ? this.copyrightHeight : 0);
|
|
}
|
|
|
|
public fullWallWidth() {
|
|
return SizeMgr.wallWindowWidth;
|
|
}
|
|
|
|
public init(rt: Runtime) {
|
|
this.currentRt = rt;
|
|
}
|
|
|
|
public liveMode() { return false; }
|
|
public dontWaitForEvents() { return false; }
|
|
public astOfAsync(id: string) { return Promise.as(undefined); }
|
|
public deploymentSettingsAsync(id:string) { return Promise.as(undefined); }
|
|
public pickScriptAsync(mode: string, message: string): Promise { return Promise.as(undefined) }
|
|
public saveAstAsync(id: string, ast: any): Promise { return Promise.as(undefined); }
|
|
public packageScriptAsync(id : string, options: any) : Promise { return Promise.as(undefined); }
|
|
|
|
/* overriden in EditorHost */
|
|
public showBackButton() {
|
|
// we need a consistent experience for tutorial
|
|
//if (TDev.Browser.hasHardwareBack) return false;
|
|
if (TDev.Browser.notifyBackToHost)
|
|
return this.currentRt.getCurrentPage().backButtonVisible;
|
|
|
|
if (this.currentRt.getPageCount() == 1 && (TDev.Browser.isCompiledApp || SizeMgr.splitScreen)) return false;
|
|
if (!this.currentRt.isStopped())
|
|
return this.currentRt.getCurrentPage().backButtonVisible;
|
|
return true;
|
|
}
|
|
|
|
public applyPageAttributes(wp: WallPage) {
|
|
this.titleDiv.setChildren(wp.title)
|
|
this.subtitleDiv.setChildren(wp.subtitle)
|
|
// do not show back button on first page
|
|
if (this.showBackButton())
|
|
this.titleContainer.className = 'wallTitleDiv';
|
|
else
|
|
this.titleContainer.className = 'wallTitleDiv wallTitleDivFirst';
|
|
var wall = elt("wallOverlay");
|
|
wall.style.background = wp.bgColor;
|
|
wall.style.color = wp.fgColor;
|
|
|
|
this.updateCloudStateColor(wp.fgColor);
|
|
|
|
var bgPic = this.bgPictureContainer;
|
|
|
|
if (wp.bgVideo) {
|
|
wp.bgVideo.style.width = '100%';
|
|
wp.bgVideo.style.height = '100%';
|
|
wp.bgVideo.style.overflow = 'hidden';
|
|
wp.bgVideo.controls = false;
|
|
bgPic.className = "wallBgPictureHorizontal"
|
|
bgPic.setChildren(wp.bgVideo);
|
|
wp.bgVideo.play();
|
|
}
|
|
else if (wp.bgPicture && wp.bgPictureWidth > 0 && wp.bgPictureHeight > 0) {
|
|
var ww = wp.bgPictureWidth;
|
|
var hh = wp.bgPictureHeight;
|
|
var pic = wp.bgPicture;
|
|
bgPic.setChildren(pic);
|
|
var r = hh / ww;
|
|
var sr = window.innerHeight / window.innerWidth;
|
|
if (ww / hh < SizeMgr.wallWindowWidth / SizeMgr.windowHeight) {
|
|
pic.style.width = '100%';
|
|
var h = (100 * r / sr);
|
|
pic.style.height = h + '%';
|
|
bgPic.style.left = "0";
|
|
bgPic.style.top = (100 - h) / 2 + "%";
|
|
bgPic.className = "wallBgPictureHorizontal"
|
|
} else {
|
|
var w = 100 / r * sr;
|
|
pic.style.width = w + '%';
|
|
pic.style.height = '100%';
|
|
bgPic.style.left = (100 - w) / 2 + "%";
|
|
bgPic.style.top = "0";
|
|
bgPic.className = "wallBgPictureVertical"
|
|
}
|
|
} else if (wp.bgPictureUrl) {
|
|
bgPic.style.backgroundImage = HTML.cssImage( wp.bgPictureUrl );
|
|
bgPic.style.backgroundSize = "cover";
|
|
bgPic.style.width = '100%';
|
|
bgPic.style.height = '100%';
|
|
bgPic.className = 'wallBgPictureVertical';
|
|
} else {
|
|
bgPic.className = "";
|
|
bgPic.style.width = '';
|
|
bgPic.style.height = '';
|
|
bgPic.style.backgroundImage = '';
|
|
bgPic.style.backgroundSize = '';
|
|
bgPic.setChildren([])
|
|
}
|
|
|
|
var walkHtml = (e: HTMLElement) => {
|
|
if (!e) return;
|
|
if (e.getAttribute && e.getAttribute("fill")) {
|
|
e.setAttribute("fill", wp.fgColor)
|
|
}
|
|
if (e.className == "topMenu-button-frame")
|
|
e.style.borderColor = wp.fgColor;
|
|
else if (e.className == "topMenu-button-desc" || e.className == "appBarSymbol")
|
|
e.style.color = wp.fgColor;
|
|
Util.childNodes(e).forEach(walkHtml)
|
|
}
|
|
|
|
walkHtml(elt("wallBtns"));
|
|
walkHtml(elt("wallFullScreenBtns"));
|
|
walkHtml(elt("wallBottomBtns"));
|
|
}
|
|
|
|
public setTransform3d(trans: string, origin: string, perspective: string) {
|
|
var ch = <HTMLElement>this.fullScreenContainer.firstChild
|
|
if (ch)
|
|
Util.setTransform(ch, trans, origin, perspective);
|
|
}
|
|
|
|
public setFullScreenElement(element: HTMLElement) {
|
|
this.fullScreenContainer.setChildren(element);
|
|
if (element) {
|
|
var wall = elt("wallOverlay");
|
|
this.fullScreenContainer.style.position = "relative";
|
|
this.fullScreenContainer.style.display = "block";
|
|
}
|
|
else {
|
|
this.fullScreenContainer.style.display = "none";
|
|
this.fullScreenContainer.innerHTML = "";
|
|
}
|
|
this.updateButtonsVisibility();
|
|
}
|
|
|
|
public isFullScreen() : boolean {
|
|
return this.fullScreenContainer.style.display != "none" &&
|
|
!!this.fullScreenContainer.firstChild;
|
|
}
|
|
|
|
public tweakMsg(): HTMLElement {
|
|
return div(null);
|
|
}
|
|
|
|
public copyrightElement(): HTMLElement {
|
|
// no copyright notice in compiled apps
|
|
if (Browser.isCompiledApp && !Browser.webRunner)
|
|
return div(null);
|
|
|
|
var copyrights = div("copyright-text copyright-info");
|
|
//var msg = this.tweakMsg();
|
|
var logo = div("copyright-text copyright-logo", SVG.getHorizLogo())
|
|
//copyrights.style.right = "0";
|
|
//logo.style.left = "0";
|
|
var theNote = div("copyright-note", logo, copyrights);
|
|
|
|
var aw = <any>window;
|
|
var userName = Util.htmlEscape(aw.userName);
|
|
var userId = Util.htmlEscape(aw.userId);
|
|
var appName = Util.htmlEscape(aw.webAppName);
|
|
var betaFriendlyId = aw.betaFriendlyId;
|
|
|
|
var shareLink = () =>
|
|
Browser.webRunner ? window.location.toString().replace(/#.*/, "") :
|
|
this.currentRt && this.currentRt.currentScriptId ?
|
|
Cloud.getServiceUrl() + "/" + this.currentRt.currentScriptId : "";
|
|
|
|
var author = Browser.inEditor ? "" : " by <b>" + userName + "</b>";
|
|
var betaNote = betaFriendlyId ? ("<b>" + betaFriendlyId + "</b> ") : "";
|
|
betaNote += "<b>" + appName + "</b>" + author;
|
|
|
|
Browser.setInnerHTML(copyrights,
|
|
//"<span class='beta-underline'>share</span> " +
|
|
//betaNote + " " +
|
|
"© " +
|
|
"<span class='beta-underline'>privacy and cookies</span> " +
|
|
"<span class='beta-underline'>legal</span>"
|
|
);
|
|
|
|
var link = (text: string, lnk: string) =>
|
|
HTML.mkButton(text, () => { window.open(/:\/\//.test(lnk) ? lnk : Cloud.getServiceUrl() + lnk) });
|
|
|
|
var popup = () => {
|
|
var m = new ModalDialog();
|
|
m.fullWhite();
|
|
m.add(div("wall-dialog-header", Util.htmlUnescape(appName)));
|
|
|
|
m.addHTML("This web app was created" + author + " using TouchDevelop.");
|
|
m.addHTML("The TouchDevelop platform - Copyright © 2014 Microsoft Corporation. All rights reserved.");
|
|
m.addHTML("<b>DISCLAIMER:</b> This web app is not endorsed by Microsoft.");
|
|
|
|
if (!Browser.inEditor)
|
|
m.add(div("wall-dialog-buttons",
|
|
link("more by " + userName, "/" + userId),
|
|
link("try touchdevelop", "")));
|
|
|
|
m.add(div("wall-dialog-buttons",
|
|
link("legal", "/legal"),
|
|
link("privacy and cookies", "/privacy")));
|
|
|
|
m.show();
|
|
}
|
|
|
|
logo.withClick(popup);
|
|
copyrights.withClick(popup);
|
|
|
|
return theNote;
|
|
}
|
|
|
|
public askSourceAccessAsync(source: string, description: string, secondchance: boolean, critical? : boolean): Promise {
|
|
if (!RuntimeSettings.askSourceAccess) // shortcut for generated app
|
|
return Promise.as(true);
|
|
|
|
var rt = this.currentRt;
|
|
return rt.permissionsAsync()
|
|
.then(d => {
|
|
var v = d[source];
|
|
if (v === false && secondchance)
|
|
v = undefined;
|
|
if (v != undefined) {
|
|
if (!v)
|
|
HTML.showProgressNotification("denied access to " + description);
|
|
return Promise.as(!!v);
|
|
}
|
|
return new Promise((onSuccess, onError, onProgress) => {
|
|
var m = new ModalDialog();
|
|
var allow = false;
|
|
m.onDismiss = () => {
|
|
d[source] = allow;
|
|
rt.savePermissionsAsync(d)
|
|
.done(() => onSuccess(allow));
|
|
}
|
|
var buttons: HTMLElement;
|
|
m.add([
|
|
div("wall-dialog-header", lf("allow access to {0}?", source)),
|
|
div("wall-dialog-body", lf("This script wants to access {0}", description)),
|
|
buttons = div("wall-dialog-buttons",
|
|
HTML.mkButton(lf("deny"), () => {
|
|
allow = false; m.dismiss();
|
|
}),
|
|
HTML.mkButton(lf("allow"), () => {
|
|
allow = true; m.dismiss();
|
|
})
|
|
)
|
|
]);
|
|
if (critical) {
|
|
m.critical()
|
|
buttons.style.display = "none";
|
|
Util.setTimeout(5000, () => {
|
|
buttons.style.display = "block";
|
|
});
|
|
}
|
|
m.show();
|
|
});
|
|
});
|
|
}
|
|
|
|
public updateButtonsVisibility() {
|
|
if (this.isHeadless()) return
|
|
|
|
var wp = this.currentRt.getCurrentPage();
|
|
var element = this.fullScreenContainer.firstChild;
|
|
var isStopped = this.currentRt.isStopped();
|
|
this.titleContainer.style.display =
|
|
(!wp.chromeVisible || element) && !isStopped ? "none" : "block";
|
|
this.backBtnDiv.style.display = this.showBackButton() ? "block" : "none";
|
|
if (wp.chromeVisible) this.wallContainer.classList.remove('no-bar');
|
|
else this.wallContainer.classList.add('no-bar');
|
|
this.wallContainer.style.display = element ? "none" : "block";
|
|
this.fullScreenBtnRow.style.display = (Browser.screenshots || element) ? "block" : "none";
|
|
this.bottomBtnsDiv.style.display = (element || !this.bottomBtnsDiv.hasChildNodes()) ? "none" : "block";
|
|
for (var i = 0; i < this.bottomBtnsDiv.children.length; ++i)
|
|
this.bottomBtnsDiv.children[i].setFlag('disabled', isStopped);
|
|
}
|
|
|
|
public applyWallStyle() {
|
|
var w = this.getWall();
|
|
w.className = "wallWithColumns";
|
|
|
|
var h = SizeMgr.windowHeight;
|
|
|
|
Util.setTransform(w, "none");
|
|
Util.setupHDragToScroll(elt("wallContainer"));
|
|
Util.resetDragToScroll(w);
|
|
|
|
this.wallOrientation = 0;
|
|
this.wallWidth = 18.5 * SizeMgr.topFontSize * 0.8;
|
|
this.wallHeight = this.userWallHeight();
|
|
}
|
|
|
|
public publishSizeUpdate() {
|
|
if (this.currentRt) {
|
|
var p = this.currentRt.getCurrentPage();
|
|
if (p)
|
|
this.applyPageAttributes(p);
|
|
}
|
|
WallPage.applySizeUpdate(elt("wallOverlay"));
|
|
}
|
|
|
|
public additionalButtons(): HTMLElement[] { return []; }
|
|
public additionalFullScreenButtons(): HTMLElement[] { return []; }
|
|
public notifyRunState() {
|
|
this.updateButtonsVisibility();
|
|
}
|
|
public notifyBreakpointHit(bp: string) {
|
|
}
|
|
public notifyBreakpointContinue() {
|
|
}
|
|
public notifyTutorial(cmd: string) {
|
|
}
|
|
|
|
public initApiKeysAsync(): Promise // boolean : reload
|
|
{ return Promise.as(); }
|
|
public agreeTermsOfUseAsync(): Promise {
|
|
return Promise.as();
|
|
}
|
|
public keyboard: TDev.RT.RuntimeKeyboard = undefined;
|
|
|
|
private keyDown(e: KeyboardEvent): boolean {
|
|
return this.keyboard.keyDown(e);
|
|
}
|
|
|
|
private keyUp(e: KeyboardEvent): boolean {
|
|
return this.keyboard.keyUp(e);
|
|
}
|
|
|
|
private cssSetup = false;
|
|
public clearCss()
|
|
{
|
|
this.cssSetup = false
|
|
Util.childNodes(document.head).forEach(ch => {
|
|
if (ch.getAttribute && ch.getAttribute("data-td-css"))
|
|
document.head.removeChild(ch)
|
|
})
|
|
}
|
|
|
|
public importCss(css: string) {
|
|
this.cssSetup = true
|
|
if (css) {
|
|
var fileref = document.createElement("style")
|
|
fileref.appendChild(document.createTextNode(css));
|
|
fileref.setAttribute("data-td-css", "yes")
|
|
document.head.appendChild(fileref)
|
|
}
|
|
}
|
|
|
|
public showWall() {
|
|
Ticker.dbg("showWall");
|
|
|
|
var back = HTML.mkRoundButton("svg:back,black", lf("back"), Ticks.wallBack, () => this.backBtnHandler());
|
|
|
|
this.keyboard = new TDev.RT.RuntimeKeyboard(this.currentRt)
|
|
|
|
this.clearCss();
|
|
|
|
if (!SizeMgr.splitScreen) {
|
|
var keyMgr = KeyboardMgr.instance;
|
|
|
|
this.wallVisible = true;
|
|
if (this.keyState == null)
|
|
this.keyState = keyMgr.saveState();
|
|
|
|
keyMgr.btnShortcut(back, "Esc");
|
|
keyMgr.register("*keydown*", (e) => this.keyDown(e));
|
|
keyMgr.register("*keyup*", (e) => this.keyUp(e));
|
|
}
|
|
|
|
this.backBtnDiv = div("wallBack", back);
|
|
|
|
this.scriptTitleDiv.setChildren([this.currentRt.compiled.scriptTitle]);
|
|
|
|
|
|
this.cloudContainer = div("inlineBlock", this.cloudSymbol, this.cloudStatus);
|
|
this.cloudContainer.withClick(() => {
|
|
if (this.cs_hasCloudState)
|
|
TDev.RT.CloudData.sessionInfoAsync(this.currentRt);
|
|
});
|
|
|
|
this.wallContainer = divId("wallContainer", "pane", divId("theWall", null), divId("theWallFloat", null));
|
|
var wall = elt("wallOverlay");
|
|
this.titleContainer.setChildren([this.scriptTitleDiv, this.titleDiv, this.subtitleDiv]);
|
|
this.topBtnRow = divId("wallBtns", "wallBtnRow",
|
|
this.backBtnDiv, this.titleContainer, this.cloudContainer,
|
|
this.additionalButtons()
|
|
);
|
|
this.fullScreenBtnRow = divId("wallFullScreenBtns", "", this.additionalFullScreenButtons());
|
|
this.bottomBtnsDiv = divId("wallBottomBtns", "bottomButtons");
|
|
this.setFullScreenElement(null);
|
|
this.bgPictureContainer.setChildren([])
|
|
wall.setChildren([
|
|
this.bgPictureContainer,
|
|
this.wallContainer,
|
|
this.fullScreenContainer,
|
|
this.topBtnRow,
|
|
this.fullScreenBtnRow,
|
|
this.bottomBtnsDiv
|
|
]);
|
|
if (this.currentRt.compiled.showAd) {
|
|
wall.appendChildren([this.adContainer]);
|
|
TDev.RT.AdManager.initialize(this.adContainer);
|
|
}
|
|
if (this.showCopyright) {
|
|
this.computeCopyrightHeight()
|
|
this.wallContainer.style.bottom = this.copyrightHeight + "px";
|
|
var copyright = this.copyrightElement();
|
|
if (copyright) {
|
|
// copyright.style.height = this.copyrightHeight + "px";
|
|
wall.appendChild(copyright);
|
|
}
|
|
}
|
|
this.applyWallStyle();
|
|
wall.style.display = "block";
|
|
wall.style.opacity = "1";
|
|
Util.showLeftPanel(wall);
|
|
this.wallShown();
|
|
}
|
|
|
|
public getFullScreenCanvas(): HTMLCanvasElement {
|
|
if (this.fullScreenContainer.style.display !== "none") {
|
|
var el = this.fullScreenContainer.firstChild;
|
|
while (el != null && !(<any>el).toDataURL)
|
|
el = el.firstChild;
|
|
var fs = <HTMLCanvasElement>el;
|
|
if (fs != null)
|
|
return fs;
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
public toScreenshotCanvas(): HTMLCanvasElement {
|
|
var fs = this.getFullScreenCanvas();
|
|
if (fs != null) {
|
|
try {
|
|
// artificially render the wall background color to avoid transparent boards
|
|
var page = this.currentRt.getCurrentPage();
|
|
var bgColor = page.bgColor || 'white';
|
|
var bgPicture = page.bgPicture;
|
|
var canvas = <HTMLCanvasElement>document.createElement("canvas");
|
|
var w = fs.width;
|
|
var h = fs.height;
|
|
var f = 1;
|
|
if (h > w) {
|
|
if (h > 800) // too tall?
|
|
f = 800 / h;
|
|
} else {
|
|
if (w > 800) // too wide?
|
|
f = 800 / w;
|
|
}
|
|
canvas.width = Math.floor(w * f);
|
|
canvas.height = Math.floor(h * f);
|
|
var ctx = canvas.getContext("2d");
|
|
ctx.save();
|
|
ctx.fillStyle = bgColor;
|
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
if (bgPicture) {
|
|
var ww = page.bgPictureWidth;
|
|
var hh = page.bgPictureHeight;
|
|
var r = hh / ww;
|
|
var sr = canvas.height / canvas.width;
|
|
var left, top;
|
|
if (r > sr) {
|
|
hh = ww * sr;
|
|
left = 0;
|
|
top = (page.bgPictureHeight - hh) / 2;
|
|
} else {
|
|
ww = hh / sr;
|
|
top = 0;
|
|
left = (page.bgPictureWidth - ww) / 2;
|
|
}
|
|
ctx.drawImage(bgPicture, left, top, ww, hh, 0, 0, canvas.width, canvas.height);
|
|
}
|
|
ctx.drawImage(fs, 0, 0, canvas.width, canvas.height);
|
|
ctx.restore();
|
|
|
|
return canvas;
|
|
} catch (e) {
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
public otherwiseBack() { }
|
|
|
|
public backBtnHandler() {
|
|
Ticker.dbg("history.back from RuntimeHostBase.backBtnHandler");
|
|
if (Browser.notifyBackToHost && this.currentRt.getPageCount() == 1) // last page
|
|
Util.externalNotify("exit");
|
|
else
|
|
Util.goBack();
|
|
}
|
|
|
|
public notifyPageButtonUpdate(): void {
|
|
this.bottomBtnsDiv.removeAllChildren();
|
|
var page = this.currentRt.getCurrentPage();
|
|
for (var i = 0; i < page.buttons.length; i++) {
|
|
var button = page.buttons[i];
|
|
this.bottomBtnsDiv.appendChild(button.getElement());
|
|
}
|
|
if (page.buttons.length > 0) {
|
|
this.bottomBtnsDiv.style.display = 'block';
|
|
(<HTMLElement>this.getWall().firstChild).style.paddingBottom = '6em';
|
|
}
|
|
else {
|
|
this.bottomBtnsDiv.style.display = 'none';
|
|
(<HTMLElement>this.getWall().firstChild).style.paddingBottom = null;
|
|
}
|
|
|
|
this.notifyRunState();
|
|
}
|
|
|
|
public notifyPagePush(): void {
|
|
this.notifyPageButtonUpdate();
|
|
if (this.currentRt.getPageCount() > 1) {
|
|
var p = this.currentRt.getCurrentPage()
|
|
if (!SizeMgr.splitScreen)
|
|
Screen.pushModalHash("page" + p.id, () => {
|
|
this.currentRt.popPagesIncluding(p);
|
|
})
|
|
}
|
|
}
|
|
|
|
public notifyPagePop(p:WallPage): void {
|
|
this.notifyPageButtonUpdate();
|
|
if (!SizeMgr.splitScreen)
|
|
Screen.popModalHash("page" + p.id)
|
|
}
|
|
|
|
public notifyStopAsync(): Promise {
|
|
Ticker.dbg("notifyStop");
|
|
var p = this.currentRt.saveDataAsync();
|
|
this.notifyRunState();
|
|
if (!SizeMgr.splitScreen && this.backBtnDiv && this.backBtnDiv.firstChild)
|
|
KeyboardMgr.instance.btnShortcut(<HTMLElement>this.backBtnDiv.firstChild, "Esc");
|
|
return p;
|
|
}
|
|
|
|
private cs_hasCloudState = false;
|
|
private cs_status = "";
|
|
private cs_type = "";
|
|
private cs_color = "#000000";
|
|
public updateCloudState(hasCloudState: boolean, type: string, status: string) {
|
|
if (hasCloudState !== this.cs_hasCloudState || type !== this.cs_type || status !== this.cs_status)
|
|
{
|
|
if (!hasCloudState)
|
|
this.cloudSymbol.setChildren([]);
|
|
else {
|
|
var svg = SVG.getCloudSymbol(this.cs_color, type, status === "connected", 1.5);
|
|
//svg.style.width = "10em";
|
|
//svg.style.height = "1.5em";
|
|
this.cloudSymbol.setChildren(svg);
|
|
}
|
|
this.cs_hasCloudState = hasCloudState;
|
|
this.cs_type = type;
|
|
}
|
|
if (status !== this.cs_status)
|
|
{
|
|
this.cloudStatus.setChildren(status);
|
|
this.cs_status = status;
|
|
}
|
|
}
|
|
private updateCloudStateColor(color: string) {
|
|
if (this.cs_color != color) {
|
|
if (!this.cs_hasCloudState)
|
|
this.cloudSymbol.setChildren([]);
|
|
else {
|
|
var svg = SVG.getCloudSymbol(color, this.cs_type, this.cs_status === "connected", 1.5);
|
|
//svg.style.width = (10 * SizeMgr.topFontSize) + "px";
|
|
//svg.style.height = (1.5 * SizeMgr.topFontSize) + "px";
|
|
//svg.style.width = "10em";
|
|
// svg.style.height = "1.5em";
|
|
this.cloudSymbol.setChildren(svg);
|
|
}
|
|
this.cs_color = color;
|
|
}
|
|
}
|
|
|
|
|
|
public attachProfilingInfo(profile: any): void
|
|
{
|
|
}
|
|
|
|
public attachCoverageInfo(profile: any, showCoverage: boolean): void
|
|
{
|
|
}
|
|
|
|
public attachDebuggingInfo(runMap: RunBitMap, stackTrace: IPackedStackTrace, errorMessage: string): void
|
|
{
|
|
}
|
|
|
|
public canEditCode()
|
|
{
|
|
return false
|
|
}
|
|
|
|
public fixErrorIn(stableName:string, error:string): void
|
|
{
|
|
}
|
|
|
|
public wallHidden()
|
|
{
|
|
}
|
|
|
|
public wallShown()
|
|
{
|
|
}
|
|
|
|
public hideWallAsync()
|
|
{
|
|
Ticker.dbg("hideWallAsync");
|
|
if (this.keyState)
|
|
KeyboardMgr.instance.loadState(this.keyState);
|
|
if (!this.wallVisible) {
|
|
return Promise.as()
|
|
}
|
|
this.clearCss();
|
|
var wall = elt("wallOverlay");
|
|
this.keyState = null;
|
|
this.wallHidden();
|
|
|
|
return Util.animAsync("fadeOut", 200, wall).then(() => {
|
|
this.wallVisible = false;
|
|
wall.style.display = "none";
|
|
});
|
|
}
|
|
|
|
public goBack()
|
|
{
|
|
Ticker.dbg("history.back from RuntimeHostBase.goBack");
|
|
Util.goBack()
|
|
}
|
|
|
|
public notifyHideWall() : void
|
|
{
|
|
Ticker.dbg("notifyHideWall");
|
|
this.hideWallAsync().done(() => {
|
|
var f = TDev.onWallClose;
|
|
if (!!f) {
|
|
TDev.onWallClose = null;
|
|
f();
|
|
}
|
|
this.goBack()
|
|
});
|
|
}
|
|
|
|
/* overriden in EditorHost */
|
|
public exceptionActions(e: any): any { return null; }
|
|
/* overriden in EditorHost */
|
|
public attachScriptStackTrace(bug: BugReport): void { }
|
|
/* overriden in EditorHost */
|
|
public debugModeEnabled(): boolean { return false; }
|
|
|
|
public exceptionHandler(e:any)
|
|
{
|
|
Ticker.dbg("wallExceptionHandler");
|
|
|
|
e.includeSource = true;
|
|
|
|
var bug = Ticker.mkBugReport(e, "runtime error");
|
|
var msg = bug.exceptionMessage;
|
|
|
|
var runMap = this.currentRt.runMap;
|
|
var stack = PackedStackTrace.buildFrom(this.currentRt.getStackTrace());
|
|
TDev.RT.App.logException(e);
|
|
|
|
var actions = this.exceptionActions(e) || {}
|
|
|
|
var debugAction = actions.debug || Util.doNothing;
|
|
var stackTraceAction = actions.stack || Util.doNothing;
|
|
var cancelAction = Util.doNothing;
|
|
var error = ((e.isUserError && (e.message || e.name)) || "") + "";
|
|
|
|
function frown(d:ModalDialog)
|
|
{
|
|
d.addFirst(div("floatingFrown", ":("))
|
|
}
|
|
|
|
if(this.canEditCode() && !!e.syntaxErrorDeclName) {
|
|
var dial = ModalDialog.buttons(
|
|
lf("errors in the code?"),
|
|
lf("the script appears to have some errors. fix each error marked with a red :( symbol and try to run again"),
|
|
"",//"message",
|
|
"",//error,
|
|
HTML.mkButton(lf("edit code"), () => {
|
|
tick(Ticks.crashDialogEdit);
|
|
dial.dismiss(); this.fixErrorIn(e.syntaxErrorDeclName, error);
|
|
})
|
|
);
|
|
dial.fullYellow();
|
|
frown(dial)
|
|
} else if(!!e.isUserError) {
|
|
var dial = ModalDialog.buttons(
|
|
lf("the script crashed"),
|
|
this.canEditCode() ? lf("do you want do debug it?") : null,
|
|
lf("error message"),
|
|
error,
|
|
this.canEditCode() ? HTML.mkButton(lf("debug"), () => {
|
|
tick(Ticks.crashDialogDebug);
|
|
dial.dismiss(); this.attachDebuggingInfo(runMap, stack, msg); debugAction();
|
|
}) : null,
|
|
HTML.mkButton(lf("cancel"), () => {
|
|
dial.dismiss()
|
|
})
|
|
);
|
|
dial.fullYellow();
|
|
frown(dial)
|
|
} else { //!isUserError
|
|
this.attachScriptStackTrace(bug);
|
|
Util.sendErrorReport(bug);
|
|
|
|
var jsinfo:HTMLElement = dbg ? div("inlineBlock", HTML.mkButton(lf("js info (dbg)"),
|
|
() => {
|
|
jsinfo.className = "";
|
|
var addInfo = bug.stackTrace ? bug.stackTrace : "(none available)";
|
|
Browser.setInnerHTML(jsinfo, Util.formatText(addInfo));
|
|
})) : undefined;
|
|
|
|
var dial = ModalDialog.buttons(
|
|
"TouchDevelop crashed",
|
|
this.canEditCode() ? "do you want do debug the script?" : null,
|
|
null, null,
|
|
this.canEditCode() ? HTML.mkButton(lf("debug"), () => { dial.dismiss(); this.attachDebuggingInfo(runMap, stack, msg); debugAction(); }) : null,
|
|
jsinfo,
|
|
HTML.mkButton(lf("cancel"), () => { dial.dismiss() })
|
|
);
|
|
dial.fullYellow();
|
|
frown(dial)
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|