Skip to content

Commit

Permalink
fix: relaxed hover service request when scrolling
Browse files Browse the repository at this point in the history
 - do not render footer when scrolling
 - fix anchor word wrapping for long long links in the markdown
 - underline the link and change the cursor to pointer on hover
 - consider status-bar height when calculating hover top

Signed-off-by: Akos Kitta <[email protected]>
  • Loading branch information
Akos Kitta committed Mar 17, 2023
1 parent 0335590 commit 5c31c93
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 13 deletions.
7 changes: 5 additions & 2 deletions arduino-ide-extension/src/browser/style/hover-service.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
/* Adapted from https://github.com/microsoft/vscode/blob/7d9b1c37f8e5ae3772782ba3b09d827eb3fdd833/src/vs/workbench/services/hover/browser/hoverService.ts */

:root {
--theia-hover-max-width: 200px;
--theia-hover-max-width: 200px; /* customized */
}

.theia-hover {
Expand All @@ -29,10 +29,13 @@

.theia-hover a {
color: var(--theia-textLink-foreground);
word-wrap: break-word; /* customized */
cursor: pointer; /* customized */
}

.theia-hover a:hover {
color: var(--theia-textLink-active-foreground);
/* color: var(--theia-textLink-active-foreground); */
text-decoration: underline; /* customized */
}

.theia-hover .hover-row .actions {
Expand Down
4 changes: 4 additions & 0 deletions arduino-ide-extension/src/browser/style/list-widget.css
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@
padding-top: 8px;
}

.component-list-item .footer.scrolling {
visibility: hidden;
}

.component-list-item .footer > * {
display: inline-block;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export class HoverService {
const documentWidth = document.body.getBoundingClientRect().width;
// document.body.getBoundingClientRect().height doesn't work as expected
// scrollHeight will always be accurate here: https://stackoverflow.com/a/44077777
const documentHeight = document.documentElement.scrollHeight;
const documentHeight = document.documentElement.scrollHeight - 22; // --theia-statusBar-height: 22px;
position = HoverPosition.invertIfNecessary(
position,
targetDimensions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class ComponentListItem<
item,
selectedVersion,
inProgress: this.state.inProgress,
isScrolling: this.props.isScrolling,
install: (item) => this.install(item),
uninstall: (item) => this.uninstall(item),
onVersionChange: (version) => this.onVersionChange(version),
Expand Down Expand Up @@ -88,6 +89,7 @@ export namespace ComponentListItem {
selectedVersion: Installable.Version
) => void;
readonly itemRenderer: ListItemRenderer<T>;
readonly isScrolling: boolean;
}

export interface State {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,33 @@ import * as React from '@theia/core/shared/react';
import { Virtuoso } from '@theia/core/shared/react-virtuoso';
import { ArduinoComponent } from '../../../common/protocol/arduino-component';
import { Installable } from '../../../common/protocol/installable';
import { HoverService } from '../../theia/core/hover-service';
import { ComponentListItem } from './component-list-item';
import { ListItemRenderer } from './list-item-renderer';

export class ComponentList<T extends ArduinoComponent> extends React.Component<
ComponentList.Props<T>
ComponentList.Props<T>,
ComponentList.State
> {
constructor(props: Readonly<ComponentList.Props<T>>) {
super(props);
this.state = {
isScrolling: false,
};
}

override render(): React.ReactNode {
return (
<Virtuoso
data={this.props.items}
isScrolling={(isScrolling) => {
if (this.state.isScrolling !== isScrolling) {
this.setState({ isScrolling });
if (isScrolling) {
this.props.hoverService.cancelHover();
}
}
}}
itemContent={(_: number, item: T) => (
<ComponentListItem<T>
key={this.props.itemLabel(item)}
Expand All @@ -21,6 +38,7 @@ export class ComponentList<T extends ArduinoComponent> extends React.Component<
uninstall={this.props.uninstall}
edited={this.props.edited}
onItemEdit={this.props.onItemEdit}
isScrolling={this.state.isScrolling}
/>
)}
/>
Expand All @@ -42,5 +60,9 @@ export namespace ComponentList {
item: T,
selectedVersion: Installable.Version
) => void;
readonly hoverService: HoverService;
}
export interface State {
isScrolling: boolean;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { ListItemRenderer } from './list-item-renderer';
import { ResponseServiceClient } from '../../../common/protocol';
import { nls } from '@theia/core/lib/common';
import { DisposableCollection } from '@theia/core/lib/common/disposable';
import { HoverService } from '../../theia/core/hover-service';

export class FilterableListContainer<
T extends ArduinoComponent,
Expand Down Expand Up @@ -93,6 +94,7 @@ export class FilterableListContainer<
uninstall={this.uninstall.bind(this)}
edited={this.state.edited}
onItemEdit={this.onItemEdit.bind(this)}
hoverService={this.props.hoverService}
/>
);
}
Expand Down Expand Up @@ -193,6 +195,7 @@ export namespace FilterableListContainer {
progressId: string;
}) => Promise<void>;
readonly commandService: CommandService;
readonly hoverService: HoverService;
}

export interface State<T, S extends Searchable.Options> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ interface ListItemRendererParams<T extends ArduinoComponent> {
readonly item: T;
readonly selectedVersion: Installable.Version | undefined;
readonly inProgress?: 'installing' | 'uninstalling' | undefined;
readonly isScrolling: boolean;
readonly install: (item: T) => Promise<void>;
readonly uninstall: (item: T) => Promise<void>;
readonly onVersionChange: (version: Installable.Version) => void;
Expand Down Expand Up @@ -156,23 +157,25 @@ export class ListItemRenderer<T extends ArduinoComponent> {

private readonly showHover = (
event: React.MouseEvent<HTMLElement>,
markdown: string
params: ListItemRendererParams<T>
) => {
this.hoverService.requestHover({
content: new MarkdownStringImpl(markdown),
target: event.currentTarget,
position: 'right',
});
if (!params.isScrolling) {
const markdown = this.markdown(params);
this.hoverService.requestHover({
content: new MarkdownStringImpl(markdown),
target: event.currentTarget,
position: 'right',
});
}
};

renderItem(params: ListItemRendererParams<T>): React.ReactNode {
const action = this.action(params);
return (
<>
<Separator />
<div
className="component-list-item noselect"
onMouseEnter={(event) => this.showHover(event, this.markdown(params))}
onMouseOver={(event) => this.showHover(event, params)}
>
<Header
params={params}
Expand Down Expand Up @@ -650,8 +653,13 @@ class Footer<T extends ArduinoComponent> extends React.Component<
}>
> {
override render(): React.ReactNode {
const { isScrolling } = this.props.params;
const className = ['footer'];
if (isScrolling) {
className.push('scrolling');
}
return (
<div className="footer">
<div className={className.join(' ')}>
<SelectVersion {...this.props} />
<Button {...this.props} />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { FilterableListContainer } from './filterable-list-container';
import { ListItemRenderer } from './list-item-renderer';
import { NotificationCenter } from '../../notification-center';
import { StatefulWidget } from '@theia/core/lib/browser';
import { HoverService } from '../../theia/core/hover-service';

@injectable()
export abstract class ListWidget<
Expand All @@ -38,6 +39,8 @@ export abstract class ListWidget<
private readonly commandService: CommandService;
@inject(ResponseServiceClient)
private readonly responseService: ResponseServiceClient;
@inject(HoverService)
private readonly hoverService: HoverService;

/**
* Do not touch or use it. It is for setting the focus on the `input` after the widget activation.
Expand Down Expand Up @@ -162,6 +165,7 @@ export abstract class ListWidget<
commandService={this.commandService}
responseService={this.responseService}
onDidShow={this.onDidShowEmitter.event}
hoverService={this.hoverService}
/>
);
}
Expand Down

0 comments on commit 5c31c93

Please sign in to comment.