88 JupyterFrontEndPlugin
99} from '@jupyterlab/application' ;
1010import { Dialog , showDialog } from '@jupyterlab/apputils' ;
11- import { IDocumentWidget } from '@jupyterlab/docregistry' ;
11+ import { DocumentWidget , IDocumentWidget } from '@jupyterlab/docregistry' ;
1212import { ContentsManager } from '@jupyterlab/services' ;
1313
1414import {
@@ -34,6 +34,10 @@ import {
3434import { RtcContentProvider } from './ydrive' ;
3535import { Awareness } from 'y-protocols/awareness' ;
3636
37+ import { YChat } from './custom_ydocs' ;
38+ import { IChatFactory } from 'jupyterlab-chat' ;
39+ import { AbstractChatModel } from '@jupyter/chat' ;
40+
3741const TWO_SESSIONS_WARNING =
3842 'The file %1 has been opened with two different views. ' +
3943 'This is not supported. Please close this view; otherwise, ' +
@@ -154,6 +158,76 @@ export const ynotebook: JupyterFrontEndPlugin<void> = {
154158 }
155159} ;
156160
161+ /**
162+ * This plugin provides the YChat shared model and handles document resets by
163+ * listening to the `YChat.resetSignal` property automatically.
164+ *
165+ * Whenever a YChat is reset, this plugin will iterate through all of the app's
166+ * document widgets and find the one containing the `YChat` shared model which
167+ * was reset. It then clears the content.
168+ */
169+ export const ychat : JupyterFrontEndPlugin < void > = {
170+ id : '@jupyter/server-documents:ychat' ,
171+ description :
172+ 'Plugin to register a custom YChat factory and handle document resets.' ,
173+ autoStart : true ,
174+ requires : [ ICollaborativeContentProvider ] ,
175+ optional : [ IChatFactory ] ,
176+ activate : (
177+ app : JupyterFrontEnd ,
178+ contentProvider : ICollaborativeContentProvider ,
179+ chatFactory ?: IChatFactory
180+ ) : void => {
181+ if ( ! chatFactory ) {
182+ console . warn (
183+ 'No existing shared model factory found for chat. Not providing custom chat shared model.'
184+ ) ;
185+ return ;
186+ }
187+
188+ const onYChatReset = ( ychat : YChat ) => {
189+ for ( const widget of app . shell . widgets ( ) ) {
190+ if ( ! ( widget instanceof DocumentWidget ) ) {
191+ continue ;
192+ }
193+ const model = widget . content . model ;
194+ const sharedModel = model && model . _sharedModel ;
195+ if (
196+ ! ( model instanceof AbstractChatModel && sharedModel instanceof YChat )
197+ ) {
198+ continue ;
199+ }
200+ if ( sharedModel !== ychat ) {
201+ continue ;
202+ }
203+
204+ // If this point is reached, we have identified the correct parent
205+ // `model: AbstractChatModel` that maintains the message state for the
206+ // `YChat` which was reset. We clear its content directly & emit a
207+ // `contentChanged` signal to update the UI.
208+ ( model as any ) . _messages = [ ] ;
209+ ( model as any ) . _messagesUpdated . emit ( ) ;
210+ break ;
211+ }
212+ } ;
213+
214+ // Override the existing `YChat` factory to provide a custom `YChat` with a
215+ // `resetSignal`, which is automatically subscribed to & refreshes the UI
216+ // state upon document reset.
217+ const yChatFactory = ( ) => {
218+ const ychat = new YChat ( ) ;
219+ ychat . resetSignal . connect ( ( ) => {
220+ onYChatReset ( ychat ) ;
221+ } ) ;
222+ return ychat ;
223+ } ;
224+ contentProvider . sharedModelFactory . registerDocumentFactory (
225+ 'chat' ,
226+ yChatFactory as any
227+ ) ;
228+ }
229+ } ;
230+
157231/**
158232 * The default collaborative drive provider.
159233 */
0 commit comments