Browse Source

Rationalize `restored` handling.

Afshin Darian 6 years ago
parent
commit
4ef87c80fa

+ 7 - 16
packages/application/src/frontend.ts

@@ -23,7 +23,7 @@ import { Widget } from '@phosphor/widgets';
  * The generic `T` argument indicates the type that the plugin `provides` upon
  * being activated.
  */
-export type JupyterFrontEndPlugin<T> = IPlugin<JupyterFrontEnd<any, any>, T>;
+export type JupyterFrontEndPlugin<T> = IPlugin<JupyterFrontEnd, T>;
 
 /**
  * The base Jupyter front-end application class.
@@ -36,28 +36,20 @@ export type JupyterFrontEndPlugin<T> = IPlugin<JupyterFrontEnd<any, any>, T>;
  *
  * `T extends JupyterFrontEnd.Shell = JupyterFrontEnd.Shell` - the type of the
  * `shell` attribute of a `JupyterFrontEnd`.
- *
- * `U = void` - the type that the front-end application's `restored` promise
- * will resolve with. If a `restored` promise is not defined by a subclass, it
- * will default to a promise that waits until the underlying phosphor
- * `Application` has `started` and subsequently resolves with `undefined`. One
- * possible candidate for this type is the restored layout description of the
- * shell; but subclasses can resolve with any type upon restoration.
  */
 export class JupyterFrontEnd<
