Skip to content

Commit 4875e78

Browse files
authored
Remove requirement to global awareness, which often fails to activate (#28)
* Remove requirement to global awareness, which often fails to activate * update galata and fix the test on menu entry * lint * Fix settings test * Handle the case where the command to open chat has not been loaded
1 parent 64d01f7 commit 4875e78

File tree

8 files changed

+686
-610
lines changed

8 files changed

+686
-610
lines changed

packages/jupyterlab-collaborative-chat/src/factory.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@ import { ChatWidget, IChatModel, IConfig } from '@jupyter/chat';
77
import { IThemeManager } from '@jupyterlab/apputils';
88
import { ABCWidgetFactory, DocumentRegistry } from '@jupyterlab/docregistry';
99
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
10-
import { Contents } from '@jupyterlab/services';
10+
import { Contents, User } from '@jupyterlab/services';
1111
import { Signal } from '@lumino/signaling';
12-
import { Awareness } from 'y-protocols/awareness';
1312

1413
import { CollaborativeChatModel } from './model';
1514
import { CollaborativeChatWidget } from './widget';
@@ -95,7 +94,7 @@ export class CollaborativeChatModelFactory
9594
implements DocumentRegistry.IModelFactory<CollaborativeChatModel>
9695
{
9796
constructor(options: CollaborativeChatModel.IOptions) {
98-
this._awareness = options.awareness;
97+
this._user = options.user;
9998
this._widgetConfig = options.widgetConfig;
10099
}
101100

@@ -167,12 +166,12 @@ export class CollaborativeChatModelFactory
167166
): CollaborativeChatModel {
168167
return new CollaborativeChatModel({
169168
...options,
170-
awareness: this._awareness,
169+
user: this._user,
171170
widgetConfig: this._widgetConfig
172171
});
173172
}
174173

175174
private _disposed = false;
176-
private _awareness: Awareness;
175+
private _user: User.IIdentity | null;
177176
private _widgetConfig: IWidgetConfig;
178177
}

packages/jupyterlab-collaborative-chat/src/index.ts

Lines changed: 124 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
*/
55

