-
Notifications
You must be signed in to change notification settings - Fork 581
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DRAFT] Workspace layer refactor #7657
Changes from all commits
46c524c
cc33cf2
010da76
5f8085b
e15f586
195b4e1
20328c6
6909468
1c81516
b19911d
c975d5d
3ff57dd
a5063a7
423fe0a
7c73231
142b6c6
b64be99
631f200
c0fd88f
6d05fa5
98d30cb
c7bed33
ffdcbad
0300ad1
7da5f13
dfbd3db
a7523ad
bc8a1a3
b8e8393
f8201ce
6939562
e6c3f9b
94605ea
592c1ec
7971ff3
88717cf
d711126
71941fd
ae41778
be015c5
e83fd6e
8700481
49fb645
6b388a8
e970d53
bb676aa
a62252d
1d52319
a3155bd
d70f46a
0ea5813
1e93dd1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,23 +28,30 @@ declare namespace pxt.workspace { | |
tutorialCompleted?: pxt.tutorial.TutorialCompletionInfo; | ||
// workspace guid of the extension under test | ||
extensionUnderTest?: string; | ||
cloudSync?: boolean; // Mark a header for syncing with a cloud provider | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. note: |
||
// id of cloud user who created this project | ||
cloudUserId?: string; | ||
} | ||
|
||
export interface Header extends InstallHeader { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. header is meta info for a project |
||
id: string; // guid (generated by us) | ||
path?: string; // for workspaces that require it | ||
recentUse: number; // seconds since epoch | ||
modificationTime: number; // seconds since epoch | ||
recentUse: number; // seconds since epoch UTC (cloud safe) | ||
modificationTime: number; // seconds since epoch UTC (cloud safe) | ||
icon?: string; // icon uri | ||
|
||
isDeleted: boolean; // mark whether or not a header has been deleted | ||
saveId?: any; // used to determine whether a project has been edited while we're saving to cloud | ||
|
||
// TODO @darzu: remove all of these? | ||
|
||
// For cloud providers | ||
blobId: string; // id of the cloud blob holding this script | ||
blobVersion: string; // version of the cloud blob | ||
blobCurrent: boolean; // has the current version of the script been pushed to cloud | ||
// For cloud providers -- DEPRECATED | ||
blobId_: string; // id of the cloud blob holding this script | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. note that "project id" is assigned by client and its user ID + project ID. Note "id" field |
||
blobVersion_: string; // version of the cloud blob | ||
blobCurrent_: boolean; // has the current version of the script been pushed to cloud | ||
darzu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
cloudVersion: string; // The cloud-assigned version number (e.g. etag) | ||
// TODO @darzu: "cloudCurrent" seems very bad. This is a stateful notation and it is hard to reason about whether or not this is true. | ||
cloudCurrent: boolean; // Has the current version of the project been pushed to cloud | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO: do we need / how do we use cloudCurrent exactly? |
||
|
||
// Used for Updating projects | ||
backupRef?: string; // guid of backed-up project (present if an update was interrupted) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -215,12 +215,11 @@ namespace pxt.editor { | |
importExampleAsync(options: ExampleImportOptions): Promise<void>; | ||
showScriptManager(): void; | ||
importProjectDialog(): void; | ||
cloudSync(): boolean; | ||
cloudSignInDialog(): void; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cloudSignInDialog is unneeded because we have new dialog |
||
cloudSignOut(): void; | ||
removeProject(): void; | ||
editText(): void; | ||
|
||
hasCloudSync(): boolean; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. renamed from cloudSync to find usages checks to see if we're signed in. |
||
|
||
getPreferredEditor(): string; | ||
saveAndCompile(): void; | ||
updateHeaderName(name: string): void; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,8 +6,8 @@ | |
|
||
import * as React from "react"; | ||
import * as ReactDOM from "react-dom"; | ||
import * as workspace from "./workspace"; | ||
import * as cloudsync from "./cloudsync"; | ||
import * as workspace from "./workspaces/workspace"; | ||
import * as cloudsync from "./workspaces/cloudsync"; | ||
import * as data from "./data"; | ||
import * as pkg from "./package"; | ||
import * as core from "./core"; | ||
|
@@ -95,7 +95,7 @@ function setEditor(editor: ProjectView) { | |
} | ||
|
||
export class ProjectView | ||
extends data.Component<IAppProps, IAppState> | ||
extends auth.Component<IAppProps, IAppState> | ||
implements IProjectView { | ||
editor: srceditor.Editor; | ||
editorFile: pkg.File; | ||
|
@@ -173,7 +173,6 @@ export class ProjectView | |
this.openDeviceSerial = this.openDeviceSerial.bind(this); | ||
this.toggleGreenScreen = this.toggleGreenScreen.bind(this); | ||
this.toggleSimulatorFullscreen = this.toggleSimulatorFullscreen.bind(this); | ||
this.cloudSignInComplete = this.cloudSignInComplete.bind(this); | ||
this.toggleSimulatorCollapse = this.toggleSimulatorCollapse.bind(this); | ||
this.showKeymap = this.showKeymap.bind(this); | ||
this.toggleKeymap = this.toggleKeymap.bind(this); | ||
|
@@ -264,8 +263,13 @@ export class ProjectView | |
} | ||
this.saveFileAsync().done(); | ||
} else if (active) { | ||
// TODO @darzu: new code path maybe: | ||
// workspace.syncAsync().then(changed => this.reloadAsync()) | ||
// reloadAsync: this.loadHeaderAsync() | ||
// OR: subscribe to data api, on change, reload | ||
|
||
data.invalidate("header:*") | ||
if (workspace.isHeadersSessionOutdated() | ||
if (workspace.isHeadersSessionOutdated() // TODO @darzu: sync check point | ||
|| workspace.isHeaderSessionOutdated(this.state.header)) { | ||
pxt.debug('workspace: changed, reloading...') | ||
let id = this.state.header ? this.state.header.id : ''; | ||
|
@@ -1300,6 +1304,7 @@ export class ProjectView | |
return checkAsync.then(() => this.openHome()); | ||
|
||
let p = Promise.resolve(); | ||
// TODO @darzu: sync checkpoint | ||
if (workspace.isHeadersSessionOutdated()) { // reload header before loading | ||
pxt.log(`sync before load`) | ||
p = p.then(() => workspace.syncAsync().then(() => { })) | ||
|
@@ -1335,7 +1340,11 @@ export class ProjectView | |
if (editorState.searchBar === undefined) editorState.searchBar = oldEditorState.searchBar; | ||
} | ||
|
||
if (!h.cloudSync && this.cloudSync()) h.cloudSync = true; | ||
// If user is signed in, sync this project to the cloud. | ||
if (this.hasCloudSync()) { | ||
// TODO @darzu: this might not be where we want to attach the user to the project | ||
h.cloudUserId = this.getUser()?.id; | ||
} | ||
|
||
return compiler.newProjectAsync() | ||
.then(() => h.backupRef ? workspace.restoreFromBackupAsync(h) : Promise.resolve()) | ||
|
@@ -1442,6 +1451,7 @@ export class ProjectView | |
} | ||
|
||
// update recentUse on the header | ||
// TODO @darzu: this is saving hte project without text... | ||
return workspace.saveAsync(h) | ||
}).then(() => this.loadTutorialFiltersAsync()) | ||
.finally(() => { | ||
|
@@ -2006,62 +2016,6 @@ export class ProjectView | |
}) | ||
} | ||
|
||
/////////////////////////////////////////////////////////// | ||
//////////// Cloud //////////// | ||
/////////////////////////////////////////////////////////// | ||
|
||
cloudSync() { | ||
return this.hasSync(); | ||
} | ||
|
||
cloudSignInDialog() { | ||
const providers = cloudsync.providers(); | ||
if (providers.length == 0) | ||
return; | ||
if (providers.length == 1) | ||
providers[0].loginAsync().then(() => { | ||
this.cloudSignInComplete(); | ||
}) | ||
else { | ||
// TODO: Revisit in new cloud sync | ||
//this.signInDialog.show(); | ||
} | ||
} | ||
|
||
cloudSignOut() { | ||
core.confirmAsync({ | ||
header: lf("Sign out"), | ||
body: lf("You are signing out. Make sure that you commited all your changes, local projects will be deleted."), | ||
agreeClass: "red", | ||
agreeIcon: "sign out", | ||
agreeLbl: lf("Sign out"), | ||
}).then(r => { | ||
if (r) { | ||
const inEditor = !!this.state.header; | ||
// Reset the cloud workspace | ||
return workspace.resetCloudAsync() | ||
.then(() => { | ||
if (inEditor) { | ||
this.openHome(); | ||
} | ||
if (this.home) { | ||
this.home.forceUpdate(); | ||
} | ||
}) | ||
} | ||
return Promise.resolve(); | ||
}); | ||
} | ||
|
||
cloudSignInComplete() { | ||
pxt.log('cloud sign in complete'); | ||
initLogin(); | ||
cloudsync.syncAsync() | ||
.then(() => { | ||
this.forceUpdate(); | ||
}).done(); | ||
} | ||
|
||
/////////////////////////////////////////////////////////// | ||
//////////// Home ///////////// | ||
/////////////////////////////////////////////////////////// | ||
|
@@ -2251,7 +2205,7 @@ export class ProjectView | |
pubCurrent: false, | ||
target: pxt.appTarget.id, | ||
targetVersion: pxt.appTarget.versions.target, | ||
cloudSync: this.cloudSync(), | ||
cloudUserId: this.getUser()?.id, | ||
temporary: options.temporary, | ||
tutorial: options.tutorial, | ||
extensionUnderTest: options.extensionUnderTest | ||
|
@@ -3090,6 +3044,10 @@ export class ProjectView | |
} | ||
} | ||
|
||
hasCloudSync() { | ||
return this.isLoggedIn(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: maybe once we go to AAD we might not be able to store data ourselves and we might need OneDrive? Probably worth adding a TODO comment |
||
} | ||
|
||
showScriptManager() { | ||
this.scriptManagerDialog.show(); | ||
} | ||
|
@@ -3327,13 +3285,15 @@ export class ProjectView | |
} | ||
|
||
showResetDialog() { | ||
console.log("showResetDialog (1)") | ||
dialogs.showResetDialogAsync().done(r => { | ||
if (!r) return Promise.resolve(); | ||
return Promise.resolve() | ||
.then(() => { | ||
return pxt.winrt.releaseAllDevicesAsync(); | ||
}) | ||
.then(() => { | ||
console.log("showResetDialog (2)") | ||
return this.resetWorkspace(); | ||
}); | ||
}); | ||
|
@@ -4540,12 +4500,19 @@ document.addEventListener("DOMContentLoaded", () => { | |
const isSandbox = pxt.shell.isSandboxMode() || pxt.shell.isReadOnly(); | ||
const isController = pxt.shell.isControllerMode(); | ||
const theme = pxt.appTarget.appTheme; | ||
if (query["ws"]) workspace.setupWorkspace(query["ws"]); | ||
// TODO @darzu: this is bad. we shouldn't be choosing a workspace in two places (see "chooseWorkspace") | ||
if (query["ws"]) { | ||
workspace.setupWorkspace(query["ws"] as workspace.WorkspaceKind) | ||
} | ||
else if ((theme.allowParentController || isController) && pxt.BrowserUtils.isIFrame()) workspace.setupWorkspace("iframe"); | ||
else if (isSandbox) workspace.setupWorkspace("mem"); | ||
else if (pxt.winrt.isWinRT()) workspace.setupWorkspace("uwp"); | ||
else if (pxt.BrowserUtils.isIpcRenderer()) workspace.setupWorkspace("idb"); | ||
else if (pxt.BrowserUtils.isLocalHost() || pxt.BrowserUtils.isPxtElectron()) workspace.setupWorkspace("fs"); | ||
// TODO @darzu: uncomment. this disables filesystem workspace | ||
//else if (pxt.BrowserUtils.isLocalHost() || pxt.BrowserUtils.isPxtElectron()) workspace.setupWorkspace("fs"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO uncomment There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this disabled the filesystem workspace |
||
else { | ||
workspace.setupWorkspace("browser"); | ||
} | ||
Promise.resolve() | ||
.then(async () => { | ||
const href = window.location.href; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the difference between "Header" and "InstallHeader" ?