Skip to content

Commit 7ea6164

Browse files
authored
Add scrolltobottom (#17)
1 parent c116df5 commit 7ea6164

File tree

3 files changed

+45
-12
lines changed

3 files changed

+45
-12
lines changed

.vscode/launch.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
{
66
"type": "node",
77
"request": "launch",
8-
"name": "Gulp hygiene-branch",
8+
"name": "Gulp watch",
99
"program": "${workspaceFolder}/node_modules/gulp/bin/gulp.js",
1010
"args": [
11-
"hygiene-branch"
11+
"watch"
1212
]
1313
},
1414
{

src/client/datascience/history-react/MainPanel.tsx

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { Cell } from './cell';
1111

1212
export interface IState {
1313
cells: ICell[];
14+
busy: boolean;
1415
}
1516

1617
export interface IMainPanelProps {
@@ -22,18 +23,21 @@ export class MainPanel extends React.Component<IMainPanelProps, IState> {
2223
// tslint:disable-next-line:no-any
2324
private messageHandlers: { [index: string]: (msg?: any) => void } = {
2425
};
26+
private bottom: HTMLDivElement | undefined;
2527

2628
// tslint:disable-next-line:max-func-body-length
2729
constructor(props: IMainPanelProps, state: IState) {
2830
super(props);
29-
this.state = { cells: [] };
31+
this.state = { cells: [], busy: false };
3032
this.updateState.bind(this);
3133
this.messageHandlers[HistoryMessages.UpdateState] = this.updateState;
3234

3335
// Setup up some dummy cells for debugging when not running in vscode
3436
// This should show a gray rectangle in the cell.
3537
if (!PostOffice.canSendMessages() && !this.props.skipDefault) {
36-
this.state = {cells: [
38+
this.state = {
39+
busy: false,
40+
cells: [
3741
{
3842
input: 'get_ipython().run_line_magic("matplotlib", "inline")',
3943
output: {
@@ -168,11 +172,20 @@ export class MainPanel extends React.Component<IMainPanelProps, IState> {
168172
}
169173
}
170174

175+
public componentDidMount() {
176+
this.scrollToBottom();
177+
}
178+
179+
public componentDidUpdate(prevProps, prevState) {
180+
this.scrollToBottom();
181+
}
182+
171183
public render() {
172184
return (
173185
<div className='main-panel'>
174186
<PostOffice messageHandlers={this.messageHandlers} />
175187
{this.renderCells()}
188+
<div ref={this.updateBottom} />
176189
</div>
177190
);
178191
}
@@ -185,6 +198,16 @@ export class MainPanel extends React.Component<IMainPanelProps, IState> {
185198
);
186199
}
187200

201+
private scrollToBottom = () => {
202+
if (this.bottom) {
203+
this.bottom.scrollIntoView({behavior: 'smooth'});
204+
}
205+
}
206+
207+
private updateBottom = (newBottom: HTMLDivElement) => {
208+
this.bottom = newBottom;
209+
}
210+
188211
// tslint:disable-next-line:no-any
189212
private updateState = (payload?: any) => {
190213
if (payload) {

src/client/datascience/jupyterServer.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { ICell, IJupyterServer } from './types';
2424

2525
export class JupyterServer implements IJupyterServer, IDisposable {
2626
private static trackingTemps: boolean = false;
27+
private static textPlainMimeType : string = 'text/plain';
2728
public isDisposed: boolean = false;
2829
private session: Session.ISession | undefined;
2930
private tempFile: temp.OpenFile | undefined;
@@ -165,8 +166,10 @@ export class JupyterServer implements IJupyterServer, IDisposable {
165166
this.handleStreamMesssage(msg as KernelMessage.IStreamMsg, cell);
166167
} else if (KernelMessage.isDisplayDataMsg(msg)) {
167168
this.handleDisplayData(msg as KernelMessage.IDisplayDataMsg, cell);
169+
} else if (KernelMessage.isErrorMsg(msg)) {
170+
this.handleError(msg as KernelMessage.IErrorMsg, cell);
168171
} else {
169-
this.logger.logWarning(`Unknown message ${typeof msg}`);
172+
this.logger.logWarning(`Unknown message ${msg.header.msg_type} : hasData=${'data' in msg.content}`);
170173
}
171174
};
172175

@@ -193,21 +196,28 @@ export class JupyterServer implements IJupyterServer, IDisposable {
193196
}
194197
}
195198

196-
private handleStreamMesssage(msg: KernelMessage.IStreamMsg, cell: ICell) {
197-
const mimeType = 'text/plain';
198-
199-
// Stream/concat the text together
200-
if (cell.output.hasOwnProperty(mimeType)) {
201-
cell.output[mimeType] = `${cell.output[mimeType].toString()}\n${msg.content.text}`;
199+
private handleTextPlain(text: string, cell: ICell) {
200+
if (cell.output.hasOwnProperty(JupyterServer.textPlainMimeType)) {
201+
cell.output[JupyterServer.textPlainMimeType] = `${cell.output[JupyterServer.textPlainMimeType].toString()}\n${text}`;
202202
} else {
203-
cell.output[mimeType] = msg.content.text;
203+
cell.output[JupyterServer.textPlainMimeType] = text;
204204
}
205205
}
206206

207+
private handleStreamMesssage(msg: KernelMessage.IStreamMsg, cell: ICell) {
208+
// Stream/concat the text together
209+
this.handleTextPlain((msg.content.text), cell);
210+
}
211+
207212
private handleDisplayData(msg: KernelMessage.IDisplayDataMsg, cell: ICell) {
208213
cell.output = msg.content.data;
209214
}
210215

216+
private handleError(msg: KernelMessage.IErrorMsg, cell: ICell) {
217+
// Stream/concat the text together
218+
this.handleTextPlain((msg.content.evalue), cell);
219+
}
220+
211221
private async generateTempFile(notebookFile?: string) : Promise<temp.OpenFile> {
212222
// Make sure we cleanup these temp files.
213223
if (!JupyterServer.trackingTemps) {

0 commit comments

Comments
 (0)