From c55420990629413823ae842238ed3b32e2d63534 Mon Sep 17 00:00:00 2001 From: Nicolas Brichet Date: Mon, 15 Apr 2024 08:52:51 +0200 Subject: [PATCH] Use the jupyter events sytem to update the chat list --- .../src/index.ts | 13 +++- .../src/widget.tsx | 59 +++++++++---------- 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/packages/jupyterlab-collaborative-chat/src/index.ts b/packages/jupyterlab-collaborative-chat/src/index.ts index c34e771..9c4f226 100644 --- a/packages/jupyterlab-collaborative-chat/src/index.ts +++ b/packages/jupyterlab-collaborative-chat/src/index.ts @@ -392,7 +392,18 @@ const chatPanel: JupyterFrontEndPlugin = { restorer.add(chatPanel, 'jupyter-chat'); } - console.log('Collaborative chat initialized'); + // Use events system to watch changes on files. + const schemaID = + 'https://events.jupyter.org/jupyter_server/contents_service/v1'; + const actions = ['create', 'delete', 'rename']; + app.serviceManager.events.stream.connect((_, emission) => { + if (emission.schema_id === schemaID) { + const action = emission.action as string; + if (actions.includes(action)) { + chatPanel.updateChatNames(); + } + } + }); return chatPanel; } diff --git a/packages/jupyterlab-collaborative-chat/src/widget.tsx b/packages/jupyterlab-collaborative-chat/src/widget.tsx index 67037dd..6f377be 100644 --- a/packages/jupyterlab-collaborative-chat/src/widget.tsx +++ b/packages/jupyterlab-collaborative-chat/src/widget.tsx @@ -21,10 +21,11 @@ import { import { CommandRegistry } from '@lumino/commands'; import { AccordionPanel, Panel } from '@lumino/widgets'; import { ChatWidget, IChatModel, IConfig } from 'chat-jupyter'; -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { CollaborativeChatModel } from './model'; import { CommandIDs } from './token'; +import { ISignal, Signal } from '@lumino/signaling'; const SIDEPANEL_CLASS = 'jp-collab-chat-sidepanel'; const ADD_BUTTON_CLASS = 'jp-collab-chat-add'; @@ -72,6 +73,7 @@ export class ChatPanel extends SidePanel { super(options); this.addClass(SIDEPANEL_CLASS); this._commands = options.commands; + this._drive = options.drive; this._rmRegistry = options.rmRegistry; this._themeManager = options.themeManager; @@ -84,13 +86,14 @@ export class ChatPanel extends SidePanel { addChat.addClass(ADD_BUTTON_CLASS); this.toolbar.addItem('createChat', addChat); - const { drive } = options; const openChat = ReactWidget.create( ); + this.updateChatNames(); + openChat.addClass(OPEN_SELECT_CLASS); this.toolbar.addItem('openChat', openChat); @@ -133,6 +136,18 @@ export class ChatPanel extends SidePanel { this.addWidget(new ChatSection({ widget, name })); } + updateChatNames = async () => { + this._drive + .get('.') + .then(model => { + const chatsName = (model.content as any[]) + .filter(f => f.type === 'file' && f.name.endsWith('.chat')) + .map(f => PathExt.basename(f.name, '.chat')); + this._chatNamesChanged.emit(chatsName); + }) + .catch(e => console.error('Error getting the chat files from drive', e)); + }; + /** * Handle `change` events for the HTMLSelect component. */ @@ -173,8 +188,10 @@ export class ChatPanel extends SidePanel { } } + private _chatNamesChanged = new Signal(this); private _commands: CommandRegistry; private _config: IConfig = {}; + private _drive: ICollaborativeDrive; private _rmRegistry: IRenderMimeRegistry; private _themeManager: IThemeManager | null; } @@ -254,42 +271,22 @@ export namespace ChatSection { } type ChatSelectProps = { - drive: ICollaborativeDrive; + chatNamesChanged: ISignal; handleChange: (event: React.ChangeEvent) => void; }; /** * A component to select a chat from the drive. */ -function ChatSelect({ drive, handleChange }: ChatSelectProps): JSX.Element { +function ChatSelect({ + chatNamesChanged, + handleChange +}: ChatSelectProps): JSX.Element { const [chatNames, setChatNames] = useState([]); - /** - * Get chats list on initial render. - */ - useEffect(() => { - // Find chat files in drive (root level only) - // TODO: search in sub-directories ? - async function getChats() { - drive - .get('.') - .then(model => { - const chatsName = (model.content as any[]) - .filter(f => f.type === 'file' && f.name.endsWith('.chat')) - .map(f => PathExt.basename(f.name, '.chat')); - setChatNames(chatsName); - }) - .catch(e => console.error('Error getting the chat file in drive')); - } - - // Listen for changes in drive. - drive.fileChanged.connect((_, change) => { - getChats(); - }); - - // Initialize the chats list. - getChats(); - }, [drive]); + chatNamesChanged.connect((_, chatNames) => { + setChatNames(chatNames); + }); return (