Skip to content

Commit 7cde864

Browse files
authored
feat(open-in-deepnote): button in toolbar (#153)
* feat(open-in-deepnote): button in toolbar * chore: fix tests
1 parent c6640a4 commit 7cde864

File tree

3 files changed

+436
-47
lines changed

3 files changed

+436
-47
lines changed

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,11 @@
857857
}
858858
],
859859
"notebook/toolbar": [
860+
{
861+
"command": "deepnote.openInDeepnote",
862+
"group": "navigation@-1",
863+
"when": "notebookType == 'deepnote'"
864+
},
860865
{
861866
"command": "deepnote.manageIntegrations",
862867
"group": "navigation@0",

src/notebooks/deepnote/openInDeepnoteHandler.node.ts

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,69 +11,71 @@ import * as fs from 'fs';
1111
import * as path from '../../platform/vscode-path/path';
1212
import { initImport, uploadFile, getErrorMessage, MAX_FILE_SIZE, getDeepnoteDomain } from './importClient.node';
1313

14-
/**
15-
* Handler for the "Open in Deepnote" command
16-
* Uploads .deepnote files to Deepnote and opens them in the web app
17-
*/
1814
@injectable()
1915
export class OpenInDeepnoteHandler implements IExtensionSyncActivationService {
2016
constructor(@inject(IExtensionContext) private readonly extensionContext: IExtensionContext) {}
2117

22-
/**
23-
* Activates the handler by registering the command
24-
*/
2518
public activate(): void {
2619
this.extensionContext.subscriptions.push(
2720
commands.registerCommand(Commands.OpenInDeepnote, () => this.handleOpenInDeepnote())
2821
);
2922
}
3023

31-
/**
32-
* Main handler for the Open in Deepnote command
33-
*/
3424
private async handleOpenInDeepnote(): Promise<void> {
3525
try {
36-
// Get the active editor
37-
const activeEditor = window.activeTextEditor;
38-
if (!activeEditor) {
39-
void window.showErrorMessage('Please open a .deepnote file first');
40-
return;
26+
let fileUri: Uri | undefined;
27+
let isNotebook = false;
28+
29+
const activeNotebookEditor = window.activeNotebookEditor;
30+
if (activeNotebookEditor) {
31+
const notebook = activeNotebookEditor.notebook;
32+
if (notebook.notebookType === 'deepnote') {
33+
fileUri = notebook.uri.with({ query: '', fragment: '' });
34+
isNotebook = true;
35+
}
4136
}
4237

43-
const fileUri = activeEditor.document.uri;
38+
if (!fileUri) {
39+
const activeEditor = window.activeTextEditor;
40+
if (!activeEditor) {
41+
void window.showErrorMessage('Please open a .deepnote file first');
42+
return;
43+
}
44+
45+
fileUri = activeEditor.document.uri;
46+
}
4447

45-
// Validate that it's a .deepnote file
4648
if (!fileUri.fsPath.endsWith('.deepnote')) {
4749
void window.showErrorMessage('This command only works with .deepnote files');
4850
return;
4951
}
5052

51-
// Ensure the file is saved
52-
if (activeEditor.document.isDirty) {
53-
const saved = await activeEditor.document.save();
54-
if (!saved) {
55-
void window.showErrorMessage('Please save the file before opening in Deepnote');
56-
return;
53+
if (isNotebook) {
54+
await commands.executeCommand('workbench.action.files.save');
55+
} else {
56+
const activeEditor = window.activeTextEditor;
57+
if (activeEditor && activeEditor.document.isDirty) {
58+
const saved = await activeEditor.document.save();
59+
if (!saved) {
60+
void window.showErrorMessage('Please save the file before opening in Deepnote');
61+
return;
62+
}
5763
}
5864
}
5965

60-
// Read the file
6166
const filePath = fileUri.fsPath;
6267
const fileName = path.basename(filePath);
6368

6469
logger.info(`Opening in Deepnote: ${fileName}`);
6570

66-
// Check file size
6771
const stats = await fs.promises.stat(filePath);
6872
if (stats.size > MAX_FILE_SIZE) {
6973
void window.showErrorMessage(`File exceeds ${MAX_FILE_SIZE / (1024 * 1024)}MB limit`);
7074
return;
7175
}
7276

73-
// Read file into buffer
7477
const fileBuffer = await fs.promises.readFile(filePath);
7578

76-
// Show progress
7779
await window.withProgress(
7880
{
7981
location: { viewId: 'workbench.view.extension.deepnoteExplorer' },
@@ -82,14 +84,12 @@ export class OpenInDeepnoteHandler implements IExtensionSyncActivationService {
8284
},
8385
async (progress) => {
8486
try {
85-
// Step 1: Initialize import
8687
progress.report({ message: l10n.t('Preparing upload...') });
8788
logger.debug(`Initializing import for ${fileName} (${stats.size} bytes)`);
8889

8990
const initResponse = await initImport(fileName, stats.size);
9091
logger.debug(`Import initialized: ${initResponse.importId}`);
9192

92-
// Step 2: Upload file
9393
progress.report({ message: l10n.t('Uploading file...') });
9494
await uploadFile(initResponse.uploadUrl, fileBuffer, (uploadProgress) => {
9595
progress.report({
@@ -98,7 +98,6 @@ export class OpenInDeepnoteHandler implements IExtensionSyncActivationService {
9898
});
9999
logger.debug('File uploaded successfully');
100100

101-
// Step 3: Open in browser
102101
progress.report({ message: l10n.t('Opening in Deepnote...') });
103102
const domain = getDeepnoteDomain();
104103
const deepnoteUrl = `https://${domain}/launch?importId=${initResponse.importId}`;

0 commit comments

Comments
 (0)