-
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
Conversation
@@ -28,7 +28,8 @@ 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 comment
The reason will be displayed to describe this comment to others. Learn more.
note:
was used to determine if a project was cloud synced (old Sam work?)
problem was it didn't distinguish account A or B
@@ -28,7 +28,8 @@ 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 | |||
// 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 comment
The reason will be displayed to describe this comment to others. Learn more.
header is meta info for a project
blobCurrent_: boolean; // has the current version of the script been pushed to cloud | ||
|
||
cloudVersion: string; // The cloud-assigned version number (e.g. etag) | ||
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 comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: do we need / how do we use cloudCurrent exactly?
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 comment
The 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
@@ -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 comment
The reason will be displayed to describe this comment to others. Learn more.
cloudSignInDialog is unneeded because we have new dialog
removeProject(): void; | ||
editText(): void; | ||
|
||
hasCloudSync(): boolean; |
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.
renamed from cloudSync to find usages
checks to see if we're signed in.
@@ -28,7 +28,8 @@ declare namespace pxt.workspace { | |||
tutorialCompleted?: pxt.tutorial.TutorialCompletionInfo; |
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" ?
@@ -3090,6 +3036,10 @@ export class ProjectView | |||
} | |||
} | |||
|
|||
hasCloudSync() { | |||
return this.isLoggedIn(); |
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.
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
@@ -4545,7 +4495,8 @@ document.addEventListener("DOMContentLoaded", () => { | |||
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"); | |||
//else if (pxt.BrowserUtils.isLocalHost() || pxt.BrowserUtils.isPxtElectron()) workspace.setupWorkspace("fs"); |
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.
TODO uncomment
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.
this disabled the filesystem workspace
} | ||
|
||
function deleteAsync(h: Header, prevVersion: Version, text?: ScriptText): Promise<void> { | ||
return Promise.resolve(); |
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.
add comment that this is intentionally left unimplemented ?
} | ||
|
||
function resetAsync(): Promise<void> { | ||
return Promise.resolve(); |
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.
TODO: need to implement
return Promise.resolve(); | ||
} | ||
|
||
export async function syncAsync(): Promise<any> { |
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.
modeled after: cloudsync.ts:syncAsync
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.
bi-directional,
looks at local cloud project headers (with matching user IDs)
looks at remote headers
resolves them
workspace.saveAsync(file.header, file.text, file.version); | ||
} else { | ||
// Conflict. | ||
// TODO: Figure out how to register these. |
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.
Need to show cloud status on the cards
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.
See Cloud Sync OneNote
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.
Do we need timestamps or incremental version numbers? Or the user in the loop?
LastWrite wins?
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.
hunch: auto-handling merges would be heavier lift and harder to get right than presenting options to user.
const FIELD_WORKING = "working"; | ||
export const UPLOADING = `${MODULE}:${FIELD_UPLOADING}`; | ||
export const DOWNLOADING = `${MODULE}:${FIELD_DOWNLOADING}`; | ||
export const WORKING = `${MODULE}:${FIELD_WORKING}`; |
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.
note these are activity flags globally.. maybe we want per-project? TBD
webapp/src/cloudsync.ts
Outdated
@@ -501,7 +503,7 @@ export function refreshToken() { | |||
} | |||
|
|||
export function syncAsync(): Promise<void> { | |||
return Promise.all([githubSyncAsync(), cloudSyncAsync()]) | |||
return Promise.all([githubSyncAsync(), cloud.syncAsync()]) |
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.
note important change: instead of local cloudSyncAsync function, we're pointing to new cloud.syncAsync
@@ -405,14 +405,14 @@ export class EditorPackage { | |||
} | |||
|
|||
savePkgAsync() { |
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.
Notes:
Work to do to work with our cloud stuff?
Switch blobCurrent to cloudCurrent ?
When you create a new project, it currently doesn't sync to the cloud. This might be responsible.. TBD
@@ -480,7 +475,7 @@ export class ProjectsCarousel extends data.Component<ProjectsCarouselProps, Proj | |||
} | |||
|
|||
fetchLocalData(): pxt.workspace.Header[] { | |||
const headers: pxt.workspace.Header[] = this.getData("header:*") |
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.
Note this was only fetching local headers... but it is called fetchLocal.. is it supposed to be local or cloud+local?
@@ -184,11 +185,11 @@ export class ScriptManagerDialog extends data.Component<ScriptManagerDialogProps | |||
.then(text => workspace.duplicateAsync(header, text, res)) | |||
.then(clonedHeader => { |
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.
called when you say "view all projects"
@@ -25,14 +25,9 @@ type Header = pxt.workspace.Header; | |||
type ScriptText = pxt.workspace.ScriptText; | |||
type WorkspaceProvider = pxt.workspace.WorkspaceProvider; | |||
type InstallHeader = pxt.workspace.InstallHeader; |
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.
NOTE about this file: this operates on a layer agnostic of the specific workspace; it uses the interfaces
webapp/src/workspace.ts
Outdated
let r = allScripts.map(e => e.header).filter(h => | ||
(withDeleted || !h.isDeleted) && | ||
!h.isBackup && | ||
(!h.cloudUserId || h.cloudUserId === cloudUserId)) |
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.
note this is now responsible for including cloud projects if signed in
let r = allScripts.map(e => e.header).filter(h => | ||
(withDeleted || !h.isDeleted) && | ||
!h.isBackup && | ||
(!h.cloudUserId || h.cloudUserId === cloudUserId)) | ||
r.sort((a, b) => b.recentUse - a.recentUse) | ||
return r | ||
} |
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.
Some thoughts on merging two workspaces (instead of layer cloud on top of workspace-agnostic layer):
- This was the path Sam and Peli took
- Might be easier to work offline if we're not merging workspaces?
- or maybe not?
@@ -1352,21 +1335,6 @@ export function saveToCloudAsync(h: Header) { | |||
return cloudsync.saveToCloudAsync(h) | |||
} | |||
|
|||
export function resetCloudAsync(): Promise<void> { |
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.
this wasn't used?
draft PR? |
Yes, I accidentally created it as non-draft and I don't see a way to demote it :( |
very hidden |
moved here: #7902 |
While working on cloud sync, I ended up discovering a bunch of inconsistencies and potential race conditions and other problems in our workspace layering, so I've started a clean up and refactor of that area of the code.
This is going on the back-burner however and we're going to take a simpler, incremental approach to cloud sync for now here: #7743
EDIT: closed and reopened here: #7902