@@ -151,7 +151,7 @@ export class ChatPanel extends SidePanel {
151151 * @param model - the model of the chat widget
152152 * @param name - the name of the chat.
153153 */
154- addChat ( model : IChatModel , name : string ) : void {
154+ addChat ( model : IChatModel , name : string , path : string ) : void {
155155 // Collapse all chats
156156 const content = this . content as AccordionPanel ;
157157 for ( let i = 0 ; i < this . widgets . length ; i ++ ) {
@@ -168,22 +168,45 @@ export class ChatPanel extends SidePanel {
168168 themeManager : this . _themeManager ,
169169 autocompletionRegistry : this . _autocompletionRegistry
170170 } ) ;
171- this . addWidget ( new ChatSection ( { name, widget, commands : this . _commands } ) ) ;
171+ this . addWidget (
172+ new ChatSection ( { name, widget, commands : this . _commands , path } )
173+ ) ;
172174 }
173175
176+ /**
177+ * Update the list of available chats in the root directory of the drive.
178+ */
174179 updateChatNames = async ( ) : Promise < void > => {
175180 const extension = chatFileType . extensions [ 0 ] ;
176181 this . _drive
177182 . get ( '.' )
178- . then ( model => {
179- const chatsName = ( model . content as any [ ] )
183+ . then ( contentModel => {
184+ const chatsNames : { [ name : string ] : string } = { } ;
185+ ( contentModel . content as any [ ] )
180186 . filter ( f => f . type === 'file' && f . name . endsWith ( extension ) )
181- . map ( f => PathExt . basename ( f . name , extension ) ) ;
182- this . _chatNamesChanged . emit ( chatsName ) ;
187+ . forEach (
188+ f => ( chatsNames [ PathExt . basename ( f . name , extension ) ] = f . name )
189+ ) ;
190+
191+ this . _chatNamesChanged . emit ( chatsNames ) ;
183192 } )
184193 . catch ( e => console . error ( 'Error getting the chat files from drive' , e ) ) ;
185194 } ;
186195
196+ /**
197+ * Open a chat if it exists in the side panel.
198+ *
199+ * @param path - the path of the chat.
200+ * @returns a boolean, whether the chat existed in the side panel or not.
201+ */
202+ openIfExists ( path : string ) : boolean {
203+ const index = this . _getChatIndex ( path ) ;
204+ if ( index > - 1 ) {
205+ this . _expandChat ( index ) ;
206+ }
207+ return index > - 1 ;
208+ }
209+
187210 /**
188211 * A message handler invoked on an `'after-show'` message.
189212 */
@@ -192,28 +215,41 @@ export class ChatPanel extends SidePanel {
192215 this . _openChat . renderPromise ?. then ( ( ) => this . updateChatNames ( ) ) ;
193216 }
194217
218+ /**
219+ * Return the index of the chat in the list (-1 if not opened).
220+ *
221+ * @param name - the chat name.
222+ */
223+ private _getChatIndex ( path : string ) {
224+ return this . widgets . findIndex ( w => ( w as ChatSection ) . path === path ) ;
225+ }
226+
227+ /**
228+ * Expand the chat from its index.
229+ */
230+ private _expandChat ( index : number ) : void {
231+ if ( ! this . widgets [ index ] . isVisible ) {
232+ ( this . content as AccordionPanel ) . expand ( index ) ;
233+ }
234+ }
235+
195236 /**
196237 * Handle `change` events for the HTMLSelect component.
197238 */
198239 private _chatSelected = (
199240 event : React . ChangeEvent < HTMLSelectElement >
200241 ) : void => {
201- const value = event . target . value ;
202- if ( value === '-' ) {
242+ const select = event . target ;
243+ const path = select . value ;
244+ const name = select . options [ select . selectedIndex ] . textContent ;
245+ if ( name === '-' ) {
203246 return ;
204247 }
205248
206- const index = this . widgets . findIndex (
207- w => ( w as ChatSection ) . name === value
208- ) ;
209- if ( index === - 1 ) {
210- this . _commands . execute ( CommandIDs . openChat , {
211- filepath : `${ value } ${ chatFileType . extensions [ 0 ] } ` ,
212- inSidePanel : true
213- } ) ;
214- } else if ( ! this . widgets [ index ] . isVisible ) {
215- ( this . content as AccordionPanel ) . expand ( index ) ;
216- }
249+ this . _commands . execute ( CommandIDs . openChat , {
250+ filepath : path ,
251+ inSidePanel : true
252+ } ) ;
217253 event . target . selectedIndex = 0 ;
218254 } ;
219255
@@ -232,7 +268,9 @@ export class ChatPanel extends SidePanel {
232268 }
233269 }
234270
235- private _chatNamesChanged = new Signal < this, string [ ] > ( this ) ;
271+ private _chatNamesChanged = new Signal < this, { [ name : string ] : string } > (
272+ this
273+ ) ;
236274 private _commands : CommandRegistry ;
237275 private _config : IConfig = { } ;
238276 private _drive : ICollaborativeDrive ;
@@ -269,8 +307,9 @@ class ChatSection extends PanelWithToolbar {
269307 super ( options ) ;
270308 this . addClass ( SECTION_CLASS ) ;
271309 this . _name = options . name ;
310+ this . _path = options . path ;
272311 this . title . label = this . _name ;
273- this . title . caption = this . _name ;
312+ this . title . caption = this . _path ;
274313 this . toolbar . addClass ( TOOLBAR_CLASS ) ;
275314
276315 this . _markAsRead = new ToolbarButton ( {
@@ -316,6 +355,13 @@ class ChatSection extends PanelWithToolbar {
316355 options . widget . node . style . height = '100%' ;
317356 }
318357
358+ /**
359+ * The path of the chat.
360+ */
361+ get path ( ) : string {
362+ return this . _path ;
363+ }
364+
319365 /**
320366 * The name of the chat.
321367 */
@@ -353,6 +399,7 @@ class ChatSection extends PanelWithToolbar {
353399
354400 private _name : string ;
355401 private _markAsRead : ToolbarButton ;
402+ private _path : string ;
356403}
357404
358405/**
@@ -366,11 +413,12 @@ export namespace ChatSection {
366413 commands : CommandRegistry ;
367414 name : string ;
368415 widget : ChatWidget ;
416+ path : string ;
369417 }
370418}
371419
372420type ChatSelectProps = {
373- chatNamesChanged : ISignal < ChatPanel , string [ ] > ;
421+ chatNamesChanged : ISignal < ChatPanel , { [ name : string ] : string } > ;
374422 handleChange : ( event : React . ChangeEvent < HTMLSelectElement > ) => void ;
375423} ;
376424
@@ -381,7 +429,9 @@ function ChatSelect({
381429 chatNamesChanged,
382430 handleChange
383431} : ChatSelectProps ) : JSX . Element {
384- const [ chatNames , setChatNames ] = useState < string [ ] > ( [ ] ) ;
432+ // An object associating a chat name to its path. Both are purely indicative, the name
433+ // is the section title and the path is used as caption.
434+ const [ chatNames , setChatNames ] = useState < { [ name : string ] : string } > ( { } ) ;
385435
386436 // Update the chat list.
387437 chatNamesChanged . connect ( ( _ , chatNames ) => {
@@ -391,8 +441,8 @@ function ChatSelect({
391441 return (
392442 < HTMLSelect onChange = { handleChange } >
393443 < option value = "-" > Open a chat</ option >
394- { chatNames . map ( name => (
395- < option value = { name } > { name } </ option >
444+ { Object . keys ( chatNames ) . map ( name => (
445+ < option value = { chatNames [ name ] } > { name } </ option >
396446 ) ) }
397447 </ HTMLSelect >
398448 ) ;
0 commit comments