-  T extends JupyterFrontEnd.Shell = JupyterFrontEnd.Shell,
-  U = void
+  T extends JupyterFrontEnd.Shell = JupyterFrontEnd.Shell
 > extends Application<T> {
   /**
    * Construct a new JupyterFrontEnd object.
    */
-  constructor(options: JupyterFrontEnd.IOptions<T, U>) {
+  constructor(options: JupyterFrontEnd.IOptions<T>) {
     super(options);
 
     // The default restored promise if one does not exist in the options.
-    const restored = new Promise<U>(resolve => {
+    const restored = new Promise(resolve => {
       requestAnimationFrame(() => {
-        resolve(undefined);
+        resolve();
       });
     });
 
@@ -81,10 +73,9 @@ export class JupyterFrontEnd<
   readonly docRegistry: DocumentRegistry;
 
   /**
-   * Promise that resolves when state is first restored, returning layout
-   * description.
+   * Promise that resolves when state is first restored.
    */
-  readonly restored: Promise<U>;
+  readonly restored: Promise<void>;
 
   /**
    * The service manager used by the application.

+ 7 - 5
packages/application/src/lab.ts

@@ -38,12 +38,12 @@ export interface ILabStatus {
   /**
    * A signal for when application changes its busy status.
    */
-  readonly busySignal: ISignal<JupyterFrontEnd<any, any>, boolean>;
+  readonly busySignal: ISignal<JupyterFrontEnd, boolean>;
 
   /**
    * A signal for when application changes its dirty status.
    */
-  readonly dirtySignal: ISignal<JupyterFrontEnd<any, any>, boolean>;
+  readonly dirtySignal: ISignal<JupyterFrontEnd, boolean>;
 
   /**
    * Whether the application is busy.
@@ -73,14 +73,16 @@ export interface ILabStatus {
 /**
  * JupyterLab is the main application class. It is instantiated once and shared.
  */
-export class JupyterLab extends JupyterFrontEnd<LabShell, ILabShell.ILayout>
+export class JupyterLab extends JupyterFrontEnd<ILabShell>
   implements ILabStatus {
   /**
    * Construct a new JupyterLab object.
    */
   constructor(options: JupyterLab.IOptions = { shell: new LabShell() }) {
     super({ shell: options.shell || new LabShell() });
-    this.restored = this.shell.restored;
+    this.restored = this.shell.restored
+      .then(() => undefined)
+      .catch(() => undefined);
     this._busySignal = new Signal(this);
     this._dirtySignal = new Signal(this);
 
@@ -139,7 +141,7 @@ export class JupyterLab extends JupyterFrontEnd<LabShell, ILabShell.ILayout>
    * Promise that resolves when state is first restored, returning layout
    * description.
    */
-  readonly restored: Promise<ILabShell.ILayout> = this.shell.restored;
+  readonly restored: Promise<void>;
 
   /**
    * Whether the application is dirty.

+ 17 - 17
packages/filebrowser-extension/src/index.ts

@@ -101,10 +101,10 @@ const browser: JupyterFrontEndPlugin<void> = {
   activate: activateBrowser,
   id: '@jupyterlab/filebrowser-extension:browser',
   requires: [
-    ILabShell,
     IFileBrowserFactory,
-    ILayoutRestorer,
     IDocumentManager,
+    ILabShell,
+    ILayoutRestorer,
     ISettingRegistry
   ],
   autoStart: true
@@ -234,10 +234,10 @@ function activateFactory(
  */
 function activateBrowser(
   app: JupyterFrontEnd,
-  shell: ILabShell,
   factory: IFileBrowserFactory,
-  restorer: ILayoutRestorer,
   docManager: IDocumentManager,
+  labShell: ILabShell,
+  restorer: ILayoutRestorer,
   settingRegistry: ISettingRegistry
 ): void {
   const browser = factory.defaultBrowser;
@@ -251,14 +251,14 @@ function activateBrowser(
   // responsible for their own restoration behavior, if any.
   restorer.add(browser, namespace);
 
-  addCommands(app, factory.tracker, browser);
+  addCommands(app, factory.tracker, browser, labShell);
 
   browser.title.iconClass = 'jp-FolderIcon jp-SideBar-tabIcon';
   browser.title.caption = 'File Browser';
-  shell.addToLeftArea(browser, { rank: 100 });
+  labShell.add(browser, 'left', { rank: 100 });
 
   // If the layout is a fresh session without saved data, open file browser.
-  app.restored.then(layout => {
+  labShell.restored.then(layout => {
     if (layout.fresh) {
       commands.execute(CommandIDs.showBrowser, void 0);
     }
@@ -267,13 +267,13 @@ function activateBrowser(
   Promise.all([app.restored, browser.model.restored]).then(() => {
     function maybeCreate() {
       // Create a launcher if there are no open items.
-      if (shell.isEmpty('main')) {
+      if (labShell.isEmpty('main')) {
         createLauncher(commands, browser);
       }
     }
 
     // When layout is modified, create a launcher if there are no open items.
-    shell.layoutModified.connect(() => {
+    labShell.layoutModified.connect(() => {
       maybeCreate();
     });
 
@@ -292,7 +292,7 @@ function activateBrowser(
       });
 
     // Whether to automatically navigate to a document's current directory
-    shell.currentChanged.connect((_, change) => {
+    labShell.currentChanged.connect((_, change) => {
       if (navigateToCurrentDirectory) {
         const { newValue } = change;
         const context = docManager.contextForWidget(newValue);
@@ -340,7 +340,7 @@ function addCommands(
   app: JupyterFrontEnd,
   tracker: InstanceTracker<FileBrowser>,
   browser: FileBrowser,
-  shell?: ILabShell
+  labShell: ILabShell
 ): void {
   const registry = app.docRegistry;
 
@@ -431,8 +431,8 @@ function addCommands(
   commands.addCommand(CommandIDs.hideBrowser, {
     execute: () => {
       const widget = tracker.currentWidget;
-      if (shell && widget && !widget.isHidden) {
-        shell.collapseLeft();
+      if (widget && !widget.isHidden) {
+        labShell.collapseLeft();
       }
     }
   });
@@ -618,17 +618,17 @@ function addCommands(
         return;
       }
       // Shortcut if we are using the main file browser
-      if (shell && browser === browserForPath) {
-        shell.activateById(browser.id);
+      if (browser === browserForPath) {
+        labShell.activateById(browser.id);
         return;
       } else {
         const areas: ILabShell.Area[] = ['left', 'right'];
         for (let area of areas) {
-          const it = shell.widgets(area);
+          const it = labShell.widgets(area);
           let widget = it.next();
           while (widget) {
             if (widget.contains(browserForPath)) {
-              shell.activateById(widget.id);
+              labShell.activateById(widget.id);
               return;
             }
             widget = it.next();

+ 6 - 6
packages/launcher-extension/src/index.ts

@@ -48,7 +48,7 @@ export default plugin;
 function activate(
   app: JupyterFrontEnd,
   palette: ICommandPalette,
-  shell: ILabShell
+  labShell: ILabShell
 ): ILauncher {
   const { commands } = app;
   const model = new LauncherModel();
@@ -59,7 +59,7 @@ function activate(
       const cwd = args['cwd'] ? String(args['cwd']) : '';
       const id = `launcher-${Private.id++}`;
       const callback = (item: Widget) => {
-        shell.add(item, 'main', { ref: id });
+        labShell.add(item, 'main', { ref: id });
       };
       const launcher = new Launcher({ cwd, callback, commands });
 
@@ -70,15 +70,15 @@ function activate(
       let main = new MainAreaWidget({ content: launcher });
 
       // If there are any other widgets open, remove the launcher close icon.
-      main.title.closable = !!toArray(shell.widgets('main')).length;
+      main.title.closable = !!toArray(labShell.widgets('main')).length;
       main.id = id;
 
-      shell.add(main, 'main', { activate: args['activate'] as boolean });
+      labShell.add(main, 'main', { activate: args['activate'] as boolean });
 
-      shell.layoutModified.connect(
+      labShell.layoutModified.connect(
         () => {
           // If there is only a launcher open, remove the close icon.
-          main.title.closable = toArray(shell.widgets('main')).length > 1;
+          main.title.closable = toArray(labShell.widgets('main')).length > 1;
         },
         main
       );