Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a safe operation for the dialog #5860

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 26 additions & 7 deletions packages/core/src/browser/dialogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export abstract class AbstractDialog<T> extends BaseWidget {
@inject(DialogProps) protected readonly props: DialogProps
) {
super();
this.id = 'theia-dialog-shell';
this.id = `theia-dialog-${(new Date()).getTime()}`;
this.addClass('dialogOverlay');
this.toDispose.push(Disposable.create(() => {
if (this.reject) {
Expand Down Expand Up @@ -148,15 +148,30 @@ export abstract class AbstractDialog<T> extends BaseWidget {
this.addKeyListener(document.body, Key.ENTER, e => this.handleEnter(e));
}

protected canHandleKeyboardEvent(event: KeyboardEvent): boolean {
let result: boolean = false;
if (this.id && event.currentTarget) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure checking this.id is necessary as id will always be defined by the parent AbstractDialog<T>:

https://github.com/theia-ide/theia/blob/cc51575a2c8660f13794ed9099ee14daaca982b9/packages/core/src/browser/dialogs.ts#L76

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vince-fugnitto I think it's necessary.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you clarify why it's necessary? (this.id is always true)
If no id is provided by a child, the parent's theia-dialog-shell will be used due to super(props).

Copy link
Contributor Author

@xieyuanhuata xieyuanhuata Aug 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vince-fugnitto
I have try add 'event.preventDefault();event.stopPropagation();' into handle func,but it does not work,to binding 'document.body' maybe too wide.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am thinking of a way to solve the problem you mentioned.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this.id = theia-dialog-${(new Date()).getTime()};

Copy link
Contributor Author

@xieyuanhuata xieyuanhuata Aug 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vince-fugnitto @akosyakov
In principle, each dialog should have a unique ID, similar to the processing of widgets in the application-shell
The current processing logic uses default timestamps to identify uniqueness.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have try add 'event.preventDefault();event.stopPropagation();' into handle func,but it does not work,to binding 'document.body' maybe too wide.

Does it stop propagation in wrong order?

Copy link
Contributor Author

@xieyuanhuata xieyuanhuata Aug 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@akosyakov
It will start accepting responses from the first addition to the listen queue.

const dialogOverlay: HTMLElement = event.currentTarget as HTMLElement;
if (dialogOverlay.lastElementChild && this.id.localeCompare(dialogOverlay.lastElementChild.id) === 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can you be sure that lastElementChild belongs to any dialog at all? What if a dialog adds other children to the body?

Copy link
Contributor Author

@xieyuanhuata xieyuanhuata Aug 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@akosyakov
I have considered the situation you said, but I want to simplify the problem in the most economical way, so I used a time-stamped ID to determine whether it is the same dialog.If it is not the same, it will not be processed.

result = true;
}
}
return result;
}

protected handleEscape(event: KeyboardEvent): boolean | void {
this.close();
if (this.canHandleKeyboardEvent(event)) {
this.close();
}
}

protected handleEnter(event: KeyboardEvent): boolean | void {
if (event.target instanceof HTMLTextAreaElement) {
return false;
if (this.canHandleKeyboardEvent(event)) {
if (event.target instanceof HTMLTextAreaElement) {
return false;
}
this.accept();
}
this.accept();
}

protected onActivateRequest(msg: Message): void {
Expand Down Expand Up @@ -277,7 +292,6 @@ export class ConfirmDialog extends AbstractDialog<boolean> {
@inject(ConfirmDialogProps) protected readonly props: ConfirmDialogProps
) {
super(props);

this.contentNode.appendChild(this.createMessageNode(this.props.msg));
this.appendCloseButton(props.cancel);
this.appendAcceptButton(props.ok);
Expand Down Expand Up @@ -324,7 +338,6 @@ export class SingleTextInputDialog extends AbstractDialog<string> {
@inject(SingleTextInputDialogProps) protected readonly props: SingleTextInputDialogProps
) {
super(props);

this.inputField = document.createElement('input');
this.inputField.type = 'text';
this.inputField.setAttribute('style', 'flex: 0;');
Expand Down Expand Up @@ -363,4 +376,10 @@ export class SingleTextInputDialog extends AbstractDialog<string> {
this.inputField.focus();
}

protected handleEnter(event: KeyboardEvent): boolean | void {
if (event.target instanceof HTMLInputElement) {
return super.handleEnter(event);
}
}

}
1 change: 1 addition & 0 deletions packages/filesystem/src/browser/file-dialog/file-dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ export class OpenFileDialog extends FileDialog<MaybeArray<FileStatNode>> {
}
super.accept();
}

}

@injectable()
Expand Down