66
import { chatIcon } from '@jupyter/chat';
7-
import { IGlobalAwareness } from '@jupyter/collaboration';
87
import { ICollaborativeDrive } from '@jupyter/docprovider';
98
import {
109
ILayoutRestorer,
@@ -29,7 +28,6 @@ import { Contents } from '@jupyterlab/services';
2928
import { ISettingRegistry } from '@jupyterlab/settingregistry';
3029
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
3130
import { launchIcon } from '@jupyterlab/ui-components';
32-
import { Awareness } from 'y-protocols/awareness';
3331

3432
import {
3533
WidgetConfig,
@@ -56,7 +54,7 @@ export const docFactories: JupyterFrontEndPlugin<IWidgetConfig> = {
5654
id: pluginIds.docFactories,
5755
description: 'A document factories for collaborative chat',
5856
autoStart: true,
59-
requires: [IGlobalAwareness, IRenderMimeRegistry],
57+
requires: [IRenderMimeRegistry],
6058
optional: [
6159
ICollaborativeDrive,
6260
ILayoutRestorer,
@@ -68,7 +66,6 @@ export const docFactories: JupyterFrontEndPlugin<IWidgetConfig> = {
6866
provides: IWidgetConfig,
6967
activate: (
7068
app: JupyterFrontEnd,
71-
awareness: Awareness,
7269
rmRegistry: IRenderMimeRegistry,
7370
drive: ICollaborativeDrive | null,
7471
restorer: ILayoutRestorer | null,
@@ -149,12 +146,22 @@ export const docFactories: JupyterFrontEndPlugin<IWidgetConfig> = {
149146
drive.sharedModelFactory.registerDocumentFactory('chat', chatFactory);
150147
}
151148

152-
// Creating and registering the model factory for our custom DocumentModel
153-
const modelFactory = new CollaborativeChatModelFactory({
154-
awareness,
155-
widgetConfig
156-
});
157-
app.docRegistry.addModelFactory(modelFactory);
149+
app.serviceManager.ready
150+
.then(() => {
151+
const user = app.serviceManager.user.identity;
152+
// Creating and registering the model factory for our custom DocumentModel
153+
const modelFactory = new CollaborativeChatModelFactory({
154+
user,
155+
widgetConfig
156+
});
157+
app.docRegistry.addModelFactory(modelFactory);
158+
})
159+
.catch(e =>
160+
console.error(
161+
'The collaborative chat model factory is not initialized',
162+
e
163+
)
164+
);
158165

159166
// Creating the widget factory to register it so the document manager knows about
160167
// our new DocumentWidget
@@ -203,12 +210,11 @@ const chatCommands: JupyterFrontEndPlugin<void> = {
203210
id: pluginIds.chatCommands,
204211
description: 'The commands to create or open a chat',
205212
autoStart: true,
206-
requires: [ICollaborativeDrive, IGlobalAwareness, IWidgetConfig],
213+
requires: [ICollaborativeDrive, IWidgetConfig],
207214
optional: [IChatPanel, ICommandPalette, ILauncher],
208215
activate: (
209216
app: JupyterFrontEnd,
210217
drive: ICollaborativeDrive,
211-
awareness: Awareness,
212218
widgetConfig: IWidgetConfig,
213219
chatPanel: ChatPanel | null,
214220
commandPalette: ICommandPalette | null,
@@ -220,7 +226,12 @@ const chatCommands: JupyterFrontEndPlugin<void> = {
220226
* Command to create a new chat.
221227
*
222228
* args:
223-
* name: the name of the chat to create.
229+
* name - optional, the name of the chat to create.
230+
* Open a dialog if not provided.
231+
* inSidePanel - optional (default to false).
232+
* Whether to open the chat in side panel or in main area.
233+
* isPalette - optional (default to false).
234+
* Whether the command is in commands palette or not.
224235
*/
225236
commands.addCommand(CommandIDs.createChat, {
226237
label: args => (args.isPalette ? 'Create a new chat' : 'Chat'),
@@ -283,81 +294,12 @@ const chatCommands: JupyterFrontEndPlugin<void> = {
283294
filepath = model.path;
284295
}
285296

286-
return commands.execute(CommandIDs.openChat, { filepath, inSidePanel });
287-
}
288-
});
289-
290-
/*
291-
* Command to open a chat.
292-
*
293-
* args:
294-
* filepath - the chat file to open.
295-
*/
296-
commands.addCommand(CommandIDs.openChat, {
297-
label: 'Open a chat',
298-
execute: async args => {
299-
const inSidePanel: boolean = (args.inSidePanel as boolean) ?? false;
300-
let filepath: string | null = (args.filepath as string) ?? null;
301-
if (filepath === null) {
302-
filepath = (
303-
await InputDialog.getText({
304-
label: 'File path',
305-
placeholder: '/path/to/the/chat/file',
306-
title: 'Path of the chat'
307-
})
308-
).value;
309-
}
310-
311-
if (!filepath) {
312-
return;
313-
}
314-
315-
let fileExist = true;
316-
await drive.get(filepath, { content: false }).catch(() => {
317-
fileExist = false;
318-
});
319-
320-
if (!fileExist) {
321-
showErrorMessage(
322-
'Error opening chat',
323-
`'${filepath}' is not a valid path`
324-
);
325-
return;
326-
}
327-
328-
if (inSidePanel && chatPanel) {
329-
// The chat is opened in the chat panel.
330-
app.shell.activateById(chatPanel.id);
331-
const model = await drive.get(filepath);
332-
333-
/**
334-
* Create a share model from the chat file
335-
*/
336-
const sharedModel = drive.sharedModelFactory.createNew({
337-
path: model.path,
338-
format: model.format,
339-
contentType: chatFileType.contentType,
340-
collaborative: true
341-
}) as YChat;
342-
343-
/**
344-
* Initialize the chat model with the share model
345-
*/
346-
const chat = new CollaborativeChatModel({
347-
awareness,
348-
sharedModel,
349-
widgetConfig
297+
if (commands.hasCommand(CommandIDs.openChat)) {
298+
return commands.execute(CommandIDs.openChat, {
299+
filepath,
300+
inSidePanel
350301
});
351-
352-
/**
353-
* Add a chat widget to the side panel.
354-
*/
355-
chatPanel.addChat(
356-
chat,
357-
PathExt.basename(model.name, chatFileType.extensions[0])
358-
);
359302
} else {
360-
// The chat is opened in the main area
361303
commands.execute('docmanager:open', {
362304
path: `RTC:${filepath}`,
363305
factory: FACTORY
@@ -366,17 +308,13 @@ const chatCommands: JupyterFrontEndPlugin<void> = {
366308
}
367309
});
368310

369-
// Add the commands to the palette
311+
// Add the command to the palette
370312
if (commandPalette) {
371313
commandPalette.addItem({
372314
category: 'Chat',
373315
command: CommandIDs.createChat,
374316
args: { isPalette: true }
375317
});
376-
commandPalette.addItem({
377-
category: 'Chat',
378-
command: CommandIDs.openChat
379-
});
380318
}
381319

382320
// Add the create command to the launcher
@@ -387,6 +325,100 @@ const chatCommands: JupyterFrontEndPlugin<void> = {
387325
rank: 1
388326
});
389327
}
328+
329+
app.serviceManager.ready
330+
.then(() => {
331+
const user = app.serviceManager.user.identity;
332+
/*
333+
* Command to open a chat.
334+
*
335+
* args:
336+
* filepath - the chat file to open.
337+
*/
338+
commands.addCommand(CommandIDs.openChat, {
339+
label: 'Open a chat',
340+
execute: async args => {
341+
const inSidePanel: boolean = (args.inSidePanel as boolean) ?? false;
342+
let filepath: string | null = (args.filepath as string) ?? null;
343+
if (filepath === null) {
344+
filepath = (
345+
await InputDialog.getText({
346+
label: 'File path',
347+
placeholder: '/path/to/the/chat/file',
348+
title: 'Path of the chat'
349+
})
350+
).value;
351+
}
352+
353+
if (!filepath) {
354+
return;
355+
}
356+
357+
let fileExist = true;
358+
await drive.get(filepath, { content: false }).catch(() => {
359+
fileExist = false;
360+
});
361+
362+
if (!fileExist) {
363+
showErrorMessage(
364+
'Error opening chat',
365+
`'${filepath}' is not a valid path`
366+
);
367+
return;
368+
}
369+
370+
if (inSidePanel && chatPanel) {
371+
// The chat is opened in the chat panel.
372+
app.shell.activateById(chatPanel.id);
373+
const model = await drive.get(filepath);
374+
375+
/**
376+
* Create a share model from the chat file
377+
*/
378+
const sharedModel = drive.sharedModelFactory.createNew({
379+
path: model.path,
380+
format: model.format,
381+
contentType: chatFileType.contentType,
382+
collaborative: true
383+
}) as YChat;
384+
385+
/**
386+
* Initialize the chat model with the share model
387+
*/
388+
const chat = new CollaborativeChatModel({
389+
user,
390+
sharedModel,
391+
widgetConfig
392+
});
393+
394+
/**
395+
* Add a chat widget to the side panel.
396+
*/
397+
chatPanel.addChat(
398+
chat,
399+
PathExt.basename(model.name, chatFileType.extensions[0])
400+
);
401+
} else {
402+
// The chat is opened in the main area
403+
commands.execute('docmanager:open', {
404+
path: `RTC:${filepath}`,
405+
factory: FACTORY
406+
});
407+
}
408+
}
409+
});
410+
411+
// Add the command to the palette
412+
if (commandPalette) {
413+
commandPalette.addItem({
414+
category: 'Chat',
415+
command: CommandIDs.openChat
416+
});
417+
}
418+
})
419+
.catch(e =>
420+
console.error('The command to open a chat is not initialized\n', e)
421+
);
390422
}
391423
};
392424

@@ -451,6 +483,7 @@ const chatPanel: JupyterFrontEndPlugin<ChatPanel> = {
451483
label: 'Move the chat to the side panel',
452484
caption: 'Move the chat to the side panel',
453485
icon: launchIcon,
486+
isEnabled: () => commands.hasCommand(CommandIDs.openChat),
454487
execute: async () => {
455488
const widget = app.shell.currentWidget;
456489
// Ensure widget is a CollaborativeChatWidget and is in main area

0 commit comments

Comments
 (0)