Merge branch 'master' into load

This commit is contained in:
Michal Moskal 2015-03-17 14:16:31 -07:00
Родитель d73566ff31 4d200bfec1
Коммит e67217c6da
45 изменённых файлов: 400 добавлений и 457 удалений

Просмотреть файл

@ -124,7 +124,7 @@ function runAndComplete(cmds, task) {
});
}
mkSimpleTask('build/genmeta.js', [ 'tools', ], "tools/genmeta.ts");
mkSimpleTask('build/genmeta.js', [ 'tools', 'generated/help.cache' ], "tools/genmeta.ts");
file('build/api.js', expand([ "build/genmeta.js", "lib" ]), { async: true }, function () {
console.log("[P] generating build/api.js, localization.json and topiclist.json");
runAndComplete([

Просмотреть файл

@ -530,6 +530,7 @@ module TDev {
public generalFlags = PropertyFlags.None;
public _isImmutable = false;
public minSkill = 0;
public _stemName:string;
public isData:boolean;
public isBuiltin:boolean;
@ -574,6 +575,8 @@ module TDev {
public isExtensionEnabled() { return false }
public isImmutable() { return this._isImmutable }
// 1 block, 2 coder, 3 pro
public md_skill(sk: number) { this.minSkill = sk; }
public md_stem(n: string) { this._stemName = n; }
public md_obsolete() { this.isObsolete = true; }
public md_isData() { this.isData = true; }

Просмотреть файл

@ -2134,7 +2134,8 @@ module TDev.AST {
this.version = App.currentVersion;
}
static metaMapping = [ "showAd", "isLibrary", "allowExport", "isCloud", "hasIds" ];
// split screen is used as a hit when loaded in the editor, serialized when publishing
static metaMapping = [ "showAd", "isLibrary", "allowExport", "isCloud", "hasIds", "splitScreen" ];
public nodeType() { return "app"; }
public things:Decl[] = [];
@ -2189,7 +2190,8 @@ module TDev.AST {
public isDocsTopic() { return this.comment && /#docs/i.test(this.comment); }
public isTutorial() { return this.isDocsTopic() && this.allActions().some(a => /^#\d/.test(a.getName())) }
public allowExport:boolean;
public hasIds:boolean;
public hasIds: boolean;
public splitScreen: boolean;
private stillParsing:boolean = true;
public accept(v:NodeVisitor) { return v.visitApp(this); }
public children() { return this.things; }
@ -4214,6 +4216,10 @@ module TDev.AST {
});
}
secondaryRun(app: App)
{
}
run(app: App)
{
DeepVisitor.clearVisitorState(app);
@ -4237,6 +4243,7 @@ module TDev.AST {
this.useAction(a);
})
this.secondaryRun(app);
this.traverseActions();

Просмотреть файл

@ -1380,7 +1380,9 @@ module TDev.AST
var code = ""
function localName(l:LocalDef) {
return Api.runtimeName(l.getName().replace(/[?]/g, ""))
var r = Api.runtimeName(l.getName().replace(/[?]/g, ""))
if (r == "s" || r == "lib") return "_" + r
return r
}
function unterm(t:JsExpr)
@ -3106,5 +3108,14 @@ module TDev.AST
{
this.options.usedProperties[p.usageKey().toLowerCase()] = true
}
secondaryRun(app: App)
{
app.libraries().forEach(l => {
if (l.isTutorial()) {
l.getPublicActions().forEach(a => this.runOnDecl(a))
}
})
}
}
}

Просмотреть файл

@ -739,8 +739,7 @@ module TDev.AppExport
return wa
}
function chooseWebsiteCoreAsync(azureResults:any[]):Promise
{
function chooseWebsiteCoreAsync(azureResults: any[]): Promise {
var r = new PromiseInv()
var m = new ModalDialog()
@ -756,6 +755,18 @@ module TDev.AppExport
var keys = Object.keys(auths).map(k => auths[k])
keys.sort((a, b) => Util.stringCompare(a.website, b.website))
// populate data from local editor if any
if (LocalShell.mgmtUrl("")) {
var wa = <Azure.WebsiteAuth> {
deploymentKey: LocalShell.deploymentKey(),
key: 'custom:local',
website: 'local',
webspace: 'custom',
destinationAppUrl: LocalShell.url()
};
keys.splice(0, 0, wa);
}
var boxes = keys.map(wa =>
websiteBox(wa)
.withClick(() => {
@ -1238,16 +1249,6 @@ module TDev.AppExport
wa.destinationAppUrl = wa.destinationAppUrl.replace(/\/*$/, "/")
m.add(div("wall-dialog-header", lf("hooray! your web site is deployed")));
m.add(div('share-url', HTML.mkA('', wa.destinationAppUrl, 'tdwebapp', wa.destinationAppUrl)));
var lnk = RT.Link.mk(wa.destinationAppUrl, RT.LinkKind.hyperlink)
lnk.set_title(wa.website + " #touchdevelop")
var options = <RT.ShareManager.ShareOptions> {
header: "share this web site",
noDismiss: true,
justButtons: true
};
RT.ShareManager.addShareButtons(m, lnk, options)
m.addOk("close", () => {
m.dismiss();
});

Просмотреть файл

@ -2412,18 +2412,18 @@ module TDev
});
} else {
var maxScore = 1;
var singl:AST.SingletonDef[] = Calculator.sortDecls(api.getSingletons());
var singl: AST.SingletonDef[] = Calculator.sortDecls(api.getSingletons().filter(sg => sg.isBrowsable()));
var skill = AST.blockMode ? 1 : AST.legacyMode ? 2 : 3;
var libSingl:IntelliItem = null;
singl.forEach((s:AST.SingletonDef) => {
if (s.isBrowsable()) {
var sc = s.usage.count() + 1e-20;
sc *= s.usageMult();
var e = this.mkIntelliItem(sc, Ticks.calcIntelliSingleton);
if (sc > maxScore) maxScore = sc;
if (skill < s.getKind().minSkill) e.score -= 1e10;
e.decl = s;
if (s.getName() == AST.libSymbol)
libSingl = e;
}
});
var libs = Script.libraries().filter(l => l.isBrowsable()).map(l => {
@ -3873,9 +3873,9 @@ module TDev
TheEditor.adjustCodeViewSize(this.stmt);
}
private sortedIntelliItems()
private sortedIntelliItems() : IntelliItem[]
{
var items0 = this.currentIntelliItems;
var items0 = this.currentIntelliItems.filter(ii => ii.score > 0);
var usedProfile = false;
if (TheEditor.intelliProfile) {
var prof = TheEditor.intelliProfile;

Просмотреть файл

@ -605,10 +605,6 @@ module TDev
return TheEditor.debugSupported();
}
public publishRunHelpLink(title: string) {
return Editor.mkHelpLink("publishing run", title);
}
public fixErrorIn(stableName:string, error:string)
{
this.hideWallAsync().then(() => {
@ -3046,6 +3042,11 @@ module TDev
else return Promise.as();
}).then(() => {
if (!Script) return;
// if the script is not edited and it requires split screen, load split screen mode from meta
if (header.status === "published" && !!Script.splitScreen) {
Util.log('published script used split mode, splitting...');
this.setSplitScreen(true);
}
this.currentRt = new Runtime();
this.setupPlayButton();
@ -4401,6 +4402,8 @@ module TDev
{
Ticker.dbg("Editor.saveStateAsync");
if (!!Script) {
if (opts.forPublishing)
Script.splitScreen = !!Script.editorState.splitScreen
if (!opts.isRevert && !!this.currentCodeView)
this.currentCodeView.commit();
Script.setStableNames();
@ -5427,6 +5430,7 @@ module TDev
isRevert?: boolean;
clearScript?: boolean;
wasUpgraded?: boolean;
forPublishing?: boolean;
}
export class SearchForNode

Просмотреть файл

@ -20,13 +20,22 @@ module TDev.Browser {
}
export var hubThemes: StringMap<HubTheme> = {
'minecraft': {
description: 'Learn to code with Mineacraft',
logoArtId: 'eopyzwpm',
wallpaperArtId: 'abqqsurv',
tutorialsTopic: 'ysxp',
requiresShell: true,
scriptSearch: '#minecraft',
},
'arduino': {
description: 'Environment to program Arduino boards',
description: 'Program Arduino boards',
logoArtId: 'kzajxznr',
wallpaperArtId: 'kzajxznr',
tutorialsTopic: 'arduinotutorials',
requiresShell: true
}
requiresShell: true,
scriptSearch: '#arduino',
},
};
export enum EditorMode {
@ -475,22 +484,34 @@ module TDev.Browser {
if ((h[1] == "follow" || h[1] == "follow-tile") && /^\w+$/.test(h[2])) {
// temporary fix
if (h[2] == 'jumpingbird') h[2] = 'jumpingbirdtutorial';
Util.log('follow: {0}', h[2]);
this.browser().clearAsync(true)
.done(() => {
// try finding built-in topic first
var bt = HelpTopic.findById(h[2]);
if (bt)
if (bt) {
Util.log('found built-in topic');
TopicInfo.mk(bt).follow();
else
}
else {
TheApiCacheMgr.getAsync(h[2], true)
.then((res: JsonIdObject) => {
if (res && res.kind == "script" && res.id != (<JsonScript>res).updateid) {
Util.log('follow topic updated to ' + (<JsonScript>res).updateid);
return TheApiCacheMgr.getAsync((<JsonScript>res).updateid, true);
}
else return Promise.as(res);
})
.done(j => {
if (j && j.kind == "script") {
var ti = TopicInfo.mk(HelpTopic.fromJsonScript(j))
ti.follow();
} else Util.setHash("hub");
}, e => {
Util.log('follow route error: {0}, {1}' + h[2], e.message);
Util.setHash("hub");
});
}
});
return;
}
@ -753,7 +774,7 @@ module TDev.Browser {
})
}
public tutorialsByUpdateIdAsync()
public tutorialsByUpdateIdAsync(): Promise // StringMap<AST.HeaderWithState>
{
return this.browser().getTutorialsStateAsync().then((headers:AST.HeaderWithState[]) => {
var res = {}
@ -807,7 +828,7 @@ module TDev.Browser {
// - once this is done, we call [finish]
// - because we may have found the tutorial we wanted in the process, we
// return a new value for [top]
private findTutorial(templateId: string, finish) {
private findTutorial(templateId: string, finish: (res: { app: AST.App; headers: StringMap<AST.HeaderWithState> }, top: HelpTopic) => void) {
var top = HelpTopic.findById("t:" + templateId)
if (!this.headerByTutorialId || Date.now() - this.headerByTutorialIdUpdated > 3000) {
@ -816,7 +837,7 @@ module TDev.Browser {
}
if (top) {
Promise.join([Promise.as(null), this.headerByTutorialId]).done(res => finish(res, top));
Promise.join([Promise.as(null), this.headerByTutorialId]).done(res => finish({ app: res[0], headers: res[1] }, top));
} else {
var fetchingId = null
var fetchId = id => {
@ -830,7 +851,7 @@ module TDev.Browser {
fetchId(j.updateid);
else {
top = HelpTopic.fromJsonScript(j);
Promise.join([top.initAsync(), this.headerByTutorialId]).done(res => finish(res, top));
Promise.join([top.initAsync(), this.headerByTutorialId]).done(res => finish({ app: res[0], headers: res[1] }, top));
}
})
}
@ -869,20 +890,20 @@ module TDev.Browser {
{
var tileOuter = div("tutTileOuter")
var startTutorial = (top, header: Cloud.Header) => {
var startTutorial = (top : HelpTopic, header: Cloud.Header) => {
Util.log("tutorialTile.start: " + templateId)
if (f)
f(header);
this.startTutorial(top, header);
};
var finish = (res, top: HelpTopic) => {
var finish = (res: { app: AST.App; headers: StringMap<AST.HeaderWithState> }, top: HelpTopic) => {
var isHelpTopic = !!top;
var tile = div("tutTile")
tileOuter.setChildren([tile])
var app:AST.App = res[0]
var progs = res[1]
var app:AST.App = res.app
var progs = res.headers
var titleText = top.json.name.replace(/ (tutorial|walkthrough)$/i, "");
var descText = top.json.description.replace(/ #(docs|tutorials|stepbystep)\b/ig, " ")
@ -1037,7 +1058,8 @@ module TDev.Browser {
bySection[k].forEach((template: ScriptTemplate) => {
var icon = div("sdIcon");
icon.style.backgroundColor = ScriptIcons.stableColorFromName(template.title);
icon.setChildren([HTML.mkImg("svg:" + template.icon + ",white")]);
// missing icons
// icon.setChildren([HTML.mkImg("svg:" + template.icon + ",white")]);
var nameBlock = div("sdName", lf_static(template.title, true));
var hd = div("sdNameBlock", nameBlock);
@ -1826,12 +1848,12 @@ module TDev.Browser {
// Copied from [tutorialTitle], and (hopefully) simplified.
this.findTutorial(id, (res, topic: HelpTopic) => {
var key = topic.updateKey();
var header = res[1][key]; // may be null or undefined
var header = res.headers[key]; // may be null or undefined
k({
title: topic.json.name.replace(/ (tutorial|walkthrough)$/i, ""),
header: header,
topic: topic,
app: res[0],
app: res.app,
});
});
}
@ -1858,6 +1880,7 @@ module TDev.Browser {
: HTML.cssImage(HTML.proxyResource(tutorial.topic.json.screenshot));
btn.style.backgroundSize = "cover";
}
ScriptInfo.addTutorialProgress(btn, tutorial.header);
buttons.push(btn);
if (buttons.length == 6) {

Просмотреть файл

@ -5441,10 +5441,31 @@ module TDev { export module Browser {
div("hubTileTitle", spanDirAuto(this.app.getName())),
div("hubTileSubtitle",
div("hubTileAuthor", spanDirAuto(this.jsonScript.username), nums)))])
ScriptInfo.addTutorialProgress(d, this.cloudHeader);
});
return d;
}
static addTutorialProgress(d: HTMLElement, header : Cloud.Header) {
if (!header || !header.guid) return;
World.getInstalledEditorStateAsync(header.guid).done(text => {
if (!text) return;
var prog = <AST.AppEditorState>JSON.parse(text);
var num = prog.tutorialNumSteps - (prog.tutorialStep || 0);
if (prog.tutorialId && num > 0) {
var starSpan = span("bold",((prog.tutorialStep || 0) + 1) + "★");
var ofSteps = prog.tutorialNumSteps ? " of " + (prog.tutorialNumSteps + 1) : "";
d.appendChild(div("tutProgress",
((prog.tutorialStep && (prog.tutorialStep == prog.tutorialNumSteps)) ?
div(lf("steps done"), lf("done!"), div("label", starSpan))
:
div("steps", starSpan, ofSteps,
div("label", lf("tutorial progress"))))
))
}
});
}
public willWork() {
return !this.app || this.app.supportsAllPlatforms(api.core.currentPlatform);
}

Просмотреть файл

@ -72,7 +72,7 @@ module TDev
{
if (!app) app = Script
TheEditor.saveStateAsync({ forReal: true }).then(() => {
TheEditor.saveStateAsync({ forReal: true, forPublishing: true }).then(() => {
TheEditor.queueNavRefresh();
World.getInstalledHeaderAsync(app.localGuid).then((h: Cloud.Header) => {
if (h.status == "published") {
@ -195,13 +195,13 @@ module TDev
this.editor.showAppLog(app);
}));
if (!isParent && TheEditor.widgetEnabled("errorsButton"))
addBtn(HTML.mkRoundButton("svg:SmilieSad,black", lf("errors"), Ticks.sideErrors, () => {
addBtn(HTML.mkRoundButton("svg:SmilieSad,black", lf("errors"), Ticks.sideErrors,() => {
this.editor.typeCheckNow();
this.editor.searchFor(":m");
}));
if (onlyParent && isBeta && TheEditor.widgetEnabled("deployButton") &&
(Azure.getWebsiteAuthForApp(app) || app.usesCloudLibs() || Script.usesCloudLibs())) {
addBtn(HTML.mkRoundButton("svg:cloudupload,black", lf("deploy"), Ticks.sideDeployWebSite,() => {
if (onlyParent && TheEditor.widgetEnabled("deployButton")) {
addBtn(HTML.mkRoundButton("svg:cloudupload,black", lf("export"), Ticks.sideDeployWebSite,() => {
TDev.RT.App.clearLogs();
var wa = Azure.getWebsiteAuthForApp(app)
var recompile = Promise.as()
@ -217,9 +217,10 @@ module TDev
Script = res.prevScript
})
if (app.isCloud) {
recompile
.then(() => AppExport.deployLocalWebappAsync(app, wa))
.then(
.done(
() => AppExport.showStatus(wa),
err => {
if (app == Script)
@ -227,8 +228,10 @@ module TDev
else
ModalDialog.info(lf("deployment not configured"),
lf("Go to the main script and try to deploy from there."))
})
.done()
});
} else {
recompile.done(() => AppExport.deployCordova(app, this.editor.getBaseScriptId()));
}
}));
}

Просмотреть файл

@ -765,9 +765,8 @@ module TDev
// create a new tracking pixel and add it to the tree
var trackUrl = this.topic.pixelTrackingUrl();
if (trackUrl) {
// generate new id on demand
var anon = Script.editorState.tutorialAnonymousId;
if (!anon) anon = Script.editorState.tutorialAnonymousId = Util.guidGen();
var anon = this.loadAnonymousId();
if (anon) {
trackUrl += "?scriptid=" + this.progressId + "&index=" + prog.index + "&total=" + prog.numSteps + "&completed=" + !!prog.completed + "&time=" + prog.lastUsed + "&anonid=" + anon;
var pixel = <HTMLImageElement> document.createElement("img");
pixel.className = "tracking-pixel";
@ -776,12 +775,13 @@ module TDev
pixel.onerror = (el) => pixel.removeSelf();
elt("root").appendChild(pixel);
}
}
// pushing directly into event hubs
var eventHubsInfo = this.topic.eventHubsTracking();
if (eventHubsInfo) {
var anon = Script.editorState.tutorialAnonymousId;
if (!anon) anon = Script.editorState.tutorialAnonymousId = Util.guidGen();
var anon = this.loadAnonymousId();
if (anon) {
var client = new XMLHttpRequest();
var url = 'https://' + eventHubsInfo.namespace + '.servicebus.windows.net/' + eventHubsInfo.hub + '/publishers/' + anon + '/messages?timeout=60&api-version=2014-01';
Util.log('event hubs: ' + url);
@ -798,6 +798,22 @@ module TDev
}));
}
}
}
private loadAnonymousId(): string {
if (!Script || !this.topic.json) return "";
var anon = Script.editorState.tutorialAnonymousId;
if (!anon) {
var ids = JSON.parse(localStorage["tutorialAnonymousIds"] || "{}");
anon = ids[this.topic.json.userid];
if (!anon) {
anon = Script.editorState.tutorialAnonymousId = ids[this.topic.json.userid] = Util.guidGen();
localStorage["tutorialAnonymousIds"] = JSON.stringify(ids);
}
}
return anon;
}
public showDiff()
{
@ -847,10 +863,15 @@ module TDev
private nowPublish()
{
if (!Cloud.getUserId() || !Cloud.isOnline() || !Cloud.canPublish() || !Script)
TheEditor.leaveTutorial(); // always leave tutorial
// not generally signed in
if (!Cloud.getUserId() || !Cloud.isOnline() || !Cloud.canPublish() || !Script) return;
// author explicitely wanted to skip step
if (!this.topic || /none/i.test(this.topic.nextTutorials()[0]))
return;
TheEditor.leaveTutorial();
World.getInstalledHeaderAsync(Script.localGuid).done((h: Cloud.Header) => {
if (h.status == "published") return Promise.as();

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -307,6 +307,7 @@ module TDev.RT {
}
//? Interact with the app runtime
//@ skill(3)
export module App
{
export function createInfoMessage(s: string) : LogMessage {

Просмотреть файл

@ -1,6 +1,7 @@
///<reference path='refs.ts'/>
module TDev.RT {
//? Browse and review scripts from the bazaar
//@ skill(3)
export module Bazaar
{
//? Returns a user object for a specified user id

Просмотреть файл

@ -2,6 +2,7 @@
module TDev.RT {
//? Arithmetic and bitwise operations on 32 bit integers
//@ skill(3)
export module Bits
{
//? Add two unsigned 32 bit numbers

Просмотреть файл

@ -2,6 +2,7 @@
module TDev { export module RT {
//? Current box element in the page.
//@ skill(2)
export module Box
{
var R = HTML;
@ -387,7 +388,7 @@ module TDev { export module RT {
}
//? Current html element in the page.
//@ betaOnly
//@ betaOnly skill(2)
export module Dom {
//? Use CSS for layout and import additional CSS stylesheets. Use string art resource to import urls.
//@ betaOnly

Просмотреть файл

@ -1,8 +1,5 @@
///<reference path='refs.ts'/>
module TDev.RT {
//? A cloud data session
//@ ctx(general) stem("session") cap(cloudData) serializable
export class CloudSession
@ -143,7 +140,7 @@ module TDev.RT {
}
//? Cloud session management
//@ cap(cloudData)
//@ cap(cloudData) skill(3)
export module CloudData {

Просмотреть файл

@ -310,13 +310,12 @@ module TDev.RT {
//@ uiAsync returns(T)
public pick_entry(text: string, r: ResumeCtx) {
var rt = r.rt;
var getView = (o:any) => {
var getView = (o: any) => {
if (o.getIndexCard) return o.getIndexCard(r.stackframe)
else if (o.getViewCore) return o.getViewCore(r.stackframe, null)
else if (o.toString) return o.toString()
else return o + ""
};
if (rt.useModalWallDialogs()) {
var m = new ModalDialog();
var chosen = null;
var btns = this.a.map((o: any) => div('modalDialogChooseItem', getView(o)).withClick(() => {
@ -326,23 +325,6 @@ module TDev.RT {
m.add([div("wall-dialog-header", text)/* ,div("wall-dialog-body", caption)*/]);
m.onDismiss = () => r.resumeVal(chosen);
m.choose(btns);
} else {
var btnsDiv: HTMLElement;
var btns2 = this.a.map((o: any) => {
var btn = HTML.mkButtonElt("wall-button", getView(o));
Util.clickHandler(btn, () =>
{
r.resumeVal(o);
btnsDiv.removeSelf();
});
return btn;
});
var elt = div("wall-dialog",
[div("wall-dialog-header", text),
/*div("wall-dialog-body", caption),*/
btnsDiv = div("wall-dialog-buttons", btns2)]);
rt.postHtml(elt, rt.current.pc);
}
}
//? Computes the sum of the key of the elements in the collection

Просмотреть файл

@ -1,7 +1,7 @@
///<reference path='refs.ts'/>
//? Create collections of items.
//@ robust
//@ robust skill(3)
module TDev.RT.Collections
{

Просмотреть файл

@ -1,6 +1,7 @@
///<reference path='refs.ts'/>
module TDev.RT {
//? Correctness helpers
//@ skill(3)
export module Contract
{
//? Specifies a precondition contract for the action; if the condition is false, execution fails. Does nothing for published scripts.

Просмотреть файл

@ -1,7 +1,7 @@
///<reference path='refs.ts'/>
//? Create collections of items.
//@ robust
//@ robust skill(2)
module TDev.RT.Create
{
//? Creates an empty collection of arbitrary type

Просмотреть файл

@ -1,6 +1,7 @@
///<reference path='refs.ts'/>
module TDev.RT {
//? Create invalid values
//@ skill(3)
export module Invalid
{

Просмотреть файл

@ -188,6 +188,7 @@ module TDev.RT {
}
//? Translation, speech to text, ...
//@ skill(2)
export module Languages
{

Просмотреть файл

@ -1,6 +1,7 @@
///<reference path='refs.ts'/>
module TDev.RT {
//? OneDrive, OneNote operations
//@ skill(3)
export module CloudStorage {
//? Prompts the user to upload a picture to OneDrive. If the filename is empty, a default filename gets generated.
//@ async returns(CloudPicture) cap(cloudservices)

Просмотреть файл

@ -1,9 +1,9 @@
///<reference path='refs.ts'/>
module TDev.RT {
//? Geo coordinates
//@ skill(3)
export module Locations
{
//? Creates a new geo coordinate location
export function create_location(latitude:number, longitude:number) : Location_ { return Location_.mk(latitude, longitude, undefined, undefined, undefined, undefined, undefined) }

Просмотреть файл

@ -1,6 +1,7 @@
///<reference path='refs.ts'/>
module TDev.RT {
//? Maps, location to address, address to location
//@ skill(3)
export module Maps
{
//? Creates a Bing map. Use 'post to wall' to display it.

Просмотреть файл

@ -2,6 +2,7 @@
module TDev.RT {
//? Pictures and music...
//@ skill(2)
export module Media
{

Просмотреть файл

@ -1,6 +1,7 @@
///<reference path='refs.ts'/>
module TDev.RT {
//? Phone numbers, vibrate, etc...
//@ skill(2)
export module Phone
{
//? Starts a phone call

Просмотреть файл

@ -1,6 +1,7 @@
///<reference path='refs.ts'/>
module TDev.RT {
//? Play, stop or resume songs, ...
//@ skill(3)
export module Player
{
var _rt: Runtime;

Просмотреть файл

@ -1,6 +1,7 @@
///<reference path='refs.ts'/>
module TDev { export module RT {
//? Access to the radio
//@ skill(3)
export module Radio
{
//? Indicates if the radio is on

Просмотреть файл

@ -1,9 +1,9 @@
///<reference path='refs.ts'/>
module TDev.RT {
//? Emails, sms, contacts, calendar, ...
//@ skill(2)
export module Social
{
//? Opens the mail client
//@ flow(SinkSharing) uiAsync
export function send_email(to:string, subject:string, body:string, r : ResumeCtx) : void

Просмотреть файл

@ -1,6 +1,7 @@
///<reference path='refs.ts'/>
module TDev.RT {
//? 2D barcodes, QR codes and NFC tags
//@ skill(3)
export module Tags
{
export var sendNFC = (writeTag:boolean, type : string, value: string, sent : (id : number) => void, transferred : () => void) =>

Просмотреть файл

@ -12,7 +12,7 @@ module TDev.RT {
}
//? tiles and notifications for Windows and Windows Phone
//@ cap(tiles)
//@ cap(tiles) skill(3)
export module Tiles
{
export var updateTileAsync = (fragment : string, data : ITileData) : Promise =>

Просмотреть файл

@ -1,7 +1,7 @@
///<reference path='refs.ts'/>
module TDev.RT {
//? time and dates
//@ robust
//@ robust skill(2)
export module Time
{
var _rt : Runtime;

Просмотреть файл

@ -1,6 +1,7 @@
///<reference path='refs.ts'/>
module TDev.RT {
//? Support for interactive tutorials.
//@ skill(3)
export module Tutorial
{
//? Signal that the step is done.

Просмотреть файл

@ -24,99 +24,56 @@ module TDev.RT {
//? Prompts the user with a ok button
//@ tandre2
//@ uiAsync
export function prompt(text:string, r: ResumeCtx) : void
{
export function prompt(text: string, r: ResumeCtx): void {
var rt = r.rt;
if (rt.useModalWallDialogs()) {
var m = new ModalDialog();
m.add([body(text),
div("wall-dialog-buttons",
[R.mkButtonOnce("ok", () => m.dismiss())])
[R.mkButtonOnce("ok",() => m.dismiss())])
]);
m.onDismiss = () => r.resume();
m.show();
} else {
var btns;
var elt = div("wall-dialog",
[body(text),
btns = div("wall-dialog-buttons",
[R.mkButtonOnce("ok", () => {
Screen.popModalHash("wall");
r.resume();
})])
]);
rt.postHtml(elt, rt.current.pc);
Screen.pushModalHash("wall", () => {
btns.removeSelf();
r.resume();
});
}
}
//? Prompts the user with ok and cancel buttons
//@ returns(boolean)
//@ tandre2
//@ uiAsync
export function ask_boolean(text:string, caption:string, r:ResumeCtx)
{
export function ask_boolean(text: string, caption: string, r: ResumeCtx) {
var rt = r.rt;
if (rt.useModalWallDialogs()) {
var value = false;
var m = new ModalDialog();
m.add([div("wall-dialog-header", text),
body(caption),
div("wall-dialog-buttons",
[R.mkButton(lf("no"), () => {
[R.mkButton(lf("no"),() => {
value = false;
m.dismiss();
}),
R.mkButton(lf("yes"), () => {
R.mkButton(lf("yes"),() => {
value = true;
m.dismiss();
})])
]);
m.onDismiss = () => r.resumeVal(value);
m.show();
} else {
var btns;
var elt = div("wall-dialog",
[div("wall-dialog-header", text),
body(caption),
btns = div("wall-dialog-buttons",
[R.mkButtonOnce("no", () => {
Screen.popModalHash("wall");
r.resumeVal(false)
}, true),
R.mkButtonOnce("yes", () => {
Screen.popModalHash("wall");
r.resumeVal(true)
}, true)])
]);
rt.postHtml(elt, rt.current.pc);
Screen.pushModalHash("wall", () => {
btns.removeSelf();
r.resumeVal(false);
});
}
}
//? Prompts the user to input a number
//@ returns(number)
//@ tandre2
//@ uiAsync
export function ask_number(text:string, r:ResumeCtx)
{
export function ask_number(text: string, r: ResumeCtx) {
var rt = r.rt;
var t = R.mkTextInput("number", lf("enter a decimal number"));
t.value = "";
if (rt.useModalWallDialogs()) {
var value = 0;
var m = new ModalDialog();
m.add([
body(text),
div("wall-dialog-input", t),
div("wall-dialog-buttons",
[R.mkButton(lf("ok"), () => {
[R.mkButton(lf("ok"),() => {
value = t.valueAsNumber;
if (!isFinite(value)) value = parseFloat(t.value); // Firefox
if (!isFinite(value)) value = undefined;
@ -125,32 +82,6 @@ module TDev.RT {
]);
m.onDismiss = () => r.resumeVal(value);
m.show();
} else {
var btns;
var elt = div("wall-dialog",
[body(text),
div("wall-dialog-input", t),
btns = div("wall-dialog-buttons",
[R.mkButtonOnce("ok", () => {
Screen.popModalHash("wall");
btns.removeSelf();
var x = t.valueAsNumber;
if (!isFinite(x)) x = parseFloat(t.value); // Firefox
if (!isFinite(x)) x = undefined;
t.blur();
t.setAttribute("readonly", "true");
// popup keyboard takes a while to dissapear in wp
Util.setTimeout(500, () => r.resumeVal(x));
})])
]);
rt.postHtml(elt, rt.current.pc);
Screen.pushModalHash("wall", () => {
btns.removeSelf();
t.blur();
t.setAttribute("readonly", "true");
Util.setTimeout(500, () => r.resumeVal(undefined));
});
}
Util.setKeyboardFocus(t);
}
@ -158,48 +89,22 @@ module TDev.RT {
//@ returns(string)
//@ tandre2
//@ uiAsync
export function ask_string(text:string, r:ResumeCtx)
{
export function ask_string(text: string, r: ResumeCtx) {
var rt = r.rt;
var t = R.mkTextArea("variableDesc");
t.value = "";
if (rt.useModalWallDialogs()) {
var value = "";
var m = new ModalDialog();
m.add([body(text),
div("wall-dialog-input", t),
div("wall-dialog-buttons",
[R.mkButton(lf("ok"), () => {
[R.mkButton(lf("ok"),() => {
value = t.value;
m.dismiss();
})])
]);
m.onDismiss = () => r.resumeVal(value);
m.show();
} else {
var btns;
var elt = div("wall-dialog",
[body(text),
div("wall-dialog-input", t),
btns = div("wall-dialog-buttons",
[R.mkButtonOnce("ok", () => {
Screen.popModalHash("wall");
t.blur();
t.setAttribute("readonly", "true");
var v = t.value;
// popup keyboard takes a while to dissapear in wp
Util.setTimeout(500, () => r.resumeVal(v));
})])
]);
Screen.pushModalHash("wall", () => {
btns.removeSelf();
t.blur();
t.setAttribute("readonly", "true");
// popup keyboard takes a while to dissapear in wp
Util.setTimeout(500, () => r.resumeVal(""));
});
rt.postHtml(elt, rt.current.pc);
}
Util.setKeyboardFocusTextArea(t);
}
@ -226,10 +131,8 @@ module TDev.RT {
//@ returns(number)
//@ tandre2
//@ uiAsync
export function pick_string(text:string, caption:string, values:Collection<string>, r:ResumeCtx)
{
export function pick_string(text: string, caption: string, values: Collection<string>, r: ResumeCtx) {
var rt = r.rt;
if (rt.useModalWallDialogs()) {
var m = new ModalDialog();
var index = -1;
var btns = values.a.map((st: string, i: number) => div('modalDialogChooseItem', st).withClick(() => {
@ -240,23 +143,6 @@ module TDev.RT {
body(caption)]);
m.onDismiss = () => r.resumeVal(index);
m.choose(btns);
} else {
var btnsDiv : HTMLElement;
var btns2 = values.a.map((st:string, i:number) => R.mkButton(st, () => {
r.resumeVal(i);
Screen.popModalHash("wall");
btnsDiv.removeSelf();
}));
var elt = div("wall-dialog",
[div("wall-dialog-header", text),
body(caption),
btnsDiv = div("wall-dialog-buttons", btns2)]);
rt.postHtml(elt, rt.current.pc);
Screen.pushModalHash("wall", () => {
btnsDiv.removeSelf();
r.resumeVal(-1);
});
}
}
//? Prompts the user to pick a time. Returns a datetime whose time is set, the date is undefined.
@ -270,10 +156,9 @@ module TDev.RT {
var t = R.mkTextInput("time", lf("enter a time"));
t.style.borderStyle = 'hidden';
t.style.borderColor = 'red';
t.onkeyup = (ev : Event) => {
t.onkeyup = (ev: Event) => {
t.style.borderStyle = String_.to_time(t.value) != null ? 'hidden' : 'solid';
};
if (rt.useModalWallDialogs()) {
var value: DateTime = undefined;
var m = new ModalDialog();
m.add([div("wall-dialog-header", text),
@ -281,7 +166,7 @@ module TDev.RT {
div("wall-dialog-input", t),
body("Enter a time like 15:43 or 3:43pm or 15:43:20 or 3:43:20pm"),
div("wall-dialog-buttons",
[R.mkButton(lf("ok"), () => {
[R.mkButton(lf("ok"),() => {
var tt = String_.to_time(t.value);
if (tt != null)
value = Time.today().add_seconds(tt);
@ -290,33 +175,6 @@ module TDev.RT {
]);
m.onDismiss = () => r.resumeVal(value);
m.show();
} else {
var btns;
var elt = div("wall-dialog",
[div("wall-dialog-header", text),
body(caption),
div("wall-dialog-input", t),
body("Enter a time like 15:43 or 3:43pm or 15:43:20 or 3:43:20pm"),
btns = div("wall-dialog-buttons",
[R.mkButtonOnce("ok", () => {
Screen.popModalHash("wall");
t.blur();
t.setAttribute("readonly", "true");
var tt = String_.to_time(t.value);
var ti = (tt != null) ? Time.today().add_seconds(tt) : undefined;
// popup keyboard takes a while to dissapear in wp
Util.setTimeout(500, () => r.resumeVal(ti));
})])
]);
rt.postHtml(elt, rt.current.pc);
Screen.pushModalHash("wall", () => {
btns.removeSelf();
t.blur();
t.setAttribute("readonly", "true");
// popup keyboard takes a while to dissapear in wp
Util.setTimeout(500, () => r.resumeVal(undefined));
});
}
Util.setKeyboardFocus(t);
}
@ -334,45 +192,19 @@ module TDev.RT {
t.onkeyup = (ev: Event) => {
t.style.borderStyle = DateTime.parse(t.value) != null ? 'hidden' : 'solid';
};
if (rt.useModalWallDialogs()) {
var value: DateTime = undefined;
var m = new ModalDialog();
m.add([div("wall-dialog-header", text),
body(caption),
div("wall-dialog-input", t),
div("wall-dialog-buttons",
[R.mkButton(lf("ok"), () => {
[R.mkButton(lf("ok"),() => {
value = DateTime.parse(t.value);
m.dismiss();
})])
]);
m.onDismiss = () => r.resumeVal(value);
m.show();
} else {
var btns;
var elt = div("wall-dialog",
[div("wall-dialog-header", text),
body(caption),
div("wall-dialog-input", t),
btns = div("wall-dialog-buttons",
[R.mkButtonOnce("ok", () => {
Screen.popModalHash("wall");
t.blur();
t.setAttribute("readonly", "true");
var dt = DateTime.parse(t.value);
// popup keyboard takes a while to dissapear in wp
Util.setTimeout(500, () => r.resumeVal(dt));
})])
]);
rt.postHtml(elt, rt.current.pc);
Screen.pushModalHash("wall", () => {
btns.removeSelf();
t.blur();
t.setAttribute("readonly", "true");
// popup keyboard takes a while to dissapear in wp
Util.setTimeout(500, () => r.resumeVal(undefined));
});
}
Util.setKeyboardFocus(t);
}

Просмотреть файл

@ -138,6 +138,7 @@ module TDev.RT {
}
//? Search and browse the web...
//@ skill(2)
export module Web {
export interface MessageWaiter {
origin: string;

Просмотреть файл

@ -20,12 +20,12 @@
"type": "MIT"
}],
"bugs":"http://github.com/microsoft/TouchDevelop/issues",
"repositories": [{
"repository": {
"type": "git",
"url": "http://github.com/microsoft/TouchDevelop.git",
"path": "node-webkit"
}],
},
"dependencies": {
"faye-websocket": "0.8.1"
"faye-websocket": "0.9.*"
}
}

Просмотреть файл

@ -314,6 +314,7 @@ module TDev
public webState: RT.Web.State = <any>{};
private state: RtState = RtState.Stopped;
private stateMsg: string = undefined;
// when an event is executing, no other event can start
private eventExecuting = false;
// used to prevent recursive invocations of mainLoop
@ -456,8 +457,6 @@ module TDev
else return [r.result];
}
private isReplaying = false;
private eventCategory: string = null;
private eventVariable: string = null;
public setNextEvent(c: string, v: string) {
@ -469,19 +468,6 @@ module TDev
this.eventVariable = null;
}
private replayStartTime: number;
private currentOffset: number;
public startReplay() {
this.isReplaying = true;
this.replayStartTime = new Date().getTime();
}
public stopReplayAsync() {
var p = this.stopAsync();
this.isReplaying = false;
return p;
}
public currentTime() {
return Util.perfNow();
}
@ -526,13 +512,6 @@ module TDev
////////////////////////////////////////////////////////////////////////
// Wall methods
////////////////////////////////////////////////////////////////////////
public useModalWallDialogs(): boolean {
if (this.rendermode)
Util.userError(lf("cannot ask user in page display code"));
return this.host.isFullScreen() ||
!this.mayPostToWall(this.getCurrentPage());
}
public mayPostToWall(p: WallPage): boolean {
return !this.headlessPluginMode && (!p.isAuto() || this.rendermode || p.crashed)
@ -1089,6 +1068,7 @@ module TDev
HistoryMgr.instance.clearModalStack();
}
if (this.state != RtState.Stopped) {
this.setState(RtState.Stopped, "stopAsync");
if (!isPause) {
this.versionNumber++;
if (this.eventQ) this.eventQ.clear();
@ -1099,7 +1079,6 @@ module TDev
ProgressOverlay.hide()
this.asyncStack = [];
this.asyncTasks = [];
this.setState(RtState.Stopped, "stopAsync");
this.compiled.stopFn(this);
if (!isPause && !this.resumeAllowed && !this.handlingException) {
var profilingData = this.compiled._getProfilingResults();
@ -1490,6 +1469,7 @@ module TDev
if (this.state == RtState.Stopped || s == RtState.Stopped)
Util.log("runtime state: {0} -> {1}, {2}", this.state, s, msg)
this.state = s;
this.stateMsg = msg;
}
private getResumeCtxCore(isBlocking: boolean, cont: IContinuationFunction) {
@ -2053,8 +2033,8 @@ module TDev
return;
}
// var lastBreak = Date.now();
var continueLater = false;
var continueLaterVersion = 0;
var numCheck = 0;
this.mainLoopRunning = true;
@ -2102,6 +2082,7 @@ module TDev
var now = Date.now();
if (now - this.lastBreak > (Browser.isNodeJS ? 1000 : 50)) {
continueLater = true;
continueLaterVersion = this.versionNumber;
break;
}
numCheck = 0;
@ -2112,7 +2093,7 @@ module TDev
}
this.mainLoopRunning = false;
if (continueLater) {
if (continueLater && continueLaterVersion == this.versionNumber && this.state != RtState.Stopped) {
this.setState(RtState.Paused, "continue later");
var ver = this.versionNumber;
var curr = this.current

Просмотреть файл

@ -47,7 +47,7 @@ module TDev {
export function canSplitScreen()
{
return !phoneMode && windowWidth*1.2 > windowHeight;
return !phoneMode && !portraitMode && windowWidth*1.2 > windowHeight;
}
export function setSplitScreen(isSplit:boolean)

Просмотреть файл

@ -754,9 +754,16 @@ module TDev{
(<any>e).programCounter = pc;
(<any>e).isUserError = true;
if (statusCode)
(<any>e).statusCode = 500;
(<any>e).statusCode = statusCode;
try {
throw e;
}
catch (err) {
Util.log('error: {0}, {1}, {2}', msg, pc, statusCode);
Util.log(err.stack + "");
throw e;
}
}
export function syntaxError(msg:string, declName:string) : any
{

Просмотреть файл

@ -1,6 +1,18 @@
///<reference path='../typings/node/node.d.ts'/>
import fs = require('fs');
var fileLog: (msg: string) => void = undefined;
if (process.env["TD_SHELL_LOG_FILE"]) {
var logPath = process.env["TD_SHELL_LOG_FILE"];
fileLog = (msg) => {
var fl = fs.openSync(logPath, "a");
var b = new Buffer(msg + '\r\n');
fs.writeSync(fl, b, 0, b.length, 0);
fs.closeSync(fl);
}
}
import url = require('url');
import http = require('http');
import https = require('https');
@ -54,9 +66,8 @@ class Logger {
logMsgs:LogMessage[] = [];
logSz = 1000;
constructor(public level:number)
{
}
constructor(public name : string, public level:number)
{}
addMsg(s:string)
{
@ -64,6 +75,7 @@ class Logger {
timestamp: Date.now(),
msg: s
}
if (fileLog) fileLog(s);
if (!inAzure) console.log(s)
if (this.logIdx >= 0) {
this.logMsgs[this.logIdx++] = m;
@ -108,9 +120,9 @@ class Logger {
}
}
var error = new Logger(3)
var info = new Logger(6)
var debug = new Logger(7)
var error = new Logger("error", 3)
var info = new Logger("info", 6)
var debug = new Logger("debug", 7)
class ApiRequest {
data:any = {}
@ -296,7 +308,6 @@ function downloadFile(u:string, f:(err:any, s:NodeBuffer, h?:any)=>void)
g.on('end', () => {
var total = Buffer.concat(bufs)
//console.log("download file: " + u + " " + total.length)
f(null, total, (<any>res).headers)
})
@ -652,7 +663,7 @@ function clone<T>(obj: T): T {
function createProcess(d:RunCliOptions)
{
var isWin = /^win/.test(os.platform())
debug.log("running: " + d.command + (d.args ? (" " + d.args.join(" ")) : ""))
debug.log("running: " + (d.cwd || "") + ">" + d.command + (d.args ? (" " + d.args.join(" ")) : ""))
var env = clone(d.env || process.env);
if (pythonEnv) Object.keys(pythonEnv).forEach(k => env[k] = pythonEnv[k]);
var proc = child_process.spawn(d.args ? d.command : isWin ? "cmd" : "sh", d.args || [isWin ? "/c" : "-c", d.command], {
@ -1576,7 +1587,6 @@ function proxyEditor(cmds:string[], req, resp)
s = (<any>s).replace(/(browsers|error)Url = .*/g, (a, b) => b + "Url = \"" + selfUrl + "/" + specRel + "/" + b + "\"")
}
s = s.replace(/localProxy = ".*"/, 'localProxy = "yes"')
//console.log(specRel)
if (rel == "local") {
s = s.replace(/betaFriendlyId = ".*"/, "betaFriendlyId = \"(local)\"")
} else if (specRel == "current") {
@ -1886,7 +1896,7 @@ function respawnLoop()
console.error("Too many failures, aborting. Please retry manually.");
process.exit();
} else {
console.log("Failure, retrying in 5s...");
debug.log("Failure, retrying in 5s...");
setTimeout(startOne, 5000);
}
}

Просмотреть файл

@ -423,6 +423,7 @@ module TDev {
time("readdb1");
if (syncVersion != mySyncVersion) return canceled;
data.items = data.indexTable.getItemsAsync(data.keys)
if (!Cloud.lite)
data.scriptVersionsInCloudItems = data.scriptsTable.getItemsAsync(data.keys.map((guid) => guid + "-scriptVersionInCloud"));
return Promise.join(data);
}).then(function (data/*: SyncData*/) {

Просмотреть файл

@ -3651,6 +3651,7 @@ var sectAzure = lf("web sites");
var sectMakers = lf("makers");
var sectTouchDevelop = lf("touchdevelop");
var sectOthers = lf("others");
var sectMinecraft = "Minecraft";
/*
editorMode: 1 = block, 2 = coder, 3 = expert
@ -3687,7 +3688,7 @@ var templates: ScriptTemplate[] = [{
title: lf("blank turtle"),
id: 'blankturtle',
icon: 'Controller',
name: 'ADJ drawing',
name: 'ADJ turtle',
description: lf("An turtle app."),
section: sectBeginners,
scriptid: 'oobxb',
@ -3710,8 +3711,25 @@ var templates: ScriptTemplate[] = [{
section: sectBeginners,
scriptid: 'mdrw',
editorMode: 1,
}, {
title: lf("blank minecraft pi"),
id: 'blankminecraftpi',
icon: 'NineColumn',
name: 'ADJ craft',
description: lf("A Minecraft Pi app."),
section: sectMinecraft,
scriptid: 'cptje',
editorMode: 1,
}, {
title: lf("blank minecraft steve"),
id: 'blankminecraftsteve',
icon: 'NineColumn',
name: 'ADJ steve',
description: lf("A Minecraft Steve app."),
section: sectMinecraft,
scriptid: 'qzky',
editorMode: 1,
},
/*{
title: lf("blank boostrap app"),
id: 'blankbootstrapapp',

Просмотреть файл

@ -5345,6 +5345,7 @@ img.tracking-pixel {
.tutProgress {
background: #09b;
color:white;
position: absolute;
right: 0;
top: 0;