@@ -43,6 +43,7 @@ import {
43
43
import {
44
44
RenderMimeRegistry ,
45
45
standardRendererFactories ,
46
+ type IRenderMime ,
46
47
} from '@jupyterlab/rendermime' ;
47
48
import type {
48
49
Contents ,
@@ -72,7 +73,7 @@ import {
72
73
WidgetManager ,
73
74
} from '../../jupyter' ;
74
75
import type { OnSessionConnection } from '../../state' ;
75
- import { newUuid , sleep } from '../../utils' ;
76
+ import { newUuid } from '../../utils' ;
76
77
import { Lumino } from '../lumino' ;
77
78
import { Loader } from '../utils' ;
78
79
import type { DatalayerNotebookExtension } from './Notebook' ;
@@ -105,6 +106,10 @@ export interface IBaseNotebookProps {
105
106
* Kernel ID to connect to
106
107
*/
107
108
kernelId ?: string ;
109
+ /**
110
+ * Additional cell output renderers.
111
+ */
112
+ renderers ?: IRenderMime . IRendererFactory [ ] ;
108
113
/**
109
114
* Service manager
110
115
*/
@@ -140,6 +145,7 @@ export function BaseNotebook(props: IBaseNotebookProps): JSX.Element {
140
145
commands,
141
146
extensions = DEFAULT_EXTENSIONS ,
142
147
kernelId,
148
+ renderers,
143
149
serviceManager,
144
150
model,
145
151
onSessionConnectionChanged,
@@ -156,7 +162,10 @@ export function BaseNotebook(props: IBaseNotebookProps): JSX.Element {
156
162
[ props . path ]
157
163
) ;
158
164
// Features
159
- const features = useMemo ( ( ) => new CommonFeatures ( { commands } ) , [ commands ] ) ;
165
+ const features = useMemo (
166
+ ( ) => new CommonFeatures ( { commands, renderers } ) ,
167
+ [ commands , renderers ]
168
+ ) ;
160
169
161
170
// Content factory
162
171
const contentFactory = useMemo (
@@ -458,15 +467,20 @@ export function BaseNotebook(props: IBaseNotebookProps): JSX.Element {
458
467
} ;
459
468
} , [ completer , panel , tracker ] ) ;
460
469
461
- const onKeyDown = useCallback (
462
- ( event : any ) => {
470
+ useEffect ( ( ) => {
471
+ const onKeyDown = ( event : any ) => {
463
472
features . commands . processKeydownEvent ( event ) ;
464
- } ,
465
- [ features . commands ]
466
- ) ;
473
+ } ;
467
474
468
- // FIXME
469
- // - connect signals - see adapter - fix kernel transfer
475
+ // FIXME It would be better to add the listener to the Box wrapping the panel
476
+ // but this requires the use of the latest version of JupyterLab/Lumino that
477
+ // capture event at bubbling phase for keyboard shortcuts rather than at capture phase.
478
+ document . addEventListener ( 'keydown' , onKeyDown , true ) ;
479
+
480
+ return ( ) => {
481
+ document . removeEventListener ( 'keydown' , onKeyDown , true ) ;
482
+ } ;
483
+ } , [ features . commands ] ) ;
470
484
471
485
return (
472
486
< >
@@ -478,7 +492,7 @@ export function BaseNotebook(props: IBaseNotebookProps): JSX.Element {
478
492
{ isLoading ? (
479
493
< Loader key = "notebook-loader" />
480
494
) : panel ? (
481
- < Box sx = { { height : '100%' } } onKeyDownCapture = { onKeyDown } >
495
+ < Box sx = { { height : '100%' } } >
482
496
< Lumino id = { id } key = "notebook-container" >
483
497
{ panel }
484
498
</ Lumino >
@@ -489,6 +503,7 @@ export function BaseNotebook(props: IBaseNotebookProps): JSX.Element {
489
503
variant = "critical"
490
504
description = "Unable to create the notebook view."
491
505
hideTitle = { true }
506
+ title = "Error"
492
507
/>
493
508
) }
494
509
</ >
@@ -679,18 +694,15 @@ export function useNotebookModel(options: {
679
694
680
695
// If sessionId has expired - reset the client model
681
696
if ( event . code === 4002 ) {
697
+ disposable . clear ( ) ;
682
698
provider ?. destroy ( ) ;
683
- ready . reject ( 'Connection closed.' ) ;
684
- ready = new PromiseDelegate ( ) ;
685
699
if ( isMounted ) {
686
- Promise . all ( [ connect ( ) , ready . promise , sleep ( 500 ) ] ) . catch (
687
- error => {
688
- console . error (
689
- 'Failed to setup collaboration connection.' ,
690
- error
691
- ) ;
692
- }
693
- ) ;
700
+ connect ( ) . catch ( error => {
701
+ console . error (
702
+ 'Failed to setup collaboration connection.' ,
703
+ error
704
+ ) ;
705
+ } ) ;
694
706
}
695
707
}
696
708
@@ -706,6 +718,9 @@ export function useNotebookModel(options: {
706
718
} ;
707
719
708
720
const connect = async ( ) => {
721
+ ready . reject ( 'Connection closed.' ) ;
722
+ ready = new PromiseDelegate ( ) ;
723
+
709
724
sharedModel = new YNotebook ( ) ;
710
725
const { ydoc, awareness } = sharedModel ;
711
726
let roomURL = '' ;
@@ -752,40 +767,35 @@ export function useNotebookModel(options: {
752
767
provider . on ( 'sync' , onSync ) ;
753
768
provider . on ( 'connection-close' , onConnectionClose ) ;
754
769
console . log ( 'Collaboration is setup with websocket provider.' ) ;
755
- // Create a new model using the one synchronize with the collaboration room
756
- const model = new NotebookModel ( {
757
- collaborationEnabled : true ,
758
- disableDocumentWideUndoRedo : true ,
759
- sharedModel,
760
- } ) ;
761
- model . readOnly = readonly ;
762
- setModel ( model ) ;
770
+
771
+ await ready . promise ;
772
+ const dispose = ( ) => {
773
+ provider ?. off ( 'sync' , onSync ) ;
774
+ provider ?. off ( 'connection-close' , onConnectionClose ) ;
775
+ provider ?. disconnect ( ) ;
776
+ provider ?. destroy ( ) ;
777
+ } ;
778
+
779
+ if ( isMounted ) {
780
+ // Create a new model using the one synchronized with the collaboration room
781
+ const model = new NotebookModel ( {
782
+ collaborationEnabled : true ,
783
+ disableDocumentWideUndoRedo : true ,
784
+ sharedModel,
785
+ } ) ;
786
+ model . readOnly = readonly ;
787
+ setModel ( model ) ;
788
+
789
+ disposable . add ( Object . freeze ( { dispose, isDisposed : false } ) ) ;
790
+ } else {
791
+ dispose ( ) ;
792
+ }
763
793
}
764
794
} ;
765
795
766
- Promise . all ( [ connect ( ) , ready . promise ] )
767
- . then ( ( ) => {
768
- if ( provider ) {
769
- const dispose = ( ) => {
770
- ( provider ! . synced ? Promise . resolve ( ) : ready . promise ) . finally (
771
- ( ) => {
772
- provider ! . off ( 'sync' , onSync ) ;
773
- provider ! . off ( 'connection-close' , onConnectionClose ) ;
774
- provider ! . disconnect ( ) ;
775
- provider ! . destroy ( ) ;
776
- }
777
- ) ;
778
- } ;
779
- if ( isMounted ) {
780
- disposable . add ( Object . freeze ( { dispose, isDisposed : false } ) ) ;
781
- } else {
782
- dispose ( ) ;
783
- }
784
- }
785
- } )
786
- . catch ( error => {
787
- console . error ( 'Failed to setup collaboration connection.' , error ) ;
788
- } ) ;
796
+ connect ( ) . catch ( error => {
797
+ console . error ( 'Failed to setup collaboration connection.' , error ) ;
798
+ } ) ;
789
799
} else {
790
800
const createModel = ( nbformat : INotebookContent | undefined ) => {
791
801
const model = new NotebookModel ( ) ;
@@ -837,7 +847,12 @@ class CommonFeatures {
837
847
protected _editorServices : IEditorServices ;
838
848
protected _rendermime : RenderMimeRegistry ;
839
849
840
- constructor ( options : { commands ?: CommandRegistry } = { } ) {
850
+ constructor (
851
+ options : {
852
+ commands ?: CommandRegistry ;
853
+ renderers ?: IRenderMime . IRendererFactory [ ] ;
854
+ } = { }
855
+ ) {
841
856
this . _commands = options . commands ?? new CommandRegistry ( ) ;
842
857
843
858
const languages = new EditorLanguageRegistry ( ) ;
@@ -858,11 +873,10 @@ class CommonFeatures {
858
873
} ,
859
874
} ) ;
860
875
861
- const initialFactories = standardRendererFactories . filter (
862
- factory => factory . mimeTypes [ 0 ] !== 'text/javascript'
863
- ) ;
864
- initialFactories . push ( jsonRendererFactory ) ;
865
- initialFactories . push ( javascriptRendererFactory ) ;
876
+ const initialFactories = standardRendererFactories
877
+ . filter ( factory => factory . mimeTypes [ 0 ] !== 'text/javascript' )
878
+ . concat ( [ jsonRendererFactory , javascriptRendererFactory ] )
879
+ . concat ( options . renderers ?? [ ] ) ;
866
880
867
881
this . _rendermime = new RenderMimeRegistry ( {
868
882
initialFactories,
@@ -1082,17 +1096,6 @@ function initializeContext(
1082
1096
) ;
1083
1097
context . sessionContext . ready . then ( ( ) => {
1084
1098
onSessionConnection ?.( context ?. sessionContext . session ?? undefined ) ;
1085
- // FIXME
1086
- // const kernelConnection = context?.sessionContext.session?.kernel;
1087
- // if (this._kernelTransfer) {
1088
- // if (kernelConnection) {
1089
- // kernelConnection.connectionStatusChanged.connect((_, status) => {
1090
- // if (status === 'connected') {
1091
- // this._kernelTransfer!.transfer(kernelConnection);
1092
- // }
1093
- // });
1094
- // }
1095
- // }
1096
1099
} ) ;
1097
1100
1098
1101
// Initialize the context
0 commit comments