55 JupyterFrontEnd ,
66 JupyterFrontEndPlugin
77} from '@jupyterlab/application' ;
8+ import { IStatusBar } from '@jupyterlab/statusbar' ;
89import {
910 IFileBrowserFactory ,
1011 FileBrowser ,
@@ -38,6 +39,127 @@ import { Drive } from '../contents';
3839import { setListingLimit } from '../requests' ;
3940import { CommandIDs } from '../token' ;
4041
42+ /**
43+ * Status bar widget for displaying drive information
44+ */
45+ class DriveStatusWidget extends Widget {
46+ constructor ( ) {
47+ super ( ) ;
48+ this . addClass ( 'jp-drive-status-widget' ) ;
49+ this . node . textContent = 'Drives: Ready' ;
50+ this . _currentPath = '' ;
51+ this . _isLoading = false ;
52+
53+ // Listen for custom events from getContents
54+ window . addEventListener ( 'drive-status-update' , ( event : Event ) => {
55+ const customEvent = event as CustomEvent ;
56+ this . handleStatusUpdate ( customEvent . detail ) ;
57+ } ) ;
58+ }
59+
60+ updateStatus ( text : string ) {
61+ this . node . textContent = `Drives: ${ text } ` ;
62+ }
63+
64+ setDriveCount ( count : number ) {
65+ this . node . textContent = `Drives: ${ count } connected` ;
66+ }
67+
68+ setError ( message : string ) {
69+ this . node . textContent = `Drives: ${ message } ` ;
70+ this . addClass ( 'jp-drive-status-error' ) ;
71+ }
72+
73+ clearError ( ) {
74+ this . removeClass ( 'jp-drive-status-error' ) ;
75+ }
76+
77+ /**
78+ * Update status when navigating to a directory
79+ */
80+ setDirectoryLoading ( path : string ) {
81+ console . log ( '[DEBUG] Setting directory loading:' , path ) ;
82+ this . _isLoading = true ;
83+ this . _currentPath = path ;
84+ const displayPath =
85+ path === '' ? 'Root' : path . split ( '/' ) . pop ( ) || 'Directory' ;
86+ this . node . textContent = `Drives: Opening ${ displayPath } ...` ;
87+ this . addClass ( 'jp-drive-status-loading' ) ;
88+ }
89+
90+ /**
91+ * Update status when a file is being opened
92+ */
93+ setFileLoading ( path : string ) {
94+ console . log ( '[DEBUG] Setting file loading:' , path ) ;
95+ this . _isLoading = true ;
96+ this . _currentPath = path ;
97+ const fileName = path . split ( '/' ) . pop ( ) || 'File' ;
98+ this . node . textContent = `Drives: Opening ${ fileName } ...` ;
99+ this . addClass ( 'jp-drive-status-loading' ) ;
100+ }
101+
102+ /**
103+ * Clear loading state and show current status
104+ */
105+ setLoaded ( path : string , type : 'directory' | 'file' = 'directory' ) {
106+ this . _isLoading = false ;
107+ this . _currentPath = path ;
108+ this . removeClass ( 'jp-drive-status-loading' ) ;
109+
110+ if ( type === 'directory' ) {
111+ const displayPath =
112+ path === '' ? 'Root' : path . split ( '/' ) . pop ( ) || 'Directory' ;
113+ this . node . textContent = `Drives: ${ displayPath } ` ;
114+ } else {
115+ const fileName = path . split ( '/' ) . pop ( ) || 'File' ;
116+ this . node . textContent = `Drives: ${ fileName } ` ;
117+ }
118+ }
119+
120+ /**
121+ * Get current path
122+ */
123+ get currentPath ( ) : string {
124+ return this . _currentPath ;
125+ }
126+
127+ /**
128+ * Check if currently loading
129+ */
130+ get isLoading ( ) : boolean {
131+ return this . _isLoading ;
132+ }
133+
134+ /**
135+ * Handle status updates from getContents function
136+ */
137+ private handleStatusUpdate ( detail : any ) {
138+ console . log ( '[DEBUG] Status update received:' , detail ) ;
139+
140+ if ( detail . type === 'loading' ) {
141+ const fullPath = detail . driveName + '/' + detail . path ;
142+ if ( detail . path === '' ) {
143+ this . setDirectoryLoading ( '' ) ;
144+ } else {
145+ // Determine if it's a directory or file based on path
146+ const isDirectory = detail . path . endsWith ( '/' ) || detail . path === '' ;
147+ if ( isDirectory ) {
148+ this . setDirectoryLoading ( fullPath ) ;
149+ } else {
150+ this . setFileLoading ( fullPath ) ;
151+ }
152+ }
153+ } else if ( detail . type === 'loaded' ) {
154+ const fullPath = detail . driveName + '/' + detail . path ;
155+ this . setLoaded ( fullPath , detail . itemType ) ;
156+ }
157+ }
158+
159+ private _currentPath : string ;
160+ private _isLoading : boolean ;
161+ }
162+
41163/**
42164 * The file browser factory ID.
43165 */
@@ -75,7 +197,8 @@ export const driveFileBrowser: JupyterFrontEndPlugin<void> = {
75197 IRouter ,
76198 JupyterFrontEnd . ITreeResolver ,
77199 ILabShell ,
78- ILayoutRestorer
200+ ILayoutRestorer ,
201+ IStatusBar
79202 ] ,
80203 activate : async (
81204 app : JupyterFrontEnd ,
@@ -86,7 +209,8 @@ export const driveFileBrowser: JupyterFrontEndPlugin<void> = {
86209 router : IRouter | null ,
87210 tree : JupyterFrontEnd . ITreeResolver | null ,
88211 labShell : ILabShell | null ,
89- restorer : ILayoutRestorer | null
212+ restorer : ILayoutRestorer | null ,
213+ statusBar : IStatusBar | null
90214 ) : Promise < void > => {
91215 console . log (
92216 'JupyterLab extension jupyter-drives:drives-file-browser is activated!'
@@ -125,6 +249,42 @@ export const driveFileBrowser: JupyterFrontEndPlugin<void> = {
125249 restorer . add ( driveBrowser , 'drive-file-browser' ) ;
126250 }
127251
252+ // Register status bar widget
253+ if ( statusBar ) {
254+ const driveStatusWidget = new DriveStatusWidget ( ) ;
255+
256+ statusBar . registerStatusItem ( 'driveBrowserStatus' , {
257+ item : driveStatusWidget ,
258+ align : 'right' ,
259+ rank : 500 ,
260+ isActive : ( ) => true
261+ } ) ;
262+
263+ // Update status when drive browser is ready
264+ driveStatusWidget . updateStatus ( 'Connected' ) ;
265+
266+ // Listen for drive changes and update status
267+ drive . loadingContents . connect ( ( sender , args ) => {
268+ const path = driveBrowser . model . path ;
269+ console . log ( '[DEBUG] Path changed:' , path , 'args:' , args ) ;
270+ if ( args . type === 'loading' ) {
271+ driveStatusWidget . setDirectoryLoading ( path ) ;
272+ } else if ( args . type === 'loaded' ) {
273+ console . log ( 'loaded' ) ;
274+ // driveStatusWidget.setLoaded(path, args.itemType);
275+ }
276+ // Status updates are now handled by custom events from getContents
277+ } ) ;
278+
279+ // Listen for model changes to update drive count
280+ drive . loadingContents . connect ( ( ) => {
281+ console . log ( '[DEBUG] Model refreshed' ) ;
282+ // const items = driveBrowser.model.items();
283+ // const driveCount = Array.from(items).length;
284+ // driveStatusWidget.setDriveCount(driveCount);
285+ } ) ;
286+ }
287+
128288 const uploader = new Uploader ( { model : driveBrowser . model , translator } ) ;
129289 toolbarRegistry . addFactory ( FILE_BROWSER_FACTORY , 'uploader' , ( ) => {
130290 return uploader ;
0 commit